Bimba.git

commit d9780e5b0ad2bdc9d6b11a1faeb560e025d48edc

Author: Adam <git@apiote.xyz>

Merge branch 'develop' for version 3.0

%!v(PANIC=String method: strings: negative Repeat count)


diff --git a/3imba.svg b/3imba.svg
new file mode 100644
index 0000000000000000000000000000000000000000..55d9af1cd0196dbde99fbb5c3272c388fdf9c2c1
--- /dev/null
+++ b/3imba.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<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="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 290.54199 108"
+   id="vector"
+   version="1.1"
+   sodipodi:docname="ic_launcher_foreground.svg"
+   width="290.54199"
+   height="108"
+   inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+  <metadata
+     id="metadata176">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs174" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1017"
+     id="namedview172"
+     showgrid="false"
+     fit-margin-top="8"
+     fit-margin-left="8"
+     fit-margin-bottom="8"
+     fit-margin-right="8"
+     inkscape:zoom="3.0903185"
+     inkscape:cx="135.99551"
+     inkscape:cy="2.2347546"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="vector" />
+  <rect
+     id="rect178"
+     width="274.54199"
+     height="92"
+     x="8"
+     y="8"
+     style="display:inline;fill:#3a3a3b;fill-opacity:1;stroke-width:0.7538203"
+     ry="16" />
+  <g
+     id="group_1"
+     transform="scale(0.16904335)"
+     style="display:inline">
+    <g
+       id="group"
+       transform="translate(173.03255,173.03255)">
+      <path
+         id="path"
+         d="m 62.962,292.5 v 0 c -3.7,-0.9 -5.7,-3.8 -4.3,-6.5 l 32.3,-62.9 c 1.3,-2.6 5.5,-4 9.2,-3 v 0 c 3.7,0.9 5.7,3.8 4.3,6.5 l -32.3,62.9 c -1.3,2.6 -5.4,4 -9.2,3 z"
+         inkscape:connector-curvature="0"
+         style="fill:#54af39" />
+      <path
+         id="path_1"
+         d="m 229.662,292.5 v 0 c 3.7,-0.9 5.7,-3.8 4.3,-6.5 l -32.3,-62.9 c -1.3,-2.6 -5.5,-4 -9.2,-3 v 0 c -3.7,0.9 -5.7,3.8 -4.3,6.5 l 32.3,62.9 c 1.3,2.6 5.5,4 9.2,3 z"
+         inkscape:connector-curvature="0"
+         style="fill:#54af39" />
+      <path
+         id="path_2"
+         d="m 151.362,36.9 -0.6,0.2 c -1.8,0.7 -3.8,-0.3 -4.5,-2.1 l -9.6,-26.7 c -0.7,-1.8 0.3,-3.8 2.1,-4.5 l 0.6,-0.2 c 1.8,-0.7 3.8,0.3 4.5,2.1 l 9.6,26.7 c 0.7,1.9 -0.3,3.9 -2.1,4.5 z"
+         inkscape:connector-curvature="0"
+         style="fill:#54af39" />
+      <path
+         id="path_3"
+         d="m 180.662,3.8 v 0 c 0,2.1 -1.7,3.8 -3.8,3.8 h -61 c -2.1,0 -3.8,-1.7 -3.8,-3.8 v 0 c 0,-2.1 1.7,-3.8 3.8,-3.8 h 61 c 2.1,0 3.8,1.7 3.8,3.8 z"
+         inkscape:connector-curvature="0"
+         style="fill:#54af39" />
+      <path
+         id="path_4"
+         d="m 218.762,236.7 h -144.9 c -13.3,0 -24,-10.8 -24,-24 v -108 c 0,-41.3 33.5,-74.9 74.9,-74.9 h 43.3 c 41.3,0 74.9,33.5 74.9,74.9 v 108 c -0.1,13.2 -10.9,24 -24.2,24 z"
+         inkscape:connector-curvature="0"
+         style="fill:#54af39" />
+      <path
+         id="path_5"
+         d="m 212.562,146.2 h -132.5 c -5.6,0 -10.2,-4.5 -10.2,-10.2 v -34.9 c 0,-16.9 13.7,-30.6 30.6,-30.6 h 91.7 c 16.9,0 30.6,13.7 30.6,30.6 V 136 c -0.1,5.7 -4.6,10.2 -10.2,10.2 z"
+         inkscape:connector-curvature="0"
+         style="fill:#ffffff" />
+      <path
+         id="path_6"
+         d="m 161.462,55.5 h -30.3 c -3.2,0 -5.7,-2.6 -5.7,-5.7 v 0 c 0,-3.2 2.6,-5.7 5.7,-5.7 h 30.3 c 3.2,0 5.7,2.6 5.7,5.7 v 0 c 0,3.1 -2.6,5.7 -5.7,5.7 z"
+         inkscape:connector-curvature="0"
+         style="fill:#ffffff" />
+      <path
+         id="path_7"
+         d="m 87.062,191.9 m -14.8,0 c 0,-3.924 1.56,-7.691 4.335,-10.465 2.774,-2.775 6.541,-4.335 10.465,-4.335 3.924,0 7.691,1.56 10.465,4.335 2.775,2.774 4.335,6.541 4.335,10.465 0,3.924 -1.56,7.691 -4.335,10.465 -2.774,2.775 -6.541,4.335 -10.465,4.335 -3.924,0 -7.691,-1.56 -10.465,-4.335 -2.775,-2.774 -4.335,-6.541 -4.335,-10.465"
+         inkscape:connector-curvature="0"
+         style="fill:#ffffff" />
+      <path
+         id="path_8"
+         d="m 205.662,191.9 m -14.8,0 c 0,-3.924 1.56,-7.691 4.335,-10.465 2.774,-2.775 6.541,-4.335 10.465,-4.335 3.924,0 7.691,1.56 10.465,4.335 2.775,2.774 4.335,6.541 4.335,10.465 0,3.924 -1.56,7.691 -4.335,10.465 -2.774,2.775 -6.541,4.335 -10.465,4.335 -3.924,0 -7.691,-1.56 -10.465,-4.335 -2.775,-2.774 -4.335,-6.541 -4.335,-10.465"
+         inkscape:connector-curvature="0"
+         style="fill:#ffffff" />
+    </g>
+  </g>
+  <g
+     aria-label="Bimba"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:64px;line-height:1.25;font-family:Railway;-inkscape-font-specification:Railway;letter-spacing:0px;word-spacing:0px;display:inline;fill:#ffffff;fill-opacity:1;stroke:none"
+     id="text987"
+     transform="translate(1.2584746)">
+    <path
+       d="m 115.02928,62.896002 c 0,0.896 -0.256,1.792 -0.704,2.624 -0.448,0.832 -1.024,1.536 -1.792,2.176 -0.768,0.64 -1.6,1.088 -2.624,1.472 -1.024,0.384 -2.048,0.512 -3.2,0.512 h -7.935998 v -14.848 h 3.391998 4.416 c 1.152,0 2.24,0.256 3.264,0.64 1.024,0.448 1.92,1.024 2.688,1.728 0.768,0.768 1.344,1.6 1.792,2.56 0.448,1.024 0.704,2.048 0.704,3.136 z m -4.672,-19.968 c 0,0.768 -0.192,1.536 -0.512,2.176 -0.384,0.64 -0.832,1.216 -1.408,1.728 -0.576,0.512 -1.216,0.896 -1.984,1.152 -0.768,0.32 -1.536,0.448 -2.368,0.448 h -5.311998 v -10.752 h 5.119998 c 0.832,0 1.664,0.192 2.432,0.448 0.768,0.256 1.472,0.64 2.112,1.088 0.576,0.512 1.024,1.024 1.408,1.664 0.32,0.64 0.512,1.344 0.512,2.048 z m 11.584,19.904 c 0,-2.688 -0.768,-5.184 -2.24,-7.424 -1.536,-2.24 -3.456,-3.968 -5.824,-5.248 0.96,-0.96 1.728,-2.048 2.304,-3.328 0.512,-1.216 0.832,-2.496 0.832,-3.904 0,-1.6 -0.384,-3.136 -1.024,-4.544 -0.704,-1.408 -1.664,-2.624 -2.816,-3.712 -1.216,-1.024 -2.624,-1.856 -4.224,-2.496 -1.6,-0.576 -3.264,-0.896 -5.056,-0.896 H 98.773 v 44.8 h 7.87228 c 2.048,0 4.032,-0.32 5.888,-1.024 1.856,-0.704 3.456,-1.664 4.864,-2.88 1.408,-1.152 2.496,-2.56 3.328,-4.224 0.768,-1.6 1.216,-3.328 1.216,-5.12 z"
+       id="path989"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ssssscccscccsscscsccssccsscccscccsccssccs" />
+    <path
+       d="m 133.07727,76.080002 v -30.336 h -6.336 v 30.336 z m 1.344,-38.272 -4.48,-4.544 -4.48,4.544 4.48,4.48 z"
+       id="path991"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 187.2212,76.080002 v -18.048 c 0,-1.664 -0.384,-3.328 -1.024,-4.864 -0.704,-1.536 -1.6,-2.88 -2.752,-4.032 -1.152,-1.152 -2.496,-2.048 -4.032,-2.752 -1.536,-0.64 -3.072,-1.024 -4.736,-1.024 -2.048,0 -4.032,0.448 -5.888,1.216 -1.92,0.832 -3.712,1.984 -5.376,3.392 -1.216,-1.344 -2.624,-2.432 -4.224,-3.328 -1.664,-0.832 -3.392,-1.28 -5.184,-1.28 -1.472,0 -2.88,0.192 -4.16,0.576 -1.344,0.384 -2.56,0.96 -3.712,1.6 v -1.856 h -6.592 v 30.4 h 6.528 v -21.504 c 0.768,-0.768 1.792,-1.408 3.008,-1.92 1.216,-0.448 2.56,-0.704 4.032,-0.704 0.96,0 1.856,0.192 2.752,0.512 0.832,0.32 1.6,0.768 2.24,1.28 0.64,0.576 1.088,1.216 1.472,1.984 0.384,0.768 0.576,1.536 0.576,2.304 v 18.048 h 6.4 v -20.096 c 0.96,-1.216 2.048,-2.176 3.328,-2.944 1.216,-0.704 2.496,-1.088 3.904,-1.088 0.96,0 1.856,0.192 2.752,0.512 0.832,0.32 1.6,0.768 2.24,1.28 0.64,0.576 1.088,1.216 1.472,1.984 0.384,0.768 0.576,1.536 0.576,2.304 v 18.048 z"
+       id="path993"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 216.53314,60.912002 c 0,1.28 -0.256,2.496 -0.768,3.648 -0.512,1.152 -1.152,2.176 -1.984,3.008 -0.896,0.896 -1.856,1.536 -2.944,2.048 -1.152,0.512 -2.304,0.704 -3.584,0.704 -1.536,0 -3.008,-0.256 -4.352,-0.768 -1.408,-0.512 -2.56,-1.216 -3.52,-2.112 v -12.736 c 0.96,-0.896 2.112,-1.6 3.456,-2.112 1.344,-0.512 2.816,-0.832 4.416,-0.832 1.28,0 2.432,0.256 3.584,0.768 1.088,0.512 2.048,1.152 2.944,1.984 0.832,0.832 1.472,1.792 1.984,2.88 0.512,1.152 0.768,2.304 0.768,3.52 z m 6.4,0 c 0,-2.112 -0.448,-4.096 -1.28,-6.016 -0.832,-1.856 -1.92,-3.52 -3.328,-4.928 -1.408,-1.408 -3.072,-2.496 -4.992,-3.328 -1.92,-0.832 -3.904,-1.28 -6.016,-1.28 -1.472,0 -2.88,0.192 -4.224,0.576 -1.344,0.384 -2.56,0.96 -3.712,1.6 v -16.256 h -6.4 v 44.8 h 6.4 v -1.472 c 1.152,0.704 2.368,1.216 3.712,1.6 1.28,0.384 2.688,0.512 4.16,0.512 2.112,0 4.096,-0.384 6.016,-1.216 1.92,-0.832 3.584,-1.984 4.992,-3.392 1.408,-1.408 2.56,-3.136 3.392,-5.056 0.832,-1.92 1.28,-3.968 1.28,-6.144 z"
+       id="path995"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 245.20509,69.296002 c -0.896,0.512 -1.856,0.96 -2.88,1.28 -1.024,0.32 -2.048,0.448 -2.944,0.448 -1.664,0 -3.136,-0.192 -4.288,-0.576 -1.152,-0.384 -1.728,-1.216 -1.728,-2.624 0,-0.896 0.256,-1.664 0.896,-2.304 0.64,-0.576 1.472,-1.024 2.56,-1.344 1.024,-0.32 2.304,-0.576 3.776,-0.704 1.408,-0.128 2.944,-0.192 4.608,-0.192 z m 6.4,6.784 v -18.88 c 0,-2.816 -0.448,-5.12 -1.344,-6.848 -0.896,-1.728 -1.92,-3.072 -3.2,-3.968 -1.28,-0.896 -2.624,-1.472 -4.032,-1.728 -1.408,-0.256 -2.688,-0.448 -3.776,-0.448 -1.536,0 -3.072,0.256 -4.672,0.768 -1.664,0.512 -3.072,1.088 -4.224,1.856 l -2.432,8.064 h 0.64 c 1.792,-1.6 3.52,-2.688 5.184,-3.328 1.664,-0.64 3.392,-0.96 5.248,-0.96 1.216,0 2.24,0.192 3.072,0.448 0.768,0.32 1.408,0.768 1.92,1.344 0.448,0.576 0.768,1.28 0.96,2.176 0.128,0.896 0.256,1.856 0.256,2.944 -3.328,0 -6.144,0.32 -8.448,0.832 -2.304,0.576 -4.16,1.344 -5.568,2.24 -1.408,0.96 -2.432,2.048 -3.072,3.328 -0.64,1.28 -0.896,2.624 -0.896,4.032 0,1.28 0.256,2.432 0.832,3.456 0.512,1.024 1.28,1.984 2.24,2.752 0.896,0.832 1.984,1.472 3.264,1.92 1.28,0.448 2.624,0.64 4.096,0.64 1.152,0 2.368,-0.192 3.776,-0.576 1.408,-0.384 2.624,-0.896 3.776,-1.664 v 1.6 z"
+       id="path997"
+       inkscape:connector-curvature="0" />
+  </g>
+  <g
+     aria-label="Bimba"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:56px;line-height:1.25;font-family:Railway;-inkscape-font-specification:Railway;letter-spacing:0px;word-spacing:0px;display:none;fill:#ffffff;fill-opacity:1;stroke:none"
+     id="text1004"
+     transform="translate(-0.114,-6.8644098)">
+    <path
+       d="m 116.40217,69.760412 c 0,0.896 -0.256,1.792 -0.704,2.624 -0.448,0.832 -1.024,1.536 -1.792,2.176 -0.768,0.64 -1.6,1.088 -2.624,1.472 -1.024,0.384 -2.048,0.512 -3.2,0.512 h -7.936 v -14.848 h 3.392 4.416 c 1.152,0 2.24,0.256 3.264,0.64 1.024,0.448 1.92,1.024 2.688,1.728 0.768,0.768 1.344,1.6 1.792,2.56 0.448,1.024 0.704,2.048 0.704,3.136 z m -4.672,-19.968 c 0,0.768 -0.192,1.536 -0.512,2.176 -0.384,0.64 -0.832,1.216 -1.408,1.728 -0.576,0.512 -1.216,0.896 -1.984,1.152 -0.768,0.32 -1.536,0.448 -2.368,0.448 h -5.312 v -10.752 h 5.12 c 0.832,0 1.664,0.192 2.432,0.448 0.768,0.256 1.472,0.64 2.112,1.088 0.576,0.512 1.024,1.024 1.408,1.664 0.32,0.64 0.512,1.344 0.512,2.048 z m 11.584,19.904 c 0,-2.688 -0.768,-5.184 -2.24,-7.424 -1.536,-2.24 -3.456,-3.968 -5.824,-5.248 0.96,-0.96 1.728,-2.048 2.304,-3.328 0.512,-1.216 0.832,-2.496 0.832,-3.904 0,-1.6 -0.384,-3.136 -1.024,-4.544 -0.704,-1.408 -1.664,-2.624 -2.816,-3.712 -1.216,-1.024 -2.624,-1.856 -4.224,-2.496 -1.6,-0.576 -3.264,-0.896 -5.056,-0.896 H 93.746168 v 44.8 h 14.272002 c 2.048,0 4.032,-0.32 5.888,-1.024 1.856,-0.704 3.456,-1.664 4.864,-2.88 1.408,-1.152 2.496,-2.56 3.328,-4.224 0.768,-1.6 1.216,-3.328 1.216,-5.12 z"
+       style="font-size:64px"
+       id="path4709"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 134.45016,82.944412 v -30.336 h -6.336 v 30.336 z m 1.344,-38.272 -4.48,-4.544 -4.48,4.544 4.48,4.48 z"
+       style="font-size:64px"
+       id="path4711"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 188.59409,82.944412 v -18.048 c 0,-1.664 -0.384,-3.328 -1.024,-4.864 -0.704,-1.536 -1.6,-2.88 -2.752,-4.032 -1.152,-1.152 -2.496,-2.048 -4.032,-2.752 -1.536,-0.64 -3.072,-1.024 -4.736,-1.024 -2.048,0 -4.032,0.448 -5.888,1.216 -1.92,0.832 -3.712,1.984 -5.376,3.392 -1.216,-1.344 -2.624,-2.432 -4.224,-3.328 -1.664,-0.832 -3.392,-1.28 -5.184,-1.28 -1.472,0 -2.88,0.192 -4.16,0.576 -1.344,0.384 -2.56,0.96 -3.712,1.6 v -1.856 h -6.592 v 30.4 h 6.528 v -21.504 c 0.768,-0.768 1.792,-1.408 3.008,-1.92 1.216,-0.448 2.56,-0.704 4.032,-0.704 0.96,0 1.856,0.192 2.752,0.512 0.832,0.32 1.6,0.768 2.24,1.28 0.64,0.576 1.088,1.216 1.472,1.984 0.384,0.768 0.576,1.536 0.576,2.304 v 18.048 h 6.4 v -20.096 c 0.96,-1.216 2.048,-2.176 3.328,-2.944 1.216,-0.704 2.496,-1.088 3.904,-1.088 0.96,0 1.856,0.192 2.752,0.512 0.832,0.32 1.6,0.768 2.24,1.28 0.64,0.576 1.088,1.216 1.472,1.984 0.384,0.768 0.576,1.536 0.576,2.304 v 18.048 z"
+       style="font-size:64px"
+       id="path4713"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 217.90603,67.776412 c 0,1.28 -0.256,2.496 -0.768,3.648 -0.512,1.152 -1.152,2.176 -1.984,3.008 -0.896,0.896 -1.856,1.536 -2.944,2.048 -1.152,0.512 -2.304,0.704 -3.584,0.704 -1.536,0 -3.008,-0.256 -4.352,-0.768 -1.408,-0.512 -2.56,-1.216 -3.52,-2.112 v -12.736 c 0.96,-0.896 2.112,-1.6 3.456,-2.112 1.344,-0.512 2.816,-0.832 4.416,-0.832 1.28,0 2.432,0.256 3.584,0.768 1.088,0.512 2.048,1.152 2.944,1.984 0.832,0.832 1.472,1.792 1.984,2.88 0.512,1.152 0.768,2.304 0.768,3.52 z m 6.4,0 c 0,-2.112 -0.448,-4.096 -1.28,-6.016 -0.832,-1.856 -1.92,-3.52 -3.328,-4.928 -1.408,-1.408 -3.072,-2.496 -4.992,-3.328 -1.92,-0.832 -3.904,-1.28 -6.016,-1.28 -1.472,0 -2.88,0.192 -4.224,0.576 -1.344,0.384 -2.56,0.96 -3.712,1.6 v -16.256 h -6.4 v 44.8 h 6.4 v -1.472 c 1.152,0.704 2.368,1.216 3.712,1.6 1.28,0.384 2.688,0.512 4.16,0.512 2.112,0 4.096,-0.384 6.016,-1.216 1.92,-0.832 3.584,-1.984 4.992,-3.392 1.408,-1.408 2.56,-3.136 3.392,-5.056 0.832,-1.92 1.28,-3.968 1.28,-6.144 z"
+       style="font-size:64px"
+       id="path4715"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 246.57798,76.160412 c -0.896,0.512 -1.856,0.96 -2.88,1.28 -1.024,0.32 -2.048,0.448 -2.944,0.448 -1.664,0 -3.136,-0.192 -4.288,-0.576 -1.152,-0.384 -1.728,-1.216 -1.728,-2.624 0,-0.896 0.256,-1.664 0.896,-2.304 0.64,-0.576 1.472,-1.024 2.56,-1.344 1.024,-0.32 2.304,-0.576 3.776,-0.704 1.408,-0.128 2.944,-0.192 4.608,-0.192 z m 6.4,6.784 v -18.88 c 0,-2.816 -0.448,-5.12 -1.344,-6.848 -0.896,-1.728 -1.92,-3.072 -3.2,-3.968 -1.28,-0.896 -2.624,-1.472 -4.032,-1.728 -1.408,-0.256 -2.688,-0.448 -3.776,-0.448 -1.536,0 -3.072,0.256 -4.672,0.768 -1.664,0.512 -3.072,1.088 -4.224,1.856 l -2.432,8.064 h 0.64 c 1.792,-1.6 3.52,-2.688 5.184,-3.328 1.664,-0.64 3.392,-0.96 5.248,-0.96 1.216,0 2.24,0.192 3.072,0.448 0.768,0.32 1.408,0.768 1.92,1.344 0.448,0.576 0.768,1.28 0.96,2.176 0.128,0.896 0.256,1.856 0.256,2.944 -3.328,0 -6.144,0.32 -8.448,0.832 -2.304,0.576 -4.16,1.344 -5.568,2.24 -1.408,0.96 -2.432,2.048 -3.072,3.328 -0.64,1.28 -0.896,2.624 -0.896,4.032 0,1.28 0.256,2.432 0.832,3.456 0.512,1.024 1.28,1.984 2.24,2.752 0.896,0.832 1.984,1.472 3.264,1.92 1.28,0.448 2.624,0.64 4.096,0.64 1.152,0 2.368,-0.192 3.776,-0.576 1.408,-0.384 2.624,-0.896 3.776,-1.664 v 1.6 z"
+       style="font-size:64px"
+       id="path4717"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>




diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..82b6b91898a92c69afe84a1c981f27ee2f58c133
--- /dev/null
+++ b/CHANGELOG.adoc
@@ -0,0 +1,76 @@
+= Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on https://keepachangelog.com/en/1.0.0/[Keep a Changelog], but uses AsciiDoc instead of Markdown,
+and this project adheres to https://semver.org/spec/v2.0.0.html[Semantic Versioning].
+
+== Unreleased
+
+* Searching lines
+* Travel planning
+* Offline timetable
+* Alerts
+
+== [3.0] – 2023-04-11
+
+=== Changed
+
+* completely new architecture
+
+== [2.2.2] – 2019-03-11
+
+=== Changed
+
+* drop HTML formatting in PEKA messages
+
+== [2.2.1] – 2019-03-04
+
+=== Changed
+
+* white icons (low floor, tickets) in night mode
+
+== [2.2.0] – 2019-02-26
+
+=== Added
+
+* showing low floor and ticket checkouts in VM departures
+
+=== Changed
+
+* departures empty state is semi-transparent
+
+== [2.1] – 2019-02-04
+
+=== Added
+
+* showing empty search result
+* loading in shed selection and stop screen
+* VM messages
+
+=== Changed
+
+* search bar
+* empty departures state
+* ‘now’ departure is ‘in a moment’ if the vehicle is not on-stop
+* sorting departures: on-stop at the top
+* sorting search results by similarity
+
+== [2.0] – 2018-09-21
+
+=== Added
+
+* official timetable from ZTM
+
+=== Changed
+
+* VM can be used without offline timetable
+* offline timetable uses exact dates (instead of workdays/saturdays/holidays)
+* VM is quicker and is more reliable (as it’s computed in the same way as offline departures)
+* favourites rewritten from scratch
+* app is movable to external storage
+* new colours—grey and green—fitting new Poznań style
+
+=== Fixed
+
+* multiple bug fixes




diff --git a/CHANGELOG.rst b/CHANGELOG.rst
deleted file mode 100644
index 7e205e91cb1687496ebb21e320a553a0466f0788..0000000000000000000000000000000000000000
--- a/CHANGELOG.rst
+++ /dev/null
@@ -1,102 +0,0 @@
-Changelog
-#########
-
-All notable changes to this project will be documented in this file.
-
-The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_`, using ReStructuredText instead of Markdown, and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_.
-
-[Unreleased]
-============
-
-Added
------
-
-+ logging and reporting crashes
-+ history of frequently searched stops
-+ retry buttons
-+ caching favourite
-+ update info in APK releases
-+ day/night setting – auto, always day, always night
-+ trip planning
-+ full timetable online
-+ free train departures
-+ searching by lines
-+ city bike stations
-
-Changed
--------
-
-* reduce flickering of search results
-* VM messages appear also in favourites (if it contains 1 stop only)
-* ‘no connectivity’ warning only when offline timetable is not present
-
-[2.2.2] – 2019-03-11
-====================
-
-Changed
--------
-
-* drop HTML formatting in PEKA messages
-
-[2.2.1] – 2019-03-04
-====================
-
-Changed
--------
-
-* white icons (low floor, tickets) in night mode
-
-[2.2.0] – 2019-02-26
-====================
-
-Added
------
-
-+ showing low floor and ticket checkouts in VM departures
-
-Changed
--------
-
-* departures empty state is semi-transparent
-
-[2.1] – 2019-02-04
-==================
-
-Added
------
-
-+ showing empty search result
-+ loading in shed selection and stop screen
-+ VM messages
-
-Changed
--------
-
-* search bar
-* empty departures state
-* ‘now’ departure is ‘in a moment’ if the vehicle is not on-stop
-* sorting departures: on-stop at the top
-* sorting search results by similarity
-
-[2.0] – 2018-09-21
-==================
-
-Added
------
-
-+ official timetable from ZTM
-
-Changed
--------
-
-* VM can be used without offline timetable
-* offline timetable uses exact dates (instead of workdays/saturdays/holidays)
-* VM is quicker and is more reliable (as it’s computed in the same way as offline departures)
-* favourites rewritten from scratch
-* app is movable to external storage
-* new colours—grey and green—fitting new Poznań style
-
-Fixed
------
-
-* multiple bug fixes




diff --git a/CODE_OF_CONDUCT b/CODE_OF_CONDUCT
new file mode 100644
index 0000000000000000000000000000000000000000..22572bcbc92d27dd11f2f1aacd9de9f9917837a6
--- /dev/null
+++ b/CODE_OF_CONDUCT
@@ -0,0 +1,53 @@
+Code of Merit
+
+1. The project creators, lead developers, core team, constitute
+the managing members of the project and have final say in every decision
+of the project, technical or otherwise, including overruling previous decisions.
+There are no limitations to this decisional power.
+
+2. Contributions are an expected result of your membership on the project.
+Don't expect others to do your work or help you with your work forever.
+
+3. All members have the same opportunities to seek any challenge they want
+within the project.
+
+4. Authority or position in the project will be proportional
+to the accrued contribution. Seniority must be earned.
+
+5. Software is evolutive: the better implementations must supersede lesser
+implementations. Technical advantage is the primary evaluation metric.
+
+6. This is a space for technical prowess; topics outside of the project
+will not be tolerated.
+
+7. Non technical conflicts will be discussed in a separate space. Disruption
+of the project will not be allowed.
+
+8. Individual characteristics, including but not limited to,
+body, sex, sexual preference, race, language, religion, nationality,
+or political preferences are irrelevant in the scope of the project and
+will not be taken into account concerning your value or that of your contribution
+to the project.
+
+9. Discuss or debate the idea, not the person.
+
+10. There is no room for ambiguity: Ambiguity will be met with questioning;
+further ambiguity will be met with silence. It is the responsibility
+of the originator to provide requested context.
+
+11. If something is illegal outside the scope of the project, it is illegal
+in the scope of the project. This Code of Merit does not take precedence over
+governing law.
+
+12. This Code of Merit governs the technical procedures of the project not the
+activities outside of it.
+
+13. Participation on the project equates to agreement of this Code of Merit.
+
+14. No objectives beyond the stated objectives of this project are relevant
+to the project. Any intent to deviate the project from its original purpose
+of existence will constitute grounds for remedial action which may include
+expulsion from the project.
+
+This document is adapted from the Code of Merit, version 1.0.
+See: https://codeofmerit.org/.




diff --git a/README.adoc b/README.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..afbd4fa417b2548febc28e4c00e9ba7e4970c5bb
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1,60 @@
+= Bimba
+apiote <me@apiote.xyz>
+v3.0 2023-04-11
+:toc:
+
+Bimba is a FLOSS public transport passenger companion; a timetable in your pocket.
+
+Bimba can be found on https://floss.social/@bimba[Mastodon]
+
+== Name
+
+Bimba is pronounced BEEM-bah [ˈbimba].
+The name is Poznań subdialect for ‘tram’.
+
+== Installing
+
+Preffered method is to download Bimba from F-Droid:
+
+[link=https://f-droid.org/packages/xyz.apiote.bimba.czwek]
+image::https://f-droid.org/badge/get-it-on.png[Get it on F-Droid,207,80]
+
+== Contribute
+
+This project uses The Code of Merit, which is available as CODE_OF_CONDUCT file.
+
+The roadmap is available in `CHANGELOG.adoc` file and—although it’s not set in stone—feature requests are highly discouraged. Contributions, however, are welcome as patches; please send them to `bimba@git.apiote.xyz` using `git send-email`. Patches must include a sign-off to certify agreement to https://developercertificate.org/[Developer Certificate of Origin].
+
+All communication—questions, bugs, etc.—should go through the mailing list available at `bimba@git.apiote.xyz`. Note that all communication will be made public at https://asgard.apiote.xyz/.
+
+== Mirrors
+
+The canonical repository for this project is https://git.apiote.xyz/Bimba.git it’s mirrored at https://notabug.org/apiote/Bimba
+
+Mirrors exist solely for the sake of the code and any additional functions provided by third-party services (including but not limited to issues and pull requests) will not be used and will be ignored.
+
+== License
+
+----
+Bimba Copyright (c) apiote
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <https://www.gnu.org/licenses/>.
+----
+
+=== Thanks to…
+
+* https://github.com/tebriz159 for new logo
+
+* https://fonts.google.com/icons[Material Icons], © Google Apache 2.0
+* https://github.com/mancj/MaterialSearchBar[Search bar], © mancj MIT




diff --git a/README.md b/README.md
deleted file mode 100644
index 793b6c5f6d49f36560e2646de2bb3029315b807d..0000000000000000000000000000000000000000
--- a/README.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Bimba [![Build Status](https://travis-ci.org/apiote/Bimba.svg?branch=master)](https://travis-ci.org/apiote/Bimba)
-Bimba (pronounced BEEM-bah [ˈbiːmbʌ], Poznań subdialect for ‘tram’) is the first Free-Software Poznań wandering guide
-
-With Bimba You can check the public transport timetable in Poznań agglomeration (run by ZTM Poznań), and thanks to the Virtual Monitor You can see when exactly a bus or tram will arrive.
-
-<a href="https://f-droid.org/packages/ml.adamsprogs.bimba/" target="_blank">
-<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="80"/></a>
-
-Bimba can be found at [Mastodon](https://floss.social/@bimba)
-
-## Mirror
-
-If You’re reading this on Github, You’re seeing a mirror. Changes are pushed to the mirror only when there’s a push to `master`. The original repo is available on [NotABug](https://notabug.org/apiote/Bimba).
-
-Tags (releases) are published in both services but binary builds after version 2.0 are available only on NotABug.
-
-Issues will be tracked in both services. Pull requests on Github will be asked to be sent via e-mail as `diff`s.
-
-## Roadmap
-
-*more important higher*
-
-* [x] incremental timetable generator
-* [x] favourite stops
-    * [x] offline timetable
-    * [x] Virtual Monitor
-    * [x] peek all departures in a favourite
-* [x] less non-intuitive timetable refresh gesture
-* [ ] nearest stop(s) by GPS
-* [ ] ‘through mid-stop’ on lines with only 1 direction
-* [ ] city bike stations on map
-* [ ] searching by line number
-* [ ] stops on map
-* [ ] refreshing on wakeup
-* [x] VM times immediately if online, not through offline timetable
-* [x] detecting holiday
-* [ ] ticket machines on map
-* [ ] ever-present searchbar
-* [ ] other things on map
-
-## If You want to help…
-
-### …be sure to…
-
-* check the issues, both closed and open;
-* check the most recent commit. Master contains published snapshots; The most recent commit will be on other branch—most likely `develop`, but there may be a release, feature or hotfix branches. For full description of workflow model head to [Nvie’s model](https://nvie.com/posts/a-successful-git-branching-model/).
-
-### …then You can…
-
-* add a new translation. Just translate `strings.xml` and make a pull request or an issue;
-* set up Your own converter instance. For more info head to the [converter readme](converter/README.md)
-* help me move my own converter to some PaaS (like Heroku or other I-don’t-know-because-I-cannot-into-cloud)
-* think about any other way
-* <small> donate. More info [there](http://apiote.tk/donate/)</small>
-
-## Thanks to…
-
-* [tebriz159@github](https://github.com/tebriz159) for new logo ([#4](https://github.com/apiote/Bimba/issues/4))
-* [Vistaus@github](https://github.com/Vistaus) for Dutch translation ([#5](https://github.com/apiote/Bimba/pull/5))
-
----
-
-    Bimba
-    Copyright (C) 2017–2018  Adam Pioterek
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-- Ticket machine icon [Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Ticket_machine_icon.svg), © [Therud](https://commons.wikimedia.org/wiki/User:Therud) CC-BY-SA 4.0
-- Icons [Material](https://material.io/icons), © Google Apache 2.0
-- Feature image [Wikimedia Commons](https://commons.wikimedia.org/wiki/File:Poznan._Kaponiera_finally_opened_(44).jpg), © MOs810 CC BY-SA 4.0
-- [Search View](https://github.com/arimorty/floatingsearchview), © arimorty Apache 2.0
-- JSON [gson](https://github.com/google/gson), © Google Apache 2.0
-- HTTP [okhttp](https://github.com/square/okhttp), © square Apache 2.0
-- [SQLite](https://github.com/requery/sqlite-android), © requery Apache 2.0




diff --git a/app/.gitignore b/app/.gitignore
index 796b96d1c402326528b4ba3c12ee9d92d0e212e9..42afabfd2abebf31384ca7797186a27a4b7dbee8 100644
--- a/app/.gitignore
+++ b/app/.gitignore
@@ -1 +1 @@
-/build
+/build
\ No newline at end of file




diff --git a/app/build.gradle b/app/build.gradle
index 053942d2c3516a112b36037739800223883f06f1..4a826718a3be350286e3dbe39465842db656594b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,48 +1,61 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
+plugins {
+    id 'com.android.application'
+    id 'org.jetbrains.kotlin.android'
+    id "org.jetbrains.kotlin.plugin.parcelize"
+}
 
 android {
-    compileSdkVersion 28
-    buildToolsVersion '28.0.3'
+    compileSdk 33
+
     defaultConfig {
-        applicationId "ml.adamsprogs.bimba"
-        minSdkVersion 19
-        targetSdkVersion 28
-        versionCode 19
-        versionName "2.2.2"
+        applicationId "xyz.apiote.bimba.czwek"
+        minSdk 21
+        targetSdk 33
+        versionCode 20
+        versionName "3.0"
+
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        vectorDrawables.useSupportLibrary = true
     }
+
     buildTypes {
         release {
             minifyEnabled false
-            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
         }
     }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+        coreLibraryDesugaringEnabled true
+    }
+    kotlinOptions {
+        jvmTarget = '1.8'
+    }
+    buildFeatures {
+        viewBinding true
+    }
+    namespace 'xyz.apiote.bimba.czwek'
+    buildToolsVersion '33.0.1'
 }
 
 dependencies {
-    implementation fileTree(include: ['*.jar'], dir: 'libs')
-    androidTestImplementation('androidx.test.espresso:espresso-core:3.1.0', {
-        exclude group: 'com.android.support', module: 'support-annotations'
-    })
-    implementation 'androidx.appcompat:appcompat:1.0.2'
-    implementation 'androidx.cardview:cardview:1.0.0'
-    implementation 'androidx.vectordrawable:vectordrawable:1.0.1'
-    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
-    implementation 'com.google.android.material:material:1.1.0-alpha04'
-    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
-    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.27.0-eap13'
-    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.27.0-eap13'
-    testImplementation 'junit:junit:4.12'
-    implementation 'io.requery:sqlite-android:3.22.0'
-    implementation 'com.google.code.gson:gson:2.8.2'
-    implementation 'com.squareup.okhttp3:okhttp:3.12.0'
-    implementation 'com.github.mancj:MaterialSearchBar:0.8.1'
-}
-repositories {
-    maven { url "https://maven.google.com" }
-    maven { url 'https://jitpack.io' }
-    mavenCentral()
+    implementation 'androidx.core:core-ktx:1.9.0'
+    implementation 'androidx.appcompat:appcompat:1.6.1'
+    implementation 'com.google.android.material:material:1.8.0'
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+    implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
+    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
+    implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3'
+    implementation 'androidx.navigation:navigation-ui-ktx:2.5.3'
+    implementation 'com.github.mancj:MaterialSearchBar:0.8.5'
+    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+    implementation 'androidx.core:core-splashscreen:1.0.0'
+    implementation 'com.google.openlocationcode:openlocationcode:1.0.4'
+    implementation 'org.osmdroid:osmdroid-android:6.1.14'
+    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
+    implementation 'org.yaml:snakeyaml:2.0'
+    implementation project(path: ':fruchtfleisch')
+    testImplementation 'junit:junit:4.13.2'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
 }




diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 386a7fa4d2a2ac482e92cea4d3f0b5bff83424f2..481bb434814107eb79d7a30b676d344b0df2f8ce 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -1,13 +1,9 @@
 # Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in /home/adam/.android-sdk/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the proguardFiles
-# directive in build.gradle.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
 #
 # For more details, see
 #   http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
 
 # If your project uses WebView with JS, uncomment the following
 # and specify the fully qualified class name to the JavaScript interface
@@ -15,3 +11,11 @@ # class:
 #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
 #   public *;
 #}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file




diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 25e36bf5433aefd3a374503d0e5d22067650e1ad..ba54cbb104e4c1c2a15a22f4172846243d9d6206 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,69 +1,69 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    package="ml.adamsprogs.bimba"
-    android:installLocation="auto">
-
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.INTERNET" />
-
-    <application
-        android:icon="@mipmap/ic_launcher"
-        android:label="@string/app_name"
-        android:roundIcon="@mipmap/ic_launcher_round"
-        android:supportsRtl="true"
-        android:theme="@style/AppTheme"
-        tools:ignore="GoogleAppIndexingWarning">
-        <activity android:name=".activities.DashActivity" />
+	xmlns:tool="http://schemas.android.com/tools">
 
-        <service
-            android:name=".datasources.TimetableDownloader"
-            android:exported="false" />
+	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+	<uses-permission android:name="android.permission.INTERNET" />
+	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
 
-        <activity
-            android:name=".activities.SplashActivity"
-            android:theme="@style/SplashTheme">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
+	<application
+		android:name="xyz.apiote.bimba.czwek.Bimba"
+		android:allowBackup="true"
+		android:dataExtractionRules="@xml/data_extraction_rules"
+		android:fullBackupContent="@xml/backup_rules"
+		android:icon="@mipmap/ic_launcher"
+		android:label="@string/app_name"
+		android:roundIcon="@mipmap/ic_launcher_round"
+		android:supportsRtl="true"
+		android:theme="@style/Theme.Bimba.Style"
+		tool:targetApi="31">
+		<activity
+			android:name="xyz.apiote.bimba.czwek.settings.ServerChooserActivity"
+			android:exported="false">
+			<meta-data
+				android:name="android.app.lib_name"
+				android:value="" />
+		</activity>
+		<activity
+			android:name="xyz.apiote.bimba.czwek.onboarding.OnboardingActivity">
+		</activity>
+		<activity
+			android:name="xyz.apiote.bimba.czwek.settings.feeds.FeedChooserActivity"
+			android:exported="false" />
+		<activity
+			android:name="xyz.apiote.bimba.czwek.onboarding.FirstRunActivity"
+			android:exported="true"
+			android:theme="@style/Theme.Bimba.Splash">
+			<intent-filter>
+				<action android:name="android.intent.action.MAIN" />
 
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-        <activity android:name=".activities.EditFavouriteActivity" />
-        <activity
-            android:name=".activities.SettingsActivity"
-            android:label="@string/title_activity_settings"
-            android:parentActivityName=".activities.DashActivity"
-            android:theme="@style/AppTheme">
-            <meta-data
-                android:name="android.support.PARENT_ACTIVITY"
-                android:value="ml.adamsprogs.bimba.activities.DashActivity" />
-        </activity>
+				<category android:name="android.intent.category.LAUNCHER" />
+			</intent-filter>
+		</activity>
+		<activity
+			android:name="xyz.apiote.bimba.czwek.departures.DeparturesActivity"
+			android:exported="true">
+			<intent-filter>
+				<action android:name="android.intent.action.VIEW" />
 
-        <service
-            android:name=".datasources.VmService"
-            android:enabled="true"
-            android:exported="false" />
+				<category android:name="android.intent.category.DEFAULT" />
+				<category android:name="android.intent.category.BROWSABLE" />
 
-        <activity android:name=".activities.StopSpecifyActivity" />
-        <activity
-            android:name=".activities.StopActivity"
-            android:label="@string/title_activity_stop"
-            android:parentActivityName=".activities.StopSpecifyActivity"
-            android:theme="@style/AppTheme">
-            <meta-data
-                android:name="android.support.PARENT_ACTIVITY"
-                android:value="ml.adamsprogs.bimba.activities.StopSpecifyActivity" />
-        </activity>
-        <activity
-            android:name=".activities.LineSpecifyActivity"
-            android:label="@string/title_activity_main"
-            android:parentActivityName=".activities.DashActivity"
-            android:theme="@style/AppTheme">
-            <meta-data
-                android:name="android.support.PARENT_ACTIVITY"
-                android:value="ml.adamsprogs.bimba.activities.DashActivity" />
-        </activity>
-    </application>
+				<data android:scheme="http" />
+				<data android:scheme="https" />
+				<data android:host="www.peka.poznan.pl" />
+				<data android:pathPrefix="/vm" />
+			</intent-filter>
+		</activity>
+		<activity
+			android:name="xyz.apiote.bimba.czwek.search.ResultsActivity"
+			android:exported="false"
+			android:label="@string/title_activity_results" />
+		<activity
+			android:name="xyz.apiote.bimba.czwek.dashboard.MainActivity"
+			android:exported="false"
+			android:windowSoftInputMode="adjustPan" />
+	</application>
 
 </manifest>
\ No newline at end of file




diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
new file mode 100644
index 0000000000000000000000000000000000000000..51de732e44c246bac252b581c3bb1b3c9aa345c6
Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ




diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png
deleted file mode 100644
index 7a9bd078b1aed42188fe767423683c64a468312e..0000000000000000000000000000000000000000
Binary files a/app/src/main/ic_launcher-web.png and /dev/null differ




diff --git a/app/src/main/java/ml/adamsprogs/bimba/Declinator.kt b/app/src/main/java/ml/adamsprogs/bimba/Declinator.kt
deleted file mode 100644
index 9f456f1352381e2bdf0b57333094c665dffea751..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/Declinator.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package ml.adamsprogs.bimba
-
-class Declinator {
-    companion object {
-        fun decline(number: Int): Int {
-            return when {
-                number == 0 -> R.string.now
-                number % 10 == 0 -> R.string.departure_in__plural_genitive
-                number == 1 -> R.string.departure_in__singular_genitive
-                number in listOf(12,13,14) -> R.string.departure_in__plural_genitive
-                number % 10 in listOf(2, 3, 4) -> R.string.departure_in__plural_nominative
-                number % 10 in listOf(1,5,6,7,8,9) -> R.string.departure_in__plural_genitive
-                else -> -1
-            }
-        }
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt b/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt
deleted file mode 100644
index faedcc757de71be595d9cd42158d306e3d44964d..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/MessageReceiver.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import ml.adamsprogs.bimba.datasources.TimetableDownloader
-import ml.adamsprogs.bimba.datasources.VmService
-import ml.adamsprogs.bimba.models.Departure
-import ml.adamsprogs.bimba.models.Plate
-
-class MessageReceiver private constructor() : BroadcastReceiver() {
-    companion object {
-        private var receiver:MessageReceiver? = null
-        fun getMessageReceiver(): MessageReceiver {
-            if (receiver == null)
-                receiver = MessageReceiver()
-            return receiver as MessageReceiver
-        }
-    }
-
-    private val onTimetableDownloadListeners: HashSet<OnTimetableDownloadListener> = HashSet()
-    private val onVmListeners: HashSet<OnVmListener> = HashSet()
-
-    override fun onReceive(context: Context?, intent: Intent?) {
-        if (intent?.action == TimetableDownloader.ACTION_DOWNLOADED) {
-            val result = intent.getStringExtra(TimetableDownloader.EXTRA_RESULT)
-            for (listener in onTimetableDownloadListeners) {
-                listener.onTimetableDownload(result)
-            }
-        }
-        if (intent?.action == VmService.ACTION_READY) {
-            val departures = intent.getStringArrayListExtra(VmService.EXTRA_DEPARTURES)?.map { Departure.fromString(it) }?.toSet()
-            val plateId = intent.getSerializableExtra(VmService.EXTRA_PLATE_ID) as Plate.ID?
-            val stopCode = intent.getSerializableExtra(VmService.EXTRA_STOP_CODE) as String
-            val code = intent.getIntExtra(VmService.EXTRA_CODE, 0)
-            for (listener in onVmListeners) {
-                listener.onVm(departures, plateId, stopCode, code)
-            }
-        }
-    }
-
-    fun addOnTimetableDownloadListener(listener: OnTimetableDownloadListener) {
-        onTimetableDownloadListeners.add(listener)
-    }
-
-    fun removeOnTimetableDownloadListener(listener: OnTimetableDownloadListener) {
-        onTimetableDownloadListeners.remove(listener)
-    }
-
-    fun addOnVmListener(listener: OnVmListener) {
-        onVmListeners.add(listener)
-    }
-
-    fun removeOnVmListener(listener: OnVmListener) {
-        onVmListeners.remove(listener)
-    }
-
-    interface OnTimetableDownloadListener {
-        fun onTimetableDownload(result: String?)
-    }
-
-    interface OnVmListener {
-        fun onVm(vmDepartures: Set<Departure>?, plateId: Plate.ID?, stopCode: String, code: Int)
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/NetworkStateReceiver.kt b/app/src/main/java/ml/adamsprogs/bimba/NetworkStateReceiver.kt
deleted file mode 100644
index 770ba13101e61f4ccd213248bb2af9aadc0f4874..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/NetworkStateReceiver.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.net.ConnectivityManager
-import android.content.Intent
-import android.content.BroadcastReceiver
-import android.content.Context
-
-class NetworkStateReceiver : BroadcastReceiver() {
-
-    private val onConnectivityChangeListeners = HashSet<OnConnectivityChangeListener>()
-
-    override fun onReceive(context: Context, intent: Intent) {
-        if (intent.extras != null) {
-            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
-            val ni = connectivityManager.activeNetworkInfo
-
-            if (ni != null && ni.isConnectedOrConnecting) {
-                for (listener in onConnectivityChangeListeners)
-                    listener.onConnectivityChange(true)
-            } else if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, java.lang.Boolean.FALSE)) {
-                for (listener in onConnectivityChangeListeners)
-                    listener.onConnectivityChange(false)
-            }
-        }
-    }
-
-    interface OnConnectivityChangeListener {
-        fun onConnectivityChange(connected: Boolean)
-    }
-
-    companion object {
-        lateinit var manager: ConnectivityManager
-
-        fun init(context: Context) {
-            manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
-        }
-
-        fun isNetworkAvailable(): Boolean {
-            val activeNetworkInfo = manager.activeNetworkInfo
-            return activeNetworkInfo != null && activeNetworkInfo.isConnected
-        }
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/NotificationChannels.kt b/app/src/main/java/ml/adamsprogs/bimba/NotificationChannels.kt
deleted file mode 100644
index 738003153a01f7d7753f888009f26268299a5f78..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/NotificationChannels.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.app.NotificationChannel
-import android.app.NotificationManager
-import android.os.Build
-import androidx.annotation.RequiresApi
-
-
-class NotificationChannels {
-    companion object {
-        const val CHANNEL_UPDATES = "updates"
-
-        @RequiresApi(Build.VERSION_CODES.O)
-        fun makeChannel(id: String, name: String, manager: NotificationManager) {
-            try {
-                manager.getNotificationChannel(id)
-            } catch (e: RuntimeException) {
-                val channel = NotificationChannel(id, name, NotificationManager.IMPORTANCE_MIN)
-                channel.enableLights(false)
-                channel.enableVibration(false)
-                channel.setShowBadge(false)
-                manager.createNotificationChannel(channel)
-            }
-        }
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/ProviderProxy.kt b/app/src/main/java/ml/adamsprogs/bimba/ProviderProxy.kt
deleted file mode 100644
index 99225e0e49c57da0143579fe0ecda2b31459456e..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/ProviderProxy.kt
+++ /dev/null
@@ -1,269 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.content.Context
-import android.content.Intent
-import kotlinx.coroutines.*
-import kotlinx.coroutines.android.Main
-import ml.adamsprogs.bimba.datasources.VmClient
-import ml.adamsprogs.bimba.datasources.VmService
-import ml.adamsprogs.bimba.models.Departure
-import ml.adamsprogs.bimba.models.Plate
-import ml.adamsprogs.bimba.models.StopSegment
-import ml.adamsprogs.bimba.models.Timetable
-import ml.adamsprogs.bimba.models.suggestions.GtfsSuggestion
-import ml.adamsprogs.bimba.models.suggestions.StopSuggestion
-import java.util.*
-import kotlin.collections.HashMap
-
-class ProviderProxy(context: Context? = null) {
-    private val vmClient = VmClient.getVmClient()
-    private var timetable: Timetable = Timetable.getTimetable(context)
-    private var suggestions = emptyList<GtfsSuggestion>()
-    private val requests = HashMap<String, Request>()
-
-    var mode = if (timetable.isEmpty()) MODE_VM else MODE_FULL
-
-    companion object {
-        const val MODE_FULL = "mode_full"
-        const val MODE_VM = "mode_vm"
-    }
-
-    fun getSuggestions(query: String = "", callback: (List<GtfsSuggestion>) -> Unit) {
-        GlobalScope.launch {
-            suggestions = getStopSuggestions(query) //+ getLineSuggestions(query) //todo<p:v+1> + bike stations, train stations, &c
-            val filtered = filterSuggestions(query)
-            launch(Dispatchers.Main) {
-                callback(filtered)
-            }
-        }
-    }
-
-    private suspend fun getStopSuggestions(query: String): List<StopSuggestion> {
-        val vmSuggestions = withContext(Dispatchers.Default) {
-            vmClient.getStops(query)
-        }
-
-        return if (vmSuggestions.isEmpty() and !timetable.isEmpty()) {
-            timetable.getStopSuggestions()
-        } else {
-            vmSuggestions
-        }
-    }
-
-    private fun filterSuggestions(query: String): List<GtfsSuggestion> {
-        return suggestions.filter {
-            deAccent(it.name).contains(deAccent(query), true)
-        }
-    }
-
-    private fun deAccent(str: String): String {
-        var result = str.replace('ę', 'e', true)
-        result = result.replace('ó', 'o', true)
-        result = result.replace('ą', 'a', true)
-        result = result.replace('ś', 's', true)
-        result = result.replace('ł', 'l', true)
-        result = result.replace('ż', 'z', true)
-        result = result.replace('ź', 'z', true)
-        result = result.replace('ć', 'c', true)
-        result = result.replace('ń', 'n', true)
-        return result
-    }
-
-    fun getSheds(name: String, callback: (Map<String, Set<String>>) -> Unit) {
-        GlobalScope.launch {
-            val vmSheds = vmClient.getSheds(name)
-
-            val sheds = if (vmSheds.isEmpty() and !timetable.isEmpty()) {
-                timetable.getHeadlinesForStop(name)
-            } else {
-                vmSheds
-            }
-
-            launch(Dispatchers.Main) {
-                callback(sheds)
-            }
-        }
-    }
-
-    fun getVmMessage(shed: String, callback: (String?) -> Unit) {
-        GlobalScope.launch {
-            val message = vmClient.getMessage(shed)
-            launch(Dispatchers.Main) {
-                callback(message)
-            }
-        }
-    }
-
-    fun subscribeForDepartures(stopSegments: Set<StopSegment>, listener: OnDeparturesReadyListener, context: Context): String {
-        stopSegments.forEach {
-            val intent = Intent(context, VmService::class.java)
-            intent.putExtra("stop", it.stop)
-            intent.action = "request"
-            context.startService(intent)
-        }
-        val uuid = UUID.randomUUID().toString()
-        requests[uuid] = Request(listener, stopSegments)
-        return uuid
-    }
-
-    fun subscribeForDepartures(stopCode: String, listener: OnDeparturesReadyListener, context: Context): String {
-        val intent = Intent(context, VmService::class.java)
-        intent.putExtra("stop", stopCode)
-        intent.action = "request"
-        context.startService(intent)
-
-        val uuid = UUID.randomUUID().toString()
-        requests[uuid] = Request(listener, setOf(StopSegment(stopCode, null)))
-        return uuid
-    }
-
-    private fun constructSegmentDepartures(stopSegments: Set<StopSegment>): Deferred<Map<String, List<Departure>>> {
-        return GlobalScope.async {
-            if (timetable.isEmpty())
-                emptyMap()
-            else {
-                timetable.getStopDeparturesBySegments(stopSegments)
-            }
-        }
-    }
-
-    private fun filterDepartures(departures: Map<String, List<Departure>>): List<Departure> {
-        val now = Calendar.getInstance().secondsAfterMidnight()
-        val lines = HashMap<String, Int>()
-        val twoDayDepartures = (timetable.getServiceForToday()?.let {
-            departures[it]
-        } ?: emptyList()) +
-                (timetable.getServiceForTomorrow()?.let { service ->
-                    departures[service]!!.map { it.copy().apply { tomorrow = true } }
-                } ?: emptyList())
-
-        return twoDayDepartures
-                .filter { it.timeTill(now) >= 0 }
-                .filter {
-                    val existed = lines[it.line] ?: 0
-                    if (existed < 3) {
-                        lines[it.line] = existed + 1
-                        true
-                    } else false
-                }
-    }
-
-    fun unsubscribeFromDepartures(uuid: String, context: Context) {
-        requests[uuid]?.unsubscribe(context)
-        requests.remove(uuid)
-    }
-
-    fun refreshTimetable(context: Context) {
-        timetable = Timetable.getTimetable(context, true)
-        mode = MODE_FULL
-    }
-
-    fun getFullTimetable(stopCode: String): Map<String, List<Departure>> {
-        return if (timetable.isEmpty())
-            emptyMap()
-        else
-            timetable.getStopDepartures(stopCode)
-
-    }
-
-    fun getFullTimetable(stopSegments: Set<StopSegment>): Map<String, List<Departure>> {
-        return if (timetable.isEmpty())
-            emptyMap()
-        else
-            timetable.getStopDeparturesBySegments(stopSegments)
-
-    }
-
-    fun fillStopSegment(stopSegment: StopSegment, callback: (StopSegment?) -> Unit) {
-        GlobalScope.launch {
-            callback(fillStopSegment(stopSegment))
-        }
-    }
-
-    suspend fun fillStopSegment(stopSegment: StopSegment): StopSegment? {
-        if (stopSegment.plates != null)
-            return stopSegment
-
-        return if (timetable.isEmpty())
-            vmClient.getDirections(stopSegment.stop)
-        else
-            timetable.getHeadlinesForStopCode(stopSegment.stop)
-    }
-
-    fun getStopName(stopCode: String, callback: (String?) -> Unit) {
-        GlobalScope.launch {
-            callback(getStopName(stopCode))
-        }
-    }
-
-    suspend fun getStopName(stopCode: String): String? {
-        return if (timetable.isEmpty())
-            vmClient.getName(stopCode)
-        else
-            timetable.getStopName(stopCode)
-    }
-
-    fun describeService(service: String, context: Context): String? {
-        return if (timetable.isEmpty())
-            null
-        else
-            timetable.getServiceDescription(service, context)
-    }
-
-    fun getServiceFirstDay(service: String): Int {
-        return timetable.getServiceFirstDay(service)
-    }
-
-    interface OnDeparturesReadyListener {
-        fun onDeparturesReady(departures: List<Departure>, plateId: Plate.ID?, code: Int)
-    }
-
-    inner class Request(private val listener: OnDeparturesReadyListener, private val segments: Set<StopSegment>) : MessageReceiver.OnVmListener {
-        private val receiver = MessageReceiver.getMessageReceiver()
-        private val receivedPlates = HashSet<Plate.ID>()
-
-        private var cache: Deferred<Map<String, List<Departure>>>? = null
-
-        init {
-            receiver.addOnVmListener(this@Request)
-            GlobalScope.launch {
-                cache = constructSegmentDepartures(segments)
-            }
-        }
-
-        override fun onVm(vmDepartures: Set<Departure>?, plateId: Plate.ID?, stopCode: String, code: Int) {
-            GlobalScope.launch(Dispatchers.Main) {
-                if ((plateId == null || vmDepartures == null) and (timetable.isEmpty())) {
-                    listener.onDeparturesReady(emptyList(), null, code)
-                    return@launch
-                }
-                if (plateId == null) {
-                    listener.onDeparturesReady(filterDepartures(cache!!.await()), null, code)
-                } else {
-                    if (segments.any { plateId in it }) {
-                        if (vmDepartures != null) {
-                            listener.onDeparturesReady(vmDepartures.toList(), plateId, code)
-                            if (plateId !in receivedPlates)
-                                receivedPlates.add(plateId)
-                        } else {
-                            receivedPlates.remove(plateId)
-                            if (receivedPlates.isEmpty()) {
-                                listener.onDeparturesReady(filterDepartures(cache!!.await()), null, code)
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        fun unsubscribe(context: Context) {
-            segments.forEach {
-                val intent = Intent(context, VmService::class.java)
-                intent.putExtra("stop", it.stop)
-                intent.action = "remove"
-                context.startService(intent)
-            }
-            receiver.removeOnVmListener(this)
-        }
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/AppCompatPreferenceActivity.java b/app/src/main/java/ml/adamsprogs/bimba/activities/AppCompatPreferenceActivity.java
deleted file mode 100644
index d276164afc8be57b1d2a6d4c629670704dd536cf..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/AppCompatPreferenceActivity.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package ml.adamsprogs.bimba.activities;
-
-import android.content.res.Configuration;
-import android.os.Bundle;
-import android.preference.PreferenceActivity;
-import android.view.MenuInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.LayoutRes;
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.ActionBar;
-import androidx.appcompat.app.AppCompatDelegate;
-import androidx.appcompat.widget.Toolbar;
-
-/**
- * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls
- * to be used with AppCompat.
- */
-public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
-
-    private AppCompatDelegate mDelegate;
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        getDelegate().installViewFactory();
-        getDelegate().onCreate(savedInstanceState);
-        super.onCreate(savedInstanceState);
-    }
-
-    @Override
-    protected void onPostCreate(Bundle savedInstanceState) {
-        super.onPostCreate(savedInstanceState);
-        getDelegate().onPostCreate(savedInstanceState);
-    }
-
-    public ActionBar getSupportActionBar() {
-        return getDelegate().getSupportActionBar();
-    }
-
-    public void setSupportActionBar(@Nullable Toolbar toolbar) {
-        getDelegate().setSupportActionBar(toolbar);
-    }
-
-    @Override
-    public MenuInflater getMenuInflater() {
-        return getDelegate().getMenuInflater();
-    }
-
-    @Override
-    public void setContentView(@LayoutRes int layoutResID) {
-        getDelegate().setContentView(layoutResID);
-    }
-
-    @Override
-    public void setContentView(View view) {
-        getDelegate().setContentView(view);
-    }
-
-    @Override
-    public void setContentView(View view, ViewGroup.LayoutParams params) {
-        getDelegate().setContentView(view, params);
-    }
-
-    @Override
-    public void addContentView(View view, ViewGroup.LayoutParams params) {
-        getDelegate().addContentView(view, params);
-    }
-
-    @Override
-    protected void onPostResume() {
-        super.onPostResume();
-        getDelegate().onPostResume();
-    }
-
-    @Override
-    protected void onTitleChanged(CharSequence title, int color) {
-        super.onTitleChanged(title, color);
-        getDelegate().setTitle(title);
-    }
-
-    @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        getDelegate().onConfigurationChanged(newConfig);
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        getDelegate().onStop();
-    }
-
-    @Override
-    protected void onDestroy() {
-        super.onDestroy();
-        getDelegate().onDestroy();
-    }
-
-    public void invalidateOptionsMenu() {
-        getDelegate().invalidateOptionsMenu();
-    }
-
-    private AppCompatDelegate getDelegate() {
-        if (mDelegate == null) {
-            mDelegate = AppCompatDelegate.create(this, null);
-        }
-        return mDelegate;
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt
deleted file mode 100644
index cd714bbfd3e7e604ffb1d83c2e9ee486a2eb482a..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/DashActivity.kt
+++ /dev/null
@@ -1,460 +0,0 @@
-package ml.adamsprogs.bimba.activities
-
-import android.annotation.SuppressLint
-import android.app.Activity
-import android.content.Context
-import android.content.DialogInterface
-import android.content.Intent
-import android.content.IntentFilter
-import android.os.Bundle
-import android.preference.PreferenceManager.getDefaultSharedPreferences
-import android.text.Editable
-import android.text.TextWatcher
-import android.view.ActionMode
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import android.view.inputmethod.InputMethodManager
-import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
-import com.google.android.material.navigation.NavigationView
-import com.google.android.material.snackbar.Snackbar
-import com.mancj.materialsearchbar.MaterialSearchBar
-import com.mancj.materialsearchbar.MaterialSearchBar.BUTTON_BACK
-import com.mancj.materialsearchbar.MaterialSearchBar.BUTTON_NAVIGATION
-import kotlinx.android.synthetic.main.activity_dash.*
-import ml.adamsprogs.bimba.*
-import ml.adamsprogs.bimba.collections.FavouriteStorage
-import ml.adamsprogs.bimba.datasources.TimetableDownloader
-import ml.adamsprogs.bimba.datasources.VmService
-import ml.adamsprogs.bimba.models.Departure
-import ml.adamsprogs.bimba.models.Plate
-import ml.adamsprogs.bimba.models.Timetable
-import ml.adamsprogs.bimba.models.adapters.FavouritesAdapter
-import ml.adamsprogs.bimba.models.adapters.SuggestionsAdapter
-import ml.adamsprogs.bimba.models.suggestions.EmptySuggestion
-import ml.adamsprogs.bimba.models.suggestions.GtfsSuggestion
-import ml.adamsprogs.bimba.models.suggestions.LineSuggestion
-import ml.adamsprogs.bimba.models.suggestions.StopSuggestion
-import java.text.DateFormat
-import java.util.*
-import kotlin.collections.ArrayList
-
-class DashActivity : AppCompatActivity(), MessageReceiver.OnTimetableDownloadListener,
-        FavouritesAdapter.OnMenuItemClickListener, FavouritesAdapter.ViewHolder.OnClickListener, ProviderProxy.OnDeparturesReadyListener, SuggestionsAdapter.OnSuggestionClickListener {
-
-    val context: Context = this
-    private val receiver = MessageReceiver.getMessageReceiver()
-    private lateinit var timetable: Timetable
-    private var suggestions: List<GtfsSuggestion>? = null
-    private lateinit var drawerLayout: androidx.drawerlayout.widget.DrawerLayout
-    private lateinit var drawerView: NavigationView
-    lateinit var favouritesList: androidx.recyclerview.widget.RecyclerView
-    lateinit var searchView: MaterialSearchBar
-    private lateinit var favourites: FavouriteStorage
-    private lateinit var adapter: FavouritesAdapter
-    private val actionModeCallback = ActionModeCallback()
-    private var actionMode: ActionMode? = null
-    private var isWarned = false
-    private lateinit var providerProxy: ProviderProxy
-    private lateinit var suggestionsAdapter: SuggestionsAdapter
-
-    companion object {
-        const val REQUEST_EDIT_FAVOURITE = 1
-    }
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_dash)
-
-        setSupportActionBar(toolbar)
-
-        providerProxy = ProviderProxy(this)
-        timetable = Timetable.getTimetable()
-        NetworkStateReceiver.init(this)
-
-        prepareFavourites()
-
-        prepareListeners()
-        startDownloaderService()
-
-        drawerLayout = drawer_layout
-        drawerView = drawer
-        //drawer.setCheckedItem(R.id.drawer_home)
-        drawerView.setNavigationItemSelectedListener { item ->
-            when (item.itemId) {
-                R.id.drawer_refresh -> {
-                    startDownloaderService(true)
-                }
-                R.id.drawer_settings -> {
-                    startActivity(Intent(context, SettingsActivity::class.java))
-                }
-                else -> {
-                }
-            }
-            drawerLayout.closeDrawer(drawerView)
-            super.onOptionsItemSelected(item)
-        }
-
-        warnTimetableValidity()
-
-        showValidityInDrawer()
-
-        searchView = search_view
-        suggestionsAdapter = SuggestionsAdapter(layoutInflater, this, this)
-        searchView.setCustomSuggestionAdapter(suggestionsAdapter)
-
-        searchView.addTextChangeListener(object : TextWatcher {
-            override fun afterTextChanged(s: Editable?) {
-                if (searchView.isSearchEnabled) {
-                    getSuggestions(s.toString())
-                }
-            }
-
-            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
-            }
-
-            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
-            }
-
-        })
-
-        searchView.setOnSearchActionListener(object : MaterialSearchBar.OnSearchActionListener {
-            override fun onButtonClicked(buttonCode: Int) {
-                when (buttonCode) {
-                    BUTTON_NAVIGATION -> {
-                        if (drawerLayout.isDrawerOpen(drawerView))
-                            drawerLayout.closeDrawer(drawerView)
-                        else
-                            drawerLayout.openDrawer(drawerView)
-                    }
-                    BUTTON_BACK -> {
-                        searchView.disableSearch()
-                    }
-                }
-            }
-
-            override fun onSearchStateChanged(enabled: Boolean) {
-            }
-
-            override fun onSearchConfirmed(text: CharSequence?) {
-                getSuggestions(text.toString())
-            }
-        })
-    }
-
-    private fun getSuggestions(query: String = "") {
-        providerProxy.getSuggestions(query) { suggestions ->
-            if (!suggestionsAdapter.equals(suggestions)) {
-                if (suggestions.isEmpty()) {
-                    suggestionsAdapter.clearSuggestions()
-                    suggestionsAdapter.addSuggestion(EmptySuggestion())
-                } else {
-                    suggestionsAdapter.updateSuggestions(suggestions, query)
-                }
-                searchView.showSuggestionsList()
-            }
-        }
-    }
-
-    override fun onSuggestionClickListener(suggestion: GtfsSuggestion) {
-        val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
-        var view = (context as DashActivity).currentFocus
-        if (view == null) {
-            view = View(context)
-        }
-        imm.hideSoftInputFromWindow(view.windowToken, 0)
-        if (suggestion is StopSuggestion) {
-            val intent = Intent(context, StopSpecifyActivity::class.java)
-            intent.putExtra(StopSpecifyActivity.EXTRA_STOP_NAME, suggestion.name)
-            startActivity(intent)
-        } else if (suggestion is LineSuggestion) {
-            val intent = Intent(context, LineSpecifyActivity::class.java)
-            intent.putExtra(LineSpecifyActivity.EXTRA_LINE_ID, suggestion.name)
-            startActivity(intent)
-        }
-    }
-
-    override fun onRestart() {
-        super.onRestart()
-        favourites = FavouriteStorage.getFavouriteStorage(context)
-        favourites.forEach {
-            it.subscribeForDepartures(this, this)
-        }
-    }
-
-    override fun onStop() {
-        super.onStop()
-        favourites.forEach {
-            it.unsubscribeFromDepartures(this)
-        }
-    }
-
-    private fun showValidityInDrawer() {
-        if (timetable.isEmpty()) {
-            drawerView.menu.findItem(R.id.drawer_validity_since).title = getString(R.string.validity_offline_unavailable)
-        } else {
-            val formatter = DateFormat.getDateInstance(DateFormat.SHORT)
-            var calendar = calendarFromIsoD(timetable.getValidSince())
-            formatter.timeZone = calendar.timeZone
-            drawerView.menu.findItem(R.id.drawer_validity_since).title = getString(R.string.valid_since, formatter.format(calendar.time))
-            calendar = calendarFromIsoD(timetable.getValidTill())
-            formatter.timeZone = calendar.timeZone
-            drawerView.menu.findItem(R.id.drawer_validity_till).title = getString(R.string.valid_till, formatter.format(calendar.time))
-        }
-    }
-
-    private fun warnTimetableValidity() {
-        if (isWarned)
-            return
-        isWarned = true
-        if (timetable.isEmpty())
-            return
-        val validTill = timetable.getValidTill()
-        val today = Calendar.getInstance().toIsoDate()
-        val tomorrow = Calendar.getInstance().apply {
-            this.add(Calendar.DAY_OF_MONTH, 1)
-        }.toIsoDate()
-
-        try {
-            timetable.getServiceForToday()
-            if (today > validTill) {
-                notifyTimetableValidity(-1)
-                suggestions = ArrayList()
-                return
-            }
-            if (today == validTill) {
-                notifyTimetableValidity(0)
-                return
-            }
-        } catch (e: IllegalArgumentException) {
-            notifyTimetableValidity(-1)
-            suggestions = ArrayList()
-            return
-        }
-
-        try {
-            timetable.getServiceForTomorrow()
-            if (tomorrow == validTill) {
-                notifyTimetableValidity(1)
-                return
-            }
-        } catch (e: IllegalArgumentException) {
-            notifyTimetableValidity(1)
-            return
-        }
-    }
-
-    private fun notifyTimetableValidity(daysTillInvalid: Int) {
-        val message = when (daysTillInvalid) {
-            -1 -> getString(R.string.timetable_validity_finished)
-            0 -> getString(R.string.timetable_validity_today)
-            1 -> getString(R.string.timetable_validity_tomorrow)
-            else -> return
-        }
-        AlertDialog.Builder(context)
-                .setPositiveButton(context.getText(android.R.string.ok)
-                ) { dialog: DialogInterface, _: Int -> dialog.cancel() }
-                .setCancelable(true)
-                .setMessage(message)
-                .create().show()
-
-        if (daysTillInvalid == -1) {
-            Timetable.delete(this)
-        }
-    }
-
-    private fun prepareFavourites() {
-        favourites = FavouriteStorage.getFavouriteStorage(context)
-        favourites.forEach {
-            it.subscribeForDepartures(this, this)
-        }
-        val layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
-        favouritesList = favourites_list
-        adapter = FavouritesAdapter(context, favourites, this, this)
-        favouritesList.adapter = adapter
-        favouritesList.itemAnimator = androidx.recyclerview.widget.DefaultItemAnimator()
-        favouritesList.layoutManager = layoutManager
-    }
-
-    override fun onDeparturesReady(departures: List<Departure>, plateId: Plate.ID?, code: Int) {
-        favouritesList.adapter!!.notifyDataSetChanged()
-        showError(drawer_layout, code, this)
-    }
-
-    private fun prepareListeners() {
-        val filter = IntentFilter(TimetableDownloader.ACTION_DOWNLOADED)
-        filter.addAction(VmService.ACTION_READY)
-        filter.addCategory(Intent.CATEGORY_DEFAULT)
-        registerReceiver(receiver, filter)
-        receiver.addOnTimetableDownloadListener(context as MessageReceiver.OnTimetableDownloadListener)
-    }
-
-    private fun startDownloaderService(force: Boolean = false) {
-        if (getDefaultSharedPreferences(this).getBoolean(getString(R.string.key_timetable_automatic_update), false) or force)
-            startService(Intent(context, TimetableDownloader::class.java))
-    }
-
-    override fun onBackPressed() {
-        if (drawerLayout.isDrawerOpen(drawerView)) {
-            drawerLayout.closeDrawer(drawerView)
-            return
-        }
-        if (searchView.isSearchEnabled) {
-            searchView.disableSearch()
-        } else {
-            super.onBackPressed()
-        }
-    }
-
-    override fun onResume() {
-        super.onResume()
-        adapter.favourites = favourites
-        favouritesList.adapter!!.notifyDataSetChanged()
-    }
-
-    override fun onDestroy() {
-        super.onDestroy()
-        receiver.removeOnTimetableDownloadListener(context as MessageReceiver.OnTimetableDownloadListener)
-        unregisterReceiver(receiver)
-    }
-
-    override fun onTimetableDownload(result: String?) {
-        val message: String = when (result) {
-            TimetableDownloader.RESULT_NO_CONNECTIVITY -> getString(R.string.no_connectivity_cant_update)
-            TimetableDownloader.RESULT_UP_TO_DATE -> getString(R.string.timetable_up_to_date)
-            TimetableDownloader.RESULT_FINISHED -> getString(R.string.timetable_downloaded)
-            else -> getString(R.string.error_try_later)
-        }
-        Snackbar.make(findViewById(R.id.drawer_layout), message, Snackbar.LENGTH_LONG).show()
-        if (result == TimetableDownloader.RESULT_FINISHED) {
-            timetable = Timetable.getTimetable(this, true)
-            getSuggestions(searchView.text)
-            showValidityInDrawer()
-        }
-    }
-
-    override fun edit(name: String): Boolean {
-        val positionBefore = favourites.indexOf(name)
-        val intent = Intent(this, EditFavouriteActivity::class.java)
-        intent.putExtra(EditFavouriteActivity.EXTRA_FAVOURITE, favourites[name])
-        intent.putExtra(EditFavouriteActivity.EXTRA_POSITION_BEFORE, positionBefore)
-        startActivityForResult(intent, REQUEST_EDIT_FAVOURITE)
-        return true
-    }
-
-    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
-        if (requestCode == REQUEST_EDIT_FAVOURITE) {
-            if (resultCode == Activity.RESULT_OK) {
-                val name = data!!.getStringExtra(EditFavouriteActivity.EXTRA_NEW_NAME)
-                val positionBefore = data.getIntExtra(EditFavouriteActivity.EXTRA_POSITION_BEFORE, -1)
-                //adapter.favourites = favourites.favouritesList
-                if (positionBefore == -1)
-                    favouritesList.adapter!!.notifyDataSetChanged()
-                else {
-                    val positionAfter = favourites.indexOf(name)
-                    favouritesList.adapter!!.notifyItemChanged(positionBefore)
-                    favouritesList.adapter!!.notifyItemMoved(positionBefore, positionAfter)
-                }
-                adapter[name]?.let {
-                    it.unsubscribeFromDepartures(context)
-                    it.subscribeForDepartures(this, context)
-                }
-            }
-        }
-    }
-
-    override fun delete(name: String): Boolean {
-        favourites.delete(name)
-        //adapter.favourites = favourites.favouritesList
-        favouritesList.adapter!!.notifyItemRemoved(favourites.indexOf(name))
-        return true
-    }
-
-    @SuppressLint("MissingSuperCall")
-    override fun onSaveInstanceState(outState: Bundle) {
-        //hack below line to be commented to prevent crash on nougat.
-        //super.onSaveInstanceState(outState);
-    }
-
-    override fun onItemClicked(position: Int) {
-        if (actionMode != null) {
-            toggleSelection(position)
-        } else {
-            val intent = Intent(context, StopActivity::class.java)
-            intent.putExtra(StopActivity.SOURCE_TYPE, StopActivity.SOURCE_TYPE_FAV)
-            intent.putExtra(StopActivity.EXTRA_FAVOURITE, favourites[position])
-            startActivity(intent)
-        }
-    }
-
-    override fun onItemLongClicked(position: Int): Boolean {
-        if (actionMode == null) {
-            actionMode = startActionMode(actionModeCallback)
-        }
-
-        toggleSelection(position)
-
-        return true
-    }
-
-    private fun toggleSelection(position: Int) {
-        adapter.toggleSelection(position)
-        val count = adapter.getSelectedItemCount()
-
-        if (count == 0) {
-            actionMode?.finish()
-        } else {
-            actionMode?.title = getString(R.string.merge_favourites)
-            actionMode?.invalidate()
-        }
-    }
-
-    private fun clearSelection() {
-        adapter.clearSelection()
-        actionMode?.finish()
-    }
-
-    private inner class ActionModeCallback : ActionMode.Callback {
-        override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
-            menuInflater.inflate(R.menu.menu_favourite_merge, menu)
-            return true
-        }
-
-        override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
-            return false
-        }
-
-        override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
-            return when (item.itemId) {
-                R.id.action_merge -> {
-                    val selectedPositions = adapter.getSelectedItems()
-                    val selectedNames = selectedPositions.map { favourites[it]?.name }.filter { it != null }.map { it!! }
-
-                    (1 until selectedNames.size).forEach {
-                        selectedNames[it].let { name ->
-                            adapter.notifyItemRemoved(adapter.indexOf(name))
-                            adapter[name]?.unsubscribeFromDepartures(context)
-                        }
-                    }
-                    favourites.merge(selectedNames, context)
-                    adapter[selectedNames[0]]?.let {
-                        it.unsubscribeFromDepartures(context)
-                        it.subscribeForDepartures(this@DashActivity, context)
-                    }
-                    adapter.notifyItemChanged(adapter.indexOf(selectedNames[0]))
-
-                    clearSelection()
-                    true
-                }
-
-                else -> false
-            }
-        }
-
-        override fun onDestroyActionMode(mode: ActionMode) {
-            (favouritesList.adapter as FavouritesAdapter).clearSelection()
-            actionMode = null
-        }
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/EditFavouriteActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/EditFavouriteActivity.kt
deleted file mode 100644
index c372b185980e24b33d0c621529557d547276aa91..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/EditFavouriteActivity.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-package ml.adamsprogs.bimba.activities
-
-import android.app.Activity
-import android.content.Intent
-import android.os.Bundle
-import android.widget.EditText
-import androidx.appcompat.app.AppCompatActivity
-import kotlinx.android.synthetic.main.activity_edit_favourite.*
-import ml.adamsprogs.bimba.R
-import ml.adamsprogs.bimba.collections.FavouriteStorage
-import ml.adamsprogs.bimba.models.Favourite
-import ml.adamsprogs.bimba.models.adapters.FavouriteEditRowAdapter
-
-
-class EditFavouriteActivity : AppCompatActivity() {
-    companion object {
-        const val EXTRA_FAVOURITE = "favourite"
-        const val EXTRA_POSITION_BEFORE = "position_before"
-        const val EXTRA_NEW_NAME = "new_name"
-    }
-
-    private lateinit var favourites: FavouriteStorage
-    private lateinit var nameEdit: EditText
-    private var favourite: Favourite? = null
-    private var positionBefore: Int? = null
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_edit_favourite)
-
-        favourite = intent.getParcelableExtra(EXTRA_FAVOURITE)
-        positionBefore = intent.getIntExtra(EXTRA_POSITION_BEFORE, -1)
-        if (favourite == null)
-            finish()
-        favourites = FavouriteStorage.getFavouriteStorage(this)
-
-        val recyclerView = favourite_edit_list
-        val layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this)
-        recyclerView!!.layoutManager = layoutManager
-        val dividerItemDecoration = androidx.recyclerview.widget.DividerItemDecoration(this, layoutManager.orientation)
-        recyclerView.addItemDecoration(dividerItemDecoration)
-        recyclerView.adapter = FavouriteEditRowAdapter(favourite!!, favourite_edit_loading, favourite_edit_list)
-        setSupportActionBar(toolbar)
-        supportActionBar?.title = getString(R.string.edit_favourite_title, favourite!!.name)
-        nameEdit = favourite_name_edit
-        nameEdit.setText(favourite!!.name)
-    }
-
-    override fun onBackPressed() {
-        favourites.rename(favourite?.name!!, nameEdit.text.toString())
-        val returnIntent = Intent()
-        returnIntent.putExtra(EXTRA_POSITION_BEFORE, positionBefore)
-        returnIntent.putExtra(EXTRA_NEW_NAME, nameEdit.text.toString())
-        setResult(Activity.RESULT_OK, returnIntent)
-        super.onBackPressed()
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/LineSpecifyActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/LineSpecifyActivity.kt
deleted file mode 100644
index 79f7b0e63feb2b36c529c64ba63418a83a215ff6..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/LineSpecifyActivity.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-package ml.adamsprogs.bimba.activities
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import androidx.appcompat.app.AppCompatActivity
-import com.google.android.material.tabs.TabLayout
-import kotlinx.android.synthetic.main.activity_line_specify.*
-import kotlinx.android.synthetic.main.fragment_line_specify.view.*
-import ml.adamsprogs.bimba.R
-import ml.adamsprogs.bimba.models.Timetable
-
-class LineSpecifyActivity : AppCompatActivity() {
-    companion object {
-        const val EXTRA_LINE_ID = "line_id"
-    }
-
-    private var sectionsPagerAdapter: SectionsPagerAdapter? = null
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_line_specify)
-
-        setSupportActionBar(toolbar)
-        supportActionBar?.setDisplayHomeAsUpEnabled(true)
-
-        val line = intent.getStringExtra(EXTRA_LINE_ID)
-
-        val timetable = Timetable.getTimetable()
-        val graphs = timetable.getTripGraphs(line)
-
-        sectionsPagerAdapter = SectionsPagerAdapter(supportFragmentManager, graphs)
-
-        container.adapter = sectionsPagerAdapter
-
-        for (i in 0 until tabs.tabCount) {
-            tabs.getTabAt(i)?.text = graphs[i].headsign
-        }
-
-        container.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabs))
-        tabs.addOnTabSelectedListener(TabLayout.ViewPagerOnTabSelectedListener(container))
-    }
-
-    inner class SectionsPagerAdapter(fm: androidx.fragment.app.FragmentManager, private val graphs: Array<Timetable.TripGraph>) : androidx.fragment.app.FragmentPagerAdapter(fm) {
-
-        override fun getItem(position: Int): androidx.fragment.app.Fragment {
-            return PlaceholderFragment.newInstance(position + 1, graphs[position])
-        }
-
-        override fun getCount() = 2
-    }
-
-    class PlaceholderFragment : androidx.fragment.app.Fragment() {
-
-        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
-                                  savedInstanceState: Bundle?): View? {
-            val rootView = inflater.inflate(R.layout.fragment_line_specify, container, false)
-            rootView.section_label.text = arguments?.getString("graph") //todo draw it + clickable
-            return rootView
-        }
-
-        companion object {
-            private const val ARG_SECTION_NUMBER = "section_number"
-
-            fun newInstance(sectionNumber: Int, graph: Timetable.TripGraph): PlaceholderFragment {
-                val fragment = PlaceholderFragment()
-                val args = Bundle()
-                args.putInt(ARG_SECTION_NUMBER, sectionNumber)
-
-                //todo serialise graph // or draw and pass image
-                //args.putString("graph", graph.first.map { "${it.key}: ${it.value.joinToString(", ")}" }.joinToString("\n"))
-
-                fragment.arguments = args
-                return fragment
-            }
-        }
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/SettingsActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/SettingsActivity.kt
deleted file mode 100644
index a05be9afc33eba5fe1030e4538f9330b44ff01c7..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/SettingsActivity.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package ml.adamsprogs.bimba.activities
-
-import android.preference.*
-import android.os.Bundle
-import androidx.core.app.NavUtils
-import android.view.MenuItem
-import kotlinx.android.synthetic.main.activity_settings.*
-
-import ml.adamsprogs.bimba.*
-
-class SettingsActivity: AppCompatPreferenceActivity() {
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_settings)
-        setSupportActionBar(toolbar)
-        supportActionBar.setDisplayHomeAsUpEnabled(true)
-    }
-
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        when (item.itemId) {
-            android.R.id.home -> {
-                NavUtils.navigateUpFromSameTask(this)
-                return true
-            }
-        }
-        return super.onOptionsItemSelected(item)
-    }
-
-    class MainPreferenceFragment : PreferenceFragment() {
-        override fun onCreate(savedInstanceState: Bundle?) {
-            super.onCreate(savedInstanceState)
-            addPreferencesFromResource(R.xml.pref_main)
-
-            bindPreferenceSummaryToValue(findPreference(getString(R.string.key_timetable_source_url)))
-        }
-
-        private fun bindPreferenceSummaryToValue(preference: Preference) {
-            preference.onPreferenceChangeListener = bindPreferenceSummaryToValueListener
-
-            bindPreferenceSummaryToValueListener.onPreferenceChange(preference,
-                    PreferenceManager
-                            .getDefaultSharedPreferences(preference.context)
-                            .getString(preference.key, ""))
-        }
-
-        private val bindPreferenceSummaryToValueListener = Preference.OnPreferenceChangeListener { preference, newValue ->
-            val stringValue = newValue.toString()
-            if (preference is EditTextPreference) {
-                if (preference.getKey() == getString(R.string.key_timetable_source_url)) {
-                    preference.summary = stringValue
-                }
-            } else {
-                preference.summary = stringValue
-            }
-            true
-        }
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/SplashActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/SplashActivity.kt
deleted file mode 100644
index ff18b865168fce18b51c8abb639f0b194051a12d..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/SplashActivity.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package ml.adamsprogs.bimba.activities
-
-import android.content.Intent
-import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.app.AppCompatDelegate
-
-
-class SplashActivity : AppCompatActivity() {
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO)
-        startActivity(Intent(this, DashActivity::class.java))
-        finish()
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
deleted file mode 100644
index 425c9d04d2798f49ec0fd81ec4b72cb41e13554a..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/StopActivity.kt
+++ /dev/null
@@ -1,285 +0,0 @@
-package ml.adamsprogs.bimba.activities
-
-import android.content.DialogInterface
-import android.content.Intent
-import android.content.IntentFilter
-import android.os.Build
-import android.os.Bundle
-import android.text.Html
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import android.widget.AdapterView
-import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.content.res.ResourcesCompat
-import com.google.android.material.snackbar.Snackbar
-import kotlinx.android.synthetic.main.activity_stop.*
-import kotlinx.android.synthetic.main.banner.*
-import ml.adamsprogs.bimba.*
-import ml.adamsprogs.bimba.collections.FavouriteStorage
-import ml.adamsprogs.bimba.datasources.TimetableDownloader
-import ml.adamsprogs.bimba.datasources.VmService
-import ml.adamsprogs.bimba.models.Departure
-import ml.adamsprogs.bimba.models.Favourite
-import ml.adamsprogs.bimba.models.Plate
-import ml.adamsprogs.bimba.models.StopSegment
-import ml.adamsprogs.bimba.models.adapters.DeparturesAdapter
-import ml.adamsprogs.bimba.models.adapters.ServiceAdapter
-import java.util.Calendar
-import kotlin.collections.HashMap
-import kotlin.collections.HashSet
-import kotlin.collections.set
-
-class StopActivity : AppCompatActivity(), MessageReceiver.OnTimetableDownloadListener, ProviderProxy.OnDeparturesReadyListener {
-    companion object {
-        const val EXTRA_STOP_CODE = "stopCode"
-        const val EXTRA_STOP_NAME = "stopName"
-        const val EXTRA_FAVOURITE = "favourite"
-        const val SOURCE_TYPE = "sourceType"
-        const val SOURCE_TYPE_STOP = "stop"
-        const val SOURCE_TYPE_FAV = "favourite"
-
-        const val TIMETABLE_TYPE_DEPARTURE = "timetable_type_departure"
-        const val TIMETABLE_TYPE_FULL = "timetable_type_full"
-    }
-
-    private var stopCode = ""
-    private var favourite: Favourite? = null
-    private var timetableType = TIMETABLE_TYPE_DEPARTURE
-    private val context = this
-    private val receiver = MessageReceiver.getMessageReceiver()
-    private lateinit var providerProxy: ProviderProxy
-    private val departures = HashMap<Plate.ID, List<Departure>>()
-    private val fullDepartures = HashMap<String, List<Departure>>()
-    private lateinit var subscriptionId: String
-    private lateinit var adapter: DeparturesAdapter
-
-
-    private lateinit var sourceType: String
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_stop)
-
-        providerProxy = ProviderProxy(this)
-
-        sourceType = intent.getStringExtra(SOURCE_TYPE)
-
-        setSupportActionBar(toolbar)
-
-        when (sourceType) {
-            SOURCE_TYPE_STOP -> {
-                stopCode = intent.getSerializableExtra(EXTRA_STOP_CODE) as String
-                supportActionBar?.title = intent.getSerializableExtra(EXTRA_STOP_NAME) as String
-            }
-            SOURCE_TYPE_FAV -> {
-                favourite = intent.getParcelableExtra(EXTRA_FAVOURITE)
-                supportActionBar?.title = favourite!!.name
-            }
-        }
-
-        showFab()
-
-        val layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this)
-        departuresList.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(departuresList.context, layoutManager.orientation))
-        departuresList.adapter = DeparturesAdapter(this, null, true)
-        adapter = departuresList.adapter as DeparturesAdapter
-        departuresList.layoutManager = layoutManager
-
-        departuresList.addOnScrollListener(object : androidx.recyclerview.widget.RecyclerView.OnScrollListener() {
-            override fun onScrollStateChanged(recyclerView: androidx.recyclerview.widget.RecyclerView, newState: Int) {}
-            override fun onScrolled(recyclerView: androidx.recyclerview.widget.RecyclerView, dx: Int, dy: Int) {
-                updateFabVisibility(dy)
-                super.onScrolled(recyclerView, dx, dy)
-            }
-        })
-
-        if (stopCode != "")
-            providerProxy.getVmMessage(stopCode) { message ->
-                if (message != null) {
-                    val rendered =
-                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-                                Html.fromHtml(message, Html.FROM_HTML_MODE_LEGACY).toString()
-                            } else {
-                                @Suppress("DEPRECATION")
-                                Html.fromHtml(message).toString()
-                            }
-
-                    banner.visibility = View.VISIBLE
-                    banner_text.text = rendered
-                    banner_more.setOnClickListener {
-                        AlertDialog.Builder(context)
-                                .setPositiveButton(context.getText(android.R.string.ok))
-                                { dialog: DialogInterface, _: Int -> dialog.cancel() }
-                                .setCancelable(true)
-                                .setMessage(rendered)
-                                .create().show()
-                    }
-                }
-            }
-
-        prepareOnDownloadListener()
-        subscribeForDepartures()
-    }
-
-    private fun showFab() {
-        if (sourceType == SOURCE_TYPE_FAV)
-            return
-
-        val favourites = FavouriteStorage.getFavouriteStorage(context)
-        if (!favourites.has(stopCode)) {
-            fab.setImageDrawable(ResourcesCompat.getDrawable(context.resources, R.drawable.ic_favourite_empty, this.theme))
-        }
-
-        fab.setOnClickListener {
-            if (!favourites.has(stopCode)) {
-                val items = HashSet<StopSegment>()
-                items.add(StopSegment(stopCode, null))
-                favourites.add(stopCode, items, this@StopActivity)
-                fab.setImageDrawable(ResourcesCompat.getDrawable(context.resources, R.drawable.ic_favourite, this.theme))
-            } else {
-                Snackbar.make(it, getString(R.string.stop_already_fav), Snackbar.LENGTH_LONG)
-                        .setAction("Action", null).show()
-            }
-        }
-    }
-
-    //fixme<p:5> maybe better effects
-    private fun updateFabVisibility(dy: Int) {
-        if (fab == null)
-            return
-        if (dy > 0) {
-            fab.hide()
-        } else {
-            fab.show()
-        }
-    }
-
-    private fun prepareOnDownloadListener() {
-        val filter = IntentFilter(TimetableDownloader.ACTION_DOWNLOADED)
-        filter.addAction(VmService.ACTION_READY)
-        filter.addCategory(Intent.CATEGORY_DEFAULT)
-        registerReceiver(receiver, filter)
-        receiver.addOnTimetableDownloadListener(context)
-    }
-
-    private fun subscribeForDepartures() {
-        subscriptionId = if (sourceType == SOURCE_TYPE_STOP) {
-            providerProxy.subscribeForDepartures(stopCode, this, this)
-        } else
-            favourite!!.subscribeForDepartures(this, context)
-    }
-
-    override fun onDeparturesReady(departures: List<Departure>, plateId: Plate.ID?, code: Int) {
-        progressBar.visibility = View.GONE
-        showError(stop_layout, code, this)
-        if (plateId == null) {
-            this.departures.clear()
-            this.departures[Plate.ID.dummy] = departures
-        } else {
-            this.departures.remove(Plate.ID.dummy)
-            this.departures[plateId] = departures
-        }
-        if (timetableType == TIMETABLE_TYPE_FULL)
-            return
-        refreshAdapter()
-        if (adapter.departures?.isEmpty() != false) {
-            emptyStateIcon.visibility = View.VISIBLE
-            emptyStateText.visibility = View.VISIBLE
-            departuresList.visibility = View.GONE
-        } else {
-            emptyStateIcon.visibility = View.GONE
-            emptyStateText.visibility = View.GONE
-            departuresList.visibility = View.VISIBLE
-        }
-    }
-
-    private fun refreshAdapter() {
-        if (timetableType == TIMETABLE_TYPE_FULL) {
-            @Suppress("UNCHECKED_CAST")
-            adapter.departures = fullDepartures[(dateSpinner.selectedItem as ServiceAdapter.RowItem).service]
-        } else {
-            val now = Calendar.getInstance()
-            val seconds = now.secondsAfterMidnight()
-            adapter.departures = this.departures.flatMap { it.value }.sortedBy { (if (it.onStop) 0 else 1) * 172800 + it.timeTill(seconds) }  // todo sorted by also onStop
-        }
-        adapter.notifyDataSetChanged()
-    }
-
-    override fun onTimetableDownload(result: String?) {
-        val message: String = when (result) {
-            TimetableDownloader.RESULT_NO_CONNECTIVITY -> getString(R.string.no_connectivity_cant_update)
-            TimetableDownloader.RESULT_UP_TO_DATE -> getString(R.string.timetable_up_to_date)
-            TimetableDownloader.RESULT_FINISHED -> getString(R.string.timetable_downloaded)
-            else -> getString(R.string.error_try_later)
-        }
-        try {
-            Snackbar.make(findViewById(R.id.stop_layout), message, Snackbar.LENGTH_LONG).show()
-        } catch (e: IllegalArgumentException) {
-        }
-        providerProxy.refreshTimetable(this)
-    }
-
-    override fun onCreateOptionsMenu(menu: Menu): Boolean {
-        if (providerProxy.mode == ProviderProxy.MODE_FULL)
-            menuInflater.inflate(R.menu.menu_stop, menu)
-        return true
-    }
-
-    override fun onOptionsItemSelected(item: MenuItem): Boolean {
-        val id = item.itemId
-
-        if (id == R.id.action_change_type) {
-            if (timetableType == TIMETABLE_TYPE_DEPARTURE) {
-                timetableType = TIMETABLE_TYPE_FULL
-
-                item.icon = (ResourcesCompat.getDrawable(resources, R.drawable.ic_timetable_departure, this.theme))
-                adapter.relativeTime = false
-                if (fullDepartures.isEmpty())
-                    if (sourceType == SOURCE_TYPE_STOP)
-                        fullDepartures.putAll(providerProxy.getFullTimetable(stopCode))
-                    else
-                        fullDepartures.putAll(favourite!!.fullTimetable())
-
-                dateSpinner.let { spinner ->
-                    spinner.adapter = ServiceAdapter(this, R.layout.toolbar_spinner_item, fullDepartures.keys.map {
-                        ServiceAdapter.RowItem(it, providerProxy.describeService(it, this)!!)
-                    }.sorted()).apply {
-                        setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
-                    }
-                    spinner.visibility = View.VISIBLE
-                    spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
-                        override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
-                            refreshAdapter()
-                        }
-
-                        override fun onNothingSelected(parent: AdapterView<*>?) {
-                        }
-
-                    }
-                }
-
-                refreshAdapter()
-            } else {
-                dateSpinner.visibility = View.GONE
-                timetableType = TIMETABLE_TYPE_DEPARTURE
-                item.icon = (ResourcesCompat.getDrawable(resources, R.drawable.ic_timetable_full, this.theme))
-                adapter.relativeTime = true
-                refreshAdapter()
-            }
-            return true
-        }
-
-        return super.onOptionsItemSelected(item)
-    }
-
-    override fun onDestroy() {
-        super.onDestroy()
-        receiver.removeOnTimetableDownloadListener(context)
-        if (sourceType == SOURCE_TYPE_STOP)
-            providerProxy.unsubscribeFromDepartures(subscriptionId, this)
-        else
-            favourite!!.unsubscribeFromDepartures(this)
-        unregisterReceiver(receiver)
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt b/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt
deleted file mode 100644
index e2db35f26607e62e800fa323755b65b7bab5d34e..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/activities/StopSpecifyActivity.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-package ml.adamsprogs.bimba.activities
-
-import android.content.Context
-import android.content.Intent
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import androidx.appcompat.app.AppCompatActivity
-import kotlinx.android.synthetic.main.activity_stop_specify.*
-import ml.adamsprogs.bimba.ProviderProxy
-import ml.adamsprogs.bimba.R
-
-class StopSpecifyActivity : AppCompatActivity() {
-
-    companion object {
-        const val EXTRA_STOP_NAME = "stopName"
-    }
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        setContentView(R.layout.activity_stop_specify)
-
-        val name = intent.getStringExtra(EXTRA_STOP_NAME)
-        val providerProxy = ProviderProxy(this)
-        providerProxy.getSheds(name) {
-            progressBar.visibility = View.GONE
-            val layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this)
-            val departuresList: androidx.recyclerview.widget.RecyclerView = list_view
-
-            departuresList.adapter = ShedAdapter(this, it, name)
-            departuresList.layoutManager = layoutManager
-        }
-        /*val timetable = Timetable.getTimetable(this)
-        val headlines = timetable.getHeadlinesForStop(name)*/
-
-
-        setSupportActionBar(toolbar)
-        supportActionBar?.title = name
-    }
-
-    class ShedAdapter(val context: Context, private val values: Map<String, Set<String>>, private val stopName: String) :
-            androidx.recyclerview.widget.RecyclerView.Adapter<ShedAdapter.ViewHolder>() {
-        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
-            val context = parent.context
-            val inflater = LayoutInflater.from(context)
-
-            val rowView = inflater.inflate(R.layout.row_shed, parent, false)
-            return ViewHolder(rowView)
-        }
-
-        override fun getItemCount(): Int = values.size
-
-        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
-            holder.root.setOnClickListener {
-                val code = values.keys.sorted()[position]
-                val intent = Intent(context, StopActivity::class.java)
-                intent.putExtra(StopActivity.SOURCE_TYPE, StopActivity.SOURCE_TYPE_STOP)
-                intent.putExtra(StopActivity.EXTRA_STOP_CODE, code)
-                intent.putExtra(StopActivity.EXTRA_STOP_NAME, stopName)
-                context.startActivity(intent)
-            }
-            holder.stopCode.text = values.keys.sorted()[position]
-            holder.stopHeadlines.text = values.entries.sortedBy { it.key }[position].value
-                    .sortedBy { it.split(" → ")[0].padStart(4, '0') }
-                    .joinToString()
-        }
-
-        inner class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) {
-            val root = itemView.findViewById<View>(R.id.shed_row)!!
-            val stopCode: TextView = itemView.findViewById(R.id.stop_code)
-            val stopHeadlines: TextView = itemView.findViewById(R.id.stop_headlines)
-        }
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/collections/FavouriteStorage.kt b/app/src/main/java/ml/adamsprogs/bimba/collections/FavouriteStorage.kt
deleted file mode 100644
index 38292650494637faefb6a23f1b8b6b6050752dbb..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/collections/FavouriteStorage.kt
+++ /dev/null
@@ -1,188 +0,0 @@
-package ml.adamsprogs.bimba.collections
-
-import android.content.Context
-import android.content.SharedPreferences
-import com.google.gson.*
-import ml.adamsprogs.bimba.models.Departure
-import ml.adamsprogs.bimba.models.Favourite
-import ml.adamsprogs.bimba.models.Plate
-import ml.adamsprogs.bimba.models.StopSegment
-import ml.adamsprogs.bimba.secondsAfterMidnight
-import java.util.Calendar
-import kotlin.collections.ArrayList
-import kotlin.collections.HashMap
-import kotlin.collections.HashSet
-import kotlin.collections.component1
-import kotlin.collections.component2
-import kotlin.collections.set
-
-
-class FavouriteStorage private constructor(context: Context) : Iterable<Favourite> {
-    companion object {
-        private var favouriteStorage: FavouriteStorage? = null
-        fun getFavouriteStorage(context: Context? = null): FavouriteStorage {
-            return if (favouriteStorage == null) {
-                if (context == null)
-                    throw IllegalArgumentException("requested new storage appContext not given")
-                else {
-                    favouriteStorage = FavouriteStorage(context)
-                    favouriteStorage as FavouriteStorage
-                }
-            } else
-                favouriteStorage as FavouriteStorage
-        }
-    }
-
-    val favourites = HashMap<String, Favourite>()
-    private val positionIndex = IndexableTreeSet<String>()
-    private val preferences: SharedPreferences = context.getSharedPreferences("ml.adamsprogs.bimba.prefs", Context.MODE_PRIVATE)
-
-    init {
-        val favouritesString = preferences.getString("favourites", "{}")
-        JsonParser().parse(favouritesString).asJsonObject.entrySet().forEach { (name, timetables) ->
-            timetables.asJsonArray.map {
-                val plates = it.asJsonObject["plates"].let { element ->
-                    if (element == null || element.isJsonNull)
-                        null
-                    else {
-                        element.asJsonArray.map { it ->
-                            it.asJsonObject.let { id ->
-                                Plate.ID(id["line"].asString, id["stop"].asString, id["headsign"].asString)
-                            }
-                        }.toHashSet()
-                    }
-                }
-                StopSegment(it.asJsonObject["stop"].asString, plates)
-            }.toHashSet().let {
-                favourites[name] = Favourite(name, it, context)
-            }
-            positionIndex.add(name)
-        }
-    }
-
-    override fun iterator(): Iterator<Favourite> = favourites.values.iterator()
-
-    fun has(name: String): Boolean = favourites.contains(name)
-
-    fun add(name: String, timetables: HashSet<StopSegment>, context: Context) {
-        if (favourites[name] == null) {
-            favourites[name] = Favourite(name, timetables, context)
-            addIndex(name)
-            serialize()
-        }
-    }
-
-    fun add(name: String, favourite: Favourite) {
-        if (favourites[name] == null) {
-            favourites[name] = favourite
-            addIndex(name)
-            serialize()
-        }
-    }
-
-    private fun addIndex(name: String) {
-        positionIndex.add(name)
-    }
-
-    fun delete(name: String) {
-        favourites.remove(name)
-        positionIndex.remove(name)
-        serialize()
-    }
-
-    fun delete(name: String, plate: Plate.ID): Boolean {
-        return favourites[name]?.delete(plate).let {
-            serialize()
-            it
-        } ?: false
-    }
-
-    private fun serialize() {
-        val rootObject = JsonObject()
-        for ((name, favourite) in favourites) {
-            val timetables = JsonArray()
-            for (timetable in favourite.segments) {
-                val segment = JsonObject()
-                segment.addProperty("stop", timetable.stop)
-                val plates =
-                        if (timetable.plates == null)
-                            JsonNull.INSTANCE
-                        else
-                            JsonArray().apply {
-                                for (plate in timetable.plates ?: HashSet()) {
-                                    val element = JsonObject()
-                                    element.addProperty("stop", plate.stop)
-                                    element.addProperty("line", plate.line)
-                                    element.addProperty("headsign", plate.headsign)
-                                    add(element)
-                                }
-                            }
-                segment.add("plates", plates)
-                timetables.add(segment)
-            }
-            rootObject.add(name, timetables)
-        }
-        val favouritesString = Gson().toJson(rootObject)
-        val editor = preferences.edit()
-        editor.putString("favourites", favouritesString)
-        editor.apply()
-    }
-
-    fun merge(names: List<String>, context: Context) {
-        if (names.size < 2)
-            return
-
-        val newCache = HashMap<String, ArrayList<Departure>>()
-        names.forEach { name ->
-            favourites[name]!!.fullTimetable().forEach {
-                if (newCache[it.key] == null)
-                    newCache[it.key] = ArrayList()
-                newCache[it.key]!!.addAll(it.value)
-            }
-        }
-        val now = Calendar.getInstance().secondsAfterMidnight()
-        newCache.forEach { entry ->
-            entry.value.sortBy { it.timeTill(now) }
-        }
-        val newFavourite = Favourite(names[0], HashSet(), newCache, context)
-        for (name in names) {
-            newFavourite.segments.addAll(favourites[name]!!.segments)
-            favourites.remove(name)
-            positionIndex.remove(name)
-        }
-        favourites[names[0]] = newFavourite
-        addIndex(names[0])
-
-        serialize()
-    }
-
-    fun rename(oldName: String, newName: String) {
-        val favourite = favourites[oldName] ?: return
-        favourite.rename(newName)
-        favourites.remove(oldName)
-        positionIndex.remove(oldName)
-        favourites[newName] = favourite
-        addIndex(newName)
-        serialize()
-    }
-
-    operator fun get(name: String): Favourite? {
-        return favourites[name]
-    }
-
-    operator fun get(position: Int): Favourite? {
-        return favourites[positionIndex[position]]
-    }
-
-    operator fun set(name: String, value: Favourite) {
-        favourites[name] = value
-        serialize()
-    }
-
-    fun indexOf(name: String): Int {
-        return positionIndex.indexOf(name)
-    }
-
-    val size
-        get() = favourites.size
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/collections/IndexableTreeSet.kt b/app/src/main/java/ml/adamsprogs/bimba/collections/IndexableTreeSet.kt
deleted file mode 100644
index 19719f1a61a394bd4cf61dcd35e09ac21a0dc08a..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/collections/IndexableTreeSet.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package ml.adamsprogs.bimba.collections
-
-import java.util.TreeSet
-
-class IndexableTreeSet<T>: TreeSet<T>() {
-    operator fun get(position: Int): T {
-        @Suppress("UNCHECKED_CAST")
-        return this.toArray()[position] as T
-    }
-
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt b/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt
deleted file mode 100644
index 8eb2b34377ea9f1abf1093d2c3928a5cff204f9d..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/datasources/TimetableDownloader.kt
+++ /dev/null
@@ -1,165 +0,0 @@
-package ml.adamsprogs.bimba.datasources
-
-import android.annotation.TargetApi
-import android.app.IntentService
-import android.app.Notification
-import android.app.NotificationManager
-import android.content.Context
-import android.content.Intent
-import android.os.Build
-import android.preference.PreferenceManager.getDefaultSharedPreferences
-import androidx.core.app.NotificationCompat
-import ml.adamsprogs.bimba.*
-import java.io.EOFException
-import java.io.File
-import java.io.FileOutputStream
-import java.io.IOException
-import java.net.ConnectException
-import java.net.HttpURLConnection
-import java.net.URL
-import java.util.zip.GZIPInputStream
-import javax.net.ssl.HttpsURLConnection
-import javax.net.ssl.SSLException
-
-class TimetableDownloader : IntentService("TimetableDownloader") {
-    companion object {
-        const val ACTION_DOWNLOADED = "ml.adamsprogs.bimba.timetableDownloaded"
-        const val EXTRA_RESULT = "result"
-        const val RESULT_NO_CONNECTIVITY = "no connectivity"
-        const val RESULT_UP_TO_DATE = "up-to-date"
-        const val RESULT_FINISHED = "finished"
-    }
-
-    private lateinit var notificationManager: NotificationManager
-    private var sizeCompressed: Int = 0
-    private var sizeUncompressed: Int = 0
-
-    override fun onHandleIntent(intent: Intent?) {
-
-        if (intent != null) {
-            notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
-            val prefs = this.getSharedPreferences("ml.adamsprogs.bimba.prefs", Context.MODE_PRIVATE)!!
-            if (!NetworkStateReceiver.isNetworkAvailable()) {
-                sendResult(RESULT_NO_CONNECTIVITY)
-                return
-            }
-
-            val localETag = prefs.getString("etag", "")
-
-            val httpCon: HttpURLConnection
-            try {
-                var sourceUrl = getDefaultSharedPreferences(this).getString(getString(R.string.key_timetable_source_url), getString(R.string.timetable_source_url))!!
-                sourceUrl = sourceUrl.replace(Regex("^.*://", RegexOption.IGNORE_CASE), "")
-                sourceUrl = "https://$sourceUrl"
-                val url = URL(sourceUrl)
-                try {
-                    httpCon = url.openConnection() as HttpsURLConnection
-                    httpCon.addRequestProperty("If-None-Match", localETag)
-                    httpCon.connect()
-                } catch (e: SSLException) {
-                    sendResult(RESULT_NO_CONNECTIVITY)
-                    return
-                }
-                if (httpCon.responseCode == HttpsURLConnection.HTTP_NOT_MODIFIED) {
-                    sendResult(RESULT_UP_TO_DATE)
-                    return
-                }
-                if (httpCon.responseCode != HttpsURLConnection.HTTP_OK) {
-                    sendResult(RESULT_NO_CONNECTIVITY)
-                    return
-                }
-            } catch (e: IOException) {
-                sendResult(RESULT_NO_CONNECTIVITY)
-                return
-            } catch (e: EOFException) {
-                sendResult(RESULT_NO_CONNECTIVITY)
-                return
-            } catch (e: ConnectException) {
-                sendResult(RESULT_NO_CONNECTIVITY)
-                return
-            }
-
-            val newETag = httpCon.getHeaderField("ETag")
-            sizeCompressed = httpCon.getHeaderField("Content-Length").toInt() / 1024
-            sizeUncompressed = httpCon.getHeaderField("X-Uncompressed-Content-Length").toInt() / 1024
-
-            notify(0, R.string.timetable_downloading, R.string.timetable_downloading_progress, R.string.timetable_decompressing, sizeCompressed, sizeUncompressed)
-
-
-            val gtfsDb = File(getSecondaryExternalFilesDir(), "timetable_new.db")
-
-            val inputStream = httpCon.inputStream
-            val gzipInputStream = GZIPInputStream(inputStream)
-            val outputStream = FileOutputStream(gtfsDb)
-
-            gzipInputStream.listenableCopyTo(outputStream) {
-                notify((it / 1024).toInt(), R.string.timetable_downloading, R.string.timetable_downloading_progress, R.string.timetable_decompressing, sizeCompressed, sizeUncompressed)
-            }
-
-            val prefsEditor = prefs.edit()
-            prefsEditor.putString("etag", newETag)
-            prefsEditor.apply()
-
-            val oldDb = File(getSecondaryExternalFilesDir(), "timetable.db")
-            gtfsDb.renameTo(oldDb) // todo<p:1> delete old before downloading (may require stopping VmService), and mutex with VmService
-
-            cancelNotification()
-
-            sendResult(RESULT_FINISHED)
-        }
-    }
-
-    private fun sendResult(result: String) {
-        val broadcastIntent = Intent()
-        broadcastIntent.action = ACTION_DOWNLOADED
-        broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
-        broadcastIntent.putExtra(EXTRA_RESULT, result)
-        sendBroadcast(broadcastIntent)
-    }
-
-    private fun notify(downloadedKBytes: Int, titleId: Int, dwdMessageId: Int, dcmMessageId: Int, sizeCompressed: Int, sizeUncompressed: Int) {
-        val progress = Math.min(downloadedKBytes, sizeCompressed)
-        val message = if (progress < sizeCompressed)
-            getString(dwdMessageId,
-                    progress / 1024F, sizeCompressed / 1024F)
-        else
-            ""
-        val title = if (progress < sizeCompressed)
-            getString(titleId)
-        else
-            getString(dcmMessageId)
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
-            notifyCompat(downloadedKBytes, title, message, sizeUncompressed)
-        else
-            notifyStandard(downloadedKBytes, title, message, sizeUncompressed)
-    }
-
-    @Suppress("DEPRECATION")
-    private fun notifyCompat(progress: Int, title: String, message: String, max: Int) {
-        val builder = NotificationCompat.Builder(this)
-                .setSmallIcon(R.drawable.ic_download)
-                .setContentTitle(title)
-                .setContentText(message)
-                .setCategory(NotificationCompat.CATEGORY_PROGRESS)
-                .setOngoing(true)
-                .setProgress(max, progress, false)
-        notificationManager.notify(42, builder.build())
-    }
-
-    @TargetApi(Build.VERSION_CODES.O)
-    private fun notifyStandard(progress: Int, title: String, message: String, max: Int) {
-        NotificationChannels.makeChannel(NotificationChannels.CHANNEL_UPDATES, "Updates", notificationManager)
-        val builder = Notification.Builder(this, NotificationChannels.CHANNEL_UPDATES)
-                .setSmallIcon(R.drawable.ic_download)
-                .setContentTitle(title)
-                .setContentText(message)
-                .setCategory(Notification.CATEGORY_PROGRESS)
-                .setOngoing(true)
-                .setProgress(max, progress, false)
-        notificationManager.notify(42, builder.build())
-    }
-
-    private fun cancelNotification() {
-        notificationManager.cancel(42)
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt b/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt
deleted file mode 100644
index 69fac3a1226caa3f5f664310cbb3e9fd5601b0c7..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmClient.kt
+++ /dev/null
@@ -1,156 +0,0 @@
-package ml.adamsprogs.bimba.datasources
-
-import com.google.gson.Gson
-import com.google.gson.JsonObject
-import com.google.gson.JsonSyntaxException
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import ml.adamsprogs.bimba.NetworkStateReceiver
-import ml.adamsprogs.bimba.models.Plate
-import ml.adamsprogs.bimba.models.StopSegment
-import ml.adamsprogs.bimba.models.suggestions.StopSuggestion
-import okhttp3.MediaType
-import okhttp3.OkHttpClient
-import okhttp3.RequestBody
-import java.io.IOException
-import java.util.*
-import kotlin.collections.HashMap
-import kotlin.collections.HashSet
-
-class VmClient {
-    companion object {
-        private var vmClient: VmClient? = null
-
-        fun getVmClient(): VmClient {
-            if (vmClient == null)
-                vmClient = VmClient()
-            return vmClient!!
-        }
-    }
-
-    suspend fun getSheds(name: String): Map<String, Set<String>> {
-        val (_, response) = makeRequest("getBollardsByStopPoint", """{"name": "$name"}""")
-        if (!response.has("success"))
-            return emptyMap()
-        val rootObject = response["success"].asJsonObject["bollards"].asJsonArray
-        val result = HashMap<String, Set<String>>()
-        rootObject.forEach { element ->
-            val code = element.asJsonObject["bollard"].asJsonObject["tag"].asString
-            result[code] = element.asJsonObject["directions"].asJsonArray.map {
-                """${it.asJsonObject["lineName"].asString} → ${it.asJsonObject["direction"].asString}"""
-            }.toSet()
-        }
-        return result
-    }
-
-    /*
-    suspend fun getPlatesByStopPoint(code: String): Set<Plate.ID>? {
-        val getTimesResponse = makeRequest("getTimes", """{"symbol": "$code"}""")
-        val name = getTimesResponse["success"].asJsonObject["bollard"].asJsonObject["name"].asString
-
-        val bollards = getBollardsByStopPoint(name)
-        return bollards.filter {
-            it.key == code
-        }.values.flatMap {
-            it.map {
-                val (line, headsign) = it.split(" → ")
-                Plate.ID(AgencyAndId(line), AgencyAndId(code), headsign)
-            }
-        }.toSet()
-    }*/
-
-    suspend fun getStops(pattern: String): List<StopSuggestion> {
-        val (_, response) = withContext(Dispatchers.Default) {
-            makeRequest("getStopPoints", """{"pattern": "$pattern"}""")
-        }
-
-        if (!response.has("success"))
-            return emptyList()
-
-        val points = response["success"].asJsonArray.map { it.asJsonObject }
-
-        val names = HashSet<String>()
-
-        points.forEach {
-            val name = it["name"].asString
-            names.add(name)
-        }
-
-        return names.map { StopSuggestion(it, "") }
-    }
-
-    suspend fun makeRequest(method: String, data: String): Pair<Int, JsonObject> {
-        if (!NetworkStateReceiver.isNetworkAvailable())
-            return Pair(0, JsonObject())
-
-        val client = OkHttpClient()
-        val url = "http://www.peka.poznan.pl/vm/method.vm?ts=${Calendar.getInstance().timeInMillis}"
-        val body = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8"),
-                "method=$method&p0=$data")
-        val request = okhttp3.Request.Builder()
-                .url(url)
-                .post(body)
-                .build()
-
-
-        var responseBody: String? = null
-        var responseCode = 0
-        try {
-            withContext(Dispatchers.Default) {
-                client.newCall(request).execute().let {
-                    responseCode = it.code()
-                    responseBody = it.body()?.string()
-                }
-            }
-        } catch (e: IOException) {
-            return Pair(0, JsonObject())
-        }
-
-        return try {
-            Pair(responseCode, Gson().fromJson(responseBody, JsonObject::class.java))
-        } catch (e: JsonSyntaxException) {
-            Pair(responseCode, JsonObject())
-        }
-    }
-
-    suspend fun getName(symbol: String): String? {
-        val (_, timesResponse) = withContext(Dispatchers.Default) {
-            makeRequest("getTimes", """{"symbol": "$symbol"}""")
-        }
-        if (!timesResponse.has("success"))
-            return null
-
-        return timesResponse["success"].asJsonObject["bollard"].asJsonObject["name"].asString
-    }
-
-    suspend fun getDirections(symbol: String): StopSegment? {
-        val name = getName(symbol)
-        val (_, directionsResponse) = withContext(Dispatchers.Default) {
-            makeRequest("getBollardsByStopPoint", """{"name": "$name"}""")
-        }
-
-        if (!directionsResponse.has("success"))
-            return null
-
-        return StopSegment(symbol,
-                directionsResponse["success"].asJsonObject["bollards"].asJsonArray.filter {
-                    it.asJsonObject["bollard"].asJsonObject["tag"].asString == symbol
-                }[0].asJsonObject["directions"].asJsonArray.map {
-                    it.asJsonObject.let { direction ->
-                        Plate.ID(direction["lineName"].asString, symbol, direction["direction"].asString)
-                    }
-                }.toSet())
-    }
-
-    suspend fun getMessage(shed: String): String? {
-        val (_, response) = makeRequest("findMessagesForBollard", """{"symbol": "$shed"}""")
-
-        if (!response.has("success"))
-            return null
-
-        if (response["success"].asJsonArray.size() == 0)
-            return null
-
-        return response["success"].asJsonArray[0].asJsonObject["content"].asString
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmService.kt b/app/src/main/java/ml/adamsprogs/bimba/datasources/VmService.kt
deleted file mode 100644
index 72340432b5fe1edc2821048998f5cac1ab93aa20..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/datasources/VmService.kt
+++ /dev/null
@@ -1,203 +0,0 @@
-package ml.adamsprogs.bimba.datasources
-
-import android.app.Service
-import android.content.Intent
-import android.os.Handler
-import android.os.HandlerThread
-import android.os.IBinder
-import android.os.Process.THREAD_PRIORITY_BACKGROUND
-import com.google.gson.JsonObject
-import kotlinx.coroutines.*
-import ml.adamsprogs.bimba.NetworkStateReceiver
-import ml.adamsprogs.bimba.calendarFromIso
-import ml.adamsprogs.bimba.models.Departure
-import ml.adamsprogs.bimba.models.Plate
-import ml.adamsprogs.bimba.secondsAfterMidnight
-import java.util.*
-import kotlin.collections.*
-
-class VmService : Service() {
-    companion object {
-        const val ACTION_READY = "ml.adamsprogs.bimba.action.vm.ready"
-        const val EXTRA_DEPARTURES = "ml.adamsprogs.bimba.extra.vm.departures"
-        const val EXTRA_PLATE_ID = "ml.adamsprogs.bimba.extra.vm.plate"
-        const val EXTRA_STOP_CODE = "ml.adamsprogs.bimba.extra.vm.stop"
-        const val EXTRA_CODE = "ml.adamsprogs.bimba.extra.vm.code"
-        const val TICK_6_ZINA_TIM = 12500L
-    }
-
-    private var handler: Handler? = null
-    private val tick6ZinaTim: Runnable = object : Runnable {
-        override fun run() {
-            handler!!.postDelayed(this, TICK_6_ZINA_TIM)
-            try {
-                for (plateId in requests.keys)
-                    GlobalScope.launch {
-                        downloadVM()
-                    }
-            } catch (e: IllegalArgumentException) {
-            }
-        }
-    }
-    private val requests = HashMap<String, Int>()
-    private val vms = HashMap<String, Set<Plate>>()
-
-    override fun onCreate() {
-        val thread = HandlerThread("ServiceStartArguments", THREAD_PRIORITY_BACKGROUND)
-        thread.start()
-        handler = Handler(thread.looper)
-        handler!!.postDelayed(tick6ZinaTim, TICK_6_ZINA_TIM)
-    }
-
-    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
-        if (intent == null)
-            return START_STICKY
-        val stopCode = intent.getStringExtra("stop")!!
-        val action = intent.action
-        val once = intent.getBooleanExtra("once", false)
-        if (action == "request") {
-            if (isAlreadyRequested(stopCode)) {
-                incrementRequest(stopCode)
-                sendResult(stopCode)
-            } else {
-                if (!once)
-                    addRequest(stopCode)
-                GlobalScope.launch {
-                    downloadVM(stopCode)
-                }
-            }
-        } else if (action == "remove") {
-            decrementRequest(stopCode)
-            cleanRequests()
-        }
-        return START_STICKY
-    }
-
-    private fun cleanRequests() {
-        val newRequests = requests.filter { it.value > 0 }
-        requests.clear()
-        newRequests.forEach {
-            requests[it.key] = it.value
-        }
-    }
-
-    private fun addRequest(stopCode: String) {
-        if (requests[stopCode] == null)
-            requests[stopCode] = 0
-        requests[stopCode] = requests[stopCode]!! + 1
-    }
-
-    private fun incrementRequest(stopCode: String) {
-        requests[stopCode] = requests[stopCode]!! + 1
-    }
-
-    private fun decrementRequest(stopCode: String) {
-        requests[stopCode] = requests[stopCode]!! - 1
-    }
-
-    private fun isAlreadyRequested(stopCode: String): Boolean {
-        return stopCode in requests
-    }
-
-
-    override fun onBind(intent: Intent): IBinder? {
-        return null
-    }
-
-    override fun onDestroy() {
-    }
-
-    @Synchronized
-    private suspend fun downloadVM() {
-        vms.forEach {
-            downloadVM(it.key)
-        }
-    }
-
-    @Synchronized
-    private suspend fun downloadVM(stopCode: String) {
-        if (!NetworkStateReceiver.isNetworkAvailable()) {
-            vms[stopCode] = emptySet()
-            sendResult(stopCode, null, null, 0)
-            return
-        }
-
-        val (code, javaRootMapObject) = withContext(Dispatchers.Default) {
-            VmClient.getVmClient().makeRequest("getTimes", """{"symbol": "$stopCode"}""")
-        }
-
-        if (!javaRootMapObject.has("success")) {
-            sendResult(stopCode, null, null, code)
-            return
-        }
-
-        val times = (javaRootMapObject["success"].asJsonObject)["times"].asJsonArray.map { it.asJsonObject }
-        parseTimes(stopCode, times)
-    }
-
-    private fun parseTimes(stopCode: String, times: List<JsonObject>) {
-        val date = Calendar.getInstance()
-        val todayDay = "${date.get(Calendar.DATE)}".padStart(2, '0')
-
-        val departures = HashMap<Plate.ID, HashSet<Departure>>()
-
-        times.forEach {
-            val thisLine = it["line"].asString
-            val thisHeadsign = it["direction"].asString
-            val thisPlateId = Plate.ID(thisLine, stopCode, thisHeadsign)
-            if (departures[thisPlateId] == null)
-                departures[thisPlateId] = HashSet()
-            val departureDay = (it["departure"].asString).split("T")[0].split("-")[2]
-            val departureTime = calendarFromIso(it["departure"].asString).secondsAfterMidnight()
-            var ticketMachine = Departure.TICKET_MACHINE_NONE
-            if (it.has("driversTicketMachine")) {
-                if (it["driversTicketMachine"].asBoolean)
-                    ticketMachine = Departure.TICKET_MACHINE_DRIVER
-            }
-            if (it.has("ticketMachine")) {
-                if (it["ticketMachine"].asBoolean)
-                    ticketMachine = Departure.TICKET_MACHINE_AUTOMAT
-            }
-            val lowFloor = if (it.has("lowFloorBus")) it["lowFloorBus"].asBoolean else false
-            val departure = Departure(thisLine, listOf(-1), departureTime, lowFloor,
-                    ArrayList(), it["direction"].asString, it["realTime"].asBoolean,
-                    departureDay != todayDay, it["onStopPoint"].asBoolean, ticketMachine)
-            departures[thisPlateId]!!.add(departure)
-        }
-
-        departures.forEach {
-            val departuresForPlate = HashMap<Int, HashSet<Departure>>()
-            departuresForPlate[-1] = it.value
-            val vm = HashSet<Plate>()
-            vm.add(Plate(it.key, departuresForPlate))
-            vms[stopCode] = vm
-            if (departures.isEmpty())
-                sendResult(stopCode, it.key, null)
-            else
-                sendResult(stopCode, it.key, it.value)
-        }
-
-    }
-
-    private fun sendResult(stopCode: String) {
-        vms[stopCode]?.forEach {
-            sendResult(it.id.stop, it.id, it.departures?.get(-1))
-        }
-
-    }
-
-    private fun sendResult(stopCode: String, plateId: Plate.ID?, departures: HashSet<Departure>?, code: Int = 200) {
-        val broadcastIntent = Intent()
-        broadcastIntent.action = ACTION_READY
-        broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT)
-        if (departures != null)
-            broadcastIntent.putStringArrayListExtra(EXTRA_DEPARTURES, departures.map { it.toString() } as ArrayList)
-        broadcastIntent.putExtra(EXTRA_CODE, code)
-        broadcastIntent.putExtra(EXTRA_PLATE_ID, plateId)
-        broadcastIntent.putExtra(EXTRA_STOP_CODE, stopCode)
-        sendBroadcast(broadcastIntent)
-    }
-}
-
-//note application stops the service on exit
-




diff --git a/app/src/main/java/ml/adamsprogs/bimba/extensions.kt b/app/src/main/java/ml/adamsprogs/bimba/extensions.kt
deleted file mode 100644
index ec86bc5c93eca92d2228020a27517054304315a0..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/extensions.kt
+++ /dev/null
@@ -1,126 +0,0 @@
-package ml.adamsprogs.bimba
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.graphics.drawable.Drawable
-import android.os.Build
-import android.text.format.DateFormat
-import android.view.View
-import com.google.android.material.snackbar.Snackbar
-import java.io.File
-import java.io.InputStream
-import java.io.OutputStream
-import java.text.SimpleDateFormat
-import java.util.*
-import kotlin.collections.ArrayList
-
-internal fun Calendar.rollTime(seconds: Int): Calendar {
-    val hour = seconds / 3600
-    val minute = (seconds % 3600) / 60
-    val second = (seconds % 60)
-    this.set(Calendar.HOUR_OF_DAY, hour)
-    this.set(Calendar.MINUTE, minute)
-    this.set(Calendar.SECOND, second)
-    this.set(Calendar.MILLISECOND, 0)
-    return this
-}
-
-internal fun Calendar.secondsAfterMidnight(): Int {
-    val hour = this.get(Calendar.HOUR_OF_DAY)
-    val minute = this.get(Calendar.MINUTE)
-    val second = this.get(Calendar.SECOND)
-    return hour * 3600 + minute * 60 + second
-}
-
-internal fun Calendar.toIsoDate(): String {
-    val year = this.get(Calendar.YEAR)
-    val month = String.format("%02d", this.get(Calendar.MONTH) + 1)
-    val day = String.format("%02d", this.get(Calendar.DAY_OF_MONTH))
-    return "$year$month$day"
-}
-
-const val ISO_8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
-const val ISO_8601_DATE_ONLY_FORMAT = "yyyyMMdd"
-
-@SuppressLint("SimpleDateFormat")
-fun calendarFromIso(iso: String): Calendar {
-    val calendar = Calendar.getInstance()
-    val dateFormat = SimpleDateFormat(ISO_8601_DATE_FORMAT)
-    val date = dateFormat.parse(iso)
-    calendar.time = date
-    return calendar
-}
-
-@SuppressLint("SimpleDateFormat")
-fun calendarFromIsoD(iso: String): Calendar {
-    val calendar = Calendar.getInstance()
-    val dateFormat = SimpleDateFormat(ISO_8601_DATE_ONLY_FORMAT)
-    val date = dateFormat.parse(iso)
-    calendar.time = date
-    return calendar
-}
-
-fun getDrawable(id: Int, context: Context): Drawable {
-    @Suppress("DEPRECATION")
-    (return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
-        context.resources.getDrawable(id, null)
-    else
-        context.resources.getDrawable(id))
-}
-
-internal fun CharSequence.safeSplit(vararg delimiters: String, ignoreCase: Boolean = false, limit: Int = 0): List<String>? {
-    if (this == "null")
-        return null
-    if (this == "")
-        return ArrayList()
-    return this.split(*delimiters, ignoreCase = ignoreCase, limit = limit)
-}
-
-internal fun Context.getSecondaryExternalFilesDir(): File {
-    val dirs = this.getExternalFilesDirs(null)
-    return dirs[0]
-//    return dirs[dirs.size - 1]
-}
-
-internal fun InputStream.listenableCopyTo(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SIZE, listener: (Long) -> Unit): Long {
-    var bytesCopied: Long = 0
-    val buffer = ByteArray(bufferSize)
-    var bytes = read(buffer)
-    while (bytes >= 0) {
-        out.write(buffer, 0, bytes)
-        bytesCopied += bytes
-        listener(bytesCopied)
-        bytes = read(buffer)
-    }
-    return bytesCopied
-}
-
-internal fun Calendar.toNiceString(context: Context, withTime: Boolean = false): String {
-    val dateFormat = DateFormat.getMediumDateFormat(context)
-    val timeFormat = DateFormat.getTimeFormat(context)
-    val now = Calendar.getInstance()
-    val date = if (get(Calendar.YEAR) == now.get(Calendar.YEAR)) {
-        when {
-            get(Calendar.DAY_OF_YEAR) == now.get(Calendar.DAY_OF_YEAR) -> timeFormat.format(time)
-            now.apply { add(Calendar.DATE, -1) }.get(Calendar.DAY_OF_YEAR) == get(Calendar.DAY_OF_YEAR) -> "Yesterday"
-            else -> DateFormat.format("d MMM" as CharSequence, this.time) as String
-        }
-    } else
-        dateFormat.format(this.time)
-
-    return if (withTime) {
-        val time = timeFormat.format(this.time)
-        "$date, $time"
-    } else
-        date
-}
-
-fun showError(view: View, code: Int, context: Context) {
-    val message = when {
-        code == 0 -> context.getString(R.string.no_connectivity)
-        (code >= 500) and (code < 600) -> context.getString(R.string.server_error)
-        else -> ""
-    }
-    if (message != "")
-        Snackbar.make(view, message, Snackbar.LENGTH_LONG).show()
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt
deleted file mode 100644
index 983fefa306c252ef87247964bac8106519239c52..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/Departure.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-package ml.adamsprogs.bimba.models
-
-import android.content.Context
-import ml.adamsprogs.bimba.Declinator
-import ml.adamsprogs.bimba.R
-import ml.adamsprogs.bimba.rollTime
-import ml.adamsprogs.bimba.safeSplit
-import java.util.*
-
-data class Departure(val line: String, val mode: List<Int>, val time: Int, val lowFloor: Boolean, //time in seconds since midnight
-                     val modification: List<String>, val headsign: String, val vm: Boolean = false,
-                     var tomorrow: Boolean = false, val onStop: Boolean = false, val ticketMachine: Int= TICKET_MACHINE_NONE) {
-
-    val isModified: Boolean
-        get() {
-            return modification.isNotEmpty()
-        }
-
-    override fun toString(): String {
-        return "$line|${mode.joinToString(";")}|$time|$lowFloor|${modification.joinToString(";")}|$headsign|$vm|$tomorrow|$onStop|$ticketMachine"
-    }
-
-    fun copy(): Departure {
-        return Departure.fromString(this.toString())
-    }
-
-    companion object {
-        const val TICKET_MACHINE_NONE = 0
-        const val TICKET_MACHINE_AUTOMAT = 1
-        const val TICKET_MACHINE_DRIVER = 2
-        fun fromString(string: String): Departure {
-            val array = string.split("|")
-            if (array.size != 10)
-                throw IllegalArgumentException()
-            val modification = array[4].safeSplit(";")!!
-            return Departure(array[0],
-                    array[1].safeSplit(";")!!.map { Integer.parseInt(it) },
-                    Integer.parseInt(array[2]), array[3] == "true",
-                    modification, array[5], array[6] == "true",
-                    array[7] == "true", array[8] == "true", Integer.parseInt(array[9]))
-        }
-    }
-
-    fun timeTill(relativeTo: Int): Int {
-        var time = this.time
-        if (this.tomorrow)
-            time += 24 * 60 * 60
-        return (time - relativeTo) / 60
-    }
-
-    val lineText: String = line
-
-    fun timeTillText(context: Context, relativeTime: Boolean = true): String {
-        val now = Calendar.getInstance()
-        val departureTime = Calendar.getInstance().rollTime(time)
-        if (tomorrow)
-            departureTime.add(Calendar.DAY_OF_MONTH, 1)
-
-        val departureIn = ((departureTime.timeInMillis - now.timeInMillis) / (1000 * 60)).toInt()
-
-        return if (departureIn > 60 || departureIn < 0 || !relativeTime)
-            context.getString(R.string.departure_at, "${String.format("%02d", departureTime.get(Calendar.HOUR_OF_DAY))}:${String.format("%02d", departureTime.get(Calendar.MINUTE))}")
-        else if (departureIn > 0 && !onStop)
-            context.getString(Declinator.decline(departureIn), departureIn.toString())
-        else if (departureIn == 0 && !onStop)
-            context.getString(R.string.in_a_moment)
-        else if (departureIn == 0)
-            context.getString(R.string.now)
-        else
-            context.getString(R.string.just_departed)
-    }
-
-    fun timeAtMessage(context: Context): String {
-        val departureTime = Calendar.getInstance().rollTime(time)
-        if (tomorrow)
-            departureTime.add(Calendar.DAY_OF_MONTH, 1)
-
-        return context.getString(R.string.departure_at,
-                "${String.format("%02d",
-                        departureTime.get(Calendar.HOUR_OF_DAY))}:${String.format("%02d",
-                        departureTime.get(Calendar.MINUTE))}") +
-                if (isModified)
-                    " " + modification.joinToString("; ", "(", ")")
-                else ""
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt
deleted file mode 100644
index 5c7db919c7242c6f09154caa31b6706562f1bddc..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/Favourite.kt
+++ /dev/null
@@ -1,169 +0,0 @@
-package ml.adamsprogs.bimba.models
-
-import android.content.Context
-import android.os.Parcel
-import android.os.Parcelable
-import ml.adamsprogs.bimba.ProviderProxy
-import ml.adamsprogs.bimba.safeSplit
-import java.io.File
-import java.math.BigInteger
-import java.security.SecureRandom
-import kotlin.collections.*
-
-class Favourite : Parcelable, ProviderProxy.OnDeparturesReadyListener {
-    private val cacheDir: File
-    private lateinit var listener: ProviderProxy.OnDeparturesReadyListener
-    var name: String
-        private set
-    var segments: HashSet<StopSegment>
-        private set
-    private var fullDepartures: Map<String, List<Departure>> = HashMap()
-    private val cache = HashMap<Plate.ID, List<Departure>>()
-    private var listenerId = ""
-
-    val size
-        get() = segments.sumBy {
-            it.size
-        }
-
-    private val providerProxy: ProviderProxy
-
-    constructor(parcel: Parcel) {
-        this.name = parcel.readString()!!
-        @Suppress("UNCHECKED_CAST")
-        val set = HashSet<StopSegment>()
-        val array = parcel.readParcelableArray(StopSegment::class.java.classLoader)!!
-        array.forEach {
-            set.add(it as StopSegment)
-        }
-        this.segments = set
-        this.cacheDir = File(parcel.readString())
-        val mapDir = File(parcel.readString())
-
-        val mapString = mapDir.readText()
-
-        val map = HashMap<String, List<Departure>>()
-        mapString.safeSplit("%")!!.forEach { it ->
-            val (k, v) = it.split("#")
-            map[k] = v.split("&").map { Departure.fromString(it) }
-        }
-        this.fullDepartures = map
-        mapDir.delete()
-        providerProxy = ProviderProxy()
-    }
-
-    constructor(name: String, segments: HashSet<StopSegment>, cache: Map<String, List<Departure>>, context: Context) {
-        this.fullDepartures = cache
-        this.name = name
-        this.segments = segments
-        this.cacheDir = context.cacheDir
-        providerProxy = ProviderProxy(context)
-    }
-
-    constructor(name: String, timetables: HashSet<StopSegment>, context: Context) {
-        this.name = name
-        this.segments = timetables
-        this.cacheDir = context.cacheDir
-        providerProxy = ProviderProxy(context)
-
-    }
-
-    override fun describeContents(): Int {
-        return Parcelable.CONTENTS_FILE_DESCRIPTOR
-    }
-
-    override fun writeToParcel(dest: Parcel?, flags: Int) {
-        dest?.writeString(name)
-        val parcelableSegments = segments.map { it }.toTypedArray()
-        dest?.writeParcelableArray(parcelableSegments, flags)
-        dest?.writeString(cacheDir.absolutePath)
-
-        val bytes = ByteArray(4) { 0 }
-        SecureRandom().nextBytes(bytes)
-        val mapFile = File(cacheDir, BigInteger(1, bytes).toString(16))
-        dest?.writeString(mapFile.absolutePath)
-
-        var isFirst = true
-        var map = ""
-        fullDepartures.forEach { it ->
-            if (isFirst)
-                isFirst = false
-            else
-                map += '%'
-
-            map += "${it.key}#${it.value.joinToString("&") { it.toString() }}"
-        }
-        mapFile.writeText(map)
-    }
-
-    fun delete(plateId: Plate.ID): Boolean {
-        segments.forEach {
-            if (!it.remove(plateId))
-                return false
-        }
-        removeFromCache(plateId)
-        return true
-    }
-
-    fun rename(newName: String) {
-        name = newName
-    }
-
-    companion object CREATOR : Parcelable.Creator<Favourite> {
-        override fun createFromParcel(parcel: Parcel): Favourite {
-            return Favourite(parcel)
-        }
-
-        override fun newArray(size: Int): Array<Favourite?> {
-            return arrayOfNulls(size)
-        }
-    }
-
-    fun nextDeparture() =
-            if (cache.isEmpty())
-                null
-            else
-                cache.flatMap { it.value }.let { it ->
-                    if (it.isEmpty())
-                        null
-                    else
-                        it.sortedBy { it.time }[0]
-                }
-
-
-    fun fullTimetable(): Map<String, List<Departure>> {
-        if (fullDepartures.isEmpty())
-            fullDepartures = providerProxy.getFullTimetable(segments)
-        return fullDepartures
-    }
-
-    private fun removeFromCache(plate: Plate.ID) {
-        val map = HashMap<String, List<Departure>>()
-        fullDepartures
-        fullDepartures.forEach { it ->
-            map[it.key] = it.value.filter { plate.line != it.line || plate.headsign != it.headsign }
-        }
-        fullDepartures = map
-    }
-
-    fun subscribeForDepartures(listener: ProviderProxy.OnDeparturesReadyListener, context: Context): String {
-        this.listener = listener
-        listenerId = providerProxy.subscribeForDepartures(segments, this, context)
-        return listenerId
-    }
-
-    override fun onDeparturesReady(departures: List<Departure>, plateId: Plate.ID?, code: Int) {
-        if (plateId == null) {
-            cache.clear()
-            cache[Plate.ID.dummy] = departures
-        } else {
-            cache.remove(Plate.ID.dummy)
-            cache[plateId] = departures
-        }
-        listener.onDeparturesReady(departures, plateId, code)
-    }
-
-    fun unsubscribeFromDepartures(context: Context) {
-        providerProxy.unsubscribeFromDepartures(listenerId, context)
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt
deleted file mode 100644
index d4f7d8cc0dd3dc9e147c63f4182cbc1e009c64e7..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/Plate.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package ml.adamsprogs.bimba.models
-
-import java.io.Serializable
-
-data class Plate(val id: ID, val departures: HashMap<Int, HashSet<Departure>>?) {
-    override fun toString(): String {
-        var result = "${id.line}=${id.stop}=${id.headsign}={"
-        if (departures != null) {
-            for ((service, column) in departures) {
-                result += service.toString() + ":"
-                for (departure in column) {
-                    result += departure.toString() + ";"
-                }
-            }
-        }
-        result += "}"
-        return result
-    }
-
-    companion object {
-        /*fun fromString(string: String): Plate {
-            val (lineStr, stopStr, headsign, departuresString) = string.split("=")
-            val departures = HashMap<Int, HashSet<Departure>>()
-            departuresString.replace("{", "").replace("}", "").split(";")
-                    .filter { it != "" }
-                    .forEach {
-                        try {
-                            val (serviceStr, depStr) = it.split(":")
-                            val dep = Departure.fromString(depStr)
-                            if (departures[serviceStr] == null)
-                                departures[serviceStr] = HashSet()
-                            departures[serviceStr]!!.add(dep)
-                        } catch (e: IllegalArgumentException) {
-                        }
-                    }
-            return Plate(ID(lineStr, stopStr, headsign), departures)
-        }
-
-        fun join(set: Set<Plate>): HashMap<String, ArrayList<Departure>> {
-            val departures = HashMap<String, ArrayList<Departure>>()
-            for (plate in set) {
-                for ((mode, d) in plate.departures!!) {
-                    if (departures[mode] == null)
-                        departures[mode] = ArrayList()
-                    departures[mode]!!.addAll(d)
-                }
-            }
-            for ((mode, _) in departures) {
-                departures[mode]?.sortBy { it.time }
-            }
-            return departures
-        }*/
-    }
-
-    data class ID(val line: String, val stop: String, val headsign: String) : Serializable {
-        companion object {
-            val dummy = Plate.ID("", "", "")
-
-            fun fromString(string: String): ID {
-                val (line, stop, headsign) = string.split("|")
-                return ID(line,
-                        stop, headsign)
-            }
-        }
-
-        override fun equals(other: Any?): Boolean {
-            if (other !is ID)
-                return false
-            return line == other.line && stop == other.stop && headsign.toLowerCase() == other.headsign.toLowerCase()
-        }
-
-        override fun toString(): String {
-            return "$line|$stop|$headsign"
-        }
-
-        override fun hashCode(): Int {
-            var result = line.hashCode()
-            result = 31 * result + stop.hashCode()
-            result = 31 * result + headsign.hashCode()
-            return result
-        }
-
-        constructor(other: Plate.ID) : this(other.line, other.stop, other.headsign)
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/StopSegment.kt b/app/src/main/java/ml/adamsprogs/bimba/models/StopSegment.kt
deleted file mode 100644
index e6ef8860315c2d2aca5a481267fb924954bf9ceb..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/StopSegment.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package ml.adamsprogs.bimba.models
-
-import android.os.Parcel
-import android.os.Parcelable
-import ml.adamsprogs.bimba.safeSplit
-
-data class StopSegment(val stop: String, var plates: Set<Plate.ID>?) : Parcelable {
-    constructor(parcel: Parcel) : this(
-            parcel.readSerializable() as String,
-            parcel.readString().safeSplit(";")?.map { Plate.ID.fromString(it) }?.toSet()
-    )
-
-    companion object CREATOR : Parcelable.Creator<StopSegment> {
-        override fun createFromParcel(parcel: Parcel): StopSegment {
-            return StopSegment(parcel)
-        }
-
-        override fun newArray(size: Int): Array<StopSegment?> {
-            return arrayOfNulls(size)
-        }
-    }
-
-    override fun writeToParcel(dest: Parcel?, flags: Int) {
-        dest?.writeSerializable(stop)
-        if (plates != null)
-            dest?.writeString(plates!!.joinToString(";") { it.toString() })
-        else
-            dest?.writeString("null")
-    }
-
-    override fun describeContents(): Int {
-        return Parcelable.CONTENTS_FILE_DESCRIPTOR
-    }
-
-    override fun equals(other: Any?): Boolean {
-        if (other !is StopSegment)
-            return false
-        if (this.stop != other.stop)
-            return false
-        if (this.plates != null && other.plates == null)
-            return false
-        if (this.plates == null && other.plates != null)
-            return false
-        if (this.plates == null && other.plates == null)
-            return true
-        if (this.plates!!.size != other.plates!!.size)
-            return false
-        if (this.plates!!.containsAll(other.plates!!))
-            return true
-        return false
-    }
-
-    override fun hashCode(): Int {
-        var hashCode = stop.hashCode()
-        plates?.forEach { hashCode = 31 * hashCode + it.hashCode() }
-        return hashCode
-    }
-
-    operator fun contains(plateId: Plate.ID): Boolean {
-        if (plates == null)
-            return plateId.stop == stop
-        return plates!!.contains(plateId)
-    }
-
-    fun remove(plateId: Plate.ID): Boolean {
-        if (plates == null)
-            return false
-
-        plates = plates!!.asSequence().filter { it != plateId }.toSet()
-        return true
-    }
-
-    override fun toString(): String {
-        var s = "$stop: "
-        if (plates == null)
-            s += "NULL"
-        else {
-            s += "{"
-            s += plates!!.joinToString { it.toString() }
-            s += "}"
-        }
-        return s
-    }
-
-    val size: Int
-        get() = plates?.size ?: 0
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt b/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt
deleted file mode 100644
index 363e7bb0640347a8ba1a3882954ead8ec6a670e4..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/Timetable.kt
+++ /dev/null
@@ -1,547 +0,0 @@
-package ml.adamsprogs.bimba.models
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.database.Cursor
-import android.database.CursorIndexOutOfBoundsException
-import android.database.sqlite.SQLiteDatabase
-import android.database.sqlite.SQLiteException
-import android.util.SparseArray
-import android.util.SparseBooleanArray
-import ml.adamsprogs.bimba.*
-import ml.adamsprogs.bimba.models.gtfs.Route
-import ml.adamsprogs.bimba.models.gtfs.Stop
-import ml.adamsprogs.bimba.models.gtfs.Trip
-import ml.adamsprogs.bimba.models.suggestions.LineSuggestion
-import ml.adamsprogs.bimba.models.suggestions.StopSuggestion
-import java.io.File
-import kotlin.collections.*
-import java.util.Calendar as JCalendar
-
-class Timetable private constructor() {
-    companion object {
-        private var timetable: Timetable? = null
-
-        fun getTimetable(context: Context? = null, force: Boolean = false): Timetable {
-            return if (timetable == null || force)
-                if (context != null) {
-                    constructTimetable(context)
-                    timetable!!
-                } else
-                    throw IllegalArgumentException("new timetable requested and no `context` given")
-            else if (context != null) {
-                try {
-                    constructTimetable(context)
-                    timetable!!
-                } catch (e: Exception) {
-                    timetable!!
-                }
-            } else
-                timetable!!
-        }
-
-        private fun constructTimetable(context: Context) {
-            val timetable = Timetable()
-            val filesDir = context.getSecondaryExternalFilesDir()
-            val dbFile = File(filesDir, "timetable.db")
-            timetable.db = try {
-                SQLiteDatabase.openDatabase(dbFile.path, null, SQLiteDatabase.OPEN_READONLY)
-            } catch (e: SQLiteException) {
-                null
-            }
-            this.timetable = timetable
-        }
-
-        fun delete(context: Context) {
-            val filesDir = context.getSecondaryExternalFilesDir()
-            val dbFile = File(filesDir, "timetable.db")
-            try {
-                dbFile.delete()
-            } catch (e: Exception) {
-            }
-        }
-    }
-
-    private var db: SQLiteDatabase? = null
-    private var _stops: List<StopSuggestion>? = null
-
-    fun refresh() {
-    }
-
-    fun getStopSuggestions(/*context: Context, */force: Boolean = false): List<StopSuggestion> {
-        if (_stops != null && !force)
-            return _stops!!
-
-        val zones = HashMap<String, String>()
-
-        val cursor = db!!.rawQuery("select stop_name, zone_id from stops", null)
-
-        while (cursor.moveToNext()) {
-            val name = cursor.getString(0)
-            val zone = cursor.getString(1)
-            zones[name] = zone
-        }
-
-        cursor.close()
-
-        _stops = zones.map {
-            /*todo
-            val colour = when (zones[it.key]) {
-                "A" -> "#${getColour(R.color.zoneA, context).toString(16)}"
-                "B" -> "#${getColour(R.color.zoneB, context).toString(16)}"
-                "C" -> "#${getColour(R.color.zoneC, context).toString(16)}"
-                else -> "#000000"
-            }
-            */
-            StopSuggestion(it.key, it.value)
-        }.sorted()
-        return _stops!!
-    }
-
-    fun getLineSuggestions(): List<LineSuggestion> {
-        val routes = ArrayList<LineSuggestion>()
-        val cursor = db!!.rawQuery("select * from routes", null)
-
-        while (cursor.moveToNext()) {
-            val routeId = cursor.getString(0)
-
-            routes.add(LineSuggestion(routeId,
-                    createRouteFromCursorRow(cursor)))
-        }
-
-        return routes.sortedBy { it.name }
-    }
-
-    fun getHeadlinesForStop(stop: String): Map<String, Set<String>> {
-        val headsigns = HashMap<String, HashSet<String>>()
-
-        var cursor = db!!.rawQuery("select stop_id, stop_code from stops where stop_name = ?",
-                arrayOf(stop))
-        val stopIds = ArrayList<String>()
-        val stopCodes = SparseArray<String>()
-        while (cursor.moveToNext()) {
-            cursor.getInt(0).let {
-                stopIds.add(it.toString())
-                stopCodes.put(it, cursor.getString(1))
-            }
-        }
-
-        cursor.close()
-
-        val where = stopIds.joinToString(" or ", "where ") { "stop_id = ?" }
-
-        cursor = db!!.rawQuery("select stop_id, route_id, trip_headsign " +
-                "from stop_times natural join trips " +
-                where, stopIds.toTypedArray())
-
-        while (cursor.moveToNext()) {
-            val stopCode = stopCodes[cursor.getInt(0)]
-            val route = cursor.getString(1)
-            val headsign = cursor.getString(2)
-            if (stopCode !in headsigns)
-                headsigns[stopCode] = HashSet()
-            headsigns[stopCode]!!.add("$route → $headsign")
-        }
-
-        cursor.close()
-
-        return headsigns
-
-        /*
-        AWF03 -> {232 → Os. Rusa}
-        AWF04 -> {232 → Rondo Kaponiera}
-        AWF02 -> {76 → Pl. Bernardyński, 74 → Os. Sobieskiego, 603 → Pl. Bernardyński}
-        AWF01 ->{76 → Os. Dębina, 603 → Łęczyca/Dworcowa}
-        AWF42 -> {29 → Pl. Wiosny Ludów}
-        AWF41 -> {10 → Połabska, 29 → Dębiec, 15 → Budziszyńska, 10 → Dębiec, 15 → Os. Sobieskiego, 12 → Os. Sobieskiego, 6 → Junikowo, 18 → Ogrody, 2 → Ogrody}
-        AWF73 -> {10 → Franowo, 29 → Franowo, 6 → Miłostowo, 5 → Stomil, 18 → Franowo, 15 → Franowo, 12 → Starołęka, 74 → Os. Orła Białego}
-        */
-    }
-
-    fun getHeadlinesForStopCode(stop: String): StopSegment {
-        var cursor = db!!.rawQuery("select stop_id from stops where stop_code = ?",
-                arrayOf(stop))
-        cursor.moveToFirst()
-        val stopId = cursor.getInt(0)
-        cursor.close()
-
-
-        cursor = db!!.rawQuery("select route_id, trip_headsign " +
-                "from stop_times natural join trips where stop_id = ? ",
-                arrayOf(stopId.toString()))
-
-        val plates = HashSet<Plate.ID>()
-
-        while (cursor.moveToNext()) {
-            val route = cursor.getString(0)
-            val headsign = cursor.getString(1)
-            plates.add(Plate.ID(route, stop, headsign))
-        }
-        cursor.close()
-        return StopSegment(stop, plates)
-    }
-
-    fun getStopName(stopCode: String): String {
-        val cursor = db!!.rawQuery("select stop_name from stops where stop_code = ?",
-                arrayOf(stopCode))
-        cursor.moveToNext()
-        val name = cursor.getString(0)
-        cursor.close()
-
-        return name
-    }
-
-    fun getStopId(stopCode: String): String {
-        val cursor = db!!.rawQuery("select stop_id from stops where stop_code = ?",
-                arrayOf(stopCode))
-        cursor.moveToNext()
-        val id = cursor.getString(0)
-        cursor.close()
-
-        return id
-    }
-
-    fun getStopCode(stopId: String): String {
-        val cursor = db!!.rawQuery("select stop_code from stops where stop_id = ?",
-                arrayOf(stopId))
-        cursor.moveToNext()
-        val code = cursor.getString(0)
-        cursor.close()
-
-        return code
-    }
-
-    fun getStopDepartures(stopCode: String): Map<String, List<Departure>> {
-        val stopID = getStopId(stopCode)
-        val map = HashMap<String, ArrayList<Departure>>()
-        val cursor = db!!.rawQuery("select route_id, service_id, departure_time, " +
-                "wheelchair_accessible, stop_sequence, trip_id, trip_headsign, route_desc " +
-                "from stop_times natural join trips natural join routes where stop_id = ?",
-                arrayOf(stopID))
-
-        while (cursor.moveToNext()) {
-            val line = cursor.getString(0)
-            val service = cursor.getInt(1).toString()
-            val mode = calendarToMode(service)
-            val time = parseTime(cursor.getString(2))
-            val lowFloor = cursor.getInt(3) == 1
-            val stopSequence = cursor.getInt(4)
-            val tripId = createTripId(cursor.getString(5))
-            val headsign = cursor.getString(6)
-            val desc = cursor.getString(7)
-
-            val modifications = Route.createModifications(desc)
-
-            val modification = explainModification(tripId, stopSequence, modifications)
-            val departure = Departure(line, mode, time, lowFloor, modification, headsign)
-            if (map[service] == null)
-                map[service] = ArrayList()
-            map[service]!!.add(departure)
-        }
-
-        cursor.close()
-        map.forEach { it.value.sortBy { it.time } }
-
-        return map
-    }
-
-    fun getStopDeparturesBySegments(segments: Set<StopSegment>): Map<String, List<Departure>> {
-        val stopCodes = HashMap<String, Int>()
-        var cursor = db!!.rawQuery("select stop_id, stop_code from stops", emptyArray())
-        while (cursor.moveToNext()) {
-            stopCodes[cursor.getString(1)] = cursor.getInt(0)
-        }
-        cursor.close()
-
-        val wheres = segments.flatMap {
-            it.plates?.map { plate ->
-                "(stop_id = ${stopCodes[plate.stop]} and route_id = '${plate.line}' and trip_headsign = '${plate.headsign}')"
-            } ?: listOf("stop_id = ${stopCodes[it.stop]}")
-        }.joinToString(" or ")
-
-        cursor = db!!.rawQuery("select route_id, service_id, departure_time, " +
-                "wheelchair_accessible, stop_sequence, trip_id, trip_headsign, route_desc " +
-                "from stop_times natural join trips natural join routes where $wheres", null)
-
-        val map = parseDeparturesCursor(cursor)
-        cursor.close()
-        return map
-    }
-
-    private fun parseDeparturesCursor(cursor: Cursor): Map<String, List<Departure>> {
-        val map = HashMap<String, ArrayList<Departure>>()
-
-        while (cursor.moveToNext()) {
-            val line = cursor.getString(0)
-            val service = cursor.getInt(1).toString()
-            val mode = calendarToMode(service)
-            val time = parseTime(cursor.getString(2))
-            val lowFloor = cursor.getInt(3) == 1
-            val stopSequence = cursor.getInt(4)
-            val tripId = createTripId(cursor.getString(5))
-            val headsign = cursor.getString(6)
-            val desc = cursor.getString(7)
-
-            val modifications = Route.createModifications(desc)
-
-            val modification = explainModification(tripId, stopSequence, modifications)
-            val departure = Departure(line, mode, time, lowFloor, modification, headsign)
-            if (map[service] == null)
-                map[service] = ArrayList()
-            map[service]!!.add(departure)
-        }
-
-        map.forEach { it.value.sortBy { it.time } }
-        return map
-    }
-
-
-    private fun parseTime(time: String): Int {
-        val cal = JCalendar.getInstance()
-        val (h, m, s) = time.split(":")
-        cal.set(JCalendar.HOUR_OF_DAY, h.toInt())
-        cal.set(JCalendar.MINUTE, m.toInt())
-        cal.set(JCalendar.SECOND, s.toInt())
-        return cal.secondsAfterMidnight()
-    }
-
-    private fun calendarToMode(serviceId: String): List<Int> {
-        val days = ArrayList<Int>()
-        val cursor = db!!.rawQuery("select * from calendar where service_id = ?",
-                arrayOf(serviceId))
-
-        cursor.moveToNext()
-        (1 until 7).forEach {
-            if (cursor.getInt(it) == 1) days.add(it - 1)
-        }
-
-        cursor.close()
-        return days
-    }
-
-    private fun explainModification(tripId: Trip.ID, stopSequence: Int, routeModifications: Map<String, String>): List<String> { //todo<p:1> "kurs obsługiwany taborem niskopodłogowym" -> ignore
-        val explanations = ArrayList<String>()
-        tripId.modification.forEach {
-            if (it.stopRange != null) {
-                if (stopSequence in it.stopRange)
-                    explanations.add(routeModifications[it.id]!!)
-            } else {
-                explanations.add(routeModifications[it.id]!!)
-            }
-        }
-
-        return explanations
-    }
-
-    private fun createRouteFromCursorRow(cursor: Cursor): Route {
-        val routeId = cursor.getString(0)
-        val agencyId = cursor.getInt(1).toString()
-        val shortName = cursor.getString(2)
-        val longName = cursor.getString(3)
-        val desc = cursor.getString(4)
-        val type = cursor.getInt(5)
-        val colour = cursor.getString(6).toInt(16)
-        val textColour = cursor.getString(7).toInt(16)
-
-        return Route.create(routeId, agencyId, shortName, longName, desc, type, colour, textColour)
-    }
-
-    private fun createTripId(rawId: String): Trip.ID {
-        if (rawId.contains('^')) {
-            var modification = rawId.split("^")[1]
-            val isMain = modification[modification.length - 1] == '+'
-            if (isMain)
-                modification = modification.subSequence(0, modification.length - 1) as String
-            val modifications = HashSet<Trip.ID.Modification>()
-            if (modification != "") {
-                modification.split(",").forEach {
-                    try {
-                        val (id, start, end) = it.split(":")
-                        modifications.add(Trip.ID.Modification(id, IntRange(start.toInt(), end.toInt())))
-                    } catch (e: Exception) {
-                        modifications.add(Trip.ID.Modification(it, null))
-                    }
-                }
-            }
-            return Trip.ID(rawId, rawId.split("^")[0], modifications, isMain)
-        } else
-            return Trip.ID(rawId, rawId, HashSet(), false)
-    }
-
-    @SuppressLint("Recycle")
-    fun isEmpty(): Boolean {
-        if (db == null)
-            return true
-        var result: Boolean
-        var cursor: Cursor? = null
-        try {
-            cursor = db!!.rawQuery("select * from feed_info", null)
-            result = !cursor.moveToNext()
-        } catch (e: Exception) {
-            result = true
-        } finally {
-            cursor?.close()
-        }
-        return result
-    }
-
-    fun getValidSince(): String {
-        val cursor = db!!.rawQuery("select feed_start_date from feed_info", null)
-
-        cursor.moveToNext()
-        val validTill = cursor.getString(0)
-
-        cursor.close()
-        return validTill
-    }
-
-    fun getValidTill(): String {
-        val cursor = db!!.rawQuery("select feed_end_date from feed_info", null)
-
-        cursor.moveToNext()
-        val validTill = cursor.getString(0)
-
-        cursor.close()
-        return validTill
-    }
-
-    fun getServiceForToday(): String? {
-        val today = JCalendar.getInstance()
-        return getServiceFor(today)
-    }
-
-    fun getServiceForTomorrow(): String? {
-        val tomorrow = JCalendar.getInstance()
-        tomorrow.add(JCalendar.DAY_OF_MONTH, 1)
-        return getServiceFor(tomorrow)
-    }
-
-    private fun getServiceFor(day: JCalendar): String? {
-        val dayColumn = arrayOf("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday")[((day.get(JCalendar.DAY_OF_WEEK) + 5) % 7)]
-        val cursor = db!!.rawQuery("select service_id from calendar where $dayColumn = 1 and start_date < ? and ? < end_date", arrayOf(day.toIsoDate(), day.toIsoDate()))
-
-        cursor.moveToFirst()
-        return try {
-            cursor.getInt(0).let {
-                cursor.close()
-                it.toString()
-            }
-        } catch (e: CursorIndexOutOfBoundsException) {
-            cursor.close()
-            null
-        }
-    }
-
-    fun getTripGraphs(id: String): Array<TripGraph> {
-        TODO("Not implemented")
-        /*
-        val graphs = arrayOf(TripGraph(), TripGraph())
-
-        val cursor = db!!.rawQuery("select trip_id, trip_headsign, direction_id, stop_id, " +
-                "stop_sequence, pickup_type, stop_name, zone_id " +
-                "from stop_times natural join trips natural join stops" +
-                "where route_id = ?", arrayOf(id))
-
-        while (cursor.moveToNext()) {
-            val trip = cursor.getString(0)
-            val headsign = cursor.getString(1)
-            val direction = cursor.getInt(2)
-            val stopId = cursor.getInt(3)
-            val sequence = cursor.getInt(4)
-            val pickupType = cursor.getInt(5)
-            val stopName = cursor.getString(6)
-            val zone = cursor.getString(7)
-
-            if (trip.contains('+')) {
-                graphs[direction].mainTrip[stopId] = sequence
-                graphs[direction].headsign = headsign
-            }
-
-            if (graphs[direction].otherTrips[trip] == null)
-                graphs[direction].otherTrips[trip] = HashMap()
-            graphs[direction].otherTrips[trip]?.put(sequence, Stop(stopId, null, stopName, null, null, zone[0], pickupType == 3))
-        }
-
-        cursor.close()
-
-        graphs.forEach {
-            val thisTripGraph = it
-            it.otherTrips.forEach {
-                val tripId = it.key
-                val trip = it.value
-                it.value.keys.sortedBy { it }.forEach {
-                    if (thisTripGraph.tripsMetadata[tripId] == "" || thisTripGraph.tripsMetadata[tripId] == "o")
-                        if (thisTripGraph.mainTrip[trip[it]!!.id] != null) {
-                            val mainLayer = thisTripGraph.mainTrip[trip[it]!!.id]!!
-                            if (it == 0 || thisTripGraph.tripsMetadata[tripId]!![0] == 'o') {
-                                thisTripGraph.tripsMetadata[tripId] = "o|$mainLayer|$it"
-                            } else {
-                                val startingLayer = mainLayer - it + 1
-                                thisTripGraph.tripsMetadata[tripId] = "i|$startingLayer|$it"
-                            }
-                        }
-                }
-            }
-        }
-
-        return graphs*/
-    }
-
-    fun getServiceFirstDay(service: String): Int {
-        val cursor = db!!.rawQuery("select * from calendar where service_id = ?", arrayOf(service))
-        cursor.moveToFirst()
-        var i = 1
-        while ((cursor.getString(i) == "0") and (i < 8)) i++
-        cursor.close()
-        return i
-    }
-
-    fun getServiceDescription(service: String, context: Context): String {
-        val dayNames = SparseArray<String>()
-        dayNames.put(1, context.getString(R.string.Mon))
-        dayNames.put(2, context.getString(R.string.Tue))
-        dayNames.put(3, context.getString(R.string.Wed))
-        dayNames.put(4, context.getString(R.string.Thu))
-        dayNames.put(5, context.getString(R.string.Fri))
-        dayNames.put(6, context.getString(R.string.Sat))
-        dayNames.put(7, context.getString(R.string.Sun))
-
-        val cursor = db!!.rawQuery("select * from calendar where service_id = ?", arrayOf(service))
-        cursor.moveToFirst()
-        val days = SparseBooleanArray()
-        for (i in 1..7) {
-            days.append(i, cursor.getString(i) == "1")
-        }
-        days.append(8, false)
-        val description = ArrayList<String>()
-        var start = 0
-
-        for (i in 1..8) {
-            if (!days[i] and (start > 0)) {
-                when {
-                    i - start == 1 -> description.add(dayNames[start])
-                    i - start == 2 -> description.add("${dayNames[start]}, ${dayNames[start + 1]}")
-                    i - start > 2 -> description.add("${dayNames[start]}–${dayNames[i - 1]}")
-                }
-                start = 0
-            }
-            if (days[i] and (start == 0))
-                start = i
-        }
-
-        val startDate = calendarFromIsoD(cursor.getString(8)).toNiceString(context)
-        val endDate = calendarFromIsoD(cursor.getString(9)).toNiceString(context)
-
-        cursor.close()
-
-        return "${description.joinToString { it }} ($startDate–$endDate)"
-    }
-
-    class TripGraph {
-        var headsign = ""
-        val mainTrip = HashMap<Int, Int>()
-        val otherTrips = HashMap<String, HashMap<Int, Stop>>()
-        val tripsMetadata = HashMap<String, String>()
-    }
-}
-




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/DeparturesAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/adapters/DeparturesAdapter.kt
deleted file mode 100644
index 224ca7fe3e1250a0475ad7323b9e153f1b5ded27..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/DeparturesAdapter.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-package ml.adamsprogs.bimba.models.adapters
-
-import android.app.AlertDialog
-import android.content.Context
-import android.content.DialogInterface
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.core.content.res.ResourcesCompat
-import kotlinx.android.synthetic.main.row_departure.view.*
-import ml.adamsprogs.bimba.R
-import ml.adamsprogs.bimba.models.Departure
-
-class DeparturesAdapter(val context: Context, var departures: List<Departure>?, var relativeTime: Boolean) :
-        androidx.recyclerview.widget.RecyclerView.Adapter<DeparturesAdapter.ViewHolder>() {
-
-    override fun getItemCount(): Int {
-        if (departures == null || departures!!.isEmpty())
-            return 1
-        return departures!!.size
-    }
-
-    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
-        holder.floorIcon.visibility = View.GONE
-        holder.infoIcon.visibility = View.GONE
-
-        if (departures == null) {
-            return
-        }
-
-        val line = holder.lineTextView
-        val time = holder.timeTextView
-        val direction = holder.directionTextView
-        if (departures!!.isEmpty()) {
-            time.text = context.getString(R.string.no_departures)
-            return
-        }
-        val departure = departures!![position]
-
-        val timeString = departure.timeTillText(context, relativeTime)
-
-        line.text = departure.lineText
-        time.text = timeString
-        direction.text = context.getString(R.string.departure_to, departure.headsign)
-        val icon = holder.typeIcon
-        if (departure.vm || departure.onStop)
-            icon.setImageDrawable(ResourcesCompat.getDrawable(context.resources, R.drawable.ic_departure_vm, context.theme))
-        else
-            icon.setImageDrawable(ResourcesCompat.getDrawable(context.resources, R.drawable.ic_departure_timetable, context.theme))
-
-        if (departure.lowFloor)
-            holder.floorIcon.visibility = View.VISIBLE
-        if (departure.isModified)
-            holder.infoIcon.visibility = View.VISIBLE
-        if (departure.ticketMachine == Departure.TICKET_MACHINE_AUTOMAT) {
-            holder.ticketMachineIcon.setImageDrawable(ResourcesCompat.getDrawable(context.resources, R.drawable.ic_ticket_machine, context.theme))
-            holder.ticketMachineIcon.visibility = View.VISIBLE
-        }
-        if (departure.ticketMachine == Departure.TICKET_MACHINE_DRIVER) {
-            holder.ticketMachineIcon.setImageDrawable(ResourcesCompat.getDrawable(context.resources, R.drawable.ic_ticket, context.theme))
-            holder.ticketMachineIcon.visibility = View.VISIBLE
-        }
-        holder.root.setOnClickListener {
-            AlertDialog.Builder(context)
-                    .setPositiveButton(context.getText(android.R.string.ok)
-                    ) { dialog: DialogInterface, _: Int -> dialog.cancel() }
-                    .setCancelable(true)
-                    .setMessage(departure.timeAtMessage(context))
-                    .create().show()
-        }
-    }
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
-        val context = parent.context
-        val inflater = LayoutInflater.from(context)
-
-        val rowView = inflater.inflate(R.layout.row_departure, parent, false)
-        return ViewHolder(rowView)
-    }
-
-    inner class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) {
-        val root = itemView.findViewById<View>(R.id.departureRow)!!
-        val lineTextView: TextView = itemView.findViewById(R.id.lineNumber)
-        val timeTextView: TextView = itemView.findViewById(R.id.departureTime)
-        val directionTextView: TextView = itemView.findViewById(R.id.departureDirection)
-        val typeIcon: ImageView = itemView.findViewById(R.id.departureTypeIcon)
-        val infoIcon: ImageView = itemView.findViewById(R.id.departureInfoIcon)
-        val floorIcon: ImageView = itemView.findViewById(R.id.departureFloorIcon)
-        val ticketMachineIcon: ImageView = itemView.findViewById(R.id.ticketMachineIcon)
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/FavouriteEditRowAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/adapters/FavouriteEditRowAdapter.kt
deleted file mode 100644
index c4e638efb519ce0f8f0d74a1f83adf615a1fb30f..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/FavouriteEditRowAdapter.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-package ml.adamsprogs.bimba.models.adapters
-
-import android.view.*
-import android.widget.*
-import kotlinx.coroutines.*
-import kotlinx.coroutines.android.Main
-import ml.adamsprogs.bimba.*
-import ml.adamsprogs.bimba.collections.FavouriteStorage
-import ml.adamsprogs.bimba.models.*
-
-
-class FavouriteEditRowAdapter(private var favourite: Favourite, private val loadingView: View, private val listView: View) :
-        androidx.recyclerview.widget.RecyclerView.Adapter<FavouriteEditRowAdapter.ViewHolder>() {
-
-    private val segments = HashMap<String, StopSegment>()
-    private val providerProxy = ProviderProxy()
-    private val favourites = FavouriteStorage.getFavouriteStorage()
-    private val platesList = ArrayList<Plate.ID>()
-    private val namesList = HashMap<Plate.ID, String>()
-
-    init {
-        GlobalScope.launch {
-            favourite.segments.forEach {
-                if (it.plates == null) {
-                    (providerProxy.fillStopSegment(it) ?: it).let { segment ->
-                        segments[segment.stop] = segment
-                        it.plates = segment.plates
-                    }
-                } else {
-                    segments[it.stop] = it
-                }
-            }
-            favourites[favourite.name] = favourite
-
-            segments.flatMap {
-                it.value.plates ?: emptyList<Plate.ID>()
-            }.sortedBy { "${it.line}${it.stop}" }.forEach {
-                platesList.add(it)
-                namesList[it] = providerProxy.getStopName(it.stop).let { name ->
-                    "${name ?: ""} (${it.stop}):\n${it.line} → ${it.headsign}"
-                }
-            }
-            launch(Dispatchers.Main) {
-                loadingView.visibility = View.GONE
-                listView.visibility = View.VISIBLE
-                this@FavouriteEditRowAdapter.notifyDataSetChanged()
-            }
-        }
-    }
-
-
-    override fun getItemCount(): Int = platesList.size
-
-    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
-        GlobalScope.launch {
-            val id = platesList[position]
-            val favouriteElement = namesList[id]
-
-            holder.rowTextView.text = favouriteElement
-            holder.deleteButton.setOnClickListener {
-                favourites.delete(favourite.name, id)
-                favourite = favourites.favourites[favourite.name]!!
-                notifyItemRemoved(platesList.indexOf(id))
-                platesList.remove(id)
-                namesList.remove(id)
-            }
-        }
-    }
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
-        val context = parent.context
-        val inflater = LayoutInflater.from(context)
-
-        val rowView = inflater.inflate(R.layout.row_favourite_edit, parent, false)
-        return ViewHolder(rowView)
-    }
-
-    inner class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) {
-        val rowTextView: TextView = itemView.findViewById(R.id.favourite_edit_row)
-        val deleteButton: ImageView = itemView.findViewById(R.id.favourite_edit_delete)
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/FavouritesAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/adapters/FavouritesAdapter.kt
deleted file mode 100644
index 1f1a1a174e5e1b149d16121b6347234d207b8a85..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/FavouritesAdapter.kt
+++ /dev/null
@@ -1,159 +0,0 @@
-package ml.adamsprogs.bimba.models.adapters
-
-import android.content.Context
-import android.util.SparseBooleanArray
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.appcompat.widget.PopupMenu
-import androidx.core.content.res.ResourcesCompat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.android.Main
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import ml.adamsprogs.bimba.R
-import ml.adamsprogs.bimba.collections.FavouriteStorage
-import ml.adamsprogs.bimba.models.Departure
-import ml.adamsprogs.bimba.models.Favourite
-import java.util.*
-
-
-class FavouritesAdapter(private val appContext: Context, var favourites: FavouriteStorage,
-                        private val onMenuItemClickListener: OnMenuItemClickListener,
-                        private val onClickListener: ViewHolder.OnClickListener) :
-        androidx.recyclerview.widget.RecyclerView.Adapter<FavouritesAdapter.ViewHolder>() {
-
-    private val selectedItems = SparseBooleanArray()
-
-    private fun isSelected(position: Int) = getSelectedItems().contains(position)
-
-    fun toggleSelection(position: Int) {
-        if (selectedItems.get(position, false)) {
-            selectedItems.delete(position)
-        } else {
-            selectedItems.put(position, true)
-        }
-        notifyItemChanged(position)
-    }
-
-    fun clearSelection() {
-        selectedItems.clear()
-        notifyDataSetChanged()
-    }
-
-    fun getSelectedItemCount() = selectedItems.size()
-
-    fun getSelectedItems(): List<Int> {
-        val items = ArrayList<Int>(selectedItems.size())
-        (0 until selectedItems.size()).mapTo(items) { selectedItems.keyAt(it) }
-        return items
-    }
-
-    override fun getItemCount() = favourites.size
-
-    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
-        GlobalScope.launch(Dispatchers.Main) /*Main on all?*/ {
-            val favourite = favourites[position]!!
-            holder.nameTextView.text = favourite.name
-
-            holder.selectedOverlay.visibility = if (isSelected(position)) View.VISIBLE else View.INVISIBLE
-            holder.moreButton.setOnClickListener { it ->
-                val popup = PopupMenu(appContext, it)
-                val inflater = popup.menuInflater
-                popup.setOnMenuItemClickListener {
-                    when (it.itemId) {
-                        R.id.favourite_edit -> onMenuItemClickListener.edit(favourite.name)
-                        R.id.favourite_delete -> onMenuItemClickListener.delete(favourite.name)
-                        else -> false
-                    }
-                }
-                inflater.inflate(R.menu.favourite_actions, popup.menu)
-                popup.show()
-            }
-
-            val nextDeparture = withContext(Dispatchers.Default) {
-                favourite.nextDeparture()
-            }
-
-            val nextDepartureText: String
-            val nextDepartureLineText: String
-            if (nextDeparture != null) {
-                nextDepartureLineText = appContext.getString(R.string.departure_to_line, nextDeparture.line, nextDeparture.headsign)
-                nextDepartureText = nextDeparture.timeTillText(appContext)
-            } else {
-                nextDepartureText = appContext.getString(R.string.no_next_departure)
-                nextDepartureLineText = ""
-            }
-            holder.timeTextView.text = nextDepartureText
-            holder.lineTextView.text = nextDepartureLineText
-            if (nextDeparture != null) {
-                if (nextDeparture.vm || nextDeparture.onStop)
-                    holder.typeIcon.setImageDrawable(ResourcesCompat.getDrawable(appContext.resources, R.drawable.ic_departure_vm, appContext.theme))
-                else
-                    holder.typeIcon.setImageDrawable(ResourcesCompat.getDrawable(appContext.resources, R.drawable.ic_departure_timetable, appContext.theme))
-                if (nextDeparture.lowFloor)
-                    holder.floorIcon.visibility = View.VISIBLE
-                if (nextDeparture.ticketMachine != Departure.TICKET_MACHINE_NONE) {
-                    holder.ticketIcon.visibility = View.VISIBLE
-                    if (nextDeparture.ticketMachine == Departure.TICKET_MACHINE_DRIVER)
-                        holder.ticketIcon.setImageDrawable(ResourcesCompat.getDrawable(appContext.resources, R.drawable.ic_ticket, appContext.theme))
-                    if (nextDeparture.ticketMachine == Departure.TICKET_MACHINE_AUTOMAT)
-                        holder.ticketIcon.setImageDrawable(ResourcesCompat.getDrawable(appContext.resources, R.drawable.ic_ticket_machine, appContext.theme))
-                }
-            }
-        }
-    }
-
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
-        val context = parent.context
-        val inflater = LayoutInflater.from(context)
-
-        val rowView = inflater.inflate(R.layout.row_favourite, parent, false)
-        return ViewHolder(rowView, onClickListener)
-    }
-
-    fun indexOf(name: String): Int {
-        return favourites.indexOf(name)
-    }
-
-    operator fun get(index: String): Favourite? {
-        return favourites[index]
-    }
-
-    class ViewHolder(itemView: View, private val listener: OnClickListener) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView), View.OnClickListener, View.OnLongClickListener {
-        override fun onLongClick(v: View?): Boolean {
-            return listener.onItemLongClicked(adapterPosition)
-        }
-
-        override fun onClick(v: View?) {
-            listener.onItemClicked(adapterPosition)
-        }
-
-        val selectedOverlay: View = itemView.findViewById(R.id.selected_overlay)
-        val nameTextView: TextView = itemView.findViewById(R.id.favourite_name)
-        val timeTextView: TextView = itemView.findViewById(R.id.favourite_time)
-        val lineTextView: TextView = itemView.findViewById(R.id.favourite_line)
-        val moreButton: ImageView = itemView.findViewById(R.id.favourite_more_button)
-        val typeIcon: ImageView = itemView.findViewById(R.id.departureTypeIcon)
-        val floorIcon: ImageView = itemView.findViewById(R.id.departureFloorIcon)
-        val ticketIcon: ImageView = itemView.findViewById(R.id.ticketMachineIcon)
-
-        init {
-            itemView.setOnClickListener(this)
-            itemView.setOnLongClickListener(this)
-        }
-
-        interface OnClickListener {
-            fun onItemClicked(position: Int)
-            fun onItemLongClicked(position: Int): Boolean
-        }
-    }
-
-    interface OnMenuItemClickListener {
-        fun edit(name: String): Boolean
-        fun delete(name: String): Boolean
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/ServiceAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/adapters/ServiceAdapter.kt
deleted file mode 100644
index 014cd4a7cf014ff56ec0ca3e54a77c90a769f805..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/ServiceAdapter.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package ml.adamsprogs.bimba.models.adapters
-
-import android.annotation.SuppressLint
-import android.view.View
-import android.view.ViewGroup
-import android.widget.TextView
-import android.view.LayoutInflater
-import ml.adamsprogs.bimba.R
-import android.app.Activity
-import android.widget.ArrayAdapter
-import ml.adamsprogs.bimba.ProviderProxy
-
-
-class ServiceAdapter(context: Activity, resourceId: Int, list: List<RowItem>) : ArrayAdapter<ServiceAdapter.RowItem>(context, resourceId, list) {
-
-    private val inflater: LayoutInflater = context.layoutInflater
-
-    @SuppressLint("ViewHolder", "InflateParams")
-    override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
-        val rowItem: RowItem = getItem(position)
-        val rowView = inflater.inflate(R.layout.toolbar_spinner_item, null, true)
-        rowView.findViewById<TextView>(R.id.text).text = rowItem.description
-
-        return rowView
-    }
-
-    @SuppressLint("InflateParams")
-    override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup?): View {
-        val rowItem: RowItem = getItem(position)
-        val rowView = inflater.inflate(R.layout.toolbar_spinner_item, null, true)
-        rowView.findViewById<TextView>(R.id.text).text = rowItem.description
-
-        return rowView
-
-    }
-
-    data class RowItem(val service: String, val description: String) : Comparable<RowItem> {
-        override fun compareTo(other: RowItem): Int {
-            val proxy = ProviderProxy()
-            return proxy.getServiceFirstDay(service).compareTo(proxy.getServiceFirstDay(other.service))
-        }
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/SuggestionsAdapter.kt b/app/src/main/java/ml/adamsprogs/bimba/models/adapters/SuggestionsAdapter.kt
deleted file mode 100644
index 6408a4506cde6c5d2fdf7a84a6024a78c5699881..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/adapters/SuggestionsAdapter.kt
+++ /dev/null
@@ -1,96 +0,0 @@
-package ml.adamsprogs.bimba.models.adapters
-
-import android.content.Context
-import android.graphics.PorterDuff
-import android.os.Build
-import android.text.Html
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.ImageView
-import android.widget.TextView
-import androidx.core.content.ContextCompat.getColor
-import ml.adamsprogs.bimba.R
-import ml.adamsprogs.bimba.getDrawable
-import ml.adamsprogs.bimba.models.suggestions.EmptySuggestion
-import ml.adamsprogs.bimba.models.suggestions.GtfsSuggestion
-import ml.adamsprogs.bimba.models.suggestions.LineSuggestion
-import ml.adamsprogs.bimba.models.suggestions.StopSuggestion
-import com.mancj.materialsearchbar.adapter.SuggestionsAdapter as SearchBarSuggestionsAdapter
-
-class SuggestionsAdapter(inflater: LayoutInflater, private val onSuggestionClickListener: OnSuggestionClickListener, private val context: Context) :
-        SearchBarSuggestionsAdapter<GtfsSuggestion, SuggestionsAdapter.ViewHolder>(inflater) {
-    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
-        val rowView = layoutInflater.inflate(R.layout.row_suggestion, parent, false)
-        return ViewHolder(rowView)
-    }
-
-    override fun getSingleViewHeight(): Int = 48
-
-    override fun onBindSuggestionHolder(suggestion: GtfsSuggestion, holder: ViewHolder?, pos: Int) {
-        holder!!.root.setOnClickListener {
-            onSuggestionClickListener.onSuggestionClickListener(suggestion)
-        }
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            holder.text.text = Html.fromHtml(suggestion.getBody(context), Html.FROM_HTML_MODE_LEGACY)
-        } else {
-            @Suppress("DEPRECATION")
-            holder.text.text = Html.fromHtml(suggestion.getBody(context))
-        }
-
-        holder.text.setTextColor(getColor(context, R.color.textDark))
-
-        val icon = getDrawable(suggestion.getIcon(), context)
-        icon.mutate()
-        icon.colorFilter = null
-        if (suggestion is StopSuggestion)
-            when (suggestion.zone) {
-                "A" -> icon.setColorFilter(getColor(context, R.color.zoneA), PorterDuff.Mode.SRC_IN)
-                "B" -> icon.setColorFilter(getColor(context, R.color.zoneB), PorterDuff.Mode.SRC_IN)
-                "C" -> icon.setColorFilter(getColor(context, R.color.zoneC), PorterDuff.Mode.SRC_IN)
-                else -> icon.setColorFilter(getColor(context, R.color.textDark), PorterDuff.Mode.SRC_IN)
-            }
-        else if (suggestion is LineSuggestion) {
-            icon.setColorFilter(suggestion.getColour(), PorterDuff.Mode.SRC_IN)
-            holder.icon.setBackgroundColor(suggestion.getBgColour())
-        }
-        holder.icon.setImageDrawable(icon)
-
-    }
-
-    fun updateSuggestions(newSuggestions: List<GtfsSuggestion>, query: String) {
-        suggestions = sort(newSuggestions, query).take(6)
-        suggestions_clone = suggestions
-        notifyDataSetChanged()
-    }
-
-    private fun sort(suggestions: List<GtfsSuggestion>, query: String): List<GtfsSuggestion> {
-        val r = Regex(query, RegexOption.IGNORE_CASE)
-        return suggestions.sortedBy {
-            (r.find(it.name)?.range?.start?.toString()?.padStart(128, '0') ?: "")+it.name
-        }
-    }
-
-    operator fun contains(suggestion: GtfsSuggestion): Boolean {
-        return suggestion in suggestions //|| suggestion in suggestions_clone
-    }
-
-    inner class ViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView) {
-        val root: View = itemView.findViewById(R.id.row_suggestion)
-        val icon: ImageView = itemView.findViewById(R.id.suggestion_row_image)
-        val text: TextView = itemView.findViewById(R.id.suggestion_row_text)
-    }
-
-    interface OnSuggestionClickListener {
-        fun onSuggestionClickListener(suggestion: GtfsSuggestion)
-    }
-
-    fun equals(other: List<GtfsSuggestion>): Boolean {
-        if ((suggestions.containsAll(other) and other.containsAll(suggestions)))
-            return true
-        if (other.isEmpty())
-            if ((suggestions.isEmpty()) or (suggestions[0] is EmptySuggestion))
-                return true
-        return false
-    }
-}




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Calendar.kt b/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Calendar.kt
deleted file mode 100644
index aad6742b778ffe1dda196494e374adb46cc4550d..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Calendar.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package ml.adamsprogs.bimba.models.gtfs
-
-data class Calendar(val monday: Boolean, val tuesday: Boolean, val wednesday: Boolean, val thursday: Boolean,
-                    val friday: Boolean, val saturday: Boolean, val sunday: Boolean)
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Route.kt b/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Route.kt
deleted file mode 100644
index c3021d8a3c0991b4cee3150a5a2f9751a2ea8764..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Route.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package ml.adamsprogs.bimba.models.gtfs
-
-import android.os.Parcel
-import android.os.Parcelable
-
-
-data class Route(val id: String, val agency: String, val shortName: String,
-                 val longName: String, val description: String, val type: Int, val colour: Int,
-                 val textColour: Int, val modifications: Map<String, String>) : Parcelable {
-    companion object CREATOR : Parcelable.Creator<Route> {
-        const val TYPE_BUS = 3
-        const val TYPE_TRAM = 0
-
-        override fun createFromParcel(parcel: Parcel): Route {
-            return Route(parcel)
-        }
-
-        override fun newArray(size: Int): Array<Route?> {
-            return arrayOfNulls(size)
-        }
-
-        fun create(id: String, agency: String, shortName: String, longName: String,
-                                desc: String, type: Int, colour: Int, textColour: Int): Route {
-            return if (desc.contains("|")) {
-                val (to, from) = desc.split("|")
-                val fromSplit = from.split("^")
-                val toSplit = to.split("^")
-                val description = "${toSplit[0]}|${fromSplit[0]}"
-                val modifications = createModifications(desc)
-                Route(id, agency, shortName, longName, description,
-                        type, colour, textColour, modifications)
-            } else {
-                val toSplit = desc.split("^")
-                val description = toSplit[0]
-                val modifications = createModifications(desc)
-                Route(id, agency, shortName, longName, description,
-                        type, colour, textColour, modifications)
-            }
-        }
-
-        fun createModifications(desc: String): Map<String, String> {
-            val (to, from) = if(desc.contains('|')) desc.split("|") else listOf(desc, null)
-            val toSplit = to!!.split("^")
-            val fromSplit = from?.split("^")
-            val modifications = HashMap<String, String>()
-            toSplit.slice(1 until toSplit.size).forEach {
-                val (k, v) = it.split(" - ")
-                modifications[k] = v
-            }
-            fromSplit?.slice(1 until fromSplit.size)?.forEach {
-                val (k,v) = it.split(" - ")
-                modifications[k] = v
-            }
-            return modifications
-        }
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    constructor(parcel: Parcel) : this(
-            parcel.readString(),
-            parcel.readString(),
-            parcel.readString(),
-            parcel.readString(),
-            parcel.readString(),
-            parcel.readInt(),
-            parcel.readInt(),
-            parcel.readInt(),
-            parcel.readSerializable() as HashMap<String, String>)
-
-    override fun writeToParcel(parcel: Parcel, flags: Int) {
-        parcel.writeString(id)
-        parcel.writeString(agency)
-        parcel.writeString(shortName)
-        parcel.writeString(longName)
-        parcel.writeString(description)
-        parcel.writeInt(type)
-        parcel.writeInt(colour)
-        parcel.writeInt(textColour)
-        parcel.writeSerializable(modifications as HashMap)
-    }
-
-    override fun describeContents(): Int {
-        return Parcelable.CONTENTS_FILE_DESCRIPTOR
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Stop.kt b/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Stop.kt
deleted file mode 100644
index a98a2517e0fe34ae0e559e46c9d398ae51605de1..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Stop.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package ml.adamsprogs.bimba.models.gtfs
-
-data class Stop(val id: Int, val code: String?, val name: String, val latitude: Float?, val Longitude: Float?, val zone: Char, val onDemand: Boolean = false) {
-    override fun toString() = "$id: $name ($zone)"
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Trip.kt b/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Trip.kt
deleted file mode 100644
index db797a31de4ba22531ebe14266ed73ed38e72254..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/gtfs/Trip.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package ml.adamsprogs.bimba.models.gtfs
-
-data class Trip(val routeId: String, val serviceId: String, val id: ID,
-                val headsign: String, val direction: Int, val shapeId: String,
-                val wheelchairAccessible: Boolean) {
-    data class ID(val rawId:String, val id: String, val modification: Set<Modification>, val isMain: Boolean) {
-        data class Modification(val id: String, val stopRange: IntRange?)
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/EmptySuggestion.kt b/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/EmptySuggestion.kt
deleted file mode 100644
index 6d1ae4255e29b82a47db5d82c5261e273dad8f82..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/EmptySuggestion.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package ml.adamsprogs.bimba.models.suggestions
-
-import android.content.Context
-import ml.adamsprogs.bimba.R
-
-class EmptySuggestion : GtfsSuggestion("Empty") {
-    override fun equals(other: Any?): Boolean {
-        return other != null && other is EmptySuggestion
-    }
-
-    override fun getIcon(): Int {
-        return R.drawable.ic_error_outline
-    }
-
-    override fun getColour(): Int {
-        return 0xffffff
-    }
-
-    override fun getBgColour(): Int {
-        return 0x000000
-    }
-
-    override fun getBody(context: Context): String {
-        return context.getString(R.string.nothing_found)
-    }
-
-    override fun compareTo(other: GtfsSuggestion): Int {
-        return if (other is EmptySuggestion)
-            0
-        else
-            -1
-    }
-
-    override fun hashCode(): Int {
-        return name.hashCode()
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/GtfsSuggestion.kt b/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/GtfsSuggestion.kt
deleted file mode 100644
index 06338fb9e936e9f0580b142ef5995ed419508c5a..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/GtfsSuggestion.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package ml.adamsprogs.bimba.models.suggestions
-
-import android.content.Context
-
-abstract class GtfsSuggestion(val name: String) : Comparable<GtfsSuggestion> {
-    abstract fun getIcon(): Int
-
-    abstract fun getColour(): Int
-
-    abstract fun getBgColour(): Int
-
-    abstract fun getBody(context: Context): String
-
-    abstract override fun equals(other: Any?): Boolean
-
-    abstract override fun hashCode(): Int
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/LineSuggestion.kt b/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/LineSuggestion.kt
deleted file mode 100644
index b6b11e162b21b5beb4d5b85e276fdcc156e4f408..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/LineSuggestion.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-package ml.adamsprogs.bimba.models.suggestions
-
-import android.content.Context
-import ml.adamsprogs.bimba.R
-import ml.adamsprogs.bimba.models.gtfs.Route
-
-class LineSuggestion(name: String, private val route: Route) : GtfsSuggestion(name) {
-    override fun getIcon(): Int {
-        return when (route.type) {
-            Route.TYPE_BUS -> R.drawable.ic_bus
-            Route.TYPE_TRAM -> R.drawable.ic_tram
-            else -> R.drawable.ic_vehicle
-        }
-    }
-
-    override fun getBody(context: Context): String {
-        return name
-    }
-
-    override fun getColour(): Int {
-        return route.colour
-    }
-
-    override fun getBgColour(): Int {
-        return route.textColour
-    }
-
-    override fun compareTo(other: GtfsSuggestion): Int {
-        return if (other is LineSuggestion)
-            name.padStart(3, '0').compareTo(other.name.padStart(3, '0'))
-        else
-            name.compareTo(other.name)
-    }
-
-    override fun equals(other: Any?): Boolean {
-        if (other == null || other !is GtfsSuggestion)
-            return false
-        return if (other is LineSuggestion)
-            name.padStart(3, '0') == other.name.padStart(3, '0')
-        else
-            name == other.name
-    }
-
-    override fun hashCode(): Int {
-        var result = route.hashCode()
-        result = 31 * result + name.hashCode()
-        return result
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/StopSuggestion.kt b/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/StopSuggestion.kt
deleted file mode 100644
index 88c4f19b68dc32e2d87aee7437e21870d9fc7093..0000000000000000000000000000000000000000
--- a/app/src/main/java/ml/adamsprogs/bimba/models/suggestions/StopSuggestion.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package ml.adamsprogs.bimba.models.suggestions
-
-import android.content.Context
-import ml.adamsprogs.bimba.R
-
-class StopSuggestion(name: String, val zone: String) : GtfsSuggestion(name) {
-
-    override fun getBody(context: Context): String {
-        return name
-    }
-
-    override fun getIcon(): Int {
-        return R.drawable.ic_stop
-    }
-
-    override fun getColour(): Int {
-        return 0xffffff
-    }
-
-    override fun getBgColour(): Int {
-        return 0x000000
-    }
-
-    override fun compareTo(other: GtfsSuggestion): Int {
-        return name.compareTo(other.name)
-    }
-
-    override fun equals(other: Any?): Boolean {
-        if (other == null || other !is GtfsSuggestion)
-            return false
-        return name == other.name
-    }
-
-    override fun hashCode(): Int {
-        var result = zone.hashCode()
-        result = 31 * result + name.hashCode()
-        return result
-    }
-}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt b/app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt
new file mode 100644
index 0000000000000000000000000000000000000000..34a162856469ff0e7d78c1277a3e48375f4e35e4
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/Bimba.kt
@@ -0,0 +1,22 @@
+package xyz.apiote.bimba.czwek
+
+import org.osmdroid.config.Configuration
+import java.io.File
+
+// todo [3.1] style
+
+class Bimba : android.app.Application() {
+	override fun onCreate() {
+		super.onCreate()
+		Configuration.getInstance()
+			.let { config ->
+				config.load(
+					applicationContext,
+					applicationContext.getSharedPreferences("shp", MODE_PRIVATE)
+				)
+				config.osmdroidBasePath = File(applicationContext.cacheDir.absolutePath, "osmdroid")
+
+				config.osmdroidTileCache = File(config.osmdroidBasePath.absolutePath, "tile")
+			}
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b0ead8725723cdf1579ad1ff8cb9148ffeef32ab
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Api.kt
@@ -0,0 +1,155 @@
+package xyz.apiote.bimba.czwek.api
+
+import android.content.Context
+import android.content.Context.MODE_PRIVATE
+import android.net.ConnectivityManager
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
+import xyz.apiote.bimba.czwek.R
+import java.io.IOException
+import java.io.InputStream
+import java.net.HttpURLConnection
+import java.net.MalformedURLException
+import java.net.URL
+import java.net.URLEncoder
+
+// todo [3.1] constants
+
+// todo [3.1] create Repository between models and api/fs
+// todo [3.1] in Repository check if responses are BARE or HTML
+
+data class Server(val host: String, val token: String, val feeds: String, val apiPath: String) {
+	companion object {
+		fun get(context: Context): Server {
+			val preferences = context.getSharedPreferences("shp", MODE_PRIVATE)
+			val host = preferences.getString("host", "bimba.apiote.xyz")!!
+			return Server(
+				host, preferences.getString("token", "")!!,
+				preferences.getString("${host}_feeds", "")!!,
+				preferences.getString("apiPath", "")!!,
+			)
+		}
+	}
+}
+
+data class Result(val stream: InputStream?, val error: Error?)
+
+data class Error(val statusCode: Int, val stringResource: Int, val imageResource: Int)
+
+suspend fun getBimba(cm: ConnectivityManager, server: Server): Result {
+	return try {
+		rawRequest(
+			URL("${hostWithScheme(server.host)}/.well-known/traffic-api"), server, cm, emptyArray()
+		)
+	} catch (e: MalformedURLException) {
+		Result(null, Error(0, R.string.error_url, R.drawable.error_url))
+	}
+}
+
+suspend fun getFeeds(cm: ConnectivityManager, server: Server): Result {
+	return try {
+		rawRequest(
+			URL("${server.apiPath}/"), server, cm, arrayOf(1u)
+		)
+	} catch (_: MalformedURLException) {
+		Result(null, Error(0, R.string.error_url, R.drawable.error_url))
+	}
+}
+
+suspend fun queryQueryables(
+	cm: ConnectivityManager, server: Server, query: String, limit: Int? = null
+): Result {
+	val params = mutableMapOf("q" to query)
+	if (limit != null) {
+		params["limit"] = limit.toString()
+	}
+	return request(server, "queryables", params, cm, arrayOf(1u))
+}
+
+suspend fun locateQueryables(cm: ConnectivityManager, server: Server, near: PositionV1): Result {
+	return request(server, "queryables", mapOf("near" to near.toString()), cm, arrayOf(1u))
+}
+
+suspend fun getLocatablesIn(
+	cm: ConnectivityManager, server: Server, bl: PositionV1, tr: PositionV1
+): Result {
+	return request(
+		server, "locatables", mapOf("lb" to bl.toString(), "rt" to tr.toString()), cm, arrayOf(1u)
+	)
+}
+
+suspend fun getDepartures(
+	cm: ConnectivityManager, server: Server, stop: String, line: String? = null
+): Result {
+	val params = mutableMapOf("code" to stop)
+	if (line != null) {
+		params["line"] = line
+	}
+	return request(server, "departures", params, cm, arrayOf(1u))
+}
+
+suspend fun rawRequest(
+	url: URL, server: Server, cm: ConnectivityManager, responseVersion: Array<UInt>
+): Result {
+	@Suppress("DEPRECATION")  // fixme later(API_29, API_23) https://developer.android.com/reference/android/net/ConnectivityManager#getActiveNetwork()
+	if (cm.activeNetworkInfo == null) {
+		return Result(null, Error(0, R.string.error_offline, R.drawable.error_net))
+	}
+	return withContext(Dispatchers.IO) {
+		val c = (url.openConnection() as HttpURLConnection).apply {
+			setRequestProperty("X-Bimba-Token", server.token)
+			responseVersion.forEach { addRequestProperty("Accept", "application/$it+bare") }
+		}
+		try {
+			if (c.responseCode == 200) {
+				Result(c.inputStream, null)
+			} else {
+				val (string, image) = when (c.responseCode) {
+					400 -> Pair(R.string.error_400, R.drawable.error_app)
+					401 -> Pair(R.string.error_401, R.drawable.error_sec)
+					403 -> Pair(R.string.error_403, R.drawable.error_sec)
+					404 -> Pair(R.string.error_404, R.drawable.error_search)
+					429 -> Pair(R.string.error_429, R.drawable.error_limit)
+					500 -> Pair(R.string.error_50x, R.drawable.error_server)
+					502 -> Pair(R.string.error_50x, R.drawable.error_server)
+					503 -> Pair(R.string.error_50x, R.drawable.error_server)
+					504 -> Pair(R.string.error_50x, R.drawable.error_server)
+					else -> Pair(R.string.error_unknown, R.drawable.error_other)
+				}
+				Result(c.errorStream, Error(c.responseCode, string, image))
+			}
+		} catch (e: IOException) {
+			Result(null, Error(0, R.string.error_connecting, R.drawable.error_server))
+		}
+	}
+}
+
+suspend fun request(
+	server: Server,
+	resource: String,
+	params: Map<String, String>,
+	cm: ConnectivityManager,
+	responseVersion: Array<UInt>
+): Result {
+	return withContext(Dispatchers.IO) {
+		val url = URL( // todo [3.1] scheme, host, path, constructed query
+			"${server.apiPath}/${server.feeds}/$resource${
+				params.map {
+					"${it.key}=${
+						URLEncoder.encode(
+							it.value, "utf-8"
+						)
+					}"
+				}.joinToString("&", "?")
+			}"
+		)
+		rawRequest(url, server, cm, responseVersion)
+	}
+}
+
+fun hostWithScheme(host: String): String =
+	if (host.startsWith("http://") or host.startsWith("https://")) {
+		host
+	} else {
+		"https://$host"
+	}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Responses.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Responses.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e8dd16c9f3c4b61219bd49d49bee82ed08978bd4
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Responses.kt
@@ -0,0 +1,272 @@
+package xyz.apiote.bimba.czwek.api
+
+import xyz.apiote.fruchtfleisch.Reader
+import java.io.InputStream
+
+class UnknownResponseVersion(val resource: String, val version: ULong) : Exception()
+
+interface DeparturesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): DeparturesResponse {
+			val reader = Reader(stream)
+			return when (val v = reader.readUInt().toULong()) {
+				0UL -> {
+					DeparturesResponseDev.unmarshal(stream)
+				}
+				1UL -> {
+					DeparturesResponseV1.unmarshal(stream)
+				}
+				else -> {
+					throw UnknownResponseVersion("Departures", v)
+				}
+			}
+		}
+	}
+}
+
+data class DeparturesResponseV1(
+	val alerts: List<AlertV1>,
+	val departures: List<DepartureV1>,
+	val stop: StopV1
+) : DeparturesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): DeparturesResponseV1 {
+			val alerts = mutableListOf<AlertV1>()
+			val departures = mutableListOf<DepartureV1>()
+
+			val reader = Reader(stream)
+			val alertsNum = reader.readUInt().toULong()
+			for (i in 0UL until alertsNum) {
+				val alert = AlertV1.unmarshal(stream)
+				alerts.add(alert)
+			}
+			val departuresNum = reader.readUInt().toULong()
+			for (i in 0UL until departuresNum) {
+				val departure = DepartureV1.unmarshal(stream)
+				departures.add(departure)
+			}
+
+			return DeparturesResponseV1(alerts, departures, StopV1.unmarshal(stream))
+		}
+	}
+}
+
+data class DeparturesResponseDev(
+	val alerts: List<AlertV1>,
+	val departures: List<DepartureV1>,
+	val stop: StopV1
+) : DeparturesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): DeparturesResponseDev {
+			val alerts = mutableListOf<AlertV1>()
+			val departures = mutableListOf<DepartureV1>()
+
+			val reader = Reader(stream)
+			val alertsNum = reader.readUInt().toULong()
+			for (i in 0UL until alertsNum) {
+				val alert = AlertV1.unmarshal(stream)
+				alerts.add(alert)
+			}
+			val departuresNum = reader.readUInt().toULong()
+			for (i in 0UL until departuresNum) {
+				val departure = DepartureV1.unmarshal(stream)
+				departures.add(departure)
+			}
+
+			return DeparturesResponseDev(alerts, departures, StopV1.unmarshal(stream))
+		}
+	}
+}
+
+interface QueryablesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): QueryablesResponse {
+			val reader = Reader(stream)
+			return when (val v = reader.readUInt().toULong()) {
+				0UL -> {
+					QueryablesResponseDev.unmarshal(stream)
+				}
+				1UL -> {
+					QueryablesResponseV1.unmarshal(stream)
+				}
+				else -> {
+					throw UnknownResponseVersion("Queryables", v)
+				}
+			}
+		}
+	}
+}
+
+data class QueryablesResponseV1(val queryables: List<QueryableV1>) : QueryablesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): QueryablesResponseV1 {
+			val queryables = mutableListOf<QueryableV1>()
+			val reader = Reader(stream)
+			val n = reader.readUInt().toULong()
+			for (i in 0UL until n) {
+				when (val r = reader.readUInt().toULong()) {
+					0UL -> {
+						queryables.add(StopV1.unmarshal(stream))
+					}
+					/*1UL -> {
+						queryables.add(Line.unmarshal(stream))
+					}*/
+					else -> {
+						throw UnknownResourceVersion("Queryable/$r", 1u)
+					}
+				}
+			}
+			return QueryablesResponseV1(queryables)
+		}
+	}
+}
+
+data class QueryablesResponseDev(val queryables: List<QueryableV1>) : QueryablesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): QueryablesResponseDev {
+			val queryables = mutableListOf<QueryableV1>()
+			val reader = Reader(stream)
+			val n = reader.readUInt().toULong()
+			for (i in 0UL until n) {
+				when (val r = reader.readUInt().toULong()) {
+					0UL -> {
+						queryables.add(StopV1.unmarshal(stream))
+					}
+					/*1UL -> {
+						queryables.add(Line.unmarshal(stream))
+					}*/
+					else -> {
+						throw UnknownResourceVersion("Queryable/$r", 1u)
+					}
+				}
+			}
+			return QueryablesResponseDev(queryables)
+		}
+	}
+}
+
+interface FeedsResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): FeedsResponse {
+			val reader = Reader(stream)
+			return when (val v = reader.readUInt().toULong()) {
+				0UL -> {
+					FeedsResponseDev.unmarshal(stream)
+				}
+				1UL -> {
+					FeedsResponseV1.unmarshal(stream)
+				}
+				else -> {
+					throw UnknownResponseVersion("Feeds", v)
+				}
+			}
+		}
+	}
+}
+
+data class FeedsResponseDev(
+	val feeds: List<FeedInfoV1>
+) : FeedsResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): FeedsResponseDev {
+			val feeds = mutableListOf<FeedInfoV1>()
+			val reader = Reader(stream)
+			val n = reader.readUInt().toULong()
+			for (i in 0UL until n) {
+				feeds.add(FeedInfoV1.unmarshal(stream))
+			}
+			return FeedsResponseDev(feeds)
+		}
+	}
+}
+
+data class FeedsResponseV1(
+	val feeds: List<FeedInfoV1>
+) : FeedsResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): FeedsResponseV1 {
+			val feeds = mutableListOf<FeedInfoV1>()
+			val reader = Reader(stream)
+			val n = reader.readUInt().toULong()
+			for (i in 0UL until n) {
+				feeds.add(FeedInfoV1.unmarshal(stream))
+			}
+			return FeedsResponseV1(feeds)
+		}
+	}
+}
+
+interface LocatablesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): LocatablesResponse {
+			val reader = Reader(stream)
+			return when (val v = reader.readUInt().toULong()) {
+				0UL -> {
+					LocatablesResponseDev.unmarshal(stream)
+				}
+				1UL -> {
+					LocatablesResponseV1.unmarshal(stream)
+				}
+				else -> {
+					throw UnknownResponseVersion("Locatables", v)
+				}
+			}
+		}
+	}
+}
+
+data class LocatablesResponseV1(val locatables: List<Locatable>) : LocatablesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): LocatablesResponseV1 {
+			val locatables = mutableListOf<Locatable>()
+			val reader = Reader(stream)
+			val n = reader.readUInt().toULong()
+			for (i in 0UL until n) {
+				when (val r = reader.readUInt().toULong()) {
+					0UL -> {
+						locatables.add(StopV1.unmarshal(stream))
+					}
+					1UL -> {
+						locatables.add(VehicleV1.unmarshal(stream))
+					}
+					else -> {
+						throw UnknownResourceVersion("Locatable/$r", 1u)
+					}
+				}
+			}
+			return LocatablesResponseV1(locatables)
+		}
+	}
+}
+data class LocatablesResponseDev(val locatables: List<Locatable>) : LocatablesResponse {
+	companion object {
+		fun unmarshal(stream: InputStream): LocatablesResponseDev {
+			val locatables = mutableListOf<Locatable>()
+			val reader = Reader(stream)
+			val n = reader.readUInt().toULong()
+			for (i in 0UL until n) {
+				when (val r = reader.readUInt().toULong()) {
+					0UL -> {
+						locatables.add(StopV1.unmarshal(stream))
+					}
+					1UL -> {
+						locatables.add(VehicleV1.unmarshal(stream))
+					}
+					else -> {
+						throw UnknownResourceVersion("Locatable/$r", 1u)
+					}
+				}
+			}
+			return LocatablesResponseDev(locatables)
+		}
+	}
+}
+
+data class ErrorResponse(val field: String, val message: String) {
+	companion object {
+		fun unmarshal(stream: InputStream): ErrorResponse {
+			val reader = Reader(stream)
+			return ErrorResponse(reader.readString(), reader.readString())
+		}
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt b/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cf7adc236dc9653c04b5173789855dd53e10d317
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/api/Structs.kt
@@ -0,0 +1,662 @@
+package xyz.apiote.bimba.czwek.api
+
+import android.content.Context
+import android.graphics.*
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.LayerDrawable
+import android.os.Parcelable
+import android.text.format.DateUtils
+import android.util.Log
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.graphics.ColorUtils.HSLToColor
+import androidx.core.graphics.drawable.toBitmap
+import kotlinx.parcelize.Parcelize
+import org.yaml.snakeyaml.Yaml
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.dpToPixel
+import xyz.apiote.bimba.czwek.dpToPixelI
+import xyz.apiote.fruchtfleisch.Reader
+import java.io.InputStream
+import java.time.Instant
+import java.time.ZoneId
+import java.time.ZonedDateTime
+import java.time.format.DateTimeFormatter
+import java.time.format.FormatStyle
+import java.time.temporal.ChronoUnit
+import java.util.*
+import java.util.zip.Adler32
+import kotlin.math.abs
+import kotlin.math.pow
+
+class TrafficFormatException(override val message: String) : IllegalArgumentException()
+class UnknownResourceVersion(val resource: String, val version: ULong) : Exception()
+
+data class BimbaInfo(
+	val contact: Map<String, String>,
+)
+
+data class Bimba(
+	val info: BimbaInfo,
+	val servers: List<Map<String, String>>,
+	val security: List<Map<String, List<*>>>
+) {
+	companion object {
+		@Suppress("UNCHECKED_CAST")
+		fun unmarshal(stream: InputStream): Bimba {
+			val map = Yaml().load(stream) as HashMap<String, *>
+			val contact =
+				if (map["info"] is Map<*, *> && (map["info"] as Map<*, *>).keys.all { it is String }) {
+					(map["info"] as Map<String, *>)["contact"]
+				} else {
+					throw TrafficFormatException("invalid info format")
+				}
+			val contactMap =
+				if (contact is Map<*, *> && contact.all { it.key is String && it.value is String }) {
+					contact as Map<String, String>
+				} else {
+					throw TrafficFormatException("invalid contact format")
+				}
+			val servers = if (map["servers"] is List<*> && (map["servers"] as List<*>).all { server ->
+					server is Map<*, *> && server.all { it.key is String && it.value is String }
+				}) {
+				map["servers"] as List<Map<String, String>>
+			} else {
+				throw TrafficFormatException("invalid servers format")
+			}
+			val security =
+				if (map["security"] is List<*> && (map["security"] as List<*>).all { security ->
+						security is Map<*, *> && security.all { it.key is String && it.value is List<*> }
+					}) {
+					map["security"] as List<Map<String, List<*>>>
+				} else {
+					throw TrafficFormatException("invalid security format")
+				}
+			val bimba = Bimba(BimbaInfo(contactMap), servers, security)
+			bimba.validate()
+			return bimba
+		}
+	}
+
+	fun isPrivate(): Boolean {
+		return security.size == 1 && security[0]["api_key"] != null
+	}
+
+	fun isRateLimited(): Boolean {
+		val items = security.foldRight(0b00) { map, acc ->
+			acc or when {
+				map.containsKey("api_key") -> 0b10
+				map.isEmpty() -> 0b01
+				else -> 0b00
+			}
+		}
+		Log.i("Rate limited", "${this}, $items")
+		return security.size == 2 && items == 0b11
+	}
+
+	private fun validate() {
+		if (servers.isEmpty() || servers[0]["url"] == null) {
+			throw TrafficFormatException("no server in info")
+		}
+		if (security.isEmpty()) {
+			throw TrafficFormatException("no security")
+		}
+	}
+}
+
+@Parcelize
+data class PositionV1(
+	val latitude: Double, val longitude: Double
+) : Parcelable {
+	fun isZero(): Boolean {
+		return latitude == 0.0 && longitude == 0.0
+	}
+
+	override fun toString(): String = "$latitude,$longitude"
+
+
+	companion object {
+		fun unmarshal(stream: InputStream): PositionV1 {
+			val reader = Reader(stream)
+			return PositionV1(
+				reader.readFloat64(), reader.readFloat64()
+			)
+		}
+	}
+}
+
+data class FeedInfoV1(
+	val name: String,
+	val id: String,
+	val attribution: String,
+	val description: String,
+	val lastUpdate: ZonedDateTime
+) {
+	companion object {
+		fun unmarshal(stream: InputStream): FeedInfoV1 {
+			val reader = Reader(stream)
+			return FeedInfoV1(
+				reader.readString(),
+				reader.readString(),
+				reader.readString(),
+				reader.readString(),
+				ZonedDateTime.parse(reader.readString(), DateTimeFormatter.ISO_DATE_TIME)
+			)
+		}
+	}
+
+	fun formatDate(): String {
+		return lastUpdate.format(
+			DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(Locale.getDefault())
+		)
+	}
+}
+
+data class AlertV1(
+	val header: String,
+	val Description: String,
+	val Url: String,
+	val Cause: ULong,  // todo [3.1] enum
+	val Effect: ULong  // todo [3.1] enum
+) {
+	companion object {
+		fun unmarshal(stream: InputStream): AlertV1 {
+			val reader = Reader(stream)
+			val header = reader.readString()
+			val description = reader.readString()
+			val url = reader.readString()
+			val cause = reader.readUInt().toULong()
+			val effect = reader.readUInt().toULong()
+			return AlertV1(header, description, url, cause, effect)
+		}
+	}
+}
+
+data class Time(
+	val Hour: UInt, val Minute: UInt, val Second: UInt, val DayOffset: Byte, val Zone: String
+) {
+	companion object {
+		fun unmarshal(stream: InputStream): Time {
+			val reader = Reader(stream)
+			return Time(
+				reader.readUInt().toULong().toUInt(),
+				reader.readUInt().toULong().toUInt(),
+				reader.readUInt().toULong().toUInt(),
+				reader.readI8(),
+				reader.readString()
+			)
+		}
+	}
+}
+
+data class ColourV1(val R: UByte, val G: UByte, val B: UByte) {
+	companion object {
+		fun unmarshal(stream: InputStream): ColourV1 {
+			val reader = Reader(stream)
+			return ColourV1(
+				reader.readU8(), reader.readU8(), reader.readU8()
+			)
+		}
+	}
+
+	fun toInt(): Int {
+		var rgb = 0xff
+		rgb = (rgb shl 8) + R.toInt()
+		rgb = (rgb shl 8) + G.toInt()
+		rgb = (rgb shl 8) + B.toInt()
+		return rgb
+	}
+}
+
+data class VehicleV1(
+	val ID: String,
+	val Position: PositionV1,
+	val Capabilities: UShort,
+	val Speed: Float,
+	val Line: LineStubV1,
+	val Headsign: String,
+	val CongestionLevel: ULong,
+	val OccupancyStatus: ULong
+) : Locatable {
+	enum class Capability(val bit: UShort) {
+		RAMP(0b0001u), LOW_FLOOR(0b0010u), LOW_ENTRY(0b0001_0000_0000u), AC(0b0100u), BIKE(0b1000u), VOICE(
+			0b0001_0000u
+		),
+		TICKET_MACHINE(0b0010_0000u), TICKET_DRIVER(0b0100_0000u), USB_CHARGING(0b1000_0000u)
+	}
+
+	override fun id(): String = ID
+
+	override fun icon(context: Context, scale: Float): Drawable {
+		return BitmapDrawable(context.resources, Line.icon(context, scale))
+	}
+
+	override fun location(): PositionV1 = Position
+
+	fun congestion(context: Context): String {
+		return when (val r = CongestionLevel.toUInt()) { // todo [3.1] enum
+			0u -> context.getString(R.string.congestion_unknown)
+			1u -> context.getString(R.string.congestion_smooth)
+			2u -> context.getString(R.string.congestion_stop_and_go)
+			3u -> context.getString(R.string.congestion_congestion)
+			4u -> context.getString(R.string.congestion_jams)
+			else -> throw UnknownResourceVersion("Congestion/$r", 1u)
+		}
+	}
+
+	fun occupancy(context: Context): String {
+		return when (val r = OccupancyStatus.toUInt()) { // todo [3.1] enum
+			0u -> context.getString(R.string.occupancy_unknown)
+			1u -> context.getString(R.string.occupancy_empty)
+			2u -> context.getString(R.string.occupancy_many_seats)
+			3u -> context.getString(R.string.occupancy_few_seats)
+			4u -> context.getString(R.string.occupancy_standing_only)
+			5u -> context.getString(R.string.occupancy_crowded)
+			6u -> context.getString(R.string.occupancy_full)
+			7u -> context.getString(R.string.occupancy_wont_let)
+			else -> throw UnknownResourceVersion("Occupancy/$r", 1u)
+		}
+	}
+
+	companion object {
+		fun unmarshal(stream: InputStream): VehicleV1 {
+			val reader = Reader(stream)
+			return VehicleV1(
+				reader.readString(),
+				PositionV1.unmarshal(stream),
+				reader.readU16(),
+				reader.readFloat32(),
+				LineStubV1.unmarshal(stream),
+				reader.readString(),
+				reader.readUInt().toULong(),
+				reader.readUInt().toULong()
+			)
+		}
+	}
+
+	fun getCapability(field: Capability): Boolean {
+		return Capabilities.and(field.bit) != (0).toUShort()
+	}
+}
+
+data class LineStubV1(
+	val name: String, val kind: LineTypeV1, val colour: ColourV1
+) : LineAbstract {
+	companion object {
+		fun unmarshal(stream: InputStream): LineStubV1 {
+			val reader = Reader(stream)
+			return LineStubV1(
+				reader.readString(),
+				LineTypeV1.of(reader.readUInt().toULong().toUInt()),
+				ColourV1.unmarshal(stream)
+			)
+		}
+	}
+
+	fun icon(context: Context, scale: Float = 1f): Bitmap {
+		return super.icon(context, kind, colour, scale)
+	}
+}
+
+data class DepartureV1(
+	val ID: String,
+	val time: Time,
+	val status: ULong,
+	val isRealtime: Boolean,
+	val vehicle: VehicleV1,
+	val boarding: UByte
+) {
+
+	fun statusText(context: Context?): String {
+		val now = Instant.now().atZone(ZoneId.systemDefault())
+		val departureTime = ZonedDateTime.of(
+			now.year, now.monthValue, now.dayOfMonth,
+			time.Hour.toInt(), time.Minute.toInt(), time.Second.toInt(), 0, ZoneId.of(time.Zone)
+		).plus(time.DayOffset.toLong(), ChronoUnit.DAYS)
+		return when (val r = status.toUInt()) {
+			0u -> DateUtils.getRelativeTimeSpanString(
+				departureTime.toEpochSecond() * 1000,
+				now.toEpochSecond() * 1000,
+				DateUtils.MINUTE_IN_MILLIS,
+				DateUtils.FORMAT_ABBREV_RELATIVE
+			).toString()
+			1u -> context?.getString(R.string.departure_momentarily) ?: "momentarily"
+			2u -> context?.getString(R.string.departure_now) ?: "now"
+			3u -> context?.getString(R.string.departure_departed) ?: "departed"
+			else -> throw UnknownResourceVersion("VehicleStatus/$r", 1u)
+		}
+	}
+
+	fun timeString(context: Context): String {
+		return if (isRealtime) {
+			context.getString(
+				R.string.at_time_realtime, time.Hour.toInt(), time.Minute.toInt(), time.Second.toInt()
+			)
+		} else {
+			context.getString(R.string.at_time, time.Hour.toInt(), time.Minute.toInt())
+		}
+	}
+
+	fun boardingText(context: Context): String {
+		// todo [3.x] probably should take into account (on|off)-boarding only, on demand
+		return when {
+			boarding == (0b0000_0000).toUByte() -> context.getString(R.string.no_boarding)
+			boarding.and(0b0011_0011u) == (0b0000_0001).toUByte() -> context.getString(R.string.on_boarding)
+			boarding.and(0b0011_0011u) == (0b0001_0000).toUByte() -> context.getString(R.string.off_boarding)
+			boarding.and(0b0011_0011u) == (0b0001_0001).toUByte() -> context.getString(R.string.boarding)
+			else -> context.getString(R.string.on_demand)
+		}
+	}
+
+	companion object {
+		fun unmarshal(stream: InputStream): DepartureV1 {
+			val reader = Reader(stream)
+			val id = reader.readString()
+			val time = Time.unmarshal(stream)
+			val status = reader.readUInt().toULong()
+			val isRealtime = reader.readBoolean()
+			val vehicle = VehicleV1.unmarshal(stream)
+			val boarding = reader.readU8()
+			return DepartureV1(id, time, status, isRealtime, vehicle, boarding)
+		}
+	}
+}
+
+interface QueryableV1
+interface Locatable {
+	fun icon(context: Context, scale: Float = 1f): Drawable
+	fun location(): PositionV1
+	fun id(): String
+}
+
+class ErrorLocatable(val stringResource: Int) : Locatable {
+	override fun icon(context: Context, scale: Float): Drawable {
+		return AppCompatResources.getDrawable(context, R.drawable.error_other)!!
+	}
+
+	override fun location(): PositionV1 {
+		return PositionV1(0.0, 0.0)
+	}
+
+	override fun id(): String {
+		return "ERROR"
+	}
+}
+
+@Parcelize
+data class StopV1(
+	val code: String,
+	val name: String,
+	val zone: String,
+	val position: PositionV1,
+	val changeOptions: List<ChangeOptionV1>
+) : QueryableV1, Locatable, Parcelable {
+
+	override fun icon(context: Context, scale: Float): Drawable {
+		val saturationArray = arrayOf(0.5f, 0.65f, 0.8f)
+		val sal = saturationArray.size
+		val lightnessArray = arrayOf(.5f)
+		val lal = lightnessArray.size
+		val md = Adler32().let {
+			it.update(name.toByteArray())
+			it.value
+		}
+		val h = md % 359f
+		val s = saturationArray[(md / 360 % sal).toInt()]
+		val l = lightnessArray[(md / 360 / sal % lal).toInt()]
+		val fg = AppCompatResources.getDrawable(context, R.drawable.stop)
+		val bg = AppCompatResources.getDrawable(context, R.drawable.stop_bg)!!.mutate().apply {
+			setTint(HSLToColor(arrayOf(h, s, l).toFloatArray()))
+		}
+		return BitmapDrawable(
+			context.resources,
+			LayerDrawable(arrayOf(bg, fg)).mutate()
+				.toBitmap(dpToPixelI(24f / scale), dpToPixelI(24f / scale), Bitmap.Config.ARGB_8888)
+		)
+	}
+
+	override fun id(): String = code
+
+	override fun location(): PositionV1 = position
+
+	override fun toString(): String {
+		var result = "$name ($code) [$zone] $position\n"
+		for (chOpt in changeOptions) result += "${chOpt.line} → ${chOpt.headsign}\n"
+		return result
+	}
+
+	fun changeOptions(context: Context): Pair<String, String> {
+		return Pair(changeOptions.groupBy { it.line }
+			.map { Pair(it.key, it.value.joinToString { co -> co.headsign }) }.joinToString {
+				context.getString(
+					R.string.vehicle_headsign, it.first, it.second
+				)
+			},
+			changeOptions.groupBy { it.line }
+				.map { Pair(it.key, it.value.joinToString { co -> co.headsign }) }.joinToString {
+					context.getString(
+						R.string.vehicle_headsign_content_description, it.first, it.second
+					)
+				})
+	}
+
+	companion object {
+		fun unmarshal(stream: InputStream): StopV1 {
+			val reader = Reader(stream)
+			val code = reader.readString()
+			val name = reader.readString()
+			val zone = reader.readString()
+			val position = PositionV1.unmarshal(stream)
+			val chOptionsNum = reader.readUInt().toULong()
+			val changeOptions = mutableListOf<ChangeOptionV1>()
+			for (i in 0UL until chOptionsNum) {
+				changeOptions.add(ChangeOptionV1.unmarshal(stream))
+			}
+			return StopV1(
+				name = name, code = code, zone = zone, position = position, changeOptions = changeOptions
+			)
+		}
+	}
+}
+
+interface LineAbstract {
+	fun textColour(c: ColourV1): Int {
+		val black = relativeLuminance(ColourV1(0u, 0u, 0u)) + .05
+		val white = relativeLuminance(ColourV1(255u, 255u, 255u)) + .05
+		val colour = relativeLuminance(c) + .05
+		return if ((white / colour) > (colour / black)) {
+			Color.WHITE
+		} else {
+			Color.BLACK
+		}
+	}
+
+	private fun relativeLuminance(colour: ColourV1): Double {
+		val r = fromSRGB(colour.R.toDouble() / 0xff)
+		val g = fromSRGB(colour.G.toDouble() / 0xff)
+		val b = fromSRGB(colour.B.toDouble() / 0xff)
+		return 0.2126 * r + 0.7152 * g + 0.0722 * b
+	}
+
+	private fun fromSRGB(part: Double): Double {
+		return if (part <= 0.03928) {
+			part / 12.92
+		} else {
+			((part + 0.055) / 1.055).pow(2.4)
+		}
+	}
+
+	fun icon(context: Context, type: LineTypeV1, colour: ColourV1, scale: Float): Bitmap {
+		val drawingBitmap = Bitmap.createBitmap(
+			dpToPixelI(24f / scale), dpToPixelI(24f / scale), Bitmap.Config.ARGB_8888
+		)
+		val canvas = Canvas(drawingBitmap)
+
+		canvas.drawPath(getSquirclePath(
+			dpToPixel(.8f / scale), dpToPixel(.8f / scale), dpToPixelI(11.2f / scale)
+		), Paint().apply { color = textColour(colour) })
+		canvas.drawPath(getSquirclePath(
+			dpToPixel(1.6f / scale), dpToPixel(1.6f / scale), dpToPixelI(10.4f / scale)
+		), Paint().apply { color = colour.toInt() })
+
+		val iconID = when (type) {
+			LineTypeV1.BUS -> R.drawable.bus_black
+			LineTypeV1.TRAM -> R.drawable.tram_black
+			LineTypeV1.UNKNOWN -> R.drawable.vehicle_black
+		}
+		val icon = AppCompatResources.getDrawable(context, iconID)?.mutate()?.apply {
+			setTint(textColour(colour))
+		}?.toBitmap(dpToPixelI(19.2f / scale), dpToPixelI(19.2f / scale), Bitmap.Config.ARGB_8888)
+		canvas.drawBitmap(
+			icon!!, dpToPixel(2.4f / scale), dpToPixel(2.4f / scale), Paint()
+		)
+		return drawingBitmap
+	}
+
+	private fun getSquirclePath(
+		left: Float, top: Float, radius: Int
+	): Path {
+		val radiusToPow = (radius * radius * radius).toDouble()
+		val path = Path()
+		path.moveTo(-radius.toFloat(), 0f)
+		for (x in -radius..radius) path.lineTo(
+			x.toFloat(), Math.cbrt(radiusToPow - abs(x * x * x)).toFloat()
+		)
+		for (x in radius downTo -radius) path.lineTo(
+			x.toFloat(), -Math.cbrt(radiusToPow - abs(x * x * x)).toFloat()
+		)
+		path.close()
+		val matrix = Matrix()
+		matrix.postTranslate((left + radius), (top + radius))
+		path.transform(matrix)
+		return path
+	}
+}
+
+data class Line(
+	val colour: ColourV1,
+	val type: LineTypeV1,
+	val headsignsThere: List<String>,
+	val headsignsBack: List<String>,
+	val graphThere: LineGraph,
+	val graphBack: LineGraph,
+	val name: String
+) : QueryableV1, LineAbstract {
+	override fun toString(): String {
+		return "$name ($type) [$colour]\n→ [${headsignsThere.joinToString()}]\n→ [${headsignsBack.joinToString()}]\n"
+	}
+
+	fun icon(context: Context, scale: Float = 1f): Bitmap {
+		return super.icon(context, type, colour, scale)
+	}
+
+	companion object {
+		fun unmarshal(stream: InputStream): Line {
+			val reader = Reader(stream)
+			val colour = ColourV1.unmarshal(stream)
+			val type = reader.readUInt()
+			val headsignsThereNum = reader.readUInt().toULong()
+			val headsignsThere = mutableListOf<String>()
+			for (i in 0UL until headsignsThereNum) {
+				headsignsThere.add(reader.readString())
+			}
+			val headsignsBackNum = reader.readUInt().toULong()
+			val headsignsBack = mutableListOf<String>()
+			for (i in 0UL until headsignsBackNum) {
+				headsignsBack.add(reader.readString())
+			}
+			val graphThere = LineGraph.unmarshal(stream)
+			val graphBack = LineGraph.unmarshal(stream)
+			val name = reader.readString()
+			return Line(
+				name = name,
+				colour = colour,
+				type = LineTypeV1.of(type.toULong().toUInt()),
+				headsignsThere = headsignsThere,
+				headsignsBack = headsignsBack,
+				graphThere = graphThere,
+				graphBack = graphBack
+			)
+		}
+	}
+}
+
+enum class LineTypeV1 {
+	UNKNOWN, TRAM, BUS;
+
+	companion object {
+		fun of(type: UInt): LineTypeV1 {
+			return when (type) {
+				0u -> valueOf("UNKNOWN")
+				1u -> valueOf("TRAM")
+				2u -> valueOf("BUS")
+				else -> throw UnknownResourceVersion("LineType/$type", 1u)
+			}
+		}
+	}
+}
+
+@Parcelize
+data class ChangeOptionV1(val line: String, val headsign: String):Parcelable {
+	companion object {
+		fun unmarshal(stream: InputStream): ChangeOptionV1 {
+			val reader = Reader(stream)
+			return ChangeOptionV1(line = reader.readString(), headsign = reader.readString())
+		}
+	}
+}
+
+data class LineGraph(
+	val stops: List<StopStub>,
+	val nextNodes: Map<Long, List<Long>>,
+	val prevNodes: Map<Long, List<Long>>
+) {
+	companion object {
+		fun unmarshal(stream: InputStream): LineGraph {
+			val reader = Reader(stream)
+			val stopsNum = reader.readUInt().toULong()
+			val stops = mutableListOf<StopStub>()
+			for (i in 0UL until stopsNum) {
+				stops.add(StopStub.unmarshal(stream))
+			}
+			val nextNodesNum = reader.readUInt().toULong()
+			val nextNodes = mutableMapOf<Long, List<Long>>()
+			for (i in 0UL until nextNodesNum) {
+				val from = reader.readInt().toLong()
+				val toNum = reader.readUInt().toULong()
+				val to = mutableListOf<Long>()
+				for (j in 0UL until toNum) {
+					to.add(reader.readInt().toLong())
+				}
+				nextNodes[from] = to
+			}
+			val prevNodesNum = reader.readUInt().toULong()
+			val prevNodes = mutableMapOf<Long, List<Long>>()
+			for (i in 0UL until prevNodesNum) {
+				val from = reader.readInt().toLong()
+				val toNum = reader.readUInt().toULong()
+				val to = mutableListOf<Long>()
+				for (j in 0UL until toNum) {
+					to.add(reader.readInt().toLong())
+				}
+				prevNodes[from] = to
+			}
+
+			return LineGraph(stops = stops, nextNodes = nextNodes, prevNodes = prevNodes)
+		}
+	}
+}
+
+data class StopStub(val name: String, val code: String, val zone: String, val onDemand: Boolean) {
+	companion object {
+		fun unmarshal(stream: InputStream): StopStub {
+			val reader = Reader(stream)
+			return StopStub(
+				code = reader.readString(),
+				name = reader.readString(),
+				zone = reader.readString(),
+				onDemand = reader.readBoolean()
+			)
+		}
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d9948e433a7a53bcfc8b905ad9771c7e84603820
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/MainActivity.kt
@@ -0,0 +1,202 @@
+package xyz.apiote.bimba.czwek.dashboard
+
+import android.Manifest
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.os.Bundle
+import android.view.View
+import android.widget.Toast
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.core.content.edit
+import androidx.core.view.WindowCompat
+import androidx.core.view.get
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks
+import androidx.navigation.fragment.NavHostFragment
+import androidx.navigation.ui.setupWithNavController
+import com.google.android.material.bottomnavigation.BottomNavigationView
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.Line
+import xyz.apiote.bimba.czwek.api.QueryableV1
+import xyz.apiote.bimba.czwek.api.StopV1
+import xyz.apiote.bimba.czwek.dashboard.ui.home.HomeFragment
+import xyz.apiote.bimba.czwek.dashboard.ui.map.MapFragment
+import xyz.apiote.bimba.czwek.dashboard.ui.voyage.VoyageFragment
+import xyz.apiote.bimba.czwek.databinding.ActivityMainBinding
+import xyz.apiote.bimba.czwek.departures.DeparturesActivity
+import xyz.apiote.bimba.czwek.search.ResultsActivity
+import xyz.apiote.bimba.czwek.settings.ServerChooserActivity
+import xyz.apiote.bimba.czwek.settings.feeds.FeedChooserActivity
+
+
+class MainActivity : AppCompatActivity() {
+	private lateinit var binding: ActivityMainBinding
+	private lateinit var locationPermissionRequest: ActivityResultLauncher<Array<String>>
+
+	private lateinit var permissionAsker: Fragment
+
+	override fun onCreate(savedInstanceState: Bundle?) {
+		super.onCreate(savedInstanceState)
+		binding = ActivityMainBinding.inflate(layoutInflater)
+		setContentView(binding.root)
+
+		getSharedPreferences("shp", MODE_PRIVATE).edit(true) {
+			putBoolean("firstRun", false)
+		}
+
+		supportFragmentManager.registerFragmentLifecycleCallbacks(
+			object : FragmentLifecycleCallbacks() {
+				override fun onFragmentViewCreated(
+					fm: FragmentManager, f: Fragment, v: View, savedInstanceState: Bundle?
+				) {
+					setNavbarIcons(f)
+					super.onFragmentViewCreated(fm, f, v, savedInstanceState)
+				}
+			}, true
+		)
+
+		binding.navigationDrawer.setNavigationItemSelectedListener {
+			when (it.itemId) {
+				R.id.drawer_servers -> {
+					startActivity(Intent(this, ServerChooserActivity::class.java))
+				}
+				R.id.drawer_cities -> {
+					startActivity(Intent(this, FeedChooserActivity::class.java))
+				}
+			}
+			false
+		}
+
+		WindowCompat.setDecorFitsSystemWindows(window, false)
+		val navView: BottomNavigationView = binding.bottomNavigation
+		val navHostFragment =
+			supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main) as NavHostFragment
+		val navController = navHostFragment.navController
+		navView.setupWithNavController(navController)
+
+		locationPermissionRequest = registerForActivityResult(
+			ActivityResultContracts.RequestMultiplePermissions()
+		) { permissions ->
+			when {
+				permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: false ||
+								permissions[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false -> {
+					when (permissionAsker) {
+						is HomeFragment -> {
+							showResults(ResultsActivity.Mode.MODE_LOCATION)
+						}
+						is MapFragment -> {
+							(permissionAsker as MapFragment).showLocation()
+						}
+					}
+				}
+				else -> {
+					// todo(ux,ui) dialog
+					Toast.makeText(this, "No location access given", Toast.LENGTH_SHORT).show()
+				}
+			}
+		}
+	}
+
+	@Suppress(
+		"OVERRIDE_DEPRECATION",
+		"DEPRECATION"
+	)  // fixme later https://developer.android.com/reference/androidx/activity/OnBackPressedDispatcher
+	override fun onBackPressed() {
+		if (binding.container.isDrawerOpen(binding.navigationDrawer)) {
+			binding.container.closeDrawer(binding.navigationDrawer)
+		} else {
+			super.onBackPressed()
+		}
+	}
+
+	fun onNavigationClicked() {
+		if (binding.container.isDrawerOpen(binding.navigationDrawer)) {
+			binding.container.closeDrawer(binding.navigationDrawer)
+		} else {
+			binding.container.openDrawer(binding.navigationDrawer)
+		}
+	}
+
+	fun onGpsClicked(fragment: Fragment) {
+		when (PackageManager.PERMISSION_GRANTED) {
+			ContextCompat.checkSelfPermission(
+				this,
+				Manifest.permission.ACCESS_COARSE_LOCATION
+			) -> {
+				when (fragment) {
+					is HomeFragment -> {
+						showResults(ResultsActivity.Mode.MODE_LOCATION)
+					}
+					is MapFragment -> {
+						fragment.showLocation()
+					}
+				}
+			}
+			else -> {
+				permissionAsker = fragment
+				locationPermissionRequest.launch(
+					arrayOf(
+						Manifest.permission.ACCESS_FINE_LOCATION,
+						Manifest.permission.ACCESS_COARSE_LOCATION
+					)
+				)
+			}
+		}
+	}
+
+	fun onSuggestionClicked(queryable: QueryableV1) {
+		when (queryable) {
+			is StopV1 -> {
+				val intent = Intent(this, DeparturesActivity::class.java).apply {
+					putExtra("code", queryable.code)
+					putExtra("name", queryable.name)
+				}
+				startActivity(intent)
+			}
+			is Line -> {
+				TODO("[3.1] start line graph activity")
+			}
+		}
+	}
+
+	fun onSearchClicked(text: CharSequence?) {
+		showResults(ResultsActivity.Mode.MODE_SEARCH, text.toString())
+	}
+
+	private fun showResults(mode: ResultsActivity.Mode, query: String = "") {
+		/* todo [3.1] (ux,low) animation
+			https://developer.android.com/guide/fragments/animate
+			https://github.com/raheemadamboev/fab-explosion-animation-app
+		*/
+		val intent = Intent(this, ResultsActivity::class.java).apply {
+			putExtra("mode", mode)
+			putExtra("query", query)
+		}
+		startActivity(intent)
+	}
+
+	private fun setNavbarIcons(f: Fragment) {
+		// todo [voyage-planning]
+		// binding.bottomNavigation.menu[2].setIcon(R.drawable.voyage_outline)
+		binding.bottomNavigation.menu[1].setIcon(R.drawable.home_outline)
+		binding.bottomNavigation.menu[0].setIcon(R.drawable.map_outline)
+		when (f) {
+			is HomeFragment -> {
+				binding.bottomNavigation.menu[1].setIcon(R.drawable.home_black)
+			}
+			is VoyageFragment -> {
+				binding.bottomNavigation.menu[2].setIcon(R.drawable.voyage_black)
+			}
+			is MapFragment -> {
+				binding.bottomNavigation.menu[0].setIcon(R.drawable.map_black)
+			}
+			else -> {
+				binding.bottomNavigation.menu[1].setIcon(R.drawable.home_black)
+			}
+		}
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..816339a9a11fdffc30fa1df3a6b2de20c054aefc
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeFragment.kt
@@ -0,0 +1,92 @@
+package xyz.apiote.bimba.czwek.dashboard.ui.home
+
+import android.content.Context
+import android.net.ConnectivityManager
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.mancj.materialsearchbar.MaterialSearchBar
+import com.mancj.materialsearchbar.MaterialSearchBar.BUTTON_NAVIGATION
+import xyz.apiote.bimba.czwek.api.QueryableV1
+import xyz.apiote.bimba.czwek.dashboard.MainActivity
+import xyz.apiote.bimba.czwek.databinding.FragmentHomeBinding
+import xyz.apiote.bimba.czwek.search.BimbaSuggestionsAdapter
+
+// todo [3.1] search: https://github.com/material-components/material-components-android/blob/master/docs/components/Search.md
+
+class HomeFragment : Fragment() {
+	private var _binding: FragmentHomeBinding? = null
+	private val binding get() = _binding!!
+
+	private var lastSuggestions = listOf<QueryableV1>()
+
+	override fun onCreateView(
+		inflater: LayoutInflater,
+		container: ViewGroup?,
+		savedInstanceState: Bundle?
+	): View {
+		_binding = FragmentHomeBinding.inflate(inflater, container, false)
+
+		val homeViewModel =
+			ViewModelProvider(this)[HomeViewModel::class.java]
+		homeViewModel.queryables.observe(viewLifecycleOwner) {
+			binding.searchBar.updateLastSuggestions(it)
+		}
+
+		val root = binding.root
+		ViewCompat.setOnApplyWindowInsetsListener(root) { view, windowInsets ->
+			val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
+			view.layoutParams = (view.layoutParams as FrameLayout.LayoutParams).apply {
+				topMargin = insets.top
+			}
+			WindowInsetsCompat.CONSUMED
+		}
+
+		binding.searchBar.lastSuggestions = lastSuggestions
+		val cm = requireContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+		binding.searchBar.addTextChangeListener(
+			homeViewModel.SearchBarWatcher(requireContext(), cm)
+		)
+		binding.searchBar.setOnSearchActionListener(object : MaterialSearchBar.OnSearchActionListener {
+			override fun onButtonClicked(buttonCode: Int) {
+				when (buttonCode) {
+					BUTTON_NAVIGATION -> {
+						(context as MainActivity).onNavigationClicked()
+					}
+				}
+			}
+
+			override fun onSearchStateChanged(enabled: Boolean) {
+			}
+
+			override fun onSearchConfirmed(text: CharSequence?) {
+				binding.searchBar.clearSuggestions()
+				(context as MainActivity).onSearchClicked(text)
+			}
+		})
+		binding.searchBar.setCardViewElevation(0)
+		binding.searchBar.setCustomSuggestionAdapter(BimbaSuggestionsAdapter(layoutInflater, context) {
+			binding.searchBar.clearSuggestions()
+			(context as MainActivity).onSuggestionClicked(it)
+		})
+
+		binding.floatingActionButton.setOnClickListener {
+			binding.searchBar.clearSuggestions()
+			(context as MainActivity).onGpsClicked(this)
+		}
+		// todo [3.1] (ux,low) on searchbar focus && if != '' -> populate suggestions
+
+		return binding.root
+	}
+
+	override fun onDestroyView() {
+		super.onDestroyView()
+		_binding = null
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..72f6efd2bb9b254905f1172adef1f9ac98a07ba0
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/home/HomeViewModel.kt
@@ -0,0 +1,88 @@
+package xyz.apiote.bimba.czwek.dashboard.ui.home
+
+import android.content.Context
+import android.net.ConnectivityManager
+import android.os.Handler
+import android.os.Looper
+import android.text.Editable
+import android.text.TextWatcher
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.launch
+import xyz.apiote.bimba.czwek.api.*
+
+class HomeViewModel : ViewModel() {
+	private val mutableQueryables = MutableLiveData<List<QueryableV1>>()
+	val queryables: LiveData<List<QueryableV1>> = mutableQueryables
+
+	fun getQueryables(cm: ConnectivityManager, server: Server, query: String) {
+		viewModelScope.launch {
+			val result = queryQueryables(cm, server, query, limit = 6)
+			if (result.error != null) {
+				// note intentionally no error showing in suggestions
+				if (result.stream != null) {
+					Log.e("Suggestion", "${b2s(result.stream.readBytes())}")
+					return@launch
+					Log.e(
+						"Suggestion",
+						"${result.error.statusCode}, ${ErrorResponse.unmarshal(result.stream).message}"
+					)
+				} else {
+					Log.e("Suggestion", "${result.error.statusCode}")
+				}
+			} else {
+				mutableQueryables.value =
+					when (val response = QueryablesResponse.unmarshal(result.stream!!)) {
+						is QueryablesResponseDev -> response.queryables
+						is QueryablesResponseV1 -> response.queryables
+						else -> null
+					}
+			}
+		}
+	}
+
+	private fun b2s(b: ByteArray): String {
+		var s = ""
+		b.forEach {
+			if (it in 32..127) {
+				s += Char(it.toInt())
+			} else {
+				s += "\\x$it"
+			}
+		}
+		return s
+	}
+
+	inner class SearchBarWatcher(
+		private val context: Context,
+		private val cm: ConnectivityManager
+	) :
+		TextWatcher {
+		private val handler = Handler(Looper.getMainLooper())
+		private var workRunnable = Runnable {}
+
+		override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
+		}
+
+		override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
+		}
+
+		override fun afterTextChanged(s: Editable?) {
+			handler.removeCallbacks(workRunnable)
+			workRunnable = Runnable {
+				val text = s.toString()
+				getQueryables(
+					cm,
+					Server.get(context), text
+				)
+			}
+			handler.postDelayed(
+				workRunnable,
+				750
+			) // todo(ux,low) make good time (probably between 500, 1000ms)
+		}
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b688de9e98fd5a9be8c9e142a98faa029b3c5ca8
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapFragment.kt
@@ -0,0 +1,244 @@
+package xyz.apiote.bimba.czwek.dashboard.ui.map
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Context.MODE_PRIVATE
+import android.content.SharedPreferences
+import android.content.res.Configuration.*
+import android.graphics.Bitmap
+import android.net.ConnectivityManager
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.content.edit
+import androidx.core.graphics.drawable.toBitmap
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import com.google.android.material.snackbar.Snackbar
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.ErrorLocatable
+import xyz.apiote.bimba.czwek.api.PositionV1
+import xyz.apiote.bimba.czwek.api.Server
+import xyz.apiote.bimba.czwek.dashboard.MainActivity
+import xyz.apiote.bimba.czwek.databinding.FragmentMapBinding
+import xyz.apiote.bimba.czwek.dpToPixelI
+import org.osmdroid.config.Configuration
+import org.osmdroid.events.MapListener
+import org.osmdroid.events.ScrollEvent
+import org.osmdroid.events.ZoomEvent
+import org.osmdroid.tileprovider.tilesource.TileSourceFactory
+import org.osmdroid.util.GeoPoint
+import org.osmdroid.views.CustomZoomButtonsController
+import org.osmdroid.views.overlay.Marker
+import org.osmdroid.views.overlay.TilesOverlay
+import org.osmdroid.views.overlay.gestures.RotationGestureOverlay
+import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider
+import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay
+
+// todo[3.1] empty state on no network
+
+class MapFragment : Fragment() {
+
+	private var maybeBinding: FragmentMapBinding? = null
+	private val binding get() = maybeBinding!!
+
+	private lateinit var locationOverlay: MyLocationNewOverlay
+	private lateinit var mapViewModel: MapViewModel
+
+	private val handler = Handler(Looper.getMainLooper())
+	private var workRunnable = Runnable {}
+
+	private var snack: Snackbar? = null
+
+	@SuppressLint("ClickableViewAccessibility")
+	override fun onCreateView(
+		inflater: LayoutInflater,
+		container: ViewGroup?,
+		savedInstanceState: Bundle?
+	): View {
+		mapViewModel =
+			ViewModelProvider(this)[MapViewModel::class.java]
+
+		observeLocatables()
+
+		maybeBinding = FragmentMapBinding.inflate(inflater, container, false)
+		val root: View = binding.root
+
+		binding.map.setTileSource(TileSourceFactory.MAPNIK)
+		if (((context?.resources?.configuration?.uiMode ?: UI_MODE_NIGHT_UNDEFINED)
+							and UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES
+		) {
+			binding.map.overlayManager.tilesOverlay.setColorFilter(TilesOverlay.INVERT_COLORS)
+		}
+		binding.map.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
+		binding.map.setMultiTouchControls(true)
+		binding.map.overlays.add(RotationGestureOverlay(binding.map).apply { isEnabled = true })
+
+		locationOverlay = MyLocationNewOverlay(GpsMyLocationProvider(context), binding.map)
+		context?.let {
+			centreMap(it.getSharedPreferences("shp", MODE_PRIVATE))
+
+			locationOverlay.setDirectionIcon(
+				AppCompatResources.getDrawable(it, R.drawable.navigation_arrow)?.mutate()
+					?.toBitmap(dpToPixelI(36f), dpToPixelI(36f), Bitmap.Config.ARGB_8888)
+			)
+			locationOverlay.setDirectionAnchor(.5f, .5f)
+			locationOverlay.setPersonIcon(
+				AppCompatResources.getDrawable(it, R.drawable.navigation_circle)?.mutate()
+					?.toBitmap(dpToPixelI(24f), dpToPixelI(24f), Bitmap.Config.ARGB_8888)
+			)
+			locationOverlay.setPersonAnchor(.5f, .5f)
+		}
+
+		binding.floatingActionButton.setOnClickListener {
+			(context as MainActivity).onGpsClicked(this)
+		}
+
+		binding.map.addMapListener(object : MapListener {
+			override fun onScroll(event: ScrollEvent?): Boolean {
+				return onMapMove()
+			}
+
+			override fun onZoom(event: ZoomEvent?): Boolean {
+				return onMapMove()
+			}
+		})
+
+		binding.map.setOnTouchListener { _, _ ->
+			binding.floatingActionButton.show()
+			false
+		}
+
+		return root
+	}
+
+	private fun onMapMove(): Boolean {
+		snack?.dismiss()
+		return delayGetLocatables()
+	}
+
+	private fun delayGetLocatables(delay: Long = 1000): Boolean {
+		handler.removeCallbacks(workRunnable)
+		workRunnable = Runnable {
+			getLocatables()
+		}
+		handler.postDelayed(workRunnable, delay)
+		return true
+	}
+
+	private fun observeLocatables() {
+		mapViewModel.locatables.observe(viewLifecycleOwner) {
+			binding.map.overlays.removeAll { marker ->
+				marker is Marker
+			}
+
+			if (it.size == 1 && it[0] is ErrorLocatable) {
+				Snackbar.make(binding.root, (it[0] as ErrorLocatable).stringResource, Snackbar.LENGTH_LONG).show()
+				return@observe
+			}
+
+			it.forEach { locatable ->
+				val marker = Marker(binding.map)
+				marker.position = GeoPoint(locatable.location().latitude, locatable.location().longitude)
+				marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
+				marker.icon = context?.let { ctx -> locatable.icon(ctx, 2f) }
+
+				context?.let { ctx ->
+					marker.setOnMarkerClickListener { _, _ ->
+						MapBottomSheet(locatable).apply {
+							(ctx as MainActivity?)?.supportFragmentManager?.let { fm ->
+								show(fm, MapBottomSheet.TAG)
+							}
+						}
+						true
+					}
+				}
+				binding.map.overlays.add(marker)
+			}
+
+			binding.map.invalidate()
+		}
+	}
+
+	fun showLocation() {
+		snack =
+			Snackbar.make(binding.root, getString(R.string.waiting_position), Snackbar.LENGTH_INDEFINITE)
+		snack!!.show()
+		binding.floatingActionButton.hide()
+		binding.map.overlays.removeAll {
+			it is MyLocationNewOverlay
+		}
+		locationOverlay.enableFollowLocation()
+		binding.map.overlays.add(locationOverlay)
+		locationOverlay.runOnFirstFix {
+			snack?.dismiss()
+		}
+	}
+
+	private fun getLocatables() {
+		maybeBinding?.let { binding ->
+			val (bl, tr) = binding.map.boundingBox.let {
+				Pair(
+					PositionV1(it.latSouth, it.lonWest),
+					PositionV1(it.latNorth, it.lonEast)
+				)
+			}
+			context?.let {
+				val cm = it.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+				mapViewModel.getLocatablesIn(
+					cm,
+					Server.get(it), bl, tr
+				)
+			}
+			delayGetLocatables(30000)
+		}
+	}
+
+	private fun centreMap(preferences: SharedPreferences) {
+		maybeBinding?.map?.controller?.apply {
+			setZoom(preferences.getFloat("mapZoom", 17.0f).toDouble())
+			val startPoint = GeoPoint(
+				preferences.getFloat("mapCentreLat", 52.39511f).toDouble(),
+				preferences.getFloat("mapCentreLon", 16.89506f).toDouble()
+			)
+			setCenter(startPoint)
+		}
+	}
+
+	override fun onResume() {
+		super.onResume()
+		binding.map.onResume()
+		locationOverlay.enableMyLocation()
+		context?.let { ctx ->
+			ctx.getSharedPreferences("shp", MODE_PRIVATE).let {
+				Configuration.getInstance()
+					.load(ctx, it)
+				centreMap(it)
+			}
+		}
+	}
+
+	override fun onPause() {
+		super.onPause()
+		binding.map.onPause()
+		locationOverlay.disableMyLocation()
+		val centre = binding.map.mapCenter
+		context?.let { ctx ->
+			ctx.getSharedPreferences("shp", MODE_PRIVATE).edit(true) {
+				this.putFloat("mapCentreLat", centre.latitude.toFloat())
+				this.putFloat("mapCentreLon", centre.longitude.toFloat())
+				this.putFloat("mapZoom", binding.map.zoomLevelDouble.toFloat())
+			}
+		}
+		handler.removeCallbacks(workRunnable)
+	}
+
+	override fun onDestroyView() {
+		super.onDestroyView()
+		maybeBinding = null
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..3a22298fe73acead5ecb23f43b9c171fe5c6deee
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/map/MapViewModel.kt
@@ -0,0 +1,170 @@
+package xyz.apiote.bimba.czwek.dashboard.ui.map
+
+import android.content.ActivityNotFoundException
+import android.content.Intent
+import android.net.ConnectivityManager
+import android.net.Uri
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.TextView
+import android.widget.Toast
+import androidx.constraintlayout.widget.Group
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import kotlinx.coroutines.launch
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.*
+import xyz.apiote.bimba.czwek.departures.DeparturesActivity
+
+class MapViewModel : ViewModel() {
+
+	private val _locatables = MutableLiveData<List<Locatable>>()
+	val locatables: MutableLiveData<List<Locatable>> = _locatables
+
+	fun getLocatablesIn(cm: ConnectivityManager, server: Server, bl: PositionV1, tr: PositionV1) {
+		viewModelScope.launch {
+			val result = xyz.apiote.bimba.czwek.api.getLocatablesIn(cm, server, bl, tr)
+			if (result.error != null) {
+				_locatables.value = listOf(ErrorLocatable(result.error.stringResource))
+				if (result.stream != null) {
+					Log.w(
+						"Map",
+						"${result.error.statusCode}, ${ErrorResponse.unmarshal(result.stream).message}"
+					)
+				} else {
+					Log.w("Map", "${result.error.statusCode}")
+				}
+				return@launch
+			} else {
+				_locatables.value = when (val response = LocatablesResponse.unmarshal(result.stream!!)) {
+					is LocatablesResponseDev -> response.locatables
+					is LocatablesResponseV1 -> response.locatables
+					else -> null
+				}
+			}
+		}
+	}
+}
+
+class MapBottomSheet(private val locatable: Locatable) : BottomSheetDialogFragment() {
+	companion object {
+		const val TAG = "MapBottomSheet"
+	}
+
+	private fun showVehicle(content: View, vehicle: VehicleV1) {
+		content.findViewById<Group>(R.id.stop_group).visibility = View.GONE
+		content.findViewById<Group>(R.id.vehicle_group).visibility = View.VISIBLE
+
+		context?.let { ctx ->
+			content.findViewById<TextView>(R.id.title).apply {
+				text = ctx.getString(R.string.vehicle_headsign, vehicle.Line.name, vehicle.Headsign)
+				contentDescription = ctx.getString(
+					R.string.vehicle_headsign_content_description,
+					vehicle.Line.name,
+					vehicle.Headsign
+				)
+			}
+			// todo units -- [3.1] settings or system-based
+			content.findViewById<TextView>(R.id.speed_text).text =
+				ctx.getString(R.string.speed_in_km_per_h, vehicle.Speed * 3.6)
+			content.findViewById<TextView>(R.id.congestion_text).text = vehicle.congestion(ctx)
+			content.findViewById<TextView>(R.id.occupancy_text).text = vehicle.occupancy(ctx)
+			content.findViewById<ImageView>(R.id.ac).visibility =
+				if (vehicle.getCapability(VehicleV1.Capability.AC)) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			content.findViewById<ImageView>(R.id.bike).visibility =
+				if (vehicle.getCapability(VehicleV1.Capability.BIKE)) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			content.findViewById<ImageView>(R.id.voice).visibility =
+				if (vehicle.getCapability(VehicleV1.Capability.VOICE)) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			content.findViewById<ImageView>(R.id.ticket).visibility =
+				if (vehicle.let {
+						it.getCapability(VehicleV1.Capability.TICKET_DRIVER) || it.getCapability(VehicleV1.Capability.TICKET_MACHINE)
+					}) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			content.findViewById<ImageView>(R.id.usb).visibility =
+				if (vehicle.getCapability(VehicleV1.Capability.USB_CHARGING)) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+		}
+	}
+
+	private fun showStop(content: View, stop: StopV1) {
+		context?.let { ctx ->
+			content.findViewById<Group>(R.id.stop_group).visibility = View.VISIBLE
+			content.findViewById<Group>(R.id.vehicle_group).visibility = View.GONE
+			content.findViewById<TextView>(R.id.title).text =
+				context?.getString(R.string.stop_title, stop.name, stop.code)
+			content.findViewById<Button>(R.id.departures_button).setOnClickListener {
+				val intent = Intent(ctx, DeparturesActivity::class.java).apply {
+					putExtra("code", stop.code)
+					putExtra("name", stop.name)
+				}
+				startActivity(intent)
+			}
+			content.findViewById<Button>(R.id.navigation_button).setOnClickListener {
+				try {
+					startActivity(
+						Intent(
+							Intent.ACTION_VIEW,
+							Uri.parse("geo:${stop.location().latitude},${stop.location().longitude}")
+						)
+					)
+				} catch (_: ActivityNotFoundException) {
+					Toast.makeText(context, ctx.getString(R.string.no_map_app), Toast.LENGTH_SHORT).show()
+				}
+			}
+
+			stop.changeOptions(ctx).let { changeOptions ->
+				content.findViewById<TextView>(R.id.change_options).apply {
+					text = changeOptions.first
+					contentDescription = changeOptions.second
+				}
+			}
+		}
+	}
+
+
+	override fun onCreateView(
+		inflater: LayoutInflater,
+		container: ViewGroup?,
+		savedInstanceState: Bundle?
+	): View {
+		val content = inflater.inflate(R.layout.map_bottom_sheet, container, false)
+		content.apply {
+			when (locatable) {
+				is VehicleV1 -> {
+					showVehicle(this, locatable)
+				}
+				is StopV1 -> {
+					showStop(this, locatable)
+				}
+			}
+		}
+		//(dialog as BottomSheetDialog).behavior.peekHeight = dpToPixelI(90f)
+
+		return content
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageFragment.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageFragment.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0e1f56ca0b9ce6d8a357cec9e38a20e5e64c97fa
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageFragment.kt
@@ -0,0 +1,42 @@
+package xyz.apiote.bimba.czwek.dashboard.ui.voyage
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import xyz.apiote.bimba.czwek.databinding.FragmentVoyageBinding
+
+class VoyageFragment : Fragment() {
+
+	private var _binding: FragmentVoyageBinding? = null
+
+	// This property is only valid between onCreateView and
+	// onDestroyView.
+	private val binding get() = _binding!!
+
+	override fun onCreateView(
+		inflater: LayoutInflater,
+		container: ViewGroup?,
+		savedInstanceState: Bundle?
+	): View {
+		val voyageViewModel =
+			ViewModelProvider(this)[VoyageViewModel::class.java]
+
+		_binding = FragmentVoyageBinding.inflate(inflater, container, false)
+		val root: View = binding.root
+
+		val textView: TextView = binding.textDashboard
+		voyageViewModel.text.observe(viewLifecycleOwner) {
+			textView.text = it
+		}
+		return root
+	}
+
+	override fun onDestroyView() {
+		super.onDestroyView()
+		_binding = null
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageViewModel.kt b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageViewModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6b1b923755b427a935e8ca9192c5c91136635b93
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/dashboard/ui/voyage/VoyageViewModel.kt
@@ -0,0 +1,13 @@
+package xyz.apiote.bimba.czwek.dashboard.ui.voyage
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+
+class VoyageViewModel : ViewModel() {
+
+	private val _text = MutableLiveData<String>().apply {
+		value = "This is voyage Fragment"
+	}
+	val text: LiveData<String> = _text
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt
new file mode 100644
index 0000000000000000000000000000000000000000..35f871c5fc86be2a7acbee7525b3d45496e97c2e
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/Departures.kt
@@ -0,0 +1,266 @@
+package xyz.apiote.bimba.czwek.departures
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.DialogInterface
+import android.content.res.Configuration.*
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.DepartureV1
+import xyz.apiote.bimba.czwek.api.VehicleV1
+import xyz.apiote.bimba.czwek.dpToPixelI
+import org.osmdroid.tileprovider.tilesource.TileSourceFactory
+import org.osmdroid.util.GeoPoint
+import org.osmdroid.views.CustomZoomButtonsController
+import org.osmdroid.views.MapView
+import org.osmdroid.views.overlay.Marker
+import org.osmdroid.views.overlay.TilesOverlay
+import org.osmdroid.views.overlay.gestures.RotationGestureOverlay
+import java.util.*
+
+
+class BimbaDepartureViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+	val root: View = itemView.findViewById(R.id.departure)
+	val lineIcon: ImageView = itemView.findViewById(R.id.line_icon)
+	val departureTime: TextView = itemView.findViewById(R.id.departure_time)
+	val lineName: TextView = itemView.findViewById(R.id.departure_line)
+	val headsign: TextView = itemView.findViewById(R.id.departure_headsign)
+
+	companion object {
+		fun bind(
+			departure: DepartureV1,
+			holder: BimbaDepartureViewHolder?,
+			context: Context?,
+			onClickListener: (DepartureV1) -> Unit
+		) {
+			holder?.root?.setOnClickListener {
+				onClickListener(departure)
+			}
+			holder?.lineIcon?.setImageBitmap(departure.vehicle.Line.icon(context!!))
+			holder?.lineIcon?.contentDescription = departure.vehicle.Line.kind.name
+			holder?.lineName?.text = departure.vehicle.Line.name
+			holder?.headsign?.text = context?.getString(R.string.departure_headsign, departure.vehicle.Headsign)
+			holder?.headsign?.contentDescription =
+				context?.getString(R.string.departure_headsign_content_description, departure.vehicle.Headsign)
+
+			holder?.departureTime?.text = departure.statusText(context)
+		}
+	}
+}
+
+class BimbaDeparturesAdapter(
+	private val inflater: LayoutInflater,
+	private val context: Context?,
+	private var departures: List<DepartureV1>,
+	private val onClickListener: ((DepartureV1) -> Unit)
+) :
+	RecyclerView.Adapter<BimbaDepartureViewHolder>() {
+
+	private var departuresPositions: MutableMap<String, Int> = HashMap()
+
+	init {
+		departures.forEachIndexed { i, departure ->
+			departuresPositions[departure.ID] = i
+		}
+	}
+
+	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BimbaDepartureViewHolder {
+		val rowView = inflater.inflate(R.layout.departure, parent, false)
+		return BimbaDepartureViewHolder(rowView)
+	}
+
+	override fun onBindViewHolder(holder: BimbaDepartureViewHolder, position: Int) {
+		BimbaDepartureViewHolder.bind(departures[position], holder, context, onClickListener)
+	}
+
+	override fun getItemCount(): Int = departures.size
+
+	fun get(ID: String): DepartureV1? {
+		val position = departuresPositions[ID]
+		return if (position == null) {
+			null
+		} else {
+			departures[position]
+		}
+	}
+
+	@SuppressLint("NotifyDataSetChanged") // todo [3.1] DiffUtil
+	fun update(departures: List<DepartureV1>) {
+		val newPositions: MutableMap<String, Int> = HashMap()
+		departures.forEachIndexed { i, departure ->
+			newPositions[departure.ID] = i
+		}
+
+		this.departures = departures
+		departuresPositions = newPositions
+		notifyDataSetChanged()
+	}
+}
+
+class DepartureBottomSheet(private var departure: DepartureV1) : BottomSheetDialogFragment() {
+	companion object {
+		const val TAG = "DepartureBottomSheet"
+	}
+
+	private var cancelCallback: (() -> Unit)? = null
+
+	fun setOnCancel(callback: () -> Unit) {
+		cancelCallback = callback
+	}
+
+	override fun onCancel(dialog: DialogInterface) {
+		super.onCancel(dialog)
+		cancelCallback?.let { it() }
+	}
+
+	fun departureID(): String {
+		return departure.ID
+	}
+
+	fun update(departure: DepartureV1) {
+		this.departure = departure
+		this.view?.let { context?.let { ctx -> setContent(it, ctx) } }
+	}
+
+	private fun setContent(view: View, ctx: Context) {
+		view.apply {
+			findViewById<TextView>(R.id.time).text = departure.timeString(ctx)
+
+			findViewById<ImageView>(R.id.rt_icon).apply {
+				visibility = if (departure.isRealtime) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			}
+			findViewById<ImageView>(R.id.wheelchair_icon).apply {
+				visibility = if (departure.vehicle.let {
+						it.getCapability(VehicleV1.Capability.LOW_FLOOR) || it.getCapability(VehicleV1.Capability.LOW_ENTRY) || it.getCapability(
+							VehicleV1.Capability.RAMP
+						)
+					}) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			}
+
+			findViewById<TextView>(R.id.line).apply {
+				contentDescription = getString(
+					R.string.vehicle_headsign_content_description,
+					departure.vehicle.Line.name,
+					departure.vehicle.Headsign
+				)
+				text = getString(R.string.vehicle_headsign, departure.vehicle.Line.name, departure.vehicle.Headsign)
+			}
+
+			findViewById<TextView>(R.id.boarding_text).text = departure.boardingText(ctx)
+			// todo units -- [3.1] settings or system-based
+			findViewById<TextView>(R.id.speed_text).text =
+				getString(R.string.speed_in_km_per_h, departure.vehicle.Speed * 3.6)
+			findViewById<TextView>(R.id.congestion_text).text = departure.vehicle.congestion(ctx)
+			findViewById<TextView>(R.id.occupancy_text).text = departure.vehicle.occupancy(ctx)
+
+			findViewById<ImageView>(R.id.ac).visibility =
+				if (departure.vehicle.getCapability(VehicleV1.Capability.AC)) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			findViewById<ImageView>(R.id.bike).visibility =
+				if (departure.vehicle.getCapability(VehicleV1.Capability.BIKE)) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			findViewById<ImageView>(R.id.voice).visibility =
+				if (departure.vehicle.getCapability(VehicleV1.Capability.VOICE)) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			findViewById<ImageView>(R.id.ticket).visibility =
+				if (departure.vehicle.let {
+						it.getCapability(VehicleV1.Capability.TICKET_DRIVER) || it.getCapability(VehicleV1.Capability.TICKET_MACHINE)
+					}) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			findViewById<ImageView>(R.id.usb).visibility =
+				if (departure.vehicle.getCapability(VehicleV1.Capability.USB_CHARGING)) {
+					View.VISIBLE
+				} else {
+					View.GONE
+				}
+			findViewById<MapView>(R.id.map).let { map ->
+				if (departure.vehicle.Position.isZero()) {
+					map.visibility = View.GONE
+					return@let
+				}
+				map.controller.apply { // todo[3.1] glide to centre, not jump
+					setZoom(19.0f.toDouble())
+					setCenter(
+						GeoPoint(
+							departure.vehicle.location().latitude,
+							departure.vehicle.location().longitude
+						)
+					)
+				}
+
+				map.overlays.removeAll { marker ->
+					marker is Marker
+				}
+				val marker = Marker(map).apply {
+					position =
+						GeoPoint(departure.vehicle.location().latitude, departure.vehicle.location().longitude)
+					setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
+					icon = context?.let { ctx -> departure.vehicle.icon(ctx, 2f) }
+					setOnClickListener {}
+				}
+				map.overlays.add(marker)
+				map.invalidate()
+			}
+		}
+	}
+
+	@SuppressLint("ClickableViewAccessibility")
+	override fun onCreateView(
+		inflater: LayoutInflater,
+		container: ViewGroup?,
+		savedInstanceState: Bundle?
+	): View {
+		val content = inflater.inflate(R.layout.departure_bottom_sheet, container, false)
+
+		context?.let { ctx ->
+			content.apply {
+				findViewById<MapView>(R.id.map).let { map ->
+					map.setTileSource(TileSourceFactory.MAPNIK)
+					if (((context?.resources?.configuration?.uiMode ?: UI_MODE_NIGHT_UNDEFINED)
+										and UI_MODE_NIGHT_MASK) == UI_MODE_NIGHT_YES
+					) {
+						map.overlayManager.tilesOverlay.setColorFilter(TilesOverlay.INVERT_COLORS)
+					}
+					map.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
+					map.setOnTouchListener { _, _ -> true }
+					map.setMultiTouchControls(true)
+					map.overlays.add(RotationGestureOverlay(map).apply { isEnabled = true })
+				}
+
+				setContent(this, ctx)
+
+				(dialog as BottomSheetDialog).behavior.peekHeight = dpToPixelI(180f)
+
+			}
+		}
+		return content
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a8813189a98bdebfaccbc5705bd3c0a1863d8049
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/departures/DeparturesActivity.kt
@@ -0,0 +1,154 @@
+package xyz.apiote.bimba.czwek.departures
+
+import android.content.Context
+import android.content.Intent
+import android.net.ConnectivityManager
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.util.Log
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.content.res.ResourcesCompat
+import androidx.core.view.WindowCompat
+import androidx.recyclerview.widget.LinearLayoutManager
+import kotlinx.coroutines.*
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.*
+import xyz.apiote.bimba.czwek.databinding.ActivityDeparturesBinding
+
+class DeparturesActivity : AppCompatActivity() {
+	private var _binding: ActivityDeparturesBinding? = null
+	private val binding get() = _binding!!
+
+	private lateinit var adapter: BimbaDeparturesAdapter
+
+	private val handler = Handler(Looper.getMainLooper())
+	private var runnable = Runnable {}
+
+	private var openBottomSheet: DepartureBottomSheet? = null
+
+	override fun onCreate(savedInstanceState: Bundle?) {
+		super.onCreate(savedInstanceState)
+		_binding = ActivityDeparturesBinding.inflate(layoutInflater)
+		setContentView(binding.root)
+
+		binding.collapsingLayout.apply {
+			title = getName()
+			val tf = ResourcesCompat.getFont(this@DeparturesActivity, R.font.yellowcircle8)
+			setCollapsedTitleTypeface(tf)
+			setExpandedTitleTypeface(tf)
+		}
+
+		binding.departuresRecycler.layoutManager = LinearLayoutManager(this)
+		adapter = BimbaDeparturesAdapter(layoutInflater, this, listOf()) {
+			DepartureBottomSheet(it).apply {
+				show(supportFragmentManager, DepartureBottomSheet.TAG)
+				openBottomSheet = this
+				setOnCancel { openBottomSheet = null }
+			}
+		}
+		binding.departuresRecycler.adapter = adapter
+		WindowCompat.setDecorFitsSystemWindows(window, false)
+	}
+
+	override fun onResume() {
+		super.onResume()
+		getDepartures()
+	}
+
+	override fun onPause() {
+		super.onPause()
+		handler.removeCallbacks(runnable)
+	}
+
+	private fun getName(): String {
+		return when (intent?.action) {
+			Intent.ACTION_VIEW -> getCode()
+			null -> intent?.extras?.getString("name") ?: ""
+			else -> ""
+		}
+	}
+
+	private fun getCode(): String {
+		@Suppress("SpellCheckingInspection")
+		return when (intent?.action) {
+			Intent.ACTION_VIEW -> intent?.data?.getQueryParameter("przystanek") ?: ""
+			null -> intent?.extras?.getString("code") ?: ""
+			else -> ""
+		}
+	}
+
+	private fun getDepartures() {
+		val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+		MainScope().launch {
+			val result = getDepartures(
+				cm,
+				Server.get(this@DeparturesActivity), getCode()
+			)
+
+			if (result.error != null) {
+				showError(result.error)
+				if (result.stream != null) {
+					val response = ErrorResponse.unmarshal(result.stream)
+					Log.w("Departures", "${result.error.statusCode}, ${response.message}")
+				} else {
+					Log.w(
+						"Departures",
+						"${result.error.statusCode}, ${getString(result.error.stringResource)}"
+					)
+				}
+				return@launch
+			}
+			val (departures, stop) = when (val response = DeparturesResponse.unmarshal(result.stream!!)) {
+				is DeparturesResponseDev -> Pair(response.departures, response.stop)
+				is DeparturesResponseV1 -> Pair(response.departures, response.stop)
+				else -> Pair(null, null)
+			}
+			updateItems(departures!!, stop!!)
+			openBottomSheet?.departureID()?.let { adapter.get(it) }?.let { openBottomSheet?.update(it) }
+		}
+		handler.removeCallbacks(runnable)
+		runnable = Runnable { getDepartures() }
+		handler.postDelayed(runnable, 30 * 1000)
+	}
+
+	private fun showError(error: Error) {
+		binding.departuresProgress.visibility = View.GONE
+		binding.departuresRecycler.visibility = View.GONE
+		binding.errorImage.visibility = View.VISIBLE
+		binding.errorText.visibility = View.VISIBLE
+
+		binding.errorText.text = getString(error.stringResource)
+		binding.errorImage.setImageDrawable(AppCompatResources.getDrawable(this, error.imageResource))
+	}
+
+	private fun updateItems(departures: List<DepartureV1>, stop: StopV1) {
+		binding.departuresProgress.visibility = View.GONE
+		adapter.update(departures)
+		binding.collapsingLayout.apply {
+			title = stop.name
+		}
+		if (departures.isEmpty()) {
+			binding.errorImage.visibility = View.VISIBLE
+			binding.errorText.visibility = View.VISIBLE
+			binding.departuresRecycler.visibility = View.GONE
+
+			binding.errorText.text = getString(R.string.no_departures)
+			binding.errorImage.setImageDrawable(
+				AppCompatResources.getDrawable(
+					this,
+					R.drawable.error_search
+				)
+			)
+		} else {
+			binding.departuresOverlay.visibility = View.GONE
+			binding.errorImage.visibility = View.GONE
+			binding.errorText.visibility = View.GONE
+			binding.departuresRecycler.visibility = View.VISIBLE
+		}
+		// todo [3.1] alerts
+		// todo [3.1] stop info
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/FirstRunActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/FirstRunActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0b82651e9a1acf4f7bfa8a20b80a4aae3fcda946
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/FirstRunActivity.kt
@@ -0,0 +1,23 @@
+package xyz.apiote.bimba.czwek.onboarding
+
+import android.content.Intent
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import xyz.apiote.bimba.czwek.dashboard.MainActivity
+
+class FirstRunActivity : AppCompatActivity() {
+	override fun onCreate(savedInstanceState: Bundle?) {
+		installSplashScreen()
+		super.onCreate(savedInstanceState)
+
+		val preferences = getSharedPreferences("shp", MODE_PRIVATE)
+		val intent = if (preferences.getBoolean("firstRun", true)) {
+			Intent(this, OnboardingActivity::class.java)
+		} else {
+			Intent(this, MainActivity::class.java)
+		}
+		startActivity(intent)
+		finish()
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/OnboardingActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/OnboardingActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4d5f9e20752b529f3885d9155f26630118633c94
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/onboarding/OnboardingActivity.kt
@@ -0,0 +1,73 @@
+package xyz.apiote.bimba.czwek.onboarding
+
+import android.content.Intent
+import android.graphics.Typeface
+import android.os.Bundle
+import android.text.Spannable
+import android.text.SpannableStringBuilder
+import android.text.style.RelativeSizeSpan
+import android.text.style.StyleSpan
+import android.widget.Button
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.databinding.ActivityOnboardingBinding
+import xyz.apiote.bimba.czwek.settings.ServerChooserActivity
+
+class OnboardingActivity : AppCompatActivity() {
+	private var _binding: ActivityOnboardingBinding? = null
+	private val binding get() = _binding!!
+
+	private val activityLauncher =
+		registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+			if (!getSharedPreferences("shp", MODE_PRIVATE).getBoolean("firstRun", true)) {
+				finish()
+			}
+		}
+
+	override fun onCreate(savedInstanceState: Bundle?) {
+		super.onCreate(savedInstanceState)
+		_binding = ActivityOnboardingBinding.inflate(layoutInflater)
+		setContentView(binding.root)
+
+
+		prepareButton(
+			binding.buttonSimple,
+			getString(R.string.onboarding_simple),
+			getString(R.string.onboarding_simple_action),
+			true
+		)
+		prepareButton(
+			binding.buttonAdvanced,
+			getString(R.string.onboarding_advanced),
+			getString(R.string.onboarding_advanced_action),
+			false
+		)
+	}
+
+	private fun prepareButton(button: Button, title: String, description: String, simple: Boolean) {
+		button.text = SpannableStringBuilder().apply {
+			append(
+				title,
+				StyleSpan(Typeface.BOLD),
+				Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+			)
+			append("\n")
+			append(
+				description,
+				RelativeSizeSpan(.75f),
+				Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
+			)
+		}
+		button.setOnClickListener {
+			moveOn(simple)
+		}
+	}
+
+	private fun moveOn(simple: Boolean) {
+		val intent = Intent(this, ServerChooserActivity::class.java).apply {
+			putExtra("simple", simple)
+		}
+		activityLauncher.launch(intent)
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/search/Results.kt b/app/src/main/java/xyz/apiote/bimba/czwek/search/Results.kt
new file mode 100644
index 0000000000000000000000000000000000000000..81cc5bbe9e2f9f1759cfbb9c76c7c70a185049b4
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/search/Results.kt
@@ -0,0 +1,133 @@
+package xyz.apiote.bimba.czwek.search
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.mancj.materialsearchbar.adapter.SuggestionsAdapter
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.Line
+import xyz.apiote.bimba.czwek.api.QueryableV1
+import xyz.apiote.bimba.czwek.api.StopV1
+
+class BimbaViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+	val root: View = itemView.findViewById(R.id.suggestion)
+	val icon: ImageView = itemView.findViewById(R.id.suggestion_image)
+	val title: TextView = itemView.findViewById(R.id.suggestion_title)
+	val description: TextView = itemView.findViewById(R.id.suggestion_description)
+
+	companion object {
+		fun bind(
+			queryable: QueryableV1,
+			holder: BimbaViewHolder?,
+			context: Context?,
+			onClickListener: (QueryableV1) -> Unit
+		) {
+			when (queryable) {
+				is StopV1 -> bindStop(queryable, holder, context)
+				//is Line -> bindLine(queryable, holder, context)
+			}
+			holder?.root?.setOnClickListener {
+				onClickListener(queryable)
+			}
+		}
+
+		private fun bindStop(stop: StopV1, holder: BimbaViewHolder?, context: Context?) {
+			holder?.icon?.apply {
+				setImageDrawable(stop.icon(context!!))
+				contentDescription = context.getString(R.string.stop_content_description)
+			}
+			holder?.title?.text = context?.getString(R.string.stop_title, stop.name, stop.code)
+			context?.let {
+				stop.changeOptions(it).let { changeOptions ->
+					holder?.description?.apply {
+						text = changeOptions.first
+						contentDescription = changeOptions.second
+					}
+				}
+			}
+		}
+
+		private fun bindLine(line: Line, holder: BimbaViewHolder?, context: Context?) {
+			holder?.icon?.apply {
+				setImageBitmap(line.icon(context!!))
+				contentDescription = line.type.name
+				colorFilter = null
+			}
+			holder?.title?.text = line.name
+			holder?.description?.text = context?.getString(
+				R.string.line_headsigns,
+				line.headsignsThere.joinToString { it },
+				line.headsignsBack.joinToString { it })
+			holder?.description?.contentDescription = context?.getString(
+				R.string.line_headsigns_content_description,
+				line.headsignsThere.joinToString { it },
+				line.headsignsBack.joinToString { it })
+		}
+	}
+}
+
+interface Adapter {
+	fun createViewHolder(
+		inflater: LayoutInflater,
+		layout: Int,
+		parent: ViewGroup
+	): BimbaViewHolder {
+		val rowView = inflater.inflate(layout, parent, false)
+		return BimbaViewHolder(rowView)
+	}
+
+	fun bindSuggestionHolder(
+		queryable: QueryableV1,
+		holder: BimbaViewHolder?,
+		context: Context?,
+		onClickListener: (QueryableV1) -> Unit
+	) {
+		BimbaViewHolder.bind(queryable, holder, context, onClickListener)
+	}
+}
+
+class BimbaResultsAdapter(
+	private val inflater: LayoutInflater,
+	private val context: Context?,
+	private var queryables: List<QueryableV1>,
+	private val onClickListener: ((QueryableV1) -> Unit)
+) :
+	RecyclerView.Adapter<BimbaViewHolder>(), Adapter {
+	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BimbaViewHolder {
+		return createViewHolder(inflater, R.layout.result, parent)
+	}
+
+	override fun onBindViewHolder(holder: BimbaViewHolder, position: Int) {
+		bindSuggestionHolder(queryables[position], holder, context, onClickListener)
+	}
+
+	override fun getItemCount(): Int = queryables.size
+
+	@SuppressLint("NotifyDataSetChanged") // todo [3.1] DiffUtil
+	fun update(queryables: List<QueryableV1>) {
+		this.queryables = queryables
+		notifyDataSetChanged()
+	}
+}
+
+class BimbaSuggestionsAdapter(
+	inflater: LayoutInflater,
+	private val context: Context?,
+	private val onClickListener: ((QueryableV1) -> Unit)
+) :
+	SuggestionsAdapter<QueryableV1, BimbaViewHolder>(inflater), Adapter {
+	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BimbaViewHolder {
+		return createViewHolder(layoutInflater, R.layout.suggestion, parent)
+	}
+
+	override fun getSingleViewHeight(): Int = 72
+
+	override fun onBindSuggestionHolder(queryable: QueryableV1, holder: BimbaViewHolder?, pos: Int) {
+		bindSuggestionHolder(queryable, holder, context, onClickListener)
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0bb34efb22825f913e597157e6d40d025455559b
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/search/ResultsActivity.kt
@@ -0,0 +1,198 @@
+package xyz.apiote.bimba.czwek.search
+
+import android.content.Context
+import android.content.Intent
+import android.location.Location
+import android.location.LocationListener
+import android.location.LocationManager
+import android.net.ConnectivityManager
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.util.Log
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.view.WindowCompat
+import androidx.recyclerview.widget.LinearLayoutManager
+import kotlinx.coroutines.*
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.*
+import xyz.apiote.bimba.czwek.databinding.ActivityResultsBinding
+import xyz.apiote.bimba.czwek.departures.DeparturesActivity
+import java.io.InputStream
+
+class ResultsActivity : AppCompatActivity(), LocationListener {
+	enum class Mode {
+		MODE_LOCATION, MODE_SEARCH
+	}
+
+	private var _binding: ActivityResultsBinding? = null
+	private val binding get() = _binding!!
+
+	private lateinit var adapter: BimbaResultsAdapter
+
+	private val handler = Handler(Looper.getMainLooper())
+	private var runnable = Runnable {}
+
+	override fun onCreate(savedInstanceState: Bundle?) {
+		super.onCreate(savedInstanceState)
+		_binding = ActivityResultsBinding.inflate(layoutInflater)
+		setContentView(binding.root)
+
+		binding.resultsRecycler.layoutManager = LinearLayoutManager(this)
+		adapter = BimbaResultsAdapter(layoutInflater, this, listOf()) {
+			when (it) {
+				is StopV1 -> {
+					val intent = Intent(this, DeparturesActivity::class.java).apply {
+						putExtra("code", it.code)
+						putExtra("name", it.name)
+					}
+					startActivity(intent)
+				}
+				is Line -> {
+					TODO("[3.1] start line graph activity")
+				}
+			}
+		}
+		binding.resultsRecycler.adapter = adapter
+		setSupportActionBar(binding.topAppBar)
+
+		WindowCompat.setDecorFitsSystemWindows(window, false)
+
+		@Suppress("DEPRECATION")  // fixme later getSerializable in API>=33
+		when (intent.extras?.get("mode")) {
+			Mode.MODE_LOCATION -> {
+				supportActionBar?.title = getString(R.string.stops_nearby)
+				locate()
+			}
+			Mode.MODE_SEARCH -> {
+				val query = intent.extras?.getString("query")!!
+				supportActionBar?.title = getString(R.string.results_for, query)
+				getQueryablesByQuery(Server.get(this), query)
+			}
+		}
+	}
+
+	private fun locate() {
+		try {
+			val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
+			locationManager.requestLocationUpdates(
+				LocationManager.GPS_PROVIDER, 1000 * 60 * 10, 100f, this
+			)
+			handler.removeCallbacks(runnable)
+			runnable = Runnable {
+				showError(Error(0, R.string.error_gps, R.drawable.error_gps))
+			}
+			handler.postDelayed(runnable, 60 * 1000)
+			locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
+				?.let { onLocationChanged(it) }
+		} catch (_: SecurityException) {
+			// this won’t happen because we don’t start this activity without location permission
+		}
+	}
+
+	override fun onLocationChanged(location: Location) {
+		handler.removeCallbacks(runnable)
+		getQueryablesByLocation(Server.get(this), PositionV1(location.latitude, location.longitude))
+	}
+
+	override fun onResume() {
+		super.onResume()
+		@Suppress("DEPRECATION")  // fixme later getSerializable in API>=33
+		if (intent.extras?.get("mode") == Mode.MODE_LOCATION) {
+			locate()
+		}
+	}
+
+	override fun onPause() {
+		super.onPause()
+		val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
+		locationManager.removeUpdates(this)
+		handler.removeCallbacks(runnable)
+	}
+
+	override fun onDestroy() {
+		super.onDestroy()
+		val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
+		locationManager.removeUpdates(this)
+		handler.removeCallbacks(runnable)
+	}
+
+	private fun getQueryablesByQuery(server: Server, query: String) {
+		val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+		MainScope().launch {
+			val result = queryQueryables(cm, server, query)
+			if (result.error != null) {
+				if (result.stream != null) {
+					val response = ErrorResponse.unmarshal(result.stream)
+					Log.w("Results", "${result.error.statusCode}, ${response.message}")
+				} else {
+					Log.w(
+						"Results",
+						"${result.error.statusCode}, ${getString(result.error.stringResource)}"
+					)
+				}
+				showError(result.error)
+			} else {
+				updateItems(unmarshallQueryablesResponse(result.stream!!)!!)
+			}
+		}
+	}
+
+	private fun getQueryablesByLocation(server: Server, position: PositionV1) {
+		val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+		MainScope().launch {
+			val result = locateQueryables(cm, server, position)
+			if (result.error != null) {
+				Log.e("Results.location", "$result")
+				showError(result.error)
+			} else {
+				updateItems(unmarshallQueryablesResponse(result.stream!!)!!)
+			}
+		}
+	}
+
+	private fun showError(error: Error) {
+		binding.resultsProgress.visibility = View.GONE
+		binding.resultsRecycler.visibility = View.GONE
+		binding.errorImage.visibility = View.VISIBLE
+		binding.errorText.visibility = View.VISIBLE
+
+		binding.errorText.text = getString(error.stringResource)
+		binding.errorImage.setImageDrawable(AppCompatResources.getDrawable(this, error.imageResource))
+	}
+
+	private fun updateItems(queryables: List<QueryableV1>) {
+		binding.resultsProgress.visibility = View.GONE
+		adapter.update(queryables)
+		if (queryables.isEmpty()) {
+			binding.errorImage.visibility = View.VISIBLE
+			binding.errorText.visibility = View.VISIBLE
+			binding.resultsRecycler.visibility = View.GONE
+
+			binding.errorText.text = getString(R.string.error_404)
+			binding.errorImage.setImageDrawable(
+				AppCompatResources.getDrawable(
+					this,
+					R.drawable.error_search
+				)
+			)
+		} else {
+			binding.resultsOverlay.visibility = View.GONE
+			binding.errorImage.visibility = View.GONE
+			binding.errorText.visibility = View.GONE
+			binding.resultsRecycler.visibility = View.VISIBLE
+		}
+	}
+
+	private suspend fun unmarshallQueryablesResponse(stream: InputStream): List<QueryableV1>? {
+		return withContext(Dispatchers.IO) {
+			when (val response = QueryablesResponse.unmarshal(stream)) {
+				is QueryablesResponseDev -> response.queryables
+				is QueryablesResponseV1 -> response.queryables
+				else -> null
+			}
+		}
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..80c0975d04174d0958a97d6e5f3f03342c3ea17f
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/settings/ServerChooserActivity.kt
@@ -0,0 +1,155 @@
+package xyz.apiote.bimba.czwek.settings
+
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.net.ConnectivityManager
+import android.os.Bundle
+import android.util.Log
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.content.edit
+import androidx.core.widget.addTextChangedListener
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import org.yaml.snakeyaml.error.YAMLException
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.Bimba
+import xyz.apiote.bimba.czwek.api.Server
+import xyz.apiote.bimba.czwek.api.TrafficFormatException
+import xyz.apiote.bimba.czwek.api.getBimba
+import xyz.apiote.bimba.czwek.databinding.ActivityServerChooserBinding
+import xyz.apiote.bimba.czwek.settings.feeds.FeedChooserActivity
+
+class ServerChooserActivity : AppCompatActivity() {
+	private var _binding: ActivityServerChooserBinding? = null
+	private val binding get() = _binding!!
+
+	private val activityLauncher =
+		registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
+			if (!preferences.getBoolean("inFeedsTransaction", true)) {
+				finish()
+			}
+		}
+
+	private lateinit var preferences: SharedPreferences
+
+	override fun onCreate(savedInstanceState: Bundle?) {
+		super.onCreate(savedInstanceState)
+		preferences = getSharedPreferences("shp", MODE_PRIVATE)
+
+		if (intent.getBooleanExtra("simple", false)) {
+			setServer("bimba.apiote.xyz", "")
+			checkServer(true)
+		} else {
+
+			_binding = ActivityServerChooserBinding.inflate(layoutInflater)
+			setContentView(binding.root)
+
+			preferences.edit(true) {
+				putBoolean("inFeedsTransaction", true)
+			}
+
+			binding.button.isEnabled = false
+			binding.serverField.editText!!.addTextChangedListener { editable ->
+				binding.button.isEnabled = !editable.isNullOrBlank()
+			}
+
+			if (!preferences.getBoolean("firstRun", true)) {
+				Server.get(this).let { server ->
+					binding.serverField.editText!!.setText(server.host)
+					binding.tokenField.editText!!.setText(server.token)
+				}
+			}
+
+			binding.button.setOnClickListener {
+				setServer(
+					binding.serverField.editText!!.text.toString(),
+					binding.tokenField.editText!!.text.toString()
+				)
+				checkServer(false)
+			}
+		}
+	}
+
+	private fun showDialog(
+		title: Int, description: Int, icon: Int, onPositive: (() -> Unit)?
+	) {
+		MaterialAlertDialogBuilder(this).setIcon(AppCompatResources.getDrawable(this, icon))
+			.setTitle(getString(title)).setMessage(getString(description))
+			.setNegativeButton(resources.getString(R.string.cancel)) { _, _ -> }.apply {
+				if (onPositive != null) {
+					setPositiveButton(resources.getString(R.string.cont)) { _, _ ->
+						onPositive()
+					}
+				}
+			}.show()
+	}
+
+	private fun checkServer(isSimple: Boolean) {
+		val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+		MainScope().launch {
+			val result = getBimba(cm, Server.get(this@ServerChooserActivity))
+			if (result.error != null) {
+				showDialog(R.string.error, result.error.stringResource, result.error.imageResource, null)
+				Log.w(
+					"ServerChooser", "${result.error.statusCode}, ${getString(result.error.stringResource)}"
+				)
+				return@launch
+			}
+			val bimba = try {
+				withContext(Dispatchers.IO) {
+					Bimba.unmarshal(result.stream!!)
+				}
+			} catch (e: YAMLException) {
+				Log.w("ServerChooser", e.message ?: "YAML error")
+				showDialog(R.string.error, R.string.error_traffic_spec, R.drawable.error_server, null)
+				return@launch
+			} catch (e: TrafficFormatException) {
+				Log.w("ServerChooser", e.message)
+				showDialog(R.string.error, R.string.error_traffic_spec, R.drawable.error_server, null)
+				return@launch
+			}
+			val token = preferences.getString("token", "")
+			updateServer(bimba.servers[0]["url"]!!)
+
+			if (bimba.isPrivate() && token == "") {
+				showDialog(R.string.error, R.string.server_private_question, R.drawable.error_sec, null)
+				return@launch
+			}
+			if (bimba.isRateLimited() && token == "" && !isSimple) {
+				showDialog(
+					R.string.rate_limit, R.string.server_rate_limited_question, R.drawable.error_limit
+				) {
+					runFeedsActivity()
+				}
+				return@launch
+			}
+			runFeedsActivity()
+		}
+	}
+
+	private fun setServer(hostname: String, token: String) {
+		preferences.edit(true) {
+			putString("host", hostname)
+			putString("token", token)
+		}
+	}
+
+	private fun updateServer(apiPath: String) {
+		preferences.edit(true) {
+			putString("apiPath", apiPath)
+		}
+	}
+
+	private fun runFeedsActivity() {
+		activityLauncher.launch(Intent(this, FeedChooserActivity::class.java))
+		if (intent.getBooleanExtra("simple", false)) {
+			finish()
+		}
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedChooserActivity.kt b/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedChooserActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c7ee64b4a4e8c7615ec942ab0725ade256e0551f
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedChooserActivity.kt
@@ -0,0 +1,108 @@
+package xyz.apiote.bimba.czwek.settings.feeds
+
+import android.content.Context
+import android.content.Intent
+import android.net.ConnectivityManager
+import android.os.Bundle
+import android.util.Log
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.content.edit
+import androidx.recyclerview.widget.LinearLayoutManager
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.launch
+import xyz.apiote.bimba.czwek.api.*
+import xyz.apiote.bimba.czwek.dashboard.MainActivity
+import xyz.apiote.bimba.czwek.databinding.ActivityFeedChooserBinding
+
+class FeedChooserActivity : AppCompatActivity() {
+	private var _binding: ActivityFeedChooserBinding? = null
+	private val binding get() = _binding!!
+
+	private lateinit var adapter: BimbaFeedInfoAdapter
+
+	override fun onCreate(savedInstanceState: Bundle?) {
+		super.onCreate(savedInstanceState)
+		_binding = ActivityFeedChooserBinding.inflate(layoutInflater)
+		setContentView(binding.root)
+
+		setUpRecycler()
+		getServer()
+
+		binding.button.setOnClickListener {
+			moveOn()
+		}
+	}
+
+	private fun setUpRecycler() {
+		binding.resultsRecycler.layoutManager = LinearLayoutManager(this)
+		adapter = BimbaFeedInfoAdapter(layoutInflater, listOf(), this) {
+			FeedBottomSheet(it).show(supportFragmentManager, FeedBottomSheet.TAG)
+		}
+		binding.resultsRecycler.adapter = adapter
+	}
+
+	private fun getServer() {
+		binding.progress.visibility = View.VISIBLE
+		binding.resultsRecycler.visibility = View.GONE
+
+		MainScope().launch {
+			val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+			Log.i("FeedChooser", "${Server.get(this@FeedChooserActivity)}")
+			val result = getFeeds(cm, Server.get(this@FeedChooserActivity))
+			if (result.error != null) {
+				showError(result.error.imageResource, result.error.stringResource)
+				if (result.stream != null) {
+					val response = ErrorResponse.unmarshal(result.stream)
+					Log.w("FeedChooser", "${result.error.statusCode}, ${response.message}")
+				} else {
+					Log.w(
+						"FeedChooser",
+						"${result.error.statusCode}, ${getString(result.error.stringResource)}"
+					)
+				}
+				return@launch
+			}
+			val feeds = when (val response = FeedsResponse.unmarshal(result.stream!!)) {
+				is FeedsResponseDev -> response.feeds
+				is FeedsResponseV1 -> response.feeds
+				else -> null
+			}
+			updateItems(feeds!!)
+		}
+	}
+
+	private fun moveOn() {
+		val preferences = getSharedPreferences("shp", MODE_PRIVATE)
+		preferences.edit(true) {
+			putBoolean("inFeedsTransaction", false)
+		}
+		if (preferences.getBoolean("firstRun", true)) {
+			val intent = Intent(this, MainActivity::class.java)
+			startActivity(intent)
+		}
+		finish()
+	}
+
+	private fun showError(image: Int, text: Int) {
+		binding.progress.visibility = View.GONE
+		binding.resultsRecycler.visibility = View.GONE
+		binding.errorImage.apply {
+			visibility = View.VISIBLE
+			setImageDrawable(AppCompatResources.getDrawable(this@FeedChooserActivity, image))
+		}
+		binding.errorText.apply {
+			visibility = View.VISIBLE
+			setText(text)
+		}
+
+	}
+
+	private fun updateItems(feeds: List<FeedInfoV1>) {
+		binding.feedsOverlay.visibility = View.GONE
+		binding.resultsRecycler.visibility = View.VISIBLE
+		binding.button.visibility = View.VISIBLE
+		adapter.update(feeds)
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedInfos.kt b/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedInfos.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ff9d63e7b907ebbdfca83abc145d1feb02bda4aa
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/settings/feeds/FeedInfos.kt
@@ -0,0 +1,102 @@
+package xyz.apiote.bimba.czwek.settings.feeds
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Context.MODE_PRIVATE
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.core.content.edit
+import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import com.google.android.material.materialswitch.MaterialSwitch
+import xyz.apiote.bimba.czwek.R
+import xyz.apiote.bimba.czwek.api.FeedInfoV1
+
+
+class BimbaFeedInfoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+	val root: View = itemView.findViewById(R.id.feed)
+	val switch: MaterialSwitch = itemView.findViewById(R.id.feed_switch)
+	val name: TextView = itemView.findViewById(R.id.feed_name)
+
+	companion object {
+		fun bind(
+			feed: FeedInfoV1,
+			context: Context,
+			holder: BimbaFeedInfoViewHolder?,
+			onClickListener: (FeedInfoV1) -> Unit
+		) {
+			val shp = context.getSharedPreferences("shp", MODE_PRIVATE)
+			val host = shp.getString("host", "bimba.apiote.xyz")!!
+			val enabledFeeds =
+				shp.getString("${host}_feeds", "")!!.split(",").associateWith { }.toMutableMap()
+
+			holder?.root?.setOnClickListener {
+				onClickListener(feed)
+			}
+			holder?.name?.text = feed.name
+			holder?.switch?.apply {
+				isChecked = feed.id in enabledFeeds
+				setOnCheckedChangeListener { _, isChecked ->
+					if (isChecked) {
+						enabledFeeds[feed.id] = Unit
+					} else {
+						enabledFeeds.remove(feed.id)
+					}
+					shp.edit(true) {
+						putString(
+							"${host}_feeds",
+							enabledFeeds.map { it.key }.filter { it != "" }.joinToString(separator = ",")
+						)
+					}
+				}
+			}
+		}
+	}
+}
+
+class BimbaFeedInfoAdapter(
+	private val inflater: LayoutInflater,
+	private var feeds: List<FeedInfoV1>,
+	private val context: Context,
+	private val onClickListener: ((FeedInfoV1) -> Unit)
+) :
+	RecyclerView.Adapter<BimbaFeedInfoViewHolder>() {
+	override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BimbaFeedInfoViewHolder {
+		val rowView = inflater.inflate(R.layout.feedinfo, parent, false)
+		return BimbaFeedInfoViewHolder(rowView)
+	}
+
+	override fun onBindViewHolder(holder: BimbaFeedInfoViewHolder, position: Int) {
+		BimbaFeedInfoViewHolder.bind(feeds[position], context, holder, onClickListener)
+	}
+
+	override fun getItemCount(): Int = feeds.size
+
+	@SuppressLint("NotifyDataSetChanged") // todo [3.1] DiffUtil
+	fun update(items: List<FeedInfoV1>) {
+		feeds = items
+		notifyDataSetChanged()
+	}
+}
+
+class FeedBottomSheet(private var feed: FeedInfoV1) : BottomSheetDialogFragment() {
+	companion object {
+		const val TAG = "DepartureBottomSheet"
+	}
+
+	override fun onCreateView(
+		inflater: LayoutInflater,
+		container: ViewGroup?,
+		savedInstanceState: Bundle?
+	): View {
+		val content = inflater.inflate(R.layout.feed_bottom_sheet, container, false)
+		content.findViewById<TextView>(R.id.title).text = feed.name
+		content.findViewById<TextView>(R.id.description).text = feed.description
+		content.findViewById<TextView>(R.id.attribution).text = feed.attribution
+		content.findViewById<TextView>(R.id.update_time).text = feed.formatDate()
+		return content
+	}
+}
\ No newline at end of file




diff --git a/app/src/main/java/xyz/apiote/bimba/czwek/utils.kt b/app/src/main/java/xyz/apiote/bimba/czwek/utils.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a5afaa2cdb25fd6504138df76cd957a7bac1b73d
--- /dev/null
+++ b/app/src/main/java/xyz/apiote/bimba/czwek/utils.kt
@@ -0,0 +1,12 @@
+package xyz.apiote.bimba.czwek
+
+import android.content.res.Resources
+import android.util.DisplayMetrics
+import kotlin.math.roundToInt
+
+fun dpToPixel(dp: Float): Float {
+	val metrics: DisplayMetrics = Resources.getSystem().displayMetrics
+	return dp * (metrics.densityDpi / 160f)
+}
+
+fun dpToPixelI(dp: Float): Int = dpToPixel(dp).roundToInt()
\ No newline at end of file




diff --git a/app/src/main/play/en-GB/listing/featureGraphic/feature-graphic.png b/app/src/main/play/en-GB/listing/featureGraphic/feature-graphic.png
deleted file mode 100644
index 1333d62dd12eb83080efd9850179902cbe689da6..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/en-GB/listing/featureGraphic/feature-graphic.png and /dev/null differ




diff --git a/app/src/main/play/en-GB/listing/fulldescription b/app/src/main/play/en-GB/listing/fulldescription
deleted file mode 100644
index 1286c61843fc2318c517f450fc3faa935dd2104d..0000000000000000000000000000000000000000
--- a/app/src/main/play/en-GB/listing/fulldescription
+++ /dev/null
@@ -1,6 +0,0 @@
-With this app You can check the public transport timetable in Poznań agglomeration (run by ZTM Poznań), and thanks to the Virtual Monitor You can see when exactly a bus or tram will arrive.
-
-Current features:
-* checking departures by stop (based on offline timetable and Virtual Monitor),
-* creating favourite stops with next departure visible on main screen,
-* checking departures by favourite




diff --git a/app/src/main/play/en-GB/listing/icon/logo.png b/app/src/main/play/en-GB/listing/icon/logo.png
deleted file mode 100644
index 7a9bd078b1aed42188fe767423683c64a468312e..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/en-GB/listing/icon/logo.png and /dev/null differ




diff --git a/app/src/main/play/en-GB/listing/phoneScreenshots/Dash.png b/app/src/main/play/en-GB/listing/phoneScreenshots/Dash.png
deleted file mode 100644
index b3d55c2a98f3e70f19d7b97b39e7947bc9946b44..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/en-GB/listing/phoneScreenshots/Dash.png and /dev/null differ




diff --git a/app/src/main/play/en-GB/listing/phoneScreenshots/StopActivity.png b/app/src/main/play/en-GB/listing/phoneScreenshots/StopActivity.png
deleted file mode 100644
index a85d7e9dfdcb7b81b3a8a7d5097923c885356065..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/en-GB/listing/phoneScreenshots/StopActivity.png and /dev/null differ




diff --git a/app/src/main/play/en-GB/listing/phoneScreenshots/modification.png b/app/src/main/play/en-GB/listing/phoneScreenshots/modification.png
deleted file mode 100644
index 2f536117feeb2ef180b3be65e36fee4154c94e4f..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/en-GB/listing/phoneScreenshots/modification.png and /dev/null differ




diff --git a/app/src/main/play/en-GB/listing/phoneScreenshots/searchStop.png b/app/src/main/play/en-GB/listing/phoneScreenshots/searchStop.png
deleted file mode 100644
index 93683ba47b92fa3429623a0222488e0df516df93..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/en-GB/listing/phoneScreenshots/searchStop.png and /dev/null differ




diff --git a/app/src/main/play/en-GB/listing/phoneScreenshots/stopSpecify.png b/app/src/main/play/en-GB/listing/phoneScreenshots/stopSpecify.png
deleted file mode 100644
index a67350f5939563ab794be2ec1ef89be4f6f5e5f5..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/en-GB/listing/phoneScreenshots/stopSpecify.png and /dev/null differ




diff --git a/app/src/main/play/en-GB/listing/promoGraphic/promo-graphic.png b/app/src/main/play/en-GB/listing/promoGraphic/promo-graphic.png
deleted file mode 100644
index 6e15268c85de20ae2ea38d0d3cfa85aa913e4f93..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/en-GB/listing/promoGraphic/promo-graphic.png and /dev/null differ




diff --git a/app/src/main/play/en-GB/listing/shortdescription b/app/src/main/play/en-GB/listing/shortdescription
deleted file mode 100644
index 59cba7356e35c4b1d6c521a6ef2ccf0aad7663f8..0000000000000000000000000000000000000000
--- a/app/src/main/play/en-GB/listing/shortdescription
+++ /dev/null
@@ -1 +0,0 @@
-First Free Software Poznań Wandering Guide




diff --git a/app/src/main/play/en-GB/whatsnew b/app/src/main/play/en-GB/whatsnew
deleted file mode 100644
index f51e399bb993cfc28ffdb3b04ec6ee640f43bd2c..0000000000000000000000000000000000000000
--- a/app/src/main/play/en-GB/whatsnew
+++ /dev/null
@@ -1,28 +0,0 @@
-[2.2.2] – 2019-03-11
-====================
-
-Changed
--------
-
-* drop HTML formatting in PEKA messages
-
-[2.2.1] – 2019-03-04
-====================
-
-Changed
--------
-
-* white icons (low floor, tickets) in night mode
-
-[2.2.0] – 2019-02-26
-====================
-
-Added
------
-
-+ showing low floor and ticket checkouts in VM departures
-
-Changed
--------
-
-* departures empty state is semi-transparent




diff --git a/app/src/main/play/pl-PL/listing/featureGraphic/feature-graphic.png b/app/src/main/play/pl-PL/listing/featureGraphic/feature-graphic.png
deleted file mode 100644
index 932fab1b2a7e57bd6709623abc11d7b9250e7071..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/pl-PL/listing/featureGraphic/feature-graphic.png and /dev/null differ




diff --git a/app/src/main/play/pl-PL/listing/fulldescription b/app/src/main/play/pl-PL/listing/fulldescription
deleted file mode 100644
index 3ef17ffaa0a5a4859a47b32488199b00d06c4beb..0000000000000000000000000000000000000000
--- a/app/src/main/play/pl-PL/listing/fulldescription
+++ /dev/null
@@ -1,6 +0,0 @@
-Dzięki tej aplikacji możesz sprawdzić rozkład jazdy w aglomeracji poznańskiej (obsługiwany przez ZTM Poznań), a dzięki Wirtualnemu Monitorowi możesz zobaczyć, kiedy dokładnie przyjedzie autobus lub tramwaj.
-
-Aktualne funkcje:
-* sprawdzanie czasu odjazdów na przystankach (na podstawie rozkładu offline i Wirtualnego Monitora),
-* tworzenie ulubionych przystanków, które pokazują najbliższy odjazd na ekranie głównym.
-* sprawdzanie czasu odjazdów w ulubionych




diff --git a/app/src/main/play/pl-PL/listing/icon/logo.png b/app/src/main/play/pl-PL/listing/icon/logo.png
deleted file mode 100644
index 7a9bd078b1aed42188fe767423683c64a468312e..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/pl-PL/listing/icon/logo.png and /dev/null differ




diff --git a/app/src/main/play/pl-PL/listing/phoneScreenshots/Dash.png b/app/src/main/play/pl-PL/listing/phoneScreenshots/Dash.png
deleted file mode 100644
index 8293e13ec0502b1ca39633a7b8c2f497e6f2fca3..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/pl-PL/listing/phoneScreenshots/Dash.png and /dev/null differ




diff --git a/app/src/main/play/pl-PL/listing/phoneScreenshots/StopActivity.png b/app/src/main/play/pl-PL/listing/phoneScreenshots/StopActivity.png
deleted file mode 100644
index 4df78339578128289b152e676c58051fded2c12f..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/pl-PL/listing/phoneScreenshots/StopActivity.png and /dev/null differ




diff --git a/app/src/main/play/pl-PL/listing/phoneScreenshots/StopSpecify.png b/app/src/main/play/pl-PL/listing/phoneScreenshots/StopSpecify.png
deleted file mode 100644
index 67b81dc87ef810057208d330df299de0a3f9bd50..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/pl-PL/listing/phoneScreenshots/StopSpecify.png and /dev/null differ




diff --git a/app/src/main/play/pl-PL/listing/phoneScreenshots/modification.png b/app/src/main/play/pl-PL/listing/phoneScreenshots/modification.png
deleted file mode 100644
index f15b3b0ab78817a7c0ab9aeff43dcdb034e7e8cb..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/pl-PL/listing/phoneScreenshots/modification.png and /dev/null differ




diff --git a/app/src/main/play/pl-PL/listing/phoneScreenshots/searchStop.png b/app/src/main/play/pl-PL/listing/phoneScreenshots/searchStop.png
deleted file mode 100644
index a9a0b5a548af7881e9061d5a17b537debd2826a7..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/pl-PL/listing/phoneScreenshots/searchStop.png and /dev/null differ




diff --git a/app/src/main/play/pl-PL/listing/promoGraphic/promo-graphic.png b/app/src/main/play/pl-PL/listing/promoGraphic/promo-graphic.png
deleted file mode 100644
index 6e15268c85de20ae2ea38d0d3cfa85aa913e4f93..0000000000000000000000000000000000000000
Binary files a/app/src/main/play/pl-PL/listing/promoGraphic/promo-graphic.png and /dev/null differ




diff --git a/app/src/main/play/pl-PL/listing/shortdescription b/app/src/main/play/pl-PL/listing/shortdescription
deleted file mode 100644
index 647bf882f7d590a818458e81cecba6a464c2c8fe..0000000000000000000000000000000000000000
--- a/app/src/main/play/pl-PL/listing/shortdescription
+++ /dev/null
@@ -1 +0,0 @@
-Pierwszy wolny spacerownik poznański




diff --git a/app/src/main/play/pl-PL/whatsnew b/app/src/main/play/pl-PL/whatsnew
deleted file mode 100644
index 720cbfab9b37820534cd0d2878ab82129fcae1be..0000000000000000000000000000000000000000
--- a/app/src/main/play/pl-PL/whatsnew
+++ /dev/null
@@ -1,28 +0,0 @@
-[2.2.2] – 2019-03-11
-====================
-
-Changed
--------
-
-* porzucenie formatowania HTML w wiadomościach PEKA
-
-[2.2.1] – 2019-03-04
-====================
-
-Changed
--------
-
-* białe ikony (niskopodłogowy, bilety) w trybie nocnym
-
-[2.2.0] – 2019-02-26
-====================
-
-Dodane
-------
-
-+ oznaczanie odjazdów WM niskopodłogowych i z możliwością kupna biletów
-
-Zmienione
----------
-
-* pusty stan odjazdów jest półprzezroczysty




diff --git a/app/src/main/res/drawable/ac.xml b/app/src/main/res/drawable/ac.xml
new file mode 100644
index 0000000000000000000000000000000000000000..95dfbd1694a17e2a90e69a2af23b1a7116ea12cd
--- /dev/null
+++ b/app/src/main/res/drawable/ac.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M22,11h-4.17l3.24,-3.24 -1.41,-1.42L15,11h-2V9l4.66,-4.66 -1.42,-1.41L13,6.17V2h-2v4.17L7.76,2.93 6.34,4.34 11,9v2H9L4.34,6.34 2.93,7.76 6.17,11H2v2h4.17l-3.24,3.24 1.41,1.42L9,13h2v2l-4.66,4.66 1.42,1.41L11,17.83V22h2v-4.17l3.24,3.24 1.42,-1.41L13,15v-2h2l4.66,4.66 1.41,-1.42L17.83,13H22z"/>
+</vector>




diff --git a/app/src/main/res/drawable/bike.xml b/app/src/main/res/drawable/bike.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1c5af85fe1c842642c65d6ae5f592f2dfd898cda
--- /dev/null
+++ b/app/src/main/res/drawable/bike.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M18.18,10l-1.7,-4.68C16.19,4.53 15.44,4 14.6,4H12v2h2.6l1.46,4h-4.81l-0.36,-1H12V7H7v2h1.75l1.82,5H9.9c-0.44,-2.23 -2.31,-3.88 -4.65,-3.99C2.45,9.87 0,12.2 0,15c0,2.8 2.2,5 5,5c2.46,0 4.45,-1.69 4.9,-4h4.2c0.44,2.23 2.31,3.88 4.65,3.99c2.8,0.13 5.25,-2.19 5.25,-5c0,-2.8 -2.2,-5 -5,-5H18.18zM7.82,16c-0.4,1.17 -1.49,2 -2.82,2c-1.68,0 -3,-1.32 -3,-3s1.32,-3 3,-3c1.33,0 2.42,0.83 2.82,2H5v2H7.82zM14.1,14h-1.4l-0.73,-2H15C14.56,12.58 14.24,13.25 14.1,14zM19,18c-1.68,0 -3,-1.32 -3,-3c0,-0.93 0.41,-1.73 1.05,-2.28l0.96,2.64l1.88,-0.68l-0.97,-2.67c0.03,0 0.06,-0.01 0.09,-0.01c1.68,0 3,1.32 3,3S20.68,18 19,18z"/>
+</vector>




diff --git a/app/src/main/res/drawable/bus_black.xml b/app/src/main/res/drawable/bus_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e2b18a05948d28b39cd2b4bfb102cac858c738bf
--- /dev/null
+++ b/app/src/main/res/drawable/bus_black.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M4,16c0,0.88 0.39,1.67 1,2.22L5,20c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1h8v1c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1.78c0.61,-0.55 1,-1.34 1,-2.22L20,6c0,-3.5 -3.58,-4 -8,-4s-8,0.5 -8,4v10zM7.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5S6.67,14 7.5,14s1.5,0.67 1.5,1.5S8.33,17 7.5,17zM16.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM18,11L6,11L6,6h12v5z"/>
+</vector>




diff --git a/app/src/main/res/drawable/crowd.xml b/app/src/main/res/drawable/crowd.xml
new file mode 100644
index 0000000000000000000000000000000000000000..76bd1cd501a769b0b3cdda828de7d686ba8baf10
--- /dev/null
+++ b/app/src/main/res/drawable/crowd.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12,12.75c1.63,0 3.07,0.39 4.24,0.9c1.08,0.48 1.76,1.56 1.76,2.73L18,18H6l0,-1.61c0,-1.18 0.68,-2.26 1.76,-2.73C8.93,13.14 10.37,12.75 12,12.75zM4,13c1.1,0 2,-0.9 2,-2c0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2C2,12.1 2.9,13 4,13zM5.13,14.1C4.76,14.04 4.39,14 4,14c-0.99,0 -1.93,0.21 -2.78,0.58C0.48,14.9 0,15.62 0,16.43V18l4.5,0v-1.61C4.5,15.56 4.73,14.78 5.13,14.1zM20,13c1.1,0 2,-0.9 2,-2c0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2C18,12.1 18.9,13 20,13zM24,16.43c0,-0.81 -0.48,-1.53 -1.22,-1.85C21.93,14.21 20.99,14 20,14c-0.39,0 -0.76,0.04 -1.13,0.1c0.4,0.68 0.63,1.46 0.63,2.29V18l4.5,0V16.43zM12,6c1.66,0 3,1.34 3,3c0,1.66 -1.34,3 -3,3s-3,-1.34 -3,-3C9,7.34 10.34,6 12,6z"/>
+</vector>




diff --git a/app/src/main/res/drawable/departure.xml b/app/src/main/res/drawable/departure.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9bf1a5d515b626ebbfc9e9b6dcfc59240d614229
--- /dev/null
+++ b/app/src/main/res/drawable/departure.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M16,1c-2.4,0 -4.52,1.21 -5.78,3.05 0.01,-0.01 0.01,-0.02 0.02,-0.03C9.84,4 9.42,4 9,4c-4.42,0 -8,0.5 -8,4v10c0,0.88 0.39,1.67 1,2.22L2,22c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1h8v1c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1.78c0.61,-0.55 1,-1.34 1,-2.22v-3.08c3.39,-0.49 6,-3.39 6,-6.92 0,-3.87 -3.13,-7 -7,-7zM4.5,19c-0.83,0 -1.5,-0.67 -1.5,-1.5S3.67,16 4.5,16s1.5,0.67 1.5,1.5S5.33,19 4.5,19zM3,13L3,8h6c0,1.96 0.81,3.73 2.11,5L3,13zM13.5,19c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM16,13c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM16.5,4L15,4v5l3.62,2.16 0.75,-1.23 -2.87,-1.68z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_app.xml b/app/src/main/res/drawable/error_app.xml
new file mode 100644
index 0000000000000000000000000000000000000000..adaa37eb80f7276f9ac19caec2c1c8c9fca932de
--- /dev/null
+++ b/app/src/main/res/drawable/error_app.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M18,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM15.5,12c0,-1.38 1.12,-2.5 2.5,-2.5 0.42,0 0.8,0.11 1.15,0.29l-3.36,3.36c-0.18,-0.35 -0.29,-0.73 -0.29,-1.15zM18,14.5c-0.42,0 -0.8,-0.11 -1.15,-0.29l3.36,-3.36c0.18,0.35 0.29,0.73 0.29,1.15 0,1.38 -1.12,2.5 -2.5,2.5zM17,18L7,18L7,6h10v1h2L19,3c0,-1.1 -0.9,-2 -2,-2L7,1c-1.1,0 -2,0.9 -2,2v18c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2v-4h-2v1z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_gps.xml b/app/src/main/res/drawable/error_gps.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d83a38e79abe3672f08f1e811d88e184ddadc1e4
--- /dev/null
+++ b/app/src/main/res/drawable/error_gps.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06c-1.13,0.12 -2.19,0.46 -3.16,0.97l1.5,1.5C10.16,5.19 11.06,5 12,5c3.87,0 7,3.13 7,7 0,0.94 -0.19,1.84 -0.52,2.65l1.5,1.5c0.5,-0.96 0.84,-2.02 0.97,-3.15L23,13v-2h-2.06zM3,4.27l2.04,2.04C3.97,7.62 3.25,9.23 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c1.77,-0.2 3.38,-0.91 4.69,-1.98L19.73,21 21,19.73 4.27,3 3,4.27zM16.27,17.54C15.09,18.45 13.61,19 12,19c-3.87,0 -7,-3.13 -7,-7 0,-1.61 0.55,-3.09 1.46,-4.27l9.81,9.81z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_limit.xml b/app/src/main/res/drawable/error_limit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..03344fd1addcf979b8cdc1c4cb33cf699add2401
--- /dev/null
+++ b/app/src/main/res/drawable/error_limit.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M23,5.5V20c0,2.2 -1.8,4 -4,4h-7.3c-1.08,0 -2.1,-0.43 -2.85,-1.19L1,14.83c0,0 1.26,-1.23 1.3,-1.25c0.22,-0.19 0.49,-0.29 0.79,-0.29c0.22,0 0.42,0.06 0.6,0.16C3.73,13.46 8,15.91 8,15.91V4c0,-0.83 0.67,-1.5 1.5,-1.5S11,3.17 11,4v7h1V1.5C12,0.67 12.67,0 13.5,0S15,0.67 15,1.5V11h1V2.5C16,1.67 16.67,1 17.5,1S19,1.67 19,2.5V11h1V5.5C20,4.67 20.67,4 21.5,4S23,4.67 23,5.5z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_net.xml b/app/src/main/res/drawable/error_net.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dde6900202fa85a63b608e96248a012b815f8d1d
--- /dev/null
+++ b/app/src/main/res/drawable/error_net.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M23.64,7c-0.45,-0.34 -4.93,-4 -11.64,-4 -1.5,0 -2.89,0.19 -4.15,0.48L18.18,13.8 23.64,7zM17.04,15.22L3.27,1.44 2,2.72l2.05,2.06C1.91,5.76 0.59,6.82 0.36,7l11.63,14.49 0.01,0.01 0.01,-0.01 3.9,-4.86 3.32,3.32 1.27,-1.27 -3.46,-3.46z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_other.xml b/app/src/main/res/drawable/error_other.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4c7fcdbf80efb3e3fc7daebf5cf6634412ca8b0
--- /dev/null
+++ b/app/src/main/res/drawable/error_other.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_search.xml b/app/src/main/res/drawable/error_search.xml
new file mode 100644
index 0000000000000000000000000000000000000000..66931d11070e03fd2d2f20c26700a0d77a45c17a
--- /dev/null
+++ b/app/src/main/res/drawable/error_search.xml
@@ -0,0 +1,6 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5C16,5.91 13.09,3 9.5,3C6.08,3 3.28,5.64 3.03,9h2.02C5.3,6.75 7.18,5 9.5,5C11.99,5 14,7.01 14,9.5S11.99,14 9.5,14c-0.17,0 -0.33,-0.03 -0.5,-0.05v2.02C9.17,15.99 9.33,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57L14,14.71v0.79l5,4.99L20.49,19L15.5,14z"/>
+    <path android:fillColor="@android:color/white" android:pathData="M6.47,10.82l-2.47,2.47l-2.47,-2.47l-0.71,0.71l2.47,2.47l-2.47,2.47l0.71,0.71l2.47,-2.47l2.47,2.47l0.71,-0.71l-2.47,-2.47l2.47,-2.47z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_sec.xml b/app/src/main/res/drawable/error_sec.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e6842fb025a6ca3102a2f1da225a2e0048ca2f66
--- /dev/null
+++ b/app/src/main/res/drawable/error_sec.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12,2L4,5v6.09c0,5.05 3.41,9.76 8,10.91c4.59,-1.15 8,-5.86 8,-10.91V5L12,2zM15.5,14.09l-1.41,1.41L12,13.42L9.91,15.5L8.5,14.09L10.59,12L8.5,9.91L9.91,8.5L12,10.59l2.09,-2.09l1.41,1.41L13.42,12L15.5,14.09z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_server.xml b/app/src/main/res/drawable/error_server.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6fddd7413b943415429acce7c9d329dd06e2c98b
--- /dev/null
+++ b/app/src/main/res/drawable/error_server.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M11,8.17L6.49,3.66C8.07,2.61 9.96,2 12,2c5.52,0 10,4.48 10,10c0,2.04 -0.61,3.93 -1.66,5.51l-1.46,-1.46C19.59,14.87 20,13.48 20,12c0,-3.35 -2.07,-6.22 -5,-7.41V5c0,1.1 -0.9,2 -2,2h-2V8.17zM21.19,21.19l-1.41,1.41l-2.27,-2.27C15.93,21.39 14.04,22 12,22C6.48,22 2,17.52 2,12c0,-2.04 0.61,-3.93 1.66,-5.51L1.39,4.22l1.41,-1.41L21.19,21.19zM11,18c-1.1,0 -2,-0.9 -2,-2v-1l-4.79,-4.79C4.08,10.79 4,11.38 4,12c0,4.08 3.05,7.44 7,7.93V18z"/>
+</vector>




diff --git a/app/src/main/res/drawable/error_url.xml b/app/src/main/res/drawable/error_url.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a8ffe8655e79b9f68645b52061550fd59a8742d9
--- /dev/null
+++ b/app/src/main/res/drawable/error_url.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M17,7h-4v1.9h4c1.71,0 3.1,1.39 3.1,3.1 0,1.43 -0.98,2.63 -2.31,2.98l1.46,1.46C20.88,15.61 22,13.95 22,12c0,-2.76 -2.24,-5 -5,-5zM16,11h-2.19l2,2L16,13zM2,4.27l3.11,3.11C3.29,8.12 2,9.91 2,12c0,2.76 2.24,5 5,5h4v-1.9L7,15.1c-1.71,0 -3.1,-1.39 -3.1,-3.1 0,-1.59 1.21,-2.9 2.76,-3.07L8.73,11L8,11v2h2.73L13,15.27L13,17h1.73l4.01,4L20,19.74 3.27,3 2,4.27z"/>
+</vector>




diff --git a/app/src/main/res/drawable/feeds_cities.xml b/app/src/main/res/drawable/feeds_cities.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7324708d81054028bfebfd981910557dff919acb
--- /dev/null
+++ b/app/src/main/res/drawable/feeds_cities.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M15,11L15,5l-3,-3 -3,3v2L3,7v14h18L21,11h-6zM7,19L5,19v-2h2v2zM7,15L5,15v-2h2v2zM7,11L5,11L5,9h2v2zM13,19h-2v-2h2v2zM13,15h-2v-2h2v2zM13,11h-2L11,9h2v2zM13,7h-2L11,5h2v2zM19,19h-2v-2h2v2zM19,15h-2v-2h2v2z"/>
+</vector>




diff --git a/app/src/main/res/drawable/feeds_servers.xml b/app/src/main/res/drawable/feeds_servers.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4a19b1b7c5a7d45a14c3fe2b89c426917130299b
--- /dev/null
+++ b/app/src/main/res/drawable/feeds_servers.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M20,13H4c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1v-6c0,-0.55 -0.45,-1 -1,-1zM7,19c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM20,3H4c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1zM7,9c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
+</vector>




diff --git a/app/src/main/res/drawable/gps_black.xml b/app/src/main/res/drawable/gps_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..163afecbe1383daef7f8c60f9d47b953b215bff9
--- /dev/null
+++ b/app/src/main/res/drawable/gps_black.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+	android:width="24dp"
+	android:height="24dp"
+	android:tint="#000000"
+	android:viewportWidth="24"
+	android:viewportHeight="24">
+	<path
+		android:fillColor="@android:color/white"
+		android:pathData="M12,8c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06C6.83,3.52 3.52,6.83 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c4.17,-0.46 7.48,-3.77 7.94,-7.94L23,13v-2h-2.06zM12,19c-3.87,0 -7,-3.13 -7,-7s3.13,-7 7,-7 7,3.13 7,7 -3.13,7 -7,7z" />
+</vector>




diff --git a/app/src/main/res/drawable/home_black.xml b/app/src/main/res/drawable/home_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3f84525033ec8e08025d8ab4d84173f1bc47ab97
--- /dev/null
+++ b/app/src/main/res/drawable/home_black.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+	android:width="24dp"
+	android:height="24dp"
+	android:viewportWidth="24.0"
+	android:viewportHeight="24.0">
+	<path
+		android:fillColor="#FF000000"
+		android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z" />
+</vector>




diff --git a/app/src/main/res/drawable/home_outline.xml b/app/src/main/res/drawable/home_outline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0a8b6b30cdc7ce7fcdabbda270b20ac23e18ca0a
--- /dev/null
+++ b/app/src/main/res/drawable/home_outline.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+	android:width="24dp"
+	android:height="24dp"
+	android:tint="#000000"
+	android:viewportWidth="24"
+	android:viewportHeight="24">
+	<path
+		android:fillColor="@android:color/white"
+		android:pathData="M12,5.69l5,4.5V18h-2v-6H9v6H7v-7.81l5,-4.5M12,3L2,12h3v8h6v-6h2v6h6v-8h3L12,3z" />
+</vector>




diff --git a/app/src/main/res/drawable/ic_bus.xml b/app/src/main/res/drawable/ic_bus.xml
deleted file mode 100644
index e16e2597920506417f854cec25afe7cf0747dd15..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_bus.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M4,16c0,0.88 0.39,1.67 1,2.22L5,20c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1h8v1c0,0.55 0.45,1 1,1h1c0.55,0 1,-0.45 1,-1v-1.78c0.61,-0.55 1,-1.34 1,-2.22L20,6c0,-3.5 -3.58,-4 -8,-4s-8,0.5 -8,4v10zM7.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5S6.67,14 7.5,14s1.5,0.67 1.5,1.5S8.33,17 7.5,17zM16.5,17c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM18,11L6,11L6,6h12v5z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml
deleted file mode 100644
index 3775b0ea66b25b8cd834f6babf32f4a1ef4615f2..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_delete.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_departure_timetable.xml b/app/src/main/res/drawable/ic_departure_timetable.xml
deleted file mode 100644
index e91498fb185aafc77724e5a25c4a89f55c9e03cb..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_departure_timetable.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0">
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="M19,3C12,2.48 12,2.482 5,3 3.89,3 3.01,3.9 3.01,5L3,19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5C21,3.9 20.1,3 19,3ZM19,19L5,19L5,8h14z" />
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="m17,12h-5v5h5z" />
-</vector>




diff --git a/app/src/main/res/drawable/ic_departure_vm.xml b/app/src/main/res/drawable/ic_departure_vm.xml
deleted file mode 100644
index c460a7a31588a447c614289fe52ebd2fcca24fa3..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_departure_vm.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M12,4C9.11,4 6.6,5.639 5.35,8.039C2.34,8.359 -0,10.91 0,14C0,17.31 2.69,20 6,20L19,20C21.76,20 24,17.76 24,15C24,12.36 21.95,10.219 19.35,10.039C18.67,6.589 15.64,4 12,4zM4.404,10.652L5.922,10.652L7.418,15.643L8.922,10.652L10.443,10.652L8.133,17.289L6.707,17.289L4.404,10.652zM11.072,10.652L12.859,10.652L14.563,15.465L16.258,10.652L18.055,10.652L18.055,17.289L16.682,17.289L16.682,15.475L16.818,12.344L15.027,17.289L14.09,17.289L12.303,12.348L12.439,15.475L12.439,17.289L11.072,17.289L11.072,10.652z"
-        android:fillColor="@color/textDark" />
-</vector>




diff --git a/app/src/main/res/drawable/ic_download.xml b/app/src/main/res/drawable/ic_download.xml
deleted file mode 100644
index a2b16c14e56813b9d6c53f6dee2a9d82729164c0..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_download.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"
-        android:fillColor="#000000"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_error_outline.xml b/app/src/main/res/drawable/ic_error_outline.xml
deleted file mode 100644
index a07a0f90acf868ee9698d8f7b559545f4984939d..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_error_outline.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M11,15h2v2h-2zM11,7h2v6h-2zM11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_favourite.xml b/app/src/main/res/drawable/ic_favourite.xml
deleted file mode 100644
index 2b8138c8e93c98773cf50fe0f2e02b0210879a70..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_favourite.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"
-        android:fillColor="#000000"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_favourite_empty.xml b/app/src/main/res/drawable/ic_favourite_empty.xml
deleted file mode 100644
index b36536b997c2bac42f2b4b09bae0e2de03d08917..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_favourite_empty.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_info.xml b/app/src/main/res/drawable/ic_info.xml
deleted file mode 100644
index c7e6ec796e60cb7fd7c509d5dee88ad745ca0f1d..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_info.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-6h2v6zM13,9h-2L11,7h2v2z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
index 9ea90121701967a2ab3c15a770b76def16c7a050..3945c5372aa671389652eff30b20b1cdd0ae56fc 100644
--- a/app/src/main/res/drawable/ic_launcher_foreground.xml
+++ b/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -1,36 +1,40 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="108dp"
-        android:height="108dp"
-        android:viewportWidth="638.8894"
-        android:viewportHeight="638.8894">
-    <group android:translateX="173.03255"
-            android:translateY="173.03255">
-      <path
-          android:pathData="m62.962,292.5v0c-3.7,-0.9 -5.7,-3.8 -4.3,-6.5l32.3,-62.9c1.3,-2.6 5.5,-4 9.2,-3v0c3.7,0.9 5.7,3.8 4.3,6.5L72.162,289.5c-1.3,2.6 -5.4,4 -9.2,3z"
-          android:fillColor="#54AF39"/>
-      <path
-          android:pathData="m229.662,292.5v0c3.7,-0.9 5.7,-3.8 4.3,-6.5l-32.3,-62.9c-1.3,-2.6 -5.5,-4 -9.2,-3v0c-3.7,0.9 -5.7,3.8 -4.3,6.5l32.3,62.9c1.3,2.6 5.5,4 9.2,3z"
-          android:fillColor="#54AF39"/>
-      <path
-          android:pathData="m151.362,36.9 l-0.6,0.2c-1.8,0.7 -3.8,-0.3 -4.5,-2.1l-9.6,-26.7c-0.7,-1.8 0.3,-3.8 2.1,-4.5l0.6,-0.2c1.8,-0.7 3.8,0.3 4.5,2.1l9.6,26.7c0.7,1.9 -0.3,3.9 -2.1,4.5z"
-          android:fillColor="#54AF39"/>
-      <path
-          android:pathData="m180.662,3.8v0c0,2.1 -1.7,3.8 -3.8,3.8h-61c-2.1,0 -3.8,-1.7 -3.8,-3.8v0c0,-2.1 1.7,-3.8 3.8,-3.8h61c2.1,0 3.8,1.7 3.8,3.8z"
-          android:fillColor="#54AF39"/>
-      <path
-          android:pathData="M218.762,236.7L73.862,236.7c-13.3,0 -24,-10.8 -24,-24v-108C49.862,63.4 83.362,29.8 124.762,29.8h43.3c41.3,0 74.9,33.5 74.9,74.9v108c-0.1,13.2 -10.9,24 -24.2,24z"
-          android:fillColor="#54AF39"/>
-      <path
-          android:pathData="M212.562,146.2L80.062,146.2c-5.6,0 -10.2,-4.5 -10.2,-10.2v-34.9c0,-16.9 13.7,-30.6 30.6,-30.6L192.162,70.5c16.9,0 30.6,13.7 30.6,30.6v34.9c-0.1,5.7 -4.6,10.2 -10.2,10.2z"
-          android:fillColor="#FFFFFF"/>
-      <path
-          android:pathData="M161.462,55.5L131.162,55.5c-3.2,0 -5.7,-2.6 -5.7,-5.7v0c0,-3.2 2.6,-5.7 5.7,-5.7h30.3c3.2,0 5.7,2.6 5.7,5.7v0c0,3.1 -2.6,5.7 -5.7,5.7z"
-          android:fillColor="#FFFFFF"/>
-      <path
-          android:pathData="M87.062,191.9m-14.8,0a14.8,14.8 0,1 1,29.6 0a14.8,14.8 0,1 1,-29.6 0"
-          android:fillColor="#FFFFFF"/>
-      <path
-          android:pathData="M205.662,191.9m-14.8,0a14.8,14.8 0,1 1,29.6 0a14.8,14.8 0,1 1,-29.6 0"
-          android:fillColor="#FFFFFF"/>
-    </group>
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+  <group android:scaleX="0.16904335"
+      android:scaleY="0.16904335">
+  	<group
+  		android:translateX="173.03255"
+  		android:translateY="173.03255">
+  		<path
+  			android:fillColor="#54AF39"
+  			android:pathData="m62.962,292.5v0c-3.7,-0.9 -5.7,-3.8 -4.3,-6.5l32.3,-62.9c1.3,-2.6 5.5,-4 9.2,-3v0c3.7,0.9 5.7,3.8 4.3,6.5L72.162,289.5c-1.3,2.6 -5.4,4 -9.2,3z" />
+  		<path
+  			android:fillColor="#54AF39"
+  			android:pathData="m229.662,292.5v0c3.7,-0.9 5.7,-3.8 4.3,-6.5l-32.3,-62.9c-1.3,-2.6 -5.5,-4 -9.2,-3v0c-3.7,0.9 -5.7,3.8 -4.3,6.5l32.3,62.9c1.3,2.6 5.5,4 9.2,3z" />
+  		<path
+  			android:fillColor="#54AF39"
+  			android:pathData="m151.362,36.9 l-0.6,0.2c-1.8,0.7 -3.8,-0.3 -4.5,-2.1l-9.6,-26.7c-0.7,-1.8 0.3,-3.8 2.1,-4.5l0.6,-0.2c1.8,-0.7 3.8,0.3 4.5,2.1l9.6,26.7c0.7,1.9 -0.3,3.9 -2.1,4.5z" />
+  		<path
+  			android:fillColor="#54AF39"
+  			android:pathData="m180.662,3.8v0c0,2.1 -1.7,3.8 -3.8,3.8h-61c-2.1,0 -3.8,-1.7 -3.8,-3.8v0c0,-2.1 1.7,-3.8 3.8,-3.8h61c2.1,0 3.8,1.7 3.8,3.8z" />
+  		<path
+  			android:fillColor="#54AF39"
+  			android:pathData="M218.762,236.7L73.862,236.7c-13.3,0 -24,-10.8 -24,-24v-108C49.862,63.4 83.362,29.8 124.762,29.8h43.3c41.3,0 74.9,33.5 74.9,74.9v108c-0.1,13.2 -10.9,24 -24.2,24z" />
+  		<path
+  			android:fillColor="#FFFFFF"
+  			android:pathData="M212.562,146.2L80.062,146.2c-5.6,0 -10.2,-4.5 -10.2,-10.2v-34.9c0,-16.9 13.7,-30.6 30.6,-30.6L192.162,70.5c16.9,0 30.6,13.7 30.6,30.6v34.9c-0.1,5.7 -4.6,10.2 -10.2,10.2z" />
+  		<path
+  			android:fillColor="#FFFFFF"
+  			android:pathData="M161.462,55.5L131.162,55.5c-3.2,0 -5.7,-2.6 -5.7,-5.7v0c0,-3.2 2.6,-5.7 5.7,-5.7h30.3c3.2,0 5.7,2.6 5.7,5.7v0c0,3.1 -2.6,5.7 -5.7,5.7z" />
+  		<path
+  			android:fillColor="#FFFFFF"
+  			android:pathData="M87.062,191.9m-14.8,0a14.8,14.8 0,1 1,29.6 0a14.8,14.8 0,1 1,-29.6 0" />
+  		<path
+  			android:fillColor="#FFFFFF"
+  			android:pathData="M205.662,191.9m-14.8,0a14.8,14.8 0,1 1,29.6 0a14.8,14.8 0,1 1,-29.6 0" />
+  	</group>
+  </group>
 </vector>




diff --git a/app/src/main/res/drawable/ic_low_floor.xml b/app/src/main/res/drawable/ic_low_floor.xml
deleted file mode 100644
index ee8013952cf5c8a7452b47c737c2517549eb8bba..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_low_floor.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="M12,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="M19,13v-2c-1.54,0.02 -3.09,-0.75 -4.07,-1.83l-1.29,-1.43c-0.17,-0.19 -0.38,-0.34 -0.61,-0.45 -0.01,0 -0.01,-0.01 -0.02,-0.01L13,7.28c-0.35,-0.2 -0.75,-0.3 -1.19,-0.26C10.76,7.11 10,8.04 10,9.09L10,15c0,1.1 0.9,2 2,2h5v5h2v-5.5c0,-1.1 -0.9,-2 -2,-2h-3v-3.45c1.29,1.07 3.25,1.94 5,1.95zM12.83,18c-0.41,1.16 -1.52,2 -2.83,2 -1.66,0 -3,-1.34 -3,-3 0,-1.31 0.84,-2.41 2,-2.83L9,12.1c-2.28,0.46 -4,2.48 -4,4.9 0,2.76 2.24,5 5,5 2.42,0 4.44,-1.72 4.9,-4h-2.07z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_merge.xml b/app/src/main/res/drawable/ic_merge.xml
deleted file mode 100644
index 18a93f7c4dbc2e9ccf2a0c1748eb98f8c4fb09a0..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_merge.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0">
-    <path
-        android:fillColor="#ffffffff"
-        android:pathData="M17,20.41L18.41,19 15,15.59 13.59,17 17,20.41zM7.5,8H11v5.59L5.59,19 7,20.41l6,-6V8h3.5L12,3.5 7.5,8z" />
-</vector>




diff --git a/app/src/main/res/drawable/ic_message.xml b/app/src/main/res/drawable/ic_message.xml
deleted file mode 100644
index d2876bfad9b41c533cbcab6156b7585e326a5644..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_message.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM18,14L6,14v-2h12v2zM18,11L6,11L6,9h12v2zM18,8L6,8L6,6h12v2z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_more.xml b/app/src/main/res/drawable/ic_more.xml
deleted file mode 100644
index 32698689639ff2e219056beced56019d70168b3e..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_more.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"
-        android:fillColor="@color/textDark"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml
deleted file mode 100644
index 40184c4b85dc0e3eec059ec810bfb833490f47ce..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_refresh.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml
deleted file mode 100644
index bb988c1e7b6e67ca36b9e4bea05d1b0a54188b96..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_settings.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:autoMirrored="true"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0">
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z" />
-</vector>




diff --git a/app/src/main/res/drawable/ic_stop.xml b/app/src/main/res/drawable/ic_stop.xml
deleted file mode 100644
index eaf0afaf749baa0f6837f340a2d48419d69cd848..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_stop.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M12,2C8.13,2 5,5.13 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9C19,5.13 15.87,2 12,2zM12,5.758C13.547,5.758 14.799,5.933 14.799,7.158L14.799,10.656C14.799,10.964 14.663,11.241 14.449,11.434L14.449,12.057C14.449,12.249 14.292,12.406 14.1,12.406L13.75,12.406C13.558,12.406 13.4,12.249 13.4,12.057L13.4,11.707L10.6,11.707L10.6,12.057C10.6,12.249 10.442,12.406 10.25,12.406L9.9,12.406C9.708,12.406 9.551,12.249 9.551,12.057L9.551,11.434C9.337,11.241 9.201,10.964 9.201,10.656L9.201,7.158C9.201,5.933 10.453,5.758 12,5.758zM9.9,7.158L9.9,8.908L14.1,8.908L14.1,7.158L9.9,7.158zM10.426,9.957C10.135,9.957 9.9,10.192 9.9,10.482C9.9,10.773 10.135,11.008 10.426,11.008C10.716,11.008 10.951,10.773 10.951,10.482C10.951,10.192 10.716,9.957 10.426,9.957zM13.574,9.957C13.284,9.957 13.049,10.192 13.049,10.482C13.049,10.773 13.284,11.008 13.574,11.008C13.865,11.008 14.1,10.773 14.1,10.482C14.1,10.192 13.865,9.957 13.574,9.957z"
-        android:fillColor="#000000"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_texthandle_end.xml b/app/src/main/res/drawable/ic_texthandle_end.xml
deleted file mode 100644
index 923f2b49a542f61b7fa1b19c720cba506b6767fb..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_texthandle_end.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<vector android:autoMirrored="true" android:height="24dp"
-    android:viewportHeight="88" android:viewportWidth="176"
-    android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillAlpha="1" android:fillColor="#54af39"
-        android:pathData="M88,0A44,44 0,0 1,132 44,44 44,0 0,1 88,88 44,44 0,0 1,44 44V0Z"
-        android:strokeAlpha="1" android:strokeColor="#00000000"
-        android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0.01982322"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_texthandle_middle.xml b/app/src/main/res/drawable/ic_texthandle_middle.xml
deleted file mode 100644
index da3c7962d98b2e2ef0113080f7491bad6e6c6dc6..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_texthandle_middle.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<vector android:height="24dp" android:viewportHeight="88"
-    android:viewportWidth="88" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillAlpha="1" android:fillColor="#54af39"
-        android:pathData="m69.7747,25.7746a36.4509,36.4508 0,0 1,0 51.5492,36.4509 36.4508,0 0,1 -51.5494,0 36.4509,36.4508 0,0 1,0 -51.5492L44,0Z"
-        android:strokeAlpha="1" android:strokeColor="#00000000"
-        android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0.01642212"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_texthandle_start.xml b/app/src/main/res/drawable/ic_texthandle_start.xml
deleted file mode 100644
index 577a11d14e6d46dade232eca4176dbcf8f469879..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_texthandle_start.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<vector android:autoMirrored="true" android:height="24dp"
-    android:viewportHeight="88" android:viewportWidth="176"
-    android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillAlpha="1" android:fillColor="#54af39"
-        android:pathData="M88,0A44,44 0,0 0,44 44,44 44,0 0,0 88,88 44,44 0,0 0,132 44V0Z"
-        android:strokeAlpha="1" android:strokeColor="#00000000"
-        android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0.01982322"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_ticket.xml b/app/src/main/res/drawable/ic_ticket.xml
deleted file mode 100644
index bac81d8c4f7287a9046ffce81489ad5a5580039f..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_ticket.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="M22,10L22,6c0,-1.11 -0.9,-2 -2,-2L4,4c-1.1,0 -1.99,0.89 -1.99,2v4c1.1,0 1.99,0.9 1.99,2s-0.89,2 -2,2v4c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2v-4c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2zM13,17.5h-2v-2h2v2zM13,13h-2v-2h2v2zM13,8.5h-2v-2h2v2z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_ticket_machine.xml b/app/src/main/res/drawable/ic_ticket_machine.xml
deleted file mode 100644
index 54ae501704b5f0035bd6f904e7987e3386f3c0db..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_ticket_machine.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24">
-  <path
-      android:pathData="M3.25,2l17.5,0l0,20l-17.5,0z"
-      android:strokeAlpha="1"
-      android:strokeLineJoin="round"
-      android:strokeWidth="0.93728513"
-      android:fillColor="@color/cardColor"
-      android:strokeColor="#00000000"
-      android:fillAlpha="1"
-      android:strokeLineCap="round"/>
-  <path
-      android:pathData="m13.7109,5.0742c-1.3615,0 -2.4673,1.1057 -2.4673,2.4672 0,1.3615 1.1057,2.4672 2.4673,2.4672 0.2537,0 0.4944,-0.0488 0.7248,-0.12l0,-0.9861c-0.1124,0.0637 -0.2367,0.115 -0.3771,0.1412l0,0.4719l-0.6574,0l0,-0.4761c-0.4218,-0.0888 -0.7798,-0.3599 -0.807,-0.8386l0.4825,0c0.0247,0.2591 0.2018,0.4594 0.6532,0.4594 0.4834,0 0.5921,-0.2413 0.5921,-0.3919 0,-0.2046 -0.1073,-0.396 -0.6574,-0.5268 -0.6117,-0.1486 -1.0303,-0.4002 -1.0303,-0.906 0,-0.4241 0.3427,-0.7007 0.7669,-0.7923l0,-0.4761l0.6574,0l0,0.4825c0.1547,0.0375 0.274,0.1088 0.3771,0.1918l0,-1.0473c-0.2304,-0.0712 -0.4711,-0.12 -0.7248,-0.12zM13.7298,6.4247c-0.37,0 -0.59,0.1678 -0.59,0.4045 0,0.2072 0.1591,0.3415 0.6574,0.4699 0.2254,0.0575 0.4514,0.1404 0.6384,0.2634l0,-0.6764l-0.158,0c-0.0123,-0.2736 -0.1581,-0.4614 -0.5478,-0.4614z"
-      android:strokeWidth="0.19732159"
-      android:fillColor="@color/textDark"/>
-  <path
-      android:pathData="M14.3915,3.8496l1.0435,0l0,7.397l-1.0435,0z"
-      android:strokeAlpha="1"
-      android:strokeWidth="0"
-      android:fillColor="@color/textDark"
-      android:strokeColor="@color/textDark"
-      android:fillAlpha="1"/>
-  <path
-      android:pathData="M6.5208,14.0367l10.9584,0l0,2.0727l-10.9584,0z"
-      android:strokeAlpha="1"
-      android:strokeLineJoin="round"
-      android:strokeWidth="0.88379633"
-      android:fillColor="@color/textDark"
-      android:strokeColor="@color/textDark"
-      android:fillAlpha="1"
-      android:strokeLineCap="round"/>
-  <path
-      android:pathData="M3.25,2L3.25,22L20.75,22L20.75,2ZM4.5,3.25L19.5,3.25L19.5,20.75L4.5,20.75Z"
-      android:strokeAlpha="1"
-      android:strokeLineJoin="round"
-      android:strokeWidth="1.00509846"
-      android:fillColor="@color/textDark"
-      android:strokeColor="@color/textDark"
-      android:fillAlpha="1"
-      android:strokeLineCap="round"/>
-  <group>
-    <clip-path android:pathData="M-3,-3l30,0l0,30L-3,27z M 0,0"/>
-    <path
-        android:fillColor="@color/textDark"
-        android:pathData="m 9.8554688,14.806641 v 3.580078 c 0,0.294849 0.2422602,0.537109 0.5371092,0.537109 h 1.072266 c 0,-0.294849 0.240307,-0.537109 0.535156,-0.537109 0.294849,0 0.535156,0.24226 0.535156,0.537109 h 1.072266 c 0.29753,0 0.537109,-0.24226 0.537109,-0.537109 v -3.580078 z m 0.6699222,1.167968 H 11.0625 v 0.535157 h -0.537109 z m 1.207031,0 h 0.535156 v 0.535157 h -0.535156 z m 1.205078,0 h 0.537109 v 0.535157 H 12.9375 Z"
-        android:strokeWidth="0.26804501"/>
-  </group>
-</vector>




diff --git a/app/src/main/res/drawable/ic_timetable_departure.xml b/app/src/main/res/drawable/ic_timetable_departure.xml
deleted file mode 100644
index 2a0bc4f2efc8c8d09bec309e12cd8e77320abedf..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_timetable_departure.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:pathData="M19,3C12,2.48 12,2.482 5,3 3.89,3 3.01,3.9 3.01,5L3,19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5C21,3.9 20.1,3 19,3ZM19,19L5,19L5,8h14z"
-        android:fillColor="#ffffff"/>
-    <path
-        android:pathData="m17,12h-5v5h5z"
-        android:fillColor="#ffffff"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_timetable_full.xml b/app/src/main/res/drawable/ic_timetable_full.xml
deleted file mode 100644
index 9518500e07590223e10da0b58f7218ff47e066f2..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_timetable_full.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<vector android:autoMirrored="true" android:height="24dp"
-    android:viewportHeight="24.0" android:viewportWidth="24.0"
-    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="#ffffff" android:pathData="M17,10L7,10v2L17,12ZM19,3C12,2.48 12,2.482 5,3 3.89,3 3.01,3.9 3.01,5L3,19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5C21,3.9 20.1,3 19,3ZM19,19L5,19L5,8L19,8ZM14,14L7,14v2h7z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_traffic.xml b/app/src/main/res/drawable/ic_traffic.xml
deleted file mode 100644
index bf022cdda4939866e398ea8f7cd71e8015f188ab..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_traffic.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#ffffff"
-        android:pathData="M20,10h-3L17,8.86c1.72,-0.45 3,-2 3,-3.86h-3L17,4c0,-0.55 -0.45,-1 -1,-1L8,3c-0.55,0 -1,0.45 -1,1v1L4,5c0,1.86 1.28,3.41 3,3.86L7,10L4,10c0,1.86 1.28,3.41 3,3.86L7,15L4,15c0,1.86 1.28,3.41 3,3.86L7,20c0,0.55 0.45,1 1,1h8c0.55,0 1,-0.45 1,-1v-1.14c1.72,-0.45 3,-2 3,-3.86h-3v-1.14c1.72,-0.45 3,-2 3,-3.86zM12,19c-1.11,0 -2,-0.9 -2,-2s0.89,-2 2,-2c1.1,0 2,0.9 2,2s-0.89,2 -2,2zM12,14c-1.11,0 -2,-0.9 -2,-2s0.89,-2 2,-2c1.1,0 2,0.9 2,2s-0.89,2 -2,2zM12,9c-1.11,0 -2,-0.9 -2,-2 0,-1.11 0.89,-2 2,-2 1.1,0 2,0.89 2,2 0,1.1 -0.89,2 -2,2z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_tram.xml b/app/src/main/res/drawable/ic_tram.xml
deleted file mode 100644
index ecef589606701c868fa9caa9a9576b57948efe58..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_tram.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M19,16.94L19,8.5c0,-2.79 -2.61,-3.4 -6.01,-3.49l0.76,-1.51L17,3.5L17,2L7,2v1.5h4.75l-0.76,1.52C7.86,5.11 5,5.73 5,8.5v8.44c0,1.45 1.19,2.66 2.59,2.97L6,21.5v0.5h2.23l2,-2L14,20l2,2h2v-0.5L16.5,20h-0.08c1.69,0 2.58,-1.37 2.58,-3.06zM12,18.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM17,14L7,14L7,9h10v5z"/>
-</vector>




diff --git a/app/src/main/res/drawable/ic_vehicle.xml b/app/src/main/res/drawable/ic_vehicle.xml
deleted file mode 100644
index ae6f37bcc062fe9cba244f5a8af0bc67bf16e3c6..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/ic_vehicle.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="24dp"
-        android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M4,15.5C4,17.43 5.57,19 7.5,19L6,20.5v0.5h12v-0.5L16.5,19c1.93,0 3.5,-1.57 3.5,-3.5L20,5c0,-3.5 -3.58,-4 -8,-4s-8,0.5 -8,4v10.5zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM18,10L6,10L6,5h12v5z"/>
-</vector>




diff --git a/app/src/main/res/drawable/inari.xml b/app/src/main/res/drawable/inari.xml
new file mode 100644
index 0000000000000000000000000000000000000000..da25ef47d0c88263da2cc9acce30d60b253a96a3
--- /dev/null
+++ b/app/src/main/res/drawable/inari.xml
@@ -0,0 +1,55 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="66.982dp"
+    android:height="55.716dp"
+    android:viewportWidth="66.982"
+    android:viewportHeight="55.716">
+  <path
+      android:pathData="M0,12.887a5.574,5.313 0,1 0,11.148 0a5.574,5.313 0,1 0,-11.148 0z"
+      android:strokeWidth="0.352122"
+      android:fillColor="#567ca0"/>
+  <path
+      android:pathData="M4.96,18.166h0.986v33.42h-0.986z"
+      android:strokeWidth="0.264866"
+      android:fillColor="#b5c5c5"/>
+  <path
+      android:pathData="M3.431,25.325h4.196v7.813h-4.196z"
+      android:strokeWidth="0.264583"
+      android:fillColor="#798595"/>
+  <path
+      android:pathData="m0.313,51.665h10.617v3.857c-3.618,0.267 -7.151,0.248 -10.617,0z"
+      android:strokeWidth="0.264583"
+      android:fillColor="#3f413c"/>
+  <path
+      android:pathData="m16.302,33.054 l5.762,-3.254 5.651,-0.183 6.147,0.293 4.652,2.215 -0.004,1.039 -3.422,2.396 -13.591,0.269z"
+      android:strokeLineJoin="miter"
+      android:strokeWidth="0.264583"
+      android:fillColor="#53221b"
+      android:strokeColor="#00000000"
+      android:strokeLineCap="butt"/>
+  <path
+      android:pathData="m27.594,26.553l0,12.511 0,0.722l0.484,0l0,-0.722 0,-12.511z"
+      android:strokeWidth="0.265"
+      android:fillColor="#5d1c18"/>
+  <path
+      android:pathData="m38.514,32.125c0.179,-0.709 -0.377,-1.396 -0.856,-1.87 -0.554,-0.544 -1.324,-1.41 -1.884,-1.957 -0.993,-0.578 -2.003,-0.898 -2.924,-1.586 -0.712,-0.696 -1.613,-0.546 -2.504,-0.857 -0.988,-0.383 -2.037,-0.15 -3.061,-0.164 -1.123,0.124 -2.255,0.275 -3.382,0.4 -0.863,0.156 -1.682,0.488 -2.422,0.946 -0.867,0.262 -1.547,0.826 -2.186,1.446 -0.789,0.558 -1.352,1.341 -2.037,2.012 -0.795,0.588 -0.88,1.652 -0.956,2.561l5.762,-3.254 5.651,-0.183 6.147,0.293z"
+      android:strokeLineJoin="miter"
+      android:strokeWidth="0.264583"
+      android:fillColor="#da4e59"
+      android:strokeColor="#00000000"
+      android:strokeLineCap="butt"/>
+  <path
+      android:pathData="m27.594,39.786h1.3v0c0,0 0.183,2.349 -0.63,2.355 -0.816,0.007 -0.67,-2.355 -0.67,-2.355z"
+      android:strokeWidth="0.264583"
+      android:fillColor="#743027"/>
+  <path
+      android:pathData="m55.478,2.524c1.557,0.025 3.113,0.049 4.67,0.074 0.066,-0.391 0.147,-0.813 0.248,-1.21 0.227,-0.373 0.095,-0.844 0.268,-1.202 0.148,-0.137 0.648,-0.364 0.706,0.058 0.115,0.42 0.124,0.927 -0.058,1.329 -0.101,0.353 -0.223,0.723 -0.389,1.032 1.599,0.008 3.198,0.017 4.796,0.025 0.197,0.326 0.599,0.218 0.915,0.392 0.456,0.096 0.354,0.596 0.295,1.009 -0.327,0.229 -0.432,0.655 -0.831,0.805 -0.229,0.283 -0.572,0.536 -0.982,0.358 -0.512,0.157 -1.007,-0.001 -1.518,-0.007 -0.386,-0.018 -0.684,0.241 -1.046,0.366 -0.398,0.176 -0.773,0.436 -1.058,0.758 -0.435,0.481 -0.955,0.035 -1.48,0.066 -0.417,-0.12 -0.696,-0.414 -1.077,-0.616 -0.429,-0.214 -0.84,-0.472 -1.2,-0.787 -0.401,-0.252 -0.878,-0.38 -1.181,-0.768 -0.3,-0.356 -0.88,-0.394 -1.031,-0.862 -0.081,-0.249 -0.155,-0.575 -0.048,-0.82z"
+      android:strokeLineJoin="miter"
+      android:strokeWidth="0.264583"
+      android:fillColor="#586c24"
+      android:strokeColor="#00000000"
+      android:strokeLineCap="butt"/>
+  <path
+      android:pathData="m7.458,15.993 l-2.092,-1.223 -2.194,1.03 0.517,-2.368 -1.658,-1.768 2.412,-0.24 1.169,-2.123 0.974,2.22 2.38,0.456 -1.81,1.612z"
+      android:fillColor="#ffe438"
+      android:strokeColor="#00000000"/>
+</vector>




diff --git a/app/src/main/res/drawable/logo_splash.xml b/app/src/main/res/drawable/logo_splash.xml
deleted file mode 100644
index d47ebc499c362c425b5022bc55fd47e9145e7e92..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/logo_splash.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<vector android:height="192dp" android:viewportHeight="293"
-    android:viewportWidth="298" android:width="192dp" xmlns:android="http://schemas.android.com/apk/res/android">
-    <path android:fillColor="#54AF39" android:pathData="m62.925,292.677l0,0c-3.69,-0.897 -5.684,-3.789 -4.288,-6.482l32.209,-62.723c1.296,-2.593 5.485,-3.989 9.174,-2.992l0,0c3.69,0.897 5.684,3.789 4.288,6.482L72.099,289.685c-1.296,2.593 -5.385,3.989 -9.174,2.992z"/>
-    <path android:fillColor="#54AF39" android:pathData="m229.156,292.677l0,0c3.69,-0.897 5.684,-3.789 4.288,-6.482l-32.209,-62.723c-1.296,-2.593 -5.485,-3.989 -9.174,-2.992l0,0c-3.69,0.897 -5.684,3.789 -4.288,6.482l32.209,62.723c1.296,2.593 5.485,3.989 9.174,2.992z"/>
-    <path android:fillColor="#54AF39" android:pathData="m151.076,37.797 l-0.598,0.199c-1.795,0.698 -3.789,-0.299 -4.487,-2.094l-9.573,-26.625c-0.698,-1.795 0.299,-3.789 2.094,-4.487l0.598,-0.199c1.795,-0.698 3.789,0.299 4.487,2.094l9.573,26.625c0.698,1.895 -0.299,3.889 -2.094,4.487z"/>
-    <path android:fillColor="#54AF39" android:pathData="m180.294,4.79l0,0c0,2.094 -1.695,3.789 -3.789,3.789l-60.828,0c-2.094,0 -3.789,-1.695 -3.789,-3.789l0,0c0,-2.094 1.695,-3.789 3.789,-3.789l60.828,0c2.094,0 3.789,1.695 3.789,3.789z"/>
-    <path android:fillColor="#54AF39" android:pathData="M218.286,237.034L73.795,237.034c-13.263,0 -23.932,-10.77 -23.932,-23.932l0,-107.696C49.862,64.222 83.268,30.717 124.551,30.717l43.178,0c41.184,0 74.689,33.406 74.689,74.689l0,107.696c-0.1,13.163 -10.869,23.932 -24.132,23.932z"/>
-    <path android:fillColor="#FFFFFF" android:pathData="M212.104,146.789L79.977,146.789c-5.584,0 -10.171,-4.487 -10.171,-10.171l0,-34.802c0,-16.852 13.661,-30.514 30.514,-30.514L191.761,71.302c16.852,0 30.514,13.661 30.514,30.514l0,34.802c-0.1,5.684 -4.587,10.171 -10.171,10.171z"/>
-    <path android:fillColor="#FFFFFF" android:pathData="M161.148,56.344L130.933,56.344c-3.191,0 -5.684,-2.593 -5.684,-5.684l0,0c0,-3.191 2.593,-5.684 5.684,-5.684l30.215,0c3.191,0 5.684,2.593 5.684,5.684l0,0c0,3.091 -2.593,5.684 -5.684,5.684z"/>
-    <path android:fillColor="#FFFFFF" android:pathData="M86.957,192.36m-14.758,0a14.758,14.758 0,1 1,29.517 0a14.758,14.758 0,1 1,-29.517 0"/>
-    <path android:fillColor="#FFFFFF" android:pathData="M205.223,192.36m-14.758,0a14.758,14.758 0,1 1,29.517 0a14.758,14.758 0,1 1,-29.517 0"/>
-</vector>




diff --git a/app/src/main/res/drawable/map_black.xml b/app/src/main/res/drawable/map_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e18171d1dbc285c53c53fb4bdcd4acebc216c02
--- /dev/null
+++ b/app/src/main/res/drawable/map_black.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+	android:width="24dp"
+	android:height="24dp"
+	android:tint="#000000"
+	android:viewportWidth="24"
+	android:viewportHeight="24">
+	<path
+		android:fillColor="@android:color/white"
+		android:pathData="M20.5,3l-0.16,0.03L15,5.1 9,3 3.36,4.9c-0.21,0.07 -0.36,0.25 -0.36,0.48V20.5c0,0.28 0.22,0.5 0.5,0.5l0.16,-0.03L9,18.9l6,2.1 5.64,-1.9c0.21,-0.07 0.36,-0.25 0.36,-0.48V3.5c0,-0.28 -0.22,-0.5 -0.5,-0.5zM15,19l-6,-2.11V5l6,2.11V19z" />
+</vector>




diff --git a/app/src/main/res/drawable/map_outline.xml b/app/src/main/res/drawable/map_outline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7d60b16d2a17887332a400f41434d035dac33a12
--- /dev/null
+++ b/app/src/main/res/drawable/map_outline.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+	android:width="24dp"
+	android:height="24dp"
+	android:tint="#000000"
+	android:viewportWidth="24"
+	android:viewportHeight="24">
+	<path
+		android:fillColor="@android:color/white"
+		android:pathData="M20.5,3l-0.16,0.03L15,5.1 9,3 3.36,4.9c-0.21,0.07 -0.36,0.25 -0.36,0.48L3,20.5c0,0.28 0.22,0.5 0.5,0.5l0.16,-0.03L9,18.9l6,2.1 5.64,-1.9c0.21,-0.07 0.36,-0.25 0.36,-0.48L21,3.5c0,-0.28 -0.22,-0.5 -0.5,-0.5zM10,5.47l4,1.4v11.66l-4,-1.4L10,5.47zM5,6.46l3,-1.01v11.7l-3,1.16L5,6.46zM19,17.54l-3,1.01L16,6.86l3,-1.16v11.84z" />
+</vector>




diff --git a/app/src/main/res/drawable/navigation_arrow.xml b/app/src/main/res/drawable/navigation_arrow.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c29f851f60d8cbd8b38d63085504c6cde84c2ffc
--- /dev/null
+++ b/app/src/main/res/drawable/navigation_arrow.xml
@@ -0,0 +1,8 @@
+<vector android:height="24dp" android:tint="?colorPrimary"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillAlpha="0.3"
+        android:fillColor="@android:color/white"
+        android:pathData="M7.72,17.7l3.47,-1.53 0.81,-0.36 0.81,0.36 3.47,1.53L12,7.27z" android:strokeAlpha="0.3"/>
+    <path android:fillColor="@android:color/white" android:pathData="M4.5,20.29l0.71,0.71L12,18l6.79,3 0.71,-0.71L12,2 4.5,20.29zM12.81,16.17l-0.81,-0.36 -0.81,0.36 -3.47,1.53L12,7.27l4.28,10.43 -3.47,-1.53z"/>
+</vector>




diff --git a/app/src/main/res/drawable/navigation_circle.xml b/app/src/main/res/drawable/navigation_circle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..535e8520e6bde8d1784a1fb26a1ba701a26dfd74
--- /dev/null
+++ b/app/src/main/res/drawable/navigation_circle.xml
@@ -0,0 +1,8 @@
+<vector android:height="24dp" android:tint="?colorPrimary"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillAlpha="0.3"
+        android:fillColor="@android:color/white"
+        android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0" android:strokeAlpha="0.3"/>
+    <path android:fillColor="@android:color/white" android:pathData="M12,2C6.47,2 2,6.47 2,12c0,5.53 4.47,10 10,10s10,-4.47 10,-10C22,6.47 17.53,2 12,2zM12,20c-4.42,0 -8,-3.58 -8,-8c0,-4.42 3.58,-8 8,-8s8,3.58 8,8C20,16.42 16.42,20 12,20z"/>
+</vector>




diff --git a/app/src/main/res/drawable/open_outside.xml b/app/src/main/res/drawable/open_outside.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a44988cc484c69541ae1cf9e3db3b1745c12626
--- /dev/null
+++ b/app/src/main/res/drawable/open_outside.xml
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:tint="?attr/colorOnSurface" android:viewportHeight="24"
+    android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z"/>
+</vector>




diff --git a/app/src/main/res/drawable/radar.xml b/app/src/main/res/drawable/radar.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4a9b66f5dfd56a6902bcb4f73c755edfbb32a8d6
--- /dev/null
+++ b/app/src/main/res/drawable/radar.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M19.74,18.33C21.15,16.6 22,14.4 22,12c0,-5.52 -4.48,-10 -10,-10S2,6.48 2,12s4.48,10 10,10c2.4,0 4.6,-0.85 6.33,-2.26c0.27,-0.22 0.53,-0.46 0.78,-0.71c0.03,-0.03 0.05,-0.06 0.07,-0.08C19.38,18.75 19.57,18.54 19.74,18.33zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8s8,3.59 8,8c0,1.85 -0.63,3.54 -1.69,4.9l-1.43,-1.43c0.69,-0.98 1.1,-2.17 1.1,-3.46c0,-3.31 -2.69,-6 -6,-6s-6,2.69 -6,6s2.69,6 6,6c1.3,0 2.51,-0.42 3.49,-1.13l1.42,1.42C15.54,19.37 13.85,20 12,20zM13.92,12.51c0.17,-0.66 0.02,-1.38 -0.49,-1.9l-0.02,-0.02c-0.77,-0.77 -2,-0.78 -2.78,-0.04c-0.01,0.01 -0.03,0.02 -0.05,0.04c-0.78,0.78 -0.78,2.05 0,2.83l0.02,0.02c0.52,0.51 1.25,0.67 1.91,0.49l1.51,1.51c-0.6,0.36 -1.29,0.58 -2.04,0.58c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4s4,1.79 4,4c0,0.73 -0.21,1.41 -0.56,2L13.92,12.51z" />
+</vector>




diff --git a/app/src/main/res/drawable/speed.xml b/app/src/main/res/drawable/speed.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8bd6c25c1798adb28ad2093bf615d11565b828ec
--- /dev/null
+++ b/app/src/main/res/drawable/speed.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M20.38,8.57l-1.23,1.85a8,8 0,0 1,-0.22 7.58L5.07,18A8,8 0,0 1,15.58 6.85l1.85,-1.23A10,10 0,0 0,3.35 19a2,2 0,0 0,1.72 1h13.85a2,2 0,0 0,1.74 -1,10 10,0 0,0 -0.27,-10.44zM10.59,15.41a2,2 0,0 0,2.83 0l5.66,-8.49 -8.49,5.66a2,2 0,0 0,0 2.83z"/>
+</vector>




diff --git a/app/src/main/res/drawable/splash_screen.xml b/app/src/main/res/drawable/splash_screen.xml
deleted file mode 100644
index 0630c0b6c2ab6efb60de91917e757d8307cc5535..0000000000000000000000000000000000000000
--- a/app/src/main/res/drawable/splash_screen.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:drawable="@color/colorPrimary" />
-    <item
-        android:gravity="center"
-        android:drawable="@drawable/logo_splash"/>
-
-</layer-list>
\ No newline at end of file




diff --git a/app/src/main/res/drawable/stop.xml b/app/src/main/res/drawable/stop.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6152d3c023e5b38f7777e0e0ea49369a119b4833
--- /dev/null
+++ b/app/src/main/res/drawable/stop.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M2,12C2,6.48 6.48,2 12,2s10,4.48 10,10 -4.48,10 -10,10S2,17.52 2,12zM12,18c3.31,0 6,-2.69 6,-6s-2.69,-6 -6,-6 -6,2.69 -6,6 2.69,6 6,6z"/>
+</vector>




diff --git a/app/src/main/res/drawable/stop_bg.xml b/app/src/main/res/drawable/stop_bg.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2bbe61ebf84e1af6e37ab94e17428476dca002a0
--- /dev/null
+++ b/app/src/main/res/drawable/stop_bg.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M2.807,12a9.193,9.193 0,1 0,18.386 0a9.193,9.193 0,1 0,-18.386 0z"
+      android:fillColor="@android:color/black"/>
+</vector>




diff --git a/app/src/main/res/drawable/ticket.xml b/app/src/main/res/drawable/ticket.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fff78c3e5c8aa8da77179e6da442ffd733e8590a
--- /dev/null
+++ b/app/src/main/res/drawable/ticket.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M22,10V6c0,-1.11 -0.9,-2 -2,-2H4C2.9,4 2.01,4.89 2.01,6v4C3.11,10 4,10.9 4,12s-0.89,2 -2,2v4c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2v-4c-1.1,0 -2,-0.9 -2,-2S20.9,10 22,10zM13,17.5h-2v-2h2V17.5zM13,13h-2v-2h2V13zM13,8.5h-2v-2h2V8.5z"/>
+</vector>




diff --git a/app/src/main/res/drawable/traffic.xml b/app/src/main/res/drawable/traffic.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a90fc1adaa70dfaabc28ac064f12b98bd2bdd3a0
--- /dev/null
+++ b/app/src/main/res/drawable/traffic.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M20,10h-3L17,8.86c1.72,-0.45 3,-2 3,-3.86h-3L17,4c0,-0.55 -0.45,-1 -1,-1L8,3c-0.55,0 -1,0.45 -1,1v1L4,5c0,1.86 1.28,3.41 3,3.86L7,10L4,10c0,1.86 1.28,3.41 3,3.86L7,15L4,15c0,1.86 1.28,3.41 3,3.86L7,20c0,0.55 0.45,1 1,1h8c0.55,0 1,-0.45 1,-1v-1.14c1.72,-0.45 3,-2 3,-3.86h-3v-1.14c1.72,-0.45 3,-2 3,-3.86zM12,19c-1.11,0 -2,-0.9 -2,-2s0.89,-2 2,-2c1.1,0 2,0.9 2,2s-0.89,2 -2,2zM12,14c-1.11,0 -2,-0.9 -2,-2s0.89,-2 2,-2c1.1,0 2,0.9 2,2s-0.89,2 -2,2zM12,9c-1.11,0 -2,-0.9 -2,-2 0,-1.11 0.89,-2 2,-2 1.1,0 2,0.89 2,2 0,1.1 -0.89,2 -2,2z"/>
+</vector>




diff --git a/app/src/main/res/drawable/tram_black.xml b/app/src/main/res/drawable/tram_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..989349cbc9a456e6458fff607d6ad99c1e9d1c79
--- /dev/null
+++ b/app/src/main/res/drawable/tram_black.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M19,16.94L19,8.5c0,-2.79 -2.61,-3.4 -6.01,-3.49l0.76,-1.51L17,3.5L17,2L7,2v1.5h4.75l-0.76,1.52C7.86,5.11 5,5.73 5,8.5v8.44c0,1.45 1.19,2.66 2.59,2.97L6,21.5v0.5h2.23l2,-2L14,20l2,2h2v-0.5L16.5,20h-0.08c1.69,0 2.58,-1.37 2.58,-3.06zM12,18.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM17,14L7,14L7,9h10v5z"/>
+</vector>




diff --git a/app/src/main/res/drawable/transfer.xml b/app/src/main/res/drawable/transfer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9bbd348b35582a1b326e1945f339eb2f550c23f1
--- /dev/null
+++ b/app/src/main/res/drawable/transfer.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M16.49,15.5v-1.75L14,16.25l2.49,2.5L16.49,17L22,17v-1.5zM19.51,19.75L14,19.75v1.5h5.51L19.51,23L22,20.5 19.51,18zM9.5,5.5c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM5.75,8.9L3,23h2.1l1.75,-8L9,17v6h2v-7.55L8.95,13.4l0.6,-3C10.85,12 12.8,13 15,13v-2c-1.85,0 -3.45,-1 -4.35,-2.45l-0.95,-1.6C9.35,6.35 8.7,6 8,6c-0.25,0 -0.5,0.05 -0.75,0.15L2,8.3L2,13h2L4,9.65l1.75,-0.75"/>
+</vector>




diff --git a/app/src/main/res/drawable/usb.xml b/app/src/main/res/drawable/usb.xml
new file mode 100644
index 0000000000000000000000000000000000000000..be1c47a4c753e537073fbab2636757cbb623a2c3
--- /dev/null
+++ b/app/src/main/res/drawable/usb.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M15,7v4h1v2h-3V5h2l-3,-4 -3,4h2v8H8v-2.07c0.7,-0.37 1.2,-1.08 1.2,-1.93 0,-1.21 -0.99,-2.2 -2.2,-2.2 -1.21,0 -2.2,0.99 -2.2,2.2 0,0.85 0.5,1.56 1.2,1.93V13c0,1.11 0.89,2 2,2h3v3.05c-0.71,0.37 -1.2,1.1 -1.2,1.95 0,1.22 0.99,2.2 2.2,2.2 1.21,0 2.2,-0.98 2.2,-2.2 0,-0.85 -0.49,-1.58 -1.2,-1.95V15h3c1.11,0 2,-0.89 2,-2v-2h1V7h-4z"/>
+</vector>




diff --git a/app/src/main/res/drawable/vehicle_black.xml b/app/src/main/res/drawable/vehicle_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5a564641966c51b347cffdc46b8967bc498796b8
--- /dev/null
+++ b/app/src/main/res/drawable/vehicle_black.xml
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#000000"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12,4L5,4C3.34,4 2,5.34 2,7v8c0,1.66 1.34,3 3,3l-1,1v1h1l2,-2.03L9,18v-5L4,13L4,5.98L13,6v2h2L15,7c0,-1.66 -1.34,-3 -3,-3zM5,14c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM20.57,9.66c-0.14,-0.4 -0.52,-0.66 -0.97,-0.66h-7.19c-0.46,0 -0.83,0.26 -0.98,0.66L10,13.77l0.01,5.51c0,0.38 0.31,0.72 0.69,0.72h0.62c0.38,0 0.68,-0.38 0.68,-0.76L12,18h8v1.24c0,0.38 0.31,0.76 0.69,0.76h0.61c0.38,0 0.69,-0.34 0.69,-0.72l0.01,-1.37v-4.14l-1.43,-4.11zM12.41,10h7.19l1.03,3h-9.25l1.03,-3zM12,16c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1zM20,16c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1 1,0.45 1,1 -0.45,1 -1,1z"/>
+</vector>




diff --git a/app/src/main/res/drawable/voice.xml b/app/src/main/res/drawable/voice.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5025538b7a1049c792bec4ed32094a28e4325965
--- /dev/null
+++ b/app/src/main/res/drawable/voice.xml
@@ -0,0 +1,8 @@
+<vector android:height="24dp" android:tint="?attr/colorOnSurface"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M10,9m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"/>
+    <path android:fillColor="@android:color/white" android:pathData="M16.39,15.56C14.71,14.7 12.53,14 10,14c-2.53,0 -4.71,0.7 -6.39,1.56C2.61,16.07 2,17.1 2,18.22V21h16v-2.78C18,17.1 17.39,16.07 16.39,15.56z"/>
+    <path android:fillColor="@android:color/white" android:pathData="M16,1h-2c0,4.97 4.03,9 9,9V8C19.14,8 16,4.86 16,1z"/>
+    <path android:fillColor="@android:color/white" android:pathData="M20,1h-2c0,2.76 2.24,5 5,5V4C21.35,4 20,2.65 20,1z"/>
+</vector>




diff --git a/app/src/main/res/drawable/voyage_black.xml b/app/src/main/res/drawable/voyage_black.xml
new file mode 100644
index 0000000000000000000000000000000000000000..64e7679467a84913e63d3c35fe2a7593046316c5
--- /dev/null
+++ b/app/src/main/res/drawable/voyage_black.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+	android:width="24dp"
+	android:height="24dp"
+	android:tint="#000000"
+	android:viewportWidth="24"
+	android:viewportHeight="24">
+	<path
+		android:fillColor="@android:color/white"
+		android:pathData="M21.71,11.29l-9,-9c-0.39,-0.39 -1.02,-0.39 -1.41,0l-9,9c-0.39,0.39 -0.39,1.02 0,1.41l9,9c0.39,0.39 1.02,0.39 1.41,0l9,-9c0.39,-0.38 0.39,-1.01 0,-1.41zM14,14.5V12h-4v3H8v-4c0,-0.55 0.45,-1 1,-1h5V7.5l3.5,3.5 -3.5,3.5z" />
+</vector>




diff --git a/app/src/main/res/drawable/voyage_outline.xml b/app/src/main/res/drawable/voyage_outline.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9818555ef3e8d71d8f9cfeb13831e94c194c88d8
--- /dev/null
+++ b/app/src/main/res/drawable/voyage_outline.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+	android:width="24dp"
+	android:height="24dp"
+	android:tint="#000000"
+	android:viewportWidth="24"
+	android:viewportHeight="24">
+	<path
+		android:fillColor="@android:color/white"
+		android:pathData="M22.43,10.59l-9.01,-9.01c-0.75,-0.75 -2.07,-0.76 -2.83,0l-9,9c-0.78,0.78 -0.78,2.04 0,2.82l9,9c0.39,0.39 0.9,0.58 1.41,0.58 0.51,0 1.02,-0.19 1.41,-0.58l8.99,-8.99c0.79,-0.76 0.8,-2.02 0.03,-2.82zM12.01,20.99l-9,-9 9,-9 9,9 -9,9zM8,11v4h2v-3h4v2.5l3.5,-3.5L14,7.5L14,10L9,10c-0.55,0 -1,0.45 -1,1z" />
+</vector>




diff --git a/app/src/main/res/drawable/wheelchair.xml b/app/src/main/res/drawable/wheelchair.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4bba0d4e74fafecb1856557c12e547e2064af8e8
--- /dev/null
+++ b/app/src/main/res/drawable/wheelchair.xml
@@ -0,0 +1,6 @@
+<vector android:autoMirrored="true" android:height="24dp"
+    android:tint="?attr/colorOnSurface" android:viewportHeight="24"
+    android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/white" android:pathData="M12,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
+    <path android:fillColor="@android:color/white" android:pathData="M19,13v-2c-1.54,0.02 -3.09,-0.75 -4.07,-1.83l-1.29,-1.43c-0.17,-0.19 -0.38,-0.34 -0.61,-0.45 -0.01,0 -0.01,-0.01 -0.02,-0.01L13,7.28c-0.35,-0.2 -0.75,-0.3 -1.19,-0.26C10.76,7.11 10,8.04 10,9.09L10,15c0,1.1 0.9,2 2,2h5v5h2v-5.5c0,-1.1 -0.9,-2 -2,-2h-3v-3.45c1.29,1.07 3.25,1.94 5,1.95zM12.83,18c-0.41,1.16 -1.52,2 -2.83,2 -1.66,0 -3,-1.34 -3,-3 0,-1.31 0.84,-2.41 2,-2.83L9,12.1c-2.28,0.46 -4,2.48 -4,4.9 0,2.76 2.24,5 5,5 2.42,0 4.44,-1.72 4.9,-4h-2.07z"/>
+</vector>




diff --git a/app/src/main/res/font/yellowcircle8.otf b/app/src/main/res/font/yellowcircle8.otf
new file mode 100644
index 0000000000000000000000000000000000000000..d7fe02a6e3eb6c6c6eab115c4b1e60c0f36bb63a
Binary files /dev/null and b/app/src/main/res/font/yellowcircle8.otf differ




diff --git a/app/src/main/res/layout/activity_dash.xml b/app/src/main/res/layout/activity_dash.xml
deleted file mode 100644
index beab223ec802c3d476e8b6cb3854326a13508063..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/activity_dash.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/drawer_layout"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/main_layout"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:clipChildren="false">
-
-        <com.google.android.material.appbar.AppBarLayout
-            android:id="@+id/appbar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:background="@color/colorAccentDark"
-            android:paddingTop="@dimen/appbar_padding_top"
-            android:theme="@style/AppTheme.AppBarOverlay"
-            android:visibility="invisible"
-            app:layout_constraintTop_toTopOf="parent">
-
-            <androidx.appcompat.widget.Toolbar
-                android:id="@+id/toolbar"
-                android:layout_width="match_parent"
-                android:layout_height="?attr/actionBarSize"
-                android:layout_weight="1"
-                android:background="@color/colorAccentDark"
-                app:layout_scrollFlags="scroll|enterAlways"
-                app:popupTheme="@style/AppTheme.PopupOverlay" />
-        </com.google.android.material.appbar.AppBarLayout>
-
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/favourites_list"
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:layout_marginTop="8dp"
-            android:scrollbars="none"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/search_view" />
-
-        <com.mancj.materialsearchbar.MaterialSearchBar
-            android:id="@+id/search_view"
-            style="@style/SearchBarTheme"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="8dp"
-            android:layout_marginTop="8dp"
-            android:layout_marginEnd="8dp"
-            android:fadeScrollbars="false"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent"
-            app:mt_hint="@string/search_placeholder"
-            app:mt_navIconEnabled="true"
-            app:mt_placeholder="@string/search_placeholder"
-            app:mt_roundedSearchBarEnabled="true"
-            app:mt_searchBarColor="@color/cardColor"
-            app:mt_speechMode="false" />
-    </androidx.constraintlayout.widget.ConstraintLayout>
-
-    <com.google.android.material.navigation.NavigationView
-        android:id="@+id/drawer"
-        android:layout_width="240dp"
-        android:layout_height="match_parent"
-        android:layout_gravity="start"
-        app:menu="@menu/menu_drawer" />
-</androidx.drawerlayout.widget.DrawerLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_departures.xml b/app/src/main/res/layout/activity_departures.xml
new file mode 100644
index 0000000000000000000000000000000000000000..328035a5a820483133b82c8089449684124bd5ac
--- /dev/null
+++ b/app/src/main/res/layout/activity_departures.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	android:paddingBottom="16dp">
+
+	<androidx.constraintlayout.widget.ConstraintLayout
+		android:id="@+id/departures_overlay"
+		android:layout_width="match_parent"
+		android:layout_height="match_parent">
+
+		<com.google.android.material.progressindicator.CircularProgressIndicator
+			android:id="@+id/departures_progress"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:indeterminate="true"
+			app:layout_constraintBottom_toBottomOf="parent"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toTopOf="parent" />
+
+		<ImageView
+			android:id="@+id/error_image"
+			android:layout_width="92dp"
+			android:layout_height="92dp"
+			android:visibility="gone"
+			app:layout_constraintBottom_toBottomOf="parent"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toTopOf="parent"
+			tool:ignore="ContentDescription"
+			tool:src="@drawable/error_net" />
+
+		<com.google.android.material.textview.MaterialTextView
+			android:id="@+id/error_text"
+			android:layout_width="0dp"
+			android:layout_height="wrap_content"
+			android:layout_marginStart="16dp"
+			android:layout_marginTop="8dp"
+			android:layout_marginEnd="16dp"
+			android:textAlignment="center"
+			android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
+			android:visibility="gone"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toBottomOf="@+id/error_image"
+			tool:text="No connection" />
+	</androidx.constraintlayout.widget.ConstraintLayout>
+
+	<com.google.android.material.appbar.AppBarLayout
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:fitsSystemWindows="true">
+
+		<com.google.android.material.appbar.CollapsingToolbarLayout
+			android:id="@+id/collapsing_layout"
+			style="?attr/collapsingToolbarLayoutMediumStyle"
+			android:layout_width="match_parent"
+			android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
+			app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
+			app:maxLines="2">
+
+			<com.google.android.material.appbar.MaterialToolbar
+				android:id="@+id/departures_app_bar"
+				android:layout_width="match_parent"
+				android:layout_height="?attr/actionBarSize"
+				android:elevation="0dp"
+				app:layout_collapseMode="pin" />
+
+		</com.google.android.material.appbar.CollapsingToolbarLayout>
+
+	</com.google.android.material.appbar.AppBarLayout>
+
+	<androidx.recyclerview.widget.RecyclerView
+		android:id="@+id/departures_recycler"
+		android:layout_width="match_parent"
+		android:layout_height="match_parent"
+		android:clipToPadding="false"
+		android:fitsSystemWindows="true"
+		android:visibility="gone"
+		app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_edit_favourite.xml b/app/src/main/res/layout/activity_edit_favourite.xml
deleted file mode 100644
index 68b83202b85739fae328d3d5a44d2e7c371e9565..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/activity_edit_favourite.xml
+++ /dev/null
@@ -1,77 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/dialog_favourite"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical">
-
-    <com.google.android.material.appbar.AppBarLayout
-        android:id="@+id/appbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="@dimen/appbar_padding_top"
-        android:theme="@style/AppTheme.AppBarOverlay"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <androidx.appcompat.widget.Toolbar
-            android:id="@+id/toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"
-            android:layout_weight="1"
-            android:background="@color/colorPrimary"
-            app:layout_scrollFlags="scroll|enterAlways"
-            app:popupTheme="@style/AppTheme.PopupOverlay" />
-    </com.google.android.material.appbar.AppBarLayout>
-
-    <TextView
-        android:id="@+id/name_label"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginTop="8dp"
-        android:labelFor="@id/favourite_name_edit"
-        android:text="@string/favourite_name"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/appbar" />
-
-    <EditText
-        android:id="@+id/favourite_name_edit"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginEnd="8dp"
-        android:ems="10"
-        android:importantForAutofill="no"
-        android:inputType="text"
-        android:text=""
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/name_label"
-        tools:ignore="UnusedAttribute" />
-
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/favourite_edit_list"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:layout_marginTop="8dp"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/favourite_name_edit">
-
-    </androidx.recyclerview.widget.RecyclerView>
-
-    <ProgressBar
-        android:id="@+id/favourite_edit_loading"
-        style="@style/Widget.AppCompat.ProgressBar"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        app:layout_constraintBottom_toBottomOf="@+id/favourite_edit_list"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/favourite_name_edit" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_feed_chooser.xml b/app/src/main/res/layout/activity_feed_chooser.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2995a2b237ba74aa7f1cfc7055c7b641820fbd13
--- /dev/null
+++ b/app/src/main/res/layout/activity_feed_chooser.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	tool:context="xyz.apiote.bimba.czwek.settings.feeds.FeedChooserActivity">
+
+	<androidx.constraintlayout.widget.ConstraintLayout
+		android:id="@+id/feeds_overlay"
+		android:layout_width="match_parent"
+		android:layout_height="match_parent">
+
+		<com.google.android.material.progressindicator.CircularProgressIndicator
+			android:id="@+id/progress"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:indeterminate="true"
+			app:layout_constraintBottom_toBottomOf="parent"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toTopOf="parent" />
+
+		<ImageView
+			android:id="@+id/error_image"
+			android:layout_width="92dp"
+			android:layout_height="92dp"
+			android:visibility="gone"
+			app:layout_constraintBottom_toBottomOf="parent"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toTopOf="parent"
+			tool:ignore="ContentDescription"
+			tool:src="@drawable/error_net" />
+
+		<com.google.android.material.textview.MaterialTextView
+			android:id="@+id/error_text"
+			android:layout_width="0dp"
+			android:layout_height="wrap_content"
+			android:layout_marginStart="16dp"
+			android:layout_marginTop="8dp"
+			android:layout_marginEnd="16dp"
+			android:textAlignment="center"
+			android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
+			android:visibility="gone"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toBottomOf="@+id/error_image"
+			tool:text="No connection" />
+	</androidx.constraintlayout.widget.ConstraintLayout>
+
+	<androidx.recyclerview.widget.RecyclerView
+		android:id="@+id/results_recycler"
+		android:layout_width="match_parent"
+		android:layout_height="0dp"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:layout_marginBottom="8dp"
+		android:visibility="gone"
+		app:layout_behavior="@string/appbar_scrolling_view_behavior"
+		app:layout_constraintBottom_toTopOf="@+id/button"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent" />
+
+	<Button
+		android:id="@+id/button"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginEnd="16dp"
+		android:layout_marginBottom="16dp"
+		android:text="@string/save"
+		android:visibility="gone"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_line_specify.xml b/app/src/main/res/layout/activity_line_specify.xml
deleted file mode 100644
index ce51c5661d1f2e400fc2ea279aceb915ae4310ef..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/activity_line_specify.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/main_content"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:fitsSystemWindows="true"
-    tools:context="ml.adamsprogs.bimba.activities.LineSpecifyActivity">
-
-    <com.google.android.material.appbar.AppBarLayout
-        android:id="@+id/appbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="@dimen/appbar_padding_top"
-        android:theme="@style/AppTheme.AppBarOverlay">
-
-        <androidx.appcompat.widget.Toolbar
-            android:id="@+id/toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"
-            android:layout_weight="1"
-            android:background="?attr/colorPrimary"
-            app:layout_scrollFlags="scroll|enterAlways"
-            app:popupTheme="@style/AppTheme.PopupOverlay"
-            app:title="@string/app_name">
-
-        </androidx.appcompat.widget.Toolbar>
-
-        <com.google.android.material.tabs.TabLayout
-            android:id="@+id/tabs"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <com.google.android.material.tabs.TabItem
-                android:id="@+id/tabItem"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/tab_text_line_to" />
-
-            <com.google.android.material.tabs.TabItem
-                android:id="@+id/tabItem2"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:text="@string/tab_text_line_fro" />
-
-        </com.google.android.material.tabs.TabLayout>
-    </com.google.android.material.appbar.AppBarLayout>
-
-    <androidx.viewpager.widget.ViewPager
-        android:id="@+id/container"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
-
-</androidx.coordinatorlayout.widget.CoordinatorLayout>




diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d378b8e473132ec02ff62392656497537026224
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	android:id="@+id/container"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent">
+
+	<androidx.coordinatorlayout.widget.CoordinatorLayout
+		android:layout_width="match_parent"
+		android:layout_height="match_parent">
+
+		<com.google.android.material.appbar.AppBarLayout
+			android:layout_width="match_parent"
+			android:layout_height="wrap_content">
+
+			<com.google.android.material.appbar.MaterialToolbar
+				android:id="@+id/top_app_bar"
+				android:layout_width="match_parent"
+				android:layout_height="?attr/actionBarSize"
+				app:title="" />
+		</com.google.android.material.appbar.AppBarLayout>
+
+		<androidx.constraintlayout.widget.ConstraintLayout
+			android:layout_width="match_parent"
+			android:layout_height="match_parent">
+
+			<androidx.fragment.app.FragmentContainerView
+				android:id="@+id/nav_host_fragment_activity_main"
+				android:name="androidx.navigation.fragment.NavHostFragment"
+				android:layout_width="match_parent"
+				android:layout_height="0dp"
+				app:defaultNavHost="true"
+				app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
+				app:layout_constraintEnd_toEndOf="parent"
+				app:layout_constraintStart_toStartOf="parent"
+				app:layout_constraintTop_toTopOf="parent"
+				app:navGraph="@navigation/front_navigation" />
+
+			<com.google.android.material.bottomnavigation.BottomNavigationView
+				android:id="@+id/bottom_navigation"
+				android:layout_width="match_parent"
+				android:layout_height="wrap_content"
+				android:layout_gravity="bottom"
+				app:layout_constraintBottom_toBottomOf="parent"
+				app:layout_constraintEnd_toEndOf="parent"
+				app:layout_constraintStart_toStartOf="parent"
+				app:menu="@menu/bottom_nav_menu" />
+		</androidx.constraintlayout.widget.ConstraintLayout>
+	</androidx.coordinatorlayout.widget.CoordinatorLayout>
+
+	<com.google.android.material.navigation.NavigationView
+		android:id="@+id/navigation_drawer"
+		android:layout_width="wrap_content"
+		android:layout_height="match_parent"
+		android:layout_gravity="start"
+		app:menu="@menu/drawer" />
+
+
+</androidx.drawerlayout.widget.DrawerLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_onboarding.xml b/app/src/main/res/layout/activity_onboarding.xml
new file mode 100644
index 0000000000000000000000000000000000000000..657b251858872a2863f33e5ed13e3a86eaff5d88
--- /dev/null
+++ b/app/src/main/res/layout/activity_onboarding.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	tool:context="xyz.apiote.bimba.czwek.onboarding.OnboardingActivity">
+
+	<androidx.constraintlayout.widget.Guideline
+		android:id="@+id/guideline2"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:orientation="horizontal"
+		app:layout_constraintGuide_percent=".125" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginEnd="8dp"
+		android:text="@string/onboarding_question"
+		android:textAlignment="center"
+		android:textAppearance="@style/TextAppearance.Material3.HeadlineMedium"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="@+id/guideline2" />
+
+	<Button
+		android:id="@+id/button_simple"
+		style="?attr/materialButtonOutlinedStyle"
+		android:layout_width="200dp"
+		android:layout_height="100dp"
+		android:layout_marginBottom="16dp"
+		app:cornerRadius="10dp"
+		app:layout_constraintBottom_toTopOf="@+id/guideline"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent" />
+
+	<androidx.constraintlayout.widget.Guideline
+		android:id="@+id/guideline"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:orientation="horizontal"
+		app:layout_constraintGuide_percent=".5" />
+
+	<Button
+		android:id="@+id/button_advanced"
+		style="?attr/materialButtonOutlinedStyle"
+		android:layout_width="200dp"
+		android:layout_height="100dp"
+		android:layout_marginTop="16dp"
+		app:cornerRadius="10dp"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/guideline" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginEnd="8dp"
+		android:layout_marginBottom="16dp"
+		android:text="@string/seatbelts_everyone"
+		android:textAlignment="center"
+		android:textAppearance="@style/TextAppearance.Material3.BodySmall"
+		android:textStyle="italic"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_results.xml b/app/src/main/res/layout/activity_results.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5a4a9eaf2035a901b8502d56a822ae2be4853f4d
--- /dev/null
+++ b/app/src/main/res/layout/activity_results.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	android:paddingBottom="16dp">
+
+	<androidx.constraintlayout.widget.ConstraintLayout
+		android:id="@+id/results_overlay"
+		android:layout_width="match_parent"
+		android:layout_height="match_parent">
+
+		<com.google.android.material.progressindicator.CircularProgressIndicator
+			android:id="@+id/results_progress"
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:indeterminate="true"
+			app:layout_constraintBottom_toBottomOf="parent"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toTopOf="parent" />
+
+		<ImageView
+			android:id="@+id/error_image"
+			android:layout_width="92dp"
+			android:layout_height="92dp"
+			android:visibility="gone"
+			app:layout_constraintBottom_toBottomOf="parent"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toTopOf="parent"
+			tool:ignore="ContentDescription"
+			tool:src="@drawable/error_net" />
+
+		<com.google.android.material.textview.MaterialTextView
+			android:id="@+id/error_text"
+			android:layout_width="0dp"
+			android:layout_height="wrap_content"
+			android:layout_marginStart="16dp"
+			android:layout_marginTop="8dp"
+			android:layout_marginEnd="16dp"
+			android:textAlignment="center"
+			android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
+			android:visibility="gone"
+			app:layout_constraintEnd_toEndOf="parent"
+			app:layout_constraintStart_toStartOf="parent"
+			app:layout_constraintTop_toBottomOf="@+id/error_image"
+			tool:text="No connection" />
+
+	</androidx.constraintlayout.widget.ConstraintLayout>
+
+	<com.google.android.material.appbar.AppBarLayout
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:fitsSystemWindows="true"
+		app:liftOnScroll="true">
+
+		<com.google.android.material.appbar.MaterialToolbar
+			android:id="@+id/top_app_bar"
+			android:layout_width="match_parent"
+			android:layout_height="?attr/actionBarSize"
+			app:title="@string/title_activity_results" />
+
+	</com.google.android.material.appbar.AppBarLayout>
+
+	<androidx.recyclerview.widget.RecyclerView
+		android:id="@+id/results_recycler"
+		android:layout_width="match_parent"
+		android:layout_height="match_parent"
+		android:clipToPadding="false"
+		android:fitsSystemWindows="true"
+		android:visibility="gone"
+		app:layout_behavior="@string/appbar_scrolling_view_behavior" />
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_server_chooser.xml b/app/src/main/res/layout/activity_server_chooser.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e441ede9d9dcddf5c313710d0470c9b4bc936e0f
--- /dev/null
+++ b/app/src/main/res/layout/activity_server_chooser.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	tool:context="xyz.apiote.bimba.czwek.settings.ServerChooserActivity">
+
+	<com.google.android.material.textfield.TextInputLayout
+		android:id="@+id/server_field"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="16dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="16dp"
+		android:hint="@string/bimba_server_address_hint"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent">
+
+		<com.google.android.material.textfield.TextInputEditText
+			android:layout_width="match_parent"
+			android:layout_height="wrap_content"
+			android:inputType="textUri" />
+
+	</com.google.android.material.textfield.TextInputLayout>
+
+	<com.google.android.material.textfield.TextInputLayout
+		android:id="@+id/token_field"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="16dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="16dp"
+		android:hint="@string/bimba_server_token_hint"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@id/server_field">
+
+		<com.google.android.material.textfield.TextInputEditText
+			android:layout_width="match_parent"
+			android:layout_height="wrap_content" />
+
+	</com.google.android.material.textfield.TextInputLayout>
+
+	<Button
+		android:id="@+id/button"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginTop="16dp"
+		android:text="@string/bimba_server_continue_button"
+		app:layout_constraintEnd_toEndOf="@+id/token_field"
+		app:layout_constraintStart_toStartOf="@+id/token_field"
+		app:layout_constraintTop_toBottomOf="@+id/token_field" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
deleted file mode 100644
index b5342c25185db6b54c6e668d71cd9667334a5b6d..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/activity_settings.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
-
-    <com.google.android.material.appbar.AppBarLayout
-        android:id="@+id/appbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="@dimen/appbar_padding_top"
-        android:theme="@style/AppTheme.AppBarOverlay"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <androidx.appcompat.widget.Toolbar
-            android:id="@+id/toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"
-            android:layout_weight="1"
-            android:background="?attr/colorPrimary"
-            app:layout_scrollFlags="scroll|enterAlways"
-            app:popupTheme="@style/AppTheme.PopupOverlay"
-            app:title="@string/title_activity_settings">
-
-        </androidx.appcompat.widget.Toolbar>
-    </com.google.android.material.appbar.AppBarLayout>
-
-    <fragment
-        android:id="@+id/settings_fragment"
-        android:name="ml.adamsprogs.bimba.activities.SettingsActivity$MainPreferenceFragment"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_marginEnd="8dp"
-        android:layout_marginStart="8dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/appbar" />
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/activity_stop.xml b/app/src/main/res/layout/activity_stop.xml
deleted file mode 100644
index e3edb3af00ca28936faa18d73db9c50a732294c0..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/activity_stop.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/stop_layout"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:fitsSystemWindows="true"
-    tools:context="ml.adamsprogs.bimba.activities.StopActivity">
-
-    <com.google.android.material.appbar.AppBarLayout
-        android:id="@+id/appbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="0dp"
-        android:paddingTop="@dimen/appbar_padding_top"
-        android:theme="@style/AppTheme.AppBarOverlay"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <androidx.appcompat.widget.Toolbar
-            android:id="@+id/toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"
-            android:layout_weight="1"
-            android:background="?attr/colorPrimary"
-            app:layout_scrollFlags="scroll|enterAlways"
-            app:popupTheme="@style/AppTheme.PopupOverlay"
-            app:title="@string/app_name">
-
-        </androidx.appcompat.widget.Toolbar>
-
-        <Spinner
-            android:id="@+id/dateSpinner"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="8dp"
-            android:layout_marginLeft="8dp"
-            android:layout_marginEnd="8dp"
-            android:layout_marginRight="8dp"
-            android:layout_marginBottom="8dp"
-            android:layout_weight="1"
-            android:visibility="gone" />
-    </com.google.android.material.appbar.AppBarLayout>
-
-    <include
-        android:id="@+id/banner"
-        layout="@layout/banner"
-        android:layout_width="match_parent"
-        android:layout_height="120dp"
-        android:visibility="gone"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@id/appbar" />
-
-    <ImageView
-        android:id="@+id/emptyStateIcon"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:layout_marginStart="8dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="8dp"
-        android:contentDescription="@string/departures_empty_state_icon"
-        android:tint="@color/textDarkMedium"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/banner"
-        app:srcCompat="@drawable/ic_traffic" />
-
-    <TextView
-        android:id="@+id/emptyStateText"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
-        android:text="@string/no_departures"
-        android:textColor="@color/textDarkMedium"
-        android:visibility="gone"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/emptyStateIcon" />
-
-    <ProgressBar
-        android:id="@+id/progressBar"
-        style="?android:attr/progressBarStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="8dp"
-        android:visibility="visible"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/banner" />
-
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/departuresList"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/banner" />
-
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
-        android:id="@+id/fab"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="end|bottom"
-        android:layout_margin="@dimen/fab_margin"
-        android:layout_marginEnd="16dp"
-        android:layout_marginBottom="16dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:srcCompat="@drawable/ic_favourite" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>




diff --git a/app/src/main/res/layout/activity_stop_specify.xml b/app/src/main/res/layout/activity_stop_specify.xml
deleted file mode 100644
index c71d7141f81900a26b50ef6fbf0d56a6eec10c20..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/activity_stop_specify.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    tools:context="ml.adamsprogs.bimba.activities.StopSpecifyActivity">
-
-    <ProgressBar
-        android:id="@+id/progressBar"
-        style="?android:attr/progressBarStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/appbar" />
-
-    <com.google.android.material.appbar.AppBarLayout
-        android:id="@+id/appbar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingTop="@dimen/appbar_padding_top"
-        android:theme="@style/AppTheme.AppBarOverlay"
-        app:layout_constraintTop_toTopOf="parent">
-
-        <androidx.appcompat.widget.Toolbar
-            android:id="@+id/toolbar"
-            android:layout_width="match_parent"
-            android:layout_height="?attr/actionBarSize"
-            android:layout_weight="1"
-            android:background="@color/colorPrimary"
-            app:popupTheme="@style/AppTheme.PopupOverlay"
-            app:title="@string/app_name" />
-    </com.google.android.material.appbar.AppBarLayout>
-
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/list_view"
-        android:layout_width="0dp"
-        android:layout_height="0dp"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/appbar" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>




diff --git a/app/src/main/res/layout/banner.xml b/app/src/main/res/layout/banner.xml
deleted file mode 100644
index edb12b05be6566596ba970dff8c2db13821df70b..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/banner.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="120dp"
-    android:orientation="vertical">
-
-    <View
-        android:id="@+id/banner_separator"
-        android:layout_width="fill_parent"
-        android:layout_height="1dp"
-        android:background="#90909090"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintEnd_toStartOf="parent"
-        app:layout_constraintStart_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent" />
-
-    <Button
-        android:id="@+id/banner_more"
-        style="@style/Widget.AppCompat.Button.Borderless.Colored"
-        android:layout_width="wrap_content"
-        android:layout_height="36dp"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="8dp"
-        android:text="@string/more"
-        android:textAppearance="@style/TextAppearance.AppCompat.Button"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent" />
-
-    <TextView
-        android:id="@+id/banner_text"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="24dp"
-        android:layout_marginEnd="16dp"
-        android:layout_marginBottom="20dp"
-        android:ellipsize="end"
-        android:maxLines="2"
-        android:minLines="1"
-        android:singleLine="false"
-        android:text=""
-        android:textAppearance="@style/TextAppearance.AppCompat.Body2"
-        app:layout_constraintBottom_toTopOf="@+id/banner_more"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toEndOf="@+id/banner_icon"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <ImageView
-        android:id="@+id/banner_icon"
-        android:layout_width="40dp"
-        android:layout_height="40dp"
-        android:layout_marginStart="16dp"
-        android:contentDescription="@string/vm_message_icon"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="@+id/banner_text"
-        app:srcCompat="@drawable/ic_message" />
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/departure.xml b/app/src/main/res/layout/departure.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dc95cff290d969279967a19552d8e2a10722323e
--- /dev/null
+++ b/app/src/main/res/layout/departure.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:id="@+id/departure"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content">
+
+	<ImageView
+		android:id="@+id/line_icon"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:layout_marginStart="8dp"
+		app:layout_constraintBottom_toTopOf="@+id/departure_headsign"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="@+id/departure_time"
+		tool:srcCompat="@drawable/bus_black"
+		tool:ignore="ContentDescription" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/departure_time"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintTop_toTopOf="parent"
+		tool:text="1hr" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/departure_line"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
+		app:layout_constraintStart_toEndOf="@+id/line_icon"
+		app:layout_constraintTop_toTopOf="parent"
+		tool:text="Metropolitan" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/departure_headsign"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:textAppearance="@style/TextAppearance.Material3.BodySmall"
+		app:layout_constraintStart_toStartOf="@+id/departure_line"
+		app:layout_constraintTop_toBottomOf="@+id/departure_line"
+		tool:text="» Tower Hill" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/departure_bottom_sheet.xml b/app/src/main/res/layout/departure_bottom_sheet.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0eb2ee87737e2abcc637c176d0f78a0fef6e1a8f
--- /dev/null
+++ b/app/src/main/res/layout/departure_bottom_sheet.xml
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content"
+	android:paddingBottom="16dp">
+
+	<com.google.android.material.bottomsheet.BottomSheetDragHandleView
+		android:id="@+id/drag_handle"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		app:layout_constraintTop_toTopOf="parent" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/time"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginTop="48dp"
+		android:textAppearance="@style/TextAppearance.Material3.DisplaySmall"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent"
+		tool:text="at 12:10:30" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/offset"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="4dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		android:visibility="gone"
+		app:layout_constraintBaseline_toBaselineOf="@+id/time"
+		app:layout_constraintStart_toEndOf="@+id/time"
+		tool:text="(+2 min)" />
+
+	<ImageView
+		android:id="@+id/rt_icon"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:layout_marginStart="16dp"
+		android:contentDescription="@string/realtime_content_description"
+		app:layout_constraintBottom_toBottomOf="@+id/time"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="@+id/time"
+		app:srcCompat="@drawable/radar" />
+
+	<ImageView
+		android:id="@+id/wheelchair_icon"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:layout_marginStart="8dp"
+		android:contentDescription="@string/wheelchair_content_description"
+		app:layout_constraintStart_toEndOf="@id/rt_icon"
+		app:layout_constraintTop_toTopOf="@+id/rt_icon"
+		app:srcCompat="@drawable/wheelchair" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/line"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:textAlignment="center"
+		android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@id/time" />
+
+	<ImageView
+		android:id="@+id/boarding_icon"
+		android:layout_width="16dp"
+		android:layout_height="16dp"
+		android:layout_marginEnd="8dp"
+		android:importantForAccessibility="no"
+		app:layout_constraintBottom_toBottomOf="@+id/boarding_text"
+		app:layout_constraintEnd_toStartOf="@+id/boarding_text"
+		app:layout_constraintTop_toTopOf="@+id/boarding_text"
+		app:srcCompat="@drawable/transfer" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/boarding_text"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="180dp"
+		android:layout_marginEnd="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		app:layout_constraintEnd_toEndOf="@id/middle"
+		app:layout_constraintTop_toTopOf="parent"
+		tool:text="on demand" />
+
+	<ImageView
+		android:id="@+id/speed_icon"
+		android:layout_width="16dp"
+		android:layout_height="16dp"
+		android:layout_marginEnd="8dp"
+		android:importantForAccessibility="no"
+		app:layout_constraintBottom_toBottomOf="@+id/speed_text"
+		app:layout_constraintEnd_toStartOf="@+id/speed_text"
+		app:layout_constraintTop_toTopOf="@+id/speed_text"
+		app:srcCompat="@drawable/speed" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/speed_text"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		app:layout_constraintEnd_toStartOf="@+id/middle"
+		app:layout_constraintTop_toBottomOf="@id/boarding_text"
+		tool:text="10 Vl" />
+
+	<ImageView
+		android:id="@+id/congestion_icon"
+		android:layout_width="16dp"
+		android:layout_height="16dp"
+		android:layout_marginStart="8dp"
+		android:layout_marginEnd="8dp"
+		android:importantForAccessibility="no"
+		app:layout_constraintBottom_toBottomOf="@+id/congestion_text"
+		app:layout_constraintStart_toStartOf="@+id/middle"
+		app:layout_constraintTop_toTopOf="@+id/congestion_text"
+		app:srcCompat="@drawable/traffic" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/congestion_text"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="180dp"
+		android:layout_marginEnd="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		app:layout_constraintStart_toEndOf="@id/congestion_icon"
+		app:layout_constraintTop_toTopOf="parent"
+		tool:text="smooth traffic" />
+
+	<ImageView
+		android:id="@+id/occupancy_icon"
+		android:layout_width="16dp"
+		android:layout_height="16dp"
+		android:layout_marginStart="8dp"
+		android:layout_marginEnd="8dp"
+		android:importantForAccessibility="no"
+		app:layout_constraintBottom_toBottomOf="@+id/occupancy_text"
+		app:layout_constraintStart_toStartOf="@+id/middle"
+		app:layout_constraintTop_toTopOf="@+id/occupancy_text"
+		app:srcCompat="@drawable/crowd" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/occupancy_text"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		app:layout_constraintStart_toEndOf="@id/occupancy_icon"
+		app:layout_constraintTop_toBottomOf="@id/congestion_text"
+		tool:text="empty vehicle" />
+
+	<androidx.constraintlayout.widget.Guideline
+		android:id="@+id/middle"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:orientation="vertical"
+		app:layout_constraintGuide_percent=".5" />
+
+	<androidx.constraintlayout.helper.widget.Flow
+		android:id="@+id/capabilities"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="8dp"
+		app:constraint_referenced_ids="ac,bike,voice,ticket,usb"
+		app:flow_horizontalGap="4dp"
+		app:flow_horizontalStyle="packed"
+		app:flow_verticalGap="4dp"
+		app:flow_wrapMode="chain"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/occupancy_text" />
+
+	<ImageView
+		android:id="@+id/ac"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/air_condition_content_description"
+		app:srcCompat="@drawable/ac"
+		tool:ignore="MissingConstraints" />
+
+	<ImageView
+		android:id="@+id/bike"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/bicycles_allowed_content_description"
+		app:srcCompat="@drawable/bike"
+		tool:ignore="MissingConstraints" />
+
+	<ImageView
+		android:id="@+id/voice"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/voice_announcements_content_description"
+		app:srcCompat="@drawable/voice"
+		tool:ignore="MissingConstraints" />
+
+	<ImageView
+		android:id="@+id/ticket"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/tickets_sold_content_description"
+		app:srcCompat="@drawable/ticket"
+		tool:ignore="MissingConstraints" />
+
+	<ImageView
+		android:id="@+id/usb"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/usb_charging_content_description"
+		app:srcCompat="@drawable/usb"
+		tool:ignore="MissingConstraints" />
+
+	<org.osmdroid.views.MapView
+		android:id="@+id/map"
+		android:layout_width="match_parent"
+		android:layout_height="250dp"
+		android:layout_margin="16dp"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/capabilities" />
+</androidx.constraintlayout.widget.ConstraintLayout>




diff --git a/app/src/main/res/layout/feed_bottom_sheet.xml b/app/src/main/res/layout/feed_bottom_sheet.xml
new file mode 100644
index 0000000000000000000000000000000000000000..41e7751df918a60fbb5f4f62925ae1705581ca86
--- /dev/null
+++ b/app/src/main/res/layout/feed_bottom_sheet.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	android:paddingBottom="16dp">
+
+	<com.google.android.material.bottomsheet.BottomSheetDragHandleView
+		android:id="@+id/drag_handle"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		app:layout_constraintTop_toTopOf="parent" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/title"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="48dp"
+		android:layout_marginEnd="8dp"
+		android:textAlignment="center"
+		android:textAppearance="@style/TextAppearance.Material3.DisplaySmall"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent"
+		tool:text="Poznań ZTM" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/description"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="8dp"
+		android:textAlignment="center"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/title"
+		tool:text="Feed for Poznań" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/attribution"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="8dp"
+		android:textAlignment="center"
+		android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/description"
+		tool:text="(c) Poznań" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/update_time"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="8dp"
+		android:textAlignment="center"
+		android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/attribution"
+		tool:text="Last update: 2023-01-01" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/feedinfo.xml b/app/src/main/res/layout/feedinfo.xml
new file mode 100644
index 0000000000000000000000000000000000000000..26ed2b036981ea9db8718aa65d08cde15b330ffe
--- /dev/null
+++ b/app/src/main/res/layout/feedinfo.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	android:id="@+id/feed"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content">
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/feed_name"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="16dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginBottom="16dp"
+		android:text=""
+		android:textAppearance="@style/TextAppearance.Material3.HeadlineMedium"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent" />
+
+	<com.google.android.material.materialswitch.MaterialSwitch
+		android:id="@+id/feed_switch"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="16dp"
+		android:layout_marginBottom="16dp"
+		android:text=""
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintTop_toTopOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6ace86db683233a7d0443fe2e126f2cb19cbe25b
--- /dev/null
+++ b/app/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	android:tag="@string/title_home"
+	tool:context="xyz.apiote.bimba.czwek.dashboard.ui.home.HomeFragment">
+
+	<com.mancj.materialsearchbar.MaterialSearchBar
+		android:id="@+id/search_bar"
+		style="@style/Theme.Bimba.SearchBar"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent"
+		app:mt_hint=""
+		app:mt_navIconEnabled="true"
+		app:mt_placeholder="@string/search_placeholder"
+		app:mt_roundedSearchBarEnabled="true" />
+
+	<com.google.android.material.floatingactionbutton.FloatingActionButton
+		android:id="@+id/floating_action_button"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_margin="16dp"
+		android:contentDescription="@string/home_fab_description"
+		android:src="@drawable/gps_black"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent" />
+
+	<ImageView
+		android:id="@+id/inari"
+		android:layout_width="0dp"
+		android:layout_height="0dp"
+		android:layout_marginStart="16dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="16dp"
+		android:layout_marginBottom="16dp"
+		android:alpha="0.25"
+		android:src="@drawable/inari"
+		app:layout_constraintBottom_toTopOf="@+id/floating_action_button"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/search_bar"
+		tool:ignore="ContentDescription" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/fragment_line_specify.xml b/app/src/main/res/layout/fragment_line_specify.xml
deleted file mode 100644
index 1a630b9bd7f0c510d4405a24e72d7d6f3b40249b..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/fragment_line_specify.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/constraintLayout"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    tools:context="ml.adamsprogs.bimba.activities.LineSpecifyActivity$PlaceholderFragment">
-
-    <TextView
-        android:id="@+id/section_label"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/activity_vertical_margin"
-        android:layout_marginEnd="@dimen/activity_horizontal_margin"
-        android:layout_marginStart="@dimen/activity_horizontal_margin"
-        android:layout_marginTop="@dimen/activity_vertical_margin"
-        app:layout_constraintLeft_toLeftOf="parent"
-        app:layout_constraintTop_toTopOf="@+id/constraintLayout"
-        tools:layout_constraintLeft_creator="1"
-        tools:layout_constraintTop_creator="1" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/fragment_map.xml b/app/src/main/res/layout/fragment_map.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a7e78704ab09536045868577128dfd17f0323a63
--- /dev/null
+++ b/app/src/main/res/layout/fragment_map.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	tool:context="xyz.apiote.bimba.czwek.dashboard.ui.map.MapFragment">
+
+	<org.osmdroid.views.MapView
+		android:id="@+id/map"
+		android:layout_width="match_parent"
+		android:layout_height="match_parent"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent" />
+
+	<com.google.android.material.floatingactionbutton.FloatingActionButton
+		android:id="@+id/floating_action_button"
+		style="?attr/floatingActionButtonSmallStyle"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_gravity="bottom|end"
+		android:layout_margin="16dp"
+		android:contentDescription="@string/home_fab_description"
+		android:src="@drawable/gps_black" />
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/fragment_voyage.xml b/app/src/main/res/layout/fragment_voyage.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2f62cca177204072a86e1efc21078da574c0aded
--- /dev/null
+++ b/app/src/main/res/layout/fragment_voyage.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="match_parent"
+	tool:context="xyz.apiote.bimba.czwek.dashboard.ui.voyage.VoyageFragment">
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/text_dashboard"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:textAlignment="center"
+		android:textSize="20sp"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent" />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/map_bottom_sheet.xml b/app/src/main/res/layout/map_bottom_sheet.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ee43994f8c22280a3fda028fd21149ee94138d3b
--- /dev/null
+++ b/app/src/main/res/layout/map_bottom_sheet.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content"
+	android:paddingBottom="16dp">
+
+	<com.google.android.material.bottomsheet.BottomSheetDragHandleView
+		android:id="@+id/drag_handle"
+		android:layout_width="match_parent"
+		android:layout_height="wrap_content"
+		app:layout_constraintTop_toTopOf="parent" />
+
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/title"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="48dp"
+		android:layout_marginEnd="8dp"
+		android:textAlignment="center"
+		android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent" />
+
+	<androidx.constraintlayout.widget.Group
+		android:id="@+id/stop_group"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		app:constraint_referenced_ids="change_options,departures_button,navigation_button" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/change_options"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_margin="16dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/title" />
+
+	<Button
+		android:id="@+id/departures_button"
+		style="@style/Widget.Material3.Button.TextButton.Icon"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_margin="4dp"
+		android:text="@string/show_departures"
+		app:icon="@drawable/departure"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/change_options" />
+
+	<Button
+		android:id="@+id/navigation_button"
+		style="@style/Widget.Material3.Button.TextButton.Icon"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_margin="4dp"
+		android:text="@string/open_in_maps_app"
+		app:icon="@drawable/open_outside"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/departures_button" />
+
+	<androidx.constraintlayout.widget.Group
+		android:id="@+id/vehicle_group"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		app:constraint_referenced_ids="speed_icon,speed_text,congestion_icon,congestion_text,occupancy_icon,occupancy_text,ac,bike,voice,ticket,usb" />
+
+	<ImageView
+		android:id="@+id/speed_icon"
+		android:layout_width="16dp"
+		android:layout_height="16dp"
+		android:layout_marginEnd="8dp"
+		android:importantForAccessibility="no"
+		app:layout_constraintBottom_toBottomOf="@+id/speed_text"
+		app:layout_constraintEnd_toStartOf="@+id/speed_text"
+		app:layout_constraintTop_toTopOf="@+id/speed_text"
+		app:srcCompat="@drawable/speed" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/speed_text"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		app:layout_constraintEnd_toStartOf="@+id/middle"
+		app:layout_constraintTop_toBottomOf="@id/title"
+		tool:text="10 Vl" />
+
+	<ImageView
+		android:id="@+id/congestion_icon"
+		android:layout_width="16dp"
+		android:layout_height="16dp"
+		android:layout_marginStart="8dp"
+		android:layout_marginEnd="8dp"
+		android:importantForAccessibility="no"
+		app:layout_constraintBottom_toBottomOf="@+id/congestion_text"
+		app:layout_constraintStart_toStartOf="@+id/middle"
+		app:layout_constraintTop_toTopOf="@+id/congestion_text"
+		app:srcCompat="@drawable/traffic" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/congestion_text"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		app:layout_constraintStart_toEndOf="@id/congestion_icon"
+		app:layout_constraintTop_toBottomOf="@id/title"
+		tool:text="smooth traffic" />
+
+	<ImageView
+		android:id="@+id/occupancy_icon"
+		android:layout_width="16dp"
+		android:layout_height="16dp"
+		android:layout_marginStart="8dp"
+		android:layout_marginEnd="8dp"
+		android:importantForAccessibility="no"
+		app:layout_constraintBottom_toBottomOf="@+id/occupancy_text"
+		app:layout_constraintStart_toStartOf="@+id/middle"
+		app:layout_constraintTop_toTopOf="@+id/occupancy_text"
+		app:srcCompat="@drawable/crowd" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/occupancy_text"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
+		app:layout_constraintStart_toEndOf="@id/occupancy_icon"
+		app:layout_constraintTop_toBottomOf="@id/congestion_text"
+		tool:text="empty vehicle" />
+
+	<androidx.constraintlayout.widget.Guideline
+		android:id="@+id/middle"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:orientation="vertical"
+		app:layout_constraintGuide_percent=".5" />
+
+	<androidx.constraintlayout.helper.widget.Flow
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="16dp"
+		android:layout_marginEnd="8dp"
+		app:constraint_referenced_ids="ac,bike,voice,ticket,usb"
+		app:flow_horizontalGap="4dp"
+		app:flow_horizontalStyle="packed"
+		app:flow_verticalGap="4dp"
+		app:flow_wrapMode="chain"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toBottomOf="@+id/occupancy_text" />
+
+	<ImageView
+		android:id="@+id/ac"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/air_condition_content_description"
+		app:srcCompat="@drawable/ac"
+		tool:ignore="MissingConstraints" />
+
+	<ImageView
+		android:id="@+id/bike"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/bicycles_allowed_content_description"
+		app:srcCompat="@drawable/bike"
+		tool:ignore="MissingConstraints" />
+
+	<ImageView
+		android:id="@+id/voice"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/voice_announcements_content_description"
+		app:srcCompat="@drawable/voice"
+		tool:ignore="MissingConstraints" />
+
+	<ImageView
+		android:id="@+id/ticket"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/tickets_sold_content_description"
+		app:srcCompat="@drawable/ticket"
+		tool:ignore="MissingConstraints" />
+
+	<ImageView
+		android:id="@+id/usb"
+		android:layout_width="24dp"
+		android:layout_height="24dp"
+		android:contentDescription="@string/usb_charging_content_description"
+		app:srcCompat="@drawable/usb"
+		tool:ignore="MissingConstraints" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>




diff --git a/app/src/main/res/layout/result.xml b/app/src/main/res/layout/result.xml
new file mode 100644
index 0000000000000000000000000000000000000000..01fcf7e803bb9022ef16c39446fc50f1d5814e0c
--- /dev/null
+++ b/app/src/main/res/layout/result.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:id="@+id/suggestion"
+	android:layout_width="match_parent"
+	android:layout_height="wrap_content">
+
+	<ImageView
+		android:id="@+id/suggestion_image"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginBottom="8dp"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent"
+		tool:ignore="ContentDescription" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/suggestion_title"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:text=""
+		android:textAppearance="@style/Theme.Bimba.SearchResult.Title"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toEndOf="@+id/suggestion_image"
+		app:layout_constraintTop_toTopOf="parent" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/suggestion_description"
+		style="@style/Theme.Bimba.SearchResult.Description"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginEnd="8dp"
+		android:text=""
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="@+id/suggestion_title"
+		app:layout_constraintTop_toBottomOf="@+id/suggestion_title" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/row_departure.xml b/app/src/main/res/layout/row_departure.xml
deleted file mode 100644
index 97799f72f76c48eaf9c07f349817cb8f5540494c..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/row_departure.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/departureRow"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    tools:layout_editor_absoluteX="0dp"
-    tools:layout_editor_absoluteY="25dp">
-
-    <TextView
-        android:id="@+id/lineNumber"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="8dp"
-        android:layout_marginEnd="16dp"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="8dp"
-        android:text=""
-        android:textAppearance="@style/TextAppearance.AppCompat.Title"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/departureTime"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <ImageView
-        android:id="@+id/departureTypeIcon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:layout_marginEnd="8dp"
-        android:contentDescription="@string/departure_type_icon_description"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <TextView
-        android:id="@+id/departureTime"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="64dp"
-        android:layout_marginTop="8dp"
-        android:text="@string/departure_row_getting_departures"
-        android:textAppearance="@style/TextAppearance.AppCompat.Headline"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <TextView
-        android:id="@+id/departureDirection"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="8dp"
-        android:text=""
-        app:layout_constraintStart_toStartOf="@+id/departureTime"
-        app:layout_constraintTop_toBottomOf="@+id/departureTime" />
-
-    <ImageView
-        android:id="@+id/departureInfoIcon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="8dp"
-        android:contentDescription="@string/departure_info"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/departureFloorIcon"
-        app:srcCompat="@drawable/ic_info" />
-
-    <ImageView
-        android:id="@+id/departureFloorIcon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="8dp"
-        android:contentDescription="@string/departure_floor"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:srcCompat="@drawable/ic_low_floor" />
-
-    <ImageView
-        android:id="@+id/ticketMachineIcon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="8dp"
-        android:contentDescription="@string/ticket_machine_icon"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/departureInfoIcon" />
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/row_favourite.xml b/app/src/main/res/layout/row_favourite.xml
deleted file mode 100644
index 55f434bf6bf45f264e38c57fcacc3713a855de5a..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/row_favourite.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/favourite_card"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_margin="4dp"
-    android:foreground="?android:attr/selectableItemBackground"
-    tools:layout_editor_absoluteX="8dp"
-    tools:layout_editor_absoluteY="128dp">
-
-    <View
-        android:id="@+id/selected_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/colorAccent"
-        android:visibility="invisible" />
-
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <TextView
-            android:id="@+id/favourite_name"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="21dp"
-            android:text=""
-            android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
-            app:layout_constraintStart_toStartOf="@+id/favourite_time"
-            app:layout_constraintTop_toTopOf="parent"
-            tools:layout_editor_absoluteX="16dp"
-            tools:layout_editor_absoluteY="21dp" />
-
-        <TextView
-            android:id="@+id/favourite_time"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:ellipsize="end"
-            android:text="@string/loading"
-            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
-            app:layout_constraintStart_toStartOf="@+id/favourite_line"
-            app:layout_constraintTop_toBottomOf="@+id/favourite_name" />
-
-        <TextView
-            android:id="@+id/favourite_line"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="16dp"
-            android:layout_marginEnd="8dp"
-            android:layout_marginBottom="16dp"
-            android:ellipsize="end"
-            android:text=""
-            android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toStartOf="@+id/ticketMachineIcon"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/favourite_time" />
-
-        <ImageView
-            android:id="@+id/departureTypeIcon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginEnd="8dp"
-            android:layout_marginBottom="8dp"
-            android:contentDescription="@string/departure_type_icon_description"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent" />
-
-        <ImageView
-            android:id="@+id/departureFloorIcon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginEnd="8dp"
-            android:layout_marginBottom="8dp"
-            android:contentDescription="@string/departure_floor"
-            android:visibility="gone"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toStartOf="@+id/departureTypeIcon"
-            app:srcCompat="@drawable/ic_low_floor" />
-
-        <ImageView
-            android:id="@+id/ticketMachineIcon"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginEnd="8dp"
-            android:layout_marginBottom="8dp"
-            android:contentDescription="@string/ticket_machine_icon"
-            android:visibility="gone"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toStartOf="@+id/departureFloorIcon" />
-
-        <ImageView
-            android:id="@+id/favourite_more_button"
-            android:layout_width="24dp"
-            android:layout_height="24dp"
-            android:layout_marginTop="8dp"
-            android:layout_marginEnd="8dp"
-            android:contentDescription="@string/favourite_row_more_button"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toTopOf="parent"
-            app:srcCompat="@drawable/ic_more" />
-    </androidx.constraintlayout.widget.ConstraintLayout>
-
-</androidx.cardview.widget.CardView>
\ No newline at end of file




diff --git a/app/src/main/res/layout/row_favourite_edit.xml b/app/src/main/res/layout/row_favourite_edit.xml
deleted file mode 100644
index 18e99b529d051bc5490f8f6826e8e9acbbdd8568..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/row_favourite_edit.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-
-    <TextView
-        android:id="@+id/favourite_edit_row"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="16dp"
-        android:layout_marginEnd="16dp"
-        android:layout_marginBottom="16dp"
-        android:text=""
-        android:textAlignment="viewStart"
-        android:textAppearance="@style/TextAppearance.AppCompat"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toStartOf="@+id/favourite_edit_delete"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <ImageView
-        android:id="@+id/favourite_edit_delete"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="16dp"
-        android:layout_marginEnd="8dp"
-        android:layout_marginBottom="16dp"
-        android:contentDescription="@string/favourite_element_delete_button"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        app:srcCompat="@drawable/ic_delete" />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/row_shed.xml b/app/src/main/res/layout/row_shed.xml
deleted file mode 100644
index 4be60699faeef456d8a654e9e1133d9debe00f1a..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/row_shed.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/shed_row"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_margin="4dp"
-    android:foreground="?android:attr/selectableItemBackground"
-    app:cardElevation="2dp">
-
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <TextView
-            android:id="@+id/stop_code"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="8dp"
-            android:layout_marginTop="8dp"
-            android:text=""
-            android:textAppearance="@style/TextAppearance.AppCompat.Headline"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent" />
-
-        <TextView
-            android:id="@+id/stop_headlines"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="6dp"
-            android:layout_marginEnd="8dp"
-            android:layout_marginStart="8dp"
-            android:layout_marginTop="6dp"
-            android:text=""
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/stop_code" />
-    </androidx.constraintlayout.widget.ConstraintLayout>
-</androidx.cardview.widget.CardView>
\ No newline at end of file




diff --git a/app/src/main/res/layout/row_suggestion.xml b/app/src/main/res/layout/row_suggestion.xml
deleted file mode 100644
index 6c2b77d5f75e48124c32f4a5c74d57c598a50067..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/row_suggestion.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/row_suggestion"
-    android:layout_width="match_parent"
-    android:layout_height="48dp"
-    android:foreground="?android:attr/selectableItemBackground"
-    android:orientation="vertical">
-
-
-    <ImageView
-        android:id="@+id/suggestion_row_image"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginTop="8dp"
-        android:layout_marginBottom="8dp"
-        android:contentDescription="@string/suggestion_row_image"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <TextView
-        android:id="@+id/suggestion_row_text"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginTop="8dp"
-        android:text=""
-        android:textAppearance="@style/TextAppearance.AppCompat.SearchResult.Title"
-        app:layout_constraintStart_toEndOf="@+id/suggestion_row_image"
-        app:layout_constraintTop_toTopOf="parent" />
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/suggestion.xml b/app/src/main/res/layout/suggestion.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d681d33fae944bf52f8243a589aab9b1aefdcce
--- /dev/null
+++ b/app/src/main/res/layout/suggestion.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:id="@+id/suggestion"
+	android:layout_width="match_parent"
+	android:layout_height="72dp">
+
+	<ImageView
+		android:id="@+id/suggestion_image"
+		android:layout_width="wrap_content"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginBottom="8dp"
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintStart_toStartOf="parent"
+		app:layout_constraintTop_toTopOf="parent"
+		tool:ignore="ContentDescription" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/suggestion_title"
+		android:layout_width="0dp"
+		android:layout_height="wrap_content"
+		android:layout_marginStart="8dp"
+		android:layout_marginTop="8dp"
+		android:layout_marginEnd="8dp"
+		android:text=""
+		android:textAppearance="@style/Theme.Bimba.SearchResult.Title"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toEndOf="@+id/suggestion_image"
+		app:layout_constraintTop_toTopOf="parent" />
+
+	<com.google.android.material.textview.MaterialTextView
+		android:id="@+id/suggestion_description"
+		style="@style/Theme.Bimba.SearchResult.Description"
+		android:layout_width="0dp"
+		android:layout_height="0dp"
+		android:layout_marginEnd="8dp"
+		android:ellipsize="end"
+		android:maxLines="4"
+		android:text=""
+		app:layout_constraintBottom_toBottomOf="parent"
+		app:layout_constraintEnd_toEndOf="parent"
+		app:layout_constraintStart_toStartOf="@+id/suggestion_title"
+		app:layout_constraintTop_toBottomOf="@+id/suggestion_title" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file




diff --git a/app/src/main/res/layout/toolbar_spinner_item.xml b/app/src/main/res/layout/toolbar_spinner_item.xml
deleted file mode 100644
index 1cb3890d88df2edaeec0cf238d7d7afb271c3f9c..0000000000000000000000000000000000000000
--- a/app/src/main/res/layout/toolbar_spinner_item.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/text"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:ellipsize="end"
-    android:singleLine="true"
-    android:textAlignment="inherit"
-    android:textColor="@color/text_on_toolbar" />




diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3631e523fcafffa65395d79c36b61911ef55aeda
--- /dev/null
+++ b/app/src/main/res/menu/bottom_nav_menu.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+	<item
+		android:id="@+id/navigation_map"
+		android:icon="@drawable/map_outline"
+		android:title="@string/title_map" />
+	<item
+		android:id="@+id/navigation_home"
+		android:icon="@drawable/home_outline"
+		android:title="@string/title_home" />
+	<!-- todo [voyage planning]
+	<item
+		android:id="@+id/navigation_voyage"
+		android:icon="@drawable/voyage_outline"
+		android:title="@string/title_voyage" />-->
+</menu>
\ No newline at end of file




diff --git a/app/src/main/res/menu/drawer.xml b/app/src/main/res/menu/drawer.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1b5fd35ca8d68a9c9a1937534cd1188ab25e7703
--- /dev/null
+++ b/app/src/main/res/menu/drawer.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+	<item
+		android:id="@+id/drawer_feeds"
+		android:title="@string/title_feeds">
+		<menu>
+			<item
+				android:id="@+id/drawer_servers"
+				android:checkable="true"
+				android:icon="@drawable/feeds_servers"
+				android:title="@string/title_servers" />
+			<item
+				android:id="@+id/drawer_cities"
+				android:checkable="true"
+				android:icon="@drawable/feeds_cities"
+				android:title="@string/title_cities" />
+		</menu>
+	</item>
+	<!-- other settings -->
+</menu>
\ No newline at end of file




diff --git a/app/src/main/res/menu/favourite_actions.xml b/app/src/main/res/menu/favourite_actions.xml
deleted file mode 100644
index bf229e060737d7e460e0ce3529001eec33b63c61..0000000000000000000000000000000000000000
--- a/app/src/main/res/menu/favourite_actions.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item
-        android:id="@+id/favourite_edit"
-        android:orderInCategory="100"
-        android:title="@string/action_edit" />
-    <item
-        android:id="@+id/favourite_delete"
-        android:orderInCategory="200"
-        android:title="@string/action_delete" />
-</menu>
\ No newline at end of file




diff --git a/app/src/main/res/menu/menu_drawer.xml b/app/src/main/res/menu/menu_drawer.xml
deleted file mode 100644
index 97188f56a4a54264e7c38e98989bbe959d299c4e..0000000000000000000000000000000000000000
--- a/app/src/main/res/menu/menu_drawer.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <!--<group android:id="@+id/drawer_group_activities">
-        <item
-            android:id="@+id/drawer_home"
-            android:icon="@drawable/ic_home"
-            android:title="@string/home" />
-    </group>-->
-    <group>
-        <item
-            android:id="@+id/drawer_refresh"
-            android:icon="@drawable/ic_refresh"
-            android:title="@string/refresh" />
-        <!--<item
-            android:id="@+id/drawer_help"
-            android:icon="@drawable/ic_help"
-            android:title="@string/help" />-->
-        <item
-            android:id="@+id/drawer_settings"
-            android:icon="@drawable/ic_settings"
-            android:title="@string/settings"
-            />
-    </group>
-    <group android:enabled="false">
-        <item
-            android:id="@+id/drawer_validity_since"
-            android:title="" />
-        <item
-            android:id="@+id/drawer_validity_till"
-            android:title="" />
-    </group>
-</menu>
\ No newline at end of file




diff --git a/app/src/main/res/menu/menu_favourite_merge.xml b/app/src/main/res/menu/menu_favourite_merge.xml
deleted file mode 100644
index 9342fb336b87d362d276538d787572c1e907dc59..0000000000000000000000000000000000000000
--- a/app/src/main/res/menu/menu_favourite_merge.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
-    <item
-        android:id="@+id/action_merge"
-        android:orderInCategory="100"
-        android:title="@string/action_merge"
-        android:icon="@drawable/ic_merge"
-        app:showAsAction="always" />
-</menu>
\ No newline at end of file




diff --git a/app/src/main/res/menu/menu_stop.xml b/app/src/main/res/menu/menu_stop.xml
deleted file mode 100644
index f5eeafa161d8425f01c97b62b4816477ecc797e0..0000000000000000000000000000000000000000
--- a/app/src/main/res/menu/menu_stop.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    tools:context="ml.adamsprogs.bimba.activities.StopActivity">
-    <item
-        android:id="@+id/action_change_type"
-        android:orderInCategory="100"
-        android:title="@string/action_change_type"
-        android:icon="@drawable/ic_timetable_full"
-        app:showAsAction="always" />
-</menu>




diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
index f26e79972c16204e3c29ca8686c84c8e17047863..a9744c7cd4682fe9080a4a27e8f4859f501f06eb 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ




diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
index 1ef879eb9735fc3de899f011625881cf535c711b..6364fe6da49d9ff739c08de256cb37a4d8a5c5b0 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ




diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
index 97892c1a73464d78ebaf32f6b008b36c92b85d38..d19adfb1c0fa38628e439d78e6262243a6df3910 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ




diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
index 201d7b04f97aed589ad7c6f6c53cb414a9504572..c1c8209e7415618e90b871ba3e74dfb25a1d9e7d 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ




diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index 1754a35d58a6965a198441317a9f2bea4280f512..7d9006cfca07b8dfc460bf137eae0b166a20cbfd 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ




diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
index ce24ee2d42727940dcba4567849562839530a27b..b242332300544ba52b80329f9dc7fe9973714a57 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ




diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 1029f94018ee1f94f43dc68e45ebdcca7ae67dbd..03b6b50be1b0316ed59ff6ef31113213b3741e6f 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ




diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
index 79dded633e2021ec81e58e7be6aa4bed5a564940..a5286e592e3f3f3fa753ac4ed58e177081a4ffde 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ




diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index d3b73fa5e4376f81d9e7dc824cf87993fca770e8..0ffae16cd06387530a542a006f798ae1e9a04f32 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ




diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
index 1586dc63387afea8dcc76f31f0d51bab07308a12..2fc5cda344d134cde5c05927ae56b0b98e1f8cff 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ




diff --git a/app/src/main/res/navigation/front_navigation.xml b/app/src/main/res/navigation/front_navigation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7dd5662bedc71ec157a816703d9b2402048f5186
--- /dev/null
+++ b/app/src/main/res/navigation/front_navigation.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<navigation xmlns:android="http://schemas.android.com/apk/res/android"
+	xmlns:app="http://schemas.android.com/apk/res-auto"
+	xmlns:tool="http://schemas.android.com/tools"
+	android:id="@+id/front_navigation"
+	app:startDestination="@+id/navigation_home">
+
+	<fragment
+		android:id="@+id/navigation_home"
+		android:name="xyz.apiote.bimba.czwek.dashboard.ui.home.HomeFragment"
+		android:label="@string/title_home"
+		tool:layout="@layout/fragment_home" />
+
+	<fragment
+		android:id="@+id/navigation_map"
+		android:name="xyz.apiote.bimba.czwek.dashboard.ui.map.MapFragment"
+		android:label="@string/title_map"
+		tool:layout="@layout/fragment_map" />
+
+	<fragment
+		android:id="@+id/navigation_voyage"
+		android:name="xyz.apiote.bimba.czwek.dashboard.ui.voyage.VoyageFragment"
+		android:label="@string/title_voyage"
+		tool:layout="@layout/fragment_voyage" />
+</navigation>
\ No newline at end of file




diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 1837105e06b078e212608ec54f3543aeacafedb1..d715893aa6f22b49f7237f704316c3c47ed9c19e 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,21 +1,77 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <color name="colorPrimary">#3a3a3b</color>
-    <color name="colorPrimaryDark">#141415</color>
-    <color name="colorAccent">#54af39</color>
-    <color name="colorAccentDark">#197f00</color>
-    <color name="colorAccent2">#be7e3e</color>
+	<color name="bimba_grey">#3a3a3b</color>
+	<color name="bimba_grey_dark">#141415</color>
+	<color name="bimba_green">#54af39</color>
+	<color name="bimba_green_container">#9afa79</color>
+	<color name="bimba_green_container_text">#032100</color>
+	<color name="bimba_green_dark">#197f00</color>
+	<color name="bimba_orange">#be7e3e</color>
+	<color name="black">#FF000000</color>
+	<color name="white">#FFFFFFFF</color>
 
-    <color name="zoneA">#00a650</color>
-    <color name="zoneB">#ed1c24</color>
-    <color name="zoneC">#ffc107</color>
+	<color name="seed">#54af39</color>
+	<color name="md_theme_light_primary">#1A6D00</color> <!-- 40 -->
+	<color name="md_theme_light_onPrimary">#FFFFFF</color> <!-- 100 -->
+	<color name="md_theme_light_primaryContainer">#9AFA79</color> <!-- 90 -->
+	<color name="md_theme_light_onPrimaryContainer">#032100</color> <!-- 10 -->
+	<color name="md_theme_light_secondary">#6A5F00</color> <!-- 40 -->
+	<color name="md_theme_light_onSecondary">#FFFFFF</color> <!-- 100 -->
+	<color name="md_theme_light_secondaryContainer">#F9E447</color> <!-- 90 -->
+	<color name="md_theme_light_onSecondaryContainer">#201C00</color> <!-- 10 -->
+	<color name="md_theme_light_tertiary">#8C4F00</color> <!-- 40 -->
+	<color name="md_theme_light_onTertiary">#FFFFFF</color> <!-- 100 -->
+	<color name="md_theme_light_tertiaryContainer">#FFDCC0</color> <!-- 90 -->
+	<color name="md_theme_light_onTertiaryContainer">#2D1600</color> <!-- 10 -->
 
-    <color name="tram">#00adef</color>
-    <color name="bus">#c4212a</color>
-    <color name="text_on_toolbar">#ffffff</color>
+	<color name="md_theme_light_error">#BA1A1A</color>
+	<color name="md_theme_light_errorContainer">#FFDAD6</color>
+	<color name="md_theme_light_onError">#FFFFFF</color>
+	<color name="md_theme_light_onErrorContainer">#410002</color>
 
-    <color name="textDark">#de000000</color>
-    <color name="textDarkMedium">#99000000</color>
-    <color name="textDarkDisabled">#45000000</color>
-    <color name="cardColor">#ffffff</color>
-</resources>
+	<color name="md_theme_light_background">#FCFCFF</color> <!-- primary 99 -->
+	<color name="md_theme_light_onBackground">#001D33</color> <!-- primary 10 -->
+	<color name="md_theme_light_surface">#FCFCFF</color> <!-- primary 99 -->
+	<color name="md_theme_light_onSurface">#001D33</color> <!-- primary 10 -->
+	<color name="md_theme_light_surfaceVariant">#DFE4D7</color> <!-- neutral 90 -->
+	<color name="md_theme_light_onSurfaceVariant">#43483F</color> <!-- neutral 30 -->
+	<color name="md_theme_light_outline">#73796E</color> <!-- neutral 50 -->
+	<color name="md_theme_light_inverseOnSurface">#E8F2FF</color> <!-- neutral 95 -->
+	<color name="md_theme_light_inverseSurface">#003353</color> <!-- neutral 20 -->
+	<color name="md_theme_light_inversePrimary">#7FDC60</color> <!-- 80 -->
+	<color name="md_theme_light_shadow">#000000</color> <!-- 0 -->
+	<color name="md_theme_light_surfaceTint">#1A6D00</color> <!-- primary 40 -->
+	<color name="md_theme_light_surfaceTintColor">#1A6D00</color> <!-- primary 40 -->
+
+	<color name="md_theme_dark_primary">#7FDC60</color> <!-- 80 -->
+	<color name="md_theme_dark_onPrimary">#093900</color> <!-- 20 -->
+	<color name="md_theme_dark_primaryContainer">#115300</color> <!-- 30 -->
+	<color name="md_theme_dark_onPrimaryContainer">#9AFA79</color> <!-- 90 -->
+	<color name="md_theme_dark_secondary">#DCC82A</color> <!-- 80 -->
+	<color name="md_theme_dark_onSecondary">#373100</color> <!-- 20 -->
+	<color name="md_theme_dark_secondaryContainer">#504700</color> <!-- 30 -->
+	<color name="md_theme_dark_onSecondaryContainer">#F9E447</color> <!-- 90 -->
+	<color name="md_theme_dark_tertiary">#FFB875</color> <!-- 80 -->
+	<color name="md_theme_dark_onTertiary">#4B2800</color> <!-- 20 -->
+	<color name="md_theme_dark_tertiaryContainer">#6B3B00</color> <!-- 30 -->
+	<color name="md_theme_dark_onTertiaryContainer">#FFDCC0</color> <!-- 90 -->
+
+	<color name="md_theme_dark_error">#FFB4AB</color>
+	<color name="md_theme_dark_errorContainer">#93000A</color>
+	<color name="md_theme_dark_onError">#690005</color>
+	<color name="md_theme_dark_onErrorContainer">#FFDAD6</color>
+
+	<color name="md_theme_dark_background">#001D33</color> <!-- primary 10 -->
+	<color name="md_theme_dark_onBackground">#CEE5FF</color> <!-- primary 90 -->
+	<color name="md_theme_dark_surface">#001D33</color> <!-- primary 10 -->
+	<color name="md_theme_dark_onSurface">#CEE5FF</color> <!-- primary 90 -->
+	<color name="md_theme_dark_surfaceVariant">#43483F</color> <!-- neutral 30 -->
+	<color name="md_theme_dark_onSurfaceVariant">#C3C8BC</color> <!-- -->
+	<color name="md_theme_dark_outline">#8D9387</color> <!-- unused -->
+	<color name="md_theme_dark_inverseOnSurface">#001D33</color> <!-- primary 10 -->
+	<color name="md_theme_dark_inverseSurface">#CEE5FF</color> <!-- primary 90 -->
+	<color name="md_theme_dark_inversePrimary">#1A6D00</color> <!-- primary 40 -->
+	<color name="md_theme_dark_shadow">#000000</color> <!-- 0 -->
+	<color name="md_theme_dark_surfaceTint">#7FDC60</color> <!-- primary 80 -->
+	<color name="md_theme_dark_surfaceTintColor">#7FDC60</color> <!-- primary 80 -->
+</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
deleted file mode 100644
index d1cd0246f80ac882c028743baba512892ebf7262..0000000000000000000000000000000000000000
--- a/app/src/main/res/values/dimens.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<resources>
-    <dimen name="activity_horizontal_margin">16dp</dimen>
-    <dimen name="activity_vertical_margin">16dp</dimen>
-    <dimen name="fab_margin">16dp</dimen>
-    <dimen name="appbar_padding_top">8dp</dimen>
-</resources>




diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 658e61ad08d71e4210f3055d01d01be567e76430..f32859adeab279291dc0da8294a9124ae7224571 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,76 +1,87 @@
 <resources>
-    <string name="app_name" translatable="false">Bimba</string>
-    <string name="timetable_downloaded">New timetable downloaded</string>
-    <string name="title_activity_stop" translatable="false">StopActivity</string>
-    <string name="action_change_type">Type</string>
-    <string name="departure_type_icon_description" translatable="false">departure type (timetable, VM)</string>
-    <string name="departure_to">→ %1$s</string>
-    <string name="departure_to_line">%1$s → %2$s</string>
-    <string name="departure_at">At %1$s</string>
-    <string name="timetable_downloading">Downloading timetable</string>
-    <string name="timetable_downloading_progress" translatable="false">%1$1.2f MiB/%2$1.2f MiB</string>
-    <string name="timetable_decompressing">Decompressing timetable</string>
-    <string name="search_placeholder">Stop…</string>
-    <string name="no_connectivity_cant_update">No connectivity – can’t update timetable</string>
-    <string name="no_connectivity">No connectivity</string>
-    <string name="timetable_up_to_date">Timetable is up-to-date</string>
-    <string name="error_try_later">Error. Try again later</string>
-    <string name="now">Now</string>
-    <string name="stop_already_fav">This stop is already in favourites</string>
-    <string name="favourite_row_more_button" translatable="false">favourite row more button</string>
-    <string name="action_edit">Edit</string>
-    <string name="action_delete">Delete</string>
-    <string name="favourite_name">Favourite name</string>
-    <string name="edit_favourite_title">Edit ‘%1$s’</string>
-    <string name="favourite_element_delete_button" translatable="false">favourite element delete button</string>
-    <string name="no_next_departure">No next departure</string>
-    <string name="action_merge">Merge</string>
-    <string name="merge_favourites">Merge favourites</string>
-    <string name="loading">Loading…</string>
-    <string name="departure_in__singular_genitive">In %1$s minute</string>
-    <string name="departure_in__plural_genitive">In %1$s minutes</string>
-    <string name="departure_in__plural_nominative">In %1$s minutes</string>
-
-    <string name="refresh">Update timetable</string>
-    <string name="title_activity_help">Help</string>
-    <string name="departure_row_getting_departures">Getting departures…</string>
-    <string name="valid_since">Valid since %1$s</string>
-    <string name="valid_till">Valid till %1$s</string>
-    <string name="departure_floor" translatable="false">departure floor type (lowFloor)</string>
-    <string name="departure_info" translatable="false">departure info icon</string>
-
-    <string name="no_departures">No departures</string>
-    <string name="title_activity_main" translatable="false">LineSpecifyActivity</string>
-    <string name="tab_text_line_to">To</string>
-    <string name="tab_text_line_fro">Fro</string>
-    <string name="timetable_validity_finished">Timetable validity has ended. Connect to the Internet to download a new one in order to continue.</string>
-    <string name="timetable_validity_today">Timetable validity ends today.</string>
-    <string name="timetable_validity_tomorrow">Timetable validity ends tomorrow.</string>
-    <string name="just_departed">Just departed</string>
-    <string name="validity_offline_unavailable">Offline timetable unavailable</string>
-    <string name="pref_category_timetable">Timetable</string>
-    <string name="timetable_source_url" translatable="false">https://bimba.tk/gtfs</string>
-    <string name="key_timetable_source_url" translatable="false">key_timetable_source_url</string>
-    <string name="title_timetable_source_url">Timetable source</string>
-    <string name="title_activity_settings">Settings</string>
-    <string name="settings">Settings</string>
-    <string name="key_timetable_automatic_update" translatable="false">key_timetable_automatic_update</string>
-    <string name="title_timetable_automatic_update">Automatic updates</string>
-
-    <string name="Mon">Mon</string>
-    <string name="Tue">Tue</string>
-    <string name="Wed">Wed</string>
-    <string name="Thu">Thu</string>
-    <string name="Fri">Fri</string>
-    <string name="Sat">Sat</string>
-    <string name="Sun">Sun</string>
-    <string name="summary_timetable_automatic_update">Automatically check for and download timetable updates</string>
-    <string name="server_error">Server error</string>
-    <string name="suggestion_row_image" translatable="false">suggestion row image</string>
-    <string name="nothing_found">Not found</string>
-    <string name="departures_empty_state_icon" translatable="false">departures empty state icon</string>
-    <string name="in_a_moment">In a moment</string>
-    <string name="more">More</string>
-    <string name="vm_message_icon" translatable="false">vm message icon</string>
-    <string name="ticket_machine_icon" translatable="false">ticket machine icon</string>
-</resources>
+	<string name="app_name">Bimba</string>
+	<string name="title_home">Home</string>
+	<string name="title_map">Map</string>
+	<string name="title_voyage">Voyage</string>
+	<string name="home_fab_description">GPS icon</string>
+	<string name="search_placeholder">Search stops and lines</string>
+	<string name="title_activity_results">Results</string>
+	<string name="cont">Continue</string>
+	<string name="save">Save</string>
+	<string name="error_400">The application made a malformed request</string>
+	<string name="error_401">A token is needed to use this server</string>
+	<string name="error_403">The token you provided is incorrect</string>
+	<string name="error_404">Not found</string>
+	<string name="error_429">Rate limit exceeded. Try again later</string>
+	<string name="error_50x">There was an error on the sever. Try again later</string>
+	<string name="error_unknown">Unknown error happened</string>
+	<string name="error_connecting">Error connecting to the server. Try again later</string> <!-- send a bug report to bimba@git.apiote.xyz, details are: url=$URL, response=$response -->
+	<string name="error_offline">You are offline. Connect to the Internet</string>
+	<string name="error_gps">Cannot obtain location</string>
+	<string name="no_departures">No departures</string>
+	<string name="waiting_position">waiting for position</string>
+	<string name="vehicle_headsign">%s » %s</string>
+	<string name="vehicle_headsign_content_description">%s towards %s</string>
+	<string name="speed_in_km_per_h">%.3f km/h</string>
+	<string name="congestion_unknown">unknown</string>
+	<string name="congestion_smooth">smooth</string>
+	<string name="congestion_stop_and_go">stop and go</string>
+	<string name="congestion_congestion">congestion</string>
+	<string name="congestion_jams">jams</string>
+	<string name="occupancy_unknown">unknown</string>
+	<string name="occupancy_empty">empty</string>
+	<string name="occupancy_many_seats">many seats</string>
+	<string name="occupancy_few_seats">few seats</string>
+	<string name="occupancy_standing_only">standing only</string>
+	<string name="occupancy_crowded">crowded</string>
+	<string name="occupancy_full">full</string>
+	<string name="occupancy_wont_let">won’t let in</string>
+	<string name="stop_title">%s [%s]</string>
+	<string name="no_map_app">No maps app installed</string>
+	<string name="departure_headsign">» %s</string>
+	<string name="departure_headsign_content_description">towards %s</string>
+	<string name="departure_momentarily">momentarily</string>
+	<string name="departure_departed">departed</string>
+	<string name="departure_now">now</string>
+	<string name="at_time">at %02d:%02d</string>
+	<string name="at_time_realtime">at %02d:%02d:%02d</string>
+	<string name="on_demand">on demand</string>
+	<string name="no_boarding">no boarding</string>
+	<string name="on_boarding">on-boarding</string>
+	<string name="off_boarding">off-boarding</string>
+	<string name="boarding">can board</string>
+	<string name="line_headsigns">%s «» %s</string>
+	<string name="line_headsigns_content_description">between %s and %s</string>
+	<string name="stops_nearby">Stops nearby</string>
+	<string name="results_for">Results for ‘%s’</string>
+	<string name="bimba_server_address_hint">Bimba server</string>
+	<string name="bimba_server_token_hint">Token</string>
+	<string name="bimba_server_continue_button">Continue</string>
+	<string name="realtime_content_description">departure is realtime</string>
+	<string name="wheelchair_content_description">vehicle is wheelchair accessible</string>
+	<string name="air_condition_content_description">air conditioning</string>
+	<string name="bicycles_allowed_content_description">bicycles allowed</string>
+	<string name="voice_announcements_content_description">voice announcements</string>
+	<string name="tickets_sold_content_description">tickets sold on board</string>
+	<string name="usb_charging_content_description">USB charging</string>
+	<string name="show_departures">Show departures</string>
+	<string name="open_in_maps_app">Open in maps app</string>
+	<string name="stop_content_description">stop</string>
+	<string name="seatbelts_everyone">Seatbelts, everyone!</string> <!-- taken from ‘Magic School Bus’. Should be translated like in the series -->
+	<string name="onboarding_question">How would you like to start?</string>
+	<string name="onboarding_simple">Simple</string>
+	<string name="onboarding_simple_action">choose cities</string>
+	<string name="onboarding_advanced">Advanced</string>
+	<string name="onboarding_advanced_action">choose server</string>
+	<string name="cancel">Cancel</string>
+	<string name="error">Error</string>
+	<string name="rate_limit">Rate limit</string>
+	<string name="server_rate_limited_question">This server is rate-limited and no token was given. Do you want to continue?</string>
+	<string name="server_private_question">This server is private and no token was given</string>
+	<string name="last_update">Last update: %s</string>
+	<string name="title_feeds">Feeds</string>
+	<string name="title_servers">Servers</string>
+	<string name="title_cities">Cities</string>
+	<string name="error_url">Malformed URL provided</string>
+	<string name="error_traffic_spec">Cannot verify traffic server</string>
+</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
deleted file mode 100644
index b957c902a4f271f8a32a4ccb889929ea847c6e6b..0000000000000000000000000000000000000000
--- a/app/src/main/res/values/styles.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
-        <item name="colorPrimary">@color/colorPrimary</item>
-        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
-        <item name="colorAccent">@color/colorAccent</item>
-    </style>
-
-    <style name="SplashTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
-        <item name="colorPrimary">@color/colorPrimary</item>
-        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
-        <item name="android:windowBackground">@drawable/splash_screen</item>
-    </style>
-
-    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
-
-    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
-
-    <style name="SearchBarTheme" parent="MaterialSearchBarLight">
-        <item name="mt_navIconTint">@color/textDark</item>
-        <item name="mt_backIconTint">@color/textDark</item>
-        <item name="mt_clearIconTint">@color/textDark</item>
-        <item name="mt_searchIconTint">@color/textDark</item>
-        <item name="mt_textCursorTint">@color/colorAccent</item>
-        <item name="mt_highlightedTextColor">@color/colorAccent</item>
-        <item name="mt_handlesTintEnabled">true</item>
-        <item name="mt_leftTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_rightTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_middleTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_leftTextSelectorDrawable">
-            @drawable/ic_texthandle_start
-        </item>
-        <item name="mt_middleTextSelectorDrawable">
-            @drawable/ic_texthandle_middle
-        </item>
-        <item name="mt_rightTextSelectorDrawable">
-            @drawable/ic_texthandle_end
-        </item>
-    </style>
-
-</resources>




diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dc24f789c068396350617f6166ef162d6478a0bc
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,72 @@
+<resources xmlns:tool="http://schemas.android.com/tools">
+
+	<style name="Theme.Bimba" parent="Theme.Material3.Light.NoActionBar">
+		<item name="android:fontFamily">@font/yellowcircle8</item>
+		<item name="colorPrimary">@color/md_theme_light_primary</item>
+		<item name="colorOnPrimary">@color/md_theme_light_onPrimary</item>
+		<item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
+		<item name="colorOnPrimaryContainer">@color/md_theme_light_onPrimaryContainer</item>
+		<item name="colorSecondary">@color/md_theme_light_secondary</item>
+		<item name="colorOnSecondary">@color/md_theme_light_onSecondary</item>
+		<item name="colorSecondaryContainer">@color/md_theme_light_secondaryContainer</item>
+		<item name="colorOnSecondaryContainer">@color/md_theme_light_onSecondaryContainer</item>
+		<item name="colorTertiary">@color/md_theme_light_tertiary</item>
+		<item name="colorOnTertiary">@color/md_theme_light_onTertiary</item>
+		<item name="colorTertiaryContainer">@color/md_theme_light_tertiaryContainer</item>
+		<item name="colorOnTertiaryContainer">@color/md_theme_light_onTertiaryContainer</item>
+		<item name="colorError">@color/md_theme_light_error</item>
+		<item name="colorErrorContainer">@color/md_theme_light_errorContainer</item>
+		<item name="colorOnError">@color/md_theme_light_onError</item>
+		<item name="colorOnErrorContainer">@color/md_theme_light_onErrorContainer</item>
+		<item name="android:colorBackground">@color/md_theme_light_background</item>
+		<item name="colorOnBackground">@color/md_theme_light_onBackground</item>
+		<item name="colorSurface">@color/md_theme_light_surface</item>
+		<item name="colorOnSurface">@color/md_theme_light_onSurface</item>
+		<item name="colorSurfaceVariant">@color/md_theme_light_surfaceVariant</item>
+		<item name="colorOnSurfaceVariant">@color/md_theme_light_onSurfaceVariant</item>
+		<item name="colorOutline">@color/md_theme_light_outline</item>
+		<item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
+		<item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
+		<item name="colorPrimaryInverse">@color/md_theme_light_inversePrimary</item>
+
+		<item name="statusBarBackground">@android:color/transparent</item>
+		<item name="android:statusBarColor">@android:color/transparent</item>
+		<item name="android:enforceStatusBarContrast" tool:targetApi="q">false</item>
+		<item name="lightStatusBar">true</item>
+	</style>
+
+	<declare-styleable name="Theme.Bimba">
+		<attr name="lightStatusBar" format="boolean" />
+	</declare-styleable>
+
+	<style name="Theme.Bimba.SearchBar" parent="MaterialSearchBarLight">
+		<item name="mt_searchBarColor">@color/md_theme_light_surfaceVariant</item>
+		<item name="mt_textColor">@color/md_theme_light_onSurfaceVariant</item>
+		<item name="mt_placeholderColor">@color/md_theme_light_onSurfaceVariant
+		</item> <!-- todo(ui) grey out -->
+		<item name="mt_backIconTint">@color/md_theme_light_onSurfaceVariant</item>
+		<item name="mt_navIconTint">@color/md_theme_light_onSurfaceVariant</item>
+		<item name="mt_searchIconTint">@color/md_theme_light_onSurfaceVariant</item>
+		<item name="mt_menuIconTint">@color/md_theme_light_onSurfaceVariant</item>
+		<item name="mt_clearIconTint">@color/md_theme_light_onSurfaceVariant</item>
+	</style>
+
+	<style name="Theme.Bimba.SearchResult.Title" parent="Theme.Bimba">
+		<item name="android:textColor">@color/md_theme_light_onSurfaceVariant</item>
+		<item name="android:textSize">16sp</item>
+	</style>
+
+	<style name="Theme.Bimba.SearchResult.Description" parent="Theme.Bimba">
+		<item name="android:textColor">@color/md_theme_light_onSurfaceVariant
+		</item> <!-- todo(ui) grey out -->
+		<item name="android:textSize">9sp</item>
+	</style>
+
+	<style name="Theme.Bimba.Splash" parent="Theme.SplashScreen">
+		<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
+		<item name="windowSplashScreenIconBackgroundColor">@color/ic_launcher_background</item>
+		<item name="postSplashScreenTheme">@style/Theme.Bimba</item>
+	</style>
+
+	<style name="Theme.Bimba.Style" />
+</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
deleted file mode 100644
index e45666bc1b5d4f67b6646206d6a314359479c076..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-de/strings.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<resources>
-    <string name="departure_to">→ %1$s</string>
-    <string name="departure_to_line">%1$s → %2$s</string>
-    <string name="departure_at">Um %1$s</string>
-    <string name="now">Jetzt</string>
-    <string name="departure_in__singular_genitive">In %1$s Minute</string>
-    <string name="departure_in__plural_genitive">In %1$s Minuten</string>
-    <string name="departure_in__plural_nominative">In %1$s Minuten</string>
-
-    <string name="timetable_downloaded">Neuer Fahrplan heruntergeladen</string>
-    <string name="action_change_type">Typ</string>
-    <string name="timetable_downloading">Fahrplan wird heruntergeladen</string>
-    <string name="search_placeholder">Haltestelle…</string>
-    <string name="no_connectivity_cant_update">Kein Verbindung – kann nicht den Fahrplan aktualisieren</string>
-    <string name="no_connectivity">Kein Verbindung</string>
-    <string name="timetable_up_to_date">Fahrplan ist aktuell</string>
-    <string name="error_try_later">Fehler. Versuch später noch einmal</string>
-    <string name="stop_already_fav">Diese Haltestelle ist bereits eine Lieblingshaltestelle</string>
-    <string name="action_edit">Bearbeiten</string>
-    <string name="action_delete">Löschen</string>
-    <string name="favourite_name">Lieblingshaltestelles Name</string>
-    <string name="edit_favourite_title">„%1$s“ bearbeiten</string>
-    <string name="no_next_departure">Keine nächste Abfahrt</string>
-    <string name="action_merge">Zusammenfügen</string>
-    <string name="merge_favourites">Lieblingshaltestellen zusammenfügen</string>
-    <string name="loading">Laden…</string>
-    <string name="refresh">Fahrplan aktualisieren</string>
-    <string name="title_activity_help">Hilfe</string>
-    <string name="valid_since">Gilt seit %1$s</string>
-    <string name="valid_till">Gilt bis %1$s</string>
-    <string name="departure_row_getting_departures">Abfahrten sammeln…</string>
-    <string name="no_departures">Keine Abfahrten</string>
-    <string name="tab_text_line_to">Hin</string>
-    <string name="tab_text_line_fro">Her</string>
-    <string name="timetable_validity_today">Fahrplan gilt nur bis heute.</string>
-    <string name="timetable_validity_finished">Die Gültigkeit des Zeitplans ist beendet. Verbind mit dem Internet, um eine neue herunterzuladen und um fortzufahren.</string>
-    <string name="timetable_validity_tomorrow">Fahrplan gilt nur bis morgen.</string>
-    <string name="just_departed">Gerade gegangen</string>
-    <string name="validity_offline_unavailable">Offline-Fahrplan ist nicht verfügbar</string>
-    <string name="pref_category_timetable">Fahrplan</string>
-    <string name="title_timetable_source_url">Quelle des Fahrplans</string>
-    <string name="title_activity_settings">Einstellungen</string>
-    <string name="settings">Einstellungen</string>
-    <string name="timetable_decompressing">Fahrplan wird entpackt</string>
-    <string name="Mon">Mo.</string>
-    <string name="Tue">Di.</string>
-    <string name="Wed">Mi.</string>
-    <string name="Thu">Do.</string>
-    <string name="Fri">Fr.</string>
-    <string name="Sat">Sa.</string>
-    <string name="Sun">So.</string>
-    <string name="title_timetable_automatic_update">Automatische Updates</string>
-    <string name="summary_timetable_automatic_update">Automatisch nach Fahrplanaktualisierungen suchen und diese herunterladen</string>
-    <string name="server_error">Serverfehler</string>
-    <string name="nothing_found">Nicht gefunden</string>
-    <string name="in_a_moment">Gleich</string>
-    <string name="more">Mehr</string>
-</resources>




diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
deleted file mode 100644
index 6a3c5754965e35da0716f027162c09739f645ae4..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-it/strings.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<resources>
-    <string name="departure_to">→ %1$s</string>
-    <string name="departure_to_line">%1$s → %2$s</string>
-    <string name="departure_at">Alle %1$s</string>
-    <string name="departure_in__singular_genitive">Tra %1$s minuto</string>
-    <string name="departure_in__plural_genitive">Tra %1$s minuti</string>
-    <string name="departure_in__plural_nominative">Tra %1$s minuti</string>
-    <string name="title_activity_help">Aiuto</string>
-    <string name="valid_since">Valido da %1$s</string>
-    <string name="valid_till">Valido a %1$s</string>
-    <string name="timetable_downloaded">Nuovo orario è stato scaricato</string>
-    <string name="action_change_type">Tipo</string>
-    <string name="timetable_downloading">Scaricando l’orario</string>
-    <string name="search_placeholder">Fermata…</string>
-    <string name="no_connectivity_cant_update">Nessuna connettività – non si riesce aggiornare l’orario</string>
-    <string name="no_connectivity">Nessuna connettività</string>
-    <string name="timetable_up_to_date">L’orario sta aggiornato</string>
-    <string name="error_try_later">Errore. Riprova più tardi</string>
-    <string name="now">Adesso</string>
-    <string name="stop_already_fav">Questa fermata è già un favorito</string>
-    <string name="action_edit">Modifica</string>
-    <string name="action_delete">Cancella</string>
-    <string name="favourite_name">Il nome del favorito</string>
-    <string name="edit_favourite_title">Modifica «%1$s»</string>
-    <string name="no_next_departure">Nessuna partenza successiva</string>
-    <string name="action_merge">Unisci</string>
-    <string name="merge_favourites">Unisci le favorite</string>
-    <string name="loading">Caricamento in corso…</string>
-    <string name="refresh">Aggiorna l’orario</string>
-    <string name="departure_row_getting_departures">Ottenere le partenze…</string>
-    <string name="no_departures">Nessune partenze</string>
-    <string name="tab_text_line_to">Avanti</string>
-    <string name="tab_text_line_fro">Indietro</string>
-    <string name="timetable_validity_today">L’orario è valido solo fino ad oggi.</string>
-    <string name="timetable_validity_finished">"La validità dell’orario è terminata. Connetti a Internet per scaricarne uno nuovo e continuare. "</string>
-    <string name="timetable_validity_tomorrow">L’orario è valido solo fino a domani.</string>
-    <string name="just_departed">Appena partito</string>
-    <string name="validity_offline_unavailable">L’orario offline non è disponibile</string>
-    <string name="pref_category_timetable">Orario</string>
-    <string name="title_timetable_source_url">Fonte dell’Orario</string>
-    <string name="title_activity_settings">Impostazioni</string>
-    <string name="settings">Impostazioni</string>
-    <string name="timetable_decompressing">Decomprimendo l’orario</string>
-    <string name="Mon">lun</string>
-    <string name="Tue">mar</string>
-    <string name="Wed">mer</string>
-    <string name="Thu">gio</string>
-    <string name="Fri">ven</string>
-    <string name="Sat">sab</string>
-    <string name="Sun">dom</string>
-    <string name="summary_timetable_automatic_update">Controlla e scarica automaticamente gli aggiornamenti dell’orario</string>
-    <string name="title_timetable_automatic_update">Aggiornamenti automatici</string>
-    <string name="server_error">Errore del server</string>
-    <string name="nothing_found">Non trovato</string>
-    <string name="in_a_moment">In un momento</string>
-    <string name="more">Più</string>
-</resources>




diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml
deleted file mode 100644
index a17e646959c11a4b4716bb7b800264a91cb92e80..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-night/colors.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <color name="textDark">#deffffff</color>
-    <color name="textDarkMedium">#99ffffff</color>
-    <color name="textDarkDisabled">#45ffffff</color>
-    <color name="cardColor">#424242</color>
-</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml
deleted file mode 100644
index 471cf22213b51f84eff2aca9f8e51a90fca5adbf..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-night/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <style name="SearchBarTheme" parent="MaterialSearchBarDark">
-        <item name="mt_navIconTint">@color/textDark</item>
-        <item name="mt_backIconTint">@color/textDark</item>
-        <item name="mt_clearIconTint">@color/textDark</item>
-        <item name="mt_searchIconTint">@color/textDark</item>
-        <item name="mt_textCursorTint">@color/colorAccent</item>
-        <item name="mt_highlightedTextColor">@color/colorAccent</item>
-        <item name="mt_handlesTintEnabled">true</item>
-        <item name="mt_leftTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_rightTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_middleTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_leftTextSelectorDrawable">
-            @drawable/ic_texthandle_start
-        </item>
-        <item name="mt_middleTextSelectorDrawable">
-            @drawable/ic_texthandle_middle
-        </item>
-        <item name="mt_rightTextSelectorDrawable">
-            @drawable/ic_texthandle_end
-        </item>
-    </style>
-</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..64131505cc055ae8432e5e6f350e280e352cd614
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,62 @@
+<resources xmlns:tool="http://schemas.android.com/tools">
+
+	<style name="Theme.Bimba" parent="Theme.Material3.Dark.NoActionBar">
+		<item name="android:fontFamily">@font/yellowcircle8</item>
+		<item name="colorPrimary">@color/md_theme_dark_primary</item>
+		<item name="colorOnPrimary">@color/md_theme_dark_onPrimary</item>
+		<item name="colorPrimaryContainer">@color/md_theme_dark_primaryContainer</item>
+		<item name="colorOnPrimaryContainer">@color/md_theme_dark_onPrimaryContainer</item>
+		<item name="colorSecondary">@color/md_theme_dark_secondary</item>
+		<item name="colorOnSecondary">@color/md_theme_dark_onSecondary</item>
+		<item name="colorSecondaryContainer">@color/md_theme_dark_secondaryContainer</item>
+		<item name="colorOnSecondaryContainer">@color/md_theme_dark_onSecondaryContainer</item>
+		<item name="colorTertiary">@color/md_theme_dark_tertiary</item>
+		<item name="colorOnTertiary">@color/md_theme_dark_onTertiary</item>
+		<item name="colorTertiaryContainer">@color/md_theme_dark_tertiaryContainer</item>
+		<item name="colorOnTertiaryContainer">@color/md_theme_dark_onTertiaryContainer</item>
+		<item name="colorError">@color/md_theme_dark_error</item>
+		<item name="colorErrorContainer">@color/md_theme_dark_errorContainer</item>
+		<item name="colorOnError">@color/md_theme_dark_onError</item>
+		<item name="colorOnErrorContainer">@color/md_theme_dark_onErrorContainer</item>
+		<item name="android:colorBackground">@color/md_theme_dark_background</item>
+		<item name="colorOnBackground">@color/md_theme_dark_onBackground</item>
+		<item name="colorSurface">@color/md_theme_dark_surface</item>
+		<item name="colorOnSurface">@color/md_theme_dark_onSurface</item>
+		<item name="colorSurfaceVariant">@color/md_theme_dark_surfaceVariant</item>
+		<item name="colorOnSurfaceVariant">@color/md_theme_dark_onSurfaceVariant</item>
+		<item name="colorOutline">@color/md_theme_dark_outline</item>
+		<item name="colorOnSurfaceInverse">@color/md_theme_dark_inverseOnSurface</item>
+		<item name="colorSurfaceInverse">@color/md_theme_dark_inverseSurface</item>
+		<item name="colorPrimaryInverse">@color/md_theme_dark_inversePrimary</item>
+
+		<item name="statusBarBackground">@android:color/transparent</item>
+		<item name="android:statusBarColor">@android:color/transparent</item>
+		<item name="android:enforceStatusBarContrast" tool:targetApi="q">false</item>
+		<item name="lightStatusBar">false</item>
+	</style>
+
+	<declare-styleable name="Theme.Bimba">
+		<attr name="lightStatusBar" format="boolean" />
+	</declare-styleable>
+
+	<style name="Theme.Bimba.SearchBar" parent="MaterialSearchBarLight">
+		<item name="mt_searchBarColor">@color/md_theme_dark_surfaceVariant</item>
+		<item name="mt_textColor">@color/md_theme_dark_onSurfaceVariant</item>
+		<item name="mt_placeholderColor">@color/md_theme_dark_onSurfaceVariant</item> <!-- todo(ui) grey out -->
+		<item name="mt_backIconTint">@color/md_theme_dark_onSurfaceVariant</item>
+		<item name="mt_navIconTint">@color/md_theme_dark_onSurfaceVariant</item>
+		<item name="mt_searchIconTint">@color/md_theme_dark_onSurfaceVariant</item>
+		<item name="mt_menuIconTint">@color/md_theme_dark_onSurfaceVariant</item>
+		<item name="mt_clearIconTint">@color/md_theme_dark_onSurfaceVariant</item>
+	</style>
+
+	<style name="Theme.Bimba.SearchResult.Title" parent="Theme.Bimba">
+		<item name="android:textColor">@color/md_theme_dark_onSurfaceVariant</item>
+		<item name="android:textSize">16sp</item>
+	</style>
+
+	<style name="Theme.Bimba.SearchResult.Description" parent="Theme.Bimba">
+		<item name="android:textColor">@color/md_theme_dark_onSurfaceVariant</item> <!-- todo(ui) grey out -->
+		<item name="android:textSize">9sp</item>
+	</style>
+</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
deleted file mode 100644
index 5722111696a88735ec67c0c2aff9eebd8ddc7252..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-nl/strings.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<resources>
-    <string name="timetable_downloaded">De nieuwe dienstregeling is gedownload</string>
-    <string name="action_change_type">Type</string>
-    <string name="departure_to">→ %1$s</string>
-    <string name="departure_to_line">%1$s → %2$s</string>
-    <string name="departure_at">Op %1$s</string>
-    <string name="timetable_downloading">Bezig met downloaden van dienstregeling</string>
-    <string name="search_placeholder">Halte…</string>
-    <string name="no_connectivity_cant_update">Geen internetverbinding – de dienstregeling kan niet worden bijgewerkt.</string>
-    <string name="no_connectivity">Geen internetverbinding</string>
-    <string name="timetable_up_to_date">De dienstregeling is volledig bijgewerkt.</string>
-    <string name="error_try_later">Fout; probeer het later opnieuw.</string>
-    <string name="now">Nu</string>
-    <string name="stop_already_fav">Deze halte staat al bij je favorieten</string>
-    <string name="action_edit">Bewerken</string>
-    <string name="action_delete">Verwijderen</string>
-    <string name="favourite_name">Naam van favoriet</string>
-    <string name="edit_favourite_title">‘%1$s’ bewerken</string>
-    <string name="no_next_departure">Geen vertrektijden</string>
-    <string name="action_merge">Samenvoegen</string>
-    <string name="merge_favourites">Favorieten samenvoegen</string>
-    <string name="loading">Bezig met laden…</string>
-    <string name="departure_in__singular_genitive">Over %1$s minuut</string>
-    <string name="departure_in__plural_genitive">Over %1$s minuten</string>
-    <string name="departure_in__plural_nominative">Over %1$s minuten</string>
-
-    <string name="refresh">Dienstregeling bijwerken</string>
-    <string name="title_activity_help">Hulp</string>
-    <string name="departure_row_getting_departures">Bezig met ophalen van vertrektijden…</string>
-    <string name="valid_since">Ingegaan op %1$s</string>
-    <string name="valid_till">Verloopt op %1$s</string>
-
-    <string name="no_departures">Geen vertrektijden</string>
-    <string name="tab_text_line_to">Naar</string>
-    <string name="tab_text_line_fro">Van</string>
-    <string name="timetable_validity_finished">De dienstregeling is verlopen. Maak verbinding met het internet om een nieuwe te downloaden.</string>
-    <string name="timetable_validity_today">De dienstregeling verloopt vandaag.</string>
-    <string name="timetable_validity_tomorrow">De dienstregeling verloopt morgen.</string>
-    <string name="just_departed">Zojuist vertrokken</string>
-    <string name="validity_offline_unavailable">Offline dienstregeling is niet beschikbaar</string>
-    <string name="pref_category_timetable">Dienstregeling</string>
-    <string name="title_timetable_source_url">Bron van de dienstregeling</string>
-    <string name="title_activity_settings">Instellingen</string>
-    <string name="settings">Instellingen</string>
-    <string name="timetable_decompressing">Bezig met uitpakken van dienstregeling</string>
-    <string name="Mon">ma</string>
-    <string name="Tue">di</string>
-    <string name="Wed">wo</string>
-    <string name="Thu">do</string>
-    <string name="Fri">vr</string>
-    <string name="Sat">za</string>
-    <string name="Sun">zo</string>
-    <string name="title_timetable_automatic_update">Automatische updates</string>
-    <string name="summary_timetable_automatic_update">Automatisch controleren en download dienstregeling updates</string>
-    <string name="server_error">Serverfout</string>
-    <string name="more">Meer</string>
-    <string name="in_a_moment">In een ogenblik</string>
-    <string name="nothing_found">Niet gevonden</string>
-</resources>




diff --git a/app/src/main/res/values-notnight/colors.xml b/app/src/main/res/values-notnight/colors.xml
deleted file mode 100644
index 2dbc91375d0d6af1a61b7634050086b1e5a1c301..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-notnight/colors.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <color name="textDark">#de000000</color>
-    <color name="textDarkMedium">#99000000</color>
-    <color name="textDarkDisabled">#45000000</color>
-    <color name="cardColor">#ffffff</color>
-</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-notnight/styles.xml b/app/src/main/res/values-notnight/styles.xml
deleted file mode 100644
index 91c96a627f637c75c0a16c6de17ca84e7963284f..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-notnight/styles.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
-    <style name="SearchBarTheme" parent="MaterialSearchBarLight">
-        <item name="mt_navIconTint">@color/textDark</item>
-        <item name="mt_backIconTint">@color/textDark</item>
-        <item name="mt_clearIconTint">@color/textDark</item>
-        <item name="mt_searchIconTint">@color/textDark</item>
-        <item name="mt_textCursorTint">@color/colorAccent</item>
-        <item name="mt_highlightedTextColor">@color/colorAccent</item>
-        <item name="mt_handlesTintEnabled">true</item>
-        <item name="mt_leftTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_rightTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_middleTextSelectorTint">@color/colorAccent</item>
-        <item name="mt_leftTextSelectorDrawable">
-            @drawable/ic_texthandle_start
-        </item>
-        <item name="mt_middleTextSelectorDrawable">
-            @drawable/ic_texthandle_middle
-        </item>
-        <item name="mt_rightTextSelectorDrawable">
-            @drawable/ic_texthandle_end
-        </item>
-    </style>
-</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
deleted file mode 100644
index 0fc914f811da656b43c9cfe73dd1c435d79a56e1..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-pl/strings.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-    <string name="timetable_downloaded">Pobrano nowy rozkład</string>
-    <string name="action_change_type">Typ</string>
-    <string name="departure_at">O %1$s</string>
-    <string name="departure_to">→ %1$s</string>
-    <string name="timetable_downloading">Pobieranie rozkładu</string>
-    <string name="search_placeholder">Przystanek…</string>
-    <string name="timetable_up_to_date">Rozkład jest aktualny</string>
-    <string name="no_connectivity_cant_update">Brak połączenia z Internetem – nie można zaktualizować rozkładu</string>
-    <string name="no_connectivity">Brak połączenia z Internetem</string>
-    <string name="error_try_later">Błąd. Spróbuj ponownie później</string>
-    <string name="now">Teraz</string>
-    <string name="stop_already_fav">Ten przystanek już jest pośród ulubionych</string>
-    <string name="departure_to_line">%1$s → %2$s</string>
-    <string name="action_delete">Usuń</string>
-    <string name="action_edit">Edytuj</string>
-    <string name="edit_favourite_title">Edytuj „%1$s”</string>
-    <string name="favourite_name">Nazwa ulubionego</string>
-    <string name="no_next_departure">Brak następnego odjazdu</string>
-    <string name="action_merge">Połącz</string>
-    <string name="merge_favourites">Połącz ulubione</string>
-    <string name="loading">Ładowanie…</string>
-    <string name="departure_in__singular_genitive">Za %1$s minutę</string>
-    <string name="departure_in__plural_genitive">Za %1$s minut</string>
-    <string name="departure_in__plural_nominative">Za %1$s minuty</string>
-    <string name="refresh">Zaktualizuj rozkład</string>
-    <string name="title_activity_help">Pomoc</string>
-    <string name="departure_row_getting_departures">Zbieranie odjazdów…</string>
-    <string name="valid_since">Ważny od %1$s</string>
-    <string name="valid_till">Ważny do %1$s</string>
-    <string name="no_departures">Brak odjazdów</string>
-    <string name="tab_text_line_to">Tam</string>
-    <string name="tab_text_line_fro">Z powrotem</string>
-    <string name="timetable_validity_today">Rozkład obowiązuje tylko do dzisiaj.</string>
-    <string name="timetable_validity_finished">Rozkład przestał obowiązywać. Połącz się z Internetem, aby pobrać nowy i kontynuować.</string>
-    <string name="timetable_validity_tomorrow">Rozkład obowiązuje tylko do jutra.</string>
-    <string name="just_departed">Właśnie odjechał</string>
-    <string name="validity_offline_unavailable">Rozkład offline jest niedostępny</string>
-    <string name="pref_category_timetable">Rozkład</string>
-    <string name="title_timetable_source_url">Źródło rozkładu</string>
-    <string name="title_activity_settings">Ustawienia</string>
-    <string name="settings">Ustawienia</string>
-    <string name="timetable_decompressing">Rozpakowywanie rozkładu</string>
-    <string name="Mon">pon.</string>
-    <string name="Tue">wt.</string>
-    <string name="Wed">śr.</string>
-    <string name="Thu">czw.</string>
-    <string name="Fri">pt.</string>
-    <string name="Sat">sob.</string>
-    <string name="Sun">niedz.</string>
-    <string name="summary_timetable_automatic_update">Automatycznie sprawdzaj i pobieraj aktualizacje rozkładu</string>
-    <string name="title_timetable_automatic_update">Automatyczne aktualizacje</string>
-    <string name="server_error">Błąd servera</string>
-    <string name="nothing_found">Nie znaleziono</string>
-    <string name="in_a_moment">Za moment</string>
-    <string name="more">Więcej</string>
-</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-v23/themes.xml b/app/src/main/res/values-v23/themes.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f2e49e303ea6be52b864cd335f562c03667883b5
--- /dev/null
+++ b/app/src/main/res/values-v23/themes.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+	<style name="Theme.Bimba.Style" parent="Theme.Bimba">
+		<item name="android:windowLightStatusBar">?attr/lightStatusBar</item>
+		<item name="android:statusBarColor">?attr/statusBarBackground</item>
+	</style>
+</resources>
\ No newline at end of file




diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml
deleted file mode 100644
index 63fc816444614bd64f68a372d1f93211628ee51d..0000000000000000000000000000000000000000
--- a/app/src/main/res/values-w820dp/dimens.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<resources>
-    <!-- Example customization of dimensions originally defined in res/values/dimens.xml
-         (such as screen margins) for screens with more than 820dp of available width. This
-         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
-    <dimen name="activity_horizontal_margin">64dp</dimen>
-</resources>




diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9157acd18cdf838751e15affe9aad8ea49f91b49
--- /dev/null
+++ b/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+   Sample backup rules file; uncomment and customize as necessary.
+   See https://developer.android.com/guide/topics/data/autobackup
+   for details.
+   Note: This file is ignored for devices older that API 31
+   See https://developer.android.com/about/versions/12/backup-restore
+-->
+<full-backup-content>
+</full-backup-content>
\ No newline at end of file




diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dbd7d6cff871fd2450b0f9c01fc1143b79092776
--- /dev/null
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+   Sample data extraction rules file; uncomment and customize as necessary.
+   See https://developer.android.com/about/versions/12/backup-restore#xml-changes
+   for details.
+-->
+<data-extraction-rules>
+	<cloud-backup>
+		<!-- Use <include> and <exclude> to control what is backed up.
+		<include .../>
+		<exclude .../>
+		-->
+	</cloud-backup>
+	<!--
+	<device-transfer>
+			<include .../>
+			<exclude .../>
+	</device-transfer>
+	-->
+</data-extraction-rules>
\ No newline at end of file




diff --git a/app/src/main/res/xml/pref_main.xml b/app/src/main/res/xml/pref_main.xml
deleted file mode 100644
index e35091e5b4688366446865e6123a4cfe880fd70b..0000000000000000000000000000000000000000
--- a/app/src/main/res/xml/pref_main.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
-    <PreferenceCategory android:title="@string/pref_category_timetable">
-        <EditTextPreference
-            android:defaultValue="@string/timetable_source_url"
-            android:key="@string/key_timetable_source_url"
-            android:summary="@string/timetable_source_url"
-            android:title="@string/title_timetable_source_url" />
-
-        <!-- todo intent get file (import) -->
-        <!-- todo reset source -->
-        <SwitchPreference
-            android:defaultValue="false"
-            android:key="@string/key_timetable_automatic_update"
-            android:summary="@string/summary_timetable_automatic_update"
-            android:title="@string/title_timetable_automatic_update" />
-    </PreferenceCategory>
-</PreferenceScreen>




diff --git a/build.gradle b/build.gradle
index 2db418dde841cfe37dc15e0d5f1cd140f603dfa2..73d1e088368f91b43d6e9b60b37550773df667cd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,31 +1,12 @@
 // Top-level build file where you can add configuration options common to all sub-projects/modules.
-
-buildscript {
-    ext.kotlin_version = '1.3.21'
-    repositories {
-        jcenter()
-        maven { url 'https://maven.google.com' }
-        //maven { url 'https://dl.bintray.com/guardian/android' } // TooLargeTool
-        google()
-    }
-    dependencies {
-        classpath 'com.android.tools.build:gradle:3.3.2'
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
-
-        // NOTE: Do not place your application dependencies here; they belong
-        // in the individual module build.gradle files
-    }
-}
-
-allprojects {
-    repositories {
-        jcenter()
-        maven { url 'https://maven.google.com' }
-        //maven { url 'https://dl.bintray.com/guardian/android' } // TooLargeTool
-        google()
-    }
+plugins {
+    id 'com.android.application' version '7.4.2' apply false
+    id 'com.android.library' version '7.4.2' apply false
+    id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
+    id 'org.jetbrains.kotlin.jvm' version '1.7.20' apply false
+    id "org.jetbrains.kotlin.plugin.parcelize" version "1.8.20" apply false
 }
 
 task clean(type: Delete) {
     delete rootProject.buildDir
-}
+}
\ No newline at end of file




diff --git a/fruchtfleisch/.gitignore b/fruchtfleisch/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8
--- /dev/null
+++ b/fruchtfleisch/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file




diff --git a/fruchtfleisch/build.gradle b/fruchtfleisch/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..e7ceb4cce7d2dcbc650fa806ead2fcfa26ba232e
--- /dev/null
+++ b/fruchtfleisch/build.gradle
@@ -0,0 +1,12 @@
+plugins {
+    id 'java-library'
+    id 'org.jetbrains.kotlin.jvm'
+}
+
+java {
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+}
+dependencies {
+    //implementation 'org.jetbrains.kotlin:kotlin-reflect:1.8.10'
+}
\ No newline at end of file




diff --git a/fruchtfleisch/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt b/fruchtfleisch/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9d49df734169f7b2934d7897e89311653de7139c
--- /dev/null
+++ b/fruchtfleisch/src/main/java/xyz/apiote/fruchtfleisch/Reader.kt
@@ -0,0 +1,128 @@
+package xyz.apiote.fruchtfleisch
+
+import java.io.EOFException
+import java.io.InputStream
+import java.lang.Double.longBitsToDouble
+import java.lang.Float.intBitsToFloat
+
+data class IntVar(private val v: Long) {
+	fun toLong() = v
+}
+data class UIntVar(private val v: ULong) {
+	fun toULong() = v
+}
+
+@Suppress("MemberVisibilityCanBePrivate", "unused", "BooleanMethodIsAlwaysInverted")
+class Reader(private val stream: InputStream) {
+	fun readUInt(): UIntVar {
+		var result: ULong = 0UL
+		var i = 0
+		var s = 0
+		while (true) {
+			val b = stream.read()
+			if (b < 0) {
+				throw EOFException("while reading byte")
+			}
+			if (b < 0x80) {
+				if (i > 9 || (i == 9 && b > 1)) {
+					TODO("throw int overflow")
+				}
+				result = result.or(b.toULong().shl(s))
+				break
+			}
+			i++
+			s += 7
+		}
+		return UIntVar(result)
+	}
+
+	fun readInt(): IntVar {
+		val unsigned = readUInt().toULong()
+		var signed = unsigned.shr(1).toLong()
+		if (unsigned.and(1UL) != 0UL) {
+			signed = signed.inv()
+		}
+		return IntVar(signed)
+	}
+
+	fun readU8(): UByte {
+		val b = stream.read()
+		if (b < 0) {
+			throw EOFException("while reading byte")
+		}
+		return b.toUByte()
+	}
+
+	fun readU16(): UShort {
+		val b1 = readU8()
+		val b2 = readU8()
+		return (b2.toUInt().shl(8) or b1.toUInt()).toUShort()
+	}
+
+	fun readU32(): UInt {
+		val b1 = readU8()
+		val b2 = readU8()
+		val b3 = readU8()
+		val b4 = readU8()
+		return b4.toUInt().shl(24) or b3.toUInt().shl(16) or b2.toUInt().shl(8) or b1.toUInt()
+	}
+
+	fun readU64(): ULong {
+		val b1 = readU8()
+		val b2 = readU8()
+		val b3 = readU8()
+		val b4 = readU8()
+		val b5 = readU8()
+		val b6 = readU8()
+		val b7 = readU8()
+		val b8 = readU8()
+		return b8.toULong().shl(56) or b7.toULong().shl(48) or b6.toULong().shl(40) or b5.toULong().shl(32) or b4.toULong().shl(24) or b3.toULong().shl(16) or b2.toULong().shl(8) or b1.toULong()
+	}
+
+	fun readI8(): Byte {
+		return readU8().toByte()
+	}
+
+	fun readI16(): Short {
+		return readU16().toShort()
+	}
+
+	fun readI32(): Int {
+		return readU32().toInt()
+	}
+
+	fun readI64(): Long {
+		return readU64().toLong()
+	}
+
+	fun readFloat32(): Float {
+		return intBitsToFloat(readI32())
+	}
+
+	fun readFloat64(): Double {
+		return longBitsToDouble(readI64())
+	}
+
+	fun readData(n: Int): ByteArray {
+		val data = ByteArray(n)
+		var left = n
+		while (left > 0) {
+			val r = stream.read(data, n - left, left)
+			left -= r
+		}
+		return data
+	}
+
+	fun readString(): String {
+		val length = readU8()
+		return readData(length.toInt()).decodeToString()
+	}
+
+	fun readBoolean(): Boolean {
+		return when (readU8().toUInt()) {
+			0u -> false
+			1u -> true
+			else -> TODO("throw wrong value")
+		}
+	}
+}
\ No newline at end of file




diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 13372aef5e24af05341d49695ee84e5f9b594659..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ




diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0a09c6d65a64c76aa4d5b2cb098701791d95d346..72a0f4c89357e1fdc5ad0b2d63031ab0a9475f5b 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Tue Aug 29 11:31:16 CEST 2017
+#Tue Aug 09 15:48:25 CEST 2022
 distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
 distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
+zipStoreBase=GRADLE_USER_HOME




diff --git a/gradle.properties b/gradle.properties
index 307d50280f7a5c9eb7f6dee93d377854a8ba7d19..cd0519bb2a9450033b80e5906f766b71d176014f 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,20 +1,23 @@
 # Project-wide Gradle settings.
-
 # IDE (e.g. Android Studio) users:
 # Gradle settings configured through the IDE *will override*
 # any settings specified in this file.
-
 # For more details on how to configure your build environment visit
 # http://www.gradle.org/docs/current/userguide/build_environment.html
-
 # Specifies the JVM arguments used for the daemon process.
 # The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx1536m
-kotlin.coroutines=enable
-android.useAndroidX=true
-android.enableJetifier=true
-
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
 # When configured, Gradle will run in incubating parallel mode.
 # This option should only be used with decoupled projects. More details, visit
 # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
 # org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file




diff --git a/gradlew b/gradlew
index 9d82f78915133e1c35a6ea51252590fb38efac2f..4f906e0c811fc9e230eb44819f509cd0627f2600 100755
--- a/gradlew
+++ b/gradlew
@@ -1,4 +1,20 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
 
 ##############################################################################
 ##
@@ -6,20 +22,38 @@ ##  Gradle start up script for UN*X
 ##
 ##############################################################################
 
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
 
 APP_NAME="Gradle"
 APP_BASE_NAME=`basename "$0"`
 
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD="maximum"
 
-warn ( ) {
+warn () {
     echo "$*"
 }
 
-die ( ) {
+die () {
     echo
     echo "$*"
     echo
@@ -30,6 +64,7 @@ # OS specific support (must be 'true' or 'false').
 cygwin=false
 msys=false
 darwin=false
+nonstop=false
 case "`uname`" in
   CYGWIN* )
     cygwin=true
@@ -40,27 +75,13 @@     ;;
   MINGW* )
     msys=true
     ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
 esac
 
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
-    ls=`ls -ld "$PRG"`
-    link=`expr "$ls" : '.*-> \(.*\)$'`
-    if expr "$link" : '/.*' > /dev/null; then
-        PRG="$link"
-    else
-        PRG=`dirname "$PRG"`"/$link"
-    fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
 # Determine the Java command to use to start the JVM.
 if [ -n "$JAVA_HOME" ] ; then
@@ -85,7 +106,7 @@ location of your Java installation."
 fi
 
 # Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
     MAX_FD_LIMIT=`ulimit -H -n`
     if [ $? -eq 0 ] ; then
         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -105,10 +126,11 @@ if $darwin; then
     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
 fi
 
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
     JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
@@ -134,27 +156,30 @@             eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
         else
             eval `echo args$i`="\"$arg\""
         fi
-        i=$((i+1))
+        i=`expr $i + 1`
     done
     case $i in
-        (0) set -- ;;
-        (1) set -- "$args0" ;;
-        (2) set -- "$args0" "$args1" ;;
-        (3) set -- "$args0" "$args1" "$args2" ;;
-        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
-        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
-        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
-        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
-        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
-        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+        0) set -- ;;
+        1) set -- "$args0" ;;
+        2) set -- "$args0" "$args1" ;;
+        3) set -- "$args0" "$args1" "$args2" ;;
+        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
     esac
 fi
 
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
-    JVM_OPTS=("$@")
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
 }
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
 
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+exec "$JAVACMD" "$@"




diff --git a/gradlew.bat b/gradlew.bat
index 8a0b282aa6885fb573c106b3551f7275c5f17e8e..107acd32c4e687021ef32db511e8a206129b88ec 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
 @if "%DEBUG%" == "" @echo off
 @rem ##########################################################################
 @rem
@@ -8,20 +24,23 @@
 @rem Set local scope for the variables with windows NT shell
 if "%OS%"=="Windows_NT" setlocal
 
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
 set DIRNAME=%~dp0
 if "%DIRNAME%" == "" set DIRNAME=.
 set APP_BASE_NAME=%~n0
 set APP_HOME=%DIRNAME%
 
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
 @rem Find java.exe
 if defined JAVA_HOME goto findJavaFromJavaHome
 
 set JAVA_EXE=java.exe
 %JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
 
 echo.
 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ :findJavaFromJavaHome
 set JAVA_HOME=%JAVA_HOME:"=%
 set JAVA_EXE=%JAVA_HOME%/bin/java.exe
 
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
 
 echo.
 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,34 +64,14 @@ echo location of your Java installation.
 
 goto fail
 
-:init
-@rem Get command-line arguments, handling Windowz variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-if "%@eval[2+2]" == "4" goto 4NT_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-goto execute
-
-:4NT_args
-@rem Get arguments from the 4NT Shell from JP Software
-set CMD_LINE_ARGS=%$
-
 :execute
 @rem Setup the command line
 
 set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
 
+
 @rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
 
 :end
 @rem End local scope for the variables with windows NT shell




diff --git a/i18n/ids b/i18n/ids
deleted file mode 100644
index 024d90586180baa9e7719ff8f489c4d5a23d2832..0000000000000000000000000000000000000000
--- a/i18n/ids
+++ /dev/null
@@ -1,52 +0,0 @@
-timetable_downloaded = New timetable downloaded
-action_change_type = Type
-departure_to = → %1$s
-departure_to_line = %1$s → %2$s
-departure_at = At %1$s
-timetable_downloading = Downloading timetable
-timetable_decompressing = Decompressing timetable
-search_placeholder = Stop…
-no_connectivity_cant_update = No connectivity – can’t update timetable
-no_connectivity = No connectivity
-timetable_up_to_date = Timetable is up-to-date
-error_try_later = Error. Try again later
-now = Now
-stop_already_fav = This stop is already in favourites
-action_edit = Edit
-action_delete = Delete
-favourite_name = Favourite name
-edit_favourite_title = Edit ‘%1$s’
-no_next_departure = No next departure
-action_merge = Merge
-merge_favourites = Merge favourites
-loading = Loading…
-departure_in__singular_genitive = In %1$s minute
-departure_in__plural_genitive = In %1$s minutes _plgen
-departure_in__plural_nominative = In %1$s minutes _plnom
-refresh = Update timetable
-title_activity_help = Help
-departure_row_getting_departures = Getting departures…
-valid_since = Valid since %1$s
-valid_till = Valid till %1$s
-no_departures = No departures
-tab_text_line_to = To
-tab_text_line_fro = Fro
-timetable_validity_finished = Timetable validity has ended. Connect to the Internet to download a new one in order to continue.
-timetable_validity_today = Timetable validity ends today.
-timetable_validity_tomorrow = Timetable validity ends tomorrow.
-just_departed = Just departed
-validity_offline_unavailable = Offline timetable unavailable
-pref_category_timetable = Timetable
-title_timetable_source_url = Timetable source
-title_activity_settings = Settings
-settings = Settings
-title_timetable_automatic_update = Automatic updates
-Mon = Mon
-Tue = Tue
-Wed = Wed
-Thu = Thu
-Fri = Fri
-Sat = Sat
-Sun = Sun
-summary_timetable_automatic_update = Automatically check for and download timetable updates
-server_error = Server error




diff --git a/i18n/messages.en.uk.po b/i18n/messages.en.uk.po
deleted file mode 100644
index 343c4c0dbf756333ff6849567b7eab2d1ea0130a..0000000000000000000000000000000000000000
--- a/i18n/messages.en.uk.po
+++ /dev/null
@@ -1,111 +0,0 @@
-#, fuzzy
-msgid ""
-msgstr ""
-"MIME-Version: 1.0\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-
-msgid "New timetable downloaded"
-msgstr "New timetable downloaded"
-msgid "Type"
-msgstr "Type"
-msgid "→ %1$s"
-msgstr "→ %1$s"
-msgid "%1$s → %2$s"
-msgstr "%1$s → %2$s"
-msgid "At %1$s"
-msgstr "At %1$s"
-msgid "Downloading timetable"
-msgstr "Downloading timetable"
-msgid "Decompressing timetable"
-msgstr "Decompressing timetable"
-msgid "Stop…"
-msgstr "Stop…"
-msgid "No connectivity – can’t update timetable"
-msgstr "No connectivity – can’t update timetable"
-msgid "No connectivity"
-msgstr "No connectivity"
-msgid "Timetable is up-to-date"
-msgstr "Timetable is up-to-date"
-msgid "Error. Try again later"
-msgstr "Error. Try again later"
-msgid "Now"
-msgstr "Now"
-msgid "This stop is already in favourites"
-msgstr "This stop is already in favourites"
-msgid "Edit"
-msgstr "Edit"
-msgid "Delete"
-msgstr "Delete"
-msgid "Favourite name"
-msgstr "Favourite name"
-msgid "Edit ‘%1$s’"
-msgstr "Edit ‘%1$s’"
-msgid "No next departure"
-msgstr "No next departure"
-msgid "Merge"
-msgstr "Merge"
-msgid "Merge favourites"
-msgstr "Merge favourites"
-msgid "Loading…"
-msgstr "Loading…"
-msgid "In %1$s minute"
-msgstr "In %1$s minute"
-msgid "In %1$s minutes _plnom"
-msgstr "In %1$s minutes"
-msgid "In %1$s minutes _plgen"
-msgstr "In %1$s minutes"
-msgid "Update timetable"
-msgstr "Update timetable"
-msgid "Help"
-msgstr "Help"
-msgid "Getting departures…"
-msgstr "Getting departures…"
-msgid "Valid since %1$s"
-msgstr "Valid since %1$s"
-msgid "Valid till %1$s"
-msgstr "Valid till %1$s"
-msgid "No departures"
-msgstr "No departures"
-msgid "To"
-msgstr "To"
-msgid "Fro"
-msgstr "Fro"
-msgid "Timetable validity has ended. Connect to the Internet to download a new one in order to continue."
-msgstr "Timetable validity has ended. Connect to the Internet to download a new one in order to continue."
-msgid "Timetable validity ends today."
-msgstr "Timetable validity ends today."
-msgid "Timetable validity ends tomorrow."
-msgstr "Timetable validity ends tomorrow."
-msgid "Just departed"
-msgstr "Just departed"
-msgid "Offline timetable unavailable"
-msgstr "Offline timetable unavailable"
-msgid "Timetable"
-msgstr "Timetable"
-msgid "Timetable source"
-msgstr "Timetable source"
-msgid "Settings"
-msgstr "Settings"
-msgid "Settings"
-msgstr "Settings"
-msgid "Automatic updates"
-msgstr "Automatic updates"
-msgid "Mon"
-msgstr "Mon"
-msgid "Tue"
-msgstr "Tue"
-msgid "Wed"
-msgstr "Wed"
-msgid "Thu"
-msgstr "Thu"
-msgid "Fri"
-msgstr "Fri"
-msgid "Sat"
-msgstr "Sat"
-msgid "Sun"
-msgstr "Sun"
-msgid "Automatically check for and download timetable updates"
-msgstr "Automatically check for and download timetable updates"
-msgid "Server error"
-msgstr "Server error"




diff --git a/i18n/messages.pl.po b/i18n/messages.pl.po
deleted file mode 100644
index 0d41090206c8ce8c4d1174918da09af66af03bdd..0000000000000000000000000000000000000000
--- a/i18n/messages.pl.po
+++ /dev/null
@@ -1,111 +0,0 @@
-#, fuzzy
-msgid ""
-msgstr ""
-"MIME-Version: 1.0\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-
-msgid "New timetable downloaded"
-msgstr "Pobrano nowy rozkład"
-msgid "Type"
-msgstr "Typ"
-msgid "At %1$s"
-msgstr "O %1$s"
-msgid "→ %1$s"
-msgstr "→ %1$s"
-msgid "Downloading timetable"
-msgstr "Pobieranie rozkładu"
-msgid "Stop…"
-msgstr "Przystanek…"
-msgid "Timetable is up-to-date"
-msgstr "Rozkład jest aktualny"
-msgid "No connectivity – can’t update timetable"
-msgstr "Brak połączenia z Internetem – nie można zaktualizować rozkładu"
-msgid "No connectivity"
-msgstr "Brak połączenia z Internetem"
-msgid "Error. Try again later"
-msgstr "Błąd. Spróbuj ponownie później"
-msgid "Now"
-msgstr "Teraz"
-msgid "This stop is already in favourites"
-msgstr "Ten przystanek już jest pośród ulubionych"
-msgid "%1$s → %2$s"
-msgstr "%1$s → %2$s"
-msgid "Delete"
-msgstr "Usuń"
-msgid "Edit"
-msgstr "Edytuj"
-msgid "Edit ‘%1$s’"
-msgstr "Edytuj „%1$s”"
-msgid "Favourite name"
-msgstr "Nazwa ulubionego"
-msgid "No next departure"
-msgstr "Brak następnego odjazdu"
-msgid "Merge"
-msgstr "Połącz"
-msgid "Merge favourites"
-msgstr "Połącz ulubione"
-msgid "Loading…"
-msgstr "Ładowanie…"
-msgid "In %1$s minute"
-msgstr "Za %1$s minutę"
-msgid "In %1$s minutes _plgen"
-msgstr "Za %1$s minut"
-msgid "In %1$s minutes _plnom"
-msgstr "Za %1$s minuty"
-msgid "Update timetable"
-msgstr "Zaktualizuj rozkład"
-msgid "Help"
-msgstr "Pomoc"
-msgid "Getting departures…"
-msgstr "Zbieranie odjazdów…"
-msgid "Valid since %1$s"
-msgstr "Ważny od %1$s"
-msgid "Valid till %1$s"
-msgstr "Ważny do %1$s"
-msgid "No departures"
-msgstr "Brak odjazdów"
-msgid "To"
-msgstr "Tam"
-msgid "Fro"
-msgstr "Z powrotem"
-msgid "Timetable validity ends today."
-msgstr "Rozkład obowiązuje tylko do dzisiaj."
-msgid "Timetable validity has ended. Connect to the Internet to download a new one in order to continue."
-msgstr "Rozkład przestał obowiązywać. Połącz się z Internetem, aby pobrać nowy i kontynuować."
-msgid "Timetable validity ends tomorrow."
-msgstr "Rozkład obowiązuje tylko do jutra."
-msgid "Just departed"
-msgstr "Właśnie odjechał"
-msgid "Offline timetable unavailable"
-msgstr "Rozkład offline jest niedostępny"
-msgid "Timetable"
-msgstr "Rozkład"
-msgid "Timetable source"
-msgstr "Źródło rozkładu"
-msgid "Settings"
-msgstr "Ustawienia"
-msgid "Settings"
-msgstr "Ustawienia"
-msgid "Decompressing timetable"
-msgstr "Rozpakowywanie rozkładu"
-msgid "Mon"
-msgstr "pon."
-msgid "Tue"
-msgstr "wt."
-msgid "Wed"
-msgstr "śr."
-msgid "Thu"
-msgstr "czw."
-msgid "Fri"
-msgstr "pt."
-msgid "Sat"
-msgstr "sob."
-msgid "Sun"
-msgstr "niedz."
-msgid "Automatically check for and download timetable updates"
-msgstr "Automatycznie sprawdzaj i pobieraj aktualizacje rozkładu"
-msgid "Automatic updates"
-msgstr "Automatyczne aktualizacje"
-msgid "Server error"
-msgstr "Błąd servera"




diff --git a/i18n/messages.pot b/i18n/messages.pot
deleted file mode 100644
index a85bef4664f60f0835ae9ae580b7298bcd27061d..0000000000000000000000000000000000000000
--- a/i18n/messages.pot
+++ /dev/null
@@ -1,161 +0,0 @@
-#, fuzzy
-msgid ""
-msgstr ""
-"MIME-Version: 1.0\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Content-Type: text/plain; charset=UTF-8\n"
-
-msgid "New timetable downloaded"
-msgstr ""
-
-msgid "Type"
-msgstr ""
-
-msgid "→ %1$s"
-msgstr ""
-
-msgid "%1$s → %2$s"
-msgstr ""
-
-msgid "At %1$s"
-msgstr ""
-
-msgid "Downloading timetable"
-msgstr ""
-
-msgid "Decompressing timetable"
-msgstr ""
-
-msgid "Stop…"
-msgstr ""
-
-msgid "No connectivity – can’t update timetable"
-msgstr ""
-
-msgid "No connectivity"
-msgstr ""
-
-msgid "Timetable is up-to-date"
-msgstr ""
-
-msgid "Error. Try again later"
-msgstr ""
-
-msgid "Now"
-msgstr ""
-
-msgid "This stop is already in favourites"
-msgstr ""
-
-msgid "Edit"
-msgstr ""
-
-msgid "Delete"
-msgstr ""
-
-msgid "Favourite name"
-msgstr ""
-
-msgid "Edit ‘%1$s’"
-msgstr ""
-
-msgid "No next departure"
-msgstr ""
-
-msgid "Merge"
-msgstr ""
-
-msgid "Merge favourites"
-msgstr ""
-
-msgid "Loading…"
-msgstr ""
-
-msgid "In %1$s minute"
-msgstr ""
-
-#. minutes – plural nominative
-msgid "In %1$s minutes _plnom"
-msgstr ""
-
-#. minutes — plural genitive
-msgid "In %1$s minutes _plgen"
-msgstr ""
-
-msgid "Update timetable"
-msgstr ""
-
-msgid "Help"
-msgstr ""
-
-msgid "Getting departures…"
-msgstr ""
-
-msgid "Valid since %1$s"
-msgstr ""
-
-msgid "Valid till %1$s"
-msgstr ""
-
-msgid "No departures"
-msgstr ""
-
-msgid "To"
-msgstr ""
-
-msgid "Fro"
-msgstr ""
-
-msgid "Timetable validity has ended. Connect to the Internet to download a new one in order to continue."
-msgstr ""
-
-msgid "Timetable validity ends today."
-msgstr ""
-
-msgid "Timetable validity ends tomorrow."
-msgstr ""
-
-msgid "Just departed"
-msgstr ""
-
-msgid "Offline timetable unavailable"
-msgstr ""
-
-msgid "Timetable"
-msgstr ""
-
-msgid "Timetable source"
-msgstr ""
-
-msgid "Settings"
-msgstr ""
-
-msgid "Automatic updates"
-msgstr ""
-
-msgid "Mon"
-msgstr ""
-
-msgid "Tue"
-msgstr ""
-
-msgid "Wed"
-msgstr ""
-
-msgid "Thu"
-msgstr ""
-
-msgid "Fri"
-msgstr ""
-
-msgid "Sat"
-msgstr ""
-
-msgid "Sun"
-msgstr ""
-
-msgid "Automatically check for and download timetable updates"
-msgstr ""
-
-msgid "Server error"
-msgstr ""




diff --git a/i18n/po2xml.py b/i18n/po2xml.py
deleted file mode 100644
index 6e63f1d3e3847fbd2bb7eef45fe3bcb1b16513a8..0000000000000000000000000000000000000000
--- a/i18n/po2xml.py
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/python3
-
-import sys
-
-ids = {}
-msgs = {}
-last_id = ''
-
-with open('ids') as ids_file:
-    for line in ids_file.readlines():
-        id, msg = line.split(' = ')
-        ids[msg.strip()] = id.strip()
-
-for line in sys.stdin:
-    line = line.split('"')
-    if line[0].strip() == 'msgid':
-        last_id = line[1]
-    if line[0].strip() == 'msgstr' and last_id != '':
-        msgs[last_id] = line[1]
-
-print("<resources>")
-for id, msg in msgs.items():
-    print(f'    <string name="{ids[id]}">{msg}</string>')
-print("</resources>")




diff --git a/i18n/strings-de.xml b/i18n/strings-de.xml
deleted file mode 100644
index 2aa35f26cd77104f979d8f986dd4469b12d46160..0000000000000000000000000000000000000000
--- a/i18n/strings-de.xml
+++ /dev/null
@@ -1,55 +0,0 @@
-<resources>
-    <string name="departure_to">→ %1$s</string>
-    <string name="departure_to_line">%1$s → %2$s</string>
-    <string name="departure_at">Um %1$s</string>
-    <string name="now">Jetzt</string>
-    <string name="departure_in__singular_genitive">In %1$s Minute</string>
-    <string name="departure_in__plural_genitive">In %1$s Minuten</string>
-    <string name="departure_in__plural_nominative">In %1$s Minuten</string>
-
-    <string name="timetable_downloaded">Neuer Fahrplan heruntergeladen</string>
-    <string name="action_change_type">Typ</string>
-    <string name="timetable_downloading">Fahrplan wird heruntergeladen</string>
-    <string name="search_placeholder">Haltestelle…</string>
-    <string name="no_connectivity_cant_update">Kein Verbindung – kann nicht den Fahrplan aktualisieren</string>
-    <string name="no_connectivity">Kein Verbindung</string>
-    <string name="timetable_up_to_date">Fahrplan ist aktuell</string>
-    <string name="error_try_later">Fehler. Versuch später noch einmal</string>
-    <string name="stop_already_fav">Diese Haltestelle ist bereits eine Lieblingshaltestelle</string>
-    <string name="action_edit">Bearbeiten</string>
-    <string name="action_delete">Löschen</string>
-    <string name="favourite_name">Lieblingshaltestelles Name</string>
-    <string name="edit_favourite_title">„%1$s“ bearbeiten</string>
-    <string name="no_next_departure">Keine nächste Abfahrt</string>
-    <string name="action_merge">Zusammenfügen</string>
-    <string name="merge_favourites">Lieblingshaltestellen zusammenfügen</string>
-    <string name="loading">Laden…</string>
-    <string name="refresh">Fahrplan aktualisieren</string>
-    <string name="title_activity_help">Hilfe</string>
-    <string name="valid_since">Gilt seit %1$s</string>
-    <string name="valid_till">Gilt bis %1$s</string>
-    <string name="departure_row_getting_departures">Abfahrten sammeln…</string>
-    <string name="no_departures">Keine Abfahrten</string>
-    <string name="tab_text_line_to">Hin</string>
-    <string name="tab_text_line_fro">Her</string>
-    <string name="timetable_validity_today">Fahrplan gilt nur bis heute.</string>
-    <string name="timetable_validity_finished">Die Gültigkeit des Zeitplans ist beendet. Verbind mit dem Internet, um eine neue herunterzuladen und um fortzufahren.</string>
-    <string name="timetable_validity_tomorrow">Fahrplan gilt nur bis morgen.</string>
-    <string name="just_departed">Gerade gegangen</string>
-    <string name="validity_offline_unavailable">Offline-Fahrplan ist nicht verfügbar</string>
-    <string name="pref_category_timetable">Fahrplan</string>
-    <string name="title_timetable_source_url">Quelle des Fahrplans</string>
-    <string name="title_activity_settings">Einstellungen</string>
-    <string name="settings">Einstellungen</string>
-    <string name="timetable_decompressing">Fahrplan wird entpackt</string>
-    <string name="Mon">Mo.</string>
-    <string name="Tue">Di.</string>
-    <string name="Wed">Mi.</string>
-    <string name="Thu">Do.</string>
-    <string name="Fri">Fr.</string>
-    <string name="Sat">Sa.</string>
-    <string name="Sun">So.</string>
-    <string name="title_timetable_automatic_update">Automatische Updates</string>
-    <string name="summary_timetable_automatic_update">Automatisch nach Fahrplanaktualisierungen suchen und diese herunterladen</string>
-    <string name="server_error">Serverfehler</string>
-</resources>




diff --git a/i18n/strings-it.xml b/i18n/strings-it.xml
deleted file mode 100644
index 96a49332ee42d46b8a59b3170fcf498ed9af25f9..0000000000000000000000000000000000000000
--- a/i18n/strings-it.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<resources>
-    <string name="departure_to">→ %1$s</string>
-    <string name="departure_to_line">%1$s → %2$s</string>
-    <string name="departure_at">Alle %1$s</string>
-    <string name="departure_in__singular_genitive">Tra %1$s minuto</string>
-    <string name="departure_in__plural_genitive">Tra %1$s minuti</string>
-    <string name="departure_in__plural_nominative">Tra %1$s minuti</string>
-    <string name="title_activity_help">Aiuto</string>
-    <string name="valid_since">Valido da %1$s</string>
-    <string name="valid_till">Valido a %1$s</string>
-    <string name="timetable_downloaded">Nuovo orario è stato scaricato</string>
-    <string name="action_change_type">Tipo</string>
-    <string name="timetable_downloading">Scaricando l’orario</string>
-    <string name="search_placeholder">Fermata…</string>
-    <string name="no_connectivity_cant_update">Nessuna connettività – non si riesce aggiornare l’orario</string>
-    <string name="no_connectivity">Nessuna connettività</string>
-    <string name="timetable_up_to_date">L’orario sta aggiornato</string>
-    <string name="error_try_later">Errore. Riprova più tardi</string>
-    <string name="now">Adesso</string>
-    <string name="stop_already_fav">Questa fermata è già un favorito</string>
-    <string name="action_edit">Modifica</string>
-    <string name="action_delete">Cancella</string>
-    <string name="favourite_name">Il nome del favorito</string>
-    <string name="edit_favourite_title">Modifica «%1$s»</string>
-    <string name="no_next_departure">Nessuna partenza successiva</string>
-    <string name="action_merge">Unisci</string>
-    <string name="merge_favourites">Unisci le favorite</string>
-    <string name="loading">Caricamento in corso…</string>
-    <string name="refresh">Aggiorna l’orario</string>
-    <string name="departure_row_getting_departures">Ottenere le partenze…</string>
-    <string name="no_departures">Nessune partenze</string>
-    <string name="tab_text_line_to">Avanti</string>
-    <string name="tab_text_line_fro">Indietro</string>
-    <string name="timetable_validity_today">L’orario è valido solo fino ad oggi.</string>
-    <string name="timetable_validity_finished">"La validità dell’orario è terminata. Connetti a Internet per scaricarne uno nuovo e continuare. "</string>
-    <string name="timetable_validity_tomorrow">L’orario è valido solo fino a domani.</string>
-    <string name="just_departed">Appena partito</string>
-    <string name="validity_offline_unavailable">L’orario offline non è disponibile</string>
-    <string name="pref_category_timetable">Orario</string>
-    <string name="title_timetable_source_url">Fonte dell’Orario</string>
-    <string name="title_activity_settings">Impostazioni</string>
-    <string name="settings">Impostazioni</string>
-    <string name="timetable_decompressing">Decomprimendo l’orario</string>
-    <string name="Mon">lun</string>
-    <string name="Tue">mar</string>
-    <string name="Wed">mer</string>
-    <string name="Thu">gio</string>
-    <string name="Fri">ven</string>
-    <string name="Sat">sab</string>
-    <string name="Sun">dom</string>
-    <string name="summary_timetable_automatic_update">Controlla e scarica automaticamente gli aggiornamenti dell’orario</string>
-    <string name="title_timetable_automatic_update">Aggiornamenti automatici</string>
-    <string name="server_error">Errore del server</string>
-</resources>




diff --git a/i18n/strings-nl.xml b/i18n/strings-nl.xml
deleted file mode 100644
index afbe30f95d0afcd22d7b45bb8e25993b461c1f65..0000000000000000000000000000000000000000
--- a/i18n/strings-nl.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<resources>
-    <string name="timetable_downloaded">De nieuwe dienstregeling is gedownload</string>
-    <string name="action_change_type">Type</string>
-    <string name="departure_to">→ %1$s</string>
-    <string name="departure_to_line">%1$s → %2$s</string>
-    <string name="departure_at">Op %1$s</string>
-    <string name="timetable_downloading">Bezig met downloaden van dienstregeling</string>
-    <string name="search_placeholder">Halte…</string>
-    <string name="no_connectivity_cant_update">Geen internetverbinding – de dienstregeling kan niet worden bijgewerkt.</string>
-    <string name="no_connectivity">Geen internetverbinding</string>
-    <string name="timetable_up_to_date">De dienstregeling is volledig bijgewerkt.</string>
-    <string name="error_try_later">Fout; probeer het later opnieuw.</string>
-    <string name="now">Nu</string>
-    <string name="stop_already_fav">Deze halte staat al bij je favorieten</string>
-    <string name="action_edit">Bewerken</string>
-    <string name="action_delete">Verwijderen</string>
-    <string name="favourite_name">Naam van favoriet</string>
-    <string name="edit_favourite_title">‘%1$s’ bewerken</string>
-    <string name="no_next_departure">Geen vertrektijden</string>
-    <string name="action_merge">Samenvoegen</string>
-    <string name="merge_favourites">Favorieten samenvoegen</string>
-    <string name="loading">Bezig met laden…</string>
-    <string name="departure_in__singular_genitive">Over %1$s minuut</string>
-    <string name="departure_in__plural_genitive">Over %1$s minuten</string>
-    <string name="departure_in__plural_nominative">Over %1$s minuten</string>
-
-    <string name="refresh">Dienstregeling bijwerken</string>
-    <string name="title_activity_help">Hulp</string>
-    <string name="departure_row_getting_departures">Bezig met ophalen van vertrektijden…</string>
-    <string name="valid_since">Ingegaan op %1$s</string>
-    <string name="valid_till">Verloopt op %1$s</string>
-
-    <string name="no_departures">Geen vertrektijden</string>
-    <string name="tab_text_line_to">Naar</string>
-    <string name="tab_text_line_fro">Van</string>
-    <string name="timetable_validity_finished">De dienstregeling is verlopen. Maak verbinding met het internet om een nieuwe te downloaden.</string>
-    <string name="timetable_validity_today">De dienstregeling verloopt vandaag.</string>
-    <string name="timetable_validity_tomorrow">De dienstregeling verloopt morgen.</string>
-    <string name="just_departed">Zojuist vertrokken</string>
-    <string name="validity_offline_unavailable">Offline dienstregeling is niet beschikbaar</string>
-    <string name="pref_category_timetable">Dienstregeling</string>
-    <string name="title_timetable_source_url">Bron van de dienstregeling</string>
-    <string name="title_activity_settings">Instellingen</string>
-    <string name="settings">Instellingen</string>
-    <string name="timetable_decompressing">Bezig met uitpakken van dienstregeling</string>
-    <string name="Mon">ma</string>
-    <string name="Tue">di</string>
-    <string name="Wed">wo</string>
-    <string name="Thu">do</string>
-    <string name="Fri">vr</string>
-    <string name="Sat">za</string>
-    <string name="Sun">zo</string>
-    <string name="title_timetable_automatic_update">Automatische updates</string>
-    <string name="summary_timetable_automatic_update">Automatisch controleren en download dienstregeling updates</string>
-    <string name="server_error">Serverfout</string>
-</resources>




diff --git a/i18n/strings-pl.xml b/i18n/strings-pl.xml
deleted file mode 100644
index 02ce0293314b34a070db9bff4bffac13496c51b9..0000000000000000000000000000000000000000
--- a/i18n/strings-pl.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-timetable_downloaded = Pobrano nowy rozkład
-action_change_type = Typ
-departure_at = O %1$s
-departure_to = → %1$s
-timetable_downloading = Pobieranie rozkładu
-search_placeholder = Przystanek…
-timetable_up_to_date = Rozkład jest aktualny
-no_connectivity_cant_update = Brak połączenia z Internetem – nie można zaktualizować rozkładu
-no_connectivity = Brak połączenia z Internetem
-error_try_later = Błąd. Spróbuj ponownie później
-now = Teraz
-stop_already_fav = Ten przystanek już jest pośród ulubionych
-departure_to_line = %1$s → %2$s
-action_delete = Usuń
-action_edit = Edytuj
-edit_favourite_title = Edytuj „%1$s”
-favourite_name = Nazwa ulubionego
-no_next_departure = Brak następnego odjazdu
-action_merge = Połącz
-merge_favourites = Połącz ulubione
-loading = Ładowanie…
-departure_in__singular_genitive = Za %1$s minutę
-departure_in__plural_genitive = Za %1$s minut
-departure_in__plural_nominative = Za %1$s minuty
-refresh = Zaktualizuj rozkład
-title_activity_help = Pomoc
-departure_row_getting_departures = Zbieranie odjazdów…
-valid_since = Ważny od %1$s
-valid_till = Ważny do %1$s
-no_departures = Brak odjazdów
-tab_text_line_to = Tam
-tab_text_line_fro = Z powrotem
-timetable_validity_today = Rozkład obowiązuje tylko do dzisiaj.
-timetable_validity_finished = Rozkład przestał obowiązywać. Połącz się z Internetem, aby pobrać nowy i kontynuować.
-timetable_validity_tomorrow = Rozkład obowiązuje tylko do jutra.
-just_departed = Właśnie odjechał
-validity_offline_unavailable = Rozkład offline jest niedostępny
-pref_category_timetable = Rozkład
-title_timetable_source_url = Źródło rozkładu
-title_activity_settings = Ustawienia
-settings = Ustawienia
-timetable_decompressing = Rozpakowywanie rozkładu
-Mon = pon.
-Tue = wt.
-Wed = śr.
-Thu = czw.
-Fri = pt.
-Sat = sob.
-Sun = niedz.
-summary_timetable_automatic_update = Automatycznie sprawdzaj i pobieraj aktualizacje rozkładu
-title_timetable_automatic_update = Automatyczne aktualizacje
-server_error = Błąd servera




diff --git a/i18n/xml2po.py b/i18n/xml2po.py
deleted file mode 100644
index 53a4ac73c4436121d509bf42f4e45052242e87c3..0000000000000000000000000000000000000000
--- a/i18n/xml2po.py
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/python3
-
-import sys
-
-ids = {}
-msgs = {}
-
-with open('ids') as ids_file:
-    for line in ids_file.readlines():
-        id, msg = line.split(' = ')
-        ids[id] = msg.strip()
-
-for line in sys.stdin.readlines():
-    id, msg = line.split(' = ')
-    msgs[id] = msg.strip()
-
-print('''#, fuzzy
-msgid ""
-msgstr ""
-"MIME-Version: 1.0\\n"
-"Content-Transfer-Encoding: 8bit\\n"
-"Content-Type: text/plain; charset=UTF-8\\n"
-''')
-
-for id, msg in msgs.items():
-    print(f'msgid "{ids[id]}"')
-    print(f'msgstr "{msg}"')




diff --git a/inari.svg b/inari.svg
new file mode 100644
index 0000000000000000000000000000000000000000..33ef0449f475b445414c384d7050c0c552173d37
--- /dev/null
+++ b/inari.svg
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="66.98246mm"
+   height="55.715553mm"
+   viewBox="0 0 66.98246 55.715553"
+   version="1.1"
+   id="svg5"
+   inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
+   sodipodi:docname="drawing.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview7"
+     pagecolor="#505050"
+     bordercolor="#eeeeee"
+     borderopacity="1"
+     inkscape:pageshadow="0"
+     inkscape:pageopacity="0"
+     inkscape:pagecheckerboard="0"
+     inkscape:document-units="mm"
+     showgrid="false"
+     inkscape:zoom="2.9362514"
+     inkscape:cx="109.66363"
+     inkscape:cy="116.30476"
+     inkscape:window-width="1920"
+     inkscape:window-height="1007"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer1"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <defs
+     id="defs2" />
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-68.809603,-134.76337)">
+    <g
+       id="g93742"
+       style="opacity:1">
+      <ellipse
+         style="fill:#567ca0;fill-opacity:1;stroke-width:0.352122"
+         id="path76"
+         cx="74.383362"
+         cy="147.65054"
+         rx="5.5737591"
+         ry="5.313138" />
+      <rect
+         style="fill:#b5c5c5;fill-opacity:1;stroke-width:0.264866"
+         id="rect180"
+         width="0.98591608"
+         height="33.420025"
+         x="73.769379"
+         y="152.92934"
+         ry="0" />
+      <rect
+         style="fill:#798595;fill-opacity:1;stroke-width:0.264583"
+         id="rect284"
+         width="4.1957474"
+         height="7.8133383"
+         x="72.240288"
+         y="160.08839" />
+      <path
+         id="rect286"
+         style="fill:#3f413c;fill-opacity:1;stroke-width:0.264583"
+         d="m 69.122551,186.42857 h 10.616875 v 3.85714 c -3.61761,0.26681 -7.1511,0.24826 -10.616875,0 z"
+         sodipodi:nodetypes="ccccc" />
+    </g>
+    <g
+       id="g93748"
+       style="opacity:1">
+      <path
+         style="fill:#53221b;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 85.111539,167.81735 5.761685,-3.25446 5.651425,-0.18282 6.146911,0.29303 4.65229,2.21507 -0.004,1.03917 -3.42174,2.39617 -13.590806,0.26858 z"
+         id="path573" />
+      <path
+         id="rect995"
+         style="fill:#5d1c18;fill-opacity:1;stroke-width:0.999999"
+         d="m 364.35938,609.69922 v 47.28516 2.73046 h 1.83007 v -2.73046 -47.28516 z"
+         transform="scale(0.26458333)" />
+      <path
+         style="fill:#da4e59;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 107.32381,166.88813 c 0.17887,-0.70857 -0.37741,-1.39599 -0.85581,-1.87043 -0.55448,-0.54375 -1.32405,-1.41023 -1.88439,-1.95734 -0.99251,-0.57802 -2.00332,-0.8984 -2.9239,-1.58632 -0.71176,-0.69646 -1.61272,-0.54635 -2.504459,-0.85685 -0.987749,-0.38335 -2.036605,-0.15004 -3.061415,-0.16444 -1.122642,0.12445 -2.25529,0.27454 -3.381729,0.40037 -0.863483,0.15571 -1.681674,0.48755 -2.422128,0.94552 -0.867217,0.26214 -1.547411,0.82582 -2.185826,1.44612 -0.789259,0.55813 -1.351825,1.34121 -2.036629,2.01205 -0.79524,0.5884 -0.879605,1.65158 -0.955985,2.56054 l 5.761685,-3.25446 5.651425,-0.18282 6.146911,0.29303 z"
+         id="path610"
+         sodipodi:nodetypes="ccccccccccc" />
+      <path
+         id="rect1099"
+         style="fill:#743027;fill-opacity:1;stroke-width:0.264583"
+         d="m 96.403603,174.54978 h 1.29989 v 0 c 0,0 0.182881,2.34872 -0.629739,2.3552 -0.816203,0.007 -0.670151,-2.3552 -0.670151,-2.3552 z"
+         sodipodi:nodetypes="cccac" />
+    </g>
+    <path
+       style="opacity:1;fill:#586c24;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 124.288,137.28695 c 1.55667,0.0247 3.11335,0.0494 4.67002,0.0741 0.0656,-0.39103 0.14672,-0.81251 0.24808,-1.21017 0.22665,-0.37332 0.0954,-0.84353 0.26759,-1.20237 0.14774,-0.13672 0.64826,-0.36418 0.70598,0.0579 0.11517,0.41977 0.12391,0.92662 -0.058,1.3294 -0.10087,0.35297 -0.22333,0.72336 -0.38857,1.03184 1.59878,0.008 3.19756,0.0169 4.79634,0.0254 0.19706,0.32618 0.59875,0.21796 0.91466,0.39235 0.45633,0.0959 0.35374,0.5962 0.2949,1.00893 -0.32729,0.22892 -0.43162,0.6555 -0.8307,0.80451 -0.22902,0.28261 -0.57205,0.53644 -0.98158,0.35787 -0.51169,0.15718 -1.00745,-10e-4 -1.51752,-0.007 -0.38644,-0.0184 -0.68374,0.24067 -1.04592,0.36592 -0.39795,0.17617 -0.77318,0.43648 -1.05834,0.75772 -0.4346,0.48119 -0.95467,0.0349 -1.47961,0.0659 -0.41668,-0.1197 -0.69595,-0.41392 -1.07726,-0.616 -0.42922,-0.21433 -0.83971,-0.47247 -1.20031,-0.78722 -0.40077,-0.25153 -0.87849,-0.37984 -1.18117,-0.7678 -0.30003,-0.35635 -0.87962,-0.39383 -1.0307,-0.86207 -0.0807,-0.24907 -0.15484,-0.57474 -0.0479,-0.81961 z"
+       id="path2287" />
+    <path
+       sodipodi:type="star"
+       style="opacity:1;fill:#ffe438;fill-opacity:1;stroke:none"
+       id="path96214"
+       inkscape:flatsided="false"
+       sodipodi:sides="5"
+       sodipodi:cx="268.70459"
+       sodipodi:cy="546.09521"
+       sodipodi:r1="27.938145"
+       sodipodi:r2="13.969073"
+       sodipodi:arg1="0.98751558"
+       sodipodi:arg2="1.6158341"
+       inkscape:rounded="0"
+       inkscape:randomized="0"
+       d="m 284.09195,569.41407 -16.01628,-9.36395 -16.79368,7.88527 3.95635,-18.12601 -12.68887,-13.53506 18.46144,-1.83853 8.95153,-16.25039 7.45345,16.98973 18.22121,3.49176 -13.85495,12.33877 z"
+       transform="matrix(0.13064095,0,0,0.13064095,39.153983,76.367755)"
+       inkscape:transform-center-x="-0.05077931"
+       inkscape:transform-center-y="-0.29988515" />
+  </g>
+</svg>




diff --git a/metadata/en-US/changelogs/20.txt b/metadata/en-US/changelogs/20.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8976acc2147fe4e4d026f425de2915c6bed646a7
--- /dev/null
+++ b/metadata/en-US/changelogs/20.txt
@@ -0,0 +1,5 @@
+Version 3.0 is completely rewritten from scratch and features totally new architecture.
+
+* Favorites are removed
+* Stops and vehicles are on map
+* UI is now Material3




diff --git a/metadata/en-US/full_description.txt b/metadata/en-US/full_description.txt
new file mode 100644
index 0000000000000000000000000000000000000000..54e327510dec975d7740b2c1d4ee297ae751647b
--- /dev/null
+++ b/metadata/en-US/full_description.txt
@@ -0,0 +1,8 @@
+Bimba lets you check public transport timetable with realtime departures. Currently Poznań agglomeration (ZTM Poznań) is supported but more feeds will be added in the future.
+
+Current features:
+* checking departures by stop,
+* searching nearby stops,
+* (ZTM Poznań only) searching stops by QR code
+* vehicle attributes for departures
+* vehicles and stops on map in real time




diff --git a/metadata/en-US/images/featureGraphic.png b/metadata/en-US/images/featureGraphic.png
new file mode 100644
index 0000000000000000000000000000000000000000..844a16c96d6c022afb07cdf727fa3230714650f9
Binary files /dev/null and b/metadata/en-US/images/featureGraphic.png differ




diff --git a/metadata/en-US/images/icon.png b/metadata/en-US/images/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..51de732e44c246bac252b581c3bb1b3c9aa345c6
Binary files /dev/null and b/metadata/en-US/images/icon.png differ




diff --git a/metadata/en-US/images/phoneScreenshots/Dash.png b/metadata/en-US/images/phoneScreenshots/Dash.png
new file mode 100644
index 0000000000000000000000000000000000000000..146004687039135fbf1128f123d9fbb96cfcb92d
Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/Dash.png differ




diff --git a/metadata/en-US/images/phoneScreenshots/StopActivity.png b/metadata/en-US/images/phoneScreenshots/StopActivity.png
new file mode 100644
index 0000000000000000000000000000000000000000..bd22a142e118239c447dd6a3f22f82b79f65f2c1
Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/StopActivity.png differ




diff --git a/metadata/en-US/images/phoneScreenshots/map.png b/metadata/en-US/images/phoneScreenshots/map.png
new file mode 100644
index 0000000000000000000000000000000000000000..7e4c4ec3692bceb8a58ab7189f1182aa6393960a
Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/map.png differ




diff --git a/metadata/en-US/images/phoneScreenshots/mapBS.png b/metadata/en-US/images/phoneScreenshots/mapBS.png
new file mode 100644
index 0000000000000000000000000000000000000000..47b86f8176f5710a9b88a60e9eb65ca2a6897f8f
Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/mapBS.png differ




diff --git a/metadata/en-US/images/phoneScreenshots/modification.png b/metadata/en-US/images/phoneScreenshots/modification.png
new file mode 100644
index 0000000000000000000000000000000000000000..a838f5725c1cdcb0fe1328ab2815f62fc788b29d
Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/modification.png differ




diff --git a/metadata/en-US/images/phoneScreenshots/modification_more.png b/metadata/en-US/images/phoneScreenshots/modification_more.png
new file mode 100644
index 0000000000000000000000000000000000000000..cfe8b805f78eb31aa4c8f6b777b0e41543cb6dad
Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/modification_more.png differ




diff --git a/metadata/en-US/images/phoneScreenshots/searchStop.png b/metadata/en-US/images/phoneScreenshots/searchStop.png
new file mode 100644
index 0000000000000000000000000000000000000000..72028597f2ee1f7372327cd2adb8c2c9b3ec65b2
Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/searchStop.png differ




diff --git a/metadata/en-US/images/phoneScreenshots/stopSpecify.png b/metadata/en-US/images/phoneScreenshots/stopSpecify.png
new file mode 100644
index 0000000000000000000000000000000000000000..015d5e1fcd1d71dfb1f5fc56162e9bb5b75ca12a
Binary files /dev/null and b/metadata/en-US/images/phoneScreenshots/stopSpecify.png differ




diff --git a/metadata/en-US/short_description.txt b/metadata/en-US/short_description.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f9a5d1ebda7eb2bd14aeea0f93880337150b5563
--- /dev/null
+++ b/metadata/en-US/short_description.txt
@@ -0,0 +1 @@
+FLOSS public transport passenger companion; a timetable in your pocket.




diff --git a/metadata/en-US/title.txt b/metadata/en-US/title.txt
new file mode 100644
index 0000000000000000000000000000000000000000..038d5e6047bc863c8fd2210be761c396b834e447
--- /dev/null
+++ b/metadata/en-US/title.txt
@@ -0,0 +1 @@
+Bimba




diff --git a/research/PDP b/research/PDP
deleted file mode 100644
index 5ff738a2a11d6ca936d5d3002da3cc8fb3cf8266..0000000000000000000000000000000000000000
--- a/research/PDP
+++ /dev/null
@@ -1,26213 +0,0 @@
-function draw_clock() {
-    var n, r, t;
-    for (canvas = Raphael("analog", 100, 100), n = canvas.circle(25, 25, 23), n.attr({
-            fill: "#F9F9F9",
-            stroke: "#003A7D",
-            "stroke-width": "2"
-        }), i = 0; i < 12; i++) {
-        var u = 25 + Math.round(18 * Math.cos(30 * i * Math.PI / 180)),
-            f = 25 + Math.round(18 * Math.sin(30 * i * Math.PI / 180)),
-            e = 25 + Math.round(22 * Math.cos(30 * i * Math.PI / 180)),
-            o = 25 + Math.round(22 * Math.sin(30 * i * Math.PI / 180));
-        r = canvas.path("M" + u + " " + f + "L" + e + " " + o)
-    }
-    hour_hand = canvas.path("M 25 25 L 25 15");
-    hour_hand.attr({
-        stroke: "#003A7D",
-        "stroke-width": 2
-    });
-    minute_hand = canvas.path("M 25 25 L 25 10");
-    minute_hand.attr({
-        stroke: "#444444",
-        "stroke-width": 1
-    });
-    second_hand = canvas.path("M 25 30 L 25 8");
-    second_hand.attr({
-        stroke: "#003A7D",
-        "stroke-width": .5
-    });
-    t = canvas.circle(25, 25, 1);
-    t.attr("fill", "#003A7D");
-    update_clock();
-    setInterval("update_clock()", 1e3)
-}
-
-function update_clock() {
-    var r = dateTimeFromServer - dateTimeFromClient,
-        u = (new Date).getTime(),
-        t = new Date;
-    t.setTime(u + r);
-    var n = t,
-        f = n.getHours(),
-        i = n.getMinutes(),
-        e = n.getSeconds();
-    hour_hand.rotate(30 * f + i / 2.5, 25, 25);
-    minute_hand.rotate(6 * i, 25, 25);
-    second_hand.rotate(6 * e, 25, 25)
-}
-
-function indirectStation() {
-    var i = $(".route ").find(".subRow").length,
-        n = $("#indirect"),
-        r = $("#newIndirect"),
-        u = '<div class="row btnRow"><button id="newIndirect" class="k-button k-button-get">' + C_DodajStacjePosrednia + "<\/button><\/div>",
-        t = $("#switchParamsMode").parent();
-    i > 0 ? (n.attr("enable", "false").addClass("k-state-disabled"), n.text(C_PrzezStacjePosrednia), t.show(), r || $(".route .container").append(u)) : (n.removeAttr("enable").removeClass("k-state-disabled"), n.text(C_DodajStacjePosrednia), $("#newIndirect").parent(".btnRow").remove(), t.hide())
-}
-
-function countChecks(n) {
-    var r = n.closest(".layer").find("ul input:checkbox").length,
-        i = n.closest(".layer").find("ul input:checkbox:checked").length,
-        t = n.closest(".multiMenu").find(".num");
-    t.html("");
-    r === i ? (t.html(""), t.append("wszyscy")) : t.append("<span>wybrano " + i + "<\/span>")
-}
-
-function null2empty(n, t, i) {
-    if (!t || t == "") return "";
-    var r = i ? i : "";
-    return n + " " + t + " " + r
-}
-
-function minuty2MinGodz(n) {
-    n = Math.ceil(n);
-    var t = Math.floor(n / 60);
-    return t < 10 && (t = "0" + t), t += ":", n % 60 < 10 && (t += "0"), t + Math.round(n % 60)
-}
-
-function minuty2HHmm(n) {
-    var t = Math.floor(n / 60),
-        i = n - t * 60;
-    return t < 10 && (t = "0" + t), i < 10 && (i = "0" + i), t + ":" + i
-}
-
-function timeStamp2Tekst(n) {
-    return minuty2MinGodz(n.TotalMinutes)
-}
-
-function jsonTime2Time(n, t) {
-    return n == "" ? "" : (t = typeof t != "undefined" ? t : "yyyy-MM-dd HH:mm", kendo.toString(new Date(parseInt(n.substr(6))), t))
-}
-
-function jsonTime2JsTime(n, t) {
-    return n == "" ? "" : (t = typeof t != "undefined" ? t : "yyyy-MM-dd HH:mm", new Date(parseInt(n.substr(6))))
-}
-
-function usunPolskieZnaki(n) {
-    return n = n.replace(/Ę/g, "E").replace(/ę/g, "e"), n = n.replace(/Ó/g, "O").replace(/o/g, "o"), n = n.replace(/Ą/g, "A").replace(/ą/g, "a"), n = n.replace(/Ś/g, "S").replace(/ś/g, "s"), n = n.replace(/Ł/g, "L").replace(/ł/g, "l"), n = n.replace(/Ż/g, "Z").replace(/ż/g, "z"), n = n.replace(/Ź/g, "Z").replace(/ź/g, "z"), n = n.replace(/Ć/g, "C").replace(/ć/g, "c"), n.replace(/Ń/g, "N").replace(/ń/g, "n")
-}
-
-function generujHashDanych(n) {
-    var t = "";
-    return t += n.StacjaPoczatkowaID.toString(), t += n.LiczbaPrzesiadek.toString(), t += Date.parse(n.Odjazd), t += Date.parse(n.Przyjazd), t + n.Pociagi[0].ZamowienieSKRJID.toString()
-}
-var dateTimeFromServer, dateTimeFromClient, mouse_is_inside;
-(function(n, t) {
-    function dt(n) {
-        var t = n.length,
-            r = i.type(n);
-        return i.isWindow(n) ? !1 : 1 === n.nodeType && t ? !0 : "array" === r || "function" !== r && (0 === t || "number" == typeof t && t > 0 && t - 1 in n)
-    }
-
-    function kf(n) {
-        var t = gt[n] = {};
-        return i.each(n.match(s) || [], function(n, i) {
-            t[i] = !0
-        }), t
-    }
-
-    function ir(n, r, u, f) {
-        if (i.acceptData(n)) {
-            var s, h, c = i.expando,
-                a = "string" == typeof r,
-                l = n.nodeType,
-                o = l ? i.cache : n,
-                e = l ? n[c] : n[c] && c;
-            if (e && o[e] && (f || o[e].data) || !a || u !== t) return e || (l ? n[c] = e = b.pop() || i.guid++ : e = c), o[e] || (o[e] = {}, l || (o[e].toJSON = i.noop)), ("object" == typeof r || "function" == typeof r) && (f ? o[e] = i.extend(o[e], r) : o[e].data = i.extend(o[e].data, r)), s = o[e], f || (s.data || (s.data = {}), s = s.data), u !== t && (s[i.camelCase(r)] = u), a ? (h = s[r], null == h && (h = s[i.camelCase(r)])) : h = s, h
-        }
-    }
-
-    function rr(n, t, r) {
-        if (i.acceptData(n)) {
-            var o, h, e, s = n.nodeType,
-                u = s ? i.cache : n,
-                f = s ? n[i.expando] : i.expando;
-            if (u[f]) {
-                if (t && (e = r ? u[f] : u[f].data)) {
-                    for (i.isArray(t) ? t = t.concat(i.map(t, i.camelCase)) : (t in e) ? t = [t] : (t = i.camelCase(t), t = (t in e) ? [t] : t.split(" ")), o = 0, h = t.length; h > o; o++) delete e[t[o]];
-                    if (!(r ? ni : i.isEmptyObject)(e)) return
-                }(r || (delete u[f].data, ni(u[f]))) && (s ? i.cleanData([n], !0) : i.support.deleteExpando || u != u.window ? delete u[f] : u[f] = null)
-            }
-        }
-    }
-
-    function ur(n, r, u) {
-        if (u === t && 1 === n.nodeType) {
-            var f = "data-" + r.replace(tr, "-$1").toLowerCase();
-            if (u = n.getAttribute(f), "string" == typeof u) {
-                try {
-                    u = "true" === u ? !0 : "false" === u ? !1 : "null" === u ? null : +u + "" === u ? +u : nr.test(u) ? i.parseJSON(u) : u
-                } catch (e) {}
-                i.data(n, r, u)
-            } else u = t
-        }
-        return u
-    }
-
-    function ni(n) {
-        for (var t in n)
-            if (("data" !== t || !i.isEmptyObject(n[t])) && "toJSON" !== t) return !1;
-        return !0
-    }
-
-    function ht() {
-        return !0
-    }
-
-    function d() {
-        return !1
-    }
-
-    function cr(n, t) {
-        do n = n[t]; while (n && 1 !== n.nodeType);
-        return n
-    }
-
-    function lr(n, t, r) {
-        if (t = t || 0, i.isFunction(t)) return i.grep(n, function(n, i) {
-            var u = !!t.call(n, i, n);
-            return u === r
-        });
-        if (t.nodeType) return i.grep(n, function(n) {
-            return n === t === r
-        });
-        if ("string" == typeof t) {
-            var u = i.grep(n, function(n) {
-                return 1 === n.nodeType
-            });
-            if (fe.test(t)) return i.filter(t, u, !r);
-            t = i.filter(t, u)
-        }
-        return i.grep(n, function(n) {
-            return i.inArray(n, t) >= 0 === r
-        })
-    }
-
-    function ar(n) {
-        var i = vr.split("|"),
-            t = n.createDocumentFragment();
-        if (t.createElement)
-            while (i.length) t.createElement(i.pop());
-        return t
-    }
-
-    function ye(n, t) {
-        return n.getElementsByTagName(t)[0] || n.appendChild(n.ownerDocument.createElement(t))
-    }
-
-    function dr(n) {
-        var t = n.getAttributeNode("type");
-        return n.type = (t && t.specified) + "/" + n.type, n
-    }
-
-    function gr(n) {
-        var t = le.exec(n.type);
-        return t ? n.type = t[1] : n.removeAttribute("type"), n
-    }
-
-    function si(n, t) {
-        for (var u, r = 0; null != (u = n[r]); r++) i._data(u, "globalEval", !t || i._data(t[r], "globalEval"))
-    }
-
-    function nu(n, t) {
-        if (1 === t.nodeType && i.hasData(n)) {
-            var u, f, o, s = i._data(n),
-                r = i._data(t, s),
-                e = s.events;
-            if (e) {
-                delete r.handle;
-                r.events = {};
-                for (u in e)
-                    for (f = 0, o = e[u].length; o > f; f++) i.event.add(t, u, e[u][f])
-            }
-            r.data && (r.data = i.extend({}, r.data))
-        }
-    }
-
-    function pe(n, t) {
-        var r, f, u;
-        if (1 === t.nodeType) {
-            if (r = t.nodeName.toLowerCase(), !i.support.noCloneEvent && t[i.expando]) {
-                u = i._data(t);
-                for (f in u.events) i.removeEvent(t, f, u.handle);
-                t.removeAttribute(i.expando)
-            }
-            "script" === r && t.text !== n.text ? (dr(t).text = n.text, gr(t)) : "object" === r ? (t.parentNode && (t.outerHTML = n.outerHTML), i.support.html5Clone && n.innerHTML && !i.trim(t.innerHTML) && (t.innerHTML = n.innerHTML)) : "input" === r && ei.test(n.type) ? (t.defaultChecked = t.checked = n.checked, t.value !== n.value && (t.value = n.value)) : "option" === r ? t.defaultSelected = t.selected = n.defaultSelected : ("input" === r || "textarea" === r) && (t.defaultValue = n.defaultValue)
-        }
-    }
-
-    function u(n, r) {
-        var s, e, h = 0,
-            f = typeof n.getElementsByTagName !== o ? n.getElementsByTagName(r || "*") : typeof n.querySelectorAll !== o ? n.querySelectorAll(r || "*") : t;
-        if (!f)
-            for (f = [], s = n.childNodes || n; null != (e = s[h]); h++) !r || i.nodeName(e, r) ? f.push(e) : i.merge(f, u(e, r));
-        return r === t || r && i.nodeName(n, r) ? i.merge([n], f) : f
-    }
-
-    function we(n) {
-        ei.test(n.type) && (n.defaultChecked = n.checked)
-    }
-
-    function fu(n, t) {
-        if (t in n) return t;
-        for (var r = t.charAt(0).toUpperCase() + t.slice(1), u = t, i = uu.length; i--;)
-            if (t = uu[i] + r, t in n) return t;
-        return u
-    }
-
-    function ut(n, t) {
-        return n = t || n, "none" === i.css(n, "display") || !i.contains(n.ownerDocument, n)
-    }
-
-    function eu(n, t) {
-        for (var f, r, o, e = [], u = 0, s = n.length; s > u; u++) r = n[u], r.style && (e[u] = i._data(r, "olddisplay"), f = r.style.display, t ? (e[u] || "none" !== f || (r.style.display = ""), "" === r.style.display && ut(r) && (e[u] = i._data(r, "olddisplay", cu(r.nodeName)))) : e[u] || (o = ut(r), (f && "none" !== f || !o) && i._data(r, "olddisplay", o ? f : i.css(r, "display"))));
-        for (u = 0; s > u; u++) r = n[u], r.style && (t && "none" !== r.style.display && "" !== r.style.display || (r.style.display = t ? e[u] || "" : "none"));
-        return n
-    }
-
-    function ou(n, t, i) {
-        var r = ge.exec(t);
-        return r ? Math.max(0, r[1] - (i || 0)) + (r[2] || "px") : t
-    }
-
-    function su(n, t, r, u, f) {
-        for (var e = r === (u ? "border" : "content") ? 4 : "width" === t ? 1 : 0, o = 0; 4 > e; e += 2) "margin" === r && (o += i.css(n, r + p[e], !0, f)), u ? ("content" === r && (o -= i.css(n, "padding" + p[e], !0, f)), "margin" !== r && (o -= i.css(n, "border" + p[e] + "Width", !0, f))) : (o += i.css(n, "padding" + p[e], !0, f), "padding" !== r && (o += i.css(n, "border" + p[e] + "Width", !0, f)));
-        return o
-    }
-
-    function hu(n, t, r) {
-        var e = !0,
-            u = "width" === t ? n.offsetWidth : n.offsetHeight,
-            f = v(n),
-            o = i.support.boxSizing && "border-box" === i.css(n, "boxSizing", !1, f);
-        if (0 >= u || null == u) {
-            if (u = y(n, t, f), (0 > u || null == u) && (u = n.style[t]), ct.test(u)) return u;
-            e = o && (i.support.boxSizingReliable || u === n.style[t]);
-            u = parseFloat(u) || 0
-        }
-        return u + su(n, t, r || (o ? "border" : "content"), e, f) + "px"
-    }
-
-    function cu(n) {
-        var u = r,
-            t = iu[n];
-        return t || (t = lu(n, u), "none" !== t && t || (rt = (rt || i("<iframe frameborder='0' width='0' height='0'/>").css("cssText", "display:block !important")).appendTo(u.documentElement), u = (rt[0].contentWindow || rt[0].contentDocument).document, u.write("<!doctype html><html><body>"), u.close(), t = lu(n, u), rt.detach()), iu[n] = t), t
-    }
-
-    function lu(n, t) {
-        var r = i(t.createElement(n)).appendTo(t.body),
-            u = i.css(r[0], "display");
-        return r.remove(), u
-    }
-
-    function ci(n, t, r, u) {
-        var f;
-        if (i.isArray(t)) i.each(t, function(t, i) {
-            r || ro.test(n) ? u(n, i) : ci(n + "[" + ("object" == typeof i ? t : "") + "]", i, r, u)
-        });
-        else if (r || "object" !== i.type(t)) u(n, t);
-        else
-            for (f in t) ci(n + "[" + f + "]", t[f], r, u)
-    }
-
-    function ku(n) {
-        return function(t, r) {
-            "string" != typeof t && (r = t, t = "*");
-            var u, f = 0,
-                e = t.toLowerCase().match(s) || [];
-            if (i.isFunction(r))
-                while (u = e[f++]) "+" === u[0] ? (u = u.slice(1) || "*", (n[u] = n[u] || []).unshift(r)) : (n[u] = n[u] || []).push(r)
-        }
-    }
-
-    function du(n, r, u, f) {
-        function o(h) {
-            var c;
-            return e[h] = !0, i.each(n[h] || [], function(n, i) {
-                var h = i(r, u, f);
-                return "string" != typeof h || s || e[h] ? s ? !(c = h) : t : (r.dataTypes.unshift(h), o(h), !1)
-            }), c
-        }
-        var e = {},
-            s = n === vi;
-        return o(r.dataTypes[0]) || !e["*"] && o("*")
-    }
-
-    function yi(n, r) {
-        var f, u, e = i.ajaxSettings.flatOptions || {};
-        for (u in r) r[u] !== t && ((e[u] ? n : f || (f = {}))[u] = r[u]);
-        return f && i.extend(!0, n, f), n
-    }
-
-    function co(n, i, r) {
-        var s, o, e, u, h = n.contents,
-            f = n.dataTypes,
-            c = n.responseFields;
-        for (u in c) u in r && (i[c[u]] = r[u]);
-        while ("*" === f[0]) f.shift(), o === t && (o = n.mimeType || i.getResponseHeader("Content-Type"));
-        if (o)
-            for (u in h)
-                if (h[u] && h[u].test(o)) {
-                    f.unshift(u);
-                    break
-                }
-        if (f[0] in r) e = f[0];
-        else {
-            for (u in r) {
-                if (!f[0] || n.converters[u + " " + f[0]]) {
-                    e = u;
-                    break
-                }
-                s || (s = u)
-            }
-            e = e || s
-        }
-        return e ? (e !== f[0] && f.unshift(e), r[e]) : t
-    }
-
-    function lo(n, t) {
-        var o, r, i, e, u = {},
-            h = 0,
-            s = n.dataTypes.slice(),
-            f = s[0];
-        if (n.dataFilter && (t = n.dataFilter(t, n.dataType)), s[1])
-            for (i in n.converters) u[i.toLowerCase()] = n.converters[i];
-        for (; r = s[++h];)
-            if ("*" !== r) {
-                if ("*" !== f && f !== r) {
-                    if (i = u[f + " " + r] || u["* " + r], !i)
-                        for (o in u)
-                            if (e = o.split(" "), e[1] === r && (i = u[f + " " + e[0]] || u["* " + e[0]])) {
-                                i === !0 ? i = u[o] : u[o] !== !0 && (r = e[0], s.splice(h--, 0, r));
-                                break
-                            }
-                    if (i !== !0)
-                        if (i && n.throws) t = i(t);
-                        else try {
-                            t = i(t)
-                        } catch (c) {
-                            return {
-                                state: "parsererror",
-                                error: i ? c : "No conversion from " + f + " to " + r
-                            }
-                        }
-                }
-                f = r
-            }
-        return {
-            state: "success",
-            data: t
-        }
-    }
-
-    function nf() {
-        try {
-            return new n.XMLHttpRequest
-        } catch (t) {}
-    }
-
-    function ao() {
-        try {
-            return new n.ActiveXObject("Microsoft.XMLHTTP")
-        } catch (t) {}
-    }
-
-    function tf() {
-        return setTimeout(function() {
-            tt = t
-        }), tt = i.now()
-    }
-
-    function wo(n, t) {
-        i.each(t, function(t, i) {
-            for (var u = (ft[t] || []).concat(ft["*"]), r = 0, f = u.length; f > r; r++)
-                if (u[r].call(n, t, i)) return
-        })
-    }
-
-    function rf(n, t, r) {
-        var h, e, o = 0,
-            l = yt.length,
-            f = i.Deferred().always(function() {
-                delete c.elem
-            }),
-            c = function() {
-                if (e) return !1;
-                for (var s = tt || tf(), t = Math.max(0, u.startTime + u.duration - s), h = t / u.duration || 0, i = 1 - h, r = 0, o = u.tweens.length; o > r; r++) u.tweens[r].run(i);
-                return f.notifyWith(n, [u, i, t]), 1 > i && o ? t : (f.resolveWith(n, [u]), !1)
-            },
-            u = f.promise({
-                elem: n,
-                props: i.extend({}, t),
-                opts: i.extend(!0, {
-                    specialEasing: {}
-                }, r),
-                originalProperties: t,
-                originalOptions: r,
-                startTime: tt || tf(),
-                duration: r.duration,
-                tweens: [],
-                createTween: function(t, r) {
-                    var f = i.Tween(n, u.opts, t, r, u.opts.specialEasing[t] || u.opts.easing);
-                    return u.tweens.push(f), f
-                },
-                stop: function(t) {
-                    var i = 0,
-                        r = t ? u.tweens.length : 0;
-                    if (e) return this;
-                    for (e = !0; r > i; i++) u.tweens[i].run(1);
-                    return t ? f.resolveWith(n, [u, t]) : f.rejectWith(n, [u, t]), this
-                }
-            }),
-            s = u.props;
-        for (bo(s, u.opts.specialEasing); l > o; o++)
-            if (h = yt[o].call(u, n, s, u.opts)) return h;
-        return wo(u, s), i.isFunction(u.opts.start) && u.opts.start.call(n, u), i.fx.timer(i.extend(c, {
-            elem: n,
-            anim: u,
-            queue: u.opts.queue
-        })), u.progress(u.opts.progress).done(u.opts.done, u.opts.complete).fail(u.opts.fail).always(u.opts.always)
-    }
-
-    function bo(n, t) {
-        var u, f, r, e, o;
-        for (r in n)
-            if (f = i.camelCase(r), e = t[f], u = n[r], i.isArray(u) && (e = u[1], u = n[r] = u[0]), r !== f && (n[f] = u, delete n[r]), o = i.cssHooks[f], o && "expand" in o) {
-                u = o.expand(u);
-                delete n[f];
-                for (r in u) r in n || (n[r] = u[r], t[r] = e)
-            } else t[f] = e
-    }
-
-    function ko(n, t, r) {
-        var u, o, w, a, s, v, l, f, b, h = this,
-            e = n.style,
-            y = {},
-            p = [],
-            c = n.nodeType && ut(n);
-        r.queue || (f = i._queueHooks(n, "fx"), null == f.unqueued && (f.unqueued = 0, b = f.empty.fire, f.empty.fire = function() {
-            f.unqueued || b()
-        }), f.unqueued++, h.always(function() {
-            h.always(function() {
-                f.unqueued--;
-                i.queue(n, "fx").length || f.empty.fire()
-            })
-        }));
-        1 === n.nodeType && ("height" in t || "width" in t) && (r.overflow = [e.overflow, e.overflowX, e.overflowY], "inline" === i.css(n, "display") && "none" === i.css(n, "float") && (i.support.inlineBlockNeedsLayout && "inline" !== cu(n.nodeName) ? e.zoom = 1 : e.display = "inline-block"));
-        r.overflow && (e.overflow = "hidden", i.support.shrinkWrapBlocks || h.always(function() {
-            e.overflow = r.overflow[0];
-            e.overflowX = r.overflow[1];
-            e.overflowY = r.overflow[2]
-        }));
-        for (o in t)
-            if (a = t[o], vo.exec(a)) {
-                if (delete t[o], v = v || "toggle" === a, a === (c ? "hide" : "show")) continue;
-                p.push(o)
-            }
-        if (w = p.length)
-            for (s = i._data(n, "fxshow") || i._data(n, "fxshow", {}), ("hidden" in s) && (c = s.hidden), v && (s.hidden = !c), c ? i(n).show() : h.done(function() {
-                    i(n).hide()
-                }), h.done(function() {
-                    var t;
-                    i._removeData(n, "fxshow");
-                    for (t in y) i.style(n, t, y[t])
-                }), o = 0; w > o; o++) u = p[o], l = h.createTween(u, c ? s[u] : 0), y[u] = s[u] || i.style(n, u), u in s || (s[u] = l.start, c && (l.end = l.start, l.start = "width" === u || "height" === u ? 1 : 0))
-    }
-
-    function f(n, t, i, r, u) {
-        return new f.prototype.init(n, t, i, r, u)
-    }
-
-    function pt(n, t) {
-        var r, i = {
-                height: n
-            },
-            u = 0;
-        for (t = t ? 1 : 0; 4 > u; u += 2 - t) r = p[u], i["margin" + r] = i["padding" + r] = n;
-        return t && (i.opacity = i.width = n), i
-    }
-
-    function uf(n) {
-        return i.isWindow(n) ? n : 9 === n.nodeType ? n.defaultView || n.parentWindow : !1
-    }
-    var et, wi, o = typeof t,
-        r = n.document,
-        ff = n.location,
-        ef = n.jQuery,
-        of = n.$,
-        ot = {},
-        b = [],
-        wt = "1.9.1",
-        bi = b.concat,
-        bt = b.push,
-        l = b.slice,
-        ki = b.indexOf,
-        sf = ot.toString,
-        it = ot.hasOwnProperty,
-        kt = wt.trim,
-        i = function(n, t) {
-            return new i.fn.init(n, t, wi)
-        },
-        st = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
-        s = /\S+/g,
-        hf = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
-        cf = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
-        di = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
-        lf = /^[\],:{}\s]*$/,
-        af = /(?:^|:|,)(?:\s*\[)+/g,
-        vf = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
-        yf = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
-        pf = /^-ms-/,
-        wf = /-([\da-z])/gi,
-        bf = function(n, t) {
-            return t.toUpperCase()
-        },
-        h = function(n) {
-            (r.addEventListener || "load" === n.type || "complete" === r.readyState) && (gi(), i.ready())
-        },
-        gi = function() {
-            r.addEventListener ? (r.removeEventListener("DOMContentLoaded", h, !1), n.removeEventListener("load", h, !1)) : (r.detachEvent("onreadystatechange", h), n.detachEvent("onload", h))
-        },
-        gt, nr, tr, pi, lt, g, nt, gu, at;
-    i.fn = i.prototype = {
-        jquery: wt,
-        constructor: i,
-        init: function(n, u, f) {
-            var e, o;
-            if (!n) return this;
-            if ("string" == typeof n) {
-                if (e = "<" === n.charAt(0) && ">" === n.charAt(n.length - 1) && n.length >= 3 ? [null, n, null] : cf.exec(n), !e || !e[1] && u) return !u || u.jquery ? (u || f).find(n) : this.constructor(u).find(n);
-                if (e[1]) {
-                    if (u = u instanceof i ? u[0] : u, i.merge(this, i.parseHTML(e[1], u && u.nodeType ? u.ownerDocument || u : r, !0)), di.test(e[1]) && i.isPlainObject(u))
-                        for (e in u) i.isFunction(this[e]) ? this[e](u[e]) : this.attr(e, u[e]);
-                    return this
-                }
-                if (o = r.getElementById(e[2]), o && o.parentNode) {
-                    if (o.id !== e[2]) return f.find(n);
-                    this.length = 1;
-                    this[0] = o
-                }
-                return this.context = r, this.selector = n, this
-            }
-            return n.nodeType ? (this.context = this[0] = n, this.length = 1, this) : i.isFunction(n) ? f.ready(n) : (n.selector !== t && (this.selector = n.selector, this.context = n.context), i.makeArray(n, this))
-        },
-        selector: "",
-        length: 0,
-        size: function() {
-            return this.length
-        },
-        toArray: function() {
-            return l.call(this)
-        },
-        get: function(n) {
-            return null == n ? this.toArray() : 0 > n ? this[this.length + n] : this[n]
-        },
-        pushStack: function(n) {
-            var t = i.merge(this.constructor(), n);
-            return t.prevObject = this, t.context = this.context, t
-        },
-        each: function(n, t) {
-            return i.each(this, n, t)
-        },
-        ready: function(n) {
-            return i.ready.promise().done(n), this
-        },
-        slice: function() {
-            return this.pushStack(l.apply(this, arguments))
-        },
-        first: function() {
-            return this.eq(0)
-        },
-        last: function() {
-            return this.eq(-1)
-        },
-        eq: function(n) {
-            var i = this.length,
-                t = +n + (0 > n ? i : 0);
-            return this.pushStack(t >= 0 && i > t ? [this[t]] : [])
-        },
-        map: function(n) {
-            return this.pushStack(i.map(this, function(t, i) {
-                return n.call(t, i, t)
-            }))
-        },
-        end: function() {
-            return this.prevObject || this.constructor(null)
-        },
-        push: bt,
-        sort: [].sort,
-        splice: [].splice
-    };
-    i.fn.init.prototype = i.fn;
-    i.extend = i.fn.extend = function() {
-        var u, o, r, e, s, h, n = arguments[0] || {},
-            f = 1,
-            l = arguments.length,
-            c = !1;
-        for ("boolean" == typeof n && (c = n, n = arguments[1] || {}, f = 2), "object" == typeof n || i.isFunction(n) || (n = {}), l === f && (n = this, --f); l > f; f++)
-            if (null != (s = arguments[f]))
-                for (e in s) u = n[e], r = s[e], n !== r && (c && r && (i.isPlainObject(r) || (o = i.isArray(r))) ? (o ? (o = !1, h = u && i.isArray(u) ? u : []) : h = u && i.isPlainObject(u) ? u : {}, n[e] = i.extend(c, h, r)) : r !== t && (n[e] = r));
-        return n
-    };
-    i.extend({
-        noConflict: function(t) {
-            return n.$ === i && (n.$ = of ), t && n.jQuery === i && (n.jQuery = ef), i
-        },
-        isReady: !1,
-        readyWait: 1,
-        holdReady: function(n) {
-            n ? i.readyWait++ : i.ready(!0)
-        },
-        ready: function(n) {
-            if (n === !0 ? !--i.readyWait : !i.isReady) {
-                if (!r.body) return setTimeout(i.ready);
-                i.isReady = !0;
-                n !== !0 && --i.readyWait > 0 || (et.resolveWith(r, [i]), i.fn.trigger && i(r).trigger("ready").off("ready"))
-            }
-        },
-        isFunction: function(n) {
-            return "function" === i.type(n)
-        },
-        isArray: Array.isArray || function(n) {
-            return "array" === i.type(n)
-        },
-        isWindow: function(n) {
-            return null != n && n == n.window
-        },
-        isNumeric: function(n) {
-            return !isNaN(parseFloat(n)) && isFinite(n)
-        },
-        type: function(n) {
-            return null == n ? n + "" : "object" == typeof n || "function" == typeof n ? ot[sf.call(n)] || "object" : typeof n
-        },
-        isPlainObject: function(n) {
-            if (!n || "object" !== i.type(n) || n.nodeType || i.isWindow(n)) return !1;
-            try {
-                if (n.constructor && !it.call(n, "constructor") && !it.call(n.constructor.prototype, "isPrototypeOf")) return !1
-            } catch (u) {
-                return !1
-            }
-            for (var r in n);
-            return r === t || it.call(n, r)
-        },
-        isEmptyObject: function(n) {
-            for (var t in n) return !1;
-            return !0
-        },
-        error: function(n) {
-            throw Error(n);
-        },
-        parseHTML: function(n, t, u) {
-            if (!n || "string" != typeof n) return null;
-            "boolean" == typeof t && (u = t, t = !1);
-            t = t || r;
-            var f = di.exec(n),
-                e = !u && [];
-            return f ? [t.createElement(f[1])] : (f = i.buildFragment([n], t, e), e && i(e).remove(), i.merge([], f.childNodes))
-        },
-        parseJSON: function(r) {
-            return n.JSON && n.JSON.parse ? n.JSON.parse(r) : null === r ? r : "string" == typeof r && (r = i.trim(r), r && lf.test(r.replace(vf, "@").replace(yf, "]").replace(af, ""))) ? Function("return " + r)() : (i.error("Invalid JSON: " + r), t)
-        },
-        parseXML: function(r) {
-            var u, f;
-            if (!r || "string" != typeof r) return null;
-            try {
-                n.DOMParser ? (f = new DOMParser, u = f.parseFromString(r, "text/xml")) : (u = new ActiveXObject("Microsoft.XMLDOM"), u.async = "false", u.loadXML(r))
-            } catch (e) {
-                u = t
-            }
-            return u && u.documentElement && !u.getElementsByTagName("parsererror").length || i.error("Invalid XML: " + r), u
-        },
-        noop: function() {},
-        globalEval: function(t) {
-            t && i.trim(t) && (n.execScript || function(t) {
-                n.eval.call(n, t)
-            })(t)
-        },
-        camelCase: function(n) {
-            return n.replace(pf, "ms-").replace(wf, bf)
-        },
-        nodeName: function(n, t) {
-            return n.nodeName && n.nodeName.toLowerCase() === t.toLowerCase()
-        },
-        each: function(n, t, i) {
-            var u, r = 0,
-                f = n.length,
-                e = dt(n);
-            if (i) {
-                if (e) {
-                    for (; f > r; r++)
-                        if (u = t.apply(n[r], i), u === !1) break
-                } else
-                    for (r in n)
-                        if (u = t.apply(n[r], i), u === !1) break
-            } else if (e) {
-                for (; f > r; r++)
-                    if (u = t.call(n[r], r, n[r]), u === !1) break
-            } else
-                for (r in n)
-                    if (u = t.call(n[r], r, n[r]), u === !1) break;
-            return n
-        },
-        trim: kt && !kt.call(" ") ? function(n) {
-            return null == n ? "" : kt.call(n)
-        } : function(n) {
-            return null == n ? "" : (n + "").replace(hf, "")
-        },
-        makeArray: function(n, t) {
-            var r = t || [];
-            return null != n && (dt(Object(n)) ? i.merge(r, "string" == typeof n ? [n] : n) : bt.call(r, n)), r
-        },
-        inArray: function(n, t, i) {
-            var r;
-            if (t) {
-                if (ki) return ki.call(t, n, i);
-                for (r = t.length, i = i ? 0 > i ? Math.max(0, r + i) : i : 0; r > i; i++)
-                    if (i in t && t[i] === n) return i
-            }
-            return -1
-        },
-        merge: function(n, i) {
-            var f = i.length,
-                u = n.length,
-                r = 0;
-            if ("number" == typeof f)
-                for (; f > r; r++) n[u++] = i[r];
-            else
-                while (i[r] !== t) n[u++] = i[r++];
-            return n.length = u, n
-        },
-        grep: function(n, t, i) {
-            var u, f = [],
-                r = 0,
-                e = n.length;
-            for (i = !!i; e > r; r++) u = !!t(n[r], r), i !== u && f.push(n[r]);
-            return f
-        },
-        map: function(n, t, i) {
-            var u, r = 0,
-                e = n.length,
-                o = dt(n),
-                f = [];
-            if (o)
-                for (; e > r; r++) u = t(n[r], r, i), null != u && (f[f.length] = u);
-            else
-                for (r in n) u = t(n[r], r, i), null != u && (f[f.length] = u);
-            return bi.apply([], f)
-        },
-        guid: 1,
-        proxy: function(n, r) {
-            var f, u, e;
-            return "string" == typeof r && (e = n[r], r = n, n = e), i.isFunction(n) ? (f = l.call(arguments, 2), u = function() {
-                return n.apply(r || this, f.concat(l.call(arguments)))
-            }, u.guid = n.guid = n.guid || i.guid++, u) : t
-        },
-        access: function(n, r, u, f, e, o, s) {
-            var h = 0,
-                l = n.length,
-                c = null == u;
-            if ("object" === i.type(u)) {
-                e = !0;
-                for (h in u) i.access(n, r, h, u[h], !0, o, s)
-            } else if (f !== t && (e = !0, i.isFunction(f) || (s = !0), c && (s ? (r.call(n, f), r = null) : (c = r, r = function(n, t, r) {
-                    return c.call(i(n), r)
-                })), r))
-                for (; l > h; h++) r(n[h], u, s ? f : f.call(n[h], h, r(n[h], u)));
-            return e ? n : c ? r.call(n) : l ? r(n[0], u) : o
-        },
-        now: function() {
-            return (new Date).getTime()
-        }
-    });
-    i.ready.promise = function(t) {
-        if (!et)
-            if (et = i.Deferred(), "complete" === r.readyState) setTimeout(i.ready);
-            else if (r.addEventListener) r.addEventListener("DOMContentLoaded", h, !1), n.addEventListener("load", h, !1);
-        else {
-            r.attachEvent("onreadystatechange", h);
-            n.attachEvent("onload", h);
-            var u = !1;
-            try {
-                u = null == n.frameElement && r.documentElement
-            } catch (e) {}
-            u && u.doScroll && function f() {
-                if (!i.isReady) {
-                    try {
-                        u.doScroll("left")
-                    } catch (n) {
-                        return setTimeout(f, 50)
-                    }
-                    gi();
-                    i.ready()
-                }
-            }()
-        }
-        return et.promise(t)
-    };
-    i.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(n, t) {
-        ot["[object " + t + "]"] = t.toLowerCase()
-    });
-    wi = i(r);
-    gt = {};
-    i.Callbacks = function(n) {
-        n = "string" == typeof n ? gt[n] || kf(n) : i.extend({}, n);
-        var o, f, c, s, e, l, r = [],
-            u = !n.once && [],
-            a = function(t) {
-                for (f = n.memory && t, c = !0, e = l || 0, l = 0, s = r.length, o = !0; r && s > e; e++)
-                    if (r[e].apply(t[0], t[1]) === !1 && n.stopOnFalse) {
-                        f = !1;
-                        break
-                    }
-                o = !1;
-                r && (u ? u.length && a(u.shift()) : f ? r = [] : h.disable())
-            },
-            h = {
-                add: function() {
-                    if (r) {
-                        var t = r.length;
-                        (function u(t) {
-                            i.each(t, function(t, f) {
-                                var e = i.type(f);
-                                "function" === e ? n.unique && h.has(f) || r.push(f) : f && f.length && "string" !== e && u(f)
-                            })
-                        })(arguments);
-                        o ? s = r.length : f && (l = t, a(f))
-                    }
-                    return this
-                },
-                remove: function() {
-                    return r && i.each(arguments, function(n, t) {
-                        for (var u;
-                            (u = i.inArray(t, r, u)) > -1;) r.splice(u, 1), o && (s >= u && s--, e >= u && e--)
-                    }), this
-                },
-                has: function(n) {
-                    return n ? i.inArray(n, r) > -1 : !(!r || !r.length)
-                },
-                empty: function() {
-                    return r = [], this
-                },
-                disable: function() {
-                    return r = u = f = t, this
-                },
-                disabled: function() {
-                    return !r
-                },
-                lock: function() {
-                    return u = t, f || h.disable(), this
-                },
-                locked: function() {
-                    return !u
-                },
-                fireWith: function(n, t) {
-                    return t = t || [], t = [n, t.slice ? t.slice() : t], !r || c && !u || (o ? u.push(t) : a(t)), this
-                },
-                fire: function() {
-                    return h.fireWith(this, arguments), this
-                },
-                fired: function() {
-                    return !!c
-                }
-            };
-        return h
-    };
-    i.extend({
-        Deferred: function(n) {
-            var u = [
-                    ["resolve", "done", i.Callbacks("once memory"), "resolved"],
-                    ["reject", "fail", i.Callbacks("once memory"), "rejected"],
-                    ["notify", "progress", i.Callbacks("memory")]
-                ],
-                f = "pending",
-                r = {
-                    state: function() {
-                        return f
-                    },
-                    always: function() {
-                        return t.done(arguments).fail(arguments), this
-                    },
-                    then: function() {
-                        var n = arguments;
-                        return i.Deferred(function(f) {
-                            i.each(u, function(u, e) {
-                                var s = e[0],
-                                    o = i.isFunction(n[u]) && n[u];
-                                t[e[1]](function() {
-                                    var n = o && o.apply(this, arguments);
-                                    n && i.isFunction(n.promise) ? n.promise().done(f.resolve).fail(f.reject).progress(f.notify) : f[s + "With"](this === r ? f.promise() : this, o ? [n] : arguments)
-                                })
-                            });
-                            n = null
-                        }).promise()
-                    },
-                    promise: function(n) {
-                        return null != n ? i.extend(n, r) : r
-                    }
-                },
-                t = {};
-            return r.pipe = r.then, i.each(u, function(n, i) {
-                var e = i[2],
-                    o = i[3];
-                r[i[1]] = e.add;
-                o && e.add(function() {
-                    f = o
-                }, u[1 ^ n][2].disable, u[2][2].lock);
-                t[i[0]] = function() {
-                    return t[i[0] + "With"](this === t ? r : this, arguments), this
-                };
-                t[i[0] + "With"] = e.fireWith
-            }), r.promise(t), n && n.call(t, t), t
-        },
-        when: function(n) {
-            var t = 0,
-                u = l.call(arguments),
-                r = u.length,
-                e = 1 !== r || n && i.isFunction(n.promise) ? r : 0,
-                f = 1 === e ? n : i.Deferred(),
-                h = function(n, t, i) {
-                    return function(r) {
-                        t[n] = this;
-                        i[n] = arguments.length > 1 ? l.call(arguments) : r;
-                        i === o ? f.notifyWith(t, i) : --e || f.resolveWith(t, i)
-                    }
-                },
-                o, c, s;
-            if (r > 1)
-                for (o = Array(r), c = Array(r), s = Array(r); r > t; t++) u[t] && i.isFunction(u[t].promise) ? u[t].promise().done(h(t, s, u)).fail(f.reject).progress(h(t, c, o)) : --e;
-            return e || f.resolveWith(s, u), f.promise()
-        }
-    });
-    i.support = function() {
-        var u, s, e, f, h, c, l, a, y, v, t = r.createElement("div");
-        if (t.setAttribute("className", "t"), t.innerHTML = "  <link/><table><\/table><a href='/a'>a<\/a><input type='checkbox'/>", s = t.getElementsByTagName("*"), e = t.getElementsByTagName("a")[0], !s || !e || !s.length) return {};
-        h = r.createElement("select");
-        l = h.appendChild(r.createElement("option"));
-        f = t.getElementsByTagName("input")[0];
-        e.style.cssText = "top:1px;float:left;opacity:.5";
-        u = {
-            getSetAttribute: "t" !== t.className,
-            leadingWhitespace: 3 === t.firstChild.nodeType,
-            tbody: !t.getElementsByTagName("tbody").length,
-            htmlSerialize: !!t.getElementsByTagName("link").length,
-            style: /top/.test(e.getAttribute("style")),
-            hrefNormalized: "/a" === e.getAttribute("href"),
-            opacity: /^0.5/.test(e.style.opacity),
-            cssFloat: !!e.style.cssFloat,
-            checkOn: !!f.value,
-            optSelected: l.selected,
-            enctype: !!r.createElement("form").enctype,
-            html5Clone: "<:nav><\/:nav>" !== r.createElement("nav").cloneNode(!0).outerHTML,
-            boxModel: "CSS1Compat" === r.compatMode,
-            deleteExpando: !0,
-            noCloneEvent: !0,
-            inlineBlockNeedsLayout: !1,
-            shrinkWrapBlocks: !1,
-            reliableMarginRight: !0,
-            boxSizingReliable: !0,
-            pixelPosition: !1
-        };
-        f.checked = !0;
-        u.noCloneChecked = f.cloneNode(!0).checked;
-        h.disabled = !0;
-        u.optDisabled = !l.disabled;
-        try {
-            delete t.test
-        } catch (p) {
-            u.deleteExpando = !1
-        }
-        f = r.createElement("input");
-        f.setAttribute("value", "");
-        u.input = "" === f.getAttribute("value");
-        f.value = "t";
-        f.setAttribute("type", "radio");
-        u.radioValue = "t" === f.value;
-        f.setAttribute("checked", "t");
-        f.setAttribute("name", "t");
-        c = r.createDocumentFragment();
-        c.appendChild(f);
-        u.appendChecked = f.checked;
-        u.checkClone = c.cloneNode(!0).cloneNode(!0).lastChild.checked;
-        t.attachEvent && (t.attachEvent("onclick", function() {
-            u.noCloneEvent = !1
-        }), t.cloneNode(!0).click());
-        for (v in {
-                submit: !0,
-                change: !0,
-                focusin: !0
-            }) t.setAttribute(a = "on" + v, "t"), u[v + "Bubbles"] = a in n || t.attributes[a].expando === !1;
-        return t.style.backgroundClip = "content-box", t.cloneNode(!0).style.backgroundClip = "", u.clearCloneStyle = "content-box" === t.style.backgroundClip, i(function() {
-            var e, f, i, h = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
-                s = r.getElementsByTagName("body")[0];
-            s && (e = r.createElement("div"), e.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px", s.appendChild(e).appendChild(t), t.innerHTML = "<table><tr><td><\/td><td>t<\/td><\/tr><\/table>", i = t.getElementsByTagName("td"), i[0].style.cssText = "padding:0;margin:0;border:0;display:none", y = 0 === i[0].offsetHeight, i[0].style.display = "", i[1].style.display = "none", u.reliableHiddenOffsets = y && 0 === i[0].offsetHeight, t.innerHTML = "", t.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;", u.boxSizing = 4 === t.offsetWidth, u.doesNotIncludeMarginInBodyOffset = 1 !== s.offsetTop, n.getComputedStyle && (u.pixelPosition = "1%" !== (n.getComputedStyle(t, null) || {}).top, u.boxSizingReliable = "4px" === (n.getComputedStyle(t, null) || {
-                width: "4px"
-            }).width, f = t.appendChild(r.createElement("div")), f.style.cssText = t.style.cssText = h, f.style.marginRight = f.style.width = "0", t.style.width = "1px", u.reliableMarginRight = !parseFloat((n.getComputedStyle(f, null) || {}).marginRight)), typeof t.style.zoom !== o && (t.innerHTML = "", t.style.cssText = h + "width:1px;padding:1px;display:inline;zoom:1", u.inlineBlockNeedsLayout = 3 === t.offsetWidth, t.style.display = "block", t.innerHTML = "<div><\/div>", t.firstChild.style.width = "5px", u.shrinkWrapBlocks = 3 !== t.offsetWidth, u.inlineBlockNeedsLayout && (s.style.zoom = 1)), s.removeChild(e), e = t = i = f = null)
-        }), s = h = c = l = e = f = null, u
-    }();
-    nr = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/;
-    tr = /([A-Z])/g;
-    i.extend({
-        cache: {},
-        expando: "jQuery" + (wt + Math.random()).replace(/\D/g, ""),
-        noData: {
-            embed: !0,
-            object: "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
-            applet: !0
-        },
-        hasData: function(n) {
-            return n = n.nodeType ? i.cache[n[i.expando]] : n[i.expando], !!n && !ni(n)
-        },
-        data: function(n, t, i) {
-            return ir(n, t, i)
-        },
-        removeData: function(n, t) {
-            return rr(n, t)
-        },
-        _data: function(n, t, i) {
-            return ir(n, t, i, !0)
-        },
-        _removeData: function(n, t) {
-            return rr(n, t, !0)
-        },
-        acceptData: function(n) {
-            if (n.nodeType && 1 !== n.nodeType && 9 !== n.nodeType) return !1;
-            var t = n.nodeName && i.noData[n.nodeName.toLowerCase()];
-            return !t || t !== !0 && n.getAttribute("classid") === t
-        }
-    });
-    i.fn.extend({
-        data: function(n, r) {
-            var e, f, u = this[0],
-                o = 0,
-                s = null;
-            if (n === t) {
-                if (this.length && (s = i.data(u), 1 === u.nodeType && !i._data(u, "parsedAttrs"))) {
-                    for (e = u.attributes; e.length > o; o++) f = e[o].name, f.indexOf("data-") || (f = i.camelCase(f.slice(5)), ur(u, f, s[f]));
-                    i._data(u, "parsedAttrs", !0)
-                }
-                return s
-            }
-            return "object" == typeof n ? this.each(function() {
-                i.data(this, n)
-            }) : i.access(this, function(r) {
-                return r === t ? u ? ur(u, n, i.data(u, n)) : null : (this.each(function() {
-                    i.data(this, n, r)
-                }), t)
-            }, null, r, arguments.length > 1, null, !0)
-        },
-        removeData: function(n) {
-            return this.each(function() {
-                i.removeData(this, n)
-            })
-        }
-    });
-    i.extend({
-        queue: function(n, r, u) {
-            var f;
-            return n ? (r = (r || "fx") + "queue", f = i._data(n, r), u && (!f || i.isArray(u) ? f = i._data(n, r, i.makeArray(u)) : f.push(u)), f || []) : t
-        },
-        dequeue: function(n, t) {
-            t = t || "fx";
-            var f = i.queue(n, t),
-                e = f.length,
-                r = f.shift(),
-                u = i._queueHooks(n, t),
-                o = function() {
-                    i.dequeue(n, t)
-                };
-            "inprogress" === r && (r = f.shift(), e--);
-            u.cur = r;
-            r && ("fx" === t && f.unshift("inprogress"), delete u.stop, r.call(n, o, u));
-            !e && u && u.empty.fire()
-        },
-        _queueHooks: function(n, t) {
-            var r = t + "queueHooks";
-            return i._data(n, r) || i._data(n, r, {
-                empty: i.Callbacks("once memory").add(function() {
-                    i._removeData(n, t + "queue");
-                    i._removeData(n, r)
-                })
-            })
-        }
-    });
-    i.fn.extend({
-        queue: function(n, r) {
-            var u = 2;
-            return "string" != typeof n && (r = n, n = "fx", u--), u > arguments.length ? i.queue(this[0], n) : r === t ? this : this.each(function() {
-                var t = i.queue(this, n, r);
-                i._queueHooks(this, n);
-                "fx" === n && "inprogress" !== t[0] && i.dequeue(this, n)
-            })
-        },
-        dequeue: function(n) {
-            return this.each(function() {
-                i.dequeue(this, n)
-            })
-        },
-        delay: function(n, t) {
-            return n = i.fx ? i.fx.speeds[n] || n : n, t = t || "fx", this.queue(t, function(t, i) {
-                var r = setTimeout(t, n);
-                i.stop = function() {
-                    clearTimeout(r)
-                }
-            })
-        },
-        clearQueue: function(n) {
-            return this.queue(n || "fx", [])
-        },
-        promise: function(n, r) {
-            var u, e = 1,
-                o = i.Deferred(),
-                f = this,
-                s = this.length,
-                h = function() {
-                    --e || o.resolveWith(f, [f])
-                };
-            for ("string" != typeof n && (r = n, n = t), n = n || "fx"; s--;) u = i._data(f[s], n + "queueHooks"), u && u.empty && (e++, u.empty.add(h));
-            return h(), o.promise(r)
-        }
-    });
-    var k, fr, ti = /[\t\r\n]/g,
-        df = /\r/g,
-        gf = /^(?:input|select|textarea|button|object)$/i,
-        ne = /^(?:a|area)$/i,
-        er = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
-        ii = /^(?:checked|selected)$/i,
-        a = i.support.getSetAttribute,
-        ri = i.support.input;
-    i.fn.extend({
-        attr: function(n, t) {
-            return i.access(this, i.attr, n, t, arguments.length > 1)
-        },
-        removeAttr: function(n) {
-            return this.each(function() {
-                i.removeAttr(this, n)
-            })
-        },
-        prop: function(n, t) {
-            return i.access(this, i.prop, n, t, arguments.length > 1)
-        },
-        removeProp: function(n) {
-            return n = i.propFix[n] || n, this.each(function() {
-                try {
-                    this[n] = t;
-                    delete this[n]
-                } catch (i) {}
-            })
-        },
-        addClass: function(n) {
-            var e, t, r, u, o, f = 0,
-                h = this.length,
-                c = "string" == typeof n && n;
-            if (i.isFunction(n)) return this.each(function(t) {
-                i(this).addClass(n.call(this, t, this.className))
-            });
-            if (c)
-                for (e = (n || "").match(s) || []; h > f; f++)
-                    if (t = this[f], r = 1 === t.nodeType && (t.className ? (" " + t.className + " ").replace(ti, " ") : " ")) {
-                        for (o = 0; u = e[o++];) 0 > r.indexOf(" " + u + " ") && (r += u + " ");
-                        t.className = i.trim(r)
-                    }
-            return this
-        },
-        removeClass: function(n) {
-            var e, t, r, u, o, f = 0,
-                h = this.length,
-                c = 0 === arguments.length || "string" == typeof n && n;
-            if (i.isFunction(n)) return this.each(function(t) {
-                i(this).removeClass(n.call(this, t, this.className))
-            });
-            if (c)
-                for (e = (n || "").match(s) || []; h > f; f++)
-                    if (t = this[f], r = 1 === t.nodeType && (t.className ? (" " + t.className + " ").replace(ti, " ") : "")) {
-                        for (o = 0; u = e[o++];)
-                            while (r.indexOf(" " + u + " ") >= 0) r = r.replace(" " + u + " ", " ");
-                        t.className = n ? i.trim(r) : ""
-                    }
-            return this
-        },
-        toggleClass: function(n, t) {
-            var r = typeof n,
-                u = "boolean" == typeof t;
-            return i.isFunction(n) ? this.each(function(r) {
-                i(this).toggleClass(n.call(this, r, this.className, t), t)
-            }) : this.each(function() {
-                if ("string" === r)
-                    for (var f, c = 0, h = i(this), e = t, l = n.match(s) || []; f = l[c++];) e = u ? e : !h.hasClass(f), h[e ? "addClass" : "removeClass"](f);
-                else(r === o || "boolean" === r) && (this.className && i._data(this, "__className__", this.className), this.className = this.className || n === !1 ? "" : i._data(this, "__className__") || "")
-            })
-        },
-        hasClass: function(n) {
-            for (var i = " " + n + " ", t = 0, r = this.length; r > t; t++)
-                if (1 === this[t].nodeType && (" " + this[t].className + " ").replace(ti, " ").indexOf(i) >= 0) return !0;
-            return !1
-        },
-        val: function(n) {
-            var u, r, e, f = this[0];
-            return arguments.length ? (e = i.isFunction(n), this.each(function(u) {
-                var f, o = i(this);
-                1 === this.nodeType && (f = e ? n.call(this, u, o.val()) : n, null == f ? f = "" : "number" == typeof f ? f += "" : i.isArray(f) && (f = i.map(f, function(n) {
-                    return null == n ? "" : n + ""
-                })), r = i.valHooks[this.type] || i.valHooks[this.nodeName.toLowerCase()], r && "set" in r && r.set(this, f, "value") !== t || (this.value = f))
-            })) : f ? (r = i.valHooks[f.type] || i.valHooks[f.nodeName.toLowerCase()], r && "get" in r && (u = r.get(f, "value")) !== t ? u : (u = f.value, "string" == typeof u ? u.replace(df, "") : null == u ? "" : u)) : void 0
-        }
-    });
-    i.extend({
-        valHooks: {
-            option: {
-                get: function(n) {
-                    var t = n.attributes.value;
-                    return !t || t.specified ? n.value : n.text
-                }
-            },
-            select: {
-                get: function(n) {
-                    for (var e, t, o = n.options, r = n.selectedIndex, u = "select-one" === n.type || 0 > r, s = u ? null : [], h = u ? r + 1 : o.length, f = 0 > r ? h : u ? r : 0; h > f; f++)
-                        if (t = o[f], !(!t.selected && f !== r || (i.support.optDisabled ? t.disabled : null !== t.getAttribute("disabled")) || t.parentNode.disabled && i.nodeName(t.parentNode, "optgroup"))) {
-                            if (e = i(t).val(), u) return e;
-                            s.push(e)
-                        }
-                    return s
-                },
-                set: function(n, t) {
-                    var r = i.makeArray(t);
-                    return i(n).find("option").each(function() {
-                        this.selected = i.inArray(i(this).val(), r) >= 0
-                    }), r.length || (n.selectedIndex = -1), r
-                }
-            }
-        },
-        attr: function(n, r, u) {
-            var f, s, e, h = n.nodeType;
-            if (n && 3 !== h && 8 !== h && 2 !== h) return typeof n.getAttribute === o ? i.prop(n, r, u) : (s = 1 !== h || !i.isXMLDoc(n), s && (r = r.toLowerCase(), f = i.attrHooks[r] || (er.test(r) ? fr : k)), u === t ? f && s && "get" in f && null !== (e = f.get(n, r)) ? e : (typeof n.getAttribute !== o && (e = n.getAttribute(r)), null == e ? t : e) : null !== u ? f && s && "set" in f && (e = f.set(n, u, r)) !== t ? e : (n.setAttribute(r, u + ""), u) : (i.removeAttr(n, r), t))
-        },
-        removeAttr: function(n, t) {
-            var r, u, e = 0,
-                f = t && t.match(s);
-            if (f && 1 === n.nodeType)
-                while (r = f[e++]) u = i.propFix[r] || r, er.test(r) ? !a && ii.test(r) ? n[i.camelCase("default-" + r)] = n[u] = !1 : n[u] = !1 : i.attr(n, r, ""), n.removeAttribute(a ? r : u)
-        },
-        attrHooks: {
-            type: {
-                set: function(n, t) {
-                    if (!i.support.radioValue && "radio" === t && i.nodeName(n, "input")) {
-                        var r = n.value;
-                        return n.setAttribute("type", t), r && (n.value = r), t
-                    }
-                }
-            }
-        },
-        propFix: {
-            tabindex: "tabIndex",
-            readonly: "readOnly",
-            "for": "htmlFor",
-            "class": "className",
-            maxlength: "maxLength",
-            cellspacing: "cellSpacing",
-            cellpadding: "cellPadding",
-            rowspan: "rowSpan",
-            colspan: "colSpan",
-            usemap: "useMap",
-            frameborder: "frameBorder",
-            contenteditable: "contentEditable"
-        },
-        prop: function(n, r, u) {
-            var e, f, s, o = n.nodeType;
-            if (n && 3 !== o && 8 !== o && 2 !== o) return s = 1 !== o || !i.isXMLDoc(n), s && (r = i.propFix[r] || r, f = i.propHooks[r]), u !== t ? f && "set" in f && (e = f.set(n, u, r)) !== t ? e : n[r] = u : f && "get" in f && null !== (e = f.get(n, r)) ? e : n[r]
-        },
-        propHooks: {
-            tabIndex: {
-                get: function(n) {
-                    var i = n.getAttributeNode("tabindex");
-                    return i && i.specified ? parseInt(i.value, 10) : gf.test(n.nodeName) || ne.test(n.nodeName) && n.href ? 0 : t
-                }
-            }
-        }
-    });
-    fr = {
-        get: function(n, r) {
-            var u = i.prop(n, r),
-                f = "boolean" == typeof u && n.getAttribute(r),
-                e = "boolean" == typeof u ? ri && a ? null != f : ii.test(r) ? n[i.camelCase("default-" + r)] : !!f : n.getAttributeNode(r);
-            return e && e.value !== !1 ? r.toLowerCase() : t
-        },
-        set: function(n, t, r) {
-            return t === !1 ? i.removeAttr(n, r) : ri && a || !ii.test(r) ? n.setAttribute(!a && i.propFix[r] || r, r) : n[i.camelCase("default-" + r)] = n[r] = !0, r
-        }
-    };
-    ri && a || (i.attrHooks.value = {
-        get: function(n, r) {
-            var u = n.getAttributeNode(r);
-            return i.nodeName(n, "input") ? n.defaultValue : u && u.specified ? u.value : t
-        },
-        set: function(n, r, u) {
-            return i.nodeName(n, "input") ? (n.defaultValue = r, t) : k && k.set(n, r, u)
-        }
-    });
-    a || (k = i.valHooks.button = {
-        get: function(n, i) {
-            var r = n.getAttributeNode(i);
-            return r && ("id" === i || "name" === i || "coords" === i ? "" !== r.value : r.specified) ? r.value : t
-        },
-        set: function(n, i, r) {
-            var u = n.getAttributeNode(r);
-            return u || n.setAttributeNode(u = n.ownerDocument.createAttribute(r)), u.value = i += "", "value" === r || i === n.getAttribute(r) ? i : t
-        }
-    }, i.attrHooks.contenteditable = {
-        get: k.get,
-        set: function(n, t, i) {
-            k.set(n, "" === t ? !1 : t, i)
-        }
-    }, i.each(["width", "height"], function(n, r) {
-        i.attrHooks[r] = i.extend(i.attrHooks[r], {
-            set: function(n, i) {
-                return "" === i ? (n.setAttribute(r, "auto"), i) : t
-            }
-        })
-    }));
-    i.support.hrefNormalized || (i.each(["href", "src", "width", "height"], function(n, r) {
-        i.attrHooks[r] = i.extend(i.attrHooks[r], {
-            get: function(n) {
-                var i = n.getAttribute(r, 2);
-                return null == i ? t : i
-            }
-        })
-    }), i.each(["href", "src"], function(n, t) {
-        i.propHooks[t] = {
-            get: function(n) {
-                return n.getAttribute(t, 4)
-            }
-        }
-    }));
-    i.support.style || (i.attrHooks.style = {
-        get: function(n) {
-            return n.style.cssText || t
-        },
-        set: function(n, t) {
-            return n.style.cssText = t + ""
-        }
-    });
-    i.support.optSelected || (i.propHooks.selected = i.extend(i.propHooks.selected, {
-        get: function(n) {
-            var t = n.parentNode;
-            return t && (t.selectedIndex, t.parentNode && t.parentNode.selectedIndex), null
-        }
-    }));
-    i.support.enctype || (i.propFix.enctype = "encoding");
-    i.support.checkOn || i.each(["radio", "checkbox"], function() {
-        i.valHooks[this] = {
-            get: function(n) {
-                return null === n.getAttribute("value") ? "on" : n.value
-            }
-        }
-    });
-    i.each(["radio", "checkbox"], function() {
-        i.valHooks[this] = i.extend(i.valHooks[this], {
-            set: function(n, r) {
-                return i.isArray(r) ? n.checked = i.inArray(i(n).val(), r) >= 0 : t
-            }
-        })
-    });
-    var ui = /^(?:input|select|textarea)$/i,
-        te = /^key/,
-        ie = /^(?:mouse|contextmenu)|click/,
-        or = /^(?:focusinfocus|focusoutblur)$/,
-        sr = /^([^.]*)(?:\.(.+)|)$/;
-    i.event = {
-        global: {},
-        add: function(n, r, u, f, e) {
-            var b, p, k, w, c, l, a, v, h, d, g, y = i._data(n);
-            if (y) {
-                for (u.handler && (w = u, u = w.handler, e = w.selector), u.guid || (u.guid = i.guid++), (p = y.events) || (p = y.events = {}), (l = y.handle) || (l = y.handle = function(n) {
-                        return typeof i === o || n && i.event.triggered === n.type ? t : i.event.dispatch.apply(l.elem, arguments)
-                    }, l.elem = n), r = (r || "").match(s) || [""], k = r.length; k--;) b = sr.exec(r[k]) || [], h = g = b[1], d = (b[2] || "").split(".").sort(), c = i.event.special[h] || {}, h = (e ? c.delegateType : c.bindType) || h, c = i.event.special[h] || {}, a = i.extend({
-                    type: h,
-                    origType: g,
-                    data: f,
-                    handler: u,
-                    guid: u.guid,
-                    selector: e,
-                    needsContext: e && i.expr.match.needsContext.test(e),
-                    namespace: d.join(".")
-                }, w), (v = p[h]) || (v = p[h] = [], v.delegateCount = 0, c.setup && c.setup.call(n, f, d, l) !== !1 || (n.addEventListener ? n.addEventListener(h, l, !1) : n.attachEvent && n.attachEvent("on" + h, l))), c.add && (c.add.call(n, a), a.handler.guid || (a.handler.guid = u.guid)), e ? v.splice(v.delegateCount++, 0, a) : v.push(a), i.event.global[h] = !0;
-                n = null
-            }
-        },
-        remove: function(n, t, r, u, f) {
-            var y, o, h, b, p, a, c, l, e, w, k, v = i.hasData(n) && i._data(n);
-            if (v && (a = v.events)) {
-                for (t = (t || "").match(s) || [""], p = t.length; p--;)
-                    if (h = sr.exec(t[p]) || [], e = k = h[1], w = (h[2] || "").split(".").sort(), e) {
-                        for (c = i.event.special[e] || {}, e = (u ? c.delegateType : c.bindType) || e, l = a[e] || [], h = h[2] && RegExp("(^|\\.)" + w.join("\\.(?:.*\\.|)") + "(\\.|$)"), b = y = l.length; y--;) o = l[y], !f && k !== o.origType || r && r.guid !== o.guid || h && !h.test(o.namespace) || u && u !== o.selector && ("**" !== u || !o.selector) || (l.splice(y, 1), o.selector && l.delegateCount--, c.remove && c.remove.call(n, o));
-                        b && !l.length && (c.teardown && c.teardown.call(n, w, v.handle) !== !1 || i.removeEvent(n, e, v.handle), delete a[e])
-                    } else
-                        for (e in a) i.event.remove(n, e + t[p], r, u, !0);
-                i.isEmptyObject(a) && (delete v.handle, i._removeData(n, "events"))
-            }
-        },
-        trigger: function(u, f, e, o) {
-            var a, v, h, p, l, c, w, b = [e || r],
-                s = it.call(u, "type") ? u.type : u,
-                y = it.call(u, "namespace") ? u.namespace.split(".") : [];
-            if (h = c = e = e || r, 3 !== e.nodeType && 8 !== e.nodeType && !or.test(s + i.event.triggered) && (s.indexOf(".") >= 0 && (y = s.split("."), s = y.shift(), y.sort()), v = 0 > s.indexOf(":") && "on" + s, u = u[i.expando] ? u : new i.Event(s, "object" == typeof u && u), u.isTrigger = !0, u.namespace = y.join("."), u.namespace_re = u.namespace ? RegExp("(^|\\.)" + y.join("\\.(?:.*\\.|)") + "(\\.|$)") : null, u.result = t, u.target || (u.target = e), f = null == f ? [u] : i.makeArray(f, [u]), l = i.event.special[s] || {}, o || !l.trigger || l.trigger.apply(e, f) !== !1)) {
-                if (!o && !l.noBubble && !i.isWindow(e)) {
-                    for (p = l.delegateType || s, or.test(p + s) || (h = h.parentNode); h; h = h.parentNode) b.push(h), c = h;
-                    c === (e.ownerDocument || r) && b.push(c.defaultView || c.parentWindow || n)
-                }
-                for (w = 0;
-                    (h = b[w++]) && !u.isPropagationStopped();) u.type = w > 1 ? p : l.bindType || s, a = (i._data(h, "events") || {})[u.type] && i._data(h, "handle"), a && a.apply(h, f), a = v && h[v], a && i.acceptData(h) && a.apply && a.apply(h, f) === !1 && u.preventDefault();
-                if (u.type = s, !(o || u.isDefaultPrevented() || l._default && l._default.apply(e.ownerDocument, f) !== !1 || "click" === s && i.nodeName(e, "a") || !i.acceptData(e) || !v || !e[s] || i.isWindow(e))) {
-                    c = e[v];
-                    c && (e[v] = null);
-                    i.event.triggered = s;
-                    try {
-                        e[s]()
-                    } catch (k) {}
-                    i.event.triggered = t;
-                    c && (e[v] = c)
-                }
-                return u.result
-            }
-        },
-        dispatch: function(n) {
-            n = i.event.fix(n);
-            var o, e, r, u, s, h = [],
-                c = l.call(arguments),
-                a = (i._data(this, "events") || {})[n.type] || [],
-                f = i.event.special[n.type] || {};
-            if (c[0] = n, n.delegateTarget = this, !f.preDispatch || f.preDispatch.call(this, n) !== !1) {
-                for (h = i.event.handlers.call(this, n, a), o = 0;
-                    (u = h[o++]) && !n.isPropagationStopped();)
-                    for (n.currentTarget = u.elem, s = 0;
-                        (r = u.handlers[s++]) && !n.isImmediatePropagationStopped();)(!n.namespace_re || n.namespace_re.test(r.namespace)) && (n.handleObj = r, n.data = r.data, e = ((i.event.special[r.origType] || {}).handle || r.handler).apply(u.elem, c), e !== t && (n.result = e) === !1 && (n.preventDefault(), n.stopPropagation()));
-                return f.postDispatch && f.postDispatch.call(this, n), n.result
-            }
-        },
-        handlers: function(n, r) {
-            var e, o, f, s, c = [],
-                h = r.delegateCount,
-                u = n.target;
-            if (h && u.nodeType && (!n.button || "click" !== n.type))
-                for (; u != this; u = u.parentNode || this)
-                    if (1 === u.nodeType && (u.disabled !== !0 || "click" !== n.type)) {
-                        for (f = [], s = 0; h > s; s++) o = r[s], e = o.selector + " ", f[e] === t && (f[e] = o.needsContext ? i(e, this).index(u) >= 0 : i.find(e, this, null, [u]).length), f[e] && f.push(o);
-                        f.length && c.push({
-                            elem: u,
-                            handlers: f
-                        })
-                    }
-            return r.length > h && c.push({
-                elem: this,
-                handlers: r.slice(h)
-            }), c
-        },
-        fix: function(n) {
-            if (n[i.expando]) return n;
-            var e, o, s, u = n.type,
-                f = n,
-                t = this.fixHooks[u];
-            for (t || (this.fixHooks[u] = t = ie.test(u) ? this.mouseHooks : te.test(u) ? this.keyHooks : {}), s = t.props ? this.props.concat(t.props) : this.props, n = new i.Event(f), e = s.length; e--;) o = s[e], n[o] = f[o];
-            return n.target || (n.target = f.srcElement || r), 3 === n.target.nodeType && (n.target = n.target.parentNode), n.metaKey = !!n.metaKey, t.filter ? t.filter(n, f) : n
-        },
-        props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
-        fixHooks: {},
-        keyHooks: {
-            props: "char charCode key keyCode".split(" "),
-            filter: function(n, t) {
-                return null == n.which && (n.which = null != t.charCode ? t.charCode : t.keyCode), n
-            }
-        },
-        mouseHooks: {
-            props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
-            filter: function(n, i) {
-                var u, o, f, e = i.button,
-                    s = i.fromElement;
-                return null == n.pageX && null != i.clientX && (o = n.target.ownerDocument || r, f = o.documentElement, u = o.body, n.pageX = i.clientX + (f && f.scrollLeft || u && u.scrollLeft || 0) - (f && f.clientLeft || u && u.clientLeft || 0), n.pageY = i.clientY + (f && f.scrollTop || u && u.scrollTop || 0) - (f && f.clientTop || u && u.clientTop || 0)), !n.relatedTarget && s && (n.relatedTarget = s === n.target ? i.toElement : s), n.which || e === t || (n.which = 1 & e ? 1 : 2 & e ? 3 : 4 & e ? 2 : 0), n
-            }
-        },
-        special: {
-            load: {
-                noBubble: !0
-            },
-            click: {
-                trigger: function() {
-                    return i.nodeName(this, "input") && "checkbox" === this.type && this.click ? (this.click(), !1) : t
-                }
-            },
-            focus: {
-                trigger: function() {
-                    if (this !== r.activeElement && this.focus) try {
-                        return this.focus(), !1
-                    } catch (n) {}
-                },
-                delegateType: "focusin"
-            },
-            blur: {
-                trigger: function() {
-                    return this === r.activeElement && this.blur ? (this.blur(), !1) : t
-                },
-                delegateType: "focusout"
-            },
-            beforeunload: {
-                postDispatch: function(n) {
-                    n.result !== t && (n.originalEvent.returnValue = n.result)
-                }
-            }
-        },
-        simulate: function(n, t, r, u) {
-            var f = i.extend(new i.Event, r, {
-                type: n,
-                isSimulated: !0,
-                originalEvent: {}
-            });
-            u ? i.event.trigger(f, null, t) : i.event.dispatch.call(t, f);
-            f.isDefaultPrevented() && r.preventDefault()
-        }
-    };
-    i.removeEvent = r.removeEventListener ? function(n, t, i) {
-        n.removeEventListener && n.removeEventListener(t, i, !1)
-    } : function(n, t, i) {
-        var r = "on" + t;
-        n.detachEvent && (typeof n[r] === o && (n[r] = null), n.detachEvent(r, i))
-    };
-    i.Event = function(n, r) {
-        return this instanceof i.Event ? (n && n.type ? (this.originalEvent = n, this.type = n.type, this.isDefaultPrevented = n.defaultPrevented || n.returnValue === !1 || n.getPreventDefault && n.getPreventDefault() ? ht : d) : this.type = n, r && i.extend(this, r), this.timeStamp = n && n.timeStamp || i.now(), this[i.expando] = !0, t) : new i.Event(n, r)
-    };
-    i.Event.prototype = {
-        isDefaultPrevented: d,
-        isPropagationStopped: d,
-        isImmediatePropagationStopped: d,
-        preventDefault: function() {
-            var n = this.originalEvent;
-            this.isDefaultPrevented = ht;
-            n && (n.preventDefault ? n.preventDefault() : n.returnValue = !1)
-        },
-        stopPropagation: function() {
-            var n = this.originalEvent;
-            this.isPropagationStopped = ht;
-            n && (n.stopPropagation && n.stopPropagation(), n.cancelBubble = !0)
-        },
-        stopImmediatePropagation: function() {
-            this.isImmediatePropagationStopped = ht;
-            this.stopPropagation()
-        }
-    };
-    i.each({
-        mouseenter: "mouseover",
-        mouseleave: "mouseout"
-    }, function(n, t) {
-        i.event.special[n] = {
-            delegateType: t,
-            bindType: t,
-            handle: function(n) {
-                var u, f = this,
-                    r = n.relatedTarget,
-                    e = n.handleObj;
-                return (!r || r !== f && !i.contains(f, r)) && (n.type = e.origType, u = e.handler.apply(this, arguments), n.type = t), u
-            }
-        }
-    });
-    i.support.submitBubbles || (i.event.special.submit = {
-        setup: function() {
-            return i.nodeName(this, "form") ? !1 : (i.event.add(this, "click._submit keypress._submit", function(n) {
-                var u = n.target,
-                    r = i.nodeName(u, "input") || i.nodeName(u, "button") ? u.form : t;
-                r && !i._data(r, "submitBubbles") && (i.event.add(r, "submit._submit", function(n) {
-                    n._submit_bubble = !0
-                }), i._data(r, "submitBubbles", !0))
-            }), t)
-        },
-        postDispatch: function(n) {
-            n._submit_bubble && (delete n._submit_bubble, this.parentNode && !n.isTrigger && i.event.simulate("submit", this.parentNode, n, !0))
-        },
-        teardown: function() {
-            return i.nodeName(this, "form") ? !1 : (i.event.remove(this, "._submit"), t)
-        }
-    });
-    i.support.changeBubbles || (i.event.special.change = {
-        setup: function() {
-            return ui.test(this.nodeName) ? (("checkbox" === this.type || "radio" === this.type) && (i.event.add(this, "propertychange._change", function(n) {
-                "checked" === n.originalEvent.propertyName && (this._just_changed = !0)
-            }), i.event.add(this, "click._change", function(n) {
-                this._just_changed && !n.isTrigger && (this._just_changed = !1);
-                i.event.simulate("change", this, n, !0)
-            })), !1) : (i.event.add(this, "beforeactivate._change", function(n) {
-                var t = n.target;
-                ui.test(t.nodeName) && !i._data(t, "changeBubbles") && (i.event.add(t, "change._change", function(n) {
-                    !this.parentNode || n.isSimulated || n.isTrigger || i.event.simulate("change", this.parentNode, n, !0)
-                }), i._data(t, "changeBubbles", !0))
-            }), t)
-        },
-        handle: function(n) {
-            var i = n.target;
-            return this !== i || n.isSimulated || n.isTrigger || "radio" !== i.type && "checkbox" !== i.type ? n.handleObj.handler.apply(this, arguments) : t
-        },
-        teardown: function() {
-            return i.event.remove(this, "._change"), !ui.test(this.nodeName)
-        }
-    });
-    i.support.focusinBubbles || i.each({
-        focus: "focusin",
-        blur: "focusout"
-    }, function(n, t) {
-        var u = 0,
-            f = function(n) {
-                i.event.simulate(t, n.target, i.event.fix(n), !0)
-            };
-        i.event.special[t] = {
-            setup: function() {
-                0 == u++ && r.addEventListener(n, f, !0)
-            },
-            teardown: function() {
-                0 == --u && r.removeEventListener(n, f, !0)
-            }
-        }
-    });
-    i.fn.extend({
-            on: function(n, r, u, f, e) {
-                var s, o;
-                if ("object" == typeof n) {
-                    "string" != typeof r && (u = u || r, r = t);
-                    for (s in n) this.on(s, r, u, n[s], e);
-                    return this
-                }
-                if (null == u && null == f ? (f = r, u = r = t) : null == f && ("string" == typeof r ? (f = u, u = t) : (f = u, u = r, r = t)), f === !1) f = d;
-                else if (!f) return this;
-                return 1 === e && (o = f, f = function(n) {
-                    return i().off(n), o.apply(this, arguments)
-                }, f.guid = o.guid || (o.guid = i.guid++)), this.each(function() {
-                    i.event.add(this, n, f, u, r)
-                })
-            },
-            one: function(n, t, i, r) {
-                return this.on(n, t, i, r, 1)
-            },
-            off: function(n, r, u) {
-                var f, e;
-                if (n && n.preventDefault && n.handleObj) return f = n.handleObj, i(n.delegateTarget).off(f.namespace ? f.origType + "." + f.namespace : f.origType, f.selector, f.handler), this;
-                if ("object" == typeof n) {
-                    for (e in n) this.off(e, r, n[e]);
-                    return this
-                }
-                return (r === !1 || "function" == typeof r) && (u = r, r = t), u === !1 && (u = d), this.each(function() {
-                    i.event.remove(this, n, u, r)
-                })
-            },
-            bind: function(n, t, i) {
-                return this.on(n, null, t, i)
-            },
-            unbind: function(n, t) {
-                return this.off(n, null, t)
-            },
-            delegate: function(n, t, i, r) {
-                return this.on(t, n, i, r)
-            },
-            undelegate: function(n, t, i) {
-                return 1 === arguments.length ? this.off(n, "**") : this.off(t, n || "**", i)
-            },
-            trigger: function(n, t) {
-                return this.each(function() {
-                    i.event.trigger(n, t, this)
-                })
-            },
-            triggerHandler: function(n, r) {
-                var u = this[0];
-                return u ? i.event.trigger(n, r, u, !0) : t
-            }
-        }),
-        function(n, t) {
-            function ti(n) {
-                return tr.test(n + "")
-            }
-
-            function ii() {
-                var n, t = [];
-                return n = function(i, u) {
-                    return t.push(i += " ") > r.cacheLength && delete n[t.shift()], n[i] = u
-                }
-            }
-
-            function l(n) {
-                return n[f] = !0, n
-            }
-
-            function b(n) {
-                var t = s.createElement("div");
-                try {
-                    return n(t)
-                } catch (i) {
-                    return !1
-                } finally {
-                    t = null
-                }
-            }
-
-            function u(n, t, i, r) {
-                var y, u, e, l, p, v, w, h, d, b;
-                if ((t ? t.ownerDocument || t : k) !== s && it(t), t = t || s, i = i || [], !n || "string" != typeof n) return i;
-                if (1 !== (l = t.nodeType) && 9 !== l) return [];
-                if (!c && !r) {
-                    if (y = ir.exec(n))
-                        if (e = y[1]) {
-                            if (9 === l) {
-                                if (u = t.getElementById(e), !u || !u.parentNode) return i;
-                                if (u.id === e) return i.push(u), i
-                            } else if (t.ownerDocument && (u = t.ownerDocument.getElementById(e)) && et(t, u) && u.id === e) return i.push(u), i
-                        } else {
-                            if (y[2]) return ut.apply(i, ft.call(t.getElementsByTagName(n), 0)), i;
-                            if ((e = y[3]) && o.getByClassName && t.getElementsByClassName) return ut.apply(i, ft.call(t.getElementsByClassName(e), 0)), i
-                        }
-                    if (o.qsa && !a.test(n)) {
-                        if (w = !0, h = f, d = t, b = 9 === l && n, 1 === l && "object" !== t.nodeName.toLowerCase()) {
-                            for (v = yt(n), (w = t.getAttribute("id")) ? h = w.replace(fr, "\\$&") : t.setAttribute("id", h), h = "[id='" + h + "'] ", p = v.length; p--;) v[p] = h + pt(v[p]);
-                            d = ni.test(n) && t.parentNode || t;
-                            b = v.join(",")
-                        }
-                        if (b) try {
-                            return ut.apply(i, ft.call(d.querySelectorAll(b), 0)), i
-                        } catch (g) {} finally {
-                            w || t.removeAttribute("id")
-                        }
-                    }
-                }
-                return lr(n.replace(at, "$1"), t, i, r)
-            }
-
-            function yi(n, t) {
-                var i = t && n,
-                    r = i && (~t.sourceIndex || li) - (~n.sourceIndex || li);
-                if (r) return r;
-                if (i)
-                    while (i = i.nextSibling)
-                        if (i === t) return -1;
-                return n ? 1 : -1
-            }
-
-            function or(n) {
-                return function(t) {
-                    var i = t.nodeName.toLowerCase();
-                    return "input" === i && t.type === n
-                }
-            }
-
-            function sr(n) {
-                return function(t) {
-                    var i = t.nodeName.toLowerCase();
-                    return ("input" === i || "button" === i) && t.type === n
-                }
-            }
-
-            function g(n) {
-                return l(function(t) {
-                    return t = +t, l(function(i, r) {
-                        for (var u, f = n([], i.length, t), e = f.length; e--;) i[u = f[e]] && (i[u] = !(r[u] = i[u]))
-                    })
-                })
-            }
-
-            function yt(n, t) {
-                var e, f, s, o, i, h, c, l = hi[n + " "];
-                if (l) return t ? 0 : l.slice(0);
-                for (i = n, h = [], c = r.preFilter; i;) {
-                    (!e || (f = ki.exec(i))) && (f && (i = i.slice(f[0].length) || i), h.push(s = []));
-                    e = !1;
-                    (f = di.exec(i)) && (e = f.shift(), s.push({
-                        value: e,
-                        type: f[0].replace(at, " ")
-                    }), i = i.slice(e.length));
-                    for (o in r.filter)(f = vt[o].exec(i)) && (!c[o] || (f = c[o](f))) && (e = f.shift(), s.push({
-                        value: e,
-                        type: o,
-                        matches: f
-                    }), i = i.slice(e.length));
-                    if (!e) break
-                }
-                return t ? i.length : i ? u.error(n) : hi(n, h).slice(0)
-            }
-
-            function pt(n) {
-                for (var t = 0, r = n.length, i = ""; r > t; t++) i += n[t].value;
-                return i
-            }
-
-            function ri(n, t, i) {
-                var r = t.dir,
-                    u = i && "parentNode" === r,
-                    e = wi++;
-                return t.first ? function(t, i, f) {
-                    while (t = t[r])
-                        if (1 === t.nodeType || u) return n(t, i, f)
-                } : function(t, i, o) {
-                    var h, s, c, l = v + " " + e;
-                    if (o) {
-                        while (t = t[r])
-                            if ((1 === t.nodeType || u) && n(t, i, o)) return !0
-                    } else
-                        while (t = t[r])
-                            if (1 === t.nodeType || u)
-                                if (c = t[f] || (t[f] = {}), (s = c[r]) && s[0] === l) {
-                                    if ((h = s[1]) === !0 || h === ot) return h === !0
-                                } else if (s = c[r] = [l], s[1] = n(t, i, o) || ot, s[1] === !0) return !0
-                }
-            }
-
-            function ui(n) {
-                return n.length > 1 ? function(t, i, r) {
-                    for (var u = n.length; u--;)
-                        if (!n[u](t, i, r)) return !1;
-                    return !0
-                } : n[0]
-            }
-
-            function wt(n, t, i, r, u) {
-                for (var e, o = [], f = 0, s = n.length, h = null != t; s > f; f++)(e = n[f]) && (!i || i(e, r, u)) && (o.push(e), h && t.push(f));
-                return o
-            }
-
-            function fi(n, t, i, r, u, e) {
-                return r && !r[f] && (r = fi(r)), u && !u[f] && (u = fi(u, e)), l(function(f, e, o, s) {
-                    var l, c, a, p = [],
-                        y = [],
-                        w = e.length,
-                        b = f || cr(t || "*", o.nodeType ? [o] : o, []),
-                        v = !n || !f && t ? b : wt(b, p, n, o, s),
-                        h = i ? u || (f ? n : w || r) ? [] : e : v;
-                    if (i && i(v, h, o, s), r)
-                        for (l = wt(h, y), r(l, [], o, s), c = l.length; c--;)(a = l[c]) && (h[y[c]] = !(v[y[c]] = a));
-                    if (f) {
-                        if (u || n) {
-                            if (u) {
-                                for (l = [], c = h.length; c--;)(a = h[c]) && l.push(v[c] = a);
-                                u(null, h = [], l, s)
-                            }
-                            for (c = h.length; c--;)(a = h[c]) && (l = u ? dt.call(f, a) : p[c]) > -1 && (f[l] = !(e[l] = a))
-                        }
-                    } else h = wt(h === e ? h.splice(w, h.length) : h), u ? u(null, e, h, s) : ut.apply(e, h)
-                })
-            }
-
-            function ei(n) {
-                for (var s, u, i, o = n.length, h = r.relative[n[0].type], c = h || r.relative[" "], t = h ? 1 : 0, l = ri(function(n) {
-                        return n === s
-                    }, c, !0), a = ri(function(n) {
-                        return dt.call(s, n) > -1
-                    }, c, !0), e = [function(n, t, i) {
-                        return !h && (i || t !== ht) || ((s = t).nodeType ? l(n, t, i) : a(n, t, i))
-                    }]; o > t; t++)
-                    if (u = r.relative[n[t].type]) e = [ri(ui(e), u)];
-                    else {
-                        if (u = r.filter[n[t].type].apply(null, n[t].matches), u[f]) {
-                            for (i = ++t; o > i; i++)
-                                if (r.relative[n[i].type]) break;
-                            return fi(t > 1 && ui(e), t > 1 && pt(n.slice(0, t - 1)).replace(at, "$1"), u, i > t && ei(n.slice(t, i)), o > i && ei(n = n.slice(i)), o > i && pt(n))
-                        }
-                        e.push(u)
-                    }
-                return ui(e)
-            }
-
-            function hr(n, t) {
-                var f = 0,
-                    i = t.length > 0,
-                    e = n.length > 0,
-                    o = function(o, h, c, l, a) {
-                        var p, d, b, w = [],
-                            k = 0,
-                            y = "0",
-                            g = o && [],
-                            nt = null != a,
-                            tt = ht,
-                            rt = o || e && r.find.TAG("*", a && h.parentNode || h),
-                            it = v += null == tt ? 1 : Math.random() || .1;
-                        for (nt && (ht = h !== s && h, ot = f); null != (p = rt[y]); y++) {
-                            if (e && p) {
-                                for (d = 0; b = n[d++];)
-                                    if (b(p, h, c)) {
-                                        l.push(p);
-                                        break
-                                    }
-                                nt && (v = it, ot = ++f)
-                            }
-                            i && ((p = !b && p) && k--, o && g.push(p))
-                        }
-                        if (k += y, i && y !== k) {
-                            for (d = 0; b = t[d++];) b(g, w, h, c);
-                            if (o) {
-                                if (k > 0)
-                                    while (y--) g[y] || w[y] || (w[y] = bi.call(l));
-                                w = wt(w)
-                            }
-                            ut.apply(l, w);
-                            nt && !o && w.length > 0 && k + t.length > 1 && u.uniqueSort(l)
-                        }
-                        return nt && (v = it, ht = tt), g
-                    };
-                return i ? l(o) : o
-            }
-
-            function cr(n, t, i) {
-                for (var r = 0, f = t.length; f > r; r++) u(n, t[r], i);
-                return i
-            }
-
-            function lr(n, t, i, u) {
-                var o, f, e, h, l, s = yt(n);
-                if (!u && 1 === s.length) {
-                    if (f = s[0] = s[0].slice(0), f.length > 2 && "ID" === (e = f[0]).type && 9 === t.nodeType && !c && r.relative[f[1].type]) {
-                        if (t = r.find.ID(e.matches[0].replace(p, w), t)[0], !t) return i;
-                        n = n.slice(f.shift().value.length)
-                    }
-                    for (o = vt.needsContext.test(n) ? 0 : f.length; o--;) {
-                        if (e = f[o], r.relative[h = e.type]) break;
-                        if ((l = r.find[h]) && (u = l(e.matches[0].replace(p, w), ni.test(f[0].type) && t.parentNode || t))) {
-                            if (f.splice(o, 1), n = u.length && pt(f), !n) return ut.apply(i, ft.call(u, 0)), i;
-                            break
-                        }
-                    }
-                }
-                return bt(n, s)(u, t, c, i, ni.test(n)), i
-            }
-
-            function pi() {}
-            var nt, ot, r, st, oi, bt, tt, ht, it, s, h, c, a, rt, ct, et, kt, f = "sizzle" + -new Date,
-                k = n.document,
-                o = {},
-                v = 0,
-                wi = 0,
-                si = ii(),
-                hi = ii(),
-                ci = ii(),
-                y = typeof t,
-                li = -2147483648,
-                lt = [],
-                bi = lt.pop,
-                ut = lt.push,
-                ft = lt.slice,
-                dt = lt.indexOf || function(n) {
-                    for (var t = 0, i = this.length; i > t; t++)
-                        if (this[t] === n) return t;
-                    return -1
-                },
-                e = "[\\x20\\t\\r\\n\\f]",
-                d = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
-                ai = d.replace("w", "w#"),
-                vi = "\\[" + e + "*(" + d + ")" + e + "*(?:([*^$|!~]?=)" + e + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + ai + ")|)|)" + e + "*\\]",
-                gt = ":(" + d + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + vi.replace(3, 8) + ")*)|.*)\\)|)",
-                at = RegExp("^" + e + "+|((?:^|[^\\\\])(?:\\\\.)*)" + e + "+$", "g"),
-                ki = RegExp("^" + e + "*," + e + "*"),
-                di = RegExp("^" + e + "*([\\x20\\t\\r\\n\\f>+~])" + e + "*"),
-                gi = RegExp(gt),
-                nr = RegExp("^" + ai + "$"),
-                vt = {
-                    ID: RegExp("^#(" + d + ")"),
-                    CLASS: RegExp("^\\.(" + d + ")"),
-                    NAME: RegExp("^\\[name=['\"]?(" + d + ")['\"]?\\]"),
-                    TAG: RegExp("^(" + d.replace("w", "w*") + ")"),
-                    ATTR: RegExp("^" + vi),
-                    PSEUDO: RegExp("^" + gt),
-                    CHILD: RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + e + "*(even|odd|(([+-]|)(\\d*)n|)" + e + "*(?:([+-]|)" + e + "*(\\d+)|))" + e + "*\\)|)", "i"),
-                    needsContext: RegExp("^" + e + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + e + "*((?:-\\d)?\\d*)" + e + "*\\)|)(?=[^-]|$)", "i")
-                },
-                ni = /[\x20\t\r\n\f]*[+~]/,
-                tr = /^[^{]+\{\s*\[native code/,
-                ir = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
-                rr = /^(?:input|select|textarea|button)$/i,
-                ur = /^h\d$/i,
-                fr = /'|\\/g,
-                er = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
-                p = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
-                w = function(n, t) {
-                    var i = "0x" + t - 65536;
-                    return i !== i ? t : 0 > i ? String.fromCharCode(i + 65536) : String.fromCharCode(55296 | i >> 10, 56320 | 1023 & i)
-                };
-            try {
-                ft.call(k.documentElement.childNodes, 0)[0].nodeType
-            } catch (ar) {
-                ft = function(n) {
-                    for (var t, i = []; t = this[n++];) i.push(t);
-                    return i
-                }
-            }
-            oi = u.isXML = function(n) {
-                var t = n && (n.ownerDocument || n).documentElement;
-                return t ? "HTML" !== t.nodeName : !1
-            };
-            it = u.setDocument = function(n) {
-                var i = n ? n.ownerDocument || n : k;
-                return i !== s && 9 === i.nodeType && i.documentElement ? (s = i, h = i.documentElement, c = oi(i), o.tagNameNoComments = b(function(n) {
-                    return n.appendChild(i.createComment("")), !n.getElementsByTagName("*").length
-                }), o.attributes = b(function(n) {
-                    n.innerHTML = "<select><\/select>";
-                    var t = typeof n.lastChild.getAttribute("multiple");
-                    return "boolean" !== t && "string" !== t
-                }), o.getByClassName = b(function(n) {
-                    return n.innerHTML = "<div class='hidden e'><\/div><div class='hidden'><\/div>", n.getElementsByClassName && n.getElementsByClassName("e").length ? (n.lastChild.className = "e", 2 === n.getElementsByClassName("e").length) : !1
-                }), o.getByName = b(function(n) {
-                    n.id = f + 0;
-                    n.innerHTML = "<a name='" + f + "'><\/a><div name='" + f + "'><\/div>";
-                    h.insertBefore(n, h.firstChild);
-                    var t = i.getElementsByName && i.getElementsByName(f).length === 2 + i.getElementsByName(f + 0).length;
-                    return o.getIdNotName = !i.getElementById(f), h.removeChild(n), t
-                }), r.attrHandle = b(function(n) {
-                    return n.innerHTML = "<a href='#'><\/a>", n.firstChild && typeof n.firstChild.getAttribute !== y && "#" === n.firstChild.getAttribute("href")
-                }) ? {} : {
-                    href: function(n) {
-                        return n.getAttribute("href", 2)
-                    },
-                    type: function(n) {
-                        return n.getAttribute("type")
-                    }
-                }, o.getIdNotName ? (r.find.ID = function(n, t) {
-                    if (typeof t.getElementById !== y && !c) {
-                        var i = t.getElementById(n);
-                        return i && i.parentNode ? [i] : []
-                    }
-                }, r.filter.ID = function(n) {
-                    var t = n.replace(p, w);
-                    return function(n) {
-                        return n.getAttribute("id") === t
-                    }
-                }) : (r.find.ID = function(n, i) {
-                    if (typeof i.getElementById !== y && !c) {
-                        var r = i.getElementById(n);
-                        return r ? r.id === n || typeof r.getAttributeNode !== y && r.getAttributeNode("id").value === n ? [r] : t : []
-                    }
-                }, r.filter.ID = function(n) {
-                    var t = n.replace(p, w);
-                    return function(n) {
-                        var i = typeof n.getAttributeNode !== y && n.getAttributeNode("id");
-                        return i && i.value === t
-                    }
-                }), r.find.TAG = o.tagNameNoComments ? function(n, i) {
-                    return typeof i.getElementsByTagName !== y ? i.getElementsByTagName(n) : t
-                } : function(n, t) {
-                    var i, r = [],
-                        f = 0,
-                        u = t.getElementsByTagName(n);
-                    if ("*" === n) {
-                        while (i = u[f++]) 1 === i.nodeType && r.push(i);
-                        return r
-                    }
-                    return u
-                }, r.find.NAME = o.getByName && function(n, i) {
-                    return typeof i.getElementsByName !== y ? i.getElementsByName(name) : t
-                }, r.find.CLASS = o.getByClassName && function(n, i) {
-                    return typeof i.getElementsByClassName === y || c ? t : i.getElementsByClassName(n)
-                }, rt = [], a = [":focus"], (o.qsa = ti(i.querySelectorAll)) && (b(function(n) {
-                    n.innerHTML = "<select><option selected=''><\/option><\/select>";
-                    n.querySelectorAll("[selected]").length || a.push("\\[" + e + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)");
-                    n.querySelectorAll(":checked").length || a.push(":checked")
-                }), b(function(n) {
-                    n.innerHTML = "<input type='hidden' i=''/>";
-                    n.querySelectorAll("[i^='']").length && a.push("[*^$]=" + e + "*(?:\"\"|'')");
-                    n.querySelectorAll(":enabled").length || a.push(":enabled", ":disabled");
-                    n.querySelectorAll("*,:x");
-                    a.push(",.*:")
-                })), (o.matchesSelector = ti(ct = h.matchesSelector || h.mozMatchesSelector || h.webkitMatchesSelector || h.oMatchesSelector || h.msMatchesSelector)) && b(function(n) {
-                    o.disconnectedMatch = ct.call(n, "div");
-                    ct.call(n, "[s!='']:x");
-                    rt.push("!=", gt)
-                }), a = RegExp(a.join("|")), rt = RegExp(rt.join("|")), et = ti(h.contains) || h.compareDocumentPosition ? function(n, t) {
-                    var r = 9 === n.nodeType ? n.documentElement : n,
-                        i = t && t.parentNode;
-                    return n === i || !(!i || 1 !== i.nodeType || !(r.contains ? r.contains(i) : n.compareDocumentPosition && 16 & n.compareDocumentPosition(i)))
-                } : function(n, t) {
-                    if (t)
-                        while (t = t.parentNode)
-                            if (t === n) return !0;
-                    return !1
-                }, kt = h.compareDocumentPosition ? function(n, t) {
-                    var r;
-                    return n === t ? (tt = !0, 0) : (r = t.compareDocumentPosition && n.compareDocumentPosition && n.compareDocumentPosition(t)) ? 1 & r || n.parentNode && 11 === n.parentNode.nodeType ? n === i || et(k, n) ? -1 : t === i || et(k, t) ? 1 : 0 : 4 & r ? -1 : 1 : n.compareDocumentPosition ? -1 : 1
-                } : function(n, t) {
-                    var r, u = 0,
-                        o = n.parentNode,
-                        s = t.parentNode,
-                        f = [n],
-                        e = [t];
-                    if (n === t) return tt = !0, 0;
-                    if (!o || !s) return n === i ? -1 : t === i ? 1 : o ? -1 : s ? 1 : 0;
-                    if (o === s) return yi(n, t);
-                    for (r = n; r = r.parentNode;) f.unshift(r);
-                    for (r = t; r = r.parentNode;) e.unshift(r);
-                    while (f[u] === e[u]) u++;
-                    return u ? yi(f[u], e[u]) : f[u] === k ? -1 : e[u] === k ? 1 : 0
-                }, tt = !1, [0, 0].sort(kt), o.detectDuplicates = tt, s) : s
-            };
-            u.matches = function(n, t) {
-                return u(n, null, null, t)
-            };
-            u.matchesSelector = function(n, t) {
-                if ((n.ownerDocument || n) !== s && it(n), t = t.replace(er, "='$1']"), !(!o.matchesSelector || c || rt && rt.test(t) || a.test(t))) try {
-                    var i = ct.call(n, t);
-                    if (i || o.disconnectedMatch || n.document && 11 !== n.document.nodeType) return i
-                } catch (r) {}
-                return u(t, s, null, [n]).length > 0
-            };
-            u.contains = function(n, t) {
-                return (n.ownerDocument || n) !== s && it(n), et(n, t)
-            };
-            u.attr = function(n, t) {
-                var i;
-                return (n.ownerDocument || n) !== s && it(n), c || (t = t.toLowerCase()), (i = r.attrHandle[t]) ? i(n) : c || o.attributes ? n.getAttribute(t) : ((i = n.getAttributeNode(t)) || n.getAttribute(t)) && n[t] === !0 ? t : i && i.specified ? i.value : null
-            };
-            u.error = function(n) {
-                throw Error("Syntax error, unrecognized expression: " + n);
-            };
-            u.uniqueSort = function(n) {
-                var r, u = [],
-                    t = 1,
-                    i = 0;
-                if (tt = !o.detectDuplicates, n.sort(kt), tt) {
-                    for (; r = n[t]; t++) r === n[t - 1] && (i = u.push(t));
-                    while (i--) n.splice(u[i], 1)
-                }
-                return n
-            };
-            st = u.getText = function(n) {
-                var r, i = "",
-                    u = 0,
-                    t = n.nodeType;
-                if (t) {
-                    if (1 === t || 9 === t || 11 === t) {
-                        if ("string" == typeof n.textContent) return n.textContent;
-                        for (n = n.firstChild; n; n = n.nextSibling) i += st(n)
-                    } else if (3 === t || 4 === t) return n.nodeValue
-                } else
-                    for (; r = n[u]; u++) i += st(r);
-                return i
-            };
-            r = u.selectors = {
-                cacheLength: 50,
-                createPseudo: l,
-                match: vt,
-                find: {},
-                relative: {
-                    ">": {
-                        dir: "parentNode",
-                        first: !0
-                    },
-                    " ": {
-                        dir: "parentNode"
-                    },
-                    "+": {
-                        dir: "previousSibling",
-                        first: !0
-                    },
-                    "~": {
-                        dir: "previousSibling"
-                    }
-                },
-                preFilter: {
-                    ATTR: function(n) {
-                        return n[1] = n[1].replace(p, w), n[3] = (n[4] || n[5] || "").replace(p, w), "~=" === n[2] && (n[3] = " " + n[3] + " "), n.slice(0, 4)
-                    },
-                    CHILD: function(n) {
-                        return n[1] = n[1].toLowerCase(), "nth" === n[1].slice(0, 3) ? (n[3] || u.error(n[0]), n[4] = +(n[4] ? n[5] + (n[6] || 1) : 2 * ("even" === n[3] || "odd" === n[3])), n[5] = +(n[7] + n[8] || "odd" === n[3])) : n[3] && u.error(n[0]), n
-                    },
-                    PSEUDO: function(n) {
-                        var i, t = !n[5] && n[2];
-                        return vt.CHILD.test(n[0]) ? null : (n[4] ? n[2] = n[4] : t && gi.test(t) && (i = yt(t, !0)) && (i = t.indexOf(")", t.length - i) - t.length) && (n[0] = n[0].slice(0, i), n[2] = t.slice(0, i)), n.slice(0, 3))
-                    }
-                },
-                filter: {
-                    TAG: function(n) {
-                        return "*" === n ? function() {
-                            return !0
-                        } : (n = n.replace(p, w).toLowerCase(), function(t) {
-                            return t.nodeName && t.nodeName.toLowerCase() === n
-                        })
-                    },
-                    CLASS: function(n) {
-                        var t = si[n + " "];
-                        return t || (t = RegExp("(^|" + e + ")" + n + "(" + e + "|$)")) && si(n, function(n) {
-                            return t.test(n.className || typeof n.getAttribute !== y && n.getAttribute("class") || "")
-                        })
-                    },
-                    ATTR: function(n, t, i) {
-                        return function(r) {
-                            var f = u.attr(r, n);
-                            return null == f ? "!=" === t : t ? (f += "", "=" === t ? f === i : "!=" === t ? f !== i : "^=" === t ? i && 0 === f.indexOf(i) : "*=" === t ? i && f.indexOf(i) > -1 : "$=" === t ? i && f.slice(-i.length) === i : "~=" === t ? (" " + f + " ").indexOf(i) > -1 : "|=" === t ? f === i || f.slice(0, i.length + 1) === i + "-" : !1) : !0
-                        }
-                    },
-                    CHILD: function(n, t, i, r, u) {
-                        var s = "nth" !== n.slice(0, 3),
-                            o = "last" !== n.slice(-4),
-                            e = "of-type" === t;
-                        return 1 === r && 0 === u ? function(n) {
-                            return !!n.parentNode
-                        } : function(t, i, h) {
-                            var a, k, c, l, y, w, b = s !== o ? "nextSibling" : "previousSibling",
-                                p = t.parentNode,
-                                g = e && t.nodeName.toLowerCase(),
-                                d = !h && !e;
-                            if (p) {
-                                if (s) {
-                                    while (b) {
-                                        for (c = t; c = c[b];)
-                                            if (e ? c.nodeName.toLowerCase() === g : 1 === c.nodeType) return !1;
-                                        w = b = "only" === n && !w && "nextSibling"
-                                    }
-                                    return !0
-                                }
-                                if (w = [o ? p.firstChild : p.lastChild], o && d) {
-                                    for (k = p[f] || (p[f] = {}), a = k[n] || [], y = a[0] === v && a[1], l = a[0] === v && a[2], c = y && p.childNodes[y]; c = ++y && c && c[b] || (l = y = 0) || w.pop();)
-                                        if (1 === c.nodeType && ++l && c === t) {
-                                            k[n] = [v, y, l];
-                                            break
-                                        }
-                                } else if (d && (a = (t[f] || (t[f] = {}))[n]) && a[0] === v) l = a[1];
-                                else
-                                    while (c = ++y && c && c[b] || (l = y = 0) || w.pop())
-                                        if ((e ? c.nodeName.toLowerCase() === g : 1 === c.nodeType) && ++l && (d && ((c[f] || (c[f] = {}))[n] = [v, l]), c === t)) break;
-                                return l -= u, l === r || 0 == l % r && l / r >= 0
-                            }
-                        }
-                    },
-                    PSEUDO: function(n, t) {
-                        var e, i = r.pseudos[n] || r.setFilters[n.toLowerCase()] || u.error("unsupported pseudo: " + n);
-                        return i[f] ? i(t) : i.length > 1 ? (e = [n, n, "", t], r.setFilters.hasOwnProperty(n.toLowerCase()) ? l(function(n, r) {
-                            for (var u, f = i(n, t), e = f.length; e--;) u = dt.call(n, f[e]), n[u] = !(r[u] = f[e])
-                        }) : function(n) {
-                            return i(n, 0, e)
-                        }) : i
-                    }
-                },
-                pseudos: {
-                    not: l(function(n) {
-                        var i = [],
-                            r = [],
-                            t = bt(n.replace(at, "$1"));
-                        return t[f] ? l(function(n, i, r, u) {
-                            for (var e, o = t(n, null, u, []), f = n.length; f--;)(e = o[f]) && (n[f] = !(i[f] = e))
-                        }) : function(n, u, f) {
-                            return i[0] = n, t(i, null, f, r), !r.pop()
-                        }
-                    }),
-                    has: l(function(n) {
-                        return function(t) {
-                            return u(n, t).length > 0
-                        }
-                    }),
-                    contains: l(function(n) {
-                        return function(t) {
-                            return (t.textContent || t.innerText || st(t)).indexOf(n) > -1
-                        }
-                    }),
-                    lang: l(function(n) {
-                        return nr.test(n || "") || u.error("unsupported lang: " + n), n = n.replace(p, w).toLowerCase(),
-                            function(t) {
-                                var i;
-                                do
-                                    if (i = c ? t.getAttribute("xml:lang") || t.getAttribute("lang") : t.lang) return i = i.toLowerCase(), i === n || 0 === i.indexOf(n + "-"); while ((t = t.parentNode) && 1 === t.nodeType);
-                                return !1
-                            }
-                    }),
-                    target: function(t) {
-                        var i = n.location && n.location.hash;
-                        return i && i.slice(1) === t.id
-                    },
-                    root: function(n) {
-                        return n === h
-                    },
-                    focus: function(n) {
-                        return n === s.activeElement && (!s.hasFocus || s.hasFocus()) && !!(n.type || n.href || ~n.tabIndex)
-                    },
-                    enabled: function(n) {
-                        return n.disabled === !1
-                    },
-                    disabled: function(n) {
-                        return n.disabled === !0
-                    },
-                    checked: function(n) {
-                        var t = n.nodeName.toLowerCase();
-                        return "input" === t && !!n.checked || "option" === t && !!n.selected
-                    },
-                    selected: function(n) {
-                        return n.parentNode && n.parentNode.selectedIndex, n.selected === !0
-                    },
-                    empty: function(n) {
-                        for (n = n.firstChild; n; n = n.nextSibling)
-                            if (n.nodeName > "@" || 3 === n.nodeType || 4 === n.nodeType) return !1;
-                        return !0
-                    },
-                    parent: function(n) {
-                        return !r.pseudos.empty(n)
-                    },
-                    header: function(n) {
-                        return ur.test(n.nodeName)
-                    },
-                    input: function(n) {
-                        return rr.test(n.nodeName)
-                    },
-                    button: function(n) {
-                        var t = n.nodeName.toLowerCase();
-                        return "input" === t && "button" === n.type || "button" === t
-                    },
-                    text: function(n) {
-                        var t;
-                        return "input" === n.nodeName.toLowerCase() && "text" === n.type && (null == (t = n.getAttribute("type")) || t.toLowerCase() === n.type)
-                    },
-                    first: g(function() {
-                        return [0]
-                    }),
-                    last: g(function(n, t) {
-                        return [t - 1]
-                    }),
-                    eq: g(function(n, t, i) {
-                        return [0 > i ? i + t : i]
-                    }),
-                    even: g(function(n, t) {
-                        for (var i = 0; t > i; i += 2) n.push(i);
-                        return n
-                    }),
-                    odd: g(function(n, t) {
-                        for (var i = 1; t > i; i += 2) n.push(i);
-                        return n
-                    }),
-                    lt: g(function(n, t, i) {
-                        for (var r = 0 > i ? i + t : i; --r >= 0;) n.push(r);
-                        return n
-                    }),
-                    gt: g(function(n, t, i) {
-                        for (var r = 0 > i ? i + t : i; t > ++r;) n.push(r);
-                        return n
-                    })
-                }
-            };
-            for (nt in {
-                    radio: !0,
-                    checkbox: !0,
-                    file: !0,
-                    password: !0,
-                    image: !0
-                }) r.pseudos[nt] = or(nt);
-            for (nt in {
-                    submit: !0,
-                    reset: !0
-                }) r.pseudos[nt] = sr(nt);
-            bt = u.compile = function(n, t) {
-                var r, u = [],
-                    e = [],
-                    i = ci[n + " "];
-                if (!i) {
-                    for (t || (t = yt(n)), r = t.length; r--;) i = ei(t[r]), i[f] ? u.push(i) : e.push(i);
-                    i = ci(n, hr(e, u))
-                }
-                return i
-            };
-            r.pseudos.nth = r.pseudos.eq;
-            r.filters = pi.prototype = r.pseudos;
-            r.setFilters = new pi;
-            it();
-            u.attr = i.attr;
-            i.find = u;
-            i.expr = u.selectors;
-            i.expr[":"] = i.expr.pseudos;
-            i.unique = u.uniqueSort;
-            i.text = u.getText;
-            i.isXMLDoc = u.isXML;
-            i.contains = u.contains
-        }(n);
-    var re = /Until$/,
-        ue = /^(?:parents|prev(?:Until|All))/,
-        fe = /^.[^:#\[\.,]*$/,
-        hr = i.expr.match.needsContext,
-        ee = {
-            children: !0,
-            contents: !0,
-            next: !0,
-            prev: !0
-        };
-    i.fn.extend({
-        find: function(n) {
-            var t, r, f, u = this.length;
-            if ("string" != typeof n) return f = this, this.pushStack(i(n).filter(function() {
-                for (t = 0; u > t; t++)
-                    if (i.contains(f[t], this)) return !0
-            }));
-            for (r = [], t = 0; u > t; t++) i.find(n, this[t], r);
-            return r = this.pushStack(u > 1 ? i.unique(r) : r), r.selector = (this.selector ? this.selector + " " : "") + n, r
-        },
-        has: function(n) {
-            var t, r = i(n, this),
-                u = r.length;
-            return this.filter(function() {
-                for (t = 0; u > t; t++)
-                    if (i.contains(this, r[t])) return !0
-            })
-        },
-        not: function(n) {
-            return this.pushStack(lr(this, n, !1))
-        },
-        filter: function(n) {
-            return this.pushStack(lr(this, n, !0))
-        },
-        is: function(n) {
-            return !!n && ("string" == typeof n ? hr.test(n) ? i(n, this.context).index(this[0]) >= 0 : i.filter(n, this).length > 0 : this.filter(n).length > 0)
-        },
-        closest: function(n, t) {
-            for (var r, f = 0, o = this.length, u = [], e = hr.test(n) || "string" != typeof n ? i(n, t || this.context) : 0; o > f; f++)
-                for (r = this[f]; r && r.ownerDocument && r !== t && 11 !== r.nodeType;) {
-                    if (e ? e.index(r) > -1 : i.find.matchesSelector(r, n)) {
-                        u.push(r);
-                        break
-                    }
-                    r = r.parentNode
-                }
-            return this.pushStack(u.length > 1 ? i.unique(u) : u)
-        },
-        index: function(n) {
-            return n ? "string" == typeof n ? i.inArray(this[0], i(n)) : i.inArray(n.jquery ? n[0] : n, this) : this[0] && this[0].parentNode ? this.first().prevAll().length : -1
-        },
-        add: function(n, t) {
-            var r = "string" == typeof n ? i(n, t) : i.makeArray(n && n.nodeType ? [n] : n),
-                u = i.merge(this.get(), r);
-            return this.pushStack(i.unique(u))
-        },
-        addBack: function(n) {
-            return this.add(null == n ? this.prevObject : this.prevObject.filter(n))
-        }
-    });
-    i.fn.andSelf = i.fn.addBack;
-    i.each({
-        parent: function(n) {
-            var t = n.parentNode;
-            return t && 11 !== t.nodeType ? t : null
-        },
-        parents: function(n) {
-            return i.dir(n, "parentNode")
-        },
-        parentsUntil: function(n, t, r) {
-            return i.dir(n, "parentNode", r)
-        },
-        next: function(n) {
-            return cr(n, "nextSibling")
-        },
-        prev: function(n) {
-            return cr(n, "previousSibling")
-        },
-        nextAll: function(n) {
-            return i.dir(n, "nextSibling")
-        },
-        prevAll: function(n) {
-            return i.dir(n, "previousSibling")
-        },
-        nextUntil: function(n, t, r) {
-            return i.dir(n, "nextSibling", r)
-        },
-        prevUntil: function(n, t, r) {
-            return i.dir(n, "previousSibling", r)
-        },
-        siblings: function(n) {
-            return i.sibling((n.parentNode || {}).firstChild, n)
-        },
-        children: function(n) {
-            return i.sibling(n.firstChild)
-        },
-        contents: function(n) {
-            return i.nodeName(n, "iframe") ? n.contentDocument || n.contentWindow.document : i.merge([], n.childNodes)
-        }
-    }, function(n, t) {
-        i.fn[n] = function(r, u) {
-            var f = i.map(this, t, r);
-            return re.test(n) || (u = r), u && "string" == typeof u && (f = i.filter(u, f)), f = this.length > 1 && !ee[n] ? i.unique(f) : f, this.length > 1 && ue.test(n) && (f = f.reverse()), this.pushStack(f)
-        }
-    });
-    i.extend({
-        filter: function(n, t, r) {
-            return r && (n = ":not(" + n + ")"), 1 === t.length ? i.find.matchesSelector(t[0], n) ? [t[0]] : [] : i.find.matches(n, t)
-        },
-        dir: function(n, r, u) {
-            for (var e = [], f = n[r]; f && 9 !== f.nodeType && (u === t || 1 !== f.nodeType || !i(f).is(u));) 1 === f.nodeType && e.push(f), f = f[r];
-            return e
-        },
-        sibling: function(n, t) {
-            for (var i = []; n; n = n.nextSibling) 1 === n.nodeType && n !== t && i.push(n);
-            return i
-        }
-    });
-    var vr = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
-        oe = / jQuery\d+="(?:null|\d+)"/g,
-        yr = RegExp("<(?:" + vr + ")[\\s/>]", "i"),
-        fi = /^\s+/,
-        pr = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
-        wr = /<([\w:]+)/,
-        br = /<tbody/i,
-        se = /<|&#?\w+;/,
-        he = /<(?:script|style|link)/i,
-        ei = /^(?:checkbox|radio)$/i,
-        ce = /checked\s*(?:[^=]|=\s*.checked.)/i,
-        kr = /^$|\/(?:java|ecma)script/i,
-        le = /^true\/(.*)/,
-        ae = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
-        e = {
-            option: [1, "<select multiple='multiple'>", "<\/select>"],
-            legend: [1, "<fieldset>", "<\/fieldset>"],
-            area: [1, "<map>", "<\/map>"],
-            param: [1, "<object>", "<\/object>"],
-            thead: [1, "<table>", "<\/table>"],
-            tr: [2, "<table><tbody>", "<\/tbody><\/table>"],
-            col: [2, "<table><tbody><\/tbody><colgroup>", "<\/colgroup><\/table>"],
-            td: [3, "<table><tbody><tr>", "<\/tr><\/tbody><\/table>"],
-            _default: i.support.htmlSerialize ? [0, "", ""] : [1, "X<div>", "<\/div>"]
-        },
-        ve = ar(r),
-        oi = ve.appendChild(r.createElement("div"));
-    e.optgroup = e.option;
-    e.tbody = e.tfoot = e.colgroup = e.caption = e.thead;
-    e.th = e.td;
-    i.fn.extend({
-        text: function(n) {
-            return i.access(this, function(n) {
-                return n === t ? i.text(this) : this.empty().append((this[0] && this[0].ownerDocument || r).createTextNode(n))
-            }, null, n, arguments.length)
-        },
-        wrapAll: function(n) {
-            if (i.isFunction(n)) return this.each(function(t) {
-                i(this).wrapAll(n.call(this, t))
-            });
-            if (this[0]) {
-                var t = i(n, this[0].ownerDocument).eq(0).clone(!0);
-                this[0].parentNode && t.insertBefore(this[0]);
-                t.map(function() {
-                    for (var n = this; n.firstChild && 1 === n.firstChild.nodeType;) n = n.firstChild;
-                    return n
-                }).append(this)
-            }
-            return this
-        },
-        wrapInner: function(n) {
-            return i.isFunction(n) ? this.each(function(t) {
-                i(this).wrapInner(n.call(this, t))
-            }) : this.each(function() {
-                var t = i(this),
-                    r = t.contents();
-                r.length ? r.wrapAll(n) : t.append(n)
-            })
-        },
-        wrap: function(n) {
-            var t = i.isFunction(n);
-            return this.each(function(r) {
-                i(this).wrapAll(t ? n.call(this, r) : n)
-            })
-        },
-        unwrap: function() {
-            return this.parent().each(function() {
-                i.nodeName(this, "body") || i(this).replaceWith(this.childNodes)
-            }).end()
-        },
-        append: function() {
-            return this.domManip(arguments, !0, function(n) {
-                (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) && this.appendChild(n)
-            })
-        },
-        prepend: function() {
-            return this.domManip(arguments, !0, function(n) {
-                (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) && this.insertBefore(n, this.firstChild)
-            })
-        },
-        before: function() {
-            return this.domManip(arguments, !1, function(n) {
-                this.parentNode && this.parentNode.insertBefore(n, this)
-            })
-        },
-        after: function() {
-            return this.domManip(arguments, !1, function(n) {
-                this.parentNode && this.parentNode.insertBefore(n, this.nextSibling)
-            })
-        },
-        remove: function(n, t) {
-            for (var r, f = 0; null != (r = this[f]); f++)(!n || i.filter(n, [r]).length > 0) && (t || 1 !== r.nodeType || i.cleanData(u(r)), r.parentNode && (t && i.contains(r.ownerDocument, r) && si(u(r, "script")), r.parentNode.removeChild(r)));
-            return this
-        },
-        empty: function() {
-            for (var n, t = 0; null != (n = this[t]); t++) {
-                for (1 === n.nodeType && i.cleanData(u(n, !1)); n.firstChild;) n.removeChild(n.firstChild);
-                n.options && i.nodeName(n, "select") && (n.options.length = 0)
-            }
-            return this
-        },
-        clone: function(n, t) {
-            return n = null == n ? !1 : n, t = null == t ? n : t, this.map(function() {
-                return i.clone(this, n, t)
-            })
-        },
-        html: function(n) {
-            return i.access(this, function(n) {
-                var r = this[0] || {},
-                    f = 0,
-                    o = this.length;
-                if (n === t) return 1 === r.nodeType ? r.innerHTML.replace(oe, "") : t;
-                if (!("string" != typeof n || he.test(n) || !i.support.htmlSerialize && yr.test(n) || !i.support.leadingWhitespace && fi.test(n) || e[(wr.exec(n) || ["", ""])[1].toLowerCase()])) {
-                    n = n.replace(pr, "<$1><\/$2>");
-                    try {
-                        for (; o > f; f++) r = this[f] || {}, 1 === r.nodeType && (i.cleanData(u(r, !1)), r.innerHTML = n);
-                        r = 0
-                    } catch (s) {}
-                }
-                r && this.empty().append(n)
-            }, null, n, arguments.length)
-        },
-        replaceWith: function(n) {
-            var t = i.isFunction(n);
-            return t || "string" == typeof n || (n = i(n).not(this).detach()), this.domManip([n], !0, function(n) {
-                var r = this.nextSibling,
-                    t = this.parentNode;
-                t && (i(this).remove(), t.insertBefore(n, r))
-            })
-        },
-        detach: function(n) {
-            return this.remove(n, !0)
-        },
-        domManip: function(n, r, f) {
-            n = bi.apply([], n);
-            var c, e, l, s, y, h, o = 0,
-                a = this.length,
-                w = this,
-                b = a - 1,
-                v = n[0],
-                p = i.isFunction(v);
-            if (p || !(1 >= a || "string" != typeof v || i.support.checkClone) && ce.test(v)) return this.each(function(i) {
-                var u = w.eq(i);
-                p && (n[0] = v.call(this, i, r ? u.html() : t));
-                u.domManip(n, r, f)
-            });
-            if (a && (h = i.buildFragment(n, this[0].ownerDocument, !1, this), c = h.firstChild, 1 === h.childNodes.length && (h = c), c)) {
-                for (r = r && i.nodeName(c, "tr"), s = i.map(u(h, "script"), dr), l = s.length; a > o; o++) e = h, o !== b && (e = i.clone(e, !0, !0), l && i.merge(s, u(e, "script"))), f.call(r && i.nodeName(this[o], "table") ? ye(this[o], "tbody") : this[o], e, o);
-                if (l)
-                    for (y = s[s.length - 1].ownerDocument, i.map(s, gr), o = 0; l > o; o++) e = s[o], kr.test(e.type || "") && !i._data(e, "globalEval") && i.contains(y, e) && (e.src ? i.ajax({
-                        url: e.src,
-                        type: "GET",
-                        dataType: "script",
-                        async: !1,
-                        global: !1,
-                        throws: !0
-                    }) : i.globalEval((e.text || e.textContent || e.innerHTML || "").replace(ae, "")));
-                h = c = null
-            }
-            return this
-        }
-    });
-    i.each({
-        appendTo: "append",
-        prependTo: "prepend",
-        insertBefore: "before",
-        insertAfter: "after",
-        replaceAll: "replaceWith"
-    }, function(n, t) {
-        i.fn[n] = function(n) {
-            for (var u, r = 0, f = [], e = i(n), o = e.length - 1; o >= r; r++) u = r === o ? this : this.clone(!0), i(e[r])[t](u), bt.apply(f, u.get());
-            return this.pushStack(f)
-        }
-    });
-    i.extend({
-        clone: function(n, t, r) {
-            var f, h, o, e, s, c = i.contains(n.ownerDocument, n);
-            if (i.support.html5Clone || i.isXMLDoc(n) || !yr.test("<" + n.nodeName + ">") ? o = n.cloneNode(!0) : (oi.innerHTML = n.outerHTML, oi.removeChild(o = oi.firstChild)), !(i.support.noCloneEvent && i.support.noCloneChecked || 1 !== n.nodeType && 11 !== n.nodeType || i.isXMLDoc(n)))
-                for (f = u(o), s = u(n), e = 0; null != (h = s[e]); ++e) f[e] && pe(h, f[e]);
-            if (t)
-                if (r)
-                    for (s = s || u(n), f = f || u(o), e = 0; null != (h = s[e]); e++) nu(h, f[e]);
-                else nu(n, o);
-            return f = u(o, "script"), f.length > 0 && si(f, !c && u(n, "script")), f = s = h = null, o
-        },
-        buildFragment: function(n, t, r, f) {
-            for (var h, o, w, s, y, p, l, b = n.length, a = ar(t), c = [], v = 0; b > v; v++)
-                if (o = n[v], o || 0 === o)
-                    if ("object" === i.type(o)) i.merge(c, o.nodeType ? [o] : o);
-                    else if (se.test(o)) {
-                for (s = s || a.appendChild(t.createElement("div")), y = (wr.exec(o) || ["", ""])[1].toLowerCase(), l = e[y] || e._default, s.innerHTML = l[1] + o.replace(pr, "<$1><\/$2>") + l[2], h = l[0]; h--;) s = s.lastChild;
-                if (!i.support.leadingWhitespace && fi.test(o) && c.push(t.createTextNode(fi.exec(o)[0])), !i.support.tbody)
-                    for (o = "table" !== y || br.test(o) ? "<table>" !== l[1] || br.test(o) ? 0 : s : s.firstChild, h = o && o.childNodes.length; h--;) i.nodeName(p = o.childNodes[h], "tbody") && !p.childNodes.length && o.removeChild(p);
-                for (i.merge(c, s.childNodes), s.textContent = ""; s.firstChild;) s.removeChild(s.firstChild);
-                s = a.lastChild
-            } else c.push(t.createTextNode(o));
-            for (s && a.removeChild(s), i.support.appendChecked || i.grep(u(c, "input"), we), v = 0; o = c[v++];)
-                if ((!f || -1 === i.inArray(o, f)) && (w = i.contains(o.ownerDocument, o), s = u(a.appendChild(o), "script"), w && si(s), r))
-                    for (h = 0; o = s[h++];) kr.test(o.type || "") && r.push(o);
-            return s = null, a
-        },
-        cleanData: function(n, t) {
-            for (var r, f, u, e, c = 0, s = i.expando, h = i.cache, l = i.support.deleteExpando, a = i.event.special; null != (r = n[c]); c++)
-                if ((t || i.acceptData(r)) && (u = r[s], e = u && h[u])) {
-                    if (e.events)
-                        for (f in e.events) a[f] ? i.event.remove(r, f) : i.removeEvent(r, f, e.handle);
-                    h[u] && (delete h[u], l ? delete r[s] : typeof r.removeAttribute !== o ? r.removeAttribute(s) : r[s] = null, b.push(u))
-                }
-        }
-    });
-    var rt, v, y, hi = /alpha\([^)]*\)/i,
-        be = /opacity\s*=\s*([^)]*)/,
-        ke = /^(top|right|bottom|left)$/,
-        de = /^(none|table(?!-c[ea]).+)/,
-        tu = /^margin/,
-        ge = RegExp("^(" + st + ")(.*)$", "i"),
-        ct = RegExp("^(" + st + ")(?!px)[a-z%]+$", "i"),
-        no = RegExp("^([+-])=(" + st + ")", "i"),
-        iu = {
-            BODY: "block"
-        },
-        to = {
-            position: "absolute",
-            visibility: "hidden",
-            display: "block"
-        },
-        ru = {
-            letterSpacing: 0,
-            fontWeight: 400
-        },
-        p = ["Top", "Right", "Bottom", "Left"],
-        uu = ["Webkit", "O", "Moz", "ms"];
-    i.fn.extend({
-        css: function(n, r) {
-            return i.access(this, function(n, r, u) {
-                var e, o, s = {},
-                    f = 0;
-                if (i.isArray(r)) {
-                    for (o = v(n), e = r.length; e > f; f++) s[r[f]] = i.css(n, r[f], !1, o);
-                    return s
-                }
-                return u !== t ? i.style(n, r, u) : i.css(n, r)
-            }, n, r, arguments.length > 1)
-        },
-        show: function() {
-            return eu(this, !0)
-        },
-        hide: function() {
-            return eu(this)
-        },
-        toggle: function(n) {
-            var t = "boolean" == typeof n;
-            return this.each(function() {
-                (t ? n : ut(this)) ? i(this).show(): i(this).hide()
-            })
-        }
-    });
-    i.extend({
-        cssHooks: {
-            opacity: {
-                get: function(n, t) {
-                    if (t) {
-                        var i = y(n, "opacity");
-                        return "" === i ? "1" : i
-                    }
-                }
-            }
-        },
-        cssNumber: {
-            columnCount: !0,
-            fillOpacity: !0,
-            fontWeight: !0,
-            lineHeight: !0,
-            opacity: !0,
-            orphans: !0,
-            widows: !0,
-            zIndex: !0,
-            zoom: !0
-        },
-        cssProps: {
-            float: i.support.cssFloat ? "cssFloat" : "styleFloat"
-        },
-        style: function(n, r, u, f) {
-            if (n && 3 !== n.nodeType && 8 !== n.nodeType && n.style) {
-                var o, s, e, h = i.camelCase(r),
-                    c = n.style;
-                if (r = i.cssProps[h] || (i.cssProps[h] = fu(c, h)), e = i.cssHooks[r] || i.cssHooks[h], u === t) return e && "get" in e && (o = e.get(n, !1, f)) !== t ? o : c[r];
-                if (s = typeof u, "string" === s && (o = no.exec(u)) && (u = (o[1] + 1) * o[2] + parseFloat(i.css(n, r)), s = "number"), !(null == u || "number" === s && isNaN(u) || ("number" !== s || i.cssNumber[h] || (u += "px"), i.support.clearCloneStyle || "" !== u || 0 !== r.indexOf("background") || (c[r] = "inherit"), e && "set" in e && (u = e.set(n, u, f)) === t))) try {
-                    c[r] = u
-                } catch (l) {}
-            }
-        },
-        css: function(n, r, u, f) {
-            var h, e, o, s = i.camelCase(r);
-            return r = i.cssProps[s] || (i.cssProps[s] = fu(n.style, s)), o = i.cssHooks[r] || i.cssHooks[s], o && "get" in o && (e = o.get(n, !0, u)), e === t && (e = y(n, r, f)), "normal" === e && r in ru && (e = ru[r]), "" === u || u ? (h = parseFloat(e), u === !0 || i.isNumeric(h) ? h || 0 : e) : e
-        },
-        swap: function(n, t, i, r) {
-            var f, u, e = {};
-            for (u in t) e[u] = n.style[u], n.style[u] = t[u];
-            f = i.apply(n, r || []);
-            for (u in t) n.style[u] = e[u];
-            return f
-        }
-    });
-    n.getComputedStyle ? (v = function(t) {
-        return n.getComputedStyle(t, null)
-    }, y = function(n, r, u) {
-        var s, h, c, o = u || v(n),
-            e = o ? o.getPropertyValue(r) || o[r] : t,
-            f = n.style;
-        return o && ("" !== e || i.contains(n.ownerDocument, n) || (e = i.style(n, r)), ct.test(e) && tu.test(r) && (s = f.width, h = f.minWidth, c = f.maxWidth, f.minWidth = f.maxWidth = f.width = e, e = o.width, f.width = s, f.minWidth = h, f.maxWidth = c)), e
-    }) : r.documentElement.currentStyle && (v = function(n) {
-        return n.currentStyle
-    }, y = function(n, i, r) {
-        var s, e, o, h = r || v(n),
-            u = h ? h[i] : t,
-            f = n.style;
-        return null == u && f && f[i] && (u = f[i]), ct.test(u) && !ke.test(i) && (s = f.left, e = n.runtimeStyle, o = e && e.left, o && (e.left = n.currentStyle.left), f.left = "fontSize" === i ? "1em" : u, u = f.pixelLeft + "px", f.left = s, o && (e.left = o)), "" === u ? "auto" : u
-    });
-    i.each(["height", "width"], function(n, r) {
-        i.cssHooks[r] = {
-            get: function(n, u, f) {
-                return u ? 0 === n.offsetWidth && de.test(i.css(n, "display")) ? i.swap(n, to, function() {
-                    return hu(n, r, f)
-                }) : hu(n, r, f) : t
-            },
-            set: function(n, t, u) {
-                var f = u && v(n);
-                return ou(n, t, u ? su(n, r, u, i.support.boxSizing && "border-box" === i.css(n, "boxSizing", !1, f), f) : 0)
-            }
-        }
-    });
-    i.support.opacity || (i.cssHooks.opacity = {
-        get: function(n, t) {
-            return be.test((t && n.currentStyle ? n.currentStyle.filter : n.style.filter) || "") ? .01 * parseFloat(RegExp.$1) + "" : t ? "1" : ""
-        },
-        set: function(n, t) {
-            var r = n.style,
-                u = n.currentStyle,
-                e = i.isNumeric(t) ? "alpha(opacity=" + 100 * t + ")" : "",
-                f = u && u.filter || r.filter || "";
-            r.zoom = 1;
-            (t >= 1 || "" === t) && "" === i.trim(f.replace(hi, "")) && r.removeAttribute && (r.removeAttribute("filter"), "" === t || u && !u.filter) || (r.filter = hi.test(f) ? f.replace(hi, e) : f + " " + e)
-        }
-    });
-    i(function() {
-        i.support.reliableMarginRight || (i.cssHooks.marginRight = {
-            get: function(n, r) {
-                return r ? i.swap(n, {
-                    display: "inline-block"
-                }, y, [n, "marginRight"]) : t
-            }
-        });
-        !i.support.pixelPosition && i.fn.position && i.each(["top", "left"], function(n, r) {
-            i.cssHooks[r] = {
-                get: function(n, u) {
-                    return u ? (u = y(n, r), ct.test(u) ? i(n).position()[r] + "px" : u) : t
-                }
-            }
-        })
-    });
-    i.expr && i.expr.filters && (i.expr.filters.hidden = function(n) {
-        return 0 >= n.offsetWidth && 0 >= n.offsetHeight || !i.support.reliableHiddenOffsets && "none" === (n.style && n.style.display || i.css(n, "display"))
-    }, i.expr.filters.visible = function(n) {
-        return !i.expr.filters.hidden(n)
-    });
-    i.each({
-        margin: "",
-        padding: "",
-        border: "Width"
-    }, function(n, t) {
-        i.cssHooks[n + t] = {
-            expand: function(i) {
-                for (var r = 0, f = {}, u = "string" == typeof i ? i.split(" ") : [i]; 4 > r; r++) f[n + p[r] + t] = u[r] || u[r - 2] || u[0];
-                return f
-            }
-        };
-        tu.test(n) || (i.cssHooks[n + t].set = ou)
-    });
-    var io = /%20/g,
-        ro = /\[\]$/,
-        au = /\r?\n/g,
-        uo = /^(?:submit|button|image|reset|file)$/i,
-        fo = /^(?:input|select|textarea|keygen)/i;
-    i.fn.extend({
-        serialize: function() {
-            return i.param(this.serializeArray())
-        },
-        serializeArray: function() {
-            return this.map(function() {
-                var n = i.prop(this, "elements");
-                return n ? i.makeArray(n) : this
-            }).filter(function() {
-                var n = this.type;
-                return this.name && !i(this).is(":disabled") && fo.test(this.nodeName) && !uo.test(n) && (this.checked || !ei.test(n))
-            }).map(function(n, t) {
-                var r = i(this).val();
-                return null == r ? null : i.isArray(r) ? i.map(r, function(n) {
-                    return {
-                        name: t.name,
-                        value: n.replace(au, "\r\n")
-                    }
-                }) : {
-                    name: t.name,
-                    value: r.replace(au, "\r\n")
-                }
-            }).get()
-        }
-    });
-    i.param = function(n, r) {
-        var u, f = [],
-            e = function(n, t) {
-                t = i.isFunction(t) ? t() : null == t ? "" : t;
-                f[f.length] = encodeURIComponent(n) + "=" + encodeURIComponent(t)
-            };
-        if (r === t && (r = i.ajaxSettings && i.ajaxSettings.traditional), i.isArray(n) || n.jquery && !i.isPlainObject(n)) i.each(n, function() {
-            e(this.name, this.value)
-        });
-        else
-            for (u in n) ci(u, n[u], r, e);
-        return f.join("&").replace(io, "+")
-    };
-    i.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 contextmenu".split(" "), function(n, t) {
-        i.fn[t] = function(n, i) {
-            return arguments.length > 0 ? this.on(t, null, n, i) : this.trigger(t)
-        }
-    });
-    i.fn.hover = function(n, t) {
-        return this.mouseenter(n).mouseleave(t || n)
-    };
-    var w, c, li = i.now(),
-        ai = /\?/,
-        eo = /#.*$/,
-        vu = /([?&])_=[^&]*/,
-        oo = /^(.*?):[ \t]*([^\r\n]*)\r?$/gm,
-        so = /^(?:GET|HEAD)$/,
-        ho = /^\/\//,
-        yu = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
-        pu = i.fn.load,
-        wu = {},
-        vi = {},
-        bu = "*/".concat("*");
-    try {
-        c = ff.href
-    } catch (go) {
-        c = r.createElement("a");
-        c.href = "";
-        c = c.href
-    }
-    w = yu.exec(c.toLowerCase()) || [];
-    i.fn.load = function(n, r, u) {
-        if ("string" != typeof n && pu) return pu.apply(this, arguments);
-        var f, s, h, e = this,
-            o = n.indexOf(" ");
-        return o >= 0 && (f = n.slice(o, n.length), n = n.slice(0, o)), i.isFunction(r) ? (u = r, r = t) : r && "object" == typeof r && (h = "POST"), e.length > 0 && i.ajax({
-            url: n,
-            type: h,
-            dataType: "html",
-            data: r
-        }).done(function(n) {
-            s = arguments;
-            e.html(f ? i("<div>").append(i.parseHTML(n)).find(f) : n)
-        }).complete(u && function(n, t) {
-            e.each(u, s || [n.responseText, t, n])
-        }), this
-    };
-    i.each(["ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend"], function(n, t) {
-        i.fn[t] = function(n) {
-            return this.on(t, n)
-        }
-    });
-    i.each(["get", "post"], function(n, r) {
-        i[r] = function(n, u, f, e) {
-            return i.isFunction(u) && (e = e || f, f = u, u = t), i.ajax({
-                url: n,
-                type: r,
-                dataType: e,
-                data: u,
-                success: f
-            })
-        }
-    });
-    i.extend({
-        active: 0,
-        lastModified: {},
-        etag: {},
-        ajaxSettings: {
-            url: c,
-            type: "GET",
-            isLocal: /^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(w[1]),
-            global: !0,
-            processData: !0,
-            async: !0,
-            contentType: "application/x-www-form-urlencoded; charset=UTF-8",
-            accepts: {
-                "*": bu,
-                text: "text/plain",
-                html: "text/html",
-                xml: "application/xml, text/xml",
-                json: "application/json, text/javascript"
-            },
-            contents: {
-                xml: /xml/,
-                html: /html/,
-                json: /json/
-            },
-            responseFields: {
-                xml: "responseXML",
-                text: "responseText"
-            },
-            converters: {
-                "* text": n.String,
-                "text html": !0,
-                "text json": i.parseJSON,
-                "text xml": i.parseXML
-            },
-            flatOptions: {
-                url: !0,
-                context: !0
-            }
-        },
-        ajaxSetup: function(n, t) {
-            return t ? yi(yi(n, i.ajaxSettings), t) : yi(i.ajaxSettings, n)
-        },
-        ajaxPrefilter: ku(wu),
-        ajaxTransport: ku(vi),
-        ajax: function(n, r) {
-            function k(n, r, s, c) {
-                var l, k, w, rt, p, a = r;
-                2 !== o && (o = 2, g && clearTimeout(g), y = t, d = c || "", f.readyState = n > 0 ? 4 : 0, s && (rt = co(u, f, s)), n >= 200 && 300 > n || 304 === n ? (u.ifModified && (p = f.getResponseHeader("Last-Modified"), p && (i.lastModified[e] = p), p = f.getResponseHeader("etag"), p && (i.etag[e] = p)), 204 === n ? (l = !0, a = "nocontent") : 304 === n ? (l = !0, a = "notmodified") : (l = lo(u, rt), a = l.state, k = l.data, w = l.error, l = !w)) : (w = a, (n || !a) && (a = "error", 0 > n && (n = 0))), f.status = n, f.statusText = (r || a) + "", l ? tt.resolveWith(h, [k, a, f]) : tt.rejectWith(h, [f, a, w]), f.statusCode(b), b = t, v && nt.trigger(l ? "ajaxSuccess" : "ajaxError", [f, u, l ? k : w]), it.fireWith(h, [f, a]), v && (nt.trigger("ajaxComplete", [f, u]), --i.active || i.event.trigger("ajaxStop")))
-            }
-            "object" == typeof n && (r = n, n = t);
-            r = r || {};
-            var l, a, e, d, g, v, y, p, u = i.ajaxSetup({}, r),
-                h = u.context || u,
-                nt = u.context && (h.nodeType || h.jquery) ? i(h) : i.event,
-                tt = i.Deferred(),
-                it = i.Callbacks("once memory"),
-                b = u.statusCode || {},
-                rt = {},
-                ut = {},
-                o = 0,
-                ft = "canceled",
-                f = {
-                    readyState: 0,
-                    getResponseHeader: function(n) {
-                        var t;
-                        if (2 === o) {
-                            if (!p)
-                                for (p = {}; t = oo.exec(d);) p[t[1].toLowerCase()] = t[2];
-                            t = p[n.toLowerCase()]
-                        }
-                        return null == t ? null : t
-                    },
-                    getAllResponseHeaders: function() {
-                        return 2 === o ? d : null
-                    },
-                    setRequestHeader: function(n, t) {
-                        var i = n.toLowerCase();
-                        return o || (n = ut[i] = ut[i] || n, rt[n] = t), this
-                    },
-                    overrideMimeType: function(n) {
-                        return o || (u.mimeType = n), this
-                    },
-                    statusCode: function(n) {
-                        var t;
-                        if (n)
-                            if (2 > o)
-                                for (t in n) b[t] = [b[t], n[t]];
-                            else f.always(n[f.status]);
-                        return this
-                    },
-                    abort: function(n) {
-                        var t = n || ft;
-                        return y && y.abort(t), k(0, t), this
-                    }
-                };
-            if (tt.promise(f).complete = it.add, f.success = f.done, f.error = f.fail, u.url = ((n || u.url || c) + "").replace(eo, "").replace(ho, w[1] + "//"), u.type = r.method || r.type || u.method || u.type, u.dataTypes = i.trim(u.dataType || "*").toLowerCase().match(s) || [""], null == u.crossDomain && (l = yu.exec(u.url.toLowerCase()), u.crossDomain = !(!l || l[1] === w[1] && l[2] === w[2] && (l[3] || ("http:" === l[1] ? 80 : 443)) == (w[3] || ("http:" === w[1] ? 80 : 443)))), u.data && u.processData && "string" != typeof u.data && (u.data = i.param(u.data, u.traditional)), du(wu, u, r, f), 2 === o) return f;
-            v = u.global;
-            v && 0 == i.active++ && i.event.trigger("ajaxStart");
-            u.type = u.type.toUpperCase();
-            u.hasContent = !so.test(u.type);
-            e = u.url;
-            u.hasContent || (u.data && (e = u.url += (ai.test(e) ? "&" : "?") + u.data, delete u.data), u.cache === !1 && (u.url = vu.test(e) ? e.replace(vu, "$1_=" + li++) : e + (ai.test(e) ? "&" : "?") + "_=" + li++));
-            u.ifModified && (i.lastModified[e] && f.setRequestHeader("If-Modified-Since", i.lastModified[e]), i.etag[e] && f.setRequestHeader("If-None-Match", i.etag[e]));
-            (u.data && u.hasContent && u.contentType !== !1 || r.contentType) && f.setRequestHeader("Content-Type", u.contentType);
-            f.setRequestHeader("Accept", u.dataTypes[0] && u.accepts[u.dataTypes[0]] ? u.accepts[u.dataTypes[0]] + ("*" !== u.dataTypes[0] ? ", " + bu + "; q=0.01" : "") : u.accepts["*"]);
-            for (a in u.headers) f.setRequestHeader(a, u.headers[a]);
-            if (u.beforeSend && (u.beforeSend.call(h, f, u) === !1 || 2 === o)) return f.abort();
-            ft = "abort";
-            for (a in {
-                    success: 1,
-                    error: 1,
-                    complete: 1
-                }) f[a](u[a]);
-            if (y = du(vi, u, r, f)) {
-                f.readyState = 1;
-                v && nt.trigger("ajaxSend", [f, u]);
-                u.async && u.timeout > 0 && (g = setTimeout(function() {
-                    f.abort("timeout")
-                }, u.timeout));
-                try {
-                    o = 1;
-                    y.send(rt, k)
-                } catch (et) {
-                    if (!(2 > o)) throw et;
-                    k(-1, et)
-                }
-            } else k(-1, "No Transport");
-            return f
-        },
-        getScript: function(n, r) {
-            return i.get(n, t, r, "script")
-        },
-        getJSON: function(n, t, r) {
-            return i.get(n, t, r, "json")
-        }
-    });
-    i.ajaxSetup({
-        accepts: {
-            script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
-        },
-        contents: {
-            script: /(?:java|ecma)script/
-        },
-        converters: {
-            "text script": function(n) {
-                return i.globalEval(n), n
-            }
-        }
-    });
-    i.ajaxPrefilter("script", function(n) {
-        n.cache === t && (n.cache = !1);
-        n.crossDomain && (n.type = "GET", n.global = !1)
-    });
-    i.ajaxTransport("script", function(n) {
-        if (n.crossDomain) {
-            var u, f = r.head || i("head")[0] || r.documentElement;
-            return {
-                send: function(t, i) {
-                    u = r.createElement("script");
-                    u.async = !0;
-                    n.scriptCharset && (u.charset = n.scriptCharset);
-                    u.src = n.url;
-                    u.onload = u.onreadystatechange = function(n, t) {
-                        (t || !u.readyState || /loaded|complete/.test(u.readyState)) && (u.onload = u.onreadystatechange = null, u.parentNode && u.parentNode.removeChild(u), u = null, t || i(200, "success"))
-                    };
-                    f.insertBefore(u, f.firstChild)
-                },
-                abort: function() {
-                    u && u.onload(t, !0)
-                }
-            }
-        }
-    });
-    pi = [];
-    lt = /(=)\?(?=&|$)|\?\?/;
-    i.ajaxSetup({
-        jsonp: "callback",
-        jsonpCallback: function() {
-            var n = pi.pop() || i.expando + "_" + li++;
-            return this[n] = !0, n
-        }
-    });
-    i.ajaxPrefilter("json jsonp", function(r, u, f) {
-        var e, s, o, h = r.jsonp !== !1 && (lt.test(r.url) ? "url" : "string" == typeof r.data && !(r.contentType || "").indexOf("application/x-www-form-urlencoded") && lt.test(r.data) && "data");
-        return h || "jsonp" === r.dataTypes[0] ? (e = r.jsonpCallback = i.isFunction(r.jsonpCallback) ? r.jsonpCallback() : r.jsonpCallback, h ? r[h] = r[h].replace(lt, "$1" + e) : r.jsonp !== !1 && (r.url += (ai.test(r.url) ? "&" : "?") + r.jsonp + "=" + e), r.converters["script json"] = function() {
-            return o || i.error(e + " was not called"), o[0]
-        }, r.dataTypes[0] = "json", s = n[e], n[e] = function() {
-            o = arguments
-        }, f.always(function() {
-            n[e] = s;
-            r[e] && (r.jsonpCallback = u.jsonpCallback, pi.push(e));
-            o && i.isFunction(s) && s(o[0]);
-            o = s = t
-        }), "script") : t
-    });
-    gu = 0;
-    at = n.ActiveXObject && function() {
-        for (var n in g) g[n](t, !0)
-    };
-    i.ajaxSettings.xhr = n.ActiveXObject ? function() {
-        return !this.isLocal && nf() || ao()
-    } : nf;
-    nt = i.ajaxSettings.xhr();
-    i.support.cors = !!nt && "withCredentials" in nt;
-    nt = i.support.ajax = !!nt;
-    nt && i.ajaxTransport(function(r) {
-        if (!r.crossDomain || i.support.cors) {
-            var u;
-            return {
-                send: function(f, e) {
-                    var h, s, o = r.xhr();
-                    if (r.username ? o.open(r.type, r.url, r.async, r.username, r.password) : o.open(r.type, r.url, r.async), r.xhrFields)
-                        for (s in r.xhrFields) o[s] = r.xhrFields[s];
-                    r.mimeType && o.overrideMimeType && o.overrideMimeType(r.mimeType);
-                    r.crossDomain || f["X-Requested-With"] || (f["X-Requested-With"] = "XMLHttpRequest");
-                    try {
-                        for (s in f) o.setRequestHeader(s, f[s])
-                    } catch (c) {}
-                    o.send(r.hasContent && r.data || null);
-                    u = function(n, f) {
-                        var s, a, l, c;
-                        try {
-                            if (u && (f || 4 === o.readyState))
-                                if (u = t, h && (o.onreadystatechange = i.noop, at && delete g[h]), f) 4 !== o.readyState && o.abort();
-                                else {
-                                    c = {};
-                                    s = o.status;
-                                    a = o.getAllResponseHeaders();
-                                    "string" == typeof o.responseText && (c.text = o.responseText);
-                                    try {
-                                        l = o.statusText
-                                    } catch (y) {
-                                        l = ""
-                                    }
-                                    s || !r.isLocal || r.crossDomain ? 1223 === s && (s = 204) : s = c.text ? 200 : 404
-                                }
-                        } catch (v) {
-                            f || e(-1, v)
-                        }
-                        c && e(s, l, c, a)
-                    };
-                    r.async ? 4 === o.readyState ? setTimeout(u) : (h = ++gu, at && (g || (g = {}, i(n).unload(at)), g[h] = u), o.onreadystatechange = u) : u()
-                },
-                abort: function() {
-                    u && u(t, !0)
-                }
-            }
-        }
-    });
-    var tt, vt, vo = /^(?:toggle|show|hide)$/,
-        yo = RegExp("^(?:([+-])=|)(" + st + ")([a-z%]*)$", "i"),
-        po = /queueHooks$/,
-        yt = [ko],
-        ft = {
-            "*": [function(n, t) {
-                var o, s, r = this.createTween(n, t),
-                    e = yo.exec(t),
-                    h = r.cur(),
-                    u = +h || 0,
-                    f = 1,
-                    c = 20;
-                if (e) {
-                    if (o = +e[2], s = e[3] || (i.cssNumber[n] ? "" : "px"), "px" !== s && u) {
-                        u = i.css(r.elem, n, !0) || o || 1;
-                        do f = f || ".5", u /= f, i.style(r.elem, n, u + s); while (f !== (f = r.cur() / h) && 1 !== f && --c)
-                    }
-                    r.unit = s;
-                    r.start = u;
-                    r.end = e[1] ? u + (e[1] + 1) * o : o
-                }
-                return r
-            }]
-        };
-    i.Animation = i.extend(rf, {
-        tweener: function(n, t) {
-            i.isFunction(n) ? (t = n, n = ["*"]) : n = n.split(" ");
-            for (var r, u = 0, f = n.length; f > u; u++) r = n[u], ft[r] = ft[r] || [], ft[r].unshift(t)
-        },
-        prefilter: function(n, t) {
-            t ? yt.unshift(n) : yt.push(n)
-        }
-    });
-    i.Tween = f;
-    f.prototype = {
-        constructor: f,
-        init: function(n, t, r, u, f, e) {
-            this.elem = n;
-            this.prop = r;
-            this.easing = f || "swing";
-            this.options = t;
-            this.start = this.now = this.cur();
-            this.end = u;
-            this.unit = e || (i.cssNumber[r] ? "" : "px")
-        },
-        cur: function() {
-            var n = f.propHooks[this.prop];
-            return n && n.get ? n.get(this) : f.propHooks._default.get(this)
-        },
-        run: function(n) {
-            var r, t = f.propHooks[this.prop];
-            return this.pos = r = this.options.duration ? i.easing[this.easing](n, this.options.duration * n, 0, 1, this.options.duration) : n, this.now = (this.end - this.start) * r + this.start, this.options.step && this.options.step.call(this.elem, this.now, this), t && t.set ? t.set(this) : f.propHooks._default.set(this), this
-        }
-    };
-    f.prototype.init.prototype = f.prototype;
-    f.propHooks = {
-        _default: {
-            get: function(n) {
-                var t;
-                return null == n.elem[n.prop] || n.elem.style && null != n.elem.style[n.prop] ? (t = i.css(n.elem, n.prop, ""), t && "auto" !== t ? t : 0) : n.elem[n.prop]
-            },
-            set: function(n) {
-                i.fx.step[n.prop] ? i.fx.step[n.prop](n) : n.elem.style && (null != n.elem.style[i.cssProps[n.prop]] || i.cssHooks[n.prop]) ? i.style(n.elem, n.prop, n.now + n.unit) : n.elem[n.prop] = n.now
-            }
-        }
-    };
-    f.propHooks.scrollTop = f.propHooks.scrollLeft = {
-        set: function(n) {
-            n.elem.nodeType && n.elem.parentNode && (n.elem[n.prop] = n.now)
-        }
-    };
-    i.each(["toggle", "show", "hide"], function(n, t) {
-        var r = i.fn[t];
-        i.fn[t] = function(n, i, u) {
-            return null == n || "boolean" == typeof n ? r.apply(this, arguments) : this.animate(pt(t, !0), n, i, u)
-        }
-    });
-    i.fn.extend({
-        fadeTo: function(n, t, i, r) {
-            return this.filter(ut).css("opacity", 0).show().end().animate({
-                opacity: t
-            }, n, i, r)
-        },
-        animate: function(n, t, r, u) {
-            var o = i.isEmptyObject(n),
-                e = i.speed(t, r, u),
-                f = function() {
-                    var t = rf(this, i.extend({}, n), e);
-                    f.finish = function() {
-                        t.stop(!0)
-                    };
-                    (o || i._data(this, "finish")) && t.stop(!0)
-                };
-            return f.finish = f, o || e.queue === !1 ? this.each(f) : this.queue(e.queue, f)
-        },
-        stop: function(n, r, u) {
-            var f = function(n) {
-                var t = n.stop;
-                delete n.stop;
-                t(u)
-            };
-            return "string" != typeof n && (u = r, r = n, n = t), r && n !== !1 && this.queue(n || "fx", []), this.each(function() {
-                var o = !0,
-                    t = null != n && n + "queueHooks",
-                    e = i.timers,
-                    r = i._data(this);
-                if (t) r[t] && r[t].stop && f(r[t]);
-                else
-                    for (t in r) r[t] && r[t].stop && po.test(t) && f(r[t]);
-                for (t = e.length; t--;) e[t].elem !== this || null != n && e[t].queue !== n || (e[t].anim.stop(u), o = !1, e.splice(t, 1));
-                (o || !u) && i.dequeue(this, n)
-            })
-        },
-        finish: function(n) {
-            return n !== !1 && (n = n || "fx"), this.each(function() {
-                var t, f = i._data(this),
-                    r = f[n + "queue"],
-                    e = f[n + "queueHooks"],
-                    u = i.timers,
-                    o = r ? r.length : 0;
-                for (f.finish = !0, i.queue(this, n, []), e && e.cur && e.cur.finish && e.cur.finish.call(this), t = u.length; t--;) u[t].elem === this && u[t].queue === n && (u[t].anim.stop(!0), u.splice(t, 1));
-                for (t = 0; o > t; t++) r[t] && r[t].finish && r[t].finish.call(this);
-                delete f.finish
-            })
-        }
-    });
-    i.each({
-        slideDown: pt("show"),
-        slideUp: pt("hide"),
-        slideToggle: pt("toggle"),
-        fadeIn: {
-            opacity: "show"
-        },
-        fadeOut: {
-            opacity: "hide"
-        },
-        fadeToggle: {
-            opacity: "toggle"
-        }
-    }, function(n, t) {
-        i.fn[n] = function(n, i, r) {
-            return this.animate(t, n, i, r)
-        }
-    });
-    i.speed = function(n, t, r) {
-        var u = n && "object" == typeof n ? i.extend({}, n) : {
-            complete: r || !r && t || i.isFunction(n) && n,
-            duration: n,
-            easing: r && t || t && !i.isFunction(t) && t
-        };
-        return u.duration = i.fx.off ? 0 : "number" == typeof u.duration ? u.duration : u.duration in i.fx.speeds ? i.fx.speeds[u.duration] : i.fx.speeds._default, (null == u.queue || u.queue === !0) && (u.queue = "fx"), u.old = u.complete, u.complete = function() {
-            i.isFunction(u.old) && u.old.call(this);
-            u.queue && i.dequeue(this, u.queue)
-        }, u
-    };
-    i.easing = {
-        linear: function(n) {
-            return n
-        },
-        swing: function(n) {
-            return .5 - Math.cos(n * Math.PI) / 2
-        }
-    };
-    i.timers = [];
-    i.fx = f.prototype.init;
-    i.fx.tick = function() {
-        var u, n = i.timers,
-            r = 0;
-        for (tt = i.now(); n.length > r; r++) u = n[r], u() || n[r] !== u || n.splice(r--, 1);
-        n.length || i.fx.stop();
-        tt = t
-    };
-    i.fx.timer = function(n) {
-        n() && i.timers.push(n) && i.fx.start()
-    };
-    i.fx.interval = 13;
-    i.fx.start = function() {
-        vt || (vt = setInterval(i.fx.tick, i.fx.interval))
-    };
-    i.fx.stop = function() {
-        clearInterval(vt);
-        vt = null
-    };
-    i.fx.speeds = {
-        slow: 600,
-        fast: 200,
-        _default: 400
-    };
-    i.fx.step = {};
-    i.expr && i.expr.filters && (i.expr.filters.animated = function(n) {
-        return i.grep(i.timers, function(t) {
-            return n === t.elem
-        }).length
-    });
-    i.fn.offset = function(n) {
-        if (arguments.length) return n === t ? this : this.each(function(t) {
-            i.offset.setOffset(this, n, t)
-        });
-        var r, e, f = {
-                top: 0,
-                left: 0
-            },
-            u = this[0],
-            s = u && u.ownerDocument;
-        if (s) return r = s.documentElement, i.contains(r, u) ? (typeof u.getBoundingClientRect !== o && (f = u.getBoundingClientRect()), e = uf(s), {
-            top: f.top + (e.pageYOffset || r.scrollTop) - (r.clientTop || 0),
-            left: f.left + (e.pageXOffset || r.scrollLeft) - (r.clientLeft || 0)
-        }) : f
-    };
-    i.offset = {
-        setOffset: function(n, t, r) {
-            var f = i.css(n, "position");
-            "static" === f && (n.style.position = "relative");
-            var e = i(n),
-                o = e.offset(),
-                l = i.css(n, "top"),
-                a = i.css(n, "left"),
-                v = ("absolute" === f || "fixed" === f) && i.inArray("auto", [l, a]) > -1,
-                u = {},
-                s = {},
-                h, c;
-            v ? (s = e.position(), h = s.top, c = s.left) : (h = parseFloat(l) || 0, c = parseFloat(a) || 0);
-            i.isFunction(t) && (t = t.call(n, r, o));
-            null != t.top && (u.top = t.top - o.top + h);
-            null != t.left && (u.left = t.left - o.left + c);
-            "using" in t ? t.using.call(n, u) : e.css(u)
-        }
-    };
-    i.fn.extend({
-        position: function() {
-            if (this[0]) {
-                var n, r, t = {
-                        top: 0,
-                        left: 0
-                    },
-                    u = this[0];
-                return "fixed" === i.css(u, "position") ? r = u.getBoundingClientRect() : (n = this.offsetParent(), r = this.offset(), i.nodeName(n[0], "html") || (t = n.offset()), t.top += i.css(n[0], "borderTopWidth", !0), t.left += i.css(n[0], "borderLeftWidth", !0)), {
-                    top: r.top - t.top - i.css(u, "marginTop", !0),
-                    left: r.left - t.left - i.css(u, "marginLeft", !0)
-                }
-            }
-        },
-        offsetParent: function() {
-            return this.map(function() {
-                for (var n = this.offsetParent || r.documentElement; n && !i.nodeName(n, "html") && "static" === i.css(n, "position");) n = n.offsetParent;
-                return n || r.documentElement
-            })
-        }
-    });
-    i.each({
-        scrollLeft: "pageXOffset",
-        scrollTop: "pageYOffset"
-    }, function(n, r) {
-        var u = /Y/.test(r);
-        i.fn[n] = function(f) {
-            return i.access(this, function(n, f, e) {
-                var o = uf(n);
-                return e === t ? o ? r in o ? o[r] : o.document.documentElement[f] : n[f] : (o ? o.scrollTo(u ? i(o).scrollLeft() : e, u ? e : i(o).scrollTop()) : n[f] = e, t)
-            }, n, f, arguments.length, null)
-        }
-    });
-    i.each({
-        Height: "height",
-        Width: "width"
-    }, function(n, r) {
-        i.each({
-            padding: "inner" + n,
-            content: r,
-            "": "outer" + n
-        }, function(u, f) {
-            i.fn[f] = function(f, e) {
-                var o = arguments.length && (u || "boolean" != typeof f),
-                    s = u || (f === !0 || e === !0 ? "margin" : "border");
-                return i.access(this, function(r, u, f) {
-                    var e;
-                    return i.isWindow(r) ? r.document.documentElement["client" + n] : 9 === r.nodeType ? (e = r.documentElement, Math.max(r.body["scroll" + n], e["scroll" + n], r.body["offset" + n], e["offset" + n], e["client" + n])) : f === t ? i.css(r, u, s) : i.style(r, u, f, s)
-                }, r, o ? f : t, o, null)
-            }
-        })
-    });
-    n.jQuery = n.$ = i;
-    "function" == typeof define && define.amd && define.amd.jQuery && define("jquery", [], function() {
-        return i
-    })
-})(window),
-function(n) {
-    function i(n, t) {
-        for (var i = window, r = (n || "").split("."); i && r.length;) i = i[r.shift()];
-        return typeof i == "function" ? i : (t.push(n), Function.constructor.apply(null, t))
-    }
-
-    function r(n) {
-        return n === "GET" || n === "POST"
-    }
-
-    function e(n, t) {
-        r(t) || n.setRequestHeader("X-HTTP-Method-Override", t)
-    }
-
-    function o(t, i, r) {
-        var u;
-        r.indexOf("application/x-javascript") === -1 && (u = (t.getAttribute("data-ajax-mode") || "").toUpperCase(), n(t.getAttribute("data-ajax-update")).each(function(t, r) {
-            var f;
-            switch (u) {
-                case "BEFORE":
-                    f = r.firstChild;
-                    n("<div />").html(i).contents().each(function() {
-                        r.insertBefore(this, f)
-                    });
-                    break;
-                case "AFTER":
-                    n("<div />").html(i).contents().each(function() {
-                        r.appendChild(this)
-                    });
-                    break;
-                default:
-                    n(r).html(i)
-            }
-        }))
-    }
-
-    function u(t, u) {
-        var s, h, f, c;
-        (s = t.getAttribute("data-ajax-confirm"), !s || window.confirm(s)) && (h = n(t.getAttribute("data-ajax-loading")), c = t.getAttribute("data-ajax-loading-duration") || 0, n.extend(u, {
-            type: t.getAttribute("data-ajax-method") || undefined,
-            url: t.getAttribute("data-ajax-url") || undefined,
-            beforeSend: function(n) {
-                var r;
-                return e(n, f), r = i(t.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments), r !== !1 && h.show(c), r
-            },
-            complete: function() {
-                h.hide(c);
-                i(t.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments)
-            },
-            success: function(n, r, u) {
-                o(t, n, u.getResponseHeader("Content-Type") || "text/html");
-                i(t.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments)
-            },
-            error: i(t.getAttribute("data-ajax-failure"), ["xhr", "status", "error"])
-        }), u.data.push({
-            name: "X-Requested-With",
-            value: "XMLHttpRequest"
-        }), f = u.type.toUpperCase(), r(f) || (u.type = "POST", u.data.push({
-            name: "X-HTTP-Method-Override",
-            value: f
-        })), n.ajax(u))
-    }
-
-    function s(t) {
-        var i = n(t).data(f);
-        return !i || !i.validate || i.validate()
-    }
-    var t = "unobtrusiveAjaxClick",
-        f = "unobtrusiveValidation";
-    n(document).on("click", "a[data-ajax=true]", function(n) {
-        n.preventDefault();
-        u(this, {
-            url: this.href,
-            type: "GET",
-            data: []
-        })
-    });
-    n(document).on("click", "form[data-ajax=true] input[type=image]", function(i) {
-        var r = i.target.name,
-            u = n(i.target),
-            f = u.parents("form")[0],
-            e = u.offset();
-        n(f).data(t, [{
-            name: r + ".x",
-            value: Math.round(i.pageX - e.left)
-        }, {
-            name: r + ".y",
-            value: Math.round(i.pageY - e.top)
-        }]);
-        setTimeout(function() {
-            n(f).removeData(t)
-        }, 0)
-    });
-    n(document).on("click", "form[data-ajax=true] :submit", function(i) {
-        var r = i.target.name,
-            u = n(i.target).parents("form")[0];
-        n(u).data(t, r ? [{
-            name: r,
-            value: i.target.value
-        }] : []);
-        setTimeout(function() {
-            n(u).removeData(t)
-        }, 0)
-    });
-    n(document).on("submit", "form[data-ajax=true]", function(i) {
-        var r = n(this).data(t) || [];
-        (i.preventDefault(), s(this)) && u(this, {
-            url: this.action,
-            type: this.method || "GET",
-            data: r.concat(n(this).serializeArray())
-        })
-    })
-}(jQuery),
-function(n) {
-    n.extend(n.fn, {
-        validate: function(t) {
-            if (!this.length) return t && t.debug && window.console && console.warn("Nothing selected, can't validate, returning nothing."), void 0;
-            var i = n.data(this[0], "validator");
-            return i ? i : (this.attr("novalidate", "novalidate"), i = new n.validator(t, this[0]), n.data(this[0], "validator", i), i.settings.onsubmit && (this.validateDelegate(":submit", "click", function(t) {
-                i.settings.submitHandler && (i.submitButton = t.target);
-                n(t.target).hasClass("cancel") && (i.cancelSubmit = !0);
-                void 0 !== n(t.target).attr("formnovalidate") && (i.cancelSubmit = !0)
-            }), this.submit(function(t) {
-                function r() {
-                    var r;
-                    return i.settings.submitHandler ? (i.submitButton && (r = n("<input type='hidden'/>").attr("name", i.submitButton.name).val(n(i.submitButton).val()).appendTo(i.currentForm)), i.settings.submitHandler.call(i, i.currentForm, t), i.submitButton && r.remove(), !1) : !0
-                }
-                return i.settings.debug && t.preventDefault(), i.cancelSubmit ? (i.cancelSubmit = !1, r()) : i.form() ? i.pendingRequest ? (i.formSubmitted = !0, !1) : r() : (i.focusInvalid(), !1)
-            })), i)
-        },
-        valid: function() {
-            if (n(this[0]).is("form")) return this.validate().form();
-            var t = !0,
-                i = n(this[0].form).validate();
-            return this.each(function() {
-                t = t && i.element(this)
-            }), t
-        },
-        removeAttrs: function(t) {
-            var i = {},
-                r = this;
-            return n.each(t.split(/\s/), function(n, t) {
-                i[t] = r.attr(t);
-                r.removeAttr(t)
-            }), i
-        },
-        rules: function(t, i) {
-            var r = this[0],
-                o, u, h;
-            if (t) {
-                var e = n.data(r.form, "validator").settings,
-                    s = e.rules,
-                    f = n.validator.staticRules(r);
-                switch (t) {
-                    case "add":
-                        n.extend(f, n.validator.normalizeRule(i));
-                        delete f.messages;
-                        s[r.name] = f;
-                        i.messages && (e.messages[r.name] = n.extend(e.messages[r.name], i.messages));
-                        break;
-                    case "remove":
-                        return i ? (o = {}, n.each(i.split(/\s/), function(n, t) {
-                            o[t] = f[t];
-                            delete f[t]
-                        }), o) : (delete s[r.name], f)
-                }
-            }
-            return u = n.validator.normalizeRules(n.extend({}, n.validator.classRules(r), n.validator.attributeRules(r), n.validator.dataRules(r), n.validator.staticRules(r)), r), u.required && (h = u.required, delete u.required, u = n.extend({
-                required: h
-            }, u)), u
-        }
-    });
-    n.extend(n.expr[":"], {
-        blank: function(t) {
-            return !n.trim("" + n(t).val())
-        },
-        filled: function(t) {
-            return !!n.trim("" + n(t).val())
-        },
-        unchecked: function(t) {
-            return !n(t).prop("checked")
-        }
-    });
-    n.validator = function(t, i) {
-        this.settings = n.extend(!0, {}, n.validator.defaults, t);
-        this.currentForm = i;
-        this.init()
-    };
-    n.validator.format = function(t, i) {
-        return 1 === arguments.length ? function() {
-            var i = n.makeArray(arguments);
-            return i.unshift(t), n.validator.format.apply(this, i)
-        } : (arguments.length > 2 && i.constructor !== Array && (i = n.makeArray(arguments).slice(1)), i.constructor !== Array && (i = [i]), n.each(i, function(n, i) {
-            t = t.replace(RegExp("\\{" + n + "\\}", "g"), function() {
-                return i
-            })
-        }), t)
-    };
-    n.extend(n.validator, {
-        defaults: {
-            messages: {},
-            groups: {},
-            rules: {},
-            errorClass: "error",
-            validClass: "valid",
-            errorElement: "label",
-            focusInvalid: !0,
-            errorContainer: n([]),
-            errorLabelContainer: n([]),
-            onsubmit: !0,
-            ignore: ":hidden",
-            ignoreTitle: !1,
-            onfocusin: function(n) {
-                this.lastActive = n;
-                this.settings.focusCleanup && !this.blockFocusCleanup && (this.settings.unhighlight && this.settings.unhighlight.call(this, n, this.settings.errorClass, this.settings.validClass), this.addWrapper(this.errorsFor(n)).hide())
-            },
-            onfocusout: function(n) {
-                !this.checkable(n) && (n.name in this.submitted || !this.optional(n)) && this.element(n)
-            },
-            onkeyup: function(n, t) {
-                (9 !== t.which || "" !== this.elementValue(n)) && (n.name in this.submitted || n === this.lastElement) && this.element(n)
-            },
-            onclick: function(n) {
-                n.name in this.submitted ? this.element(n) : n.parentNode.name in this.submitted && this.element(n.parentNode)
-            },
-            highlight: function(t, i, r) {
-                "radio" === t.type ? this.findByName(t.name).addClass(i).removeClass(r) : n(t).addClass(i).removeClass(r)
-            },
-            unhighlight: function(t, i, r) {
-                "radio" === t.type ? this.findByName(t.name).removeClass(i).addClass(r) : n(t).removeClass(i).addClass(r)
-            }
-        },
-        setDefaults: function(t) {
-            n.extend(n.validator.defaults, t)
-        },
-        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.",
-            maxlength: n.validator.format("Please enter no more than {0} characters."),
-            minlength: n.validator.format("Please enter at least {0} characters."),
-            rangelength: n.validator.format("Please enter a value between {0} and {1} characters long."),
-            range: n.validator.format("Please enter a value between {0} and {1}."),
-            max: n.validator.format("Please enter a value less than or equal to {0}."),
-            min: n.validator.format("Please enter a value greater than or equal to {0}.")
-        },
-        autoCreateRanges: !1,
-        prototype: {
-            init: function() {
-                function i(t) {
-                    var i = n.data(this[0].form, "validator"),
-                        r = "on" + t.type.replace(/^validate/, "");
-                    i.settings[r] && i.settings[r].call(i, this[0], t)
-                }
-                var r, t;
-                this.labelContainer = n(this.settings.errorLabelContainer);
-                this.errorContext = this.labelContainer.length && this.labelContainer || n(this.currentForm);
-                this.containers = n(this.settings.errorContainer).add(this.settings.errorLabelContainer);
-                this.submitted = {};
-                this.valueCache = {};
-                this.pendingRequest = 0;
-                this.pending = {};
-                this.invalid = {};
-                this.reset();
-                r = this.groups = {};
-                n.each(this.settings.groups, function(t, i) {
-                    "string" == typeof i && (i = i.split(/\s/));
-                    n.each(i, function(n, i) {
-                        r[i] = t
-                    })
-                });
-                t = this.settings.rules;
-                n.each(t, function(i, r) {
-                    t[i] = n.validator.normalizeRule(r)
-                });
-                n(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ", "focusin focusout keyup", i).validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", i);
-                this.settings.invalidHandler && n(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler)
-            },
-            form: function() {
-                return this.checkForm(), n.extend(this.submitted, this.errorMap), this.invalid = n.extend({}, this.errorMap), this.valid() || n(this.currentForm).triggerHandler("invalid-form", [this]), this.showErrors(), this.valid()
-            },
-            checkForm: function() {
-                this.prepareForm();
-                for (var n = 0, t = this.currentElements = this.elements(); t[n]; n++) this.check(t[n]);
-                return this.valid()
-            },
-            element: function(t) {
-                t = this.validationTargetFor(this.clean(t));
-                this.lastElement = t;
-                this.prepareElement(t);
-                this.currentElements = n(t);
-                var i = this.check(t) !== !1;
-                return i ? delete this.invalid[t.name] : this.invalid[t.name] = !0, this.numberOfInvalids() || (this.toHide = this.toHide.add(this.containers)), this.showErrors(), i
-            },
-            showErrors: function(t) {
-                if (t) {
-                    n.extend(this.errorMap, t);
-                    this.errorList = [];
-                    for (var i in t) this.errorList.push({
-                        message: t[i],
-                        element: this.findByName(i)[0]
-                    });
-                    this.successList = n.grep(this.successList, function(n) {
-                        return !(n.name in t)
-                    })
-                }
-                this.settings.showErrors ? this.settings.showErrors.call(this, this.errorMap, this.errorList) : this.defaultShowErrors()
-            },
-            resetForm: function() {
-                n.fn.resetForm && n(this.currentForm).resetForm();
-                this.submitted = {};
-                this.lastElement = null;
-                this.prepareForm();
-                this.hideErrors();
-                this.elements().removeClass(this.settings.errorClass).removeData("previousValue")
-            },
-            numberOfInvalids: function() {
-                return this.objectLength(this.invalid)
-            },
-            objectLength: function(n) {
-                var t = 0;
-                for (var i in n) t++;
-                return t
-            },
-            hideErrors: function() {
-                this.addWrapper(this.toHide).hide()
-            },
-            valid: function() {
-                return 0 === this.size()
-            },
-            size: function() {
-                return this.errorList.length
-            },
-            focusInvalid: function() {
-                if (this.settings.focusInvalid) try {
-                    n(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").focus().trigger("focusin")
-                } catch (t) {}
-            },
-            findLastActive: function() {
-                var t = this.lastActive;
-                return t && 1 === n.grep(this.errorList, function(n) {
-                    return n.element.name === t.name
-                }).length && t
-            },
-            elements: function() {
-                var t = this,
-                    i = {};
-                return n(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function() {
-                    return !this.name && t.settings.debug && window.console && console.error("%o has no name assigned", this), this.name in i || !t.objectLength(n(this).rules()) ? !1 : (i[this.name] = !0, !0)
-                })
-            },
-            clean: function(t) {
-                return n(t)[0]
-            },
-            errors: function() {
-                var t = this.settings.errorClass.replace(" ", ".");
-                return n(this.settings.errorElement + "." + t, this.errorContext)
-            },
-            reset: function() {
-                this.successList = [];
-                this.errorList = [];
-                this.errorMap = {};
-                this.toShow = n([]);
-                this.toHide = n([]);
-                this.currentElements = n([])
-            },
-            prepareForm: function() {
-                this.reset();
-                this.toHide = this.errors().add(this.containers)
-            },
-            prepareElement: function(n) {
-                this.reset();
-                this.toHide = this.errorsFor(n)
-            },
-            elementValue: function(t) {
-                var r = n(t).attr("type"),
-                    i = n(t).val();
-                return "radio" === r || "checkbox" === r ? n("input[name='" + n(t).attr("name") + "']:checked").val() : "string" == typeof i ? i.replace(/\r/g, "") : i
-            },
-            check: function(t) {
-                var r, u;
-                t = this.validationTargetFor(this.clean(t));
-                var i, f = n(t).rules(),
-                    e = !1,
-                    s = this.elementValue(t);
-                for (r in f) {
-                    u = {
-                        method: r,
-                        parameters: f[r]
-                    };
-                    try {
-                        if (i = n.validator.methods[r].call(this, s, t, u.parameters), "dependency-mismatch" === i) {
-                            e = !0;
-                            continue
-                        }
-                        if (e = !1, "pending" === i) return this.toHide = this.toHide.not(this.errorsFor(t)), void 0;
-                        if (!i) return this.formatAndAdd(t, u), !1
-                    } catch (o) {
-                        throw this.settings.debug && window.console && console.log("Exception occurred when checking element " + t.id + ", check the '" + u.method + "' method.", o), o;
-                    }
-                }
-                if (!e) return (this.objectLength(f) && this.successList.push(t), !0)
-            },
-            customDataMessage: function(t, i) {
-                return n(t).data("msg-" + i.toLowerCase()) || t.attributes && n(t).attr("data-msg-" + i.toLowerCase())
-            },
-            customMessage: function(n, t) {
-                var i = this.settings.messages[n];
-                return i && (i.constructor === String ? i : i[t])
-            },
-            findDefined: function() {
-                for (var n = 0; arguments.length > n; n++)
-                    if (void 0 !== arguments[n]) return arguments[n];
-                return void 0
-            },
-            defaultMessage: function(t, i) {
-                return this.findDefined(this.customMessage(t.name, i), this.customDataMessage(t, i), !this.settings.ignoreTitle && t.title || void 0, n.validator.messages[i], "<strong>Warning: No message defined for " + t.name + "<\/strong>")
-            },
-            formatAndAdd: function(t, i) {
-                var r = this.defaultMessage(t, i.method),
-                    u = /\$?\{(\d+)\}/g;
-                "function" == typeof r ? r = r.call(this, i.parameters, t) : u.test(r) && (r = n.validator.format(r.replace(u, "{$1}"), i.parameters));
-                this.errorList.push({
-                    message: r,
-                    element: t
-                });
-                this.errorMap[t.name] = r;
-                this.submitted[t.name] = r
-            },
-            addWrapper: function(n) {
-                return this.settings.wrapper && (n = n.add(n.parent(this.settings.wrapper))), n
-            },
-            defaultShowErrors: function() {
-                for (var i, t, n = 0; this.errorList[n]; n++) t = this.errorList[n], this.settings.highlight && this.settings.highlight.call(this, t.element, this.settings.errorClass, this.settings.validClass), this.showLabel(t.element, t.message);
-                if (this.errorList.length && (this.toShow = this.toShow.add(this.containers)), this.settings.success)
-                    for (n = 0; this.successList[n]; n++) this.showLabel(this.successList[n]);
-                if (this.settings.unhighlight)
-                    for (n = 0, i = this.validElements(); i[n]; n++) this.settings.unhighlight.call(this, i[n], 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 n(this.errorList).map(function() {
-                    return this.element
-                })
-            },
-            showLabel: function(t, i) {
-                var r = this.errorsFor(t);
-                r.length ? (r.removeClass(this.settings.validClass).addClass(this.settings.errorClass), r.html(i)) : (r = n("<" + this.settings.errorElement + ">").attr("for", this.idOrName(t)).addClass(this.settings.errorClass).html(i || ""), this.settings.wrapper && (r = r.hide().show().wrap("<" + this.settings.wrapper + "/>").parent()), this.labelContainer.append(r).length || (this.settings.errorPlacement ? this.settings.errorPlacement(r, n(t)) : r.insertAfter(t)));
-                !i && this.settings.success && (r.text(""), "string" == typeof this.settings.success ? r.addClass(this.settings.success) : this.settings.success(r, t));
-                this.toShow = this.toShow.add(r)
-            },
-            errorsFor: function(t) {
-                var i = this.idOrName(t);
-                return this.errors().filter(function() {
-                    return n(this).attr("for") === i
-                })
-            },
-            idOrName: function(n) {
-                return this.groups[n.name] || (this.checkable(n) ? n.name : n.id || n.name)
-            },
-            validationTargetFor: function(n) {
-                return this.checkable(n) && (n = this.findByName(n.name).not(this.settings.ignore)[0]), n
-            },
-            checkable: function(n) {
-                return /radio|checkbox/i.test(n.type)
-            },
-            findByName: function(t) {
-                return n(this.currentForm).find("[name='" + t + "']")
-            },
-            getLength: function(t, i) {
-                switch (i.nodeName.toLowerCase()) {
-                    case "select":
-                        return n("option:selected", i).length;
-                    case "input":
-                        if (this.checkable(i)) return this.findByName(i.name).filter(":checked").length
-                }
-                return t.length
-            },
-            depend: function(n, t) {
-                return this.dependTypes[typeof n] ? this.dependTypes[typeof n](n, t) : !0
-            },
-            dependTypes: {
-                boolean: function(n) {
-                    return n
-                },
-                string: function(t, i) {
-                    return !!n(t, i.form).length
-                },
-                "function": function(n, t) {
-                    return n(t)
-                }
-            },
-            optional: function(t) {
-                var i = this.elementValue(t);
-                return !n.validator.methods.required.call(this, i, t) && "dependency-mismatch"
-            },
-            startRequest: function(n) {
-                this.pending[n.name] || (this.pendingRequest++, this.pending[n.name] = !0)
-            },
-            stopRequest: function(t, i) {
-                this.pendingRequest--;
-                0 > this.pendingRequest && (this.pendingRequest = 0);
-                delete this.pending[t.name];
-                i && 0 === this.pendingRequest && this.formSubmitted && this.form() ? (n(this.currentForm).submit(), this.formSubmitted = !1) : !i && 0 === this.pendingRequest && this.formSubmitted && (n(this.currentForm).triggerHandler("invalid-form", [this]), this.formSubmitted = !1)
-            },
-            previousValue: function(t) {
-                return n.data(t, "previousValue") || n.data(t, "previousValue", {
-                    old: null,
-                    valid: !0,
-                    message: this.defaultMessage(t, "remote")
-                })
-            }
-        },
-        classRuleSettings: {
-            required: {
-                required: !0
-            },
-            email: {
-                email: !0
-            },
-            url: {
-                url: !0
-            },
-            date: {
-                date: !0
-            },
-            dateISO: {
-                dateISO: !0
-            },
-            number: {
-                number: !0
-            },
-            digits: {
-                digits: !0
-            },
-            creditcard: {
-                creditcard: !0
-            }
-        },
-        addClassRules: function(t, i) {
-            t.constructor === String ? this.classRuleSettings[t] = i : n.extend(this.classRuleSettings, t)
-        },
-        classRules: function(t) {
-            var i = {},
-                r = n(t).attr("class");
-            return r && n.each(r.split(" "), function() {
-                this in n.validator.classRuleSettings && n.extend(i, n.validator.classRuleSettings[this])
-            }), i
-        },
-        attributeRules: function(t) {
-            var u = {},
-                e = n(t),
-                f = e[0].getAttribute("type"),
-                r, i;
-            for (r in n.validator.methods) "required" === r ? (i = e.get(0).getAttribute(r), "" === i && (i = !0), i = !!i) : i = e.attr(r), /min|max/.test(r) && (null === f || /number|range|text/.test(f)) && (i = Number(i)), i ? u[r] = i : f === r && "range" !== f && (u[r] = !0);
-            return u.maxlength && /-1|2147483647|524288/.test(u.maxlength) && delete u.maxlength, u
-        },
-        dataRules: function(t) {
-            var i, r, u = {},
-                f = n(t);
-            for (i in n.validator.methods) r = f.data("rule-" + i.toLowerCase()), void 0 !== r && (u[i] = r);
-            return u
-        },
-        staticRules: function(t) {
-            var i = {},
-                r = n.data(t.form, "validator");
-            return r.settings.rules && (i = n.validator.normalizeRule(r.settings.rules[t.name]) || {}), i
-        },
-        normalizeRules: function(t, i) {
-            return n.each(t, function(r, u) {
-                if (u === !1) return delete t[r], void 0;
-                if (u.param || u.depends) {
-                    var f = !0;
-                    switch (typeof u.depends) {
-                        case "string":
-                            f = !!n(u.depends, i.form).length;
-                            break;
-                        case "function":
-                            f = u.depends.call(i, i)
-                    }
-                    f ? t[r] = void 0 !== u.param ? u.param : !0 : delete t[r]
-                }
-            }), n.each(t, function(r, u) {
-                t[r] = n.isFunction(u) ? u(i) : u
-            }), n.each(["minlength", "maxlength"], function() {
-                t[this] && (t[this] = Number(t[this]))
-            }), n.each(["rangelength", "range"], function() {
-                var i;
-                t[this] && (n.isArray(t[this]) ? t[this] = [Number(t[this][0]), Number(t[this][1])] : "string" == typeof t[this] && (i = t[this].split(/[\s,]+/), t[this] = [Number(i[0]), Number(i[1])]))
-            }), n.validator.autoCreateRanges && (t.min && t.max && (t.range = [t.min, t.max], delete t.min, delete t.max), t.minlength && t.maxlength && (t.rangelength = [t.minlength, t.maxlength], delete t.minlength, delete t.maxlength)), t
-        },
-        normalizeRule: function(t) {
-            if ("string" == typeof t) {
-                var i = {};
-                n.each(t.split(/\s/), function() {
-                    i[this] = !0
-                });
-                t = i
-            }
-            return t
-        },
-        addMethod: function(t, i, r) {
-            n.validator.methods[t] = i;
-            n.validator.messages[t] = void 0 !== r ? r : n.validator.messages[t];
-            3 > i.length && n.validator.addClassRules(t, n.validator.normalizeRule(t))
-        },
-        methods: {
-            required: function(t, i, r) {
-                if (!this.depend(r, i)) return "dependency-mismatch";
-                if ("select" === i.nodeName.toLowerCase()) {
-                    var u = n(i).val();
-                    return u && u.length > 0
-                }
-                return this.checkable(i) ? this.getLength(t, i) > 0 : n.trim(t).length > 0
-            },
-            email: function(n, t) {
-                return this.optional(t) || /^((([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(n)
-            },
-            url: function(n, t) {
-                return this.optional(t) || /^(https?|s?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(n)
-            },
-            date: function(n, t) {
-                return this.optional(t) || !/Invalid|NaN/.test("" + new Date(n))
-            },
-            dateISO: function(n, t) {
-                return this.optional(t) || /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(n)
-            },
-            number: function(n, t) {
-                return this.optional(t) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(n)
-            },
-            digits: function(n, t) {
-                return this.optional(t) || /^\d+$/.test(n)
-            },
-            creditcard: function(n, t) {
-                var r, e;
-                if (this.optional(t)) return "dependency-mismatch";
-                if (/[^0-9 \-]+/.test(n)) return !1;
-                var f = 0,
-                    i = 0,
-                    u = !1;
-                for (n = n.replace(/\D/g, ""), r = n.length - 1; r >= 0; r--) e = n.charAt(r), i = parseInt(e, 10), u && (i *= 2) > 9 && (i -= 9), f += i, u = !u;
-                return 0 == f % 10
-            },
-            minlength: function(t, i, r) {
-                var u = n.isArray(t) ? t.length : this.getLength(n.trim(t), i);
-                return this.optional(i) || u >= r
-            },
-            maxlength: function(t, i, r) {
-                var u = n.isArray(t) ? t.length : this.getLength(n.trim(t), i);
-                return this.optional(i) || r >= u
-            },
-            rangelength: function(t, i, r) {
-                var u = n.isArray(t) ? t.length : this.getLength(n.trim(t), i);
-                return this.optional(i) || u >= r[0] && r[1] >= u
-            },
-            min: function(n, t, i) {
-                return this.optional(t) || n >= i
-            },
-            max: function(n, t, i) {
-                return this.optional(t) || i >= n
-            },
-            range: function(n, t, i) {
-                return this.optional(t) || n >= i[0] && i[1] >= n
-            },
-            equalTo: function(t, i, r) {
-                var u = n(r);
-                return this.settings.onfocusout && u.unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
-                    n(i).valid()
-                }), t === u.val()
-            },
-            remote: function(t, i, r) {
-                var f, u, e;
-                return this.optional(i) ? "dependency-mismatch" : (f = this.previousValue(i), this.settings.messages[i.name] || (this.settings.messages[i.name] = {}), f.originalMessage = this.settings.messages[i.name].remote, this.settings.messages[i.name].remote = f.message, r = "string" == typeof r && {
-                    url: r
-                } || r, f.old === t) ? f.valid : (f.old = t, u = this, this.startRequest(i), e = {}, e[i.name] = t, n.ajax(n.extend(!0, {
-                    url: r,
-                    mode: "abort",
-                    port: "validate" + i.name,
-                    dataType: "json",
-                    data: e,
-                    success: function(r) {
-                        var e, h, s, o;
-                        u.settings.messages[i.name].remote = f.originalMessage;
-                        e = r === !0 || "true" === r;
-                        e ? (h = u.formSubmitted, u.prepareElement(i), u.formSubmitted = h, u.successList.push(i), delete u.invalid[i.name], u.showErrors()) : (s = {}, o = r || u.defaultMessage(i, "remote"), s[i.name] = f.message = n.isFunction(o) ? o(t) : o, u.invalid[i.name] = !0, u.showErrors(s));
-                        f.valid = e;
-                        u.stopRequest(i, e)
-                    }
-                }, r)), "pending")
-            }
-        }
-    });
-    n.format = n.validator.format
-}(jQuery),
-function(n) {
-    var t = {},
-        i;
-    n.ajaxPrefilter ? n.ajaxPrefilter(function(n, i, r) {
-        var u = n.port;
-        "abort" === n.mode && (t[u] && t[u].abort(), t[u] = r)
-    }) : (i = n.ajax, n.ajax = function(r) {
-        var f = ("mode" in r ? r : n.ajaxSettings).mode,
-            u = ("port" in r ? r : n.ajaxSettings).port;
-        return "abort" === f ? (t[u] && t[u].abort(), t[u] = i.apply(this, arguments), t[u]) : i.apply(this, arguments)
-    })
-}(jQuery),
-function(n) {
-    n.extend(n.fn, {
-        validateDelegate: function(t, i, r) {
-            return this.bind(i, function(i) {
-                var u = n(i.target);
-                if (u.is(t)) return r.apply(u, arguments)
-            })
-        }
-    })
-}(jQuery),
-function(n) {
-    function i(n, t, i) {
-        n.rules[t] = i;
-        n.message && (n.messages[t] = n.message)
-    }
-
-    function h(n) {
-        return n.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g)
-    }
-
-    function f(n) {
-        return n.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1")
-    }
-
-    function e(n) {
-        return n.substr(0, n.lastIndexOf(".") + 1)
-    }
-
-    function o(n, t) {
-        return n.indexOf("*.") === 0 && (n = n.replace("*.", t)), n
-    }
-
-    function c(t, i) {
-        var r = n(this).find("[data-valmsg-for='" + f(i[0].name) + "']"),
-            u = r.attr("data-valmsg-replace"),
-            e = u ? n.parseJSON(u) !== !1 : null;
-        r.removeClass("field-validation-valid").addClass("field-validation-error");
-        t.data("unobtrusiveContainer", r);
-        e ? (r.empty(), t.removeClass("input-validation-error").appendTo(r)) : t.hide()
-    }
-
-    function l(t, i) {
-        var u = n(this).find("[data-valmsg-summary=true]"),
-            r = u.find("ul");
-        r && r.length && i.errorList.length && (r.empty(), u.addClass("validation-summary-errors").removeClass("validation-summary-valid"), n.each(i.errorList, function() {
-            n("<li />").html(this.message).appendTo(r)
-        }))
-    }
-
-    function a(t) {
-        var i = t.data("unobtrusiveContainer"),
-            r = i.attr("data-valmsg-replace"),
-            u = r ? n.parseJSON(r) : null;
-        i && (i.addClass("field-validation-valid").removeClass("field-validation-error"), t.removeData("unobtrusiveContainer"), u && i.empty())
-    }
-
-    function v() {
-        var t = n(this);
-        t.data("validator").resetForm();
-        t.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors");
-        t.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")
-    }
-
-    function s(t) {
-        var i = n(t),
-            r = i.data(u),
-            f = n.proxy(v, t);
-        return r || (r = {
-            options: {
-                errorClass: "input-validation-error",
-                errorElement: "span",
-                errorPlacement: n.proxy(c, t),
-                invalidHandler: n.proxy(l, t),
-                messages: {},
-                rules: {},
-                success: n.proxy(a, t)
-            },
-            attachValidation: function() {
-                i.unbind("reset." + u, f).bind("reset." + u, f).validate(this.options)
-            },
-            validate: function() {
-                return i.validate(), i.valid()
-            }
-        }, i.data(u, r)), r
-    }
-    var r = n.validator,
-        t, u = "unobtrusiveValidation";
-    r.unobtrusive = {
-        adapters: [],
-        parseElement: function(t, i) {
-            var u = n(t),
-                f = u.parents("form")[0],
-                r, e, o;
-            f && (r = s(f), r.options.rules[t.name] = e = {}, r.options.messages[t.name] = o = {}, n.each(this.adapters, function() {
-                var i = "data-val-" + this.name,
-                    r = u.attr(i),
-                    s = {};
-                r !== undefined && (i += "-", n.each(this.params, function() {
-                    s[this] = u.attr(i + this)
-                }), this.adapt({
-                    element: t,
-                    form: f,
-                    message: r,
-                    params: s,
-                    rules: e,
-                    messages: o
-                }))
-            }), n.extend(e, {
-                __dummy__: !0
-            }), i || r.attachValidation())
-        },
-        parse: function(t) {
-            var i = n(t).parents("form").andSelf().add(n(t).find("form")).filter("form");
-            n(t).find(":input[data-val=true]").each(function() {
-                r.unobtrusive.parseElement(this, !0)
-            });
-            i.each(function() {
-                var n = s(this);
-                n && n.attachValidation()
-            })
-        }
-    };
-    t = r.unobtrusive.adapters;
-    t.add = function(n, t, i) {
-        return i || (i = t, t = []), this.push({
-            name: n,
-            params: t,
-            adapt: i
-        }), this
-    };
-    t.addBool = function(n, t) {
-        return this.add(n, function(r) {
-            i(r, t || n, !0)
-        })
-    };
-    t.addMinMax = function(n, t, r, u, f, e) {
-        return this.add(n, [f || "min", e || "max"], function(n) {
-            var f = n.params.min,
-                e = n.params.max;
-            f && e ? i(n, u, [f, e]) : f ? i(n, t, f) : e && i(n, r, e)
-        })
-    };
-    t.addSingleVal = function(n, t, r) {
-        return this.add(n, [t || "val"], function(u) {
-            i(u, r || n, u.params[t])
-        })
-    };
-    r.addMethod("__dummy__", function() {
-        return !0
-    });
-    r.addMethod("regex", function(n, t, i) {
-        var r;
-        return this.optional(t) ? !0 : (r = new RegExp(i).exec(n), r && r.index === 0 && r[0].length === n.length)
-    });
-    r.addMethod("nonalphamin", function(n, t, i) {
-        var r;
-        return i && (r = n.match(/\W/g), r = r && r.length >= i), r
-    });
-    t.addSingleVal("accept", "exts").addSingleVal("regex", "pattern");
-    t.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");
-    t.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range");
-    t.add("equalto", ["other"], function(t) {
-        var r = e(t.element.name),
-            u = t.params.other,
-            s = o(u, r),
-            h = n(t.form).find(":input[name='" + f(s) + "']")[0];
-        i(t, "equalTo", h)
-    });
-    t.add("required", function(n) {
-        (n.element.tagName.toUpperCase() !== "INPUT" || n.element.type.toUpperCase() !== "CHECKBOX") && i(n, "required", !0)
-    });
-    t.add("remote", ["url", "type", "additionalfields"], function(t) {
-        var r = {
-                url: t.params.url,
-                type: t.params.type || "GET",
-                data: {}
-            },
-            u = e(t.element.name);
-        n.each(h(t.params.additionalfields || t.element.name), function(i, e) {
-            var s = o(e, u);
-            r.data[s] = function() {
-                return n(t.form).find(":input[name='" + f(s) + "']").val()
-            }
-        });
-        i(t, "remote", r)
-    });
-    t.add("password", ["min", "nonalphamin", "regex"], function(n) {
-        n.params.min && i(n, "minlength", n.params.min);
-        n.params.nonalphamin && i(n, "nonalphamin", n.params.nonalphamin);
-        n.params.regex && i(n, "regex", n.params.regex)
-    });
-    n(function() {
-        r.unobtrusive.parse(document)
-    })
-}(jQuery);
-window.Modernizr = function(n, t, i) {
-        function a(n) {
-            c.cssText = n
-        }
-
-        function vt(n, t) {
-            return a(y.join(n + ";") + (t || ""))
-        }
-
-        function h(n, t) {
-            return typeof n === t
-        }
-
-        function v(n, t) {
-            return !!~("" + n).indexOf(t)
-        }
-
-        function lt(n, t) {
-            var u, r;
-            for (u in n)
-                if (r = n[u], !v(r, "-") && c[r] !== i) return t == "pfx" ? r : !0;
-            return !1
-        }
-
-        function yt(n, t, r) {
-            var f, u;
-            for (f in n)
-                if (u = t[n[f]], u !== i) return r === !1 ? n[f] : h(u, "function") ? u.bind(r || t) : u;
-            return !1
-        }
-
-        function f(n, t, i) {
-            var r = n.charAt(0).toUpperCase() + n.slice(1),
-                u = (n + " " + ot.join(r + " ") + r).split(" ");
-            return h(t, "string") || h(t, "undefined") ? lt(u, t) : (u = (n + " " + st.join(r + " ") + r).split(" "), yt(u, t, i))
-        }
-
-        function pt() {
-            u.input = function(i) {
-                for (var r = 0, u = i.length; r < u; r++) w[i[r]] = !!(i[r] in o);
-                return w.list && (w.list = !!(t.createElement("datalist") && n.HTMLDataListElement)), w
-            }("autocomplete autofocus list placeholder max min multiple pattern required step".split(" "));
-            u.inputtypes = function(n) {
-                for (var u = 0, r, f, e, h = n.length; u < h; u++) o.setAttribute("type", f = n[u]), r = o.type !== "text", r && (o.value = g, o.style.cssText = "position:absolute;visibility:hidden;", /^range$/.test(f) && o.style.WebkitAppearance !== i ? (s.appendChild(o), e = t.defaultView, r = e.getComputedStyle && e.getComputedStyle(o, null).WebkitAppearance !== "textfield" && o.offsetHeight !== 0, s.removeChild(o)) : /^(search|tel)$/.test(f) || (r = /^(url|email)$/.test(f) ? o.checkValidity && o.checkValidity() === !1 : o.value != g)), ht[n[u]] = !!r;
-                return ht
-            }("search tel url email datetime date month week time datetime-local number range color".split(" "))
-        }
-        var u = {},
-            d = !0,
-            s = t.documentElement,
-            e = "modernizr",
-            ut = t.createElement(e),
-            c = ut.style,
-            o = t.createElement("input"),
-            g = ":)",
-            ft = {}.toString,
-            y = " -webkit- -moz- -o- -ms- ".split(" "),
-            et = "Webkit Moz O ms",
-            ot = et.split(" "),
-            st = et.toLowerCase().split(" "),
-            p = {
-                svg: "http://www.w3.org/2000/svg"
-            },
-            r = {},
-            ht = {},
-            w = {},
-            nt = [],
-            tt = nt.slice,
-            b, l = function(n, i, r, u) {
-                var l, a, c, v, f = t.createElement("div"),
-                    h = t.body,
-                    o = h || t.createElement("body");
-                if (parseInt(r, 10))
-                    while (r--) c = t.createElement("div"), c.id = u ? u[r] : e + (r + 1), f.appendChild(c);
-                return l = ["&#173;", '<style id="s', e, '">', n, "<\/style>"].join(""), f.id = e, (h ? f : o).innerHTML += l, o.appendChild(f), h || (o.style.background = "", o.style.overflow = "hidden", v = s.style.overflow, s.style.overflow = "hidden", s.appendChild(o)), a = i(f, n), h ? f.parentNode.removeChild(f) : (o.parentNode.removeChild(o), s.style.overflow = v), !!a
-            },
-            at = function(t) {
-                var i = n.matchMedia || n.msMatchMedia,
-                    r;
-                return i ? i(t).matches : (l("@media " + t + " { #" + e + " { position: absolute; } }", function(t) {
-                    r = (n.getComputedStyle ? getComputedStyle(t, null) : t.currentStyle).position == "absolute"
-                }), r)
-            },
-            ct = function() {
-                function r(r, u) {
-                    u = u || t.createElement(n[r] || "div");
-                    r = "on" + r;
-                    var f = r in u;
-                    return f || (u.setAttribute || (u = t.createElement("div")), u.setAttribute && u.removeAttribute && (u.setAttribute(r, ""), f = h(u[r], "function"), h(u[r], "undefined") || (u[r] = i), u.removeAttribute(r))), u = null, f
-                }
-                var n = {
-                    select: "input",
-                    change: "input",
-                    submit: "form",
-                    reset: "form",
-                    error: "img",
-                    load: "img",
-                    abort: "img"
-                };
-                return r
-            }(),
-            it = {}.hasOwnProperty,
-            rt, k;
-        rt = h(it, "undefined") || h(it.call, "undefined") ? function(n, t) {
-            return t in n && h(n.constructor.prototype[t], "undefined")
-        } : function(n, t) {
-            return it.call(n, t)
-        };
-        Function.prototype.bind || (Function.prototype.bind = function(n) {
-            var t = this,
-                i, r;
-            if (typeof t != "function") throw new TypeError;
-            return i = tt.call(arguments, 1), r = function() {
-                var f, e, u;
-                return this instanceof r ? (f = function() {}, f.prototype = t.prototype, e = new f, u = t.apply(e, i.concat(tt.call(arguments))), Object(u) === u) ? u : e : t.apply(n, i.concat(tt.call(arguments)))
-            }, r
-        });
-        r.flexbox = function() {
-            return f("flexWrap")
-        };
-        r.flexboxlegacy = function() {
-            return f("boxDirection")
-        };
-        r.canvas = function() {
-            var n = t.createElement("canvas");
-            return !!(n.getContext && n.getContext("2d"))
-        };
-        r.canvastext = function() {
-            return !!(u.canvas && h(t.createElement("canvas").getContext("2d").fillText, "function"))
-        };
-        r.webgl = function() {
-            return !!n.WebGLRenderingContext
-        };
-        r.touch = function() {
-            var i;
-            return "ontouchstart" in n || n.DocumentTouch && t instanceof DocumentTouch ? i = !0 : l(["@media (", y.join("touch-enabled),("), e, ")", "{#modernizr{top:9px;position:absolute}}"].join(""), function(n) {
-                i = n.offsetTop === 9
-            }), i
-        };
-        r.geolocation = function() {
-            return "geolocation" in navigator
-        };
-        r.postmessage = function() {
-            return !!n.postMessage
-        };
-        r.websqldatabase = function() {
-            return !!n.openDatabase
-        };
-        r.indexedDB = function() {
-            return !!f("indexedDB", n)
-        };
-        r.hashchange = function() {
-            return ct("hashchange", n) && (t.documentMode === i || t.documentMode > 7)
-        };
-        r.history = function() {
-            return !!(n.history && history.pushState)
-        };
-        r.draganddrop = function() {
-            var n = t.createElement("div");
-            return "draggable" in n || "ondragstart" in n && "ondrop" in n
-        };
-        r.websockets = function() {
-            return "WebSocket" in n || "MozWebSocket" in n
-        };
-        r.rgba = function() {
-            return a("background-color:rgba(150,255,150,.5)"), v(c.backgroundColor, "rgba")
-        };
-        r.hsla = function() {
-            return a("background-color:hsla(120,40%,100%,.5)"), v(c.backgroundColor, "rgba") || v(c.backgroundColor, "hsla")
-        };
-        r.multiplebgs = function() {
-            return a("background:url(https://),url(https://),red url(https://)"), /(url\s*\(.*?){3}/.test(c.background)
-        };
-        r.backgroundsize = function() {
-            return f("backgroundSize")
-        };
-        r.borderimage = function() {
-            return f("borderImage")
-        };
-        r.borderradius = function() {
-            return f("borderRadius")
-        };
-        r.boxshadow = function() {
-            return f("boxShadow")
-        };
-        r.textshadow = function() {
-            return t.createElement("div").style.textShadow === ""
-        };
-        r.opacity = function() {
-            return vt("opacity:.55"), /^0.55$/.test(c.opacity)
-        };
-        r.cssanimations = function() {
-            return f("animationName")
-        };
-        r.csscolumns = function() {
-            return f("columnCount")
-        };
-        r.cssgradients = function() {
-            var n = "background-image:";
-            return a((n + "-webkit- ".split(" ").join("gradient(linear,left top,right bottom,from(#9f9),to(white));" + n) + y.join("linear-gradient(left top,#9f9, white);" + n)).slice(0, -n.length)), v(c.backgroundImage, "gradient")
-        };
-        r.cssreflections = function() {
-            return f("boxReflect")
-        };
-        r.csstransforms = function() {
-            return !!f("transform")
-        };
-        r.csstransforms3d = function() {
-            var n = !!f("perspective");
-            return n && "webkitPerspective" in s.style && l("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}", function(t) {
-                n = t.offsetLeft === 9 && t.offsetHeight === 3
-            }), n
-        };
-        r.csstransitions = function() {
-            return f("transition")
-        };
-        r.fontface = function() {
-            var n;
-            return l('@font-face {font-family:"font";src:url("https://")}', function(i, r) {
-                var f = t.getElementById("smodernizr"),
-                    u = f.sheet || f.styleSheet,
-                    e = u ? u.cssRules && u.cssRules[0] ? u.cssRules[0].cssText : u.cssText || "" : "";
-                n = /src/i.test(e) && e.indexOf(r.split(" ")[0]) === 0
-            }), n
-        };
-        r.generatedcontent = function() {
-            var n;
-            return l(["#", e, "{font:0/0 a}#", e, ':after{content:"', g, '";visibility:hidden;font:3px/1 a}'].join(""), function(t) {
-                n = t.offsetHeight >= 3
-            }), n
-        };
-        r.video = function() {
-            var i = t.createElement("video"),
-                n = !1;
-            try {
-                (n = !!i.canPlayType) && (n = new Boolean(n), n.ogg = i.canPlayType('video/ogg; codecs="theora"').replace(/^no$/, ""), n.h264 = i.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/, ""), n.webm = i.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/, ""))
-            } catch (r) {}
-            return n
-        };
-        r.audio = function() {
-            var i = t.createElement("audio"),
-                n = !1;
-            try {
-                (n = !!i.canPlayType) && (n = new Boolean(n), n.ogg = i.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, ""), n.mp3 = i.canPlayType("audio/mpeg;").replace(/^no$/, ""), n.wav = i.canPlayType('audio/wav; codecs="1"').replace(/^no$/, ""), n.m4a = (i.canPlayType("audio/x-m4a;") || i.canPlayType("audio/aac;")).replace(/^no$/, ""))
-            } catch (r) {}
-            return n
-        };
-        r.localstorage = function() {
-            try {
-                return localStorage.setItem(e, e), localStorage.removeItem(e), !0
-            } catch (n) {
-                return !1
-            }
-        };
-        r.sessionstorage = function() {
-            try {
-                return sessionStorage.setItem(e, e), sessionStorage.removeItem(e), !0
-            } catch (n) {
-                return !1
-            }
-        };
-        r.webworkers = function() {
-            return !!n.Worker
-        };
-        r.applicationcache = function() {
-            return !!n.applicationCache
-        };
-        r.svg = function() {
-            return !!t.createElementNS && !!t.createElementNS(p.svg, "svg").createSVGRect
-        };
-        r.inlinesvg = function() {
-            var n = t.createElement("div");
-            return n.innerHTML = "<svg/>", (n.firstChild && n.firstChild.namespaceURI) == p.svg
-        };
-        r.smil = function() {
-            return !!t.createElementNS && /SVGAnimate/.test(ft.call(t.createElementNS(p.svg, "animate")))
-        };
-        r.svgclippaths = function() {
-            return !!t.createElementNS && /SVGClipPath/.test(ft.call(t.createElementNS(p.svg, "clipPath")))
-        };
-        for (k in r) rt(r, k) && (b = k.toLowerCase(), u[b] = r[k](), nt.push((u[b] ? "" : "no-") + b));
-        return u.input || pt(), u.addTest = function(n, t) {
-                if (typeof n == "object")
-                    for (var r in n) rt(n, r) && u.addTest(r, n[r]);
-                else {
-                    if (n = n.toLowerCase(), u[n] !== i) return u;
-                    t = typeof t == "function" ? t() : t;
-                    typeof d != "undefined" && d && (s.className += " " + (t ? "" : "no-") + n);
-                    u[n] = t
-                }
-                return u
-            }, a(""), ut = o = null,
-            function(n, t) {
-                function p(n, t) {
-                    var i = n.createElement("p"),
-                        r = n.getElementsByTagName("head")[0] || n.documentElement;
-                    return i.innerHTML = "x<style>" + t + "<\/style>", r.insertBefore(i.lastChild, r.firstChild)
-                }
-
-                function c() {
-                    var n = r.elements;
-                    return typeof n == "string" ? n.split(" ") : n
-                }
-
-                function o(n) {
-                    var t = h[n[s]];
-                    return t || (t = {}, e++, n[s] = e, h[e] = t), t
-                }
-
-                function l(n, r, u) {
-                    if (r || (r = t), i) return r.createElement(n);
-                    u || (u = o(r));
-                    var f;
-                    return f = u.cache[n] ? u.cache[n].cloneNode() : y.test(n) ? (u.cache[n] = u.createElem(n)).cloneNode() : u.createElem(n), f.canHaveChildren && !v.test(n) ? u.frag.appendChild(f) : f
-                }
-
-                function w(n, r) {
-                    if (n || (n = t), i) return n.createDocumentFragment();
-                    r = r || o(n);
-                    for (var f = r.frag.cloneNode(), u = 0, e = c(), s = e.length; u < s; u++) f.createElement(e[u]);
-                    return f
-                }
-
-                function b(n, t) {
-                    t.cache || (t.cache = {}, t.createElem = n.createElement, t.createFrag = n.createDocumentFragment, t.frag = t.createFrag());
-                    n.createElement = function(i) {
-                        return r.shivMethods ? l(i, n, t) : t.createElem(i)
-                    };
-                    n.createDocumentFragment = Function("h,f", "return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&(" + c().join().replace(/\w+/g, function(n) {
-                        return t.createElem(n), t.frag.createElement(n), 'c("' + n + '")'
-                    }) + ");return n}")(r, t.frag)
-                }
-
-                function a(n) {
-                    n || (n = t);
-                    var u = o(n);
-                    return !r.shivCSS || f || u.hasCSS || (u.hasCSS = !!p(n, "article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}")), i || b(n, u), n
-                }
-                var u = n.html5 || {},
-                    v = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,
-                    y = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,
-                    f, s = "_html5shiv",
-                    e = 0,
-                    h = {},
-                    i, r;
-                (function() {
-                    try {
-                        var n = t.createElement("a");
-                        n.innerHTML = "<xyz><\/xyz>";
-                        f = "hidden" in n;
-                        i = n.childNodes.length == 1 || function() {
-                            t.createElement("a");
-                            var n = t.createDocumentFragment();
-                            return typeof n.cloneNode == "undefined" || typeof n.createDocumentFragment == "undefined" || typeof n.createElement == "undefined"
-                        }()
-                    } catch (r) {
-                        f = !0;
-                        i = !0
-                    }
-                })();
-                r = {
-                    elements: u.elements || "abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",
-                    shivCSS: u.shivCSS !== !1,
-                    supportsUnknownElements: i,
-                    shivMethods: u.shivMethods !== !1,
-                    type: "default",
-                    shivDocument: a,
-                    createElement: l,
-                    createDocumentFragment: w
-                };
-                n.html5 = r;
-                a(t)
-            }(this, t), u._version = "2.6.2", u._prefixes = y, u._domPrefixes = st, u._cssomPrefixes = ot, u.mq = at, u.hasEvent = ct, u.testProp = function(n) {
-                return lt([n])
-            }, u.testAllProps = f, u.testStyles = l, u.prefixed = function(n, t, i) {
-                return t ? f(n, t, i) : f(n, "pfx")
-            }, s.className = s.className.replace(/(^|\s)no-js(\s|$)/, "$1$2") + (d ? " js " + nt.join(" ") : ""), u
-    }(this, this.document),
-    function(n, t, i) {
-        function l(n) {
-            var t = {},
-                r = /^jQuery\d+$/;
-            return i.each(n.attributes, function(n, i) {
-                i.specified && !r.test(i.name) && (t[i.name] = i.value)
-            }), t
-        }
-
-        function f(n, r) {
-            var f = this,
-                u = i(f);
-            if (f.value == u.attr("placeholder") && u.hasClass("placeholder"))
-                if (u.data("placeholder-password")) {
-                    if (u = u.hide().next().show().attr("id", u.removeAttr("id").data("placeholder-id")), n === !0) return u[0].value = r;
-                    u.focus()
-                } else f.value = "", u.removeClass("placeholder"), f == t.activeElement && f.select()
-        }
-
-        function s() {
-            var t, r = this,
-                n = i(r),
-                e = n,
-                u = this.id;
-            if (r.value == "") {
-                if (r.type == "password") {
-                    if (!n.data("placeholder-textinput")) {
-                        try {
-                            t = n.clone().attr({
-                                type: "text"
-                            })
-                        } catch (o) {
-                            t = i("<input>").attr(i.extend(l(this), {
-                                type: "text"
-                            }))
-                        }
-                        t.removeAttr("name").data({
-                            "placeholder-password": !0,
-                            "placeholder-id": u
-                        }).bind("focus.placeholder", f);
-                        n.data({
-                            "placeholder-textinput": t,
-                            "placeholder-id": u
-                        }).before(t)
-                    }
-                    n = n.removeAttr("id").hide().prev().attr("id", u).show()
-                }
-                n.addClass("placeholder");
-                n[0].value = n.attr("placeholder")
-            } else n.removeClass("placeholder")
-        }
-        var u = "placeholder" in t.createElement("input"),
-            e = "placeholder" in t.createElement("textarea"),
-            h = i.fn,
-            c = i.valHooks,
-            o, r;
-        u && e ? (r = h.placeholder = function() {
-            return this
-        }, r.input = r.textarea = !0) : (r = h.placeholder = function() {
-            var n = this;
-            return n.filter((u ? "textarea" : ":input") + "[placeholder]").not(".placeholder").bind({
-                "focus.placeholder": f,
-                "blur.placeholder": s
-            }).data("placeholder-enabled", !0).trigger("blur.placeholder"), n
-        }, r.input = u, r.textarea = e, o = {
-            get: function(n) {
-                var t = i(n);
-                return t.data("placeholder-enabled") && t.hasClass("placeholder") ? "" : n.value
-            },
-            set: function(n, r) {
-                var u = i(n);
-                return u.data("placeholder-enabled") ? (r == "" ? (n.value = r, n != t.activeElement && s.call(n)) : u.hasClass("placeholder") ? f.call(n, !0, r) || (n.value = r) : n.value = r, u) : n.value = r
-            }
-        }, u || (c.input = o), e || (c.textarea = o), i(function() {
-            i(t).delegate("form", "submit.placeholder", function() {
-                var n = i(".placeholder", this).each(f);
-                setTimeout(function() {
-                    n.each(s)
-                }, 10)
-            })
-        }), i(n).bind("beforeunload.placeholder", function() {
-            i(".placeholder").each(function() {
-                this.value = ""
-            })
-        }))
-    }(this, document, jQuery),
-    function(n) {
-        "function" == typeof define && define.amd ? define(["jquery"], n) : n(jQuery)
-    }(function(n) {
-        function r(n) {
-            return n
-        }
-
-        function u(n) {
-            return decodeURIComponent(n.replace(f, " "))
-        }
-
-        function i(n) {
-            0 === n.indexOf('"') && (n = n.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\"));
-            try {
-                return t.json ? JSON.parse(n) : n
-            } catch (i) {}
-        }
-        var f = /\+/g,
-            t = n.cookie = function(f, e, o) {
-                var l, s;
-                if (void 0 !== e) return (o = n.extend({}, t.defaults, o), "number" == typeof o.expires) && (l = o.expires, s = o.expires = new Date, s.setDate(s.getDate() + l)), e = t.json ? JSON.stringify(e) : e + "", document.cookie = [t.raw ? f : encodeURIComponent(f), "=", t.raw ? e : encodeURIComponent(e), o.expires ? "; expires=" + o.expires.toUTCString() : "", o.path ? "; path=" + o.path : "", o.domain ? "; domain=" + o.domain : "", o.secure ? "; secure" : ""].join("");
-                for (var a = t.raw ? r : u, v = document.cookie.split("; "), h = f ? void 0 : {}, c = 0, b = v.length; b > c; c++) {
-                    var y = v[c].split("="),
-                        p = a(y.shift()),
-                        w = a(y.join("="));
-                    if (f && f === p) {
-                        h = i(w);
-                        break
-                    }
-                    f || (h[p] = i(w))
-                }
-                return h
-            };
-        t.defaults = {};
-        n.removeCookie = function(t, i) {
-            return void 0 !== n.cookie(t) ? (n.cookie(t, "", n.extend(i, {
-                expires: -1
-            })), !0) : !1
-        }
-    });
-typeof JSON != "object" && (JSON = {}),
-    function() {
-        "use strict";
-
-        function i(n) {
-            return n < 10 ? "0" + n : n
-        }
-
-        function o(n) {
-            return e.lastIndex = 0, e.test(n) ? '"' + n.replace(e, function(n) {
-                var t = s[n];
-                return typeof t == "string" ? t : "\\u" + ("0000" + n.charCodeAt(0).toString(16)).slice(-4)
-            }) + '"' : '"' + n + '"'
-        }
-
-        function u(i, f) {
-            var s, l, h, a, v = n,
-                c, e = f[i];
-            e && typeof e == "object" && typeof e.toJSON == "function" && (e = e.toJSON(i));
-            typeof t == "function" && (e = t.call(f, i, e));
-            switch (typeof e) {
-                case "string":
-                    return o(e);
-                case "number":
-                    return isFinite(e) ? String(e) : "null";
-                case "boolean":
-                case "null":
-                    return String(e);
-                case "object":
-                    if (!e) return "null";
-                    if (n += r, c = [], Object.prototype.toString.apply(e) === "[object Array]") {
-                        for (a = e.length, s = 0; s < a; s += 1) c[s] = u(s, e) || "null";
-                        return h = c.length === 0 ? "[]" : n ? "[\n" + n + c.join(",\n" + n) + "\n" + v + "]" : "[" + c.join(",") + "]", n = v, h
-                    }
-                    if (t && typeof t == "object")
-                        for (a = t.length, s = 0; s < a; s += 1) typeof t[s] == "string" && (l = t[s], h = u(l, e), h && c.push(o(l) + (n ? ": " : ":") + h));
-                    else
-                        for (l in e) Object.prototype.hasOwnProperty.call(e, l) && (h = u(l, e), h && c.push(o(l) + (n ? ": " : ":") + h));
-                    return h = c.length === 0 ? "{}" : n ? "{\n" + n + c.join(",\n" + n) + "\n" + v + "}" : "{" + c.join(",") + "}", n = v, h
-            }
-        }
-        typeof Date.prototype.toJSON != "function" && (Date.prototype.toJSON = function() {
-            return isFinite(this.valueOf()) ? this.getUTCFullYear() + "-" + i(this.getUTCMonth() + 1) + "-" + i(this.getUTCDate()) + "T" + i(this.getUTCHours()) + ":" + i(this.getUTCMinutes()) + ":" + i(this.getUTCSeconds()) + "Z" : null
-        }, String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function() {
-            return this.valueOf()
-        });
-        var f = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-            e = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-            n, r, s = {
-                "\b": "\\b",
-                "\t": "\\t",
-                "\n": "\\n",
-                "\f": "\\f",
-                "\r": "\\r",
-                '"': '\\"',
-                "\\": "\\\\"
-            },
-            t;
-        typeof JSON.stringify != "function" && (JSON.stringify = function(i, f, e) {
-            var o;
-            if (n = "", r = "", typeof e == "number")
-                for (o = 0; o < e; o += 1) r += " ";
-            else typeof e == "string" && (r = e);
-            if (t = f, f && typeof f != "function" && (typeof f != "object" || typeof f.length != "number")) throw new Error("JSON.stringify");
-            return u("", {
-                "": i
-            })
-        });
-        typeof JSON.parse != "function" && (JSON.parse = function(text, reviver) {
-            function walk(n, t) {
-                var r, u, i = n[t];
-                if (i && typeof i == "object")
-                    for (r in i) Object.prototype.hasOwnProperty.call(i, r) && (u = walk(i, r), u !== undefined ? i[r] = u : delete i[r]);
-                return reviver.call(n, t, i)
-            }
-            var j;
-            if (text = String(text), f.lastIndex = 0, f.test(text) && (text = text.replace(f, function(n) {
-                    return "\\u" + ("0000" + n.charCodeAt(0).toString(16)).slice(-4)
-                })), /^[\],:{}\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, ""))) return j = eval("(" + text + ")"), typeof reviver == "function" ? walk({
-                "": j
-            }, "") : j;
-            throw new SyntaxError("JSON.parse");
-        })
-    }(),
-    function() {
-        function ut() {
-            var u = !1,
-                n;
-            if ("localStorage" in window) try {
-                window.localStorage.setItem("_tmptest", "tmpval");
-                u = !0;
-                window.localStorage.removeItem("_tmptest")
-            } catch (f) {}
-            if (u) try {
-                window.localStorage && (i = window.localStorage, r = "localStorage", s = i.jStorage_update)
-            } catch (e) {} else if ("globalStorage" in window) try {
-                window.globalStorage && (i = window.globalStorage[window.location.hostname], r = "globalStorage", s = i.jStorage_update)
-            } catch (o) {} else if (t = document.createElement("link"), t.addBehavior) {
-                t.style.behavior = "url(#default#userData)";
-                document.getElementsByTagName("head")[0].appendChild(t);
-                try {
-                    t.load("jStorage")
-                } catch (h) {
-                    t.setAttribute("jStorage", "{}");
-                    t.save("jStorage");
-                    t.load("jStorage")
-                }
-                n = "{}";
-                try {
-                    n = t.getAttribute("jStorage")
-                } catch (c) {}
-                try {
-                    s = t.getAttribute("jStorage_update")
-                } catch (a) {}
-                i.jStorage = n;
-                r = "userDataBehavior"
-            } else {
-                t = null;
-                return
-            }
-            it();
-            p();
-            y("local");
-            y("session");
-            ft();
-            rt();
-            "addEventListener" in window && window.addEventListener("pageshow", function(n) {
-                n.persisted && l()
-            }, !1)
-        }
-
-        function y(t, i) {
-            function l() {
-                if (t == "session") try {
-                    o = u.parse(window.name || "{}")
-                } catch (n) {
-                    o = {}
-                }
-            }
-
-            function a() {
-                t == "session" && (window.name = u.stringify(o))
-            }
-            var c = !1,
-                s = 0,
-                h, f, o = {},
-                v = Math.random();
-            if (i || typeof window[t + "Storage"] == "undefined") {
-                if (t == "local" && window.globalStorage) {
-                    localStorage = window.globalStorage[window.location.hostname];
-                    return
-                }
-                if (r == "userDataBehavior") {
-                    i && window[t + "Storage"] && window[t + "Storage"].parentNode && window[t + "Storage"].parentNode.removeChild(window[t + "Storage"]);
-                    f = document.createElement("button");
-                    document.getElementsByTagName("head")[0].appendChild(f);
-                    t == "local" ? o = n : t == "session" && l();
-                    for (h in o) o.hasOwnProperty(h) && h != "__jstorage_meta" && h != "length" && typeof o[h] != "undefined" && (h in f || s++, f[h] = o[h]);
-                    f.length = s;
-                    f.key = function(n) {
-                        var i = 0,
-                            t;
-                        l();
-                        for (t in o)
-                            if (o.hasOwnProperty(t) && t != "__jstorage_meta" && t != "length" && typeof o[t] != "undefined") {
-                                if (i == n) return t;
-                                i++
-                            }
-                    };
-                    f.getItem = function(n) {
-                        return (l(), t == "session") ? o[n] : e.jStorage.get(n)
-                    };
-                    f.setItem = function(n, t) {
-                        typeof t != "undefined" && (f[n] = (t || "").toString())
-                    };
-                    f.removeItem = function(n) {
-                        if (t == "local") return e.jStorage.deleteKey(n);
-                        f[n] = undefined;
-                        c = !0;
-                        n in f && f.removeAttribute(n);
-                        c = !1
-                    };
-                    f.clear = function() {
-                        if (t == "session") {
-                            window.name = "";
-                            y("session", !0);
-                            return
-                        }
-                        e.jStorage.flush()
-                    };
-                    t == "local" && (d = function(n, t) {
-                        n != "length" && (c = !0, typeof t == "undefined" ? n in f && (s--, f.removeAttribute(n)) : (n in f || s++, f[n] = (t || "").toString()), f.length = s, c = !1)
-                    });
-                    f.attachEvent("onpropertychange", function(n) {
-                        if (n.propertyName != "length" && !c && n.propertyName != "length") {
-                            if (t == "local") n.propertyName in o || typeof f[n.propertyName] == "undefined" || s++;
-                            else if (t == "session") {
-                                l();
-                                typeof f[n.propertyName] == "undefined" || n.propertyName in o ? typeof f[n.propertyName] == "undefined" && n.propertyName in o ? (delete o[n.propertyName], s--) : o[n.propertyName] = f[n.propertyName] : (o[n.propertyName] = f[n.propertyName], s++);
-                                a();
-                                f.length = s;
-                                return
-                            }
-                            e.jStorage.set(n.propertyName, f[n.propertyName]);
-                            f.length = s
-                        }
-                    });
-                    window[t + "Storage"] = f
-                }
-            }
-        }
-
-        function tt() {
-            var n = "{}";
-            if (r == "userDataBehavior") {
-                t.load("jStorage");
-                try {
-                    n = t.getAttribute("jStorage")
-                } catch (u) {}
-                try {
-                    s = t.getAttribute("jStorage_update")
-                } catch (f) {}
-                i.jStorage = n
-            }
-            it();
-            p();
-            rt()
-        }
-
-        function ft() {
-            r == "localStorage" || r == "globalStorage" ? "addEventListener" in window ? window.addEventListener("storage", l, !1) : document.attachEvent("onstorage", l) : r == "userDataBehavior" && setInterval(l, 1e3)
-        }
-
-        function l() {
-            var n;
-            clearTimeout(g);
-            g = setTimeout(function() {
-                if (r == "localStorage" || r == "globalStorage") n = i.jStorage_update;
-                else if (r == "userDataBehavior") {
-                    t.load("jStorage");
-                    try {
-                        n = t.getAttribute("jStorage_update")
-                    } catch (u) {}
-                }
-                n && n != s && (s = n, et())
-            }, 25)
-        }
-
-        function et() {
-            var i = u.parse(u.stringify(n.__jstorage_meta.CRC32)),
-                r, t, f, e;
-            tt();
-            r = u.parse(u.stringify(n.__jstorage_meta.CRC32));
-            f = [];
-            e = [];
-            for (t in i)
-                if (i.hasOwnProperty(t)) {
-                    if (!r[t]) {
-                        e.push(t);
-                        continue
-                    }
-                    i[t] != r[t] && String(i[t]).substr(0, 2) == "2." && f.push(t)
-                }
-            for (t in r) r.hasOwnProperty(t) && (i[t] || f.push(t));
-            c(f, "updated");
-            c(e, "deleted")
-        }
-
-        function c(n, t) {
-            var u, i, e, r, o;
-            if (n = [].concat(n || []), t == "flushed") {
-                n = [];
-                for (u in f) f.hasOwnProperty(u) && n.push(u);
-                t = "deleted"
-            }
-            for (i = 0, e = n.length; i < e; i++)
-                if (f[n[i]])
-                    for (r = 0, o = f[n[i]].length; r < o; r++) f[n[i]][r](n[i], t)
-        }
-
-        function a() {
-            var n = (+new Date).toString();
-            r == "localStorage" || r == "globalStorage" ? i.jStorage_update = n : r == "userDataBehavior" && (t.setAttribute("jStorage_update", n), t.save("jStorage"));
-            l()
-        }
-
-        function it() {
-            if (i.jStorage) try {
-                n = u.parse(String(i.jStorage))
-            } catch (t) {
-                i.jStorage = "{}"
-            } else i.jStorage = "{}";
-            w = i.jStorage ? String(i.jStorage).length : 0;
-            n.__jstorage_meta || (n.__jstorage_meta = {});
-            n.__jstorage_meta.CRC32 || (n.__jstorage_meta.CRC32 = {})
-        }
-
-        function v() {
-            st();
-            try {
-                i.jStorage = u.stringify(n);
-                t && (t.setAttribute("jStorage", i.jStorage), t.save("jStorage"));
-                w = i.jStorage ? String(i.jStorage).length : 0
-            } catch (r) {}
-        }
-
-        function o(n) {
-            if (!n || typeof n != "string" && typeof n != "number") throw new TypeError("Key name must be string or numeric");
-            if (n == "__jstorage_meta") throw new TypeError("Reserved key name");
-            return !0
-        }
-
-        function p() {
-            var u, t, i, f, r = Infinity,
-                e = !1,
-                o = [];
-            if (clearTimeout(nt), n.__jstorage_meta && typeof n.__jstorage_meta.TTL == "object") {
-                u = +new Date;
-                i = n.__jstorage_meta.TTL;
-                f = n.__jstorage_meta.CRC32;
-                for (t in i) i.hasOwnProperty(t) && (i[t] <= u ? (delete i[t], delete f[t], delete n[t], e = !0, o.push(t)) : i[t] < r && (r = i[t]));
-                r != Infinity && (nt = setTimeout(p, r - u));
-                e && (v(), a(), c(o, "deleted"))
-            }
-        }
-
-        function rt() {
-            var t, r, i;
-            if (n.__jstorage_meta.PubSub) {
-                for (r = b, i = len = n.__jstorage_meta.PubSub.length - 1; i >= 0; i--) t = n.__jstorage_meta.PubSub[i], t[0] > b && (r = t[0], ot(t[1], t[2]));
-                b = r
-            }
-        }
-
-        function ot(n, t) {
-            if (h[n])
-                for (var i = 0, r = h[n].length; i < r; i++) h[n][i](n, u.parse(u.stringify(t)))
-        }
-
-        function st() {
-            var i, t, r;
-            if (n.__jstorage_meta.PubSub) {
-                for (i = +new Date - 2e3, t = 0, r = n.__jstorage_meta.PubSub.length; t < r; t++)
-                    if (n.__jstorage_meta.PubSub[t][0] <= i) {
-                        n.__jstorage_meta.PubSub.splice(t, n.__jstorage_meta.PubSub.length - t);
-                        break
-                    }
-                n.__jstorage_meta.PubSub.length || delete n.__jstorage_meta.PubSub
-            }
-        }
-
-        function ht(t, i) {
-            n.__jstorage_meta || (n.__jstorage_meta = {});
-            n.__jstorage_meta.PubSub || (n.__jstorage_meta.PubSub = []);
-            n.__jstorage_meta.PubSub.unshift([+new Date, t, i]);
-            v();
-            a()
-        }
-
-        function ct(n, t) {
-            for (var f = n.length, i = t ^ f, u = 0, r; f >= 4;) r = n.charCodeAt(u) & 255 | (n.charCodeAt(++u) & 255) << 8 | (n.charCodeAt(++u) & 255) << 16 | (n.charCodeAt(++u) & 255) << 24, r = (r & 65535) * 1540483477 + (((r >>> 16) * 1540483477 & 65535) << 16), r ^= r >>> 24, r = (r & 65535) * 1540483477 + (((r >>> 16) * 1540483477 & 65535) << 16), i = (i & 65535) * 1540483477 + (((i >>> 16) * 1540483477 & 65535) << 16) ^ r, f -= 4, ++u;
-            switch (f) {
-                case 3:
-                    i ^= (n.charCodeAt(u + 2) & 255) << 16;
-                case 2:
-                    i ^= (n.charCodeAt(u + 1) & 255) << 8;
-                case 1:
-                    i ^= n.charCodeAt(u) & 255;
-                    i = (i & 65535) * 1540483477 + (((i >>> 16) * 1540483477 & 65535) << 16)
-            }
-            return i ^= i >>> 13, i = (i & 65535) * 1540483477 + (((i >>> 16) * 1540483477 & 65535) << 16), i ^= i >>> 15, i >>> 0
-        }
-        var e = window.jQuery || window.$ || (window.$ = {}),
-            u = {
-                parse: window.JSON && (window.JSON.parse || window.JSON.decode) || String.prototype.evalJSON && function(n) {
-                    return String(n).evalJSON()
-                } || e.parseJSON || e.evalJSON,
-                stringify: Object.toJSON || window.JSON && (window.JSON.stringify || window.JSON.encode) || e.toJSON
-            };
-        if (!u.parse || !u.stringify) throw new Error("No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page");
-        var n = {},
-            i = {
-                jStorage: "{}"
-            },
-            t = null,
-            w = 0,
-            r = !1,
-            f = {},
-            g = !1,
-            s = 0,
-            h = {},
-            b = +new Date,
-            nt, k = {
-                isXML: function(n) {
-                    var t = (n ? n.ownerDocument || n : 0).documentElement;
-                    return t ? t.nodeName !== "HTML" : !1
-                },
-                encode: function(n) {
-                    if (!this.isXML(n)) return !1;
-                    try {
-                        return (new XMLSerializer).serializeToString(n)
-                    } catch (t) {
-                        try {
-                            return n.xml
-                        } catch (i) {}
-                    }
-                    return !1
-                },
-                decode: function(n) {
-                    var i = "DOMParser" in window && (new DOMParser).parseFromString || window.ActiveXObject && function(n) {
-                            var t = new ActiveXObject("Microsoft.XMLDOM");
-                            return t.async = "false", t.loadXML(n), t
-                        },
-                        t;
-                    return i ? (t = i.call("DOMParser" in window && new DOMParser || window, n, "text/xml"), this.isXML(t) ? t : !1) : !1
-                }
-            },
-            d = function() {};
-        e.jStorage = {
-            version: "0.3.1",
-            set: function(t, i, r) {
-                if (o(t), r = r || {}, typeof i == "undefined") return this.deleteKey(t), i;
-                if (k.isXML(i)) i = {
-                    _is_xml: !0,
-                    xml: k.encode(i)
-                };
-                else {
-                    if (typeof i == "function") return undefined;
-                    i && typeof i == "object" && (i = u.parse(u.stringify(i)))
-                }
-                return n[t] = i, n.__jstorage_meta.CRC32[t] = "2." + ct(u.stringify(i)), this.setTTL(t, r.TTL || 0), d(t, i), c(t, "updated"), i
-            },
-            get: function(t, i) {
-                return (o(t), t in n) ? n[t] && typeof n[t] == "object" && n[t]._is_xml ? k.decode(n[t].xml) : n[t] : typeof i == "undefined" ? null : i
-            },
-            deleteKey: function(t) {
-                return (o(t), t in n) ? (delete n[t], typeof n.__jstorage_meta.TTL == "object" && t in n.__jstorage_meta.TTL && delete n.__jstorage_meta.TTL[t], delete n.__jstorage_meta.CRC32[t], d(t, undefined), v(), a(), c(t, "deleted"), !0) : !1
-            },
-            setTTL: function(t, i) {
-                var r = +new Date;
-                return (o(t), i = Number(i) || 0, t in n) ? (n.__jstorage_meta.TTL || (n.__jstorage_meta.TTL = {}), i > 0 ? n.__jstorage_meta.TTL[t] = r + i : delete n.__jstorage_meta.TTL[t], v(), p(), a(), !0) : !1
-            },
-            getTTL: function(t) {
-                var r = +new Date,
-                    i;
-                return (o(t), t in n && n.__jstorage_meta.TTL && n.__jstorage_meta.TTL[t]) ? (i = n.__jstorage_meta.TTL[t] - r, i || 0) : 0
-            },
-            flush: function() {
-                return n = {
-                    __jstorage_meta: {
-                        CRC32: {}
-                    }
-                }, y("local", !0), v(), a(), c(null, "flushed"), !0
-            },
-            storageObj: function() {
-                function t() {}
-                return t.prototype = n, new t
-            },
-            index: function() {
-                var i = [];
-                for (var t in n) n.hasOwnProperty(t) && t != "__jstorage_meta" && i.push(t);
-                return i
-            },
-            storageSize: function() {
-                return w
-            },
-            currentBackend: function() {
-                return r
-            },
-            storageAvailable: function() {
-                return !!r
-            },
-            listenKeyChange: function(n, t) {
-                o(n);
-                f[n] || (f[n] = []);
-                f[n].push(t)
-            },
-            stopListening: function(n, t) {
-                if (o(n), f[n]) {
-                    if (!t) {
-                        delete f[n];
-                        return
-                    }
-                    for (var i = f[n].length - 1; i >= 0; i--) f[n][i] == t && f[n].splice(i, 1)
-                }
-            },
-            subscribe: function(n, t) {
-                if (n = (n || "").toString(), !n) throw new TypeError("Channel not defined");
-                h[n] || (h[n] = []);
-                h[n].push(t)
-            },
-            publish: function(n, t) {
-                if (n = (n || "").toString(), !n) throw new TypeError("Channel not defined");
-                ht(n, t)
-            },
-            reInit: function() {
-                tt()
-            }
-        };
-        ut()
-    }(),
-    function(n, t) {
-        function ut() {}
-
-        function bi(n, t) {
-            if (t) return "'" + n.split("'").join("\\'").split('\\"').join('\\\\\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t") + "'";
-            var i = n.charAt(0),
-                r = n.substring(1);
-            return i === "=" ? "+(" + r + ")+" : i === ":" ? "+e(" + r + ")+" : ";" + n + ";o+="
-        }
-
-        function e(n, t, i) {
-            return (n = n + "", t = t || 2, i = t - n.length, i) ? rr[t].substring(0, i) + n : n
-        }
-
-        function ur(t, u) {
-            var c = r.browser,
-                o, g = t.css("direction") == "rtl",
-                e, v;
-            if (t.parent().hasClass("k-animation-container")) e = t.parent(".k-animation-container"), v = e[0].style, e.is(":hidden") && e.show(), o = tt.test(v.width) || tt.test(v.height), o || e.css({
-                width: t.outerWidth(),
-                height: t.outerHeight(),
-                boxSizing: "content-box",
-                mozBoxSizing: "content-box",
-                webkitBoxSizing: "content-box"
-            });
-            else {
-                var y = t.css(i.support.transitions.css + "box-shadow") || t.css("box-shadow"),
-                    f = y ? y.match(vi) || [0, 0, 0, 0, 0] : [0, 0, 0, 0, 0],
-                    l = p.max(+f[3], +(f[4] || 0)),
-                    a = -f[1] + l,
-                    w = +f[1] + l,
-                    b = +f[2] + l,
-                    s = t[0].style.width,
-                    h = t[0].style.height,
-                    k = tt.test(s),
-                    d = tt.test(h);
-                c.opera && (a = w = b = 5);
-                o = k || d;
-                !k && (!u || u && s) && (s = t.outerWidth());
-                !d && (!u || u && h) && (h = t.outerHeight());
-                t.wrap(n("<div/>").addClass("k-animation-container").css({
-                    width: s,
-                    height: h,
-                    marginLeft: a * (g ? 1 : -1),
-                    paddingLeft: a,
-                    paddingRight: w,
-                    paddingBottom: b
-                }));
-                o && t.css({
-                    width: "100%",
-                    height: "100%",
-                    boxSizing: "border-box",
-                    mozBoxSizing: "border-box",
-                    webkitBoxSizing: "border-box"
-                })
-            }
-            return c.msie && p.floor(c.version) <= 7 && (t.css({
-                zoom: 1
-            }), t.children(".k-menu").width(t.width())), t.parent()
-        }
-
-        function kt(n) {
-            for (var t = 1, i = arguments.length, t = 1; t < i; t++) dt(n, arguments[t]);
-            return n
-        }
-
-        function dt(n, t) {
-            var o = i.data.ObservableArray,
-                s = i.data.DataSource,
-                u, r, f, e;
-            for (u in t) r = t[u], f = typeof r, f === a && r !== null && r.constructor !== Array && r.constructor !== o && r.constructor !== s ? r instanceof Date ? n[u] = new Date(r.getTime()) : ft(r.clone) ? n[u] = r.clone() : (e = n[u], n[u] = typeof e === a ? e || {} : {}, dt(n[u], r)) : f !== rt && (n[u] = r);
-            return n
-        }
-
-        function ct(n, i, r) {
-            for (var u in i)
-                if (i.hasOwnProperty(u) && i[u].test(n)) return u;
-            return r !== t ? r : n
-        }
-
-        function fr(n) {
-            return n.replace(/([a-z][A-Z])/g, function(n) {
-                return n.charAt(0) + "-" + n.charAt(1).toLowerCase()
-            })
-        }
-
-        function gt(n) {
-            return n.replace(/\-(\w)/g, function(n, t) {
-                return t.toUpperCase()
-            })
-        }
-
-        function er(t, r) {
-            var u = {},
-                f;
-            return document.defaultView && document.defaultView.getComputedStyle ? (f = document.defaultView.getComputedStyle(t, ""), r && n.each(r, function(n, t) {
-                u[t] = f.getPropertyValue(t)
-            })) : (f = t.currentStyle, r && n.each(r, function(n, t) {
-                u[t] = f[gt(t)]
-            })), i.size(u) || (u = f), u
-        }
-
-        function or(n) {
-            var t = 0;
-            for (var i in n) n.hasOwnProperty(i) && i != "toJSON" && t++;
-            return t
-        }
-
-        function sr(n, t, i) {
-            var u, f, e, o;
-            return (t || (t = "offset"), u = n[t](), f = r.mobileOS, r.touch && f.ios && f.flatVersion < 410 && (e = t == "offset" ? u : n.offset(), o = u.left == e.left && u.top == e.top, o)) ? {
-                top: u.top - window.scrollY,
-                left: u.left - window.scrollX
-            } : (r.browser.msie && (r.pointers || r.msPointers) && !i && (u.top -= window.pageYOffset - document.documentElement.scrollTop, u.left -= window.pageXOffset - document.documentElement.scrollLeft), u)
-        }
-
-        function hr(n) {
-            var t = {};
-            return d(typeof n == "string" ? n.split(" ") : n, function(n) {
-                t[n] = this
-            }), t
-        }
-
-        function cr(n) {
-            return new i.effects.Element(n)
-        }
-
-        function ti(n, t, i, r) {
-            return typeof n === u && (ft(t) && (r = t, t = 400, i = !1), ft(i) && (r = i, i = !1), typeof t === pt && (i = t, t = 400), n = {
-                effects: n,
-                duration: t,
-                reverse: i,
-                complete: r
-            }), s({
-                effects: {},
-                duration: 400,
-                reverse: !1,
-                init: g,
-                teardown: g,
-                hide: !1
-            }, n, {
-                completeCallback: n.complete,
-                complete: g
-            })
-        }
-
-        function ii(t, i, r, u, f) {
-            for (var e = 0, s = t.length, o; e < s; e++) o = n(t[e]), o.queue(function() {
-                h.promise(o, ti(i, r, u, f))
-            });
-            return t
-        }
-
-        function lr(n, t, i, r, u, f) {
-            return h.transitionPromise(n, t, ti(i, r, u, f))
-        }
-
-        function ar(n, t, i, r) {
-            return t && (t = t.split(" "), d(t, function(t, i) {
-                n.toggleClass(i, r)
-            })), n
-        }
-
-        function wr(n) {
-            return ("" + n).replace(vr, "&amp;").replace(yr, "&lt;").replace(pr, "&gt;")
-        }
-
-        function at(n, r) {
-            var u;
-            return r.indexOf("data") === 0 && (r = r.substring(4), r = r.charAt(0).toLowerCase() + r.substring(1)), r = r.replace(gr, "-$1"), u = n.getAttribute("data-" + i.ns + r), u === null ? u = t : u === "null" ? u = null : u === "true" ? u = !0 : u === "false" ? u = !1 : yi.test(u) ? u = parseFloat(u) : kr.test(u) && !dr.test(u) && (u = new Function("return (" + u + ")")()), u
-        }
-
-        function fi(r, u) {
-            var o = {},
-                e, f;
-            for (e in u) f = at(r, e), f !== t && (br.test(e) && (f = i.template(n("#" + f).html())), o[e] = f);
-            return o
-        }
-
-        function nu(t, i) {
-            return n.contains(t, i) ? -1 : 1
-        }
-
-        function tu() {
-            var t = n(this);
-            return n.inArray(t.attr("data-role"), ["slider", "rangeslider"]) > 0 || t.is(":visible")
-        }
-
-        function iu(n, t) {
-            var i = n.nodeName.toLowerCase();
-            return (/input|select|textarea|button|object/.test(i) ? !n.disabled : "a" === i ? n.href || t : t) && ru(n)
-        }
-
-        function ru(t) {
-            return !n(t).parents().addBack().filter(function() {
-                return n.css(this, "visibility") === "hidden" || n.expr.filters.hidden(this)
-            }).length
-        }
-
-        function o(n, t) {
-            return new o.fn.init(n, t)
-        }
-        var i = window.kendo = window.kendo || {
-                cultures: {}
-            },
-            s = n.extend,
-            d = n.each,
-            li = n.isArray,
-            ot = n.proxy,
-            g = n.noop,
-            p = Math,
-            v, nt = window.JSON || {},
-            r = {},
-            tt = /%/,
-            ai = /\{(\d+)(:[^\}]+)?\}/g,
-            vi = /(\d+(?:\.?)\d*)px\s*(\d+(?:\.?)\d*)px\s*(\d+(?:\.?)\d*)px\s*(\d+)?/i,
-            yi = /^(\+|-?)\d+(\.?)\d*$/,
-            c = "function",
-            u = "string",
-            l = "number",
-            a = "object",
-            it = "null",
-            pt = "boolean",
-            rt = "undefined",
-            wt = {},
-            bt = {},
-            st = [].slice,
-            y = window.Globalize,
-            ni, h, lt, ri, ui, w, ei, oi, hi, vt, et, ci, yt, k;
-        i.version = "2013.3.1324";
-        ut.extend = function(n) {
-            var r = function() {},
-                t, u = this,
-                i = n && n.init ? n.init : function() {
-                    u.apply(this, arguments)
-                },
-                f;
-            r.prototype = u.prototype;
-            f = i.fn = i.prototype = new r;
-            for (t in n) f[t] = typeof n[t] !== a || n[t] instanceof Array || n[t] === null ? n[t] : s(!0, {}, r.prototype[t], n[t]);
-            return f.constructor = i, i.extend = u.extend, i
-        };
-        ut.prototype._initOptions = function(n) {
-            this.options = kt({}, this.options, n)
-        };
-        var ft = i.isFunction = function(n) {
-                return typeof n == "function"
-            },
-            pi = function() {
-                this._defaultPrevented = !0
-            },
-            wi = function() {
-                return this._defaultPrevented === !0
-            },
-            ht = ut.extend({
-                init: function() {
-                    this._events = {}
-                },
-                bind: function(n, i, r) {
-                    var f = this,
-                        e, s = typeof n === u ? [n] : n,
-                        h, l, o, v = typeof i === c,
-                        a;
-                    if (i === t) {
-                        for (e in n) f.bind(e, n[e]);
-                        return f
-                    }
-                    for (e = 0, h = s.length; e < h; e++) n = s[e], o = v ? i : i[n], o && (r && (l = o, o = function() {
-                        f.unbind(n, o);
-                        l.apply(f, arguments)
-                    }), a = f._events[n] = f._events[n] || [], a.push(o));
-                    return f
-                },
-                one: function(n, t) {
-                    return this.bind(n, t, !0)
-                },
-                first: function(n, t) {
-                    for (var r = this, e = typeof n === u ? [n] : n, f, h = typeof t === c, s, i = 0, o = e.length; i < o; i++) n = e[i], f = h ? t : t[n], f && (s = r._events[n] = r._events[n] || [], s.unshift(f));
-                    return r
-                },
-                trigger: function(n, t) {
-                    var u = this,
-                        i = u._events[n],
-                        r, f;
-                    if (i) {
-                        for (t = t || {}, t.sender = u, t._defaultPrevented = !1, t.preventDefault = pi, t.isDefaultPrevented = wi, i = i.slice(), r = 0, f = i.length; r < f; r++) i[r].call(u, t);
-                        return t._defaultPrevented === !0
-                    }
-                    return !1
-                },
-                unbind: function(n, i) {
-                    var u = this,
-                        f = u._events[n],
-                        r;
-                    if (n === t) u._events = {};
-                    else if (f)
-                        if (i)
-                            for (r = f.length - 1; r >= 0; r--) f[r] === i && f.splice(r, 1);
-                        else u._events[n] = [];
-                    return u
-                }
-            });
-        var ki = /^\w+/,
-            di = /\$\{([^}]*)\}/g,
-            gi = /\\\}/g,
-            nr = /__CURLY__/g,
-            tr = /\\#/g,
-            ir = /__SHARP__/g,
-            rr = ["", "0", "00", "000", "0000"];
-        v = {
-                paramName: "data",
-                useWithBlock: !0,
-                render: function(n, t) {
-                    for (var u = "", i = 0, r = t.length; i < r; i++) u += n(t[i]);
-                    return u
-                },
-                compile: function(t, r) {
-                    var h = s({}, this, r),
-                        c = h.paramName,
-                        a = c.match(ki)[0],
-                        l = h.useWithBlock,
-                        u = "var o,e=kendo.htmlEncode;",
-                        o, e, f;
-                    if (ft(t)) return t.length === 2 ? function(i) {
-                        return t(n, {
-                            data: i
-                        }).join("")
-                    } : t;
-                    for (u += l ? "with(" + c + "){" : "", u += "o=", e = t.replace(gi, "__CURLY__").replace(di, "#=e($1)#").replace(nr, "}").replace(tr, "__SHARP__").split("#"), f = 0; f < e.length; f++) u += bi(e[f], f % 2 == 0);
-                    u += l ? ";}" : ";";
-                    u += "return o;";
-                    u = u.replace(ir, "#");
-                    try {
-                        return o = new Function(a, u), o._slotCount = Math.floor(e.length / 2), o
-                    } catch (v) {
-                        throw new Error(i.format("Invalid template:'{0}' Generated code:'{1}'", t, u));
-                    }
-                }
-            },
-            function() {
-                function o(n) {
-                    return f.lastIndex = 0, f.test(n) ? '"' + n.replace(f, function(n) {
-                        var t = s[n];
-                        return typeof t === u ? t : "\\u" + ("0000" + n.charCodeAt(0).toString(16)).slice(-4)
-                    }) + '"' : '"' + n + '"'
-                }
-
-                function r(f, e) {
-                    var v, w, y, k, d = n,
-                        p, s = e[f],
-                        b;
-                    if (s && typeof s === a && typeof s.toJSON === c && (s = s.toJSON(f)), typeof t === c && (s = t.call(e, f, s)), b = typeof s, b === u) return o(s);
-                    if (b === l) return isFinite(s) ? String(s) : it;
-                    if (b === pt || b === it) return String(s);
-                    if (b === a) {
-                        if (!s) return it;
-                        if (n += i, p = [], h.apply(s) === "[object Array]") {
-                            for (k = s.length, v = 0; v < k; v++) p[v] = r(v, s) || it;
-                            return y = p.length === 0 ? "[]" : n ? "[\n" + n + p.join(",\n" + n) + "\n" + d + "]" : "[" + p.join(",") + "]", n = d, y
-                        }
-                        if (t && typeof t === a)
-                            for (k = t.length, v = 0; v < k; v++) typeof t[v] === u && (w = t[v], y = r(w, s), y && p.push(o(w) + (n ? ": " : ":") + y));
-                        else
-                            for (w in s) Object.hasOwnProperty.call(s, w) && (y = r(w, s), y && p.push(o(w) + (n ? ": " : ":") + y));
-                        return y = p.length === 0 ? "{}" : n ? "{\n" + n + p.join(",\n" + n) + "\n" + d + "}" : "{" + p.join(",") + "}", n = d, y
-                    }
-                }
-                var f = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-                    n, i, s = {
-                        "\b": "\\b",
-                        "\t": "\\t",
-                        "\n": "\\n",
-                        "\f": "\\f",
-                        "\r": "\\r",
-                        '"': '\\"',
-                        "\\": "\\\\"
-                    },
-                    t, h = {}.toString;
-                typeof Date.prototype.toJSON !== c && (Date.prototype.toJSON = function() {
-                    var n = this;
-                    return isFinite(n.valueOf()) ? e(n.getUTCFullYear(), 4) + "-" + e(n.getUTCMonth() + 1) + "-" + e(n.getUTCDate()) + "T" + e(n.getUTCHours()) + ":" + e(n.getUTCMinutes()) + ":" + e(n.getUTCSeconds()) + "Z" : null
-                }, String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function() {
-                    return this.valueOf()
-                });
-                typeof nt.stringify !== c && (nt.stringify = function(f, e, o) {
-                    var s;
-                    if (n = "", i = "", typeof o === l)
-                        for (s = 0; s < o; s += 1) i += " ";
-                    else typeof o === u && (i = o);
-                    if (t = e, e && typeof e !== c && (typeof e !== a || typeof e.length !== l)) throw new Error("JSON.stringify");
-                    return r("", {
-                        "": f
-                    })
-                })
-            }(),
-            function() {
-                function v(n) {
-                    if (n) {
-                        if (n.numberFormat) return n;
-                        if (typeof n === u) {
-                            var t = i.cultures;
-                            return t[n] || t[n.split("-")[0]] || null
-                        }
-                        return null
-                    }
-                    return null
-                }
-
-                function w(n) {
-                    return n && (n = v(n)), n || i.cultures.current
-                }
-
-                function rt(n) {
-                    n.groupSizes = n.groupSize;
-                    n.percent.groupSizes = n.percent.groupSize;
-                    n.currency.groupSizes = n.currency.groupSize
-                }
-
-                function ut(n, i, r) {
-                    r = w(r);
-                    var u = r.calendars.standard,
-                        f = u.days,
-                        o = u.months;
-                    return i = u.patterns[i] || i, i.replace(d, function(i) {
-                        var r;
-                        return i === "d" ? r = n.getDate() : i === "dd" ? r = e(n.getDate()) : i === "ddd" ? r = f.namesAbbr[n.getDay()] : i === "dddd" ? r = f.names[n.getDay()] : i === "M" ? r = n.getMonth() + 1 : i === "MM" ? r = e(n.getMonth() + 1) : i === "MMM" ? r = o.namesAbbr[n.getMonth()] : i === "MMMM" ? r = o.names[n.getMonth()] : i === "yy" ? r = e(n.getFullYear() % 100) : i === "yyyy" ? r = e(n.getFullYear(), 4) : i === "h" ? r = n.getHours() % 12 || 12 : i === "hh" ? r = e(n.getHours() % 12 || 12) : i === "H" ? r = n.getHours() : i === "HH" ? r = e(n.getHours()) : i === "m" ? r = n.getMinutes() : i === "mm" ? r = e(n.getMinutes()) : i === "s" ? r = n.getSeconds() : i === "ss" ? r = e(n.getSeconds()) : i === "f" ? r = p.floor(n.getMilliseconds() / 100) : i === "ff" ? r = p.floor(n.getMilliseconds() / 10) : i === "fff" ? r = n.getMilliseconds() : i === "tt" && (r = n.getHours() < 12 ? u.AM[0] : u.PM[0]), r !== t ? r : i.slice(1, i.length - 1)
-                    })
-                }
-
-                function ft(n, i, u) {
-                    u = w(u);
-                    var l = u.numberFormat,
-                        ot = l.groupSize[0],
-                        lt = l[c],
-                        vt = l[f],
-                        at = l.decimals,
-                        kt = l.pattern[0],
-                        dt = [],
-                        yt, ft, st, pt, wt, et = n < 0,
-                        b, p, rt, ei, gt = r,
-                        y = r,
-                        e, ut, d, ni, ri, it, v, a, bt, ti, ui, ii, fi, ht = -1,
-                        ct;
-                    if (n === t) return r;
-                    if (!isFinite(n)) return n;
-                    if (!i) return u.name.length ? n.toLocaleString() : n.toString();
-                    if (wt = g.exec(i), wt) {
-                        if (i = wt[1].toLowerCase(), ft = i === "c", st = i === "p", (ft || st) && (l = ft ? l.currency : l.percent, ot = l.groupSize[0], lt = l[c], vt = l[f], at = l.decimals, yt = l.symbol, kt = l.pattern[et ? 0 : 1]), pt = wt[2], pt && (at = +pt), i === "e") return pt ? n.toExponential(at) : n.toExponential();
-                        if (st && (n *= 100), n = h(n, at), et = n < 0, n = n.split(f), b = n[0], p = n[1], et && (b = b.substring(1)), y = b, rt = b.length, rt >= ot)
-                            for (y = r, e = 0; e < rt; e++) e > 0 && (rt - e) % ot == 0 && (y += lt), y += b.charAt(e);
-                        if (p && (y += vt + p), i === "n" && !et) return y;
-                        for (n = r, e = 0, ut = kt.length; e < ut; e++) d = kt.charAt(e), n += d === "n" ? y : d === "$" || d === "%" ? yt : d;
-                        return n
-                    }
-                    if (et && (n = -n), (i.indexOf("'") > -1 || i.indexOf('"') > -1 || i.indexOf("\\") > -1) && (i = i.replace(nt, function(n) {
-                            var t = n.charAt(0).replace("\\", ""),
-                                i = n.slice(1).replace(t, "");
-                            return dt.push(i), k
-                        })), i = i.split(";"), et && i[1]) i = i[1], ri = !0;
-                    else if (n === 0) {
-                        if (i = i[2] || i[0], i.indexOf(o) == -1 && i.indexOf(s) == -1) return i
-                    } else i = i[0];
-                    if (ui = i.indexOf("%"), ii = i.indexOf("$"), st = ui != -1, ft = ii != -1, st && (n *= 100), ft && i[ii - 1] === "\\" && (i = i.split("\\").join(""), ft = !1), (ft || st) && (l = ft ? l.currency : l.percent, ot = l.groupSize[0], lt = l[c], vt = l[f], at = l.decimals, yt = l.symbol), ni = i.indexOf(c) > -1, ni && (i = i.replace(tt, r)), it = i.indexOf(f), ut = i.length, it != -1 ? (p = n.toString().split("e"), p = p[1] ? h(n, Math.abs(p[1])) : p[0], p = p.split(f)[1] || r, a = i.lastIndexOf(s) - it, v = i.lastIndexOf(o) - it, bt = a > -1, ti = v > -1, e = p.length, bt || ti || (i = i.substring(0, it) + i.substring(it + 1), ut = i.length, it = -1, e = 0), bt && a > v ? e = a : v > a && (ti && e > v ? e = v : bt && e < a && (e = a)), e > -1 && (n = h(n, e))) : n = h(n), v = i.indexOf(o), fi = a = i.indexOf(s), ht = v == -1 && a != -1 ? a : v != -1 && a == -1 ? v : v > a ? a : v, v = i.lastIndexOf(o), a = i.lastIndexOf(s), ct = v == -1 && a != -1 ? a : v != -1 && a == -1 ? v : v > a ? v : a, ht == ut && (ct = ht), ht != -1) {
-                        if (y = n.toString().split(f), b = y[0], p = y[1] || r, rt = b.length, ei = p.length, et && n * -1 >= 0 && (et = !1), ni)
-                            if (rt === ot && rt < it - fi) b = lt + b;
-                            else if (rt > ot) {
-                            for (y = r, e = 0; e < rt; e++) e > 0 && (rt - e) % ot == 0 && (y += lt), y += b.charAt(e);
-                            b = y
-                        }
-                        for (n = i.substring(0, ht), et && !ri && (n += "-"), e = ht; e < ut; e++) {
-                            if (d = i.charAt(e), it == -1) {
-                                if (ct - e < rt) {
-                                    n += b;
-                                    break
-                                }
-                            } else if (a != -1 && a < e && (gt = r), it - e <= rt && it - e > -1 && (n += b, e = it), it === e) {
-                                n += (p ? vt : r) + p;
-                                e += ct - it + 1;
-                                continue
-                            }
-                            d === s ? (n += d, gt = d) : d === o && (n += gt)
-                        }
-                        if (ct >= ht && (n += i.substring(ct + 1)), ft || st) {
-                            for (y = r, e = 0, ut = n.length; e < ut; e++) d = n.charAt(e), y += d === "$" || d === "%" ? yt : d;
-                            n = y
-                        }
-                        if (ut = dt.length, ut)
-                            for (e = 0; e < ut; e++) n = n.replace(k, dt[e])
-                    }
-                    return n
-                }
-                var d = /dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|HH|H|hh|h|mm|m|fff|ff|f|tt|ss|s|"[^"]*"|'[^']*'/g,
-                    g = /^(n|c|p|e)(\d*)$/i,
-                    nt = /(\\.)|(['][^']*[']?)|(["][^"]*["]?)/g,
-                    tt = /\,/g,
-                    r = "",
-                    f = ".",
-                    c = ",",
-                    o = "#",
-                    s = "0",
-                    k = "??",
-                    a = "en-US",
-                    it = {}.toString;
-                i.cultures["en-US"] = {
-                    name: a,
-                    numberFormat: {
-                        pattern: ["-n"],
-                        decimals: 2,
-                        ",": ",",
-                        ".": ".",
-                        groupSize: [3],
-                        percent: {
-                            pattern: ["-n %", "n %"],
-                            decimals: 2,
-                            ",": ",",
-                            ".": ".",
-                            groupSize: [3],
-                            symbol: "%"
-                        },
-                        currency: {
-                            pattern: ["($n)", "$n"],
-                            decimals: 2,
-                            ",": ",",
-                            ".": ".",
-                            groupSize: [3],
-                            symbol: "$"
-                        }
-                    },
-                    calendars: {
-                        standard: {
-                            days: {
-                                names: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
-                                namesAbbr: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
-                                namesShort: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
-                            },
-                            months: {
-                                names: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
-                                namesAbbr: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
-                            },
-                            AM: ["AM", "am", "AM"],
-                            PM: ["PM", "pm", "PM"],
-                            patterns: {
-                                d: "M/d/yyyy",
-                                D: "dddd, MMMM dd, yyyy",
-                                F: "dddd, MMMM dd, yyyy h:mm:ss tt",
-                                g: "M/d/yyyy h:mm tt",
-                                G: "M/d/yyyy h:mm:ss tt",
-                                m: "MMMM dd",
-                                M: "MMMM dd",
-                                s: "yyyy'-'MM'-'ddTHH':'mm':'ss",
-                                t: "h:mm tt",
-                                T: "h:mm:ss tt",
-                                u: "yyyy'-'MM'-'dd HH':'mm':'ss'Z'",
-                                y: "MMMM, yyyy",
-                                Y: "MMMM, yyyy"
-                            },
-                            "/": "/",
-                            ":": ":",
-                            firstDay: 0,
-                            twoDigitYearMax: 2029
-                        }
-                    }
-                };
-                i.culture = function(n) {
-                    var u = i.cultures,
-                        r;
-                    if (n !== t) r = v(n) || u[a], r.calendar = r.calendars.standard, u.current = r, y && rt(r.numberFormat);
-                    else return u.current
-                };
-                i.findCulture = v;
-                i.getCulture = w;
-                i.culture(a);
-                var et = 9e15,
-                    h = function(n, t) {
-                        var i = Math.pow(10, t || 0),
-                            r = Math.round(n * i);
-                        return r > et ? n.toFixed(t) : (r / i).toFixed(t)
-                    },
-                    b = function(n, i, r) {
-                        if (i) {
-                            if (it.call(n) === "[object Date]") return ut(n, i, r);
-                            if (typeof n === l) return ft(n, i, r)
-                        }
-                        return n !== t ? n : ""
-                    };
-                y && (b = function(t, i, r) {
-                    return n.isPlainObject(r) && (r = r.name), y.format(t, i, r)
-                });
-                i.format = function(n) {
-                    var t = arguments;
-                    return n.replace(ai, function(n, i, r) {
-                        var u = t[parseInt(i, 10) + 1];
-                        return b(u, r ? r.substring(1) : "")
-                    })
-                };
-                i._extractFormat = function(n) {
-                    return n.slice(0, 3) === "{0:" && (n = n.slice(3, n.length - 1)), n
-                };
-                i._activeElement = function() {
-                    try {
-                        return document.activeElement
-                    } catch (n) {
-                        return document.documentElement.activeElement
-                    }
-                };
-                i._round = h;
-                i.toString = b
-            }(),
-            function() {
-                function r(n, t, i) {
-                    return !(n >= t && n <= i)
-                }
-
-                function b(n) {
-                    return n.charAt(0)
-                }
-
-                function s(t) {
-                    return n.map(t, b)
-                }
-
-                function k(n, t) {
-                    t || n.getHours() !== 23 || n.setHours(n.getHours() + 2)
-                }
-
-                function d(n) {
-                    for (var t = 0, r = n.length, i = []; t < r; t++) i[t] = (n[t] + "").toLowerCase();
-                    return i
-                }
-
-                function h(n) {
-                    var t = {};
-                    for (var i in n) t[i] = d(n[i]);
-                    return t
-                }
-
-                function g(n, i, u) {
-                    if (!n) return null;
-                    var p = function(n) {
-                            for (var t = 0; i[rt] === n;) t++, rt++;
-                            return t > 0 && (rt -= 1), t
-                        },
-                        nt = function(t) {
-                            var r = e[t] || new RegExp("^\\d{1," + t + "}"),
-                                i = n.substr(b, t).match(r);
-                            return i ? (i = i[0], b += i.length, parseInt(i, 10)) : null
-                        },
-                        ht = function(t, i) {
-                            for (var r = 0, o = t.length, f, e, u; r < o; r++)
-                                if (f = t[r], e = f.length, u = n.substr(b, e), i && (u = u.toLowerCase()), u == f) return b += e, r + 1;
-                            return null
-                        },
-                        ft = function() {
-                            var t = !1;
-                            return n.charAt(b) === i[rt] && (b++, t = !0), t
-                        },
-                        y = u.calendars.standard,
-                        c = null,
-                        tt = null,
-                        w = null,
-                        o = null,
-                        it = null,
-                        ut = null,
-                        d = null,
-                        rt = 0,
-                        b = 0,
-                        yt = !1,
-                        pt = new Date,
-                        ct = y.twoDigitYearMax || 2029,
-                        et = pt.getFullYear(),
-                        l, f, dt, wt, bt, kt, gt, g, lt, at, vt, ot, ni, st;
-                    for (i || (i = "d"), wt = y.patterns[i], wt && (i = wt), i = i.split(""), dt = i.length; rt < dt; rt++)
-                        if (l = i[rt], yt) l === "'" ? yt = !1 : ft();
-                        else if (l === "d") {
-                        if (f = p("d"), y._lowerDays || (y._lowerDays = h(y.days)), w = f < 3 ? nt(2) : ht(y._lowerDays[f == 3 ? "namesAbbr" : "names"], !0), w === null || r(w, 1, 31)) return null
-                    } else if (l === "M") {
-                        if (f = p("M"), y._lowerMonths || (y._lowerMonths = h(y.months)), tt = f < 3 ? nt(2) : ht(y._lowerMonths[f == 3 ? "namesAbbr" : "names"], !0), tt === null || r(tt, 1, 12)) return null;
-                        tt -= 1
-                    } else if (l === "y") {
-                        if (f = p("y"), c = nt(f), c === null) return null;
-                        f == 2 && (typeof ct == "string" && (ct = et + parseInt(ct, 10)), c = et - et % 100 + c, c > ct && (c -= 100))
-                    } else if (l === "h") {
-                        if (p("h"), o = nt(2), o == 12 && (o = 0), o === null || r(o, 0, 11)) return null
-                    } else if (l === "H") {
-                        if (p("H"), o = nt(2), o === null || r(o, 0, 23)) return null
-                    } else if (l === "m") {
-                        if (p("m"), it = nt(2), it === null || r(it, 0, 59)) return null
-                    } else if (l === "s") {
-                        if (p("s"), ut = nt(2), ut === null || r(ut, 0, 59)) return null
-                    } else if (l === "f") {
-                        if (f = p("f"), st = n.substr(b, f).match(e[3]), d = nt(f), d !== null && (st = st[0].length, st < 3 && (d *= Math.pow(10, 3 - st)), f > 3 && (d = parseInt(d.toString().substring(0, 3), 10))), d === null || r(d, 0, 999)) return null
-                    } else if (l === "t") {
-                        if (f = p("t"), lt = y.AM, at = y.PM, f === 1 && (lt = s(lt), at = s(at)), bt = ht(at), !bt && !ht(lt)) return null
-                    } else if (l === "z") {
-                        if (kt = !0, f = p("z"), n.substr(b, 1) === "Z") {
-                            if (!gt) return null;
-                            ft();
-                            continue
-                        }
-                        if ((g = n.substr(b, 6).match(f > 2 ? v : a), !g) || (g = g[0], b = g.length, g = g.split(":"), vt = parseInt(g[0], 10), r(vt, -12, 13)) || f > 2 && (ot = parseInt(g[1], 10), isNaN(ot) || r(ot, 0, 59))) return null
-                    } else if (l === "T") gt = ft();
-                    else if (l === "'") yt = !0, ft();
-                    else if (!ft()) return null;
-                    return (ni = o !== null || it !== null || ut || null, c === null && tt === null && w === null && ni ? (c = et, tt = pt.getMonth(), w = pt.getDate()) : (c === null && (c = et), w === null && (w = 1)), bt && o < 12 && (o += 12), kt ? (vt && (o += -vt), ot && (it += -ot), n = new Date(Date.UTC(c, tt, w, o, it, ut, d))) : (n = new Date(c, tt, w, o, it, ut, d), k(n, o)), c < 100 && n.setFullYear(c), n.getDate() !== w && kt === t) ? null : n
-                }
-                var u = /\u00A0/g,
-                    c = /[eE][\-+]?[0-9]+/,
-                    a = /[+|\-]\d{1,2}/,
-                    v = /[+|\-]\d{1,2}:\d{2}/,
-                    p = /^\/Date\((.*?)\)\/$/,
-                    w = /[+-]{1}\d+/,
-                    f = ["G", "g", "d", "F", "D", "y", "m", "T", "t"],
-                    e = {
-                        2: /^\d{1,2}/,
-                        3: /^\d{1,3}/,
-                        4: /^\d{4}/
-                    },
-                    o = {}.toString;
-                i.parseDate = function(n, t, r) {
-                    if (o.call(n) === "[object Date]") return n;
-                    var e = 0,
-                        u = null,
-                        s, c, h;
-                    if (n && n.indexOf("/D") === 0 && (u = p.exec(n), u)) return u = u[1], h = w.exec(u), u = parseInt(u, 10), h && (u -= parseInt(h[0], 10) * i.date.MS_PER_MINUTE), new Date(u);
-                    if (r = i.getCulture(r), !t) {
-                        for (t = [], c = r.calendar.patterns, s = f.length; e < s; e++) t[e] = c[f[e]];
-                        e = 0;
-                        t = ["yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM/dd", "ddd MMM dd yyyy HH:mm:ss", "yyyy-MM-ddTHH:mm:ss.fffffffzzz", "yyyy-MM-ddTHH:mm:ss.fffzzz", "yyyy-MM-ddTHH:mm:sszzz", "yyyy-MM-ddTHH:mmzzz", "yyyy-MM-ddTHH:mmzz", "yyyy-MM-ddTHH:mm:ss", "yyyy-MM-ddTHH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd"].concat(t)
-                    }
-                    for (t = li(t) ? t : [t], s = t.length; e < s; e++)
-                        if (u = g(n, t[e], r), u) return u;
-                    return u
-                };
-                i.parseInt = function(n, t) {
-                    var r = i.parseFloat(n, t);
-                    return r && (r = r | 0), r
-                };
-                i.parseFloat = function(n, t, r) {
-                    if (!n && n !== 0) return null;
-                    if (typeof n === l) return n;
-                    n = n.toString();
-                    t = i.getCulture(t);
-                    var f = t.numberFormat,
-                        h = f.percent,
-                        a = f.currency,
-                        s = a.symbol,
-                        v = h.symbol,
-                        e = n.indexOf("-"),
-                        o, y;
-                    return c.test(n) ? (n = parseFloat(n.replace(f["."], ".")), isNaN(n) && (n = null), n) : e > 0 ? null : (e = e > -1, n.indexOf(s) > -1 || r && r.toLowerCase().indexOf("c") > -1 ? (f = a, o = f.pattern[0].replace("$", s).split("n"), n.indexOf(o[0]) > -1 && n.indexOf(o[1]) > -1 && (n = n.replace(o[0], "").replace(o[1], ""), e = !0)) : n.indexOf(v) > -1 && (y = !0, f = h, s = v), n = n.replace("-", "").replace(s, "").replace(u, " ").split(f[","].replace(u, " ")).join("").replace(f["."], "."), n = parseFloat(n), isNaN(n) ? n = null : e && (n *= -1), n && y && (n /= 100), n)
-                };
-                y && (i.parseDate = function(n, t, i) {
-                    return o.call(n) === "[object Date]" ? n : y.parseDate(n, t, i)
-                }, i.parseFloat = function(i, r) {
-                    return typeof i === l ? i : i === t || i === null ? null : (n.isPlainObject(r) && (r = r.name), i = y.parseFloat(i, r), isNaN(i) ? null : i)
-                })
-            }(),
-            function() {
-                var e, i, f, c;
-                r.scrollbar = function() {
-                    var n = document.createElement("div"),
-                        t;
-                    return n.style.cssText = "overflow:scroll;overflow-x:hidden;zoom:1;clear:both", n.innerHTML = "&nbsp;", document.body.appendChild(n), t = n.offsetWidth - n.scrollWidth, document.body.removeChild(n), t
-                };
-                r.isRtl = function(t) {
-                    return n(t).closest(".k-rtl").length > 0
-                };
-                e = document.createElement("table");
-                try {
-                    e.innerHTML = "<tr><td><\/td><\/tr>";
-                    r.tbodyInnerHtml = !0
-                } catch (l) {
-                    r.tbodyInnerHtml = !1
-                }
-                r.touch = "ontouchstart" in window;
-                r.msPointers = window.MSPointerEvent;
-                r.pointers = window.PointerEvent;
-                var o = r.transitions = !1,
-                    h = r.transforms = !1,
-                    s = "HTMLElement" in window ? HTMLElement.prototype : [];
-                r.hasHW3D = "WebKitCSSMatrix" in window && "m11" in new window.WebKitCSSMatrix || "MozPerspective" in document.documentElement.style || "msPerspective" in document.documentElement.style;
-                d(["Moz", "webkit", "O", "ms"], function() {
-                    var t = this.toString(),
-                        i = typeof e.style[t + "Transition"] === u,
-                        n;
-                    if (i || typeof e.style[t + "Transform"] === u) return n = t.toLowerCase(), h = {
-                        css: n != "ms" ? "-" + n + "-" : "",
-                        prefix: t,
-                        event: n === "o" || n === "webkit" ? n : ""
-                    }, i && (o = h, o.event = o.event ? o.event + "TransitionEnd" : "transitionend"), !1
-                });
-                e = null;
-                r.transforms = h;
-                r.transitions = o;
-                r.devicePixelRatio = window.devicePixelRatio === t ? 1 : window.devicePixelRatio;
-                try {
-                    r.screenWidth = window.outerWidth || window.screen ? window.screen.availWidth : window.innerWidth;
-                    r.screenHeight = window.outerHeight || window.screen ? window.screen.availHeight : window.innerHeight
-                } catch (l) {
-                    r.screenWidth = window.screen.availWidth;
-                    r.screenHeight = window.screen.availHeight
-                }
-                r.detectOS = function(n) {
-                    var t = !1,
-                        u, f = [],
-                        o = !/mobile safari/i.test(n),
-                        e = {
-                            fire: /(Silk)\/(\d+)\.(\d+(\.\d+)?)/,
-                            android: /(Android|Android.*(?:Opera|Firefox).*?\/)\s*(\d+)\.(\d+(\.\d+)?)/,
-                            iphone: /(iPhone|iPod).*OS\s+(\d+)[\._]([\d\._]+)/,
-                            ipad: /(iPad).*OS\s+(\d+)[\._]([\d_]+)/,
-                            meego: /(MeeGo).+NokiaBrowser\/(\d+)\.([\d\._]+)/,
-                            webos: /(webOS)\/(\d+)\.(\d+(\.\d+)?)/,
-                            blackberry: /(BlackBerry|BB10).*?Version\/(\d+)\.(\d+(\.\d+)?)/,
-                            playbook: /(PlayBook).*?Tablet\s*OS\s*(\d+)\.(\d+(\.\d+)?)/,
-                            wp: /(Windows Phone(?: OS)?)\s(\d+)\.(\d+(\.\d+)?)/,
-                            windows: /(MSIE)\s+(\d+)\.(\d+(\.\d+)?)/,
-                            tizen: /(tizen).*?Version\/(\d+)\.(\d+(\.\d+)?)/i,
-                            sailfish: /(sailfish).*rv:(\d+)\.(\d+(\.\d+)?).*firefox/i,
-                            ffos: /(Mobile).*rv:(\d+)\.(\d+(\.\d+)?).*Firefox/
-                        },
-                        s = {
-                            ios: /^i(phone|pad|pod)$/i,
-                            android: /^android|fire$/i,
-                            blackberry: /^blackberry|playbook/i,
-                            windows: /windows/,
-                            wp: /wp/,
-                            flat: /sailfish|ffos|tizen/i,
-                            meego: /meego/
-                        },
-                        h = {
-                            tablet: /playbook|ipad|fire/i
-                        },
-                        c = {
-                            omini: /Opera\sMini/i,
-                            omobile: /Opera\sMobi/i,
-                            firefox: /Firefox|Fennec/i,
-                            mobilesafari: /version\/.*safari/i,
-                            chrome: /chrome/i,
-                            webkit: /webkit/i,
-                            ie: /MSIE|Windows\sPhone/i
-                        };
-                    for (var i in e)
-                        if (e.hasOwnProperty(i) && (f = n.match(e[i]), f)) {
-                            if (i == "windows" && "plugins" in navigator) return !1;
-                            t = {};
-                            t.device = i;
-                            t.tablet = ct(i, h, !1);
-                            t.browser = ct(n, c, "default");
-                            t.name = ct(i, s);
-                            t[t.name] = !0;
-                            t.majorVersion = f[2];
-                            t.minorVersion = f[3].replace("_", ".");
-                            u = t.minorVersion.replace(".", "").substr(0, 2);
-                            t.flatVersion = t.majorVersion + u + new Array(3 - (u.length < 3 ? u.length : 2)).join("0");
-                            t.appMode = window.navigator.standalone || /file|local|wmapp/.test(window.location.protocol) || typeof PhoneGap !== rt || typeof cordova !== rt;
-                            t.android && (r.devicePixelRatio < 1.5 && t.flatVersion < 400 || o) && (r.screenWidth > 800 || r.screenHeight > 800) && (t.tablet = i);
-                            break
-                        }
-                    return t
-                };
-                i = r.mobileOS = r.detectOS(navigator.userAgent);
-                r.wpDevicePixelRatio = i.wp ? screen.width / 320 : 0;
-                r.kineticScrollNeeded = i && (r.touch || r.msPointers || r.pointers);
-                r.hasNativeScrolling = !1;
-                (i.ios && i.majorVersion > 4 || i.android && i.majorVersion > 2 || i.wp) && (r.hasNativeScrolling = i);
-                r.mouseAndTouchPresent = r.touch && !(r.mobileOS.ios || r.mobileOS.android);
-                r.detectBrowser = function(n) {
-                    var t = !1,
-                        i = [],
-                        r = {
-                            webkit: /(chrome)[ \/]([\w.]+)/i,
-                            safari: /(webkit)[ \/]([\w.]+)/i,
-                            opera: /(opera)(?:.*version|)[ \/]([\w.]+)/i,
-                            msie: /(msie\s|trident.*? rv:)([\w.]+)/i,
-                            mozilla: /(mozilla)(?:.*? rv:([\w.]+)|)/i
-                        };
-                    for (var u in r)
-                        if (r.hasOwnProperty(u) && (i = n.match(r[u]), i)) {
-                            t = {};
-                            t[u] = !0;
-                            t[i[1].toLowerCase()] = !0;
-                            t.version = parseInt(document.documentMode || i[2], 10);
-                            break
-                        }
-                    return t
-                };
-                r.browser = r.detectBrowser(navigator.userAgent);
-                r.zoomLevel = function() {
-                    try {
-                        return r.touch ? document.documentElement.clientWidth / window.innerWidth : r.browser.msie && r.browser.version >= 10 ? (top || window).document.documentElement.offsetWidth / (top || window).innerWidth : 1
-                    } catch (n) {
-                        return 1
-                    }
-                };
-                r.cssBorderSpacing = typeof document.documentElement.style.borderSpacing != "undefined" && !(r.browser.msie && r.browser.version < 8),
-                    function(t) {
-                        var i, r = parseInt(t.version, 10);
-                        t.msie ? i = "ie" : t.mozilla ? i = "ff" : t.safari ? i = "safari" : t.webkit ? i = "webkit" : t.opera && (i = "opera");
-                        i && n(document.documentElement).addClass("k-" + i + " k-" + i + r)
-                    }(r.browser);
-                r.eventCapture = document.documentElement.addEventListener;
-                f = document.createElement("input");
-                r.placeholder = "placeholder" in f;
-                r.input = function() {
-                    for (var i = ["number", "date", "time", "month", "week", "datetime", "datetime-local"], e = i.length, r = "test", u = {}, n = 0, t; n < e; n++) t = i[n], f.setAttribute("type", t), f.value = r, u[t.replace("-", "")] = f.type !== "text" && f.value !== r;
-                    return u
-                }();
-                f.style.cssText = "float:left;";
-                r.cssFloat = !!f.style.cssFloat;
-                f = null;
-                r.stableSort = function() {
-                    var n = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].sort(function() {
-                        return 0
-                    });
-                    return n[0] === 0 && n[1] === 1 && n[2] === 2 && n[3] === 3 && n[4] === 4 && n[5] === 5 && n[6] === 6 && n[7] === 7 && n[8] === 8 && n[9] === 9 && n[10] === 10 && n[11] === 11 && n[12] === 12
-                }();
-                r.matchesSelector = s.webkitMatchesSelector || s.mozMatchesSelector || s.msMatchesSelector || s.oMatchesSelector || s.matchesSelector || function(t) {
-                    for (var i = document.querySelectorAll ? (this.parentNode || document).querySelectorAll(t) || [] : n(t), r = i.length; r--;)
-                        if (i[r] == this) return !0;
-                    return !1
-                };
-                r.pushState = window.history && window.history.pushState;
-                c = document.documentMode;
-                r.hashChange = "onhashchange" in window && !(r.browser.msie && (!c || c <= 8))
-            }();
-        ni = {
-            left: {
-                reverse: "right"
-            },
-            right: {
-                reverse: "left"
-            },
-            down: {
-                reverse: "up"
-            },
-            up: {
-                reverse: "down"
-            },
-            top: {
-                reverse: "bottom"
-            },
-            bottom: {
-                reverse: "top"
-            },
-            "in": {
-                reverse: "out"
-            },
-            out: {
-                reverse: "in"
-            }
-        };
-        h = {};
-        n.extend(h, {
-            Element: function(t) {
-                this.element = n(t)
-            },
-            promise: function(n, t) {
-                n.is(":visible") || n.css({
-                    display: n.data("olddisplay") || "block"
-                }).css("display");
-                t.hide && n.data("olddisplay", n.css("display")).hide();
-                t.init && t.init();
-                t.completeCallback && t.completeCallback(n);
-                n.dequeue()
-            },
-            transitionPromise: function(n, t, r) {
-                var u = i.wrap(n);
-                return u.append(t), n.hide(), t.show(), r.completeCallback && r.completeCallback(n), n
-            },
-            disable: function() {
-                this.promise = this.promiseShim;
-                this.transitionPromise = this.transitionPromiseShim
-            },
-            enable: function() {
-                this.promise = this.animatedPromise;
-                this.transitionPromise = this.animatedTransitionPromise
-            }
-        });
-        h.promiseShim = h.promise;
-        h.transitionPromiseShim = h.transitionPromise;
-        "kendoAnimate" in n.fn || s(n.fn, {
-            kendoStop: function(n, t) {
-                return this.stop(n, t)
-            },
-            kendoAnimate: function(n, t, i, r) {
-                return ii(this, n, t, i, r)
-            },
-            kendoAnimateTo: function(n, t, i, r, u) {
-                return lr(this, n, t, i, r, u)
-            },
-            kendoAddClass: function(n, t) {
-                return i.toggleClass(this, n, t, !0)
-            },
-            kendoRemoveClass: function(n, t) {
-                return i.toggleClass(this, n, t, !1)
-            },
-            kendoToggleClass: function(n, t, r) {
-                return i.toggleClass(this, n, t, r)
-            }
-        });
-        var vr = /&/g,
-            yr = /</g,
-            pr = />/g;
-        lt = function(n) {
-            return n.target
-        };
-        r.touch && (lt = function(n) {
-            var t = "originalEvent" in n ? n.originalEvent.changedTouches : "changedTouches" in n ? n.changedTouches : null;
-            return t ? document.elementFromPoint(t[0].clientX, t[0].clientY) : n.target
-        }, d(["swipe", "swipeLeft", "swipeRight", "swipeUp", "swipeDown", "doubleTap", "tap"], function(t, i) {
-            n.fn[i] = function(n) {
-                return this.bind(i, n)
-            }
-        }));
-        r.touch ? r.mobileOS ? (r.mousedown = "touchstart", r.mouseup = "touchend", r.mousemove = "touchmove", r.mousecancel = "touchcancel", r.click = "touchend", r.resize = "orientationchange") : (r.mousedown = "mousedown touchstart", r.mouseup = "mouseup touchend", r.mousemove = "mousemove touchmove", r.mousecancel = "mouseleave touchcancel", r.click = "click", r.resize = "resize") : r.pointers ? (r.mousemove = "pointermove", r.mousedown = "pointerdown", r.mouseup = "pointerup", r.mousecancel = "pointercancel", r.click = "pointerup", r.resize = "orientationchange resize") : r.msPointers ? (r.mousemove = "MSPointerMove", r.mousedown = "MSPointerDown", r.mouseup = "MSPointerUp", r.mousecancel = "MSPointerCancel", r.click = "MSPointerUp", r.resize = "orientationchange resize") : (r.mousemove = "mousemove", r.mousedown = "mousedown", r.mouseup = "mouseup", r.mousecancel = "mouseleave", r.click = "click", r.resize = "resize");
-        ri = function(n, t) {
-            for (var o = t || "d", r, i, e = 1, u = 0, f = n.length; u < f; u++) i = n[u], i !== "" && (r = i.indexOf("["), r !== 0 && (r == -1 ? i = "." + i : (e++, i = "." + i.substring(0, r) + " || {})" + i.substring(r))), e++, o += i + (u < f - 1 ? " || {})" : ")"));
-            return new Array(e).join("(") + o
-        };
-        ui = /^([a-z]+:)?\/\//i;
-        s(i, {
-            ui: i.ui || {},
-            fx: i.fx || cr,
-            effects: i.effects || h,
-            mobile: i.mobile || {},
-            data: i.data || {},
-            dataviz: i.dataviz || {
-                ui: {
-                    roles: {}
-                }
-            },
-            keys: {
-                INSERT: 45,
-                DELETE: 46,
-                BACKSPACE: 8,
-                TAB: 9,
-                ENTER: 13,
-                ESC: 27,
-                LEFT: 37,
-                UP: 38,
-                RIGHT: 39,
-                DOWN: 40,
-                END: 35,
-                HOME: 36,
-                SPACEBAR: 32,
-                PAGEUP: 33,
-                PAGEDOWN: 34,
-                F2: 113,
-                F10: 121,
-                F12: 123
-            },
-            support: i.support || r,
-            animate: i.animate || ii,
-            ns: "",
-            attr: function(n) {
-                return "data-" + i.ns + n
-            },
-            wrap: ur,
-            deepExtend: kt,
-            getComputedStyles: er,
-            size: or,
-            toCamelCase: gt,
-            toHyphens: fr,
-            getOffset: i.getOffset || sr,
-            parseEffects: i.parseEffects || hr,
-            toggleClass: i.toggleClass || ar,
-            directions: i.directions || ni,
-            Observable: ht,
-            Class: ut,
-            Template: v,
-            template: ot(v.compile, v),
-            render: ot(v.render, v),
-            stringify: ot(nt.stringify, nt),
-            eventTarget: lt,
-            htmlEncode: wr,
-            isLocalUrl: function(n) {
-                return n && !ui.test(n)
-            },
-            expr: function(n, t, i) {
-                return n = n || "", typeof t == u && (i = t, t = !1), i = i || "d", n && n.charAt(0) !== "[" && (n = "." + n), t ? ri(n.split("."), i) : i + n
-            },
-            getter: function(n, t) {
-                return wt[n] = wt[n] || new Function("d", "return " + i.expr(n, t))
-            },
-            setter: function(n) {
-                return bt[n] = bt[n] || new Function("d,value", i.expr(n) + "=value")
-            },
-            accessor: function(n) {
-                return {
-                    get: i.getter(n),
-                    set: i.setter(n)
-                }
-            },
-            guid: function() {
-                for (var t = "", i, n = 0; n < 32; n++) i = p.random() * 16 | 0, (n == 8 || n == 12 || n == 16 || n == 20) && (t += "-"), t += (n == 12 ? 4 : n == 16 ? i & 3 | 8 : i).toString(16);
-                return t
-            },
-            roleSelector: function(n) {
-                return n.replace(/(\S+)/g, "[" + i.attr("role") + "=$1],").slice(0, -1)
-            },
-            triggeredByInput: function(n) {
-                return /^(label|input|textarea|select)$/i.test(n.target.tagName)
-            },
-            logToConsole: function(n) {
-                var t = window.console;
-                typeof t != "undefined" && t.log && t.log(n)
-            }
-        });
-        w = ht.extend({
-            init: function(n, t) {
-                var r = this;
-                r.element = i.jQuery(n).handler(r);
-                ht.fn.init.call(r);
-                t = r.options = s(!0, {}, r.options, t);
-                r.element.attr(i.attr("role")) || r.element.attr(i.attr("role"), (t.name || "").toLowerCase());
-                r.element.data("kendo" + t.prefix + t.name, r);
-                r.bind(r.events, t)
-            },
-            events: [],
-            options: {
-                prefix: ""
-            },
-            _hasBindingTarget: function() {
-                return !!this.element[0].kendoBindingTarget
-            },
-            _tabindex: function(n) {
-                n = n || this.wrapper;
-                var i = this.element,
-                    t = "tabindex",
-                    r = n.attr(t) || i.attr(t);
-                i.removeAttr(t);
-                n.attr(t, isNaN(r) ? 0 : r)
-            },
-            setOptions: function(t) {
-                for (var i = this, u = 0, f = i.events.length, r; u < f; u++) r = i.events[u], i.options[r] && t[r] && i.unbind(r, i.options[r]);
-                n.extend(i.options, t);
-                i.bind(i.events, t)
-            },
-            resize: function(n) {
-                var t = this.getSize(),
-                    i = this._size;
-                (n || !i || t.width !== i.width || t.height !== i.height) && (this._resize(t), this.trigger("resize", t), this._size = t)
-            },
-            getSize: function() {
-                return i.dimensions(this.element)
-            },
-            size: function(n) {
-                if (n) this.setSize(n);
-                else return this.getSize()
-            },
-            setSize: n.noop,
-            _resize: n.noop,
-            destroy: function() {
-                var n = this;
-                n.element.removeData("kendo" + n.options.prefix + n.options.name);
-                n.element.removeData("handler");
-                n.unbind()
-            }
-        });
-        i.dimensions = function(n, t) {
-            var i = n[0];
-            return t && n.css(t), {
-                width: i.offsetWidth,
-                height: i.offsetHeight
-            }
-        };
-        i.notify = g;
-        var br = /template$/i,
-            kr = /^\s*(?:\{(?:.|\r\n|\n)*\}|\[(?:.|\r\n|\n)*\])\s*$/,
-            dr = /^\{(\d+)(:[^\}]+)?\}/,
-            gr = /([A-Z])/g;
-        i.initWidget = function(r, f, e) {
-            var s, a, o, l, y, h, v, c;
-            if ((e ? e.roles && (e = e.roles) : e = i.ui.roles, r = r.nodeType ? r : r[0], h = r.getAttribute("data-" + i.ns + "role"), h) && (o = h.indexOf(".") === -1 ? e[h] : i.getter(h)(window), o)) {
-                for (c = at(r, "dataSource"), f = n.extend({}, fi(r, o.fn.options), f), c && (f.dataSource = typeof c === u ? i.getter(c)(window) : c), l = 0, y = o.fn.events.length; l < y; l++) a = o.fn.events[l], v = at(r, a), v !== t && (f[a] = i.getter(v)(window));
-                return s = n(r).data("kendo" + o.fn.options.prefix + o.fn.options.name), s ? s.setOptions(f) : s = new o(r, f), s
-            }
-        };
-        i.rolesFromNamespaces = function(n) {
-            var r = [],
-                t, u;
-            for (n[0] || (n = [i.ui, i.dataviz.ui]), t = 0, u = n.length; t < u; t++) r[t] = n[t].roles;
-            return s.apply(null, [{}].concat(r.reverse()))
-        };
-        i.init = function(t) {
-            var r = i.rolesFromNamespaces(st.call(arguments, 1));
-            n(t).find("[data-" + i.ns + "role]").addBack().each(function() {
-                i.initWidget(this, {}, r)
-            })
-        };
-        i.destroy = function(t) {
-            n(t).find("[data-" + i.ns + "role]").addBack().each(function() {
-                var t = i.widgetInstance(n(this));
-                t && t.destroy()
-            })
-        };
-        i.resize = function(t) {
-            var u = n(t).find("[data-" + i.ns + "role]").addBack().filter(tu),
-                r;
-            u.length && (r = n.makeArray(u), r.sort(nu), n.each(r, function() {
-                var t = i.widgetInstance(n(this));
-                t && t.resize()
-            }))
-        };
-        i.parseOptions = fi;
-        s(i.ui, {
-            Widget: w,
-            roles: {},
-            progress: function(t, r) {
-                var u = t.find(".k-loading-mask"),
-                    o = i.support,
-                    c = o.browser,
-                    f, s, h, e;
-                r ? u.length || (f = o.isRtl(t), s = f ? "right" : "left", e = t.scrollLeft(), h = c.webkit ? f ? t[0].scrollWidth - t.width() - 2 * e : 0 : 0, u = n("<div class='k-loading-mask'><span class='k-loading-text'>Loading...<\/span><div class='k-loading-image'/><div class='k-loading-color'/><\/div>").width("100%").height("100%").css("top", t.scrollTop()).css(s, Math.abs(e) + h).prependTo(t)) : u && u.remove()
-            },
-            plugin: function(r, f, e) {
-                var o = r.fn.options.name,
-                    s;
-                f = f || i.ui;
-                e = e || "";
-                f[o] = r;
-                f.roles[o.toLowerCase()] = r;
-                s = "getKendo" + e + o;
-                o = "kendo" + e + o;
-                n.fn[o] = function(f) {
-                    var e = this,
-                        s;
-                    return typeof f === u ? (s = st.call(arguments, 1), this.each(function() {
-                        var r = n.data(this, o),
-                            u, h;
-                        if (!r) throw new Error(i.format("Cannot call method '{0}' of {1} before it is initialized", f, o));
-                        if (u = r[f], typeof u !== c) throw new Error(i.format("Cannot find method '{0}' of {1}", f, o));
-                        return h = u.apply(r, s), h !== t ? (e = h, !1) : void 0
-                    })) : this.each(function() {
-                        new r(this, f)
-                    }), e
-                };
-                n.fn[s] = function() {
-                    return this.data(o)
-                }
-            }
-        });
-        ei = {
-            bind: function() {
-                return this
-            }
-        };
-        oi = w.extend({
-            init: function(n, t) {
-                w.fn.init.call(this, n, t);
-                this.element.autoApplyNS();
-                this.wrapper = this.element;
-                this.element.addClass("km-widget")
-            },
-            destroy: function() {
-                w.fn.destroy.call(this);
-                this.element.kendoDestroy()
-            },
-            options: {
-                prefix: "Mobile"
-            },
-            events: [],
-            view: function() {
-                var n = this.element.closest(i.roleSelector("view splitview modalview drawer"));
-                return i.widgetInstance(n, i.mobile.ui)
-            },
-            container: function() {
-                var n = this.element.closest(i.roleSelector("view layout modalview drawer"));
-                return i.widgetInstance(n, i.mobile.ui) || ei
-            }
-        });
-        s(i.mobile, {
-            init: function(n) {
-                i.init(n, i.mobile.ui, i.ui, i.dataviz.ui)
-            },
-            ui: {
-                Widget: oi,
-                roles: {},
-                plugin: function(n) {
-                    i.ui.plugin(n, i.mobile.ui, "Mobile")
-                }
-            }
-        });
-        i.touchScroller = function(t, u) {
-            return n(t).map(function(t, f) {
-                return f = n(f), r.kineticScrollNeeded && i.mobile.ui.Scroller && !f.data("kendoMobileScroller") ? (f.kendoMobileScroller(u), f.data("kendoMobileScroller")) : !1
-            })[0]
-        };
-        i.preventDefault = function(n) {
-            n.preventDefault()
-        };
-        i.widgetInstance = function(n, t) {
-            var r = n.data(i.ns + "role"),
-                u, f, s, e, o;
-            if (r)
-                for (r === "content" && (r = "scroller"), u = t ? [t.roles[r]] : [i.ui.roles[r], i.dataviz.ui.roles[r], i.mobile.ui.roles[r]], r.indexOf(".") >= 0 && (u = [i.getter(r)(window)]), f = 0, s = u.length; f < s; f++)
-                    if (e = u[f], e && (o = n.data("kendo" + e.fn.options.prefix + e.fn.options.name), o)) return o
-        };
-        i.onResize = function(t) {
-            var i = t;
-            r.mobileOS.android && (i = function() {
-                setTimeout(t, 600)
-            });
-            n(window).on(r.resize, i);
-            return i
-        };
-        i.unbindResize = function(t) {
-            n(window).off(r.resize, t)
-        };
-        i.attrValue = function(n, t) {
-            return n.data(i.ns + t)
-        };
-        i.days = {
-            Sunday: 0,
-            Monday: 1,
-            Tuesday: 2,
-            Wednesday: 3,
-            Thursday: 4,
-            Friday: 5,
-            Saturday: 6
-        };
-        n.extend(n.expr[":"], {
-            kendoFocusable: function(t) {
-                var i = n.attr(t, "tabindex");
-                return iu(t, !isNaN(i) && i > -1)
-            }
-        });
-        var si = ["mousedown", "mousemove", "mouseenter", "mouseleave", "mouseover", "mouseout", "mouseup", "click"],
-            uu = "label, input, [data-rel=external]",
-            f = {
-                setupMouseMute: function() {
-                    var t = 0,
-                        u = si.length,
-                        e = document.documentElement,
-                        i;
-                    if (!f.mouseTrap && r.eventCapture)
-                        for (f.mouseTrap = !0, f.bustClick = !1, f.captureMouse = !1, i = function(t) {
-                                f.captureMouse && (t.type === "click" ? f.bustClick && !n(t.target).is(uu) && (t.preventDefault(), t.stopPropagation()) : t.stopPropagation())
-                            }; t < u; t++) e.addEventListener(si[t], i, !0)
-                },
-                muteMouse: function(n) {
-                    f.captureMouse = !0;
-                    n.data.bustClick && (f.bustClick = !0);
-                    clearTimeout(f.mouseTrapTimeoutID)
-                },
-                unMuteMouse: function() {
-                    clearTimeout(f.mouseTrapTimeoutID);
-                    f.mouseTrapTimeoutID = setTimeout(function() {
-                        f.captureMouse = !1;
-                        f.bustClick = !1
-                    }, 400)
-                }
-            },
-            b = {
-                down: "touchstart mousedown",
-                move: "mousemove touchmove",
-                up: "mouseup touchend touchcancel",
-                cancel: "mouseleave touchcancel"
-            };
-        r.touch && (r.mobileOS.ios || r.mobileOS.android) ? b = {
-            down: "touchstart",
-            move: "touchmove",
-            up: "touchend touchcancel",
-            cancel: "touchcancel"
-        } : r.pointers ? b = {
-            down: "pointerdown",
-            move: "pointermove",
-            up: "pointerup",
-            cancel: "pointercancel pointerleave"
-        } : r.msPointers && (b = {
-            down: "MSPointerDown",
-            move: "MSPointerMove",
-            up: "MSPointerUp",
-            cancel: "MSPointerCancel MSPointerLeave"
-        });
-        !r.msPointers || "onmspointerenter" in window || n.each({
-            MSPointerEnter: "MSPointerOver",
-            MSPointerLeave: "MSPointerOut"
-        }, function(t, i) {
-            n.event.special[t] = {
-                delegateType: i,
-                bindType: i,
-                handle: function(t) {
-                    var u, f = this,
-                        r = t.relatedTarget,
-                        e = t.handleObj;
-                    return r && (r === f || n.contains(f, r)) || (t.type = e.origType, u = e.handler.apply(this, arguments), t.type = i), u
-                }
-            }
-        });
-        hi = function(n) {
-            return b[n] || n
-        };
-        vt = /([^ ]+)/g;
-        i.applyEventMap = function(n, t) {
-            return n = n.replace(vt, hi), t && (n = n.replace(vt, "$1." + t)), n
-        };
-        et = n.fn.on;
-        s(!0, o, n);
-        o.fn = o.prototype = new n;
-        o.fn.constructor = o;
-        o.fn.init = function(t, i) {
-            return i && i instanceof n && !(i instanceof o) && (i = o(i)), n.fn.init.call(this, t, i, ci)
-        };
-        o.fn.init.prototype = o.fn;
-        ci = o(document);
-        s(o.fn, {
-            handler: function(n) {
-                return this.data("handler", n), this
-            },
-            autoApplyNS: function(n) {
-                return this.data("kendoNS", n || i.guid()), this
-            },
-            on: function() {
-                var t = this,
-                    l = t.data("kendoNS"),
-                    s, n, e, o, h, c;
-                return arguments.length === 1 ? et.call(t, arguments[0]) : (s = t, n = st.call(arguments), typeof n[n.length - 1] === rt && n.pop(), e = n[n.length - 1], o = i.applyEventMap(n[0], l), r.mouseAndTouchPresent && o.search(/mouse|click/) > -1 && this[0] !== document.documentElement && (f.setupMouseMute(), h = n.length === 2 ? null : n[1], c = o.indexOf("click") > -1 && o.indexOf("touchend") > -1, et.call(this, {
-                    touchstart: f.muteMouse,
-                    touchend: f.unMuteMouse
-                }, h, {
-                    bustClick: c
-                })), typeof e === u && (s = t.data("handler"), e = s[e], n[n.length - 1] = function(n) {
-                    e.call(s, n)
-                }), n[0] = o, et.apply(t, n), t)
-            },
-            kendoDestroy: function(n) {
-                return n = n || this.data("kendoNS"), n && this.off("." + n), this
-            }
-        });
-        i.jQuery = o;
-        i.eventMap = b;
-        i.timezone = function() {
-            function i(i, r) {
-                var u, o, s, c = r[3],
-                    e = r[4],
-                    f = r[5],
-                    h = r[8];
-                return (h || (r[8] = h = {}), h[i]) ? h[i] : (isNaN(e) ? e.indexOf("last") === 0 ? (u = new Date(Date.UTC(i, n[c] + 1, 1, f[0] - 24, f[1], f[2], 0)), o = t[e.substr(4, 3)], s = u.getUTCDay(), u.setUTCDate(u.getUTCDate() + o - s - (o > s ? 7 : 0))) : e.indexOf(">=") >= 0 && (u = new Date(Date.UTC(i, n[c], e.substr(5), f[0], f[1], f[2], 0)), o = t[e.substr(0, 3)], s = u.getUTCDay(), u.setUTCDate(u.getUTCDate() + o - s + (o < s ? 7 : 0))) : u = new Date(Date.UTC(i, n[c], e, f[0], f[1], f[2], 0)), h[i] = u)
-            }
-
-            function f(n, t, r) {
-                var f, e, u;
-                return (t = t[r], !t) ? (f = r.split(":"), e = 0, f.length > 1 && (e = f[0] * 60 + Number(f[1])), [-1e6, "max", "-", "Jan", 1, [0, 0, 0], e, "-"]) : (u = new Date(n).getUTCFullYear(), t = jQuery.grep(t, function(n) {
-                    var i = n[0],
-                        t = n[1];
-                    return i <= u && (t >= u || i == u && t == "only" || t == "max")
-                }), t.push(n), t.sort(function(n, t) {
-                    return typeof n != "number" && (n = Number(i(u, n))), typeof t != "number" && (t = Number(i(u, t))), n - t
-                }), t[jQuery.inArray(n, t) - 1])
-            }
-
-            function e(n, t, i) {
-                var r = t[i],
-                    u, f, e;
-                if (typeof r == "string" && (r = t[r]), !r) throw new Error('Timezone "' + i + '" is either incorrect, or kendo.timezones.min.js is not included.');
-                for (u = r.length - 1; u >= 0; u--)
-                    if (f = r[u][3], f && n > f) break;
-                if (e = r[u + 1], !e) throw new Error('Timezone "' + i + '" not found on ' + n + ".");
-                return e
-            }
-
-            function r(n, t, i, r) {
-                typeof n != l && (n = Date.UTC(n.getFullYear(), n.getMonth(), n.getDate(), n.getHours(), n.getMinutes(), n.getSeconds(), n.getMilliseconds()));
-                var u = e(n, t, r);
-                return {
-                    zone: u,
-                    rule: f(n, i, u[1])
-                }
-            }
-
-            function o(n, t) {
-                if (t == "Etc/UTC" || t == "Etc/GMT") return 0;
-                var i = r(n, this.zones, this.rules, t),
-                    u = i.zone,
-                    f = i.rule;
-                return f ? u[0] - f[6] : u[0]
-            }
-
-            function s(n, t) {
-                var f = r(n, this.zones, this.rules, t),
-                    e = f.zone,
-                    i = f.rule,
-                    u = e[2];
-                return u.indexOf("/") >= 0 ? u.split("/")[i && i[6] ? 1 : 0] : u.indexOf("%s") >= 0 ? u.replace("%s", !i || i[7] == "-" ? "" : i[7]) : u
-            }
-
-            function h(n, t, i) {
-                var r, f;
-                return typeof t == u && (t = this.offset(n, t)), typeof i == u && (i = this.offset(n, i)), r = n.getTimezoneOffset(), n = new Date(n.getTime() + (t - i) * 6e4), f = n.getTimezoneOffset(), new Date(n.getTime() + (f - r) * 6e4)
-            }
-
-            function c(n, t) {
-                return this.convert(n, n.getTimezoneOffset(), t)
-            }
-
-            function a(n, t) {
-                return this.convert(n, t, n.getTimezoneOffset())
-            }
-
-            function v(n) {
-                return this.apply(new Date(n), "Etc/UTC")
-            }
-            var n = {
-                    Jan: 0,
-                    Feb: 1,
-                    Mar: 2,
-                    Apr: 3,
-                    May: 4,
-                    Jun: 5,
-                    Jul: 6,
-                    Aug: 7,
-                    Sep: 8,
-                    Oct: 9,
-                    Nov: 10,
-                    Dec: 11
-                },
-                t = {
-                    Sun: 0,
-                    Mon: 1,
-                    Tue: 2,
-                    Wed: 3,
-                    Thu: 4,
-                    Fri: 5,
-                    Sat: 6
-                };
-            return {
-                zones: {},
-                rules: {},
-                offset: o,
-                convert: h,
-                apply: c,
-                remove: a,
-                abbr: s,
-                toLocalDate: v
-            }
-        }();
-        i.date = function() {
-            function t(n, t) {
-                return t === 0 && n.getHours() === 23 ? (n.setHours(n.getHours() + 2), !0) : !1
-            }
-
-            function e(n, i, r) {
-                var u = n.getHours();
-                r = r || 1;
-                i = (i - n.getDay() + 7 * r) % 7;
-                n.setDate(n.getDate() + i);
-                t(n, u)
-            }
-
-            function c(n, t, i) {
-                return n = new Date(n), e(n, t, i), n
-            }
-
-            function o(n) {
-                return new Date(n.getFullYear(), n.getMonth(), 1)
-            }
-
-            function l(n) {
-                var t = new Date(n.getFullYear(), n.getMonth() + 1, 0),
-                    i = o(n),
-                    r = Math.abs(t.getTimezoneOffset() - i.getTimezoneOffset());
-                return r && t.setHours(i.getHours() + r / 60), t
-            }
-
-            function i(n) {
-                return n = new Date(n.getFullYear(), n.getMonth(), n.getDate(), 0, 0, 0), t(n, 0), n
-            }
-
-            function a(n) {
-                return Date.UTC(n.getFullYear(), n.getMonth(), n.getDate(), n.getHours(), n.getMinutes(), n.getSeconds(), n.getMilliseconds())
-            }
-
-            function r(n) {
-                return n.getTime() - i(n)
-            }
-
-            function v(t, i, u) {
-                var e = r(i),
-                    o = r(u),
-                    f;
-                return !t || e == o ? !0 : (i >= u && (u += n), f = r(t), e > f && (f += n), o < e && (o += n), f >= e && f <= o)
-            }
-
-            function y(t, i, r) {
-                var e = i.getTime(),
-                    u = r.getTime(),
-                    f;
-                return e >= u && (u += n), f = t.getTime(), f >= e && f <= u
-            }
-
-            function u(i, r) {
-                var u = i.getHours();
-                return i = new Date(i), s(i, r * n), t(i, u), i
-            }
-
-            function s(n, t, i) {
-                var u = n.getTimezoneOffset(),
-                    r;
-                n.setTime(n.getTime() + t);
-                i || (r = n.getTimezoneOffset() - u, n.setTime(n.getTime() + r * f))
-            }
-
-            function h() {
-                return i(new Date)
-            }
-
-            function p(n) {
-                return i(n).getTime() == h().getTime()
-            }
-
-            function w(n) {
-                var t = new Date(1980, 1, 1, 0, 0, 0);
-                return n && t.setHours(n.getHours(), n.getMinutes(), n.getSeconds(), n.getMilliseconds()), t
-            }
-            var f = 6e4,
-                n = 864e5;
-            return {
-                adjustDST: t,
-                dayOfWeek: c,
-                setDayOfWeek: e,
-                getDate: i,
-                isInDateRange: y,
-                isInTimeRange: v,
-                isToday: p,
-                nextDay: function(n) {
-                    return u(n, 1)
-                },
-                previousDay: function(n) {
-                    return u(n, -1)
-                },
-                toUtcTime: a,
-                MS_PER_DAY: n,
-                MS_PER_MINUTE: f,
-                setTime: s,
-                addDays: u,
-                today: h,
-                toInvariantTime: w,
-                firstDayOfMonth: o,
-                lastDayOfMonth: l,
-                getMilliseconds: r
-            }
-        }();
-        i.stripWhitespace = function(n) {
-            for (var t = document.createNodeIterator(n, NodeFilter.SHOW_TEXT, function(t) {
-                    return t.parentNode == n ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT
-                }, !1); t.nextNode();) t.referenceNode && !t.referenceNode.textContent.trim() && t.referenceNode.parentNode.removeChild(t.referenceNode)
-        };
-        yt = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(n) {
-            setTimeout(n, 1e3 / 60)
-        };
-        i.animationFrame = function(n) {
-            yt.call(window, n)
-        };
-        k = [];
-        i.queueAnimation = function(n) {
-            k[k.length] = n;
-            k.length === 1 && i.runNextAnimation()
-        };
-        i.runNextAnimation = function() {
-            var n = k.shift();
-            i.animationFrame(function() {
-                n();
-                yt[0] && i.runNextAnimation()
-            })
-        };
-        i.parseQueryStringParams = function(n) {
-            for (var u = n.split("?")[1] || "", r = {}, i = u.split(/&|=/), f = i.length, t = 0; t < f; t += 2) i[t] !== "" && (r[decodeURIComponent(i[t])] = decodeURIComponent(i[t + 1]));
-            return r
-        }
-    }(jQuery);
-typeof kendo_module == "undefined" && (kendo_module = function() {});
-kendo_module({
-    id: "core",
-    name: "Core",
-    category: "framework",
-    description: "The core of the Kendo framework."
-});
-kendo_module({
-        id: "fx",
-        name: "Effects",
-        category: "framework",
-        description: "Required for animation effects in all Kendo UI widgets.",
-        depends: ["core"]
-    }),
-    function(n, t) {
-        function ii(n) {
-            return parseInt(n, 10)
-        }
-
-        function p(n, t) {
-            return ii(n.css(t))
-        }
-
-        function ir(n) {
-            var t = n.effects;
-            return t === "zoom" && (t = "zoom:in fade:in"), t === "fade" && (t = "fade:in"), t === "slide" && (t = "tile:left"), /^slide:(.+)$/.test(t) && (t = "tile:" + RegExp.$1), t === "overlay" && (t = "slideIn:left"), /^overlay:(.+)$/.test(t) && (t = "slideIn:" + RegExp.$1), n.effects = i.parseEffects(t), tr && t == "tile:left" && (n.previousDivisor = 3), n
-        }
-
-        function rr(n) {
-            var t = [];
-            for (var i in n) t.push(i);
-            return t
-        }
-
-        function st(n) {
-            for (var t in n) rt.indexOf(t) != -1 && d.indexOf(t) == -1 && delete n[t];
-            return n
-        }
-
-        function ht(n, t) {
-            var r = [],
-                u = {},
-                o, i, s, c;
-            for (i in t) o = i.toLowerCase(), c = f && rt.indexOf(o) != -1, !h.hasHW3D && c && d.indexOf(o) == -1 ? delete t[i] : (s = t[i], c ? r.push(i + "(" + s + ")") : u[i] = s);
-            return r.length && (u[e] = r.join(" ")), u
-        }
-
-        function ri(n, t) {
-            var u, i, r;
-            return f ? (u = n.css(e), u == gi) ? t == "scale" ? 1 : 0 : (i = u.match(new RegExp(t + "\\s*\\(([\\d\\w\\.]+)")), r = 0, i ? r = ii(i[1]) : (i = u.match(vi) || [0, 0, 0, 0, 0], t = t.toLowerCase(), yi.test(t) ? r = parseFloat(i[3] / i[2]) : t == "translatey" ? r = parseFloat(i[4] / i[2]) : t == "scale" ? r = parseFloat(i[2]) : t == "rotate" && (r = parseFloat(Math.atan2(i[2], i[1])))), r) : parseFloat(n.css(t))
-        }
-
-        function lt(n) {
-            return n.charAt(0).toUpperCase() + n.substring(1)
-        }
-
-        function o(n, t) {
-            var i = l.extend(t),
-                r = i.prototype.directions;
-            u[lt(n)] = i;
-            u.Element.prototype[n] = function(n, t, r, u) {
-                return new i(this.element, n, t, r, u)
-            };
-            a(r, function(t, r) {
-                u.Element.prototype[n + lt(r)] = function(n, t, u) {
-                    return new i(this.element, r, n, t, u)
-                }
-            })
-        }
-
-        function fi(n, t, i, r) {
-            o(n, {
-                directions: ui,
-                startValue: function(n) {
-                    return this._startValue = n, this
-                },
-                endValue: function(n) {
-                    return this._endValue = n, this
-                },
-                shouldHide: function() {
-                    return this._shouldHide
-                },
-                prepare: function(n, u) {
-                    var s = this,
-                        f, e, h = this._direction === "out",
-                        o = s.element.data(t),
-                        c = !(isNaN(o) || o == i);
-                    f = c ? o : typeof this._startValue != "undefined" ? this._startValue : h ? i : r;
-                    e = typeof this._endValue != "undefined" ? this._endValue : h ? r : i;
-                    this._reverse ? (n[t] = e, u[t] = f) : (n[t] = f, u[t] = e);
-                    s._shouldHide = u[t] === r
-                }
-            })
-        }
-
-        function hi(n, t) {
-            var r = i.directions[t].vertical,
-                u = n[r ? nt : ft]() / 2 + "px";
-            return oi[t].replace("$size", u)
-        }
-        var i = window.kendo,
-            u = i.effects,
-            a = n.each,
-            r = n.extend,
-            ci = n.proxy,
-            h = i.support,
-            vt = h.browser,
-            f = h.transforms,
-            s = h.transitions,
-            li = {
-                scale: 0,
-                scalex: 0,
-                scaley: 0,
-                scale3d: 0
-            },
-            ai = {
-                translate: 0,
-                translatex: 0,
-                translatey: 0,
-                translate3d: 0
-            },
-            yt = typeof document.documentElement.style.zoom != "undefined" && !f,
-            vi = /matrix3?d?\s*\(.*,\s*([\d\.\-]+)\w*?,\s*([\d\.\-]+)\w*?,\s*([\d\.\-]+)\w*?,\s*([\d\.\-]+)\w*?/i,
-            pt = /^(-?[\d\.\-]+)?[\w\s]*,?\s*(-?[\d\.\-]+)?[\w\s]*/i,
-            yi = /translatex?$/i,
-            pi = /(zoom|fade|expand)(\w+)/,
-            wt = /(zoom|fade|expand)/,
-            wi = /[xy]$/i,
-            rt = ["perspective", "rotate", "rotatex", "rotatey", "rotatez", "rotate3d", "scale", "scalex", "scaley", "scalez", "scale3d", "skew", "skewx", "skewy", "translate", "translatex", "translatey", "translatez", "translate3d", "matrix", "matrix3d"],
-            d = ["rotate", "scale", "scalex", "scaley", "skew", "skewx", "skewy", "translate", "translatex", "translatey", "matrix"],
-            bi = {
-                rotate: "deg",
-                scale: "",
-                skew: "px",
-                translate: "px"
-            },
-            g = f.css,
-            ki = Math.round,
-            di = "",
-            w = "px",
-            gi = "none",
-            ut = "auto",
-            ft = "width",
-            nt = "height",
-            bt = "hidden",
-            et = "origin",
-            kt = "abortId",
-            tt = "overflow",
-            v = "translate",
-            b = "position",
-            dt = "completeCallback",
-            y = g + "transition",
-            e = g + "transform",
-            nr = g + "backface-visibility",
-            gt = g + "perspective",
-            ot = "1500px",
-            ni = "perspective(" + ot + ")",
-            tr = h.mobileOS && h.mobileOS.majorVersion == 7,
-            c = {
-                left: {
-                    reverse: "right",
-                    property: "left",
-                    transition: "translatex",
-                    vertical: !1,
-                    modifier: -1
-                },
-                right: {
-                    reverse: "left",
-                    property: "left",
-                    transition: "translatex",
-                    vertical: !1,
-                    modifier: 1
-                },
-                down: {
-                    reverse: "up",
-                    property: "top",
-                    transition: "translatey",
-                    vertical: !0,
-                    modifier: 1
-                },
-                up: {
-                    reverse: "down",
-                    property: "top",
-                    transition: "translatey",
-                    vertical: !0,
-                    modifier: -1
-                },
-                top: {
-                    reverse: "bottom"
-                },
-                bottom: {
-                    reverse: "top"
-                },
-                "in": {
-                    reverse: "out",
-                    modifier: -1
-                },
-                out: {
-                    reverse: "in",
-                    modifier: 1
-                },
-                vertical: {
-                    reverse: "vertical"
-                },
-                horizontal: {
-                    reverse: "horizontal"
-                }
-            },
-            ti, ct, l, k, ui, ei, oi, si, it, at;
-        i.directions = c;
-        r(n.fn, {
-            kendoStop: function(n, t) {
-                return s ? u.stopQueue(this, n || !1, t || !1) : this.stop(n, t)
-            }
-        });
-        f && !s && (a(d, function(t, i) {
-            n.fn[i] = function(t) {
-                if (typeof t == "undefined") return ri(this, i);
-                var r = n(this)[0],
-                    u = i + "(" + t + bi[i.replace(wi, "")] + ")";
-                return r.style.cssText.indexOf(e) == -1 ? n(this).css(e, u) : r.style.cssText = r.style.cssText.replace(new RegExp(i + "\\(.*?\\)", "i"), u), this
-            };
-            n.fx.step[i] = function(t) {
-                n(t.elem)[i](t.now)
-            }
-        }), ti = n.fx.prototype.cur, n.fx.prototype.cur = function() {
-            return d.indexOf(this.prop) != -1 ? parseFloat(n(this.elem)[this.prop]()) : ti.apply(this, arguments)
-        });
-        i.toggleClass = function(n, t, i, u) {
-            return t && (t = t.split(" "), s && (i = r({
-                exclusive: "all",
-                duration: 400,
-                ease: "ease-out"
-            }, i), n.css(y, i.exclusive + " " + i.duration + "ms " + i.ease), setTimeout(function() {
-                n.css(y, "").css(nt)
-            }, i.duration)), a(t, function(t, i) {
-                n.toggleClass(i, u)
-            })), n
-        };
-        i.parseEffects = function(n, t) {
-            var i = {};
-            return typeof n == "string" ? a(n.split(" "), function(n, r) {
-                var o = !wt.test(r),
-                    s = r.replace(pi, function(n, t, i) {
-                        return t + ":" + i.toLowerCase()
-                    }),
-                    u = s.split(":"),
-                    f = u[1],
-                    e = {};
-                u.length > 1 && (e.direction = t && o ? c[f].reverse : f);
-                i[u[0]] = e
-            }) : a(n, function(n) {
-                var r = this.direction;
-                r && t && !wt.test(n) && (this.direction = c[r].reverse);
-                i[n] = this
-            }), i
-        };
-        s && r(u, {
-            transition: function(t, i, u) {
-                var h, l = 0,
-                    a = t.data("keys") || [],
-                    f, c, o;
-                if (u = r({
-                        duration: 200,
-                        ease: "ease-out",
-                        complete: null,
-                        exclusive: "all"
-                    }, u), c = !1, o = function() {
-                        c || (c = !0, f && (clearTimeout(f), f = null), t.removeData(kt).dequeue().css(y, "").css(y), u.complete.call(t))
-                    }, u.duration = n.fx ? n.fx.speeds[u.duration] || u.duration : u.duration, h = ht(t, i), n.merge(a, rr(h)), t.data("keys", n.unique(a)).height(), t.css(y, u.exclusive + " " + u.duration + "ms " + u.ease).css(y), t.css(h).css(e), s.event) {
-                    t.one(s.event, o);
-                    u.duration !== 0 && (l = 500)
-                }
-                f = setTimeout(o, u.duration + l);
-                t.data(kt, f);
-                t.data(dt, o)
-            },
-            stopQueue: function(n, t, r) {
-                var u, f = n.data("keys"),
-                    e = !r && f,
-                    o = n.data(dt);
-                return e && (u = i.getComputedStyles(n[0], f)), o && o(), e && n.css(u), n.removeData("keys").stop(t)
-            }
-        });
-        ct = i.Class.extend({
-            init: function(n, t) {
-                var i = this;
-                i.element = n;
-                i.effects = [];
-                i.options = t;
-                i.restore = []
-            },
-            run: function(t) {
-                var a = this,
-                    l, h, v, k = t.length,
-                    c = a.element,
-                    i = a.options,
-                    p = n.Deferred(),
-                    o = {},
-                    y = {},
-                    w, b, d, g;
-                for (a.effects = t, p.then(n.proxy(a, "complete")), c.data("animating", !0), h = 0; h < k; h++)
-                    for (l = t[h], l.setReverse(i.reverse), l.setOptions(i), a.addRestoreProperties(l.restore), l.prepare(o, y), b = l.children(), v = 0, d = b.length; v < d; v++) b[v].duration(i.duration).run();
-                for (g in i.effects) r(y, i.effects[g].properties);
-                for (c.is(":visible") || r(o, {
-                        display: c.data("olddisplay") || "block"
-                    }), f && !i.reset && (w = c.data("targetTransform"), w && (o = r(w, o))), o = ht(c, o), f && !s && (o = st(o)), c.css(o).css(e), h = 0; h < k; h++) t[h].setup();
-                return i.init && i.init(), c.data("targetTransform", y), u.animate(c, y, r({}, i, {
-                    complete: p.resolve
-                })), p.promise()
-            },
-            stop: function() {
-                n(this.element).kendoStop(!0, !0)
-            },
-            addRestoreProperties: function(n) {
-                for (var i = this.element, t, r = 0, u = n.length; r < u; r++) t = n[r], this.restore.push(t), i.data(t) || i.data(t, i.css(t))
-            },
-            restoreCallback: function() {
-                for (var t, i = this.element, n = 0, r = this.restore.length; n < r; n++) t = this.restore[n], i.css(t, i.data(t))
-            },
-            complete: function() {
-                var i = this,
-                    r = 0,
-                    t = i.element,
-                    u = i.options,
-                    e = i.effects,
-                    o = e.length;
-                for (t.removeData("animating").dequeue(), u.hide && t.data("olddisplay", t.css("display")).hide(), this.restoreCallback(), yt && !f && setTimeout(n.proxy(this, "restoreCallback"), 0); r < o; r++) e[r].teardown();
-                u.completeCallback && u.completeCallback(t)
-            }
-        });
-        u.promise = function(n, t) {
-            var r = [],
-                f, s = new ct(n, t),
-                e = i.parseEffects(t.effects),
-                h, o;
-            t.effects = e;
-            for (o in e) f = u[lt(o)], f && (h = new f(n, e[o].direction), r.push(h));
-            r[0] ? s.run(r) : (n.is(":visible") || n.css({
-                display: n.data("olddisplay") || "block"
-            }).css("display"), t.init && t.init(), n.dequeue(), s.complete())
-        };
-        u.transitionPromise = function(n, t, i) {
-            return u.animateTo(n, t, i), n
-        };
-        r(u, {
-            animate: function(i, e, o) {
-                var h = o.transition !== !1;
-                delete o.transition;
-                s && "transition" in u && h ? u.transition(i, e, o) : f ? i.animate(st(e), {
-                    queue: !1,
-                    show: !1,
-                    hide: !1,
-                    duration: o.duration,
-                    complete: o.complete
-                }) : i.each(function() {
-                    var i = n(this),
-                        u = {};
-                    a(rt, function(n, o) {
-                        var c, y = e ? e[o] + " " : null,
-                            s, w, k, h, l, a;
-                        y && (s = e, o in li && e[o] !== t ? (c = y.match(pt), f && r(s, {
-                            scale: +c[0]
-                        })) : o in ai && e[o] !== t && (w = i.css(b), k = w == "absolute" || w == "fixed", i.data(v) || (k ? i.data(v, {
-                            top: p(i, "top") || 0,
-                            left: p(i, "left") || 0,
-                            bottom: p(i, "bottom"),
-                            right: p(i, "right")
-                        }) : i.data(v, {
-                            top: p(i, "marginTop") || 0,
-                            left: p(i, "marginLeft") || 0
-                        })), h = i.data(v), c = y.match(pt), c && (l = o == v + "y" ? 0 : +c[1], a = o == v + "y" ? +c[1] : +c[2], k ? (isNaN(h.right) ? isNaN(l) || r(s, {
-                            left: h.left + l
-                        }) : isNaN(l) || r(s, {
-                            right: h.right - l
-                        }), isNaN(h.bottom) ? isNaN(a) || r(s, {
-                            top: h.top + a
-                        }) : isNaN(a) || r(s, {
-                            bottom: h.bottom - a
-                        })) : (isNaN(l) || r(s, {
-                            marginLeft: h.left + l
-                        }), isNaN(a) || r(s, {
-                            marginTop: h.top + a
-                        })))), !f && o != "scale" && o in s && delete s[o], s && r(u, s))
-                    });
-                    vt.msie && delete u.scale;
-                    i.animate(u, {
-                        queue: !1,
-                        show: !1,
-                        hide: !1,
-                        duration: o.duration,
-                        complete: o.complete
-                    })
-                })
-            },
-            animateTo: function(t, i, u) {
-                function a(n) {
-                    i[0].style.cssText = "";
-                    t.each(function() {
-                        this.style.cssText = ""
-                    });
-                    h.mobileOS.android || f.css(tt, c);
-                    s || e.css(b, l);
-                    u.completeCallback && u.completeCallback.call(t, n)
-                }
-                var o, f = t.parents().filter(i.parents()).first(),
-                    e = n().add(t.parent()).add(i.parent()),
-                    s = t.css(b) == "absolute",
-                    c, l;
-                s || (l = e.css(b), e.css(b, "absolute"));
-                u = ir(u);
-                h.mobileOS.android || (c = f.css(tt), f.css(tt, "hidden"));
-                n.each(u.effects, function(n, t) {
-                    o = o || t.direction
-                });
-                u.complete = vt.msie ? function() {
-                    setTimeout(a, 0)
-                } : a;
-                u.previous = u.reverse ? i : t;
-                u.reset = !0;
-                (u.reverse ? t : i).each(function() {
-                    n(this).kendoAnimate(r(!0, {}, u));
-                    u.complete = null;
-                    u.previous = null
-                })
-            }
-        });
-        u.animatedPromise = u.promise;
-        u.animatedTransitionPromise = u.transitionPromise;
-        l = i.Class.extend({
-            init: function(n, t) {
-                var i = this;
-                i.element = n;
-                i._direction = t;
-                i.options = {};
-                i._additionalEffects = [];
-                i.restore || (i.restore = [])
-            },
-            reverse: function() {
-                return this._reverse = !0, this.run()
-            },
-            play: function() {
-                return this._reverse = !1, this.run()
-            },
-            add: function(n) {
-                return this._additionalEffects.push(n), this
-            },
-            direction: function(n) {
-                return this._direction = n, this
-            },
-            duration: function(n) {
-                return this._duration = n, this
-            },
-            compositeRun: function() {
-                var n = this,
-                    t = new ct(n.element, {
-                        reverse: n._reverse,
-                        duration: n._duration
-                    }),
-                    i = n._additionalEffects.concat([n]);
-                return t.run(i)
-            },
-            run: function() {
-                if (this._additionalEffects && this._additionalEffects[0]) return this.compositeRun();
-                var o = this,
-                    t = o.element,
-                    h = 0,
-                    y = o.restore,
-                    w = y.length,
-                    c, l = n.Deferred(),
-                    i = {},
-                    a = {},
-                    v, p = o.children(),
-                    b = p.length;
-                for (l.then(n.proxy(o, "_complete")), t.data("animating", !0), h = 0; h < w; h++) c = y[h], t.data(c) || t.data(c, t.css(c));
-                for (h = 0; h < b; h++) p[h].duration(o._duration).run();
-                return o.prepare(i, a), t.is(":visible") || r(i, {
-                    display: t.data("olddisplay") || "block"
-                }), f && (v = t.data("targetTransform"), v && (i = r(v, i))), i = ht(t, i), f && !s && (i = st(i)), t.css(i).css(e), o.setup(), t.data("targetTransform", a), u.animate(t, a, {
-                    duration: o._duration,
-                    complete: l.resolve
-                }), l.promise()
-            },
-            stop: function() {
-                for (var t = 0, i = this.children(), r = i.length, t = 0; t < r; t++) i[t].stop();
-                return n(this.element).kendoStop(!0, !0), this
-            },
-            restoreCallback: function() {
-                for (var t, i = this.element, n = 0, r = this.restore.length; n < r; n++) t = this.restore[n], i.css(t, i.data(t))
-            },
-            _complete: function() {
-                var t = this,
-                    i = t.element;
-                i.removeData("animating").dequeue();
-                t.restoreCallback();
-                t.shouldHide() && i.data("olddisplay", i.css("display")).hide();
-                yt && !f && setTimeout(n.proxy(t, "restoreCallback"), 0);
-                t.teardown()
-            },
-            setOptions: function(n) {
-                r(!0, this.options, n)
-            },
-            children: function() {
-                return []
-            },
-            shouldHide: n.noop,
-            setup: n.noop,
-            prepare: n.noop,
-            teardown: n.noop,
-            directions: [],
-            setReverse: function(n) {
-                return this._reverse = n, this
-            }
-        });
-        k = ["left", "right", "up", "down"];
-        ui = ["in", "out"];
-        o("slideIn", {
-            directions: k,
-            divisor: function(n) {
-                return this.options.divisor = n, this
-            },
-            prepare: function(n, t) {
-                var r = this,
-                    u, e = r.element,
-                    i = c[r._direction],
-                    h = -i.modifier * (i.vertical ? e.outerHeight() : e.outerWidth()),
-                    o = h / (r.options && r.options.divisor || 1) + w,
-                    s = "0px";
-                r._reverse && (u = n, n = t, t = u);
-                f ? (n[i.transition] = o, t[i.transition] = s) : (n[i.property] = o, t[i.property] = s)
-            }
-        });
-        o("tile", {
-            directions: k,
-            init: function(n, t, i) {
-                l.prototype.init.call(this, n, t);
-                this.options = {
-                    previous: i
-                }
-            },
-            previousDivisor: function(n) {
-                return this.options.previousDivisor = n, this
-            },
-            children: function() {
-                var n = this,
-                    t = n._reverse,
-                    r = n.options.previous,
-                    e = n.options.previousDivisor || 1,
-                    u = n._direction,
-                    f = [i.fx(n.element).slideIn(u).setReverse(t)];
-                return r && f.push(i.fx(r).slideIn(c[u].reverse).divisor(e).setReverse(!t)), f
-            }
-        });
-        fi("fade", "opacity", 1, 0);
-        fi("zoom", "scale", 1, .01);
-        o("slideMargin", {
-            prepare: function(n, t) {
-                var r = this,
-                    i = r.element,
-                    u = r.options,
-                    o = i.data(et),
-                    s = u.offset,
-                    f, e = r._reverse;
-                e || o !== null || i.data(et, parseFloat(i.css("margin-" + u.axis)));
-                f = i.data(et) || 0;
-                t["margin-" + u.axis] = e ? f : f + s
-            }
-        });
-        o("slideTo", {
-            prepare: function(n, t) {
-                var u = this,
-                    e = u.element,
-                    o = u.options,
-                    i = o.offset.split(","),
-                    r = u._reverse;
-                f ? (t.translatex = r ? 0 : i[0], t.translatey = r ? 0 : i[1]) : (t.left = r ? 0 : i[0], t.top = r ? 0 : i[1]);
-                e.css("left")
-            }
-        });
-        o("expand", {
-            directions: ["horizontal", "vertical"],
-            restore: [tt],
-            prepare: function(n, i) {
-                var f = this,
-                    e = f.element,
-                    o = f.options,
-                    s = f._reverse,
-                    r = f._direction === "vertical" ? nt : ft,
-                    h = e[0].style[r],
-                    c = e.data(r),
-                    u = parseFloat(c || h),
-                    l = ki(e.css(r, ut)[r]());
-                n.overflow = bt;
-                u = o && o.reset ? l || u : u || l;
-                i[r] = (s ? 0 : u) + w;
-                n[r] = (s ? u : 0) + w;
-                c === t && e.data(r, h)
-            },
-            shouldHide: function() {
-                return this._reverse
-            },
-            teardown: function() {
-                var t = this,
-                    i = t.element,
-                    n = t._direction === "vertical" ? nt : ft,
-                    r = i.data(n);
-                (r == ut || r === di) && setTimeout(function() {
-                    i.css(n, ut).css(n)
-                }, 0)
-            }
-        });
-        ei = {
-            position: "absolute",
-            marginLeft: 0,
-            marginTop: 0,
-            scale: 1
-        };
-        o("transfer", {
-            init: function(n, t) {
-                this.element = n;
-                this.options = {
-                    target: t
-                };
-                this.restore = []
-            },
-            setup: function() {
-                this.element.appendTo(document.body)
-            },
-            prepare: function(n, t) {
-                var s = this,
-                    i = s.element,
-                    g = s.options,
-                    nt = s._reverse,
-                    h = g.target,
-                    u, tt = ri(i, "scale"),
-                    l = h.offset(),
-                    a = h.outerHeight() / i.outerHeight();
-                r(n, ei);
-                t.scale = 1;
-                i.css(e, "scale(1)").css(e);
-                u = i.offset();
-                i.css(e, "scale(" + tt + ")");
-                var f = 0,
-                    o = 0,
-                    v = l.left - u.left,
-                    y = l.top - u.top,
-                    p = f + i.outerWidth(),
-                    b = o,
-                    it = v + h.outerWidth(),
-                    rt = y,
-                    c = (y - o) / (v - f),
-                    k = (rt - b) / (it - p),
-                    d = (o - b - c * f + k * p) / (k - c),
-                    ut = o + c * (d - f);
-                n.top = u.top;
-                n.left = u.left;
-                n.transformOrigin = d + w + " " + ut + w;
-                nt ? n.scale = a : t.scale = a
-            }
-        });
-        oi = {
-            top: "rect(auto auto $size auto)",
-            bottom: "rect($size auto auto auto)",
-            left: "rect(auto $size auto auto)",
-            right: "rect(auto auto auto $size)"
-        };
-        si = {
-            top: {
-                start: "rotatex(0deg)",
-                end: "rotatex(180deg)"
-            },
-            bottom: {
-                start: "rotatex(-180deg)",
-                end: "rotatex(0deg)"
-            },
-            left: {
-                start: "rotatey(0deg)",
-                end: "rotatey(-180deg)"
-            },
-            right: {
-                start: "rotatey(180deg)",
-                end: "rotatey(0deg)"
-            }
-        };
-        o("turningPage", {
-            directions: k,
-            init: function(n, t, i) {
-                l.prototype.init.call(this, n, t);
-                this._container = i
-            },
-            prepare: function(n, t) {
-                var r = this,
-                    f = r._reverse,
-                    o = f ? c[r._direction].reverse : r._direction,
-                    u = si[o];
-                n.zIndex = 1;
-                r._clipInHalf && (n.clip = hi(r._container, i.directions[o].reverse));
-                n[nr] = bt;
-                t[e] = ni + (f ? u.start : u.end);
-                n[e] = ni + (f ? u.end : u.start)
-            },
-            setup: function() {
-                this._container.append(this.element)
-            },
-            face: function(n) {
-                return this._face = n, this
-            },
-            shouldHide: function() {
-                var n = this,
-                    t = n._reverse,
-                    i = n._face;
-                return t && !i || !t && i
-            },
-            clipInHalf: function(n) {
-                return this._clipInHalf = n, this
-            },
-            temporary: function() {
-                return this.element.addClass("temp-page"), this
-            }
-        });
-        o("staticPage", {
-            directions: k,
-            init: function(n, t, i) {
-                l.prototype.init.call(this, n, t);
-                this._container = i
-            },
-            restore: ["clip"],
-            prepare: function(n, t) {
-                var i = this,
-                    r = i._reverse ? c[i._direction].reverse : i._direction;
-                n.clip = hi(i._container, r);
-                n.opacity = .999;
-                t.opacity = 1
-            },
-            shouldHide: function() {
-                var n = this,
-                    t = n._reverse,
-                    i = n._face;
-                return t && !i || !t && i
-            },
-            face: function(n) {
-                return this._face = n, this
-            }
-        });
-        o("pageturn", {
-            directions: ["horizontal", "vertical"],
-            init: function(n, t, i, r) {
-                l.prototype.init.call(this, n, t);
-                this.options = {};
-                this.options.face = i;
-                this.options.back = r
-            },
-            children: function() {
-                var r = this,
-                    u = r.options,
-                    n = r._direction === "horizontal" ? "left" : "top",
-                    f = i.directions[n].reverse,
-                    t = r._reverse,
-                    o, s = u.face.clone(!0).removeAttr("id"),
-                    h = u.back.clone(!0).removeAttr("id"),
-                    e = r.element;
-                return t && (o = n, n = f, f = o), [i.fx(u.face).staticPage(n, e).face(!0).setReverse(t), i.fx(u.back).staticPage(f, e).setReverse(t), i.fx(s).turningPage(n, e).face(!0).clipInHalf(!0).temporary().setReverse(t), i.fx(h).turningPage(f, e).clipInHalf(!0).temporary().setReverse(t)]
-            },
-            prepare: function(n, t) {
-                n[gt] = ot;
-                n.transformStyle = "preserve-3d";
-                n.opacity = .999;
-                t.opacity = 1
-            },
-            teardown: function() {
-                this.element.find(".temp-page").remove()
-            }
-        });
-        o("flip", {
-            directions: ["horizontal", "vertical"],
-            init: function(n, t, i, r) {
-                l.prototype.init.call(this, n, t);
-                this.options = {};
-                this.options.face = i;
-                this.options.back = r
-            },
-            children: function() {
-                var n = this,
-                    f = n.options,
-                    t = n._direction === "horizontal" ? "left" : "top",
-                    r = i.directions[t].reverse,
-                    u = n._reverse,
-                    e, o = n.element;
-                return u && (e = t, t = r, r = e), [i.fx(f.face).turningPage(t, o).face(!0).setReverse(u), i.fx(f.back).turningPage(r, o).setReverse(u)]
-            },
-            prepare: function(n) {
-                n[gt] = ot;
-                n.transformStyle = "preserve-3d"
-            }
-        });
-        it = i.Class.extend({
-            init: function() {
-                var n = this;
-                n._tickProxy = ci(n._tick, n);
-                n._started = !1
-            },
-            tick: n.noop,
-            done: n.noop,
-            onEnd: n.noop,
-            onCancel: n.noop,
-            start: function() {
-                this.done() || (this._started = !0, i.animationFrame(this._tickProxy))
-            },
-            cancel: function() {
-                this._started = !1;
-                this.onCancel()
-            },
-            _tick: function() {
-                var n = this;
-                n._started && (n.tick(), n.done() ? (n._started = !1, n.onEnd()) : i.queueAnimation(n._tickProxy))
-            }
-        });
-        at = it.extend({
-            init: function(n) {
-                var t = this;
-                r(t, n);
-                it.fn.init.call(t)
-            },
-            done: function() {
-                return this.timePassed() >= this.duration
-            },
-            timePassed: function() {
-                return Math.min(this.duration, new Date - this.startDate)
-            },
-            moveTo: function(n) {
-                var t = this,
-                    i = t.movable;
-                t.initial = i[t.axis];
-                t.delta = n.location - t.initial;
-                t.duration = typeof n.duration == "number" ? n.duration : 300;
-                t.tick = t._easeProxy(n.ease);
-                t.startDate = new Date;
-                t.start()
-            },
-            _easeProxy: function(n) {
-                var t = this;
-                return function() {
-                    t.movable.moveAxis(t.axis, n(t.timePassed(), t.initial, t.delta, t.duration))
-                }
-            }
-        });
-        r(at, {
-            easeOutExpo: function(n, t, i, r) {
-                return n == r ? t + i : i * (-Math.pow(2, -10 * n / r) + 1) + t
-            },
-            easeOutBack: function(n, t, i, r, u) {
-                return u = 1.70158, i * ((n = n / r - 1) * n * ((u + 1) * n + u) + 1) + t
-            }
-        });
-        u.Animation = it;
-        u.Transition = at;
-        u.createEffect = o
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "data",
-        name: "Data source",
-        category: "framework",
-        description: "Powerful component for using local and remote data.Fully supports CRUD, Sorting, Paging, Filtering, Grouping, and Aggregates.",
-        depends: ["core"],
-        features: [{
-            id: "data-odata",
-            name: "OData",
-            description: "Support for accessing Open Data Protocol (OData) services.",
-            depends: ["data.odata"]
-        }, {
-            id: "data-XML",
-            name: "XML",
-            description: "Support for binding to XML.",
-            depends: ["data.xml"]
-        }]
-    }),
-    function(n, t) {
-        function gt(n, t, i, u) {
-            return function(f) {
-                var e = {};
-                for (var o in f) e[o] = f[o];
-                e.field = u ? i + "." + f.field : i;
-                t == r && n._notifyChange && n._notifyChange(e);
-                n.trigger(t, e)
-            }
-        }
-
-        function li(t, i) {
-            if (t === i) return !0;
-            var r = n.type(t),
-                f = n.type(i),
-                u;
-            if (r !== f) return !1;
-            if (r === "date") return t.getTime() === i.getTime();
-            if (r !== "object" && r !== "array") return !1;
-            for (u in t)
-                if (!li(t[u], i[u])) return !1;
-            return !0
-        }
-
-        function ou(n, t) {
-            var i;
-            for (var r in n)
-                if ((i = n[r], l(i) && i.field && i.field === t) || i === t) return i;
-            return null
-        }
-
-        function u(n) {
-            this.data = n || []
-        }
-
-        function it(n, i) {
-            if (n) {
-                var r = typeof n === o ? {
-                        field: n,
-                        dir: i
-                    } : n,
-                    u = d(r) ? r : r !== t ? [r] : [];
-                return pr(u, function(n) {
-                    return !!n.dir
-                })
-            }
-        }
-
-        function wi(n) {
-            var i, f, r, t, u = n.filters;
-            if (u)
-                for (i = 0, f = u.length; i < f; i++) r = u[i], t = r.operator, t && typeof t === o && (r.operator = pi[t.toLowerCase()] || t), wi(r)
-        }
-
-        function ct(n) {
-            if (n && !k(n)) return (d(n) || !n.filters) && (n = {
-                logic: "and",
-                filters: d(n) ? n : [n]
-            }), wi(n), n
-        }
-
-        function su(n) {
-            return d(n) ? n : [n]
-        }
-
-        function rt(n, i) {
-            var r = typeof n === o ? {
-                    field: n,
-                    dir: i
-                } : n,
-                u = d(r) ? r : r !== t ? [r] : [];
-            return vt(u, function(n) {
-                return {
-                    field: n.field,
-                    dir: n.dir || "asc",
-                    aggregates: n.aggregates
-                }
-            })
-        }
-
-        function hu(n, t) {
-            return n && n.getTime && t && t.getTime ? n.getTime() === t.getTime() : n === t
-        }
-
-        function cu(n, t, r, u, f) {
-            var o, h, s, c, e;
-            for (t = t || [], c = t.length, o = 0; o < c; o++) h = t[o], s = h.aggregate, e = h.field, n[e] = n[e] || {}, n[e][s] = bi[s.toLowerCase()](n[e][s], r, i.accessor(e), u, f)
-        }
-
-        function ki(n) {
-            return typeof n == "number" && !isNaN(n)
-        }
-
-        function lu(n) {
-            for (var i = n.length, r = new Array(i), t = 0; t < i; t++) r[t] = n[t].toJSON();
-            return r
-        }
-
-        function di(n, t) {
-            t = t || {};
-            var i = new u(n),
-                f = t.aggregate,
-                r = t.filter;
-            return r && (i = i.filter(r)), i.aggregate(f)
-        }
-
-        function au(n, t, i, r, u) {
-            for (var e, f, o, s = 0, h = n.length; s < h; s++) {
-                e = n[s];
-                for (f in t) o = u[f], o && o !== f && (e[o] = t[f](e), delete e[f])
-            }
-        }
-
-        function tr(n, t, i, r, u) {
-            for (var e, f, o, s = 0, h = n.length; s < h; s++) {
-                e = n[s];
-                for (f in t) e[f] = i._parse(f, t[f](e)), o = u[f], o && o !== f && delete e[o]
-            }
-        }
-
-        function ir(n, t, i, r, u) {
-            for (var f, o, e = 0, s = n.length; e < s; e++) f = n[e], o = r[f.field], o && o != f.field && (f.field = o), f.value = i._parse(f.field, f.value), f.hasSubgroups ? ir(f.items, t, i, r, u) : tr(f.items, t, i, r, u)
-        }
-
-        function ni(n, t, i, r, u, f) {
-            return function(e) {
-                return e = n(e), e && !k(r) && (st.call(e) === "[object Array]" || e instanceof p || (e = [e]), i(e, r, new t, u, f)), e || []
-            }
-        }
-
-        function ii(n, t, i, r) {
-            for (var f, e = 0, u, o; t.length && r;)
-                if (f = t[e], u = f.items, o = u.length, n && n.field === f.field && n.value === f.value ? (n.hasSubgroups && n.items.length ? ii(n.items[n.items.length - 1], f.items, i, r) : (u = u.slice(i, i + r), n.items = n.items.concat(u)), t.splice(e--, 1)) : f.hasSubgroups && u.length ? ii(f, u, i, r) : (u = u.slice(i, i + r), f.items = u, f.items.length || t.splice(e--, 1)), u.length === 0 ? i -= o : (i = 0, r -= u.length), ++e >= t.length) break;
-            e < t.length && t.splice(e, t.length - e)
-        }
-
-        function rr(n) {
-            for (var i = [], t = 0, r = n.length; t < r; t++) i = n[t].hasSubgroups ? i.concat(rr(n[t].items)) : i.concat(n[t].items.slice());
-            return i
-        }
-
-        function ur(n, t) {
-            var r, f, u, i;
-            if (t)
-                for (r = 0, f = n.length; r < f; r++) u = n[r], i = u.items, u.hasSubgroups ? ur(i, t) : !i.length || i[0] instanceof t || (i.type = t, i.wrapAll(i, i))
-        }
-
-        function fr(n, t) {
-            for (var i = 0, r = n.length; i < r; i++)
-                if (n[i].hasSubgroups) {
-                    if (fr(n[i].items, t)) return !0
-                } else if (t(n[i].items, n[i])) return !0
-        }
-
-        function vu(n, t) {
-            for (var i = 0, r = n.length; i < r; i++)
-                if (n[i].uid == t.uid) return t = n[i], n.splice(i, 1), t
-        }
-
-        function er(n, t) {
-            for (var i, u, r = n.length - 1, f = 0; r >= f; r--) u = n[r], i = {
-                value: t.get(u.field),
-                field: u.field,
-                items: i ? [i] : [t],
-                hasSubgroups: !!i,
-                aggregates: {}
-            };
-            return i
-        }
-
-        function or(n, t) {
-            return t ? hr(n, function(n) {
-                return n[t.idField] === t.id
-            }) : -1
-        }
-
-        function sr(n, t) {
-            return t ? hr(n, function(n) {
-                return n.uid == t.uid
-            }) : -1
-        }
-
-        function hr(n, t) {
-            for (var i = 0, r = n.length; i < r; i++)
-                if (t(n[i])) return i;
-            return -1
-        }
-
-        function cr(n, t) {
-            if (n && !k(n)) {
-                var i = n[t],
-                    r;
-                return (r = l(i) ? i.from || i.field || t : n[t] || t, y(r)) ? t : r
-            }
-            return t
-        }
-
-        function lr(n, t) {
-            var r, f, i = {};
-            for (var u in n) u !== "filters" && (i[u] = n[u]);
-            if (n.filters)
-                for (i.filters = [], r = 0, f = n.filters.length; r < f; r++) i.filters[r] = lr(n.filters[r], t);
-            else i.field = cr(t.fields, i.field);
-            return i
-        }
-
-        function lt(n, t) {
-            for (var o = [], i, u, f, r = 0, e = n.length; r < e; r++) {
-                i = {};
-                u = n[r];
-                for (f in u) i[f] = u[f];
-                i.field = cr(t.fields, i.field);
-                i.aggregates && d(i.aggregates) && (i.aggregates = lt(i.aggregates, t));
-                o.push(i)
-            }
-            return o
-        }
-
-        function yu(t, i) {
-            for (var o = n(t)[0].children, h = [], e, c = i[0], l = i[1], u, r, f = 0, s = o.length; f < s; f++)(e = {}, r = o[f], r.disabled) || (e[c.field] = r.text, u = r.attributes.value, u = u && u.specified ? r.value : r.text, e[l.field] = u, h.push(e));
-            return h
-        }
-
-        function pu(t, i) {
-            for (var s = n(t)[0].tBodies[0], h = s ? s.rows : [], r, v = i.length, l = [], a, f, e, o, u = 0, c = h.length; u < c; u++) {
-                for (f = {}, o = !0, a = h[u].cells, r = 0; r < v; r++) e = a[r], e.nodeName.toLowerCase() !== "th" && (o = !1, f[i[r].field] = e.innerHTML);
-                o || l.push(f)
-            }
-            return l
-        }
-
-        function ar(n) {
-            return function() {
-                var t = this._data,
-                    i = h.fn[n].apply(this, dt.call(arguments));
-                return this._data != t && this._attachBubbleHandlers(), i
-            }
-        }
-
-        function vr(t, i) {
-            function c(n, t) {
-                return n.filter(t).add(n.find(t))
-            }
-            for (var l = n(t).children(), v = [], r, b = i[0].field, y = i[1] && i[1].field, p = i[2] && i[2].field, w = i[3] && i[3].field, f, s, o, h, u, e = 0, a = l.length; e < a; e++) r = {
-                _loaded: !0
-            }, f = l.eq(e), o = f[0].firstChild, u = f.children(), t = u.filter("ul"), u = u.filter(":not(ul)"), s = f.attr("data-id"), s && (r.id = s), o && (r[b] = o.nodeType == 3 ? o.nodeValue : u.text()), y && (r[y] = c(u, "a").attr("href")), w && (r[w] = c(u, "img").attr("src")), p && (h = c(u, ".k-sprite").prop("className"), r[p] = h && n.trim(h.replace("k-sprite", ""))), t.length && (r.items = vr(t.eq(0), i)), f.attr("data-hasChildren") == "true" && (r.hasChildren = !0), v.push(r);
-            return v
-        }
-        var e = n.extend,
-            v = n.proxy,
-            l = n.isPlainObject,
-            k = n.isEmptyObject,
-            d = n.isArray,
-            pr = n.grep,
-            at = n.ajax,
-            vt, yt = n.each,
-            b = n.noop,
-            i = window.kendo,
-            y = i.isFunction,
-            g = i.Observable,
-            ft = i.Class,
-            o = "string",
-            pt = "function",
-            ei = "create",
-            oi = "read",
-            si = "update",
-            hi = "destroy",
-            r = "change",
-            ci = "sync",
-            wt = "get",
-            a = "error",
-            tt = "requestStart",
-            bt = "progress",
-            nt = "requestEnd",
-            wr = [ei, oi, si, hi],
-            et = function(n) {
-                return n
-            },
-            ot = i.getter,
-            kt = i.stringify,
-            f = Math,
-            br = [].push,
-            kr = [].join,
-            dr = [].pop,
-            gr = [].splice,
-            nu = [].shift,
-            dt = [].slice,
-            tu = [].unshift,
-            st = {}.toString,
-            iu = i.support.stableSort,
-            ru = /^\/Date\((.*?)\)\/$/,
-            uu = /(\r+|\n+)/g,
-            fu = /(?=['\\])/g,
-            p = g.extend({
-                init: function(n, t) {
-                    var i = this;
-                    i.type = t || s;
-                    g.fn.init.call(i);
-                    i.length = n.length;
-                    i.wrapAll(n, i)
-                },
-                toJSON: function() {
-                    for (var i = this.length, t, r = new Array(i), n = 0; n < i; n++) t = this[n], t instanceof s && (t = t.toJSON()), r[n] = t;
-                    return r
-                },
-                parent: b,
-                wrapAll: function(n, t) {
-                    var r = this,
-                        i, u, f = function() {
-                            return r
-                        };
-                    for (t = t || [], i = 0, u = n.length; i < u; i++) t[i] = r.wrap(n[i], f);
-                    return t
-                },
-                wrap: function(n, t) {
-                    var i = this,
-                        u;
-                    return n !== null && st.call(n) === "[object Object]" && (u = n instanceof i.type || n instanceof c, u || (n = n instanceof s ? n.toJSON() : n, n = new i.type(n)), n.parent = t, n.bind(r, function(n) {
-                        i.trigger(r, {
-                            field: n.field,
-                            node: n.node,
-                            index: n.index,
-                            items: n.items || [this],
-                            action: n.node ? n.action || "itemchange" : "itemchange"
-                        })
-                    })), n
-                },
-                push: function() {
-                    var i = this.length,
-                        n = this.wrapAll(arguments),
-                        t;
-                    return t = br.apply(this, n), this.trigger(r, {
-                        action: "add",
-                        index: i,
-                        items: n
-                    }), t
-                },
-                slice: dt,
-                join: kr,
-                pop: function() {
-                    var n = this.length,
-                        t = dr.apply(this);
-                    return n && this.trigger(r, {
-                        action: "remove",
-                        index: n - 1,
-                        items: [t]
-                    }), t
-                },
-                splice: function(n, t, i) {
-                    var e = this.wrapAll(dt.call(arguments, 2)),
-                        u, f, o;
-                    if (u = gr.apply(this, [n, t].concat(e)), u.length)
-                        for (this.trigger(r, {
-                                action: "remove",
-                                index: n,
-                                items: u
-                            }), f = 0, o = u.length; f < o; f++) u[f].children && u[f].unbind(r);
-                    return i && this.trigger(r, {
-                        action: "add",
-                        index: n,
-                        items: e
-                    }), u
-                },
-                shift: function() {
-                    var t = this.length,
-                        n = nu.apply(this);
-                    return t && this.trigger(r, {
-                        action: "remove",
-                        index: 0,
-                        items: [n]
-                    }), n
-                },
-                unshift: function() {
-                    var n = this.wrapAll(arguments),
-                        t;
-                    return t = tu.apply(this, n), this.trigger(r, {
-                        action: "add",
-                        index: 0,
-                        items: n
-                    }), t
-                },
-                indexOf: function(n) {
-                    for (var i = this, t = 0, r = i.length; t < r; t++)
-                        if (i[t] === n) return t;
-                    return -1
-                },
-                forEach: function(n) {
-                    for (var t = 0, i = this.length; t < i; t++) n(this[t], t, this)
-                },
-                map: function(n) {
-                    for (var t = 0, i = [], r = this.length; t < r; t++) i[t] = n(this[t], t, this);
-                    return i
-                },
-                filter: function(n) {
-                    for (var t = 0, i = [], r, u = this.length; t < u; t++) r = this[t], n(r, t, this) && (i[i.length] = r);
-                    return i
-                },
-                find: function(n) {
-                    for (var t = 0, i, r = this.length; t < r; t++)
-                        if (i = this[t], n(i, t, this)) return i
-                },
-                every: function(n) {
-                    for (var t = 0, i, r = this.length; t < r; t++)
-                        if (i = this[t], !n(i, t, this)) return !1;
-                    return !0
-                },
-                some: function(n) {
-                    for (var t = 0, i, r = this.length; t < r; t++)
-                        if (i = this[t], n(i, t, this)) return !0;
-                    return !1
-                },
-                remove: function(n) {
-                    this.splice(this.indexOf(n), 1)
-                },
-                empty: function() {
-                    this.splice(0, this.length)
-                }
-            }),
-            s = g.extend({
-                init: function(n) {
-                    var r = this,
-                        u, t, f = function() {
-                            return r
-                        };
-                    g.fn.init.call(this);
-                    for (t in n) u = n[t], t.charAt(0) != "_" && (u = r.wrap(u, t, f)), r[t] = u;
-                    r.uid = i.guid()
-                },
-                shouldSerialize: function(n) {
-                    return this.hasOwnProperty(n) && n !== "_events" && typeof this[n] !== pt && n !== "uid"
-                },
-                forEach: function(n) {
-                    for (var t in this) this.shouldSerialize(t) && n(this[t], t)
-                },
-                toJSON: function() {
-                    var i = {},
-                        n;
-                    for (var t in this) this.shouldSerialize(t) && (n = this[t], (n instanceof s || n instanceof p) && (n = n.toJSON()), i[t] = n);
-                    return i
-                },
-                get: function(n) {
-                    var t = this;
-                    return t.trigger(wt, {
-                        field: n
-                    }), n === "this" ? t : i.getter(n, !0)(t)
-                },
-                _set: function(n, t) {
-                    var o = this,
-                        f = n.indexOf(".") >= 0,
-                        r, u, e;
-                    if (f)
-                        for (r = n.split("."), u = ""; r.length > 1;) {
-                            if (u += r.shift(), e = i.getter(u, !0)(o), e instanceof s) return e.set(r.join("."), t), f;
-                            u += "."
-                        }
-                    return i.setter(n)(o, t), f
-                },
-                set: function(n, t) {
-                    var u = this,
-                        f = i.getter(n, !0)(u);
-                    f !== t && (u.trigger("set", {
-                        field: n,
-                        value: t
-                    }) || (!u._set(n, u.wrap(t, n, function() {
-                        return u
-                    })) || n.indexOf("(") >= 0 || n.indexOf("[") >= 0) && u.trigger(r, {
-                        field: n
-                    }))
-                },
-                parent: b,
-                wrap: function(n, t, i) {
-                    var o = this,
-                        u = st.call(n),
-                        f, e;
-                    return n != null && (u === "[object Object]" || u === "[object Array]") && (f = n instanceof p, e = n instanceof h, u !== "[object Object]" || e || f ? (u === "[object Array]" || f || e) && (f || e || (n = new p(n)), n.parent() != i() && n.bind(r, gt(o, r, t, !1))) : (n instanceof s || (n = new s(n)), n.parent() != i() && (n.bind(wt, gt(o, wt, t, !0)), n.bind(r, gt(o, r, t, !0)))), n.parent = i), n
-                }
-            }),
-            ai = {
-                number: function(n) {
-                    return i.parseFloat(n)
-                },
-                date: function(n) {
-                    return i.parseDate(n)
-                },
-                boolean: function(n) {
-                    return typeof n === o ? n.toLowerCase() === "true" : n != null ? !!n : n
-                },
-                string: function(n) {
-                    return n != null ? n + "" : n
-                },
-                "default": function(n) {
-                    return n
-                }
-            },
-            eu = {
-                string: "",
-                number: 0,
-                date: new Date,
-                boolean: !1,
-                "default": ""
-            },
-            c = s.extend({
-                init: function(i) {
-                    var r = this;
-                    (!i || n.isEmptyObject(i)) && (i = n.extend({}, r.defaults, i));
-                    s.fn.init.call(r, i);
-                    r.dirty = !1;
-                    r.idField && (r.id = r.get(r.idField), r.id === t && (r.id = r._defaultId))
-                },
-                shouldSerialize: function(n) {
-                    return s.fn.shouldSerialize.call(this, n) && n !== "uid" && !(this.idField !== "id" && n === "id") && n !== "dirty" && n !== "_accessors"
-                },
-                _parse: function(n, t) {
-                    var u = this,
-                        f = n,
-                        r = u.fields || {},
-                        i;
-                    return n = r[n], n || (n = ou(r, f)), n && (i = n.parse, !i && n.type && (i = ai[n.type.toLowerCase()])), i ? i(t) : t
-                },
-                _notifyChange: function(n) {
-                    var t = n.action;
-                    (t == "add" || t == "remove") && (this.dirty = !0)
-                },
-                editable: function(n) {
-                    return n = (this.fields || {})[n], n ? n.editable !== !1 : !0
-                },
-                set: function(n, t, i) {
-                    var r = this;
-                    r.editable(n) && (t = r._parse(n, t), li(t, r.get(n)) || (r.dirty = !0, s.fn.set.call(r, n, t, i)))
-                },
-                accept: function(n) {
-                    var t = this,
-                        u = function() {
-                            return t
-                        },
-                        i, r;
-                    for (i in n) r = n[i], i.charAt(0) != "_" && (r = t.wrap(n[i], i, u)), t._set(i, r);
-                    t.idField && (t.id = t.get(t.idField));
-                    t.dirty = !1
-                },
-                isNew: function() {
-                    return this.id === this._defaultId
-                }
-            }),
-            ht, vi, yi, pi, bi, ti, h, ri, ui, w, fi, yr;
-        c.define = function(n, i) {
-            i === t && (i = n, n = c);
-            var s, r = e({
-                    defaults: {}
-                }, i),
-                f, u, y, l, a, w, p = {},
-                h, v = r.id;
-            if (v && (r.idField = v), r.id && delete r.id, v && (r.defaults[v] = r._defaultId = ""), st.call(r.fields) === "[object Array]") {
-                for (a = 0, w = r.fields.length; a < w; a++) u = r.fields[a], typeof u === o ? p[u] = {} : u.field && (p[u.field] = u);
-                r.fields = p
-            }
-            for (f in r.fields) u = r.fields[f], y = u.type || "default", l = null, h = f, f = typeof u.field === o ? u.field : f, u.nullable || (l = r.defaults[h !== f ? h : f] = u.defaultValue !== t ? u.defaultValue : eu[y.toLowerCase()]), i.id === f && (r._defaultId = l), r.defaults[h !== f ? h : f] = l, u.parse = u.parse || ai[y];
-            return s = n.extend(r), s.define = function(n) {
-                return c.define(s, n)
-            }, r.fields && (s.fields = r.fields, s.idField = r.idField), s
-        };
-        ht = {
-            selector: function(n) {
-                return y(n) ? n : ot(n)
-            },
-            compare: function(n) {
-                var t = this.selector(n);
-                return function(n, i) {
-                    return (n = t(n), i = t(i), n == null && i == null) ? 0 : n == null ? -1 : i == null ? 1 : n.localeCompare ? n.localeCompare(i) : n > i ? 1 : n < i ? -1 : 0
-                }
-            },
-            create: function(n) {
-                var t = n.compare || this.compare(n.field);
-                return n.dir == "desc" ? function(n, i) {
-                    return t(i, n, !0)
-                } : t
-            },
-            combine: function(n) {
-                return function(t, i) {
-                    for (var u = n[0](t, i), r = 1, f = n.length; r < f; r++) u = u || n[r](t, i);
-                    return u
-                }
-            }
-        };
-        vi = e({}, ht, {
-            asc: function(n) {
-                var t = this.selector(n);
-                return function(n, i) {
-                    var r = t(n),
-                        u = t(i);
-                    return (r && r.getTime && u && u.getTime && (r = r.getTime(), u = u.getTime()), r === u) ? n.__position - i.__position : r == null ? -1 : u == null ? 1 : r.localeCompare ? r.localeCompare(u) : r > u ? 1 : -1
-                }
-            },
-            desc: function(n) {
-                var t = this.selector(n);
-                return function(n, i) {
-                    var u = t(n),
-                        r = t(i);
-                    return (u && u.getTime && r && r.getTime && (u = u.getTime(), r = r.getTime()), u === r) ? n.__position - i.__position : u == null ? 1 : r == null ? -1 : r.localeCompare ? r.localeCompare(u) : u < r ? 1 : -1
-                }
-            },
-            create: function(n) {
-                return this[n.dir](n.field)
-            }
-        });
-        vt = function(n, t) {
-            for (var r = n.length, u = new Array(r), i = 0; i < r; i++) u[i] = t(n[i], i, n);
-            return u
-        };
-        yi = function() {
-            function t(n) {
-                return n.replace(fu, "\\").replace(uu, "")
-            }
-
-            function n(n, i, r, u) {
-                var f;
-                return r != null && (typeof r === o && (r = t(r), f = ru.exec(r), f ? r = new Date(+f[1]) : u ? (r = "'" + r.toLowerCase() + "'", i = "(" + i + " || '').toLowerCase()") : r = "'" + r + "'"), r.getTime && (i = "(" + i + "?" + i + ".getTime():" + i + ")", r = r.getTime())), i + " " + n + " " + r
-            }
-            return {
-                eq: function(t, i, r) {
-                    return n("==", t, i, r)
-                },
-                neq: function(t, i, r) {
-                    return n("!=", t, i, r)
-                },
-                gt: function(t, i, r) {
-                    return n(">", t, i, r)
-                },
-                gte: function(t, i, r) {
-                    return n(">=", t, i, r)
-                },
-                lt: function(t, i, r) {
-                    return n("<", t, i, r)
-                },
-                lte: function(t, i, r) {
-                    return n("<=", t, i, r)
-                },
-                startswith: function(n, i, r) {
-                    return r && (n = "(" + n + " || '').toLowerCase()", i && (i = i.toLowerCase())), i && (i = t(i)), n + ".lastIndexOf('" + i + "', 0) == 0"
-                },
-                endswith: function(n, i, r) {
-                    return r && (n = "(" + n + " || '').toLowerCase()", i && (i = i.toLowerCase())), i && (i = t(i)), n + ".indexOf('" + i + "', " + n + ".length - " + (i || "").length + ") >= 0"
-                },
-                contains: function(n, i, r) {
-                    return r && (n = "(" + n + " || '').toLowerCase()", i && (i = i.toLowerCase())), i && (i = t(i)), n + ".indexOf('" + i + "') >= 0"
-                },
-                doesnotcontain: function(n, i, r) {
-                    return r && (n = "(" + n + " || '').toLowerCase()", i && (i = i.toLowerCase())), i && (i = t(i)), n + ".indexOf('" + i + "') == -1"
-                }
-            }
-        }();
-        u.filterExpr = function(n) {
-            for (var l = [], r, f, e = [], o = [], h, c, v = n.filters, s = 0, a = v.length; s < a; s++) r = v[s], h = r.field, c = r.operator, r.filters ? (f = u.filterExpr(r), r = f.expression.replace(/__o\[(\d+)\]/g, function(n, t) {
-                return t = +t, "__o[" + (o.length + t) + "]"
-            }).replace(/__f\[(\d+)\]/g, function(n, t) {
-                return t = +t, "__f[" + (e.length + t) + "]"
-            }), o.push.apply(o, f.operators), e.push.apply(e, f.fields)) : (typeof h === pt ? (f = "__f[" + e.length + "](d)", e.push(h)) : f = i.expr(h), typeof c === pt ? (r = "__o[" + o.length + "](" + f + ", " + r.value + ")", o.push(c)) : r = yi[(c || "eq").toLowerCase()](f, r.value, r.ignoreCase !== t ? r.ignoreCase : !0)), l.push(r);
-            return {
-                expression: "(" + l.join({
-                    and: " && ",
-                    or: " || "
-                }[n.logic]) + ")",
-                fields: e,
-                operators: o
-            }
-        };
-        pi = {
-            "==": "eq",
-            equals: "eq",
-            isequalto: "eq",
-            equalto: "eq",
-            equal: "eq",
-            "!=": "neq",
-            ne: "neq",
-            notequals: "neq",
-            isnotequalto: "neq",
-            notequalto: "neq",
-            notequal: "neq",
-            "<": "lt",
-            islessthan: "lt",
-            lessthan: "lt",
-            less: "lt",
-            "<=": "lte",
-            le: "lte",
-            islessthanorequalto: "lte",
-            lessthanequal: "lte",
-            ">": "gt",
-            isgreaterthan: "gt",
-            greaterthan: "gt",
-            greater: "gt",
-            ">=": "gte",
-            isgreaterthanorequalto: "gte",
-            greaterthanequal: "gte",
-            ge: "gte",
-            notsubstringof: "doesnotcontain"
-        };
-        u.normalizeFilter = ct;
-        u.prototype = {
-            toArray: function() {
-                return this.data
-            },
-            range: function(n, t) {
-                return new u(this.data.slice(n, n + t))
-            },
-            skip: function(n) {
-                return new u(this.data.slice(n))
-            },
-            take: function(n) {
-                return new u(this.data.slice(0, n))
-            },
-            select: function(n) {
-                return new u(vt(this.data, n))
-            },
-            order: function(n, t) {
-                var i = {
-                    dir: t
-                };
-                return n && (n.compare ? i.compare = n.compare : i.field = n), new u(this.data.slice(0).sort(ht.create(i)))
-            },
-            orderBy: function(n) {
-                return this.order(n, "asc")
-            },
-            orderByDescending: function(n) {
-                return this.order(n, "desc")
-            },
-            sort: function(n, t, i) {
-                var r, f, u = it(n, t),
-                    e = [];
-                if (i = i || ht, u.length) {
-                    for (r = 0, f = u.length; r < f; r++) e.push(i.create(u[r]));
-                    return this.orderBy({
-                        compare: i.combine(e)
-                    })
-                }
-                return this
-            },
-            filter: function(n) {
-                var t, r, s, i, h, c = this.data,
-                    f, e, l = [],
-                    o;
-                if (n = ct(n), !n || n.filters.length === 0) return this;
-                for (i = u.filterExpr(n), f = i.fields, e = i.operators, h = o = new Function("d, __f, __o", "return " + i.expression), (f.length || e.length) && (o = function(n) {
-                        return h(n, f, e)
-                    }), t = 0, s = c.length; t < s; t++) r = c[t], o(r) && l.push(r);
-                return new u(l)
-            },
-            group: function(n, t) {
-                n = rt(n || []);
-                t = t || this.data;
-                var f = this,
-                    i = new u(f.data),
-                    r;
-                return n.length > 0 && (r = n[0], i = i.groupBy(r).select(function(i) {
-                    var f = new u(t).filter([{
-                        field: i.field,
-                        operator: "eq",
-                        value: i.value,
-                        ignoreCase: !1
-                    }]);
-                    return {
-                        field: i.field,
-                        value: i.value,
-                        items: n.length > 1 ? new u(i.items).group(n.slice(1), f.toArray()).toArray() : i.items,
-                        hasSubgroups: n.length > 1,
-                        aggregates: f.aggregate(r.aggregates)
-                    }
-                })), i
-            },
-            groupBy: function(n) {
-                if (k(n) || !this.data.length) return new u([]);
-                for (var t = n.field, o = this._sortForGrouping(t, n.dir || "asc"), c = i.accessor(t), s, r = c.get(o[0], t), f = {
-                        field: t,
-                        value: r,
-                        items: []
-                    }, h, a = [f], e = 0, l = o.length; e < l; e++) s = o[e], h = c.get(s, t), hu(r, h) || (r = h, f = {
-                    field: t,
-                    value: r,
-                    items: []
-                }, a.push(f)), f.items.push(s);
-                return new u(a)
-            },
-            _sortForGrouping: function(n, t) {
-                var i, f, r = this.data;
-                if (!iu) {
-                    for (i = 0, f = r.length; i < f; i++) r[i].__position = i;
-                    for (r = new u(r).sort(n, t, vi).toArray(), i = 0, f = r.length; i < f; i++) delete r[i].__position;
-                    return r
-                }
-                return this.sort(n, t).toArray()
-            },
-            aggregate: function(n) {
-                var t, i, r = {};
-                if (n && n.length)
-                    for (t = 0, i = this.data.length; t < i; t++) cu(r, n, this.data[t], t, i);
-                return r
-            }
-        };
-        bi = {
-            sum: function(n, t, i) {
-                return (n || 0) + i.get(t)
-            },
-            count: function(n) {
-                return (n || 0) + 1
-            },
-            average: function(n, t, i, r, u) {
-                return n = (n || 0) + i.get(t), r == u - 1 && (n = n / u), n
-            },
-            max: function(n, t, i) {
-                var r = i.get(t);
-                return n = n || 0, n < r && (n = r), n
-            },
-            min: function(n, t, i) {
-                var r = i.get(t);
-                return ki(n) || (n = r), n > r && ki(r) && (n = r), n
-            }
-        };
-        u.process = function(n, i) {
-            i = i || {};
-            var r = new u(n),
-                f = i.group,
-                e = rt(f || []).concat(it(i.sort || [])),
-                o, s = i.filter,
-                h = i.skip,
-                c = i.take;
-            return s && (r = r.filter(s), o = r.toArray().length), e && (r = r.sort(e), f && (n = r.toArray())), h !== t && c !== t && (r = r.range(h, c)), f && (r = r.group(f, n)), {
-                total: o,
-                data: r.toArray()
-            }
-        };
-        var gi = ft.extend({
-                init: function(n) {
-                    this.data = n.data
-                },
-                read: function(n) {
-                    n.success(this.data)
-                },
-                update: function(n) {
-                    n.success(n.data)
-                },
-                create: function(n) {
-                    n.success(n.data)
-                },
-                destroy: function(n) {
-                    n.success(n.data)
-                }
-            }),
-            nr = ft.extend({
-                init: function(n) {
-                    var i = this,
-                        t;
-                    n = i.options = e({}, i.options, n);
-                    yt(wr, function(t, i) {
-                        typeof n[i] === o && (n[i] = {
-                            url: n[i]
-                        })
-                    });
-                    i.cache = n.cache ? ut.create(n.cache) : {
-                        find: b,
-                        add: b
-                    };
-                    t = n.parameterMap;
-                    i.parameterMap = y(t) ? t : function(n) {
-                        var i = {};
-                        return yt(n, function(n, r) {
-                            n in t && (n = t[n], l(n) && (r = n.value(r), n = n.key));
-                            i[n] = r
-                        }), i
-                    }
-                },
-                options: {
-                    parameterMap: et
-                },
-                create: function(n) {
-                    return at(this.setup(n, ei))
-                },
-                read: function(i) {
-                    var f = this,
-                        r, o, u, e = f.cache;
-                    i = f.setup(i, oi);
-                    r = i.success || b;
-                    o = i.error || b;
-                    u = e.find(i.data);
-                    u !== t ? r(u) : (i.success = function(n) {
-                        e.add(i.data, n);
-                        r(n)
-                    }, n.ajax(i))
-                },
-                update: function(n) {
-                    return at(this.setup(n, si))
-                },
-                destroy: function(n) {
-                    return at(this.setup(n, hi))
-                },
-                setup: function(n, t) {
-                    n = n || {};
-                    var u = this,
-                        r, i = u.options[t],
-                        f = y(i.data) ? i.data(n.data) : i.data;
-                    return n = e(!0, {}, i, n), r = e(!0, {}, f, n.data), n.data = u.parameterMap(r, t), y(n.url) && (n.url = n.url(r)), n
-                }
-            }),
-            ut = ft.extend({
-                init: function() {
-                    this._store = {}
-                },
-                add: function(n, i) {
-                    n !== t && (this._store[kt(n)] = i)
-                },
-                find: function(n) {
-                    return this._store[kt(n)]
-                },
-                clear: function() {
-                    this._store = {}
-                },
-                remove: function(n) {
-                    delete this._store[kt(n)]
-                }
-            });
-        ut.create = function(n) {
-            var t = {
-                inmemory: function() {
-                    return new ut
-                }
-            };
-            return l(n) && y(n.find) ? n : n === !0 ? new ut : t[n]()
-        };
-        ti = ft.extend({
-            init: function(n) {
-                var t = this,
-                    s, u, i, y;
-                n = n || {};
-                for (s in n) u = n[s], t[s] = typeof u === o ? ot(u) : u;
-                if (y = n.modelBase || c, l(t.model) && (t.model = i = y.define(t.model)), t.model) {
-                    var w = v(t.data, t),
-                        b = v(t.groups, t),
-                        k = v(t.serialize, t),
-                        f = {},
-                        h = {},
-                        p = {},
-                        e = {},
-                        a = !1,
-                        r;
-                    i = t.model;
-                    i.fields && (yt(i.fields, function(n, t) {
-                        var i;
-                        r = n;
-                        l(t) && t.field ? r = t.field : typeof t === o && (r = t);
-                        l(t) && t.from && (i = t.from);
-                        a = a || i && i !== n || r !== n;
-                        h[n] = ot(i || r);
-                        p[n] = ot(n);
-                        f[i || r] = n;
-                        e[n] = i || r
-                    }), !n.serialize && a && (t.serialize = ni(k, i, au, p, f, e)));
-                    t.data = ni(w, i, tr, h, f, e);
-                    t.groups = ni(b, i, ir, h, f, e)
-                }
-            },
-            errors: function(n) {
-                return n ? n.errors : null
-            },
-            parse: et,
-            data: et,
-            total: function(n) {
-                return n.length
-            },
-            groups: et,
-            aggregates: function() {
-                return {}
-            },
-            serialize: function(n) {
-                return n
-            }
-        });
-        h = g.extend({
-            init: function(n) {
-                var u = this,
-                    o, f;
-                n && (f = n.data);
-                n = u.options = e({}, u.options, n);
-                u._map = {};
-                u._prefetch = {};
-                u._data = [];
-                u._pristineData = [];
-                u._ranges = [];
-                u._view = [];
-                u._pristine = [];
-                u._destroyed = [];
-                u._pageSize = n.pageSize;
-                u._page = n.page || (n.pageSize ? 1 : t);
-                u._sort = it(n.sort);
-                u._filter = ct(n.filter);
-                u._group = rt(n.group);
-                u._aggregate = n.aggregate;
-                u._total = n.total;
-                g.fn.init.call(u);
-                u.transport = ri.create(n, f);
-                u.reader = new i.data.readers[n.schema.type || "json"](n.schema);
-                o = u.reader.model || {};
-                u._data = u._observe(u._data);
-                u.bind([a, r, tt, ci, nt, bt], n)
-            },
-            options: {
-                data: [],
-                schema: {
-                    modelBase: c
-                },
-                serverSorting: !1,
-                serverPaging: !1,
-                serverFiltering: !1,
-                serverGrouping: !1,
-                serverAggregates: !1,
-                batch: !1
-            },
-            _isServerGrouped: function() {
-                var n = this.group() || [];
-                return this.options.serverGrouping && n.length
-            },
-            _flatData: function(n) {
-                return this._isServerGrouped() ? rr(n) : n
-            },
-            parent: b,
-            get: function(n) {
-                for (var i = this._flatData(this._data), t = 0, r = i.length; t < r; t++)
-                    if (i[t].id == n) return i[t]
-            },
-            getByUid: function(n) {
-                var t, r, i = this._flatData(this._data);
-                if (i)
-                    for (t = 0, r = i.length; t < r; t++)
-                        if (i[t].uid == n) return i[t]
-            },
-            indexOf: function(n) {
-                return sr(this._data, n)
-            },
-            at: function(n) {
-                return this._data[n]
-            },
-            data: function(n) {
-                var i = this;
-                if (n !== t) i._data = this._observe(n), i._ranges = [], i._addRange(i._data), i._total = i._data.length, i._process(i._data);
-                else return i._data
-            },
-            view: function() {
-                return this._view
-            },
-            add: function(n) {
-                return this.insert(this._data.length, n)
-            },
-            _createNewModel: function(n) {
-                return this.reader.model ? new this.reader.model(n) : new s(n)
-            },
-            insert: function(n, t) {
-                return t || (t = n, n = 0), t instanceof c || (t = this._createNewModel(t)), this._isServerGrouped() ? this._data.splice(n, 0, er(this.group(), t)) : this._data.splice(n, 0, t), t
-            },
-            remove: function(n) {
-                var t, i = this,
-                    r = i._isServerGrouped();
-                return this._eachItem(i._data, function(u) {
-                    return t = vu(u, n), t && r ? (t.isNew && t.isNew() || i._destroyed.push(t), !0) : void 0
-                }), n
-            },
-            sync: function() {
-                var t = this,
-                    i, f, e = [],
-                    o = [],
-                    s = t._destroyed,
-                    u = t._flatData(t._data),
-                    r;
-                if (t.reader.model) {
-                    for (i = 0, f = u.length; i < f; i++) u[i].isNew() ? e.push(u[i]) : u[i].dirty && o.push(u[i]);
-                    r = t._send("create", e);
-                    r.push.apply(r, t._send("update", o));
-                    r.push.apply(r, t._send("destroy", s));
-                    n.when.apply(null, r).then(function() {
-                        for (var n = 0, i = arguments.length; n < i; n++) t._accept(arguments[n]);
-                        t._change({
-                            action: "sync"
-                        });
-                        t.trigger(ci)
-                    })
-                }
-            },
-            cancelChanges: function(n) {
-                var t = this;
-                n instanceof i.data.Model ? t._cancelModel(n) : (t._destroyed = [], t._data = t._observe(t._pristineData), t.options.serverPaging && (t._total = t.reader.total(t._pristine)), t._change())
-            },
-            hasChanges: function() {
-                var n, i, t = this._data;
-                if (this._destroyed.length) return !0;
-                for (n = 0, i = t.length; n < i; n++)
-                    if (t[n].isNew() || t[n].dirty) return !0;
-                return !1
-            },
-            _accept: function(t) {
-                var r = this,
-                    f = t.models,
-                    i = t.response,
-                    u = 0,
-                    s = r._isServerGrouped(),
-                    h = r._pristineData,
-                    e = t.type,
-                    o;
-                if (r.trigger(nt, {
-                        response: i,
-                        type: e
-                    }), i && !k(i)) {
-                    if (i = r.reader.parse(i), r._handleCustomErrors(i)) return;
-                    i = r.reader.data(i);
-                    n.isArray(i) || (i = [i])
-                } else i = n.map(f, function(n) {
-                    return n.toJSON()
-                });
-                for (e === "destroy" && (r._destroyed = []), u = 0, o = f.length; u < o; u++) e !== "destroy" ? (f[u].accept(i[u]), e === "create" ? h.push(s ? er(r.group(), f[u]) : i[u]) : e === "update" && r._updatePristineForModel(f[u], i[u])) : r._removePristineForModel(f[u])
-            },
-            _updatePristineForModel: function(n, t) {
-                this._executeOnPristineForModel(n, function(n, r) {
-                    i.deepExtend(r[n], t)
-                })
-            },
-            _executeOnPristineForModel: function(n, t) {
-                this._eachPristineItem(function(i) {
-                    var r = or(i, n);
-                    if (r > -1) return t(r, i), !0
-                })
-            },
-            _removePristineForModel: function(n) {
-                this._executeOnPristineForModel(n, function(n, t) {
-                    t.splice(n, 1)
-                })
-            },
-            _readData: function(n) {
-                var t = this._isServerGrouped() ? this.reader.groups : this.reader.data;
-                return t(n)
-            },
-            _eachPristineItem: function(n) {
-                this._eachItem(this._pristineData, n)
-            },
-            _eachItem: function(n, t) {
-                n && n.length && (this._isServerGrouped() ? fr(n, t) : t(n))
-            },
-            _pristineForModel: function(n) {
-                var i, t, r = function(r) {
-                    return t = or(r, n), t > -1 ? (i = r[t], !0) : void 0
-                };
-                return this._eachPristineItem(r), i
-            },
-            _cancelModel: function(n) {
-                var i = this._pristineForModel(n),
-                    t;
-                this._eachItem(this._data, function(r) {
-                    t = sr(r, n);
-                    t != -1 && (!n.isNew() && i ? r[t].accept(i) : r.splice(t, 1))
-                })
-            },
-            _promise: function(t, i, r) {
-                var u = this,
-                    f = u.transport;
-                return n.Deferred(function(n) {
-                    u.trigger(tt, {
-                        type: r
-                    });
-                    f[r].call(f, e({
-                        success: function(t) {
-                            n.resolve({
-                                response: t,
-                                models: i,
-                                type: r
-                            })
-                        },
-                        error: function(t, i, r) {
-                            n.reject(t);
-                            u.error(t, i, r)
-                        }
-                    }, t))
-                }).promise()
-            },
-            _send: function(n, t) {
-                var r = this,
-                    i, f, u = [],
-                    e = r.reader.serialize(lu(t));
-                if (r.options.batch) t.length && u.push(r._promise({
-                    data: {
-                        models: e
-                    }
-                }, t, n));
-                else
-                    for (i = 0, f = t.length; i < f; i++) u.push(r._promise({
-                        data: e[i]
-                    }, [t[i]], n));
-                return u
-            },
-            read: function(n) {
-                var t = this,
-                    i = t._params(n);
-                t._queueRequest(i, function() {
-                    t.trigger(tt, {
-                        type: "read"
-                    }) ? t._dequeueRequest() : (t.trigger(bt), t._ranges = [], t.transport.read({
-                        data: i,
-                        success: v(t.success, t),
-                        error: v(t.error, t)
-                    }))
-                })
-            },
-            success: function(t) {
-                var i = this,
-                    r = i.options;
-                if (i.trigger(nt, {
-                        response: t,
-                        type: "read"
-                    }), t = i.reader.parse(t), i._handleCustomErrors(t)) {
-                    i._dequeueRequest();
-                    return
-                }
-                i._pristine = l(t) ? n.extend(!0, {}, t) : t.slice ? t.slice(0) : t;
-                i._total = i.reader.total(t);
-                i._aggregate && r.serverAggregates && (i._aggregateResult = i.reader.aggregates(t));
-                t = i._readData(t);
-                i._pristineData = t.slice(0);
-                i._data = i._observe(t);
-                i._addRange(i._data);
-                i._process(i._data);
-                i._dequeueRequest()
-            },
-            _addRange: function(n) {
-                var t = this,
-                    i = t._skip || 0,
-                    r = i + t._flatData(n).length;
-                t._ranges.push({
-                    start: i,
-                    end: r,
-                    data: n
-                });
-                t._ranges.sort(function(n, t) {
-                    return n.start - t.start
-                })
-            },
-            error: function(n, t, i) {
-                this._dequeueRequest();
-                this.trigger(nt, {});
-                this.trigger(a, {
-                    xhr: n,
-                    status: t,
-                    errorThrown: i
-                })
-            },
-            _params: function(n) {
-                var t = this,
-                    i = e({
-                        take: t.take(),
-                        skip: t.skip(),
-                        page: t.page(),
-                        pageSize: t.pageSize(),
-                        sort: t._sort,
-                        filter: t._filter,
-                        group: t._group,
-                        aggregate: t._aggregate
-                    }, n);
-                return t.options.serverPaging || (delete i.take, delete i.skip, delete i.page, delete i.pageSize), t.options.serverGrouping ? t.reader.model && i.group && (i.group = lt(i.group, t.reader.model)) : delete i.group, t.options.serverFiltering ? t.reader.model && i.filter && (i.filter = lr(i.filter, t.reader.model)) : delete i.filter, t.options.serverSorting ? t.reader.model && i.sort && (i.sort = lt(i.sort, t.reader.model)) : delete i.sort, t.options.serverAggregates ? t.reader.model && i.aggregate && (i.aggregate = lt(i.aggregate, t.reader.model)) : delete i.aggregate, i
-            },
-            _queueRequest: function(n, i) {
-                var r = this;
-                r._requestInProgress ? r._pending = {
-                    callback: v(i, r),
-                    options: n
-                } : (r._requestInProgress = !0, r._pending = t, i())
-            },
-            _dequeueRequest: function() {
-                var n = this;
-                n._requestInProgress = !1;
-                n._pending && n._queueRequest(n._pending.options, n._pending.callback)
-            },
-            _handleCustomErrors: function(n) {
-                if (this.reader.errors) {
-                    var t = this.reader.errors(n);
-                    if (t) return this.trigger(a, {
-                        xhr: null,
-                        status: "customerror",
-                        errorThrown: "custom error",
-                        errors: t
-                    }), !0
-                }
-                return !1
-            },
-            _observe: function(n) {
-                var t = this,
-                    i = t.reader.model,
-                    u = !1;
-                return i && n.length && (u = !(n[0] instanceof i)), n instanceof p ? u && (n.type = t.reader.model, n.wrapAll(n, n)) : (n = new p(n, t.reader.model), n.parent = function() {
-                    return t.parent()
-                }), t._isServerGrouped() && ur(n, i), t._changeHandler && t._data && t._data instanceof p ? t._data.unbind(r, t._changeHandler) : t._changeHandler = v(t._change, t), n.bind(r, t._changeHandler)
-            },
-            _change: function(n) {
-                var t = this,
-                    r, f, i = n ? n.action : "",
-                    u;
-                if (i === "remove")
-                    for (r = 0, f = n.items.length; r < f; r++) n.items[r].isNew && n.items[r].isNew() || t._destroyed.push(n.items[r]);
-                t.options.autoSync && (i === "add" || i === "remove" || i === "itemchange") ? t.sync() : (u = parseInt(t._total || t.reader.total(t._pristine), 10), i === "add" ? u += n.items.length : i === "remove" ? u -= n.items.length : i === "itemchange" || i === "sync" || t.options.serverPaging || (u = t.reader.total(t._pristine)), t._total = u, t._process(t._data, n))
-            },
-            _process: function(n, i) {
-                var f = this,
-                    e = {},
-                    o;
-                f.options.serverPaging !== !0 && (e.skip = f._skip, e.take = f._take || f._pageSize, e.skip === t && f._page !== t && f._pageSize !== t && (e.skip = (f._page - 1) * f._pageSize));
-                f.options.serverSorting !== !0 && (e.sort = f._sort);
-                f.options.serverFiltering !== !0 && (e.filter = f._filter);
-                f.options.serverGrouping !== !0 && (e.group = f._group);
-                f.options.serverAggregates !== !0 && (e.aggregate = f._aggregate, f._aggregateResult = di(n, e));
-                o = u.process(n, e);
-                f._view = o.data;
-                o.total === t || f.options.serverFiltering || (f._total = o.total);
-                i = i || {};
-                i.items = i.items || f._view;
-                f.trigger(r, i)
-            },
-            _mergeState: function(n) {
-                var i = this;
-                return n !== t && (i._pageSize = n.pageSize, i._page = n.page, i._sort = n.sort, i._filter = n.filter, i._group = n.group, i._aggregate = n.aggregate, i._skip = n.skip, i._take = n.take, i._skip === t && (i._skip = i.skip(), n.skip = i.skip()), i._take === t && i._pageSize !== t && (i._take = i._pageSize, n.take = i._take), n.sort && (i._sort = n.sort = it(n.sort)), n.filter && (i._filter = n.filter = ct(n.filter)), n.group && (i._group = n.group = rt(n.group)), n.aggregate && (i._aggregate = n.aggregate = su(n.aggregate))), n
-            },
-            query: function(n) {
-                var i = this,
-                    f, e = i.options.serverSorting || i.options.serverPaging || i.options.serverFiltering || i.options.serverGrouping || i.options.serverAggregates;
-                e || (i._data === t || i._data.length === 0) && !i._destroyed.length ? i.read(i._mergeState(n)) : i.trigger(tt, {
-                    type: "read"
-                }) || (i.trigger(bt), f = u.process(i._data, i._mergeState(n)), i.options.serverFiltering || (i._total = f.total !== t ? f.total : i._data.length), i._view = f.data, i._aggregateResult = di(i._data, n), i.trigger(nt, {}), i.trigger(r, {
-                    items: f.data
-                }))
-            },
-            fetch: function(t) {
-                var i = this;
-                return n.Deferred(function(n) {
-                    var f = function(r) {
-                            i.unbind(a, u);
-                            n.resolve();
-                            t && t.call(i, r)
-                        },
-                        u = function(t) {
-                            n.reject(t)
-                        };
-                    i.one(r, f);
-                    i.one(a, u);
-                    i._query()
-                }).promise()
-            },
-            _query: function(n) {
-                var t = this;
-                t.query(e({}, {
-                    page: t.page(),
-                    pageSize: t.pageSize(),
-                    sort: t.sort(),
-                    filter: t.filter(),
-                    group: t.group(),
-                    aggregate: t.aggregate()
-                }, n))
-            },
-            next: function(n) {
-                var t = this,
-                    i = t.page(),
-                    r = t.total();
-                if (n = n || {}, i && (!r || !(i + 1 > t.totalPages()))) return t._skip = i * t.take(), i += 1, n.page = i, t._query(n), i
-            },
-            prev: function(n) {
-                var t = this,
-                    i = t.page();
-                if (n = n || {}, i && i !== 1) return t._skip = t._skip - t.take(), i -= 1, n.page = i, t._query(n), i
-            },
-            page: function(n) {
-                var i = this,
-                    r;
-                if (n !== t) {
-                    n = f.max(f.min(f.max(n, 1), i.totalPages()), 1);
-                    i._query({
-                        page: n
-                    });
-                    return
-                }
-                return r = i.skip(), r !== t ? f.round((r || 0) / (i.take() || 1)) + 1 : t
-            },
-            pageSize: function(n) {
-                var i = this;
-                if (n !== t) {
-                    i._query({
-                        pageSize: n,
-                        page: 1
-                    });
-                    return
-                }
-                return i.take()
-            },
-            sort: function(n) {
-                var i = this;
-                if (n !== t) {
-                    i._query({
-                        sort: n
-                    });
-                    return
-                }
-                return i._sort
-            },
-            filter: function(n) {
-                var i = this;
-                if (n === t) return i._filter;
-                i._query({
-                    filter: n,
-                    page: 1
-                })
-            },
-            group: function(n) {
-                var i = this;
-                if (n !== t) {
-                    i._query({
-                        group: n
-                    });
-                    return
-                }
-                return i._group
-            },
-            total: function() {
-                return parseInt(this._total || 0, 10)
-            },
-            aggregate: function(n) {
-                var i = this;
-                if (n !== t) {
-                    i._query({
-                        aggregate: n
-                    });
-                    return
-                }
-                return i._aggregate
-            },
-            aggregates: function() {
-                return this._aggregateResult
-            },
-            totalPages: function() {
-                var n = this,
-                    t = n.pageSize() || n.total();
-                return f.ceil((n.total() || 0) / t)
-            },
-            inRange: function(n, t) {
-                var i = this,
-                    r = f.min(n + t, i.total());
-                return !i.options.serverPaging && i.data.length > 0 ? !0 : i._findRange(n, r).length > 0
-            },
-            lastRange: function() {
-                var n = this._ranges;
-                return n[n.length - 1] || {
-                    start: 0,
-                    end: 0,
-                    data: []
-                }
-            },
-            firstItemUid: function() {
-                var n = this._ranges;
-                return n.length && n[0].data.length && n[0].data[0].uid
-            },
-            range: function(n, i) {
-                n = f.min(n || 0, this.total());
-                var r = this,
-                    e = f.max(f.floor(n / i), 0) * i,
-                    u = f.min(e + i, r.total()),
-                    o;
-                if (o = r._findRange(n, f.min(n + i, r.total())), o.length) {
-                    r._skip = n > r.skip() ? f.min(u, (r.totalPages() - 1) * r.take()) : e;
-                    r._take = i;
-                    var s = r.options.serverPaging,
-                        h = r.options.serverSorting,
-                        c = r.options.serverFiltering;
-                    try {
-                        r.options.serverPaging = !0;
-                        r._isServerGrouped() || r.group() && r.group().length || (r.options.serverSorting = !0);
-                        r.options.serverFiltering = !0;
-                        s && (r._data = o = r._observe(o));
-                        r._process(o)
-                    } finally {
-                        r.options.serverPaging = s;
-                        r.options.serverSorting = h;
-                        r.options.serverFiltering = c
-                    }
-                    return
-                }
-                i !== t && (r._rangeExists(e, u) ? e < n && r.prefetch(u, i, function() {
-                    r.range(n, i)
-                }) : r.prefetch(e, i, function() {
-                    n > e && u < r.total() && !r._rangeExists(u, f.min(u + i, r.total())) ? r.prefetch(u, i, function() {
-                        r.range(n, i)
-                    }) : r.range(n, i)
-                }))
-            },
-            _findRange: function(n, i) {
-                for (var f = this, p = f._ranges, r, w = [], c, l, s, b, a, v, h = f.options, g = h.serverSorting || h.serverPaging || h.serverFiltering || h.serverGrouping || h.serverAggregates, y, e, d, o = 0, k = p.length; o < k; o++)
-                    if (r = p[o], n >= r.start && n <= r.end) {
-                        for (e = 0, c = o; c < k; c++)
-                            if (r = p[c], y = f._flatData(r.data), y.length && n + e >= r.start && (b = r.data, a = r.end, g || (d = rt(f.group() || []).concat(it(f.sort() || [])), v = u.process(r.data, {
-                                    sort: d,
-                                    filter: f.filter()
-                                }), y = b = v.data, v.total !== t && (a = v.total)), l = 0, n + e > r.start && (l = n + e - r.start), s = y.length, a > i && (s = s - (a - i)), e += s - l, w = f._mergeGroups(w, b, l, s), i <= r.end && e == i - n)) return w;
-                        break
-                    }
-                return []
-            },
-            _mergeGroups: function(n, t, i, r) {
-                if (this._isServerGrouped()) {
-                    var u = t.toJSON(),
-                        f;
-                    return n.length && (f = n[n.length - 1]), ii(f, u, i, r), n.concat(u)
-                }
-                return n.concat(t.slice(i, r))
-            },
-            skip: function() {
-                var n = this;
-                return n._skip === t ? n._page !== t ? (n._page - 1) * (n.take() || 1) : t : n._skip
-            },
-            take: function() {
-                return this._take || this._pageSize
-            },
-            _prefetchSuccessHandler: function(n, t, i) {
-                var u = this;
-                return function(f) {
-                    var h = !1,
-                        e = {
-                            start: n,
-                            end: t,
-                            data: []
-                        },
-                        o, c, s;
-                    if (u._dequeueRequest(), u.trigger(nt, {
-                            response: f,
-                            type: "read"
-                        }), f = u.reader.parse(f), s = u._readData(f), s.length) {
-                        for (o = 0, c = u._ranges.length; o < c; o++)
-                            if (u._ranges[o].start === n) {
-                                h = !0;
-                                e = u._ranges[o];
-                                break
-                            }
-                        h || u._ranges.push(e)
-                    }
-                    e.data = u._observe(s);
-                    e.end = e.start + u._flatData(e.data).length;
-                    u._ranges.sort(function(n, t) {
-                        return n.start - t.start
-                    });
-                    u._total = u.reader.total(f);
-                    i && s.length ? i() : u.trigger(r, {})
-                }
-            },
-            prefetch: function(n, t, i) {
-                var r = this,
-                    u = f.min(n + t, r.total()),
-                    e = {
-                        take: t,
-                        skip: n,
-                        page: n / t + 1,
-                        pageSize: t,
-                        sort: r._sort,
-                        filter: r._filter,
-                        group: r._group,
-                        aggregate: r._aggregate
-                    };
-                r._rangeExists(n, u) ? i && i() : (clearTimeout(r._timeout), r._timeout = setTimeout(function() {
-                    r._queueRequest(e, function() {
-                        r.trigger(tt, {
-                            type: "read"
-                        }) ? r._dequeueRequest() : r.transport.read({
-                            data: r._params(e),
-                            success: r._prefetchSuccessHandler(n, u, i)
-                        })
-                    })
-                }, 100))
-            },
-            _rangeExists: function(n, t) {
-                for (var f = this, r = f._ranges, i = 0, u = r.length; i < u; i++)
-                    if (r[i].start <= n && r[i].end >= t) return !0;
-                return !1
-            }
-        });
-        ri = {};
-        ri.create = function(n, t) {
-            var u, r = n.transport;
-            return r ? (r.read = typeof r.read === o ? {
-                url: r.read
-            } : r.read, n.type && (i.data.transports[n.type] && !l(i.data.transports[n.type]) ? u = new i.data.transports[n.type](e(r, {
-                data: t
-            })) : r = e(!0, {}, i.data.transports[n.type], r), n.schema = e(!0, {}, i.data.schemas[n.type], n.schema)), u || (u = y(r.read) ? r : new nr(r))) : u = new gi({
-                data: n.data
-            }), u
-        };
-        h.create = function(n) {
-            n = n && n.push ? {
-                data: n
-            } : n;
-            var t = n || {},
-                u = t.data,
-                r = t.fields,
-                c = t.table,
-                l = t.select,
-                f, a, s = {},
-                o;
-            if (u || !r || t.transport || (c ? u = pu(c, r) : l && (u = yu(l, r))), i.data.Model && r && (!t.schema || !t.schema.model)) {
-                for (f = 0, a = r.length; f < a; f++) o = r[f], o.type && (s[o.field] = o);
-                k(s) || (t.schema = e(!0, t.schema, {
-                    model: {
-                        fields: s
-                    }
-                }))
-            }
-            return t.data = u, t instanceof h ? t : new h(t)
-        };
-        ui = c.define({
-            init: function(n) {
-                var t = this,
-                    r = t.hasChildren || n && n.hasChildren,
-                    f = "items",
-                    u = {};
-                i.data.Model.fn.init.call(t, n);
-                typeof t.children === o && (f = t.children);
-                u = {
-                    schema: {
-                        data: f,
-                        model: {
-                            hasChildren: r,
-                            id: t.idField
-                        }
-                    }
-                };
-                typeof t.children !== o && e(u, t.children);
-                u.data = n;
-                r || (r = u.schema.data);
-                typeof r === o && (r = i.getter(r));
-                y(r) && (t.hasChildren = !!r.call(t, t));
-                t._childrenOptions = u;
-                t.hasChildren && t._initChildren();
-                t._loaded = !!(n && (n[f] || n._loaded))
-            },
-            _initChildren: function() {
-                var n = this,
-                    t, i, u;
-                n.children instanceof w || (t = n.children = new w(n._childrenOptions), i = t.transport, u = i.parameterMap, i.parameterMap = function(t) {
-                    return t[n.idField || "id"] = n.id, u && (t = u(t)), t
-                }, t.parent = function() {
-                    return n
-                }, t.bind(r, function(t) {
-                    t.node = t.node || n;
-                    n.trigger(r, t)
-                }), t.bind(a, function(t) {
-                    var i = n.parent();
-                    i && (t.node = t.node || n, i.trigger(a, t))
-                }), n._updateChildrenField())
-            },
-            append: function(n) {
-                this._initChildren();
-                this.loaded(!0);
-                this.children.add(n)
-            },
-            hasChildren: !1,
-            level: function() {
-                for (var n = this.parentNode(), t = 0; n && n.parentNode;) t++, n = n.parentNode ? n.parentNode() : null;
-                return t
-            },
-            _updateChildrenField: function() {
-                var n = this._childrenOptions.schema.data;
-                this[n || "items"] = this.children.data()
-            },
-            _childrenLoaded: function() {
-                this._loaded = !0;
-                this._updateChildrenField()
-            },
-            load: function() {
-                var i = {},
-                    u = "_query",
-                    n;
-                if (this.hasChildren) {
-                    this._initChildren();
-                    n = this.children;
-                    i[this.idField || "id"] = this.id;
-                    this._loaded || (n._data = t, u = "read");
-                    n.one(r, v(this._childrenLoaded, this));
-                    n[u](i)
-                } else this.loaded(!0)
-            },
-            parentNode: function() {
-                var n = this.parent();
-                return n.parent()
-            },
-            loaded: function(n) {
-                if (n !== t) this._loaded = n;
-                else return this._loaded
-            },
-            shouldSerialize: function(n) {
-                return c.fn.shouldSerialize.call(this, n) && n !== "children" && n !== "_loaded" && n !== "hasChildren" && n !== "_childrenOptions"
-            }
-        });
-        w = h.extend({
-            init: function(n) {
-                var t = ui.define({
-                    children: n
-                });
-                h.fn.init.call(this, e(!0, {}, {
-                    schema: {
-                        modelBase: t,
-                        model: t
-                    }
-                }, n));
-                this._attachBubbleHandlers()
-            },
-            _attachBubbleHandlers: function() {
-                var n = this;
-                n._data.bind(a, function(t) {
-                    n.trigger(a, t)
-                })
-            },
-            remove: function(n) {
-                var t = n.parentNode(),
-                    i = this,
-                    r;
-                return t && t._initChildren && (i = t.children), r = h.fn.remove.call(i, n), t && !i.data().length && (t.hasChildren = !1), r
-            },
-            success: ar("success"),
-            data: ar("data"),
-            insert: function(n, t) {
-                var i = this.parent();
-                return i && i._initChildren && (i.hasChildren = !0, i._initChildren()), h.fn.insert.call(this, n, t)
-            },
-            _find: function(n, t) {
-                var r, e, i, u, f;
-                if (i = h.fn[n].call(this, t), i) return i;
-                if (u = this._flatData(this.data()), u)
-                    for (r = 0, e = u.length; r < e; r++)
-                        if ((f = u[r].children, f instanceof w) && (i = f[n](t), i)) return i
-            },
-            get: function(n) {
-                return this._find("get", n)
-            },
-            getByUid: function(n) {
-                return this._find("getByUid", n)
-            }
-        });
-        w.create = function(n) {
-            n = n && n.push ? {
-                data: n
-            } : n;
-            var t = n || {},
-                i = t.data,
-                r = t.fields,
-                u = t.list;
-            return i && i._dataSource ? i._dataSource : (i || !r || t.transport || u && (i = vr(u, r)), t.data = i, t instanceof w ? t : new w(t))
-        };
-        fi = i.Observable.extend({
-            init: function(n, t, r) {
-                i.Observable.fn.init.call(this);
-                this._prefetching = !1;
-                this.dataSource = n;
-                this.prefetch = !r;
-                var u = this;
-                n.bind("change", function() {
-                    u._change()
-                });
-                this._syncWithDataSource();
-                this.setViewSize(t)
-            },
-            setViewSize: function(n) {
-                this.viewSize = n;
-                this._recalculate()
-            },
-            at: function(n) {
-                var i = this.pageSize,
-                    r, u;
-                if (n >= this.total()) {
-                    this.trigger("endreached", {
-                        index: n
-                    });
-                    return
-                }
-                return this.useRanges ? (this.useRanges && ((n < this.dataOffset || n > this.skip + i) && (u = Math.floor(n / i) * i, this.range(u)), n === this.prefetchThreshold && this._prefetch(), n === this.midPageThreshold ? this.range(this.nextMidRange) : n === this.nextPageThreshold ? this.range(this.nextFullRange) : n === this.pullBackThreshold && (this.offset === this.skip ? this.range(this.previousMidRange) : this.range(this.previousFullRange)), r = this.dataSource.at(n - this.dataOffset)), r === t && this.trigger("endreached", {
-                    index: n
-                }), r) : this.dataSource.view()[n]
-            },
-            indexOf: function(n) {
-                return this.dataSource.data().indexOf(n) + this.dataOffset
-            },
-            total: function() {
-                return parseInt(this.dataSource.total(), 10)
-            },
-            next: function() {
-                var n = this,
-                    t = n.pageSize,
-                    i = n.skip - n.viewSize,
-                    r = f.max(f.floor(i / t), 0) * t + t;
-                this.offset = i;
-                this.dataSource.prefetch(r, t, function() {
-                    n._goToRange(i, !0)
-                })
-            },
-            range: function(n) {
-                if (this.offset !== n) {
-                    var r = this,
-                        t = this.pageSize,
-                        u = f.max(f.floor(n / t), 0) * t + t,
-                        i = this.dataSource;
-                    this.offset = n;
-                    this._recalculate();
-                    i.inRange(n, t) ? this._goToRange(n) : this.prefetch && i.prefetch(u, t, function() {
-                        r._goToRange(n, !0)
-                    })
-                }
-            },
-            syncDataSource: function() {
-                var n = this.offset;
-                this.offset = null;
-                this.range(n)
-            },
-            destroy: function() {
-                this.unbind()
-            },
-            _prefetch: function() {
-                var i = this,
-                    n = this.pageSize,
-                    t = this.skip + n,
-                    r = this.dataSource;
-                r.inRange(t, n) || this._prefetching || !this.prefetch || (this._prefetching = !0, this.trigger("prefetching", {
-                    skip: t,
-                    take: n
-                }), r.prefetch(t, n, function() {
-                    i._prefetching = !1;
-                    i.trigger("prefetched", {
-                        skip: t,
-                        take: n
-                    })
-                }))
-            },
-            _goToRange: function(n, t) {
-                this.offset === n && (this.dataOffset = n, this._expanding = t, this.dataSource.range(n, this.pageSize))
-            },
-            _change: function() {
-                var n = this.dataSource,
-                    t = n.firstItemUid();
-                this.length = this.useRanges ? n.lastRange().end : n.view().length;
-                this._firstItemUid === t && this.useRanges || (this._syncWithDataSource(), this._recalculate(), this.trigger("reset", {
-                    offset: this.offset
-                }));
-                this.trigger("resize");
-                this._expanding && this.trigger("expand");
-                delete this._expanding
-            },
-            _syncWithDataSource: function() {
-                var n = this.dataSource;
-                this._firstItemUid = n.firstItemUid();
-                this.dataOffset = this.offset = n.skip() || 0;
-                this.pageSize = n.pageSize();
-                this.useRanges = n.options.serverPaging
-            },
-            _recalculate: function() {
-                var t = this.pageSize,
-                    r = this.offset,
-                    i = this.viewSize,
-                    n = Math.ceil(r / t) * t;
-                this.skip = n;
-                this.midPageThreshold = n + t - 1;
-                this.nextPageThreshold = n + i - 1;
-                this.prefetchThreshold = n + Math.floor(t / 3 * 2);
-                this.pullBackThreshold = this.offset - 1;
-                this.nextMidRange = n + t - i;
-                this.nextFullRange = n;
-                this.previousMidRange = r - i;
-                this.previousFullRange = n - t
-            }
-        });
-        yr = i.Observable.extend({
-            init: function(n, t) {
-                var r = this;
-                i.Observable.fn.init.call(r);
-                this.dataSource = n;
-                this.batchSize = t;
-                this._total = 0;
-                this.buffer = new fi(n, t * 3);
-                this.buffer.bind({
-                    endreached: function(n) {
-                        r.trigger("endreached", {
-                            index: n.index
-                        })
-                    },
-                    prefetching: function(n) {
-                        r.trigger("prefetching", {
-                            skip: n.skip,
-                            take: n.take
-                        })
-                    },
-                    prefetched: function(n) {
-                        r.trigger("prefetched", {
-                            skip: n.skip,
-                            take: n.take
-                        })
-                    },
-                    reset: function() {
-                        r._total = 0;
-                        r.trigger("reset")
-                    },
-                    resize: function() {
-                        r._total = Math.ceil(this.length / r.batchSize);
-                        r.trigger("resize", {
-                            total: r.total(),
-                            offset: this.offset
-                        })
-                    }
-                })
-            },
-            syncDataSource: function() {
-                this.buffer.syncDataSource()
-            },
-            at: function(n) {
-                var i = this.buffer,
-                    f = n * this.batchSize,
-                    o = this.batchSize,
-                    e = [],
-                    u, r;
-                for (i.offset > f && i.at(i.offset - 1), r = 0; r < o; r++) {
-                    if (u = i.at(f + r), u === t) break;
-                    e.push(u)
-                }
-                return e
-            },
-            total: function() {
-                return this._total
-            },
-            destroy: function() {
-                this.buffer.destroy();
-                this.unbind()
-            }
-        });
-        e(!0, i.data, {
-            readers: {
-                json: ti
-            },
-            Query: u,
-            DataSource: h,
-            HierarchicalDataSource: w,
-            Node: ui,
-            ObservableObject: s,
-            ObservableArray: p,
-            LocalTransport: gi,
-            RemoteTransport: nr,
-            Cache: ut,
-            DataReader: ti,
-            Model: c,
-            Buffer: fi,
-            BatchBuffer: yr
-        })
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "validator",
-        name: "Validator",
-        category: "web",
-        description: "The Validator offers an easy way to do a client-side form validation.",
-        depends: ["core"]
-    }),
-    function(n) {
-        function nt(i) {
-            var r = t.ui.validator.ruleResolvers || {},
-                u = {};
-            for (var f in r) n.extend(!0, u, r[f].resolve(i));
-            return u
-        }
-
-        function tt(n) {
-            return n.replace(/&amp/g, "&amp;").replace(/&quot;/g, '"').replace(/&#39;/g, "'").replace(/&lt;/g, "<").replace(/&gt;/g, ">")
-        }
-
-        function it(n) {
-            return (n = (n + "").split("."), n.length > 1) ? n[1].length : 0
-        }
-
-        function rt(t) {
-            return n.parseHTML ? n(n.parseHTML(t)) : n(t)
-        }
-        var t = window.kendo,
-            f = t.ui.Widget,
-            i = ".kendoValidator",
-            u = "k-invalid-msg",
-            p = new RegExp(u, "i"),
-            w = "k-invalid",
-            b = /^((([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,
-            k = /^(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,
-            r = ":input:not(:button,[type=submit],[type=reset],[disabled],[readonly])",
-            o = ":checkbox:not([disabled],[readonly])",
-            e = "[type=number],[type=range]",
-            s = "blur",
-            h = "name",
-            c = "form",
-            l = "novalidate",
-            d = n.proxy,
-            a = function(n, t) {
-                return typeof t == "string" && (t = new RegExp("^(?:" + t + ")$")), t.test(n)
-            },
-            v = function(n, t, i) {
-                var r = n.val();
-                return n.filter(t).length && r !== "" ? a(r, i) : !0
-            },
-            g = function(n, t) {
-                return n.length ? n[0].attributes[t] != null : !1
-            },
-            y;
-        t.ui.validator || (t.ui.validator = {
-            rules: {},
-            messages: {}
-        });
-        y = f.extend({
-            init: function(i, r) {
-                var u = this,
-                    e = nt(i);
-                r = r || {};
-                r.rules = n.extend({}, t.ui.validator.rules, e.rules, r.rules);
-                r.messages = n.extend({}, t.ui.validator.messages, e.messages, r.messages);
-                f.fn.init.call(u, i, r);
-                u._errorTemplate = t.template(u.options.errorTemplate);
-                u.element.is(c) && u.element.attr(l, l);
-                u._errors = {};
-                u._attachEvents()
-            },
-            events: ["validate"],
-            options: {
-                name: "Validator",
-                errorTemplate: '<span class="k-widget k-tooltip k-tooltip-validation"><span class="k-icon k-warning"> <\/span> #=message#<\/span>',
-                messages: {
-                    required: "{0} is required",
-                    pattern: "{0} is not valid",
-                    min: "{0} should be greater than or equal to {1}",
-                    max: "{0} should be smaller than or equal to {1}",
-                    step: "{0} is not valid",
-                    email: "{0} is not valid email",
-                    url: "{0} is not valid URL",
-                    date: "{0} is not valid date"
-                },
-                rules: {
-                    required: function(n) {
-                        var i = n.filter("[type=checkbox]").length && !n.is(":checked"),
-                            t = n.val();
-                        return !(g(n, "required") && (t === "" || !t || i))
-                    },
-                    pattern: function(n) {
-                        return n.filter("[type=text],[type=email],[type=url],[type=tel],[type=search],[type=password]").filter("[pattern]").length && n.val() !== "" ? a(n.val(), n.attr("pattern")) : !0
-                    },
-                    min: function(n) {
-                        if (n.filter(e + ",[" + t.attr("type") + "=number]").filter("[min]").length && n.val() !== "") {
-                            var i = parseFloat(n.attr("min")) || 0,
-                                r = t.parseFloat(n.val());
-                            return i <= r
-                        }
-                        return !0
-                    },
-                    max: function(n) {
-                        if (n.filter(e + ",[" + t.attr("type") + "=number]").filter("[max]").length && n.val() !== "") {
-                            var i = parseFloat(n.attr("max")) || 0,
-                                r = t.parseFloat(n.val());
-                            return i >= r
-                        }
-                        return !0
-                    },
-                    step: function(n) {
-                        if (n.filter(e + ",[" + t.attr("type") + "=number]").filter("[step]").length && n.val() !== "") {
-                            var f = parseFloat(n.attr("min")) || 0,
-                                i = parseFloat(n.attr("step")) || 1,
-                                o = parseFloat(n.val()),
-                                r = it(i),
-                                u;
-                            return r ? (u = Math.pow(10, r), (o - f) * u % (i * u) / Math.pow(100, r) == 0) : (o - f) % i == 0
-                        }
-                        return !0
-                    },
-                    email: function(n) {
-                        return v(n, "[type=email],[" + t.attr("type") + "=email]", b)
-                    },
-                    url: function(n) {
-                        return v(n, "[type=url],[" + t.attr("type") + "=url]", k)
-                    },
-                    date: function(n) {
-                        return n.filter("[type^=date],[" + t.attr("type") + "=date]").length && n.val() !== "" ? t.parseDate(n.val(), n.attr(t.attr("format"))) !== null : !0
-                    }
-                },
-                validateOnBlur: !0
-            },
-            destroy: function() {
-                f.fn.destroy.call(this);
-                this.element.off(i)
-            },
-            _submit: function(n) {
-                return this.validate() ? !0 : (n.stopPropagation(), n.stopImmediatePropagation(), n.preventDefault(), !1)
-            },
-            _attachEvents: function() {
-                var t = this;
-                if (t.element.is(c)) t.element.on("submit" + i, d(t._submit, t));
-                if (t.options.validateOnBlur)
-                    if (t.element.is(r)) {
-                        t.element.on(s + i, function() {
-                            t.validateInput(t.element)
-                        });
-                        if (t.element.is(o)) t.element.on("click" + i, function() {
-                            t.validateInput(t.element)
-                        })
-                    } else {
-                        t.element.on(s + i, r, function() {
-                            t.validateInput(n(this))
-                        });
-                        t.element.on("click" + i, o, function() {
-                            t.validateInput(n(this))
-                        })
-                    }
-            },
-            validate: function() {
-                var i, n, t = !1,
-                    f, u;
-                if (this._errors = {}, this.element.is(r)) t = this.validateInput(this.element);
-                else {
-                    for (u = !1, i = this.element.find(r), n = 0, f = i.length; n < f; n++) this.validateInput(i.eq(n)) || (u = !0);
-                    t = !u
-                }
-                return this.trigger("validate", {
-                    valid: t
-                }), t
-            },
-            validateInput: function(t) {
-                var r;
-                t = n(t);
-                var i = this,
-                    c = i._errorTemplate,
-                    s = i._checkValidity(t),
-                    f = s.valid,
-                    l = "." + u,
-                    e = t.attr(h) || "",
-                    a = i._findMessageContainer(e).add(t.next(l)).hide(),
-                    o;
-                return t.removeAttr("aria-invalid"), f || (o = i._extractMessage(t, s.key), i._errors[e] = o, r = rt(c({
-                    message: tt(o)
-                })), i._decorateMessageContainer(r, e), a.replaceWith(r).length || r.insertAfter(t), r.show(), t.attr("aria-invalid", !0)), t.toggleClass(w, !f), f
-            },
-            hideMessages: function() {
-                var i = this,
-                    t = "." + u,
-                    n = i.element;
-                n.is(r) ? n.next(t).hide() : n.find(t).hide()
-            },
-            _findMessageContainer: function(i) {
-                for (var u, h, e = t.ui.validator.messageLocators, o, r = n(), s = this.element[0].getElementsByTagName("*"), f = 0, c = s.length; f < c; f++) u = s[f], p.test(u.className) && (h = u.getAttribute(t.attr("for")), h === i && (r = r.add(u)));
-                for (o in e) r = r.add(e[o].locate(this.element, i));
-                return r
-            },
-            _decorateMessageContainer: function(n, i) {
-                var r = t.ui.validator.messageLocators,
-                    f;
-                n.addClass(u).attr(t.attr("for"), i || "");
-                for (f in r) r[f].decorate(n, i);
-                n.attr("role", "alert")
-            },
-            _extractMessage: function(n, i) {
-                var u = this,
-                    r = u.options.messages[i],
-                    f = n.attr(h);
-                return r = t.isFunction(r) ? r(n) : r, t.format(n.attr(t.attr(i + "-msg")) || n.attr("validationMessage") || n.attr("title") || r || "", f, n.attr(i))
-            },
-            _checkValidity: function(n) {
-                var t = this.options.rules;
-                for (var i in t)
-                    if (!t[i](n)) return {
-                        valid: !1,
-                        key: i
-                    };
-                return {
-                    valid: !0
-                }
-            },
-            errors: function() {
-                var n = [],
-                    t = this._errors;
-                for (var i in t) n.push(t[i]);
-                return n
-            }
-        });
-        t.ui.plugin(y)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "userevents",
-        name: "User Events",
-        category: "framework",
-        depends: ["core"],
-        hidden: !0
-    }),
-    function(n) {
-        function it(n, t) {
-            var i = n.x.location,
-                r = n.y.location,
-                u = t.x.location,
-                f = t.y.location,
-                e = i - u,
-                o = r - f;
-            return {
-                center: {
-                    x: (i + u) / 2,
-                    y: (r + f) / 2
-                },
-                distance: Math.sqrt(e * e + o * o)
-            }
-        }
-
-        function h(n) {
-            var t = [],
-                r = n.originalEvent,
-                f = n.currentTarget,
-                e = 0,
-                s, o, u;
-            if (n.api) t.push({
-                id: 2,
-                event: n,
-                target: n.target,
-                currentTarget: n.target,
-                location: n
-            });
-            else if (n.type.match(/touch/))
-                for (o = r ? r.changedTouches : [], s = o.length; e < s; e++) u = o[e], t.push({
-                    location: u,
-                    event: n,
-                    target: u.target,
-                    currentTarget: f,
-                    id: u.identifier
-                });
-            else i.pointers || i.msPointers ? t.push({
-                location: r,
-                event: n,
-                target: n.target,
-                currentTarget: f,
-                id: r.pointerId
-            }) : t.push({
-                id: 1,
-                event: n,
-                target: n.target,
-                currentTarget: f,
-                location: n
-            });
-            return t
-        }
-
-        function ct(t) {
-            var i, r, u;
-            t.preventDefault();
-            i = n(t.data.root);
-            r = i.closest(".k-widget").parent();
-            r[0] || (r = i.parent());
-            u = n.extend(!0, {}, t, {
-                target: i[0]
-            });
-            r.trigger(n.Event(t.type, u))
-        }
-
-        function ut(n) {
-            for (var r = t.eventMap.up.split(" "), i = 0, u = r.length; i < u; i++) n(r[i])
-        }
-        var t = window.kendo,
-            i = t.support,
-            ft = window.document,
-            c = t.Class,
-            l = t.Observable,
-            u = n.now,
-            f = n.extend,
-            a = i.mobileOS,
-            et = a && a.android,
-            v = 800,
-            ot = i.browser.msie ? 5 : 0,
-            y = "press",
-            p = "hold",
-            w = "select",
-            b = "start",
-            e = "move",
-            o = "end",
-            k = "cancel",
-            s = "tap",
-            d = "release",
-            st = "gesturestart",
-            g = "gesturechange",
-            nt = "gestureend",
-            tt = "gesturetap",
-            rt = c.extend({
-                init: function(n, t) {
-                    var i = this;
-                    i.axis = n;
-                    i._updateLocationData(t);
-                    i.startLocation = i.location;
-                    i.velocity = i.delta = 0;
-                    i.timeStamp = u()
-                },
-                move: function(n) {
-                    var t = this,
-                        i = n["page" + t.axis],
-                        r = u(),
-                        f = r - t.timeStamp || 1;
-                    (i || !et) && (t.delta = i - t.location, t._updateLocationData(n), t.initialDelta = i - t.startLocation, t.velocity = t.delta / f, t.timeStamp = r)
-                },
-                _updateLocationData: function(n) {
-                    var t = this,
-                        i = t.axis;
-                    t.location = n["page" + i];
-                    t.client = n["client" + i];
-                    t.screen = n["screen" + i]
-                }
-            }),
-            ht = c.extend({
-                init: function(n, t, i) {
-                    var r = this;
-                    f(r, {
-                        x: new rt("X", i.location),
-                        y: new rt("Y", i.location),
-                        userEvents: n,
-                        target: t,
-                        currentTarget: i.currentTarget,
-                        initialTouch: i.target,
-                        id: i.id,
-                        _moved: !1,
-                        _finished: !1
-                    });
-                    r.press = function() {
-                        r._trigger(y, i);
-                        r._holdTimeout = setTimeout(function() {
-                            r._trigger(p, i)
-                        }, n.minHold)
-                    }
-                },
-                move: function(n) {
-                    var t = this;
-                    if (!t._finished) {
-                        if (t.x.move(n.location), t.y.move(n.location), !t._moved) {
-                            if (t._withinIgnoreThreshold()) return;
-                            if (r.current && r.current !== t.userEvents) return t.dispose();
-                            t._start(n)
-                        }
-                        t._finished || t._trigger(e, n)
-                    }
-                },
-                end: function(n) {
-                    var t = this;
-                    (t.endTime = u(), t._finished) || (t._finished = !0, t._moved ? t._trigger(o, n) : t._trigger(s, n), clearTimeout(t._holdTimeout), t._trigger(d, n), t.dispose())
-                },
-                dispose: function() {
-                    var t = this,
-                        r = t.userEvents,
-                        i = r.touches;
-                    t._finished = !0;
-                    i.splice(n.inArray(t, i), 1)
-                },
-                skip: function() {
-                    this.dispose()
-                },
-                cancel: function() {
-                    this.dispose()
-                },
-                isMoved: function() {
-                    return this._moved
-                },
-                _start: function(n) {
-                    clearTimeout(this._holdTimeout);
-                    this.startTime = u();
-                    this._moved = !0;
-                    this._trigger(b, n)
-                },
-                _trigger: function(n, t) {
-                    var i = this,
-                        r = t.event,
-                        u = {
-                            touch: i,
-                            x: i.x,
-                            y: i.y,
-                            target: i.target,
-                            event: r
-                        };
-                    i.userEvents.notify(n, u) && r.preventDefault()
-                },
-                _withinIgnoreThreshold: function() {
-                    var n = this.x.initialDelta,
-                        t = this.y.initialDelta;
-                    return Math.sqrt(n * n + t * t) <= this.userEvents.threshold
-                }
-            }),
-            r = l.extend({
-                init: function(r, u) {
-                    var h = this,
-                        a, c = t.guid(),
-                        it, rt;
-                    u = u || {};
-                    a = h.filter = u.filter;
-                    h.threshold = u.threshold || ot;
-                    h.minHold = u.minHold || v;
-                    h.touches = [];
-                    h._maxTouches = u.multiTouch ? 2 : 1;
-                    h.allowSelection = u.allowSelection;
-                    h.captureUpIfMoved = u.captureUpIfMoved;
-                    h.eventNS = c;
-                    r = n(r).handler(h);
-                    l.fn.init.call(h);
-                    f(h, {
-                        element: r,
-                        surface: u.global ? n(ft.documentElement) : n(u.surface || r),
-                        stopPropagation: u.stopPropagation,
-                        pressed: !1
-                    });
-                    h.surface.handler(h).on(t.applyEventMap("move", c), "_move").on(t.applyEventMap("up cancel", c), "_end");
-                    r.on(t.applyEventMap("down", c), a, "_start");
-                    if ((i.pointers || i.msPointers) && r.css("-ms-touch-action", "pinch-zoom double-tap-zoom"), u.preventDragEvent) r.on(t.applyEventMap("dragstart", c), t.preventDefault);
-                    r.on(t.applyEventMap("mousedown selectstart", c), a, {
-                        root: r
-                    }, "_select");
-                    h.captureUpIfMoved && i.eventCapture && (it = h.surface[0], rt = n.proxy(h.preventIfMoving, h), ut(function(n) {
-                        it.addEventListener(n, rt, !0)
-                    }));
-                    h.bind([y, p, s, b, e, o, d, k, st, g, nt, tt, w], u)
-                },
-                preventIfMoving: function(n) {
-                    this._isMoved() && n.preventDefault()
-                },
-                destroy: function() {
-                    var n = this,
-                        t;
-                    n._destroyed || (n._destroyed = !0, n.captureUpIfMoved && i.eventCapture && (t = n.surface[0], ut(function(i) {
-                        t.removeEventListener(i, n.preventIfMoving)
-                    })), n.element.kendoDestroy(n.eventNS), n.surface.kendoDestroy(n.eventNS), n.element.removeData("handler"), n.surface.removeData("handler"), n._disposeAll(), n.unbind(), delete n.surface, delete n.element)
-                },
-                capture: function() {
-                    r.current = this
-                },
-                cancel: function() {
-                    this._disposeAll();
-                    this.trigger(k)
-                },
-                notify: function(n, t) {
-                    var r = this,
-                        i = r.touches;
-                    if (this._isMultiTouch()) {
-                        switch (n) {
-                            case e:
-                                n = g;
-                                break;
-                            case o:
-                                n = nt;
-                                break;
-                            case s:
-                                n = tt
-                        }
-                        f(t, {
-                            touches: i
-                        }, it(i[0], i[1]))
-                    }
-                    return this.trigger(n, t)
-                },
-                press: function(n, t, i) {
-                    this._apiCall("_start", n, t, i)
-                },
-                move: function(n, t) {
-                    this._apiCall("_move", n, t)
-                },
-                end: function(n, t) {
-                    this._apiCall("_end", n, t)
-                },
-                _isMultiTouch: function() {
-                    return this.touches.length > 1
-                },
-                _maxTouchesReached: function() {
-                    return this.touches.length >= this._maxTouches
-                },
-                _disposeAll: function() {
-                    for (var n = this.touches; n.length > 0;) n.pop().dispose()
-                },
-                _isMoved: function() {
-                    return n.grep(this.touches, function(n) {
-                        return n.isMoved()
-                    }).length
-                },
-                _select: function(n) {
-                    (!this.allowSelection || this.trigger(w, {
-                        event: n
-                    })) && ct(n)
-                },
-                _start: function(t) {
-                    var i = this,
-                        f = 0,
-                        s = i.filter,
-                        e, o = h(t),
-                        c = o.length,
-                        u;
-                    if (!i._maxTouchesReached())
-                        for (r.current = null, i.currentTarget = t.currentTarget, i.stopPropagation && t.stopPropagation(); f < c; f++) {
-                            if (i._maxTouchesReached()) break;
-                            (u = o[f], e = s ? n(u.currentTarget) : i.element, e.length) && (u = new ht(i, e, u), i.touches.push(u), u.press(), i._isMultiTouch() && i.notify("gesturestart", {}))
-                        }
-                },
-                _move: function(n) {
-                    this._eachTouch("move", n)
-                },
-                _end: function(n) {
-                    this._eachTouch("end", n)
-                },
-                _eachTouch: function(n, t) {
-                    for (var c = this, e = {}, o = h(t), s = c.touches, r, u, f, i = 0; i < s.length; i++) r = s[i], e[r.id] = r;
-                    for (i = 0; i < o.length; i++) u = o[i], f = e[u.id], f && f[n](u)
-                },
-                _apiCall: function(t, i, r, u) {
-                    this[t]({
-                        api: !0,
-                        pageX: i,
-                        pageY: r,
-                        clientX: i,
-                        clientY: r,
-                        target: u || this.element,
-                        stopPropagation: n.noop,
-                        preventDefault: n.noop
-                    })
-                }
-            });
-        r.minHold = function(n) {
-            v = n
-        };
-        t.getTouches = h;
-        t.touchDelta = it;
-        t.UserEvents = r
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "draganddrop",
-        name: "Drag & drop",
-        category: "framework",
-        description: "Drag & drop functionality for any DOM element.",
-        depends: ["core", "userevents"]
-    }),
-    function(n, t) {
-        function dt(t, i) {
-            try {
-                return n.contains(t, i) || t == i
-            } catch (r) {
-                return !1
-            }
-        }
-
-        function g(n) {
-            return kt ? l.elementFromPoint(n.x.screen, n.y.screen) : l.elementFromPoint(n.x.client, n.y.client)
-        }
-
-        function w(n, t) {
-            return parseInt(n.css(t), 10) || 0
-        }
-
-        function st(n, t) {
-            return Math.min(Math.max(n, t.min), t.max)
-        }
-
-        function ht(n, t) {
-            var i = b(n),
-                r = i.left + w(n, "borderLeftWidth") + w(n, "paddingLeft"),
-                u = i.top + w(n, "borderTopWidth") + w(n, "paddingTop"),
-                f = r + n.width() - t.outerWidth(!0),
-                e = u + n.height() - t.outerHeight(!0);
-            return {
-                x: {
-                    min: r,
-                    max: f
-                },
-                y: {
-                    min: u,
-                    max: e
-                }
-            }
-        }
-
-        function gt(n, i, r) {
-            for (var f, e, u = 0, o = i && i.length, s = r && r.length; n && n.parentNode;) {
-                for (u = 0; u < o; u++)
-                    if (f = i[u], f.element[0] === n) return {
-                        target: f,
-                        targetElement: n
-                    };
-                for (u = 0; u < s; u++)
-                    if (e = r[u], v.matchesSelector.call(n, e.options.filter)) return {
-                        target: e,
-                        targetElement: n
-                    };
-                n = n.parentNode
-            }
-            return t
-        }
-        var i = window.kendo,
-            v = i.support,
-            l = window.document,
-            pt = i.Class,
-            o = i.ui.Widget,
-            u = i.Observable,
-            wt = i.UserEvents,
-            f = n.proxy,
-            r = n.extend,
-            b = i.getOffset,
-            y = {},
-            s = {},
-            h = {},
-            e, k = v.mobileOS,
-            bt = k && k.android,
-            kt = bt && k.browser == "chrome",
-            tt = "keyup",
-            a = "change",
-            it = "dragstart",
-            rt = "hold",
-            ut = "drag",
-            ft = "dragend",
-            et = "dragcancel",
-            d = "dragenter",
-            p = "dragleave",
-            ot = "drop",
-            ni = u.extend({
-                init: function(t, r) {
-                    var e = this,
-                        o = t[0];
-                    e.capture = !1;
-                    o.addEventListener ? (n.each(i.eventMap.down.split(" "), function() {
-                        o.addEventListener(this, f(e._press, e), !0)
-                    }), n.each(i.eventMap.up.split(" "), function() {
-                        o.addEventListener(this, f(e._release, e), !0)
-                    })) : (n.each(i.eventMap.down.split(" "), function() {
-                        o.attachEvent(this, f(e._press, e))
-                    }), n.each(i.eventMap.up.split(" "), function() {
-                        o.attachEvent(this, f(e._release, e))
-                    }));
-                    u.fn.init.call(e);
-                    e.bind(["press", "release"], r || {})
-                },
-                captureNext: function() {
-                    this.capture = !0
-                },
-                cancelCapture: function() {
-                    this.capture = !1
-                },
-                _press: function(n) {
-                    var t = this;
-                    t.trigger("press");
-                    t.capture && n.preventDefault()
-                },
-                _release: function(n) {
-                    var t = this;
-                    t.trigger("release");
-                    t.capture && (n.preventDefault(), t.cancelCapture())
-                }
-            }),
-            ct = u.extend({
-                init: function(t) {
-                    var i = this;
-                    u.fn.init.call(i);
-                    i.forcedEnabled = !1;
-                    n.extend(i, t);
-                    i.scale = 1;
-                    i.horizontal ? (i.measure = "offsetWidth", i.scrollSize = "scrollWidth", i.axis = "x") : (i.measure = "offsetHeight", i.scrollSize = "scrollHeight", i.axis = "y")
-                },
-                makeVirtual: function() {
-                    n.extend(this, {
-                        virtual: !0,
-                        forcedEnabled: !0,
-                        _virtualMin: 0,
-                        _virtualMax: 0
-                    })
-                },
-                virtualSize: function(n, t) {
-                    (this._virtualMin !== n || this._virtualMax !== t) && (this._virtualMin = n, this._virtualMax = t, this.update())
-                },
-                outOfBounds: function(n) {
-                    return n > this.max || n < this.min
-                },
-                forceEnabled: function() {
-                    this.forcedEnabled = !0
-                },
-                getSize: function() {
-                    return this.container[0][this.measure]
-                },
-                getTotal: function() {
-                    return this.element[0][this.scrollSize]
-                },
-                rescale: function(n) {
-                    this.scale = n
-                },
-                update: function(n) {
-                    var t = this,
-                        u = t.virtual ? t._virtualMax : t.getTotal(),
-                        r = u * t.scale,
-                        i = t.getSize();
-                    t.max = t.virtual ? -t._virtualMin : 0;
-                    t.size = i;
-                    t.total = r;
-                    t.min = Math.min(t.max, i - r);
-                    t.minScale = i / u;
-                    t.centerOffset = (r - i) / 2;
-                    t.enabled = t.forcedEnabled || r > i;
-                    n || t.trigger(a, t)
-                }
-            }),
-            ti = u.extend({
-                init: function(n) {
-                    var t = this;
-                    u.fn.init.call(t);
-                    t.x = new ct(r({
-                        horizontal: !0
-                    }, n));
-                    t.y = new ct(r({
-                        horizontal: !1
-                    }, n));
-                    t.container = n.container;
-                    t.forcedMinScale = n.minScale;
-                    t.maxScale = n.maxScale || 100;
-                    t.bind(a, n)
-                },
-                rescale: function(n) {
-                    this.x.rescale(n);
-                    this.y.rescale(n);
-                    this.refresh()
-                },
-                centerCoordinates: function() {
-                    return {
-                        x: Math.min(0, -this.x.centerOffset),
-                        y: Math.min(0, -this.y.centerOffset)
-                    }
-                },
-                refresh: function() {
-                    var n = this;
-                    n.x.update();
-                    n.y.update();
-                    n.enabled = n.x.enabled || n.y.enabled;
-                    n.minScale = n.forcedMinScale || Math.min(n.x.minScale, n.y.minScale);
-                    n.fitScale = Math.max(n.x.minScale, n.y.minScale);
-                    n.trigger(a)
-                }
-            }),
-            lt = u.extend({
-                init: function(n) {
-                    var t = this;
-                    r(t, n);
-                    u.fn.init.call(t)
-                },
-                dragMove: function(n) {
-                    var t = this,
-                        i = t.dimension,
-                        r = t.axis,
-                        u = t.movable,
-                        f = u[r] + n;
-                    i.enabled && ((f < i.min && n < 0 || f > i.max && n > 0) && (n *= t.resistance), u.translateAxis(r, n), t.trigger(a, t))
-                }
-            }),
-            ii = pt.extend({
-                init: function(n) {
-                    var t = this,
-                        u, f, e, i;
-                    r(t, {
-                        elastic: !0
-                    }, n);
-                    e = t.elastic ? .5 : 0;
-                    i = t.movable;
-                    t.x = u = new lt({
-                        axis: "x",
-                        dimension: t.dimensions.x,
-                        resistance: e,
-                        movable: i
-                    });
-                    t.y = f = new lt({
-                        axis: "y",
-                        dimension: t.dimensions.y,
-                        resistance: e,
-                        movable: i
-                    });
-                    t.userEvents.bind(["move", "end", "gesturestart", "gesturechange"], {
-                        gesturestart: function(n) {
-                            t.gesture = n;
-                            t.offset = t.dimensions.container.offset()
-                        },
-                        gesturechange: function(n) {
-                            var h = t.gesture,
-                                c = h.center,
-                                l = n.center,
-                                r = n.distance / h.distance,
-                                v = t.dimensions.minScale,
-                                a = t.dimensions.maxScale,
-                                e, o, s;
-                            i.scale <= v && r < 1 && (r += (1 - r) * .8);
-                            i.scale * r >= a && (r = a / i.scale);
-                            o = i.x + t.offset.left;
-                            s = i.y + t.offset.top;
-                            e = {
-                                x: (o - c.x) * r + l.x - o,
-                                y: (s - c.y) * r + l.y - s
-                            };
-                            i.scaleWith(r);
-                            u.dragMove(e.x);
-                            f.dragMove(e.y);
-                            t.dimensions.rescale(i.scale);
-                            t.gesture = n;
-                            n.preventDefault()
-                        },
-                        move: function(n) {
-                            n.event.target.tagName.match(/textarea|input/i) || (u.dimension.enabled || f.dimension.enabled ? (u.dragMove(n.x.delta), f.dragMove(n.y.delta), n.preventDefault()) : n.touch.skip())
-                        },
-                        end: function(n) {
-                            n.preventDefault()
-                        }
-                    })
-                }
-            }),
-            ri = v.transitions.prefix + "Transform",
-            nt, at, c, vt, yt;
-        nt = v.hasHW3D ? function(n, t, i) {
-            return "translate3d(" + n + "px," + t + "px,0) scale(" + i + ")"
-        } : function(n, t, i) {
-            return "translate(" + n + "px," + t + "px) scale(" + i + ")"
-        };
-        at = u.extend({
-            init: function(t) {
-                var i = this;
-                u.fn.init.call(i);
-                i.element = n(t);
-                i.element[0].style.webkitTransformOrigin = "left top";
-                i.x = 0;
-                i.y = 0;
-                i.scale = 1;
-                i._saveCoordinates(nt(i.x, i.y, i.scale))
-            },
-            translateAxis: function(n, t) {
-                this[n] += t;
-                this.refresh()
-            },
-            scaleTo: function(n) {
-                this.scale = n;
-                this.refresh()
-            },
-            scaleWith: function(n) {
-                this.scale *= n;
-                this.refresh()
-            },
-            translate: function(n) {
-                this.x += n.x;
-                this.y += n.y;
-                this.refresh()
-            },
-            moveAxis: function(n, t) {
-                this[n] = t;
-                this.refresh()
-            },
-            moveTo: function(n) {
-                r(this, n);
-                this.refresh()
-            },
-            refresh: function() {
-                var n = this,
-                    r = n.x,
-                    u = n.y,
-                    t;
-                n.round && (r = Math.round(r), u = Math.round(u));
-                t = nt(r, u, n.scale);
-                t != n.coordinates && (i.support.browser.msie && i.support.browser.version < 10 ? (n.element[0].style.position = "absolute", n.element[0].style.left = n.x + "px", n.element[0].style.top = n.y + "px") : n.element[0].style[ri] = t, n._saveCoordinates(t), n.trigger(a))
-            },
-            _saveCoordinates: function(n) {
-                this.coordinates = n
-            }
-        });
-        c = o.extend({
-            init: function(n, t) {
-                var i = this,
-                    r;
-                o.fn.init.call(i, n, t);
-                r = i.options.group;
-                r in s ? s[r].push(i) : s[r] = [i]
-            },
-            events: [d, p, ot],
-            options: {
-                name: "DropTarget",
-                group: "default"
-            },
-            destroy: function() {
-                var i = this.options.group,
-                    t = s[i] || h[i],
-                    n;
-                if (t.length > 1) {
-                    for (o.fn.destroy.call(this), n = 0; n < t.length; n++)
-                        if (t[n] == this) {
-                            t.splice(n, 1);
-                            break
-                        }
-                } else c.destroyGroup(i)
-            },
-            _trigger: function(n, t) {
-                var i = this,
-                    u = y[i.options.group];
-                if (u) return i.trigger(n, r({}, t.event, {
-                    draggable: u,
-                    dropTarget: t.dropTarget
-                }))
-            },
-            _over: function(n) {
-                this._trigger(d, n)
-            },
-            _out: function(n) {
-                this._trigger(p, n)
-            },
-            _drop: function(n) {
-                var t = this,
-                    i = y[t.options.group];
-                i && (i.dropped = !t._trigger(ot, n))
-            }
-        });
-        c.destroyGroup = function(n) {
-            var t = s[n] || h[n],
-                i;
-            if (t) {
-                for (i = 0; i < t.length; i++) o.fn.destroy.call(t[i]);
-                t.length = 0;
-                delete s[n];
-                delete h[n]
-            }
-        };
-        c._cache = s;
-        vt = c.extend({
-            init: function(n, t) {
-                var i = this,
-                    r;
-                o.fn.init.call(i, n, t);
-                r = i.options.group;
-                r in h ? h[r].push(i) : h[r] = [i]
-            },
-            options: {
-                name: "DropTargetArea",
-                group: "default",
-                filter: null
-            }
-        });
-        yt = o.extend({
-            init: function(n, t) {
-                var r = this;
-                o.fn.init.call(r, n, t);
-                r._activated = !1;
-                r.userEvents = new wt(r.element, {
-                    global: !0,
-                    stopPropagation: !0,
-                    filter: r.options.filter,
-                    threshold: r.options.distance,
-                    start: f(r._start, r),
-                    hold: f(r._hold, r),
-                    move: f(r._drag, r),
-                    end: f(r._end, r),
-                    cancel: f(r._cancel, r)
-                });
-                r._afterEndHandler = f(r._afterEnd, r);
-                r.captureEscape = function(n) {
-                    n.keyCode === i.keys.ESC && (r._trigger(et, {
-                        event: n
-                    }), r.userEvents.cancel())
-                }
-            },
-            events: [rt, it, ut, ft, et],
-            options: {
-                name: "Draggable",
-                distance: 5,
-                group: "default",
-                cursorOffset: null,
-                axis: null,
-                container: null,
-                holdToDrag: !1,
-                dropped: !1
-            },
-            cancelHold: function() {
-                this._activated = !1
-            },
-            _updateHint: function(t) {
-                var r = this,
-                    i, o = r.options,
-                    u = r.boundaries,
-                    e = o.axis,
-                    f = r.options.cursorOffset;
-                f ? i = {
-                    left: t.x.location + f.left,
-                    top: t.y.location + f.top
-                } : (r.hintOffset.left += t.x.delta, r.hintOffset.top += t.y.delta, i = n.extend({}, r.hintOffset));
-                u && (i.top = st(i.top, u.y), i.left = st(i.left, u.x));
-                e === "x" ? delete i.top : e === "y" && delete i.left;
-                r.hint.css(i)
-            },
-            _start: function(t) {
-                var r = this,
-                    u = r.options,
-                    o = u.container,
-                    f = u.hint,
-                    e;
-                if (u.holdToDrag && !r._activated) {
-                    r.userEvents.cancel();
-                    return
-                }
-                r.currentTarget = t.target;
-                r.currentTargetOffset = b(r.currentTarget);
-                f && (r.hint && r.hint.stop(!0, !0).remove(), r.hint = i.isFunction(f) ? n(f.call(r, r.currentTarget)) : f, e = b(r.currentTarget), r.hintOffset = e, r.hint.css({
-                    position: "absolute",
-                    zIndex: 2e4,
-                    left: e.left,
-                    top: e.top
-                }).appendTo(l.body));
-                y[u.group] = r;
-                r.dropped = !1;
-                o && (r.boundaries = ht(o, r.hint));
-                r._trigger(it, t) && (r.userEvents.cancel(), r._afterEnd());
-                n(l).on(tt, r.captureEscape)
-            },
-            _hold: function(n) {
-                this.currentTarget = n.target;
-                this._trigger(rt, n) ? this.userEvents.cancel() : this._activated = !0
-            },
-            _drag: function(t) {
-                var i = this;
-                t.preventDefault();
-                i._withDropTarget(t, function(i, u) {
-                    if (!i) {
-                        e && (e._trigger(p, r(t, {
-                            dropTarget: n(e.targetElement)
-                        })), e = null);
-                        return
-                    }
-                    if (e) {
-                        if (u === e.targetElement) return;
-                        e._trigger(p, r(t, {
-                            dropTarget: n(e.targetElement)
-                        }))
-                    }
-                    i._trigger(d, r(t, {
-                        dropTarget: n(u)
-                    }));
-                    e = r(i, {
-                        targetElement: u
-                    })
-                });
-                i._trigger(ut, t);
-                i.hint && i._updateHint(t)
-            },
-            _end: function(t) {
-                var i = this;
-                i._withDropTarget(t, function(i, u) {
-                    i && (i._drop(r({}, t, {
-                        dropTarget: n(u)
-                    })), e = null)
-                });
-                i._trigger(ft, t);
-                i._cancel(t.event)
-            },
-            _cancel: function() {
-                var n = this;
-                n._activated = !1;
-                n.hint && !n.dropped ? setTimeout(function() {
-                    n.hint.stop(!0, !0).animate(n.currentTargetOffset, "fast", n._afterEndHandler)
-                }, 0) : n._afterEnd()
-            },
-            _trigger: function(n, t) {
-                var i = this;
-                return i.trigger(n, r({}, t.event, {
-                    x: t.x,
-                    y: t.y,
-                    currentTarget: i.currentTarget,
-                    dropTarget: t.dropTarget
-                }))
-            },
-            _withDropTarget: function(n, t) {
-                var r = this,
-                    i, u, o = r.options,
-                    f = s[o.group],
-                    e = h[o.group];
-                (f && f.length || e && e.length) && (i = g(n), r.hint && dt(r.hint[0], i) && (r.hint.hide(), i = g(n), i || (i = g(n)), r.hint.show()), u = gt(i, f, e), u ? t(u.target, u.targetElement) : t())
-            },
-            destroy: function() {
-                var n = this;
-                o.fn.destroy.call(n);
-                n._afterEnd();
-                n.userEvents.destroy()
-            },
-            _afterEnd: function() {
-                var t = this;
-                t.hint && t.hint.remove();
-                delete y[t.options.group];
-                t.trigger("destroy");
-                n(l).off(tt, t.captureEscape)
-            }
-        });
-        i.ui.plugin(c);
-        i.ui.plugin(vt);
-        i.ui.plugin(yt);
-        i.TapCapture = ni;
-        i.containerBoundaries = ht;
-        r(i.ui, {
-            Pane: ii,
-            PaneDimensions: ti,
-            Movable: at
-        })
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "reorderable",
-        name: "Reorderable",
-        category: "framework",
-        depends: ["core", "draganddrop"],
-        advanced: !0
-    }),
-    function(n) {
-        function u(t, i) {
-            t = n(t);
-            i ? t.find(".k-drag-status").removeClass("k-add").addClass("k-denied") : t.find(".k-drag-status").removeClass("k-denied").addClass("k-add")
-        }
-        var t = window.kendo,
-            i = t.ui.Widget,
-            r = "change",
-            f = "k-reorderable",
-            e = i.extend({
-                init: function(e, o) {
-                    var s = this,
-                        h, c = t.guid() + "-reorderable";
-                    i.fn.init.call(s, e, o);
-                    e = s.element.addClass(f);
-                    o = s.options;
-                    s.draggable = h = o.draggable || new t.ui.Draggable(e, {
-                        group: c,
-                        filter: o.filter,
-                        hint: o.hint
-                    });
-                    s.reorderDropCue = n('<div class="k-reorder-cue"><div class="k-icon k-i-arrow-s"><\/div><div class="k-icon k-i-arrow-n"><\/div><\/div>');
-                    e.find(h.options.filter).kendoDropTarget({
-                        group: h.options.group,
-                        dragenter: function(n) {
-                            if (s._draggable) {
-                                var i = this.element,
-                                    r, f = i[0] === s._draggable[0];
-                                u(n.draggable.hint, f);
-                                f || (r = t.getOffset(i), s.reorderDropCue.css({
-                                    height: i.outerHeight(),
-                                    top: r.top,
-                                    left: r.left + (i.index() > s._draggable.index() ? i.outerWidth() : 0)
-                                }).appendTo(document.body))
-                            }
-                        },
-                        dragleave: function(n) {
-                            u(n.draggable.hint, !0);
-                            s.reorderDropCue.remove()
-                        },
-                        drop: function() {
-                            if (s._draggable) {
-                                var t = s._draggable[0],
-                                    i = this.element[0],
-                                    n;
-                                t !== i && (n = e.find(h.options.filter), s.trigger(r, {
-                                    element: s._draggable,
-                                    oldIndex: n.index(t),
-                                    newIndex: n.index(i)
-                                }))
-                            }
-                        }
-                    });
-                    h.bind(["dragcancel", "dragend", "dragstart"], {
-                        dragcancel: function() {
-                            s.reorderDropCue.remove();
-                            s._draggable = null
-                        },
-                        dragend: function() {
-                            s.reorderDropCue.remove();
-                            s._draggable = null
-                        },
-                        dragstart: function(n) {
-                            s._draggable = n.currentTarget
-                        }
-                    })
-                },
-                options: {
-                    name: "Reorderable",
-                    filter: "*"
-                },
-                events: [r],
-                destroy: function() {
-                    var n = this;
-                    i.fn.destroy.call(n);
-                    n.draggable && n.draggable.destroy();
-                    t.destroy(n.element)
-                }
-            });
-        t.ui.plugin(e)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "resizable",
-        name: "Resizable",
-        category: "framework",
-        depends: ["core", "draganddrop"],
-        advanced: !0
-    }),
-    function(n, t) {
-        var u = window.kendo,
-            o = u.ui,
-            f = o.Widget,
-            r = n.proxy,
-            e = u.isFunction,
-            s = n.extend,
-            i = "horizontal",
-            h = "vertical",
-            c = "start",
-            l = "resize",
-            a = "resizeend",
-            v = f.extend({
-                init: function(n, t) {
-                    var u = this;
-                    f.fn.init.call(u, n, t);
-                    u.orientation = u.options.orientation.toLowerCase() != h ? i : h;
-                    u._positionMouse = u.orientation == i ? "x" : "y";
-                    u._position = u.orientation == i ? "left" : "top";
-                    u._sizingDom = u.orientation == i ? "outerWidth" : "outerHeight";
-                    u.draggable = new o.Draggable(n, {
-                        distance: 0,
-                        filter: t.handle,
-                        drag: r(u._resize, u),
-                        dragcancel: r(u._cancel, u),
-                        dragstart: r(u._start, u),
-                        dragend: r(u._stop, u)
-                    });
-                    u.userEvents = u.draggable.userEvents
-                },
-                events: [l, a, c],
-                options: {
-                    name: "Resizable",
-                    orientation: i
-                },
-                resize: function() {},
-                _max: function(n) {
-                    var i = this,
-                        u = i.hint ? i.hint[i._sizingDom]() : 0,
-                        r = i.options.max;
-                    return e(r) ? r(n) : r !== t ? i._initialElementPosition + r - u : r
-                },
-                _min: function(n) {
-                    var r = this,
-                        i = r.options.min;
-                    return e(i) ? i(n) : i !== t ? r._initialElementPosition + i : i
-                },
-                _start: function(t) {
-                    var i = this,
-                        r = i.options.hint,
-                        u = n(t.currentTarget);
-                    i._initialElementPosition = u.position()[i._position];
-                    i._initialMousePosition = t[i._positionMouse].startLocation;
-                    r && (i.hint = e(r) ? n(r(u)) : r, i.hint.css({
-                        position: "absolute"
-                    }).css(i._position, i._initialElementPosition).appendTo(i.element));
-                    i.trigger(c, t);
-                    i._maxPosition = i._max(t);
-                    i._minPosition = i._min(t);
-                    n(document.body).css("cursor", u.css("cursor"))
-                },
-                _resize: function(n) {
-                    var i = this,
-                        u = i._maxPosition,
-                        f = i._minPosition,
-                        e = i._initialElementPosition + (n[i._positionMouse].location - i._initialMousePosition),
-                        r;
-                    r = f !== t ? Math.max(f, e) : e;
-                    i.position = r = u !== t ? Math.min(u, r) : r;
-                    i.hint && i.hint.toggleClass(i.options.invalidClass || "", r == u || r == f).css(i._position, r);
-                    i.resizing = !0;
-                    i.trigger(l, s(n, {
-                        position: r
-                    }))
-                },
-                _stop: function(t) {
-                    var i = this;
-                    i.hint && i.hint.remove();
-                    i.resizing = !1;
-                    i.trigger(a, s(t, {
-                        position: i.position
-                    }));
-                    n(document.body).css("cursor", "")
-                },
-                _cancel: function(n) {
-                    var i = this;
-                    i.hint && (i.position = t, i.hint.css(i._position, i._initialElementPosition), i._stop(n))
-                },
-                destroy: function() {
-                    var n = this;
-                    f.fn.destroy.call(n);
-                    n.draggable && n.draggable.destroy()
-                },
-                press: function(n) {
-                    if (n) {
-                        var t = n.position(),
-                            i = this;
-                        i.userEvents.press(t.left, t.top, n[0]);
-                        i.targetPosition = t;
-                        i.target = n
-                    }
-                },
-                move: function(n) {
-                    var i = this,
-                        f = i._position,
-                        r = i.targetPosition,
-                        u = i.position;
-                    u === t && (u = r[f]);
-                    r[f] = u + n;
-                    i.userEvents.move(r.left, r.top)
-                },
-                end: function() {
-                    this.userEvents.end();
-                    this.target = this.position = t
-                }
-            });
-        u.ui.plugin(v)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "sortable",
-        name: "Sortable",
-        category: "framework",
-        depends: ["data"],
-        advanced: !0
-    }),
-    function(n, t) {
-        var i = window.kendo,
-            s = n.proxy,
-            r = "dir",
-            u = "asc",
-            h = "single",
-            c = "field",
-            f = "desc",
-            l = ".kendoSortable",
-            a = ".k-link",
-            e = "aria-sort",
-            o = i.ui.Widget,
-            v = o.extend({
-                init: function(n, t) {
-                    var i = this,
-                        r;
-                    o.fn.init.call(i, n, t);
-                    i._refreshHandler = s(i.refresh, i);
-                    i.dataSource = i.options.dataSource.bind("change", i._refreshHandler);
-                    r = i.element.find(a);
-                    r[0] || (r = i.element.wrapInner('<a class="k-link" href="#"/>').find(a));
-                    i.link = r;
-                    i.element.on("click" + l, s(i._click, i))
-                },
-                options: {
-                    name: "Sortable",
-                    mode: h,
-                    allowUnsort: !0,
-                    compare: null,
-                    filter: ""
-                },
-                destroy: function() {
-                    var n = this;
-                    o.fn.destroy.call(n);
-                    n.element.off(l);
-                    n.dataSource.unbind("change", n._refreshHandler)
-                },
-                refresh: function() {
-                    var o = this,
-                        a = o.dataSource.sort() || [],
-                        s, v, h, l, t = o.element,
-                        y = t.attr(i.attr(c));
-                    for (t.removeAttr(i.attr(r)), t.removeAttr(e), s = 0, v = a.length; s < v; s++) h = a[s], y == h.field && t.attr(i.attr(r), h.dir);
-                    l = t.attr(i.attr(r));
-                    t.find(".k-i-arrow-n,.k-i-arrow-s").remove();
-                    l === u ? (n('<span class="k-icon k-i-arrow-n" />').appendTo(o.link), t.attr(e, "ascending")) : l === f && (n('<span class="k-icon k-i-arrow-s" />').appendTo(o.link), t.attr(e, "descending"))
-                },
-                _click: function(n) {
-                    var e = this,
-                        v = e.element,
-                        y = v.attr(i.attr(c)),
-                        s = v.attr(i.attr(r)),
-                        l = e.options,
-                        p = e.options.compare == null ? t : e.options.compare,
-                        o = e.dataSource.sort() || [],
-                        a, w;
-                    if (n.preventDefault(), !l.filter || v.is(l.filter)) {
-                        if (s = s === u ? f : s === f && l.allowUnsort ? t : u, l.mode === h) o = [{
-                            field: y,
-                            dir: s,
-                            compare: p
-                        }];
-                        else if (l.mode === "multiple") {
-                            for (a = 0, w = o.length; a < w; a++)
-                                if (o[a].field === y) {
-                                    o.splice(a, 1);
-                                    break
-                                }
-                            o.push({
-                                field: y,
-                                dir: s,
-                                compare: p
-                            })
-                        }
-                        e.dataSource.sort(o)
-                    }
-                }
-            });
-        i.ui.plugin(v)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "selectable",
-        name: "Selectable",
-        category: "framework",
-        depends: ["core", "userevents"],
-        advanced: !0
-    }),
-    function(n) {
-        function y(n, t) {
-            var i = u.getOffset(n),
-                r = t.left + t.width,
-                f = t.top + t.height;
-            return i.right = i.left + n.outerWidth(), i.bottom = i.top + n.outerHeight(), !(i.left > r || i.right < t.left || i.top > f || i.bottom < t.top)
-        }
-
-        function p(n, i, u, e) {
-            for (var o, s = 0, h = n.length; s < h; s++) o = n.eq(s), y(o, u) ? o.hasClass(t) ? e && i !== o[0] && o.removeClass(t).addClass(r) : o.hasClass(f) || o.hasClass(r) || o.addClass(f) : o.hasClass(f) ? o.removeClass(f) : e && o.hasClass(r) && o.removeClass(r).addClass(t)
-        }
-        var u = window.kendo,
-            s = u.ui.Widget,
-            i = n.proxy,
-            h = Math.abs,
-            c = "aria-selected",
-            t = "k-state-selected",
-            f = "k-state-selecting",
-            e = "k-selectable",
-            o = "change",
-            v = ".kendoSelectable",
-            r = "k-state-unselecting",
-            l = !1,
-            a;
-        (function(n) {
-            (function() {
-                n('<div class="parent"><span /><\/div>').on("click", ">*", function() {
-                    l = !0
-                }).find("span").click().end().off()
-            })()
-        })(n);
-        a = s.extend({
-            init: function(t, r) {
-                var f = this,
-                    o;
-                s.fn.init.call(f, t, r);
-                f._marquee = n("<div class='k-marquee'><div class='k-marquee-color'><\/div><\/div>");
-                f._lastActive = null;
-                f.element.addClass(e);
-                o = f.options.multiple;
-                f.userEvents = new u.UserEvents(f.element, {
-                    global: !0,
-                    allowSelection: !0,
-                    filter: (l ? "" : "." + e + " ") + f.options.filter,
-                    tap: i(f._tap, f)
-                });
-                o && f.userEvents.bind("start", i(f._start, f)).bind("move", i(f._move, f)).bind("end", i(f._end, f)).bind("select", i(f._select, f))
-            },
-            events: [o],
-            options: {
-                name: "Selectable",
-                filter: ">*",
-                multiple: !1
-            },
-            _tap: function(i) {
-                var u = n(i.target),
-                    r = this,
-                    f = i.event.ctrlKey || i.event.metaKey,
-                    s = r.options.multiple,
-                    a = s && i.event.shiftKey,
-                    h, c = i.event.which,
-                    l = i.event.button;
-                u.closest("." + e)[0] !== r.element[0] || c && c == 3 || l && l == 2 || (h = u.hasClass(t), s && f || r.clear(), a ? r.selectRange(r._firstSelectee(), u) : (h && f ? (r._unselect(u), r._notify(o)) : r.value(u), r._lastActive = r._downTarget = u))
-            },
-            _start: function(i) {
-                var u = this,
-                    f = n(i.target),
-                    s = f.hasClass(t),
-                    o = i.event.ctrlKey || i.event.metaKey;
-                if (u._downTarget = f, f.closest("." + e)[0] !== u.element[0]) {
-                    u.userEvents.cancel();
-                    u._downTarget = null;
-                    return
-                }
-                u._marquee.appendTo(document.body).css({
-                    left: i.x.client + 1,
-                    top: i.y.client + 1,
-                    width: 0,
-                    height: 0
-                });
-                o || u.clear();
-                s && (u._selectElement(f, !0), o && f.addClass(r))
-            },
-            _move: function(n) {
-                var t = this,
-                    i = {
-                        left: n.x.startLocation > n.x.location ? n.x.location : n.x.startLocation,
-                        top: n.y.startLocation > n.y.location ? n.y.location : n.y.startLocation,
-                        width: h(n.x.initialDelta),
-                        height: h(n.y.initialDelta)
-                    },
-                    r = t.element.find(t.options.filter);
-                t._marquee.css(i);
-                p(r, t._downTarget[0], i, n.event.ctrlKey || n.event.metaKey);
-                n.preventDefault()
-            },
-            _end: function() {
-                var n = this;
-                n._marquee.remove();
-                n._unselect(n.element.find(n.options.filter + "." + r)).removeClass(r);
-                n.value(n.element.find(n.options.filter + "." + f));
-                n._lastActive = n._downTarget
-            },
-            value: function(n) {
-                var r = this,
-                    u = i(r._selectElement, r);
-                if (n) {
-                    n.each(function() {
-                        u(this)
-                    });
-                    r._notify(o);
-                    return
-                }
-                return r.element.find(r.options.filter + "." + t)
-            },
-            _firstSelectee: function() {
-                var n = this,
-                    t;
-                return n._lastActive !== null ? n._lastActive : (t = n.value(), t.length > 0 ? t[0] : n.element.find(n.options.filter))
-            },
-            _selectElement: function(i, r) {
-                var u = n(i),
-                    e = !r && this._notify("select", {
-                        element: i
-                    });
-                u.removeClass(f);
-                e || (u.addClass(t), this.options.aria && u.attr(c, !0))
-            },
-            _notify: function(n, t) {
-                return t = t || {}, this.trigger(n, t)
-            },
-            _unselect: function(n) {
-                return n.removeClass(t), this.options.aria && n.attr(c, !1), n
-            },
-            _select: function(t) {
-                var i = "input,a,textarea,.k-multiselect-wrap,select",
-                    r = u.support.browser.msie;
-                n(t.event.target).is(i) ? (this.userEvents.cancel(), this._downTarget = null) : r && (!r || n(u._activeElement()).is(i)) || t.preventDefault()
-            },
-            clear: function() {
-                var n = this.element.find(this.options.filter + "." + t);
-                this._unselect(n)
-            },
-            selectRange: function(r, u) {
-                var e = this,
-                    s = !1,
-                    h, l, a, f, v = e.element.find(e.options.filter),
-                    c = i(e._selectElement, e);
-                for (r = n(r)[0], u = n(u)[0], h = 0, l = v.length; h < l; h++) f = v[h], s ? (c(f), s = f !== u) : f === r ? (s = r !== u, c(f)) : f === u ? (a = r, r = u, u = a, s = !0, c(f)) : n(f).removeClass(t);
-                e._notify(o)
-            },
-            destroy: function() {
-                var n = this;
-                s.fn.destroy.call(n);
-                n.element.off(v);
-                n.userEvents.destroy()
-            }
-        });
-        u.ui.plugin(a)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "button",
-        name: "Button",
-        category: "web",
-        description: "The Button widget displays styled buttons.",
-        depends: ["core"]
-    }),
-    function(n, t) {
-        var u = window.kendo,
-            o = u.ui.Widget,
-            i = n.proxy,
-            f = u.keys,
-            e = "click",
-            l = "k-button",
-            a = "k-button-icon",
-            v = "k-button-icontext",
-            r = ".kendoButton",
-            s = "disabled",
-            y = "k-state-disabled",
-            h = "k-state-focused",
-            c = "k-state-selected",
-            p = o.extend({
-                init: function(n, t) {
-                    var f = this;
-                    o.fn.init.call(f, n, t);
-                    n = f.wrapper = f.element;
-                    t = f.options;
-                    n.addClass(l).attr("role", "button");
-                    t.enable = t.enable && !n.attr(s);
-                    f.enable(t.enable);
-                    f._tabindex();
-                    f._graphics();
-                    n.on(e + r, i(f._click, f)).on("focus" + r, i(f._focus, f)).on("blur" + r, i(f._blur, f)).on("keydown" + r, i(f._keydown, f)).on("keyup" + r, i(f._keyup, f));
-                    u.notify(f)
-                },
-                events: [e],
-                options: {
-                    name: "Button",
-                    icon: "",
-                    spriteCssClass: "",
-                    imageUrl: "",
-                    enable: !0
-                },
-                _isNativeButton: function() {
-                    return this.element.prop("tagName").toLowerCase() == "button"
-                },
-                _click: function(n) {
-                    this.options.enable && this.trigger(e, {
-                        event: n
-                    })
-                },
-                _focus: function() {
-                    this.options.enable && this.element.addClass(h)
-                },
-                _blur: function() {
-                    this.element.removeClass(h)
-                },
-                _keydown: function(n) {
-                    var t = this;
-                    t._isNativeButton() || (n.keyCode == f.ENTER || n.keyCode == f.SPACEBAR) && (n.keyCode == f.SPACEBAR && (n.preventDefault(), t.options.enable && t.element.addClass(c)), t._click(n))
-                },
-                _keyup: function() {
-                    this.element.removeClass(c)
-                },
-                _graphics: function() {
-                    var h = this,
-                        t = h.element,
-                        u = h.options,
-                        f = u.icon,
-                        e = u.spriteCssClass,
-                        o = u.imageUrl,
-                        i, r, s;
-                    (e || o || f) && (s = !0, t.contents().not("span.k-sprite").not("span.k-icon").not("img.k-image").each(function(t, i) {
-                        (i.nodeType == 1 || i.nodeType == 3 && n.trim(i.nodeValue).length > 0) && (s = !1)
-                    }), s ? t.addClass(a) : t.addClass(v));
-                    f ? (i = t.children("span.k-icon").first(), i[0] || (i = n('<span class="k-icon"><\/span>').prependTo(t)), i.addClass("k-i-" + f)) : e ? (i = t.children("span.k-sprite").first(), i[0] || (i = n('<span class="k-sprite"><\/span>').prependTo(t)), i.addClass(e)) : o && (r = t.children("img.k-image").first(), r[0] || (r = n('<img alt="icon" class="k-image" />').prependTo(t)), r.attr("src", o))
-                },
-                enable: function(n) {
-                    var i = this,
-                        r = i.element;
-                    n === t && (n = !0);
-                    n = !!n;
-                    i.options.enable = n;
-                    r.toggleClass(y, !n).attr("aria-disabled", !n).attr(s, !n)
-                }
-            });
-        u.ui.plugin(p)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "pager",
-        name: "Pager",
-        category: "framework",
-        depends: ["data"],
-        advanced: !0
-    }),
-    function(n, t) {
-        function v(n, t, r, u, f) {
-            return n({
-                idx: t,
-                text: r,
-                ns: i.ns,
-                numeric: u,
-                title: f || ""
-            })
-        }
-
-        function e(n, t, i) {
-            return tt({
-                className: n.substring(1),
-                text: t,
-                wrapClassName: i || ""
-            })
-        }
-
-        function o(n, t, r, u) {
-            n.find(t).parent().attr(i.attr("page"), r).attr("tabindex", -1).toggleClass("k-state-disabled", u)
-        }
-
-        function w(n, t) {
-            o(n, h, 1, t <= 1)
-        }
-
-        function b(n, t) {
-            o(n, l, Math.max(1, t - 1), t <= 1)
-        }
-
-        function k(n, t, i) {
-            o(n, a, Math.min(i, t + 1), t >= i)
-        }
-
-        function d(n, t, i) {
-            o(n, c, i, t >= i)
-        }
-        var i = window.kendo,
-            y = i.ui,
-            s = y.Widget,
-            u = n.proxy,
-            h = ".k-i-seek-w",
-            c = ".k-i-seek-e",
-            l = ".k-i-arrow-w",
-            a = ".k-i-arrow-e",
-            r = "change",
-            f = ".kendoPager",
-            p = "click",
-            g = "keydown",
-            nt = "disabled",
-            tt = i.template('<a href="\\#" title="#=text#" class="k-link k-pager-nav #= wrapClassName #"><span class="k-icon #= className #">#=text#<\/span><\/a>'),
-            it = s.extend({
-                init: function(t, o) {
-                    var v = this,
-                        nt, y;
-                    if (s.fn.init.call(v, t, o), o = v.options, v.dataSource = i.data.DataSource.create(o.dataSource), v.linkTemplate = i.template(v.options.linkTemplate), v.selectTemplate = i.template(v.options.selectTemplate), nt = v.page(), y = v.totalPages(), v._refreshHandler = u(v.refresh, v), v.dataSource.bind(r, v._refreshHandler), o.previousNext && (v.element.find(h).length || (v.element.append(e(h, o.messages.first, "k-pager-first")), w(v.element, nt, y)), v.element.find(l).length || (v.element.append(e(l, o.messages.previous)), b(v.element, nt, y))), o.numeric && (v.list = v.element.find(".k-pager-numbers"), v.list.length || (v.list = n('<ul class="k-pager-numbers k-reset" />').appendTo(v.element))), o.input) {
-                        v.element.find(".k-pager-input").length || v.element.append('<span class="k-pager-input k-label">' + o.messages.page + '<input class="k-textbox">' + i.format(o.messages.of, y) + "<\/span>");
-                        v.element.on(g + f, ".k-pager-input input", u(v._keydown, v))
-                    }
-                    if (o.previousNext && (v.element.find(a).length || (v.element.append(e(a, o.messages.next)), k(v.element, nt, y)), v.element.find(c).length || (v.element.append(e(c, o.messages.last, "k-pager-last")), d(v.element, nt, y))), o.pageSizes) {
-                        v.element.find(".k-pager-sizes").length || n('<span class="k-pager-sizes k-label"><select/>' + o.messages.itemsPerPage + "<\/span>").appendTo(v.element).find("select").html(n.map(n.isArray(o.pageSizes) ? o.pageSizes : [5, 10, 20], function(n) {
-                            return "<option>" + n + "<\/option>"
-                        }).join("")).end().appendTo(v.element);
-                        v.element.find(".k-pager-sizes select").val(v.pageSize());
-                        i.ui.DropDownList && v.element.find(".k-pager-sizes select").show().kendoDropDownList();
-                        v.element.on(r + f, ".k-pager-sizes select", u(v._change, v))
-                    }
-                    if (o.refresh) {
-                        v.element.find(".k-pager-refresh").length || v.element.append('<a href="#" class="k-pager-refresh k-link" title="' + o.messages.refresh + '"><span class="k-icon k-i-refresh">' + o.messages.refresh + "<\/span><\/a>");
-                        v.element.on(p + f, ".k-pager-refresh", u(v._refreshClick, v))
-                    }
-                    o.info && (v.element.find(".k-pager-info").length || v.element.append('<span class="k-pager-info k-label" />'));
-                    v.element.on(p + f, "a", u(v._click, v)).addClass("k-pager-wrap k-widget");
-                    o.autoBind && v.refresh();
-                    i.notify(v)
-                },
-                destroy: function() {
-                    var n = this;
-                    s.fn.destroy.call(n);
-                    n.element.off(f);
-                    n.dataSource.unbind(r, n._refreshHandler);
-                    i.destroy(n.element)
-                },
-                events: [r],
-                options: {
-                    name: "Pager",
-                    selectTemplate: '<li><span class="k-state-selected">#=text#<\/span><\/li>',
-                    linkTemplate: '<li><a tabindex="-1" href="\\#" class="k-link" data-#=ns#page="#=idx#" #if (title !== "") {# title="#=title#" #}#>#=text#<\/a><\/li>',
-                    buttonCount: 10,
-                    autoBind: !0,
-                    numeric: !0,
-                    info: !0,
-                    input: !1,
-                    previousNext: !0,
-                    pageSizes: !1,
-                    refresh: !1,
-                    messages: {
-                        display: "{0} - {1} of {2} items",
-                        empty: "No items to display",
-                        page: "Page",
-                        of: "of {0}",
-                        itemsPerPage: "items per page",
-                        first: "Go to the first page",
-                        previous: "Go to the previous page",
-                        next: "Go to the next page",
-                        last: "Go to the last page",
-                        refresh: "Refresh",
-                        morePages: "More pages"
-                    }
-                },
-                setDataSource: function(n) {
-                    var t = this;
-                    t.dataSource.unbind(r, t._refreshHandler);
-                    t.dataSource = t.options.dataSource = n;
-                    n.bind(r, t._refreshHandler);
-                    t.options.autoBind && n.fetch()
-                },
-                refresh: function(n) {
-                    var t = this,
-                        e, a, s = 1,
-                        f = "",
-                        y, r = t.page(),
-                        u = t.options,
-                        h = t.pageSize(),
-                        c = t.dataSource.total(),
-                        o = t.totalPages(),
-                        p = t.linkTemplate,
-                        l = u.buttonCount;
-                    if (!n || n.action != "itemchange") {
-                        if (u.numeric) {
-                            for (r > l && (y = r % l, s = y === 0 ? r - l + 1 : r - y + 1), a = Math.min(s + l - 1, o), s > 1 && (f += v(p, s - 1, "...", !1, u.messages.morePages)), e = s; e <= a; e++) f += v(e == r ? t.selectTemplate : p, e, e, !0);
-                            a < o && (f += v(p, e, "...", !1, u.messages.morePages));
-                            f === "" && (f = t.selectTemplate({
-                                text: 0
-                            }));
-                            t.list.html(f)
-                        }
-                        u.info && (f = c > 0 ? i.format(u.messages.display, (r - 1) * h + 1, Math.min(r * h, c), c) : u.messages.empty, t.element.find(".k-pager-info").html(f));
-                        u.input && t.element.find(".k-pager-input").html(t.options.messages.page + '<input class="k-textbox">' + i.format(u.messages.of, o)).find("input").val(r).attr(nt, c < 1).toggleClass("k-state-disabled", c < 1);
-                        u.previousNext && (w(t.element, r, o), b(t.element, r, o), k(t.element, r, o), d(t.element, r, o));
-                        u.pageSizes && t.element.find(".k-pager-sizes select").val(h).filter("[" + i.attr("role") + "=dropdownlist]").kendoDropDownList("value", h).kendoDropDownList("text", h)
-                    }
-                },
-                _keydown: function(n) {
-                    if (n.keyCode === i.keys.ENTER) {
-                        var r = this.element.find(".k-pager-input").find("input"),
-                            t = parseInt(r.val(), 10);
-                        (isNaN(t) || t < 1 || t > this.totalPages()) && (t = this.page());
-                        r.val(t);
-                        this.page(t)
-                    }
-                },
-                _refreshClick: function(n) {
-                    n.preventDefault();
-                    this.dataSource.read()
-                },
-                _change: function(n) {
-                    var t = parseInt(n.currentTarget.value, 10);
-                    isNaN(t) || this.dataSource.pageSize(t)
-                },
-                _click: function(t) {
-                    var r = n(t.currentTarget);
-                    t.preventDefault();
-                    r.is(".k-state-disabled") || this.page(r.attr(i.attr("page")))
-                },
-                totalPages: function() {
-                    return Math.ceil((this.dataSource.total() || 0) / this.pageSize())
-                },
-                pageSize: function() {
-                    return this.dataSource.pageSize() || this.dataSource.total()
-                },
-                page: function(n) {
-                    if (n !== t) this.dataSource.page(n), this.trigger(r, {
-                        index: n
-                    });
-                    else return this.dataSource.total() > 0 ? this.dataSource.page() : 0
-                }
-            });
-        y.plugin(it)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "popup",
-        name: "Pop-up",
-        category: "framework",
-        depends: ["core"],
-        advanced: !0
-    }),
-    function(n) {
-        function y(t, i) {
-            return t === i || n.contains(t, i)
-        }
-        var t = window.kendo,
-            it = t.ui,
-            p = it.Widget,
-            f = t.support,
-            r = t.getOffset,
-            lt = t._activeElement,
-            w = "open",
-            b = "close",
-            rt = "deactivate",
-            ut = "activate",
-            u = "center",
-            ft = "left",
-            s = "right",
-            k = "top",
-            h = "bottom",
-            d = "absolute",
-            et = "hidden",
-            c = "body",
-            g = "location",
-            e = "position",
-            ot = "visible",
-            st = "effects",
-            ht = "k-state-active",
-            l = "k-state-border",
-            at = /k-state-border-(\w+)/,
-            ct = ".k-picker-wrap, .k-dropdown-wrap, .k-link",
-            a = "down",
-            nt = n(window),
-            tt = n(document.documentElement),
-            v = "resize scroll",
-            vt = f.transitions.css,
-            yt = vt + "transform",
-            i = n.extend,
-            o = ".kendoPopup",
-            pt = ["font-family", "font-size", "font-stretch", "font-style", "font-weight", "line-height"],
-            wt = p.extend({
-                init: function(r, u) {
-                    var f = this,
-                        e;
-                    u = u || {};
-                    u.isRtl && (u.origin = u.origin || h + " " + s, u.position = u.position || k + " " + s);
-                    p.fn.init.call(f, r, u);
-                    r = f.element;
-                    u = f.options;
-                    f.collisions = u.collision ? u.collision.split(" ") : [];
-                    f.collisions.length === 1 && f.collisions.push(f.collisions[0]);
-                    e = n(f.options.anchor).closest(".k-popup,.k-group").filter(":not([class^=km-])");
-                    u.appendTo = n(n(u.appendTo)[0] || e[0] || c);
-                    f.element.hide().addClass("k-popup k-group k-reset").toggleClass("k-rtl", !!u.isRtl).css({
-                        position: d
-                    }).appendTo(u.appendTo).on("mouseenter" + o, function() {
-                        f._hovered = !0
-                    }).on("mouseleave" + o, function() {
-                        f._hovered = !1
-                    });
-                    if (f.wrapper = n(), u.animation === !1 && (u.animation = {
-                            open: {
-                                effects: {}
-                            },
-                            close: {
-                                hide: !0,
-                                effects: {}
-                            }
-                        }), i(u.animation.open, {
-                            complete: function() {
-                                f.wrapper.css({
-                                    overflow: ot
-                                });
-                                f.trigger(ut)
-                            }
-                        }), i(u.animation.close, {
-                            complete: function() {
-                                f.wrapper.hide();
-                                var o = f.wrapper.data(g),
-                                    s = n(u.anchor),
-                                    i, e;
-                                o && f.wrapper.css(o);
-                                u.anchor != c && (i = (s[0].className.match(at) || ["", "down"])[1], e = l + "-" + i, s.removeClass(e).children(ct).removeClass(ht).removeClass(e), r.removeClass(l + "-" + t.directions[i].reverse));
-                                f._closing = !1;
-                                f.trigger(rt)
-                            }
-                        }), f._mousedownProxy = function(n) {
-                            f._mousedown(n)
-                        }, f._resizeProxy = function(n) {
-                            f._resize(n)
-                        }, u.toggleTarget) n(u.toggleTarget).on(u.toggleEvent + o, n.proxy(f.toggle, f))
-                },
-                events: [w, ut, b, rt],
-                options: {
-                    name: "Popup",
-                    toggleEvent: "click",
-                    origin: h + " " + ft,
-                    position: k + " " + ft,
-                    anchor: c,
-                    collision: "flip fit",
-                    viewport: window,
-                    copyAnchorStyles: !0,
-                    autosize: !1,
-                    modal: !1,
-                    animation: {
-                        open: {
-                            effects: "slideIn:down",
-                            transition: !0,
-                            duration: 200
-                        },
-                        close: {
-                            duration: 100,
-                            hide: !0
-                        }
-                    }
-                },
-                destroy: function() {
-                    var i = this,
-                        r = i.options,
-                        f = i.element.off(o),
-                        u;
-                    p.fn.destroy.call(i);
-                    r.toggleTarget && n(r.toggleTarget).off(o);
-                    r.modal || (tt.unbind(a, i._mousedownProxy), nt.unbind(v, i._resizeProxy));
-                    t.destroy(i.element.children());
-                    r.appendTo[0] === document.body && (u = f.parent(".k-animation-container"), u[0] ? u.remove() : f.remove())
-                },
-                open: function(r, u) {
-                    var o = this,
-                        rt = {
-                            isFixed: !isNaN(parseInt(u, 10)),
-                            x: r,
-                            y: u
-                        },
-                        y = o.element,
-                        s = o.options,
-                        p = "down",
-                        h, b, g = n(s.anchor),
-                        it;
-                    if (!o.visible()) {
-                        if (s.copyAnchorStyles && y.css(t.getComputedStyles(g[0], pt)), y.data("animating") || o.trigger(w)) return;
-                        s.modal || (tt.unbind(a, o._mousedownProxy).bind(a, o._mousedownProxy), f.mobileOS.ios || f.mobileOS.android || nt.unbind(v, o._resizeProxy).bind(v, o._resizeProxy));
-                        o.wrapper = b = t.wrap(y, s.autosize).css({
-                            overflow: et,
-                            display: "block",
-                            position: d
-                        });
-                        f.mobileOS.android && b.add(g).css(yt, "translatez(0)");
-                        b.css(e);
-                        n(s.appendTo)[0] == document.body && b.css(k, "-10000px");
-                        h = i(!0, {}, s.animation.open);
-                        o.flipped = o._position(rt);
-                        h.effects = t.parseEffects(h.effects, o.flipped);
-                        p = h.effects.slideIn ? h.effects.slideIn.direction : p;
-                        s.anchor != c && (it = l + "-" + p, y.addClass(l + "-" + t.directions[p].reverse), g.addClass(it).children(ct).addClass(ht).addClass(it));
-                        y.data(st, h.effects).kendoStop(!0).kendoAnimate(h)
-                    }
-                },
-                toggle: function() {
-                    var n = this;
-                    n[n.visible() ? b : w]()
-                },
-                visible: function() {
-                    return this.element.is(":" + ot)
-                },
-                close: function() {
-                    var r = this,
-                        s = r.options,
-                        o, u, f, e;
-                    if (r.visible()) {
-                        if (o = r.wrapper[0] ? r.wrapper : t.wrap(r.element).hide(), r._closing || r.trigger(b)) return;
-                        r.element.find(".k-popup").each(function() {
-                            var i = n(this),
-                                t = i.data("kendoPopup");
-                            t && t.close()
-                        });
-                        tt.unbind(a, r._mousedownProxy);
-                        nt.unbind(v, r._resizeProxy);
-                        u = i(!0, {}, s.animation.close);
-                        f = r.element.data(st);
-                        e = u.effects;
-                        !e && !t.size(e) && f && t.size(f) && (u.effects = f, u.reverse = !0);
-                        r._closing = !0;
-                        r.element.kendoStop(!0);
-                        o.css({
-                            overflow: et
-                        });
-                        r.element.kendoAnimate(u)
-                    }
-                },
-                _resize: function(n) {
-                    var t = this;
-                    n.type === "resize" ? (clearTimeout(t._resizeTimeout), t._resizeTimeout = setTimeout(function() {
-                        t._position();
-                        t._resizeTimeout = null
-                    }, 50)) : t._hovered || y(t.element[0], lt()) || t.close()
-                },
-                _mousedown: function(i) {
-                    var u = this,
-                        s = u.element[0],
-                        e = u.options,
-                        h = n(e.anchor)[0],
-                        o = e.toggleTarget,
-                        f = t.eventTarget(i),
-                        r = n(f).closest(".k-popup"),
-                        c = r.parent().parent(".km-shim").length;
-                    (r = r[0], c || !r || r === u.element[0]) && n(i.target).closest("a").data("rel") !== "popover" && (y(s, f) || y(h, f) || o && y(n(o)[0], f) || u.close())
-                },
-                _fit: function(n, t, i) {
-                    var r = 0;
-                    return n + t > i && (r = i - (n + t)), n < 0 && (r = -n), r
-                },
-                _flip: function(n, t, i, r, f, e, o) {
-                    var s = 0;
-                    return o = o || t, e !== f && e !== u && f !== u && (n + o > r && (s += -(i + t)), n + s < 0 && (s += i + t)), s
-                },
-                _position: function(t) {
-                    var o = this,
-                        nt = o.element.css(e, ""),
-                        u = o.wrapper,
-                        y = o.options,
-                        c = n(y.viewport),
-                        ot = n(c).offset(),
-                        l = n(y.anchor),
-                        tt = y.origin.toLowerCase().split(" "),
-                        it = y.position.toLowerCase().split(" "),
-                        p = o.collisions,
-                        w = f.zoomLevel(),
-                        b, rt, h, k = 10002,
-                        ut = 0,
-                        st, v, s, et;
-                    if (b = l.parents().filter(u.siblings()), b[0])
-                        if (h = Number(n(b).css("zIndex")), h) k = h + 1;
-                        else
-                            for (rt = l.parentsUntil(b), st = rt.length; ut < st; ut++) h = Number(n(rt[ut]).css("zIndex")), h && k < h && (k = h + 1);
-                    u.css("zIndex", k);
-                    t && t.isFixed ? u.css({
-                        left: t.x,
-                        top: t.y
-                    }) : u.css(o._align(tt, it));
-                    var ft = r(u, e, l[0] === u.offsetParent()[0]),
-                        a = r(u),
-                        ht = l.offsetParent().parent(".k-animation-container,.k-popup,.k-group");
-                    return ht.length && (ft = r(u, e, !0), a = r(u)), c[0] === window ? (a.top -= window.pageYOffset || document.documentElement.scrollTop || 0, a.left -= window.pageXOffset || document.documentElement.scrollLeft || 0) : (a.top -= ot.top, a.left -= ot.left), o.wrapper.data(g) || u.data(g, i({}, ft)), v = i({}, a), s = i({}, ft), p[0] === "fit" && (s.top += o._fit(v.top, u.outerHeight(), c.height() / w)), p[1] === "fit" && (s.left += o._fit(v.left, u.outerWidth(), c.width() / w)), et = i({}, s), p[0] === "flip" && (s.top += o._flip(v.top, nt.outerHeight(), l.outerHeight(), c.height() / w, tt[0], it[0], u.outerHeight())), p[1] === "flip" && (s.left += o._flip(v.left, nt.outerWidth(), l.outerWidth(), c.width() / w, tt[1], it[1], u.outerWidth())), nt.css(e, d), u.css(s), s.left != et.left || s.top != et.top
-                },
-                _align: function(t, i) {
-                    var c = this,
-                        v = c.wrapper,
-                        l = n(c.options.anchor),
-                        y = t[0],
-                        p = t[1],
-                        w = i[0],
-                        b = i[1],
-                        k = r(l),
-                        d = n(c.options.appendTo),
-                        a, g = v.outerWidth(),
-                        nt = v.outerHeight(),
-                        tt = l.outerWidth(),
-                        it = l.outerHeight(),
-                        f = k.top,
-                        e = k.left,
-                        o = Math.round;
-                    return d[0] != document.body && (a = r(d), f -= a.top, e -= a.left), y === h && (f += it), y === u && (f += o(it / 2)), w === h && (f -= nt), w === u && (f -= o(nt / 2)), p === s && (e += tt), p === u && (e += o(tt / 2)), b === s && (e -= g), b === u && (e -= o(g / 2)), {
-                        top: f,
-                        left: e
-                    }
-                }
-            });
-        it.plugin(wt)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "tooltip",
-        name: "Tooltip",
-        category: "web",
-        description: "The Tooltip widget displays a popup hint for a given html element.",
-        depends: ["core", "popup"]
-    }),
-    function(n) {
-        function w(n) {
-            while (n.length) ot(n), n = n.parent()
-        }
-
-        function ot(n) {
-            var i = n.data(t.ns + "title");
-            i && (n.attr("title", i), n.removeData(t.ns + "title"))
-        }
-
-        function st(n) {
-            var i = n.attr("title");
-            i && (n.data(t.ns + "title", i), n.attr("title", ""))
-        }
-
-        function b(n) {
-            while (n.length && !n.is("body")) st(n), n = n.parent()
-        }
-        var t = window.kendo,
-            u = t.ui.Widget,
-            k = t.ui.Popup,
-            d = t.isFunction,
-            g = n.isPlainObject,
-            s = n.extend,
-            r = n.proxy,
-            f = n(document),
-            nt = t.isLocalUrl,
-            h = "_tt_active",
-            c = "aria-describedby",
-            l = "show",
-            a = "hide",
-            v = "error",
-            e = "contentLoad",
-            y = "requestStart",
-            o = "k-content-frame",
-            tt = '<div role="tooltip" class="k-widget k-tooltip#if (!autoHide) {# k-tooltip-closable#}#">#if (!autoHide) {# <div class="k-tooltip-button"><a href="\\#" class="k-icon k-i-close">close<\/a><\/div> #}#<div class="k-tooltip-content"><\/div>#if (callout){ #<div class="k-callout k-callout-#=dir#"><\/div>#}#<\/div>',
-            it = t.template("<iframe frameborder='0' class='" + o + "' src='#= content.url #'>This page requires frames in order to show content<\/iframe>"),
-            i = ".kendoTooltip",
-            rt = {
-                bottom: {
-                    origin: "bottom center",
-                    position: "top center"
-                },
-                top: {
-                    origin: "top center",
-                    position: "bottom center"
-                },
-                left: {
-                    origin: "center left",
-                    position: "center right",
-                    collision: "fit flip"
-                },
-                right: {
-                    origin: "center right",
-                    position: "center left",
-                    collision: "fit flip"
-                },
-                center: {
-                    position: "center center",
-                    origin: "center center"
-                }
-            },
-            ut = {
-                top: "bottom",
-                bottom: "top",
-                left: "right",
-                right: "left",
-                center: "center"
-            },
-            p = {
-                bottom: "n",
-                top: "s",
-                left: "e",
-                right: "w",
-                center: "n"
-            },
-            ft = {
-                horizontal: {
-                    offset: "top",
-                    size: "outerHeight"
-                },
-                vertical: {
-                    offset: "left",
-                    size: "outerWidth"
-                }
-            },
-            et = function(n) {
-                return n.target.data(t.ns + "title")
-            },
-            ht = u.extend({
-                init: function(n, t) {
-                    var f = this,
-                        e;
-                    u.fn.init.call(f, n, t);
-                    e = f.options.position.match(/left|right/) ? "horizontal" : "vertical";
-                    f.dimensions = ft[e];
-                    f._documentKeyDownHandler = r(f._documentKeyDown, f);
-                    f.element.on(f.options.showOn + i, f.options.filter, r(f._showOn, f)).on("mouseenter" + i, f.options.filter, r(f._mouseenter, f));
-                    if (this.options.autoHide) f.element.on("mouseleave" + i, f.options.filter, r(f._mouseleave, f))
-                },
-                options: {
-                    name: "Tooltip",
-                    filter: "",
-                    content: et,
-                    showAfter: 100,
-                    callout: !0,
-                    position: "bottom",
-                    showOn: "mouseenter",
-                    autoHide: !0,
-                    width: null,
-                    height: null,
-                    animation: {
-                        open: {
-                            effects: "fade:in",
-                            duration: 0
-                        },
-                        close: {
-                            effects: "fade:out",
-                            duration: 40,
-                            hide: !0
-                        }
-                    }
-                },
-                events: [l, a, e, v, y],
-                _mouseenter: function(t) {
-                    b(n(t.currentTarget))
-                },
-                _showOn: function(t) {
-                    var i = this,
-                        r = n(t.currentTarget);
-                    i.options.showOn && i.options.showOn.match(/click|focus/) ? i._show(r) : (clearTimeout(i.timeout), i.timeout = setTimeout(function() {
-                        i._show(r)
-                    }, i.options.showAfter))
-                },
-                _appendContent: function(n) {
-                    var u = this,
-                        r = u.options.content,
-                        f = u.content,
-                        h = u.options.iframe,
-                        s;
-                    if (g(r) && r.url)
-                        if ("iframe" in u.options || (h = !nt(r.url)), u.trigger(y, {
-                                options: r,
-                                target: n
-                            }), h) {
-                            f.hide();
-                            s = f.find("." + o)[0];
-                            s ? s.src = r.url || s.src : f.html(it({
-                                content: r
-                            }));
-                            f.find("." + o).off("load" + i).on("load" + i, function() {
-                                u.trigger(e);
-                                f.show()
-                            })
-                        } else f.empty(), t.ui.progress(f, !0), u._ajaxRequest(r);
-                    else r && d(r) ? (r = r({
-                        sender: this,
-                        target: n
-                    }), u.content.html(r || "")) : u.content.html(r)
-                },
-                _ajaxRequest: function(n) {
-                    var i = this;
-                    jQuery.ajax(s({
-                        type: "GET",
-                        dataType: "html",
-                        cache: !1,
-                        error: function(n, r) {
-                            t.ui.progress(i.content, !1);
-                            i.trigger(v, {
-                                status: r,
-                                xhr: n
-                            })
-                        },
-                        success: r(function(n) {
-                            t.ui.progress(i.content, !1);
-                            i.content.html(n);
-                            i.trigger(e)
-                        }, i)
-                    }, n))
-                },
-                _documentKeyDown: function(n) {
-                    n.keyCode === t.keys.ESC && this.hide()
-                },
-                refresh: function() {
-                    var t = this,
-                        n = t.popup;
-                    n && n.options.anchor && t._appendContent(n.options.anchor)
-                },
-                hide: function() {
-                    this.popup && this.popup.close()
-                },
-                show: function(n) {
-                    n = n || this.element;
-                    b(n);
-                    this._show(n)
-                },
-                _show: function(n) {
-                    var t = this,
-                        r = t.target();
-                    t.popup || t._initPopup();
-                    r && r[0] != n[0] && (t.popup.close(), t.popup.element.kendoStop(!0, !0));
-                    r && r[0] == n[0] || (t._appendContent(n), t.popup.options.anchor = n);
-                    t.popup.one("deactivate", function() {
-                        w(n);
-                        n.removeAttr(c);
-                        this.element.removeAttr("id").attr("aria-hidden", !0);
-                        f.off("keydown" + i, t._documentKeyDownHandler)
-                    });
-                    t.popup.open()
-                },
-                _initPopup: function() {
-                    var u = this,
-                        e = u.options,
-                        o = n(t.template(tt)({
-                            callout: e.callout && e.position !== "center",
-                            dir: p[e.position],
-                            autoHide: e.autoHide
-                        }));
-                    if (u.popup = new k(o, s({
-                            activate: function() {
-                                var t = this.options.anchor,
-                                    n = t[0].id || u.element[0].id;
-                                n && (t.attr(c, n + h), this.element.attr("id", n + h));
-                                e.callout && u._positionCallout();
-                                this.element.removeAttr("aria-hidden");
-                                f.on("keydown" + i, u._documentKeyDownHandler);
-                                u.trigger(l)
-                            },
-                            close: function() {
-                                u.trigger(a)
-                            },
-                            copyAnchorStyles: !1,
-                            animation: e.animation
-                        }, rt[e.position])), o.css({
-                            width: e.width,
-                            height: e.height
-                        }), u.content = o.find(".k-tooltip-content"), u.arrow = o.find(".k-callout"), e.autoHide) o.on("mouseleave" + i, r(u._mouseleave, u));
-                    else o.on("click" + i, ".k-tooltip-button", r(u._closeButtonClick, u))
-                },
-                _closeButtonClick: function(n) {
-                    n.preventDefault();
-                    this.hide()
-                },
-                _mouseleave: function(t) {
-                    if (this.popup) {
-                        var r = n(t.currentTarget),
-                            i = r.offset(),
-                            u = t.pageX,
-                            f = t.pageY;
-                        if (i.right = i.left + r.outerWidth(), i.bottom = i.top + r.outerHeight(), u > i.left && u < i.right && f > i.top && f < i.bottom) return;
-                        this.popup.close()
-                    } else w(n(t.currentTarget));
-                    clearTimeout(this.timeout)
-                },
-                _positionCallout: function() {
-                    var t = this,
-                        u = t.options.position,
-                        f = t.dimensions,
-                        i = f.offset,
-                        r = t.popup,
-                        e = r.options.anchor,
-                        o = n(e).offset(),
-                        s = parseInt(t.arrow.css("border-top-width"), 10),
-                        h = n(r.element).offset(),
-                        c = p[r.flipped ? ut[u] : u],
-                        l = o[i] - h[i] + n(e)[f.size]() / 2 - s;
-                    t.arrow.removeClass("k-callout-n k-callout-s k-callout-w k-callout-e").addClass("k-callout-" + c).css(i, l)
-                },
-                target: function() {
-                    return this.popup ? this.popup.options.anchor : null
-                },
-                destroy: function() {
-                    var n = this.popup;
-                    n && (n.element.off(i), n.destroy());
-                    this.element.off(i);
-                    f.off("keydown" + i, this._documentKeyDownHandler);
-                    u.fn.destroy.call(this)
-                }
-            });
-        t.ui.plugin(ht)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "list",
-        name: "List",
-        category: "framework",
-        depends: ["data", "popup"],
-        hidden: !0
-    }),
-    function(n, t) {
-        function b(t, i) {
-            t.filters && (t.filters = n.grep(t.filters, function(n) {
-                return b(n, i), n.filters ? n.filters.length : n.field != i
-            }))
-        }
-        var i = window.kendo,
-            l = i.ui,
-            o = l.Widget,
-            f = i.keys,
-            u = i.support,
-            ft = i.htmlEncode,
-            et = i._activeElement,
-            s = "id",
-            a = "li",
-            r = "change",
-            v = "character",
-            k = "k-state-focused",
-            y = "k-state-hover",
-            d = "k-loading",
-            p = "open",
-            g = "close",
-            nt = "select",
-            w = "selected",
-            tt = "progress",
-            it = "requestEnd",
-            rt = "width",
-            ut = n.extend,
-            e = n.proxy,
-            h = u.browser,
-            ot = h.msie && h.version < 9,
-            st = /"/g,
-            ht = {
-                ComboBox: "DropDownList",
-                DropDownList: "ComboBox"
-            },
-            c = o.extend({
-                init: function(t, i) {
-                    var r = this,
-                        h = r.ns,
-                        f;
-                    o.fn.init.call(r, t, i);
-                    t = r.element;
-                    r._isSelect = t.is(nt);
-                    r._template();
-                    r.ul = n('<ul unselectable="on" class="k-list k-reset"/>').css({
-                        overflow: u.kineticScrollNeeded ? "" : "auto"
-                    }).on("mouseenter" + h, a, function() {
-                        n(this).addClass(y)
-                    }).on("mouseleave" + h, a, function() {
-                        n(this).removeClass(y)
-                    }).on("click" + h, a, e(r._click, r)).attr({
-                        tabIndex: -1,
-                        role: "listbox",
-                        "aria-hidden": !0
-                    });
-                    r.list = n("<div class='k-list-container'/>").append(r.ul).on("mousedown" + h, function(n) {
-                        n.preventDefault()
-                    });
-                    f = t.attr(s);
-                    f && (r.list.attr(s, f + "-list"), r.ul.attr(s, f + "_listbox"), r._optionID = f + "_option_selected");
-                    r._header();
-                    r._accessors();
-                    r._initValue()
-                },
-                options: {
-                    valuePrimitive: !1,
-                    headerTemplate: ""
-                },
-                setOptions: function(n) {
-                    o.fn.setOptions.call(this, n);
-                    n && n.enable !== t && (n.enabled = n.enable)
-                },
-                focus: function() {
-                    this._focused.focus()
-                },
-                readonly: function(n) {
-                    this._editable({
-                        readonly: n === t ? !0 : n,
-                        disable: !1
-                    })
-                },
-                enable: function(n) {
-                    this._editable({
-                        readonly: !1,
-                        disable: !(n = n === t ? !0 : n)
-                    })
-                },
-                _filterSource: function(n) {
-                    var i = this,
-                        u = i.options,
-                        r = i.dataSource,
-                        t = r.filter() || {};
-                    b(t, u.dataTextField);
-                    n && (t = t.filters || [], t.push(n));
-                    r.filter(t)
-                },
-                _header: function() {
-                    var t = this.options.headerTemplate,
-                        i;
-                    n.isFunction(t) && (t = t({}));
-                    t && (this.list.prepend(t), i = this.ul.prev(), this.header = i[0] ? i : null)
-                },
-                _initValue: function() {
-                    var n = this,
-                        t = n.options.value;
-                    t !== null ? n.element.val(t) : (t = n._accessor(), n.options.value = t);
-                    n._old = t
-                },
-                _ignoreCase: function() {
-                    var t = this,
-                        i = t.dataSource.reader.model,
-                        n;
-                    i && i.fields && (n = i.fields[t.options.dataTextField], n && n.type && n.type !== "string" && (t.options.ignoreCase = !1))
-                },
-                items: function() {
-                    return this.ul[0].children
-                },
-                current: function(n) {
-                    var i = this,
-                        r = i._optionID;
-                    if (n !== t) i._current && (i._current.removeClass(k).removeAttr("aria-selected").removeAttr(s), i._focused.removeAttr("aria-activedescendant")), n && (n.addClass(k), i._scroll(n), r && (n.attr("id", r), i._focused.attr("aria-activedescendant", r))), i._current = n;
-                    else return i._current
-                },
-                destroy: function() {
-                    var n = this,
-                        t = n.ns;
-                    o.fn.destroy.call(n);
-                    n._unbindDataSource();
-                    n.ul.off(t);
-                    n.list.off(t);
-                    n._touchScroller && n._touchScroller.destroy();
-                    n.popup.destroy();
-                    n._form && n._form.off("reset", n._resetHandler)
-                },
-                dataItem: function(n) {
-                    var i = this;
-                    return n === t && (n = i.selectedIndex), i._data()[n]
-                },
-                _accessors: function() {
-                    var n = this,
-                        r = n.element,
-                        t = n.options,
-                        u = i.getter,
-                        f = r.attr(i.attr("text-field")),
-                        e = r.attr(i.attr("value-field"));
-                    f && (t.dataTextField = f);
-                    e && (t.dataValueField = e);
-                    n._text = u(t.dataTextField);
-                    n._value = u(t.dataValueField)
-                },
-                _aria: function(n) {
-                    var i = this,
-                        r = i.options,
-                        u = i._focused;
-                    r.suggest !== t && u.attr("aria-autocomplete", r.suggest ? "both" : "list");
-                    n = n ? n + " " + i.ul[0].id : i.ul[0].id;
-                    u.attr("aria-owns", n);
-                    i.ul.attr("aria-live", !r.filter || r.filter === "none" ? "off" : "polite")
-                },
-                _blur: function() {
-                    var n = this;
-                    n._change();
-                    n.close()
-                },
-                _change: function() {
-                    var n = this,
-                        i = n.selectedIndex,
-                        e = n.options.value,
-                        u = n.value(),
-                        f;
-                    n._isSelect && !n._bound && e && (u = e);
-                    u !== n._old ? f = !0 : i !== t && i !== n._oldIndex && (f = !0);
-                    f && (n._old = u, n._oldIndex = i, n.trigger(r), n.element.trigger(r))
-                },
-                _click: function(t) {
-                    t.isDefaultPrevented() || this._accept(n(t.currentTarget))
-                },
-                _data: function() {
-                    return this.dataSource.view()
-                },
-                _enable: function() {
-                    var n = this,
-                        i = n.options,
-                        r = n.element.is("[disabled]");
-                    i.enable !== t && (i.enabled = i.enable);
-                    !i.enabled || r ? n.enable(!1) : n.readonly(n.element.is("[readonly]"))
-                },
-                _focus: function(n) {
-                    var t = this;
-                    if (t.popup.visible() && n && t.trigger(nt, {
-                            item: n
-                        })) {
-                        t.close();
-                        return
-                    }
-                    t._select(n);
-                    t._triggerCascade(!0);
-                    t._blur()
-                },
-                _index: function(n) {
-                    for (var i = this, u = i._data(), t = 0, r = u.length; t < r; t++)
-                        if (i._dataValue(u[t]) == n) return t;
-                    return -1
-                },
-                _dataValue: function(n) {
-                    var i = this._value(n);
-                    return i === t && (i = this._text(n)), i
-                },
-                _height: function(n) {
-                    if (n) {
-                        var t = this,
-                            r = t.list,
-                            e = t.popup.visible(),
-                            i = t.options.height,
-                            f = t.header,
-                            u;
-                        u = r.add(r.parent(".k-animation-container")).show();
-                        i = t.ul[0].scrollHeight > i ? i : "auto";
-                        u.height(i);
-                        f && t.ul.height(i == "auto" ? i : r.height() - f.height());
-                        e || u.hide()
-                    }
-                },
-                _adjustListWidth: function() {
-                    var t = this.list,
-                        i = t[0].style.width,
-                        u = this.wrapper,
-                        n, r;
-                    if (t.data(rt) || !i) return n = window.getComputedStyle ? window.getComputedStyle(u[0], null) : 0, r = n ? parseFloat(n.width) : u.outerWidth(), n && (h.mozilla || h.msie) && (r += parseFloat(n.paddingLeft) + parseFloat(n.paddingRight) + parseFloat(n.borderLeftWidth) + parseFloat(n.borderRightWidth)), i = t.css("box-sizing") !== "border-box" ? r - (t.outerWidth() - t.width()) : r, t.css({
-                        fontFamily: u.css("font-family"),
-                        width: i
-                    }).data(rt, i), !0
-                },
-                _popup: function() {
-                    var n = this,
-                        e = n.list,
-                        t = n._focused,
-                        r = n.options,
-                        f = n.wrapper;
-                    n.popup = new l.Popup(e, ut({}, r.popup, {
-                        anchor: f,
-                        open: function(i) {
-                            n._adjustListWidth();
-                            n.trigger(p) ? i.preventDefault() : (t.attr("aria-expanded", !0), n.ul.attr("aria-hidden", !1))
-                        },
-                        close: function(i) {
-                            n.trigger(g) ? i.preventDefault() : (t.attr("aria-expanded", !1), n.ul.attr("aria-hidden", !0))
-                        },
-                        animation: r.animation,
-                        isRtl: u.isRtl(f)
-                    }));
-                    n.popup.one(p, function() {
-                        n._height(n._data().length)
-                    });
-                    n._touchScroller = i.touchScroller(n.popup.element)
-                },
-                _makeUnselectable: function() {
-                    ot && this.list.find("*").attr("unselectable", "on")
-                },
-                _toggleHover: function(t) {
-                    n(t.currentTarget).toggleClass(y, t.type === "mouseenter")
-                },
-                _toggle: function(n) {
-                    var i = this,
-                        r = u.touch && u.MSPointers && u.pointers;
-                    n = n !== t ? n : !i.popup.visible();
-                    r || i._focused[0] === et() || i._focused.focus();
-                    i[n ? p : g]()
-                },
-                _scroll: function(n) {
-                    if (n) {
-                        n[0] && (n = n[0]);
-                        var r = this.ul[0],
-                            t = n.offsetTop,
-                            o = n.offsetHeight,
-                            u = r.scrollTop,
-                            s = r.clientHeight,
-                            h = t + o,
-                            f = this._touchScroller,
-                            i, e;
-                        f ? (i = f.dimensions.y, i.enabled && t > i.size && (t = t - i.size + o + 4, f.scrollTo(0, -t))) : (e = this.header ? this.header.outerHeight() : 0, r.scrollTop = u > t ? t - e : h > u + s ? h - s - e : u)
-                    }
-                },
-                _template: function() {
-                    var t = this,
-                        n = t.options,
-                        r = n.template,
-                        u = n.dataSource;
-                    t._isSelect && t.element[0].length && (u || (n.dataTextField = n.dataTextField || "text", n.dataValueField = n.dataValueField || "value"));
-                    r ? (r = i.template(r), t.template = function(n) {
-                        return '<li tabindex="-1" role="option" unselectable="on" class="k-item">' + r(n) + "<\/li>"
-                    }) : t.template = i.template('<li tabindex="-1" role="option" unselectable="on" class="k-item">${' + i.expr(n.dataTextField, "data") + "}<\/li>", {
-                        useWithBlock: !1
-                    })
-                },
-                _triggerCascade: function(n) {
-                    var t = this,
-                        i = t.value();
-                    (!t._bound && i || t._old !== i) && t.trigger("cascade", {
-                        userTriggered: n
-                    })
-                },
-                _unbindDataSource: function() {
-                    var n = this;
-                    n.dataSource.unbind(r, n._refreshHandler).unbind(tt, n._progressHandler).unbind(it, n._requestEndHandler).unbind("error", n._errorHandler)
-                }
-            });
-        ut(c, {
-            caret: function(n) {
-                var t = n.ownerDocument.selection;
-                return t ? Math.abs(t.createRange().moveStart(v, -n.value.length)) : n.selectionStart
-            },
-            selectText: function(n, t, i) {
-                try {
-                    if (n.createTextRange) {
-                        n.focus();
-                        var r = n.createTextRange();
-                        r.collapse(!0);
-                        r.moveStart(v, t);
-                        r.moveEnd(v, i - t);
-                        r.select()
-                    } else n.setSelectionRange(t, i)
-                } catch (u) {}
-            },
-            inArray: function(n, t) {
-                var i, r, u = t.children;
-                if (!n || n.parentNode !== t) return -1;
-                for (i = 0, r = u.length; i < r; i++)
-                    if (n === u[i]) return i;
-                return -1
-            }
-        });
-        i.ui.List = c;
-        l.Select = c.extend({
-            init: function(n, t) {
-                c.fn.init.call(this, n, t);
-                this._initial = this.element.val()
-            },
-            setDataSource: function(n) {
-                this.options.dataSource = n;
-                this._dataSource();
-                this._bound = !1;
-                this.options.autoBind && this.dataSource.fetch()
-            },
-            close: function() {
-                this.popup.close()
-            },
-            select: function(n) {
-                var i = this;
-                if (n === t) return i.selectedIndex;
-                i._select(n);
-                i._triggerCascade();
-                i._old = i._accessor();
-                i._oldIndex = i.selectedIndex
-            },
-            _accessor: function(n, i) {
-                var r = this.element[0],
-                    e = this._isSelect,
-                    f = r.selectedIndex,
-                    u;
-                if (n === t) return e ? f > -1 && (u = r.options[f], u && (n = u.value)) : n = r.value, n;
-                e ? (f > -1 && r.options[f].removeAttribute(w), r.selectedIndex = i, u = r.options[i], u && u.setAttribute(w, w)) : r.value = n
-            },
-            _hideBusy: function() {
-                var n = this;
-                clearTimeout(n._busy);
-                n._arrow.removeClass(d);
-                n._focused.attr("aria-busy", !1);
-                n._busy = null
-            },
-            _showBusy: function() {
-                var n = this;
-                (n._request = !0, n._busy) || (n._busy = setTimeout(function() {
-                    n._focused.attr("aria-busy", !0);
-                    n._arrow.addClass(d)
-                }, 100))
-            },
-            _requestEnd: function() {
-                this._request = !1
-            },
-            _dataSource: function() {
-                var t = this,
-                    s = t.element,
-                    f = t.options,
-                    u = f.dataSource || {},
-                    o;
-                u = n.isArray(u) ? {
-                    data: u
-                } : u;
-                t._isSelect && (o = s[0].selectedIndex, o > -1 && (f.index = o), u.select = s, u.fields = [{
-                    field: f.dataTextField
-                }, {
-                    field: f.dataValueField
-                }]);
-                t.dataSource && t._refreshHandler ? t._unbindDataSource() : (t._refreshHandler = e(t.refresh, t), t._progressHandler = e(t._showBusy, t), t._requestEndHandler = e(t._requestEnd, t), t._errorHandler = e(t._hideBusy, t));
-                t.dataSource = i.data.DataSource.create(u).bind(r, t._refreshHandler).bind(tt, t._progressHandler).bind(it, t._requestEndHandler).bind("error", t._errorHandler)
-            },
-            _get: function(t) {
-                var r = this,
-                    u = r._data(),
-                    i, f;
-                if (typeof t == "function")
-                    for (i = 0, f = u.length; i < f; i++)
-                        if (t(u[i])) {
-                            t = i;
-                            break
-                        }
-                if (typeof t == "number") {
-                    if (t < 0) return n();
-                    t = n(r.ul[0].children[t])
-                }
-                return t && t.nodeType && (t = n(t)), t
-            },
-            _move: function(n) {
-                var t = this,
-                    e = n.keyCode,
-                    o = t.ul[0],
-                    c = t.popup.visible() ? "_select" : "_accept",
-                    i = t._current,
-                    h = e === f.DOWN,
-                    u, s;
-                if (e === f.UP || h) {
-                    if (n.altKey) t.toggle(h);
-                    else {
-                        if (u = o.firstChild, !u && !t._accessor() && t._state !== "filter") {
-                            if (!t._fetch) {
-                                t.dataSource.one(r, function() {
-                                    t._move(n);
-                                    t._fetch = !1
-                                });
-                                t._fetch = !0;
-                                t._filterSource()
-                            }
-                            return n.preventDefault(), !0
-                        }
-                        h ? (i && (t.selectedIndex !== -1 || t.value() || i[0] !== u) ? (i = i[0].nextSibling, i || u !== o.lastChild || (i = u)) : i = u, t[c](i)) : (i = i ? i[0].previousSibling : o.lastChild, i || u !== o.lastChild || (i = u), t[c](i))
-                    }
-                    n.preventDefault();
-                    s = !0
-                } else e === f.ENTER || e === f.TAB ? (t.popup.visible() && n.preventDefault(), (t._typing || !t.popup.visible() && t.selectedIndex === -1) && (i = null), t._accept(i), s = !0) : e === f.ESC && (t.popup.visible() && n.preventDefault(), t.close(), s = !0);
-                return s
-            },
-            _selectItem: function() {
-                var n = this,
-                    i = n.options,
-                    u, r;
-                u = n._isSelect && !n._initial && !i.value && i.index && !n._bound;
-                u || (r = n._selectedValue || i.value || n._accessor());
-                r ? n.value(r) : n._bound === t && n.select(i.index)
-            },
-            _fetchItems: function(n) {
-                var t = this,
-                    i = t.ul[0].firstChild;
-                if (t._request) return !0;
-                if (!t._fetch && !i) {
-                    if (t.options.cascadeFrom) return !i;
-                    t.dataSource.one(r, function() {
-                        t.value(n);
-                        t._fetch = !1
-                    });
-                    return t._fetch = !0, t.dataSource.fetch(), !0
-                }
-            },
-            _options: function(n, i) {
-                var e = this,
-                    c = e.element,
-                    l = n.length,
-                    o = "",
-                    u, s, h, r, f = 0;
-                for (i && (f = 1, o = i); f < l; f++) u = "<option", s = n[f], h = e._text(s), r = e._value(s), r !== t && (r += "", r.indexOf('"') !== -1 && (r = r.replace(st, "&quot;")), u += ' value="' + r + '"'), u += ">", h !== t && (u += ft(h)), u += "<\/option>", o += u;
-                c.html(o)
-            },
-            _reset: function() {
-                var t = this,
-                    i = t.element,
-                    r = i.attr("form"),
-                    u = r ? n("#" + r) : i.closest("form");
-                u[0] && (t._resetHandler = function() {
-                    setTimeout(function() {
-                        t.value(t._initial)
-                    })
-                }, t._form = u.on("reset", t._resetHandler))
-            },
-            _cascade: function() {
-                var t = this,
-                    u = t.options,
-                    s = u.cascadeFrom,
-                    i, f, e, o, h;
-                if (s) {
-                    if (t._selectedValue = u.value || t._accessor(), f = n("#" + s), i = f.data("kendo" + u.name), i || (i = f.data("kendo" + ht[u.name])), !i) return;
-                    u.autoBind = !1;
-                    o = u.cascadeFromField || i.options.dataValueField;
-                    h = function() {
-                        var n = t._selectedValue || t.value();
-                        t._userTriggered ? t._clearSelection(i, !0) : n ? (t.value(n), t.dataSource.view()[0] && t.selectedIndex !== -1 || t._clearSelection(i, !0)) : t.select(u.index);
-                        t.enable();
-                        t._triggerCascade(t._userTriggered);
-                        t._userTriggered = !1
-                    };
-                    e = function() {
-                        var e = i.dataItem(),
-                            n = e ? i._value(e) : null,
-                            u, f;
-                        n || n === 0 ? (u = t.dataSource.filter() || {}, b(u, o), f = u.filters || [], f.push({
-                            field: o,
-                            operator: "eq",
-                            value: n
-                        }), t.dataSource.one(r, h).filter(f)) : (t.enable(!1), t._clearSelection(i), t._triggerCascade(t._userTriggered), t._userTriggered = !1)
-                    };
-                    i.bind("cascade", function(n) {
-                        t._userTriggered = n.userTriggered;
-                        e()
-                    });
-                    i._bound ? e() : i.value() || t.enable(!1)
-                }
-            }
-        })
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "calendar",
-        name: "Calendar",
-        category: "web",
-        description: "The Calendar widget renders a graphical calendar that supports navigation and selection.",
-        depends: ["core"]
-    }),
-    function(n, t) {
-        function li(n, t, i, r) {
-            var u = n.getFullYear(),
-                e = t.getFullYear(),
-                o = i.getFullYear(),
-                f;
-            return u = u - u % r, f = u + (r - 1), u < e && (u = e), f > o && (f = o), u + "-" + f
-        }
-
-        function d(n) {
-            for (var t = 0, i, f = n.min, e = n.max, r = n.start, o = n.setter, s = n.build, h = n.cells || 12, c = n.perRow || 4, l = n.content || bi, a = n.empty || ki, u = n.html || '<table tabindex="0" role="grid" class="k-content k-meta-view" cellspacing="0"><tbody><tr role="row">'; t < h; t++) t > 0 && t % c == 0 && (u += '<\/tr><tr role="row">'), i = s(r, t), u += nt(r, f, e) ? l(i) : a(i), o(r, 1);
-            return u + "<\/tr><\/tbody><\/table>"
-        }
-
-        function st(n, t, i) {
-            var f = n.getFullYear(),
-                r = t.getFullYear(),
-                e = r,
-                u = 0;
-            return i && (r = r - r % i, e = r - r % i + i - 1), f > e ? u = 1 : f < r && (u = -1), u
-        }
-
-        function g() {
-            var n = new i;
-            return new i(n.getFullYear(), n.getMonth(), n.getDate())
-        }
-
-        function v(n, t, r) {
-            var u = g();
-            return n && (u = new i(+n)), t > u ? u = new i(+t) : r < u && (u = new i(+r)), u
-        }
-
-        function nt(n, t, i) {
-            return +n >= +t && +n <= +i
-        }
-
-        function ai(n, t) {
-            return n.slice(t).concat(n.slice(0, t))
-        }
-
-        function vi(n, t, r) {
-            t = t instanceof i ? t.getFullYear() : n.getFullYear() + r * t;
-            n.setFullYear(t)
-        }
-
-        function yi(t) {
-            n(this).toggleClass(nr, tr.indexOf(t.type) > -1 || t.type == ri)
-        }
-
-        function ur(n) {
-            n.preventDefault()
-        }
-
-        function ht(n) {
-            return at(n).calendars.standard
-        }
-
-        function ct(n) {
-            var i = o[n.start],
-                r = o[n.depth],
-                u = at(n.culture);
-            n.format = wi(n.format || u.calendars.standard.patterns.d);
-            isNaN(i) && (i = 0, n.start = a);
-            (r === t || r > i) && (n.depth = a);
-            n.dates || (n.dates = [])
-        }
-
-        function pi(n) {
-            di && n.find("*").attr("unselectable", "on")
-        }
-
-        function fr(n, t) {
-            for (var i = 0, r = t.length; i < r; i++)
-                if (n === +t[i]) return !0;
-            return !1
-        }
-
-        function er(n, t) {
-            return n ? n.getFullYear() === t.getFullYear() && n.getMonth() === t.getMonth() && n.getDate() === t.getDate() : !1
-        }
-
-        function or(n, t) {
-            return n ? n.getFullYear() === t.getFullYear() && n.getMonth() === t.getMonth() : !1
-        }
-        var r = window.kendo,
-            tt = r.support,
-            lt = r.ui,
-            y = lt.Widget,
-            u = r.keys,
-            it = r.parseDate,
-            p = r.date.adjustDST,
-            wi = r._extractFormat,
-            l = r.template,
-            at = r.getCulture,
-            vt = r.support.transitions,
-            yt = vt ? vt.css + "transform-origin" : "",
-            bi = l('<td#=data.cssClass# role="gridcell"><a tabindex="-1" class="k-link" href="\\#" data-#=data.ns#value="#=data.dateString#">#=data.value#<\/a><\/td>', {
-                useWithBlock: !1
-            }),
-            ki = l('<td role="gridcell">&nbsp;<\/td>', {
-                useWithBlock: !1
-            }),
-            pt = r.support.browser,
-            di = pt.msie && pt.version < 9,
-            f = ".kendoCalendar",
-            s = "click" + f,
-            gi = "keydown" + f,
-            rt = "id",
-            wt = "min",
-            bt = "left",
-            ut = "slideIn",
-            a = "month",
-            kt = "century",
-            ft = "change",
-            dt = "navigate",
-            et = "value",
-            nr = "k-state-hover",
-            h = "k-state-disabled",
-            c = "k-state-focused",
-            w = "k-other-month",
-            gt = ' class="' + w + '"',
-            ni = "k-nav-today",
-            ti = "td:has(.k-link)",
-            ii = "blur" + f,
-            ri = "focus",
-            ui = ri + f,
-            tr = tt.touch ? "touchstart" : "mouseenter",
-            fi = tt.touch ? "touchstart" + f : "mouseenter" + f,
-            ei = tt.touch ? "touchend" + f + " touchmove" + f : "mouseleave" + f,
-            ir = 6e4,
-            oi = 864e5,
-            b = "_prevArrow",
-            k = "_nextArrow",
-            ot = "aria-disabled",
-            si = "aria-selected",
-            hi = n.proxy,
-            ci = n.extend,
-            i = Date,
-            o = {
-                month: 0,
-                year: 1,
-                decade: 2,
-                century: 3
-            },
-            rr = y.extend({
-                init: function(t, u) {
-                    var e = this,
-                        h, l;
-                    y.fn.init.call(e, t, u);
-                    t = e.wrapper = e.element;
-                    u = e.options;
-                    u.url = window.unescape(u.url);
-                    e._templates();
-                    e._header();
-                    e._footer(e.footer);
-                    l = t.addClass("k-widget k-calendar").on(fi + " " + ei, ti, yi).on(gi, "table.k-content", hi(e._move, e)).on(s, ti, function(t) {
-                        var i = t.currentTarget.firstChild;
-                        i.href.indexOf("#") != -1 && t.preventDefault();
-                        e._click(n(i))
-                    }).on("mouseup" + f, function() {
-                        e._focusView(e.options.focusOnNav !== !1)
-                    }).attr(rt);
-                    l && (e._cellID = l + "_cell_selected");
-                    ct(u);
-                    h = it(u.value, u.format, u.culture);
-                    e._index = o[u.start];
-                    e._current = new i(+v(h, u.min, u.max));
-                    e._addClassProxy = function() {
-                        e._active = !0;
-                        e._cell.addClass(c)
-                    };
-                    e._removeClassProxy = function() {
-                        e._active = !1;
-                        e._cell.removeClass(c)
-                    };
-                    e.value(h);
-                    r.notify(e)
-                },
-                options: {
-                    name: "Calendar",
-                    value: null,
-                    min: new i(1900, 0, 1),
-                    max: new i(2099, 11, 31),
-                    dates: [],
-                    url: "",
-                    culture: "",
-                    footer: "",
-                    format: "",
-                    month: {},
-                    start: a,
-                    depth: a,
-                    animation: {
-                        horizontal: {
-                            effects: ut,
-                            reverse: !0,
-                            duration: 500,
-                            divisor: 2
-                        },
-                        vertical: {
-                            effects: "zoomIn",
-                            duration: 400
-                        }
-                    }
-                },
-                events: [ft, dt],
-                setOptions: function(n) {
-                    var t = this;
-                    ct(n);
-                    y.fn.setOptions.call(t, n);
-                    t._templates();
-                    t._footer(t.footer);
-                    t._index = o[t.options.start];
-                    t.navigate()
-                },
-                destroy: function() {
-                    var n = this,
-                        t = n._today;
-                    n.element.off(f);
-                    n._title.off(f);
-                    n[b].off(f);
-                    n[k].off(f);
-                    r.destroy(n._table);
-                    t && r.destroy(t.off(f));
-                    y.fn.destroy.call(n)
-                },
-                current: function() {
-                    return this._current
-                },
-                view: function() {
-                    return this._view
-                },
-                focus: function(n) {
-                    n = n || this._table;
-                    this._bindTable(n);
-                    n.focus()
-                },
-                min: function(n) {
-                    return this._option(wt, n)
-                },
-                max: function(n) {
-                    return this._option("max", n)
-                },
-                navigateToPast: function() {
-                    this._navigate(b, -1)
-                },
-                navigateToFuture: function() {
-                    this._navigate(k, 1)
-                },
-                navigateUp: function() {
-                    var n = this,
-                        t = n._index;
-                    n._title.hasClass(h) || n.navigate(n._current, ++t)
-                },
-                navigateDown: function(n) {
-                    var t = this,
-                        i = t._index,
-                        r = t.options.depth;
-                    if (n) {
-                        if (i === o[r]) {
-                            +t._value != +n && (t.value(n), t.trigger(ft));
-                            return
-                        }
-                        t.navigate(n, --i)
-                    }
-                },
-                navigate: function(r, u) {
-                    u = isNaN(u) ? o[u] : u;
-                    var f = this,
-                        l = f.options,
-                        tt = l.culture,
-                        p = l.min,
-                        w = l.max,
-                        it = f._title,
-                        y = f._table,
-                        d = f._oldTable,
-                        rt = f._value,
-                        ut = f._current,
-                        ft = r && +r > +ut,
-                        et = u !== t && u !== f._index,
-                        g, a, nt, s;
-                    r || (r = ut);
-                    f._current = r = new i(+v(r, p, w));
-                    u === t ? u = f._index : f._index = u;
-                    f._view = a = e.views[u];
-                    nt = a.compare;
-                    s = u === o[kt];
-                    it.toggleClass(h, s).attr(ot, s);
-                    s = nt(r, p) < 1;
-                    f[b].toggleClass(h, s).attr(ot, s);
-                    s = nt(r, w) > -1;
-                    f[k].toggleClass(h, s).attr(ot, s);
-                    y && d && d.data("animating") && (d.kendoStop(!0, !0), y.kendoStop(!0, !0));
-                    f._oldTable = y;
-                    (!y || f._changeView) && (it.html(a.title(r, p, w, tt)), f._table = g = n(a.content(ci({
-                        min: p,
-                        max: w,
-                        date: r,
-                        url: l.url,
-                        dates: l.dates,
-                        format: l.format,
-                        culture: tt
-                    }, f[a.name]))), pi(g), f._animate({
-                        from: y,
-                        to: g,
-                        vertical: et,
-                        future: ft
-                    }), f._focus(r), f.trigger(dt));
-                    u === o[l.depth] && rt && f._class("k-state-selected", a.toDateString(rt));
-                    f._class(c, a.toDateString(r));
-                    !y && f._cell && f._cell.removeClass(c);
-                    f._changeView = !0
-                },
-                value: function(n) {
-                    var r = this,
-                        f = r._view,
-                        u = r.options,
-                        e = r._view,
-                        o = u.min,
-                        s = u.max;
-                    if (n === t) return r._value;
-                    n = it(n, u.format, u.culture);
-                    n !== null && (n = new i(+n), nt(n, o, s) || (n = null));
-                    r._value = n;
-                    e && n === null && r._cell ? r._cell.removeClass("k-state-selected") : (r._changeView = !n || f && f.compare(n, r._current) !== 0, r.navigate(n))
-                },
-                _move: function(t) {
-                    var f = this,
-                        y = f.options,
-                        e = t.keyCode,
-                        p = f._view,
-                        w = f._index,
-                        s = new i(+f._current),
-                        h = r.support.isRtl(f.wrapper),
-                        c, o, l, a;
-                    return t.target === f._table[0] && (f._active = !0), t.ctrlKey ? e == u.RIGHT && !h || e == u.LEFT && h ? (f.navigateToFuture(), o = !0) : e == u.LEFT && !h || e == u.RIGHT && h ? (f.navigateToPast(), o = !0) : e == u.UP ? (f.navigateUp(), o = !0) : e == u.DOWN && (f._click(n(f._cell[0].firstChild)), o = !0) : (e == u.RIGHT && !h || e == u.LEFT && h ? (c = 1, o = !0) : e == u.LEFT && !h || e == u.RIGHT && h ? (c = -1, o = !0) : e == u.UP ? (c = w === 0 ? -7 : -4, o = !0) : e == u.DOWN ? (c = w === 0 ? 7 : 4, o = !0) : e == u.ENTER ? (f._click(n(f._cell[0].firstChild)), o = !0) : e == u.HOME || e == u.END ? (l = e == u.HOME ? "first" : "last", a = p[l](s), s = new i(a.getFullYear(), a.getMonth(), a.getDate(), s.getHours(), s.getMinutes(), s.getSeconds(), s.getMilliseconds()), o = !0) : e == u.PAGEUP ? (o = !0, f.navigateToPast()) : e == u.PAGEDOWN && (o = !0, f.navigateToFuture()), (c || l) && (l || p.setDate(s, c), f._focus(v(s, y.min, y.max)))), o && t.preventDefault(), f._current
-                },
-                _animate: function(n) {
-                    var t = this,
-                        i = n.from,
-                        r = n.to,
-                        u = t._active;
-                    i ? i.parent().data("animating") ? (i.parent().kendoStop(!0, !0).remove(), i.remove(), r.insertAfter(t.element[0].firstChild), t._focusView(u)) : i.is(":visible") && t.options.animation !== !1 ? t[n.vertical ? "_vertical" : "_horizontal"](i, r, n.future) : (r.insertAfter(i), i.remove(), t._focusView(u)) : (r.insertAfter(t.element[0].firstChild), t._bindTable(r))
-                },
-                _horizontal: function(n, i, r) {
-                    var u = this,
-                        o = u._active,
-                        f = u.options.animation.horizontal,
-                        s = f.effects,
-                        e = n.outerWidth();
-                    s && s.indexOf(ut) != -1 && (n.add(i).css({
-                        width: e
-                    }), n.wrap("<div/>"), u._focusView(o, n), n.parent().css({
-                        position: "relative",
-                        width: e * 2,
-                        float: bt,
-                        "margin-left": r ? 0 : -e
-                    }), i[r ? "insertAfter" : "insertBefore"](n), ci(f, {
-                        effects: ut + ":" + (r ? "right" : bt),
-                        complete: function() {
-                            n.remove();
-                            i.unwrap();
-                            u._focusView(o);
-                            u._oldTable = t
-                        }
-                    }), n.parent().kendoStop(!0, !0).kendoAnimate(f))
-                },
-                _vertical: function(n, i) {
-                    var r = this,
-                        e = r.options.animation.vertical,
-                        o = e.effects,
-                        s = r._active,
-                        f, u;
-                    o && o.indexOf("zoom") != -1 && (i.css({
-                        position: "absolute",
-                        top: n.prev().outerHeight(),
-                        left: 0
-                    }).insertBefore(n), yt && (f = r._cellByDate(r._view.toDateString(r._current)), u = f.position(), u = u.left + parseInt(f.width() / 2, 10) + "px " + (u.top + parseInt(f.height() / 2, 10) + "px"), i.css(yt, u)), n.kendoStop(!0, !0).kendoAnimate({
-                        effects: "fadeOut",
-                        duration: 600,
-                        complete: function() {
-                            n.remove();
-                            i.css({
-                                position: "static",
-                                top: 0,
-                                left: 0
-                            });
-                            r._focusView(s);
-                            r._oldTable = t
-                        }
-                    }), i.kendoStop(!0, !0).kendoAnimate(e))
-                },
-                _cellByDate: function(t) {
-                    return this._table.find("td:not(." + w + ")").filter(function() {
-                        return n(this.firstChild).attr(r.attr(et)) === t
-                    })
-                },
-                _class: function(t, i) {
-                    var u = this,
-                        e = u._cellID,
-                        f = u._cell;
-                    f && f.removeAttr(si).removeAttr("aria-label").removeAttr(rt);
-                    f = u._table.find("td:not(." + w + ")").removeClass(t).filter(function() {
-                        return n(this.firstChild).attr(r.attr(et)) === i
-                    }).attr(si, !0);
-                    t !== c || u._active || u.options.focusOnNav === !1 || (t = "");
-                    f.addClass(t);
-                    f[0] && (u._cell = f);
-                    e && (f.attr(rt, e), u._table.removeAttr("aria-activedescendant").attr("aria-activedescendant", e))
-                },
-                _bindTable: function(n) {
-                    n.on(ui, this._addClassProxy).on(ii, this._removeClassProxy)
-                },
-                _click: function(n) {
-                    var u = this,
-                        f = u.options,
-                        e = new Date(+u._current),
-                        t = n.attr(r.attr(et)).split("/");
-                    t = new i(t[0], t[1], t[2]);
-                    p(t, 0);
-                    u._view.setDate(e, t);
-                    u.navigateDown(v(e, f.min, f.max))
-                },
-                _focus: function(n) {
-                    var t = this,
-                        i = t._view;
-                    i.compare(n, t._current) !== 0 ? t.navigate(n) : (t._current = n, t._class(c, i.toDateString(n)))
-                },
-                _focusView: function(n, t) {
-                    n && this.focus(t)
-                },
-                _footer: function(t) {
-                    var i = this,
-                        f = g(),
-                        e = i.element,
-                        u = e.find(".k-footer");
-                    if (!t) {
-                        i._toggle(!1);
-                        u.hide();
-                        return
-                    }
-                    u[0] || (u = n('<div class="k-footer"><a href="#" class="k-link k-nav-today"><\/a><\/div>').appendTo(e));
-                    i._today = u.show().find(".k-link").html(t(f)).attr("title", r.toString(f, "D", i.options.culture));
-                    i._toggle()
-                },
-                _header: function() {
-                    var n = this,
-                        i = n.element,
-                        t;
-                    i.find(".k-header")[0] || i.html('<div class="k-header"><a href="#" role="button" class="k-link k-nav-prev"><span class="k-icon k-i-arrow-w"><\/span><\/a><a href="#" role="button" aria-live="assertive" aria-atomic="true" class="k-link k-nav-fast"><\/a><a href="#" role="button" class="k-link k-nav-next"><span class="k-icon k-i-arrow-e"><\/span><\/a><\/div>');
-                    t = i.find(".k-link").on(fi + " " + ei + " " + ui + " " + ii, yi).click(!1);
-                    n._title = t.eq(1).on(s, function() {
-                        n._focusView(n.options.focusOnNav !== !1);
-                        n.navigateUp()
-                    });
-                    n[b] = t.eq(0).on(s, function() {
-                        n._focusView(n.options.focusOnNav !== !1);
-                        n.navigateToPast()
-                    });
-                    n[k] = t.eq(2).on(s, function() {
-                        n._focusView(n.options.focusOnNav !== !1);
-                        n.navigateToFuture()
-                    })
-                },
-                _navigate: function(n, t) {
-                    var r = this,
-                        f = r._index + 1,
-                        u = new i(+r._current);
-                    n = r[n];
-                    n.hasClass(h) || (f > 3 ? u.setFullYear(u.getFullYear() + 100 * t) : e.views[f].setDate(u, t), r.navigate(u))
-                },
-                _option: function(n, r) {
-                    var u = this,
-                        f = u.options,
-                        e = u._value || u._current,
-                        o;
-                    if (r === t) return f[n];
-                    (r = it(r, f.format, f.culture), r) && (f[n] = new i(+r), o = n === wt ? r > e : e > r, (o || or(e, r)) && (o && (u._value = null), u._changeView = !0), u._changeView || (u._changeView = !!(f.month.content || f.month.empty)), u.navigate(u._value), u._toggle())
-                },
-                _toggle: function(n) {
-                    var i = this,
-                        u = i.options,
-                        r = i._today;
-                    if (n === t && (n = nt(g(), u.min, u.max)), r)
-                        if (r.off(s), n) r.addClass(ni).removeClass(h).on(s, hi(i._todayClick, i));
-                        else r.removeClass(ni).addClass(h).on(s, ur)
-                },
-                _todayClick: function(n) {
-                    var t = this,
-                        r = o[t.options.depth],
-                        i = g();
-                    n.preventDefault();
-                    t._view.compare(t._current, i) === 0 && t._index == r && (t._changeView = !1);
-                    t._value = i;
-                    t.navigate(i, r);
-                    t.trigger(ft)
-                },
-                _templates: function() {
-                    var n = this,
-                        t = n.options,
-                        i = t.footer,
-                        u = t.month,
-                        f = u.content,
-                        e = u.empty;
-                    n.month = {
-                        content: l('<td#=data.cssClass# role="gridcell"><a tabindex="-1" class="k-link#=data.linkClass#" href="#=data.url#" ' + r.attr("value") + '="#=data.dateString#" title="#=data.title#">' + (f || "#=data.value#") + "<\/a><\/td>", {
-                            useWithBlock: !!f
-                        }),
-                        empty: l('<td role="gridcell">' + (e || "&nbsp;") + "<\/td>", {
-                            useWithBlock: !!e
-                        })
-                    };
-                    n.footer = i !== !1 ? l(i || '#= kendo.toString(data,"D","' + t.culture + '") #', {
-                        useWithBlock: !1
-                    }) : null
-                }
-            }),
-            e;
-        lt.plugin(rr);
-        e = {
-            firstDayOfMonth: function(n) {
-                return new i(n.getFullYear(), n.getMonth(), 1)
-            },
-            firstVisibleDay: function(n, t) {
-                t = t || r.culture().calendar;
-                for (var f = t.firstDay, u = new i(n.getFullYear(), n.getMonth(), 0, n.getHours(), n.getMinutes(), n.getSeconds(), n.getMilliseconds()); u.getDay() != f;) e.setTime(u, -1 * oi);
-                return u
-            },
-            setTime: function(n, t) {
-                var u = n.getTimezoneOffset(),
-                    r = new i(n.getTime() + t),
-                    f = r.getTimezoneOffset() - u;
-                n.setTime(r.getTime() + f * ir)
-            },
-            views: [{
-                name: a,
-                title: function(n, t, i, r) {
-                    return ht(r).months.names[n.getMonth()] + " " + n.getFullYear()
-                },
-                content: function(n) {
-                    for (var u = this, f = 0, o = n.min, s = n.max, h = n.date, c = n.dates, nt = n.format, l = n.culture, y = n.url, tt = y && c[0], a = ht(l), b = a.firstDay, k = a.days, it = ai(k.names, b), rt = ai(k.namesShort, b), v = e.firstVisibleDay(h, a), ut = u.first(h), ft = u.last(h), et = u.toDateString, t = new i, g = '<table tabindex="0" role="grid" class="k-content" cellspacing="0"><thead><tr role="row">'; f < 7; f++) g += '<th scope="col" title="' + it[f] + '">' + rt[f] + "<\/th>";
-                    return t = new i(t.getFullYear(), t.getMonth(), t.getDate()), p(t, 0), t = +t, d({
-                        cells: 42,
-                        perRow: 7,
-                        html: g += '<\/tr><\/thead><tbody><tr role="row">',
-                        start: new i(v.getFullYear(), v.getMonth(), v.getDate()),
-                        min: new i(o.getFullYear(), o.getMonth(), o.getDate()),
-                        max: new i(s.getFullYear(), s.getMonth(), s.getDate()),
-                        content: n.content,
-                        empty: n.empty,
-                        setter: u.setDate,
-                        build: function(n) {
-                            var i = [],
-                                u = n.getDay(),
-                                f = "",
-                                e = "#";
-                            return (n < ut || n > ft) && i.push(w), +n === t && i.push("k-today"), (u === 0 || u === 6) && i.push("k-weekend"), tt && fr(+n, c) && (e = y.replace("{0}", r.toString(n, nt, l)), f = " k-action-link"), {
-                                date: n,
-                                dates: c,
-                                ns: r.ns,
-                                title: r.toString(n, "D", l),
-                                value: n.getDate(),
-                                dateString: et(n),
-                                cssClass: i[0] ? ' class="' + i.join(" ") + '"' : "",
-                                linkClass: f,
-                                url: e
-                            }
-                        }
-                    })
-                },
-                first: function(n) {
-                    return e.firstDayOfMonth(n)
-                },
-                last: function(n) {
-                    var t = new i(n.getFullYear(), n.getMonth() + 1, 0),
-                        r = e.firstDayOfMonth(n),
-                        u = Math.abs(t.getTimezoneOffset() - r.getTimezoneOffset());
-                    return u && t.setHours(r.getHours() + u / 60), t
-                },
-                compare: function(n, t) {
-                    var i = n.getMonth(),
-                        r = n.getFullYear(),
-                        u = t.getMonth(),
-                        f = t.getFullYear();
-                    return r > f ? 1 : r < f ? -1 : i == u ? 0 : i > u ? 1 : -1
-                },
-                setDate: function(n, t) {
-                    var r = n.getHours();
-                    t instanceof i ? n.setFullYear(t.getFullYear(), t.getMonth(), t.getDate()) : e.setTime(n, t * oi);
-                    p(n, r)
-                },
-                toDateString: function(n) {
-                    return n.getFullYear() + "/" + n.getMonth() + "/" + n.getDate()
-                }
-            }, {
-                name: "year",
-                title: function(n) {
-                    return n.getFullYear()
-                },
-                content: function(n) {
-                    var f = ht(n.culture).months.namesAbbr,
-                        e = this.toDateString,
-                        t = n.min,
-                        u = n.max;
-                    return d({
-                        min: new i(t.getFullYear(), t.getMonth(), 1),
-                        max: new i(u.getFullYear(), u.getMonth(), 1),
-                        start: new i(n.date.getFullYear(), 0, 1),
-                        setter: this.setDate,
-                        build: function(n) {
-                            return {
-                                value: f[n.getMonth()],
-                                ns: r.ns,
-                                dateString: e(n),
-                                cssClass: ""
-                            }
-                        }
-                    })
-                },
-                first: function(n) {
-                    return new i(n.getFullYear(), 0, n.getDate())
-                },
-                last: function(n) {
-                    return new i(n.getFullYear(), 11, n.getDate())
-                },
-                compare: function(n, t) {
-                    return st(n, t)
-                },
-                setDate: function(n, t) {
-                    var r, u = n.getHours();
-                    t instanceof i ? (r = t.getMonth(), n.setFullYear(t.getFullYear(), r, n.getDate()), r !== n.getMonth() && n.setDate(0)) : (r = n.getMonth() + t, n.setMonth(r), r > 11 && (r -= 12), r > 0 && n.getMonth() != r && n.setDate(0));
-                    p(n, u)
-                },
-                toDateString: function(n) {
-                    return n.getFullYear() + "/" + n.getMonth() + "/1"
-                }
-            }, {
-                name: "decade",
-                title: function(n, t, i) {
-                    return li(n, t, i, 10)
-                },
-                content: function(n) {
-                    var t = n.date.getFullYear(),
-                        u = this.toDateString;
-                    return d({
-                        start: new i(t - t % 10 - 1, 0, 1),
-                        min: new i(n.min.getFullYear(), 0, 1),
-                        max: new i(n.max.getFullYear(), 0, 1),
-                        setter: this.setDate,
-                        build: function(n, t) {
-                            return {
-                                value: n.getFullYear(),
-                                ns: r.ns,
-                                dateString: u(n),
-                                cssClass: t === 0 || t == 11 ? gt : ""
-                            }
-                        }
-                    })
-                },
-                first: function(n) {
-                    var t = n.getFullYear();
-                    return new i(t - t % 10, n.getMonth(), n.getDate())
-                },
-                last: function(n) {
-                    var t = n.getFullYear();
-                    return new i(t - t % 10 + 9, n.getMonth(), n.getDate())
-                },
-                compare: function(n, t) {
-                    return st(n, t, 10)
-                },
-                setDate: function(n, t) {
-                    vi(n, t, 1)
-                },
-                toDateString: function(n) {
-                    return n.getFullYear() + "/0/1"
-                }
-            }, {
-                name: kt,
-                title: function(n, t, i) {
-                    return li(n, t, i, 100)
-                },
-                content: function(n) {
-                    var o = n.date.getFullYear(),
-                        f = n.min.getFullYear(),
-                        e = n.max.getFullYear(),
-                        s = this.toDateString,
-                        t = f,
-                        u = e;
-                    return t = t - t % 10, u = u - u % 10, u - t < 10 && (u = t + 9), d({
-                        start: new i(o - o % 100 - 10, 0, 1),
-                        min: new i(t, 0, 1),
-                        max: new i(u, 0, 1),
-                        setter: this.setDate,
-                        build: function(n, t) {
-                            var i = n.getFullYear(),
-                                u = i + 9;
-                            return i < f && (i = f), u > e && (u = e), {
-                                ns: r.ns,
-                                value: i + " - " + u,
-                                dateString: s(n),
-                                cssClass: t === 0 || t == 11 ? gt : ""
-                            }
-                        }
-                    })
-                },
-                first: function(n) {
-                    var t = n.getFullYear();
-                    return new i(t - t % 100, n.getMonth(), n.getDate())
-                },
-                last: function(n) {
-                    var t = n.getFullYear();
-                    return new i(t - t % 100 + 99, n.getMonth(), n.getDate())
-                },
-                compare: function(n, t) {
-                    return st(n, t, 100)
-                },
-                setDate: function(n, t) {
-                    vi(n, t, 10)
-                },
-                toDateString: function(n) {
-                    var t = n.getFullYear();
-                    return t - t % 10 + "/0/1"
-                }
-            }]
-        };
-        e.isEqualDatePart = er;
-        e.makeUnselectable = pi;
-        e.restrictValue = v;
-        e.isInRange = nt;
-        e.normalize = ct;
-        e.viewsEnum = o;
-        r.calendar = e
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "datepicker",
-        name: "DatePicker",
-        category: "web",
-        description: "The DatePicker widget allows the user to select a date from a calendar or by direct input.",
-        depends: ["calendar", "popup"]
-    }),
-    function(n, t) {
-        function d(t) {
-            var i = t.parseFormats,
-                r = t.format;
-            o.normalize(t);
-            i = n.isArray(i) ? i : [i];
-            n.inArray(r, i) === -1 && i.splice(0, 0, t.format);
-            t.parseFormats = i
-        }
-
-        function pt(n) {
-            n.preventDefault()
-        }
-        var i = window.kendo,
-            f = i.ui,
-            e = f.Widget,
-            c = i.parseDate,
-            u = i.keys,
-            bt = i.template,
-            kt = i._activeElement,
-            g = "<div />",
-            nt = "<span />",
-            r = ".kendoDatePicker",
-            tt = "click" + r,
-            l = "open",
-            a = "close",
-            v = "change",
-            it = "disabled",
-            rt = "readonly",
-            y = "k-state-default",
-            ut = "k-state-focused",
-            ft = "k-state-selected",
-            p = "k-state-disabled",
-            dt = "k-state-hover",
-            ii = "keydown" + r,
-            gt = "mouseenter" + r + " mouseleave" + r,
-            et = "mousedown" + r,
-            w = "id",
-            ot = "min",
-            st = "max",
-            ht = "month",
-            ct = "aria-disabled",
-            lt = "aria-expanded",
-            b = "aria-hidden",
-            at = "aria-readonly",
-            o = i.calendar,
-            ni = o.isInRange,
-            vt = o.restrictValue,
-            ti = o.isEqualDatePart,
-            k = n.extend,
-            s = n.proxy,
-            yt = Date,
-            h = function(t) {
-                var r = this,
-                    u, o = document.body,
-                    e = n(g).attr(b, "true").addClass("k-calendar-container").appendTo(o);
-                r.options = t = t || {};
-                u = t.id;
-                u && (u += "_dateview", e.attr(w, u), r._dateViewID = u);
-                r.popup = new f.Popup(e, k(t.popup, t, {
-                    name: "Popup",
-                    isRtl: i.support.isRtl(t.anchor)
-                }));
-                r.div = e;
-                r.value(t.value)
-            },
-            wt;
-        h.prototype = {
-            _calendar: function() {
-                var t = this,
-                    r = t.calendar,
-                    u = t.options,
-                    e;
-                r || (e = n(g).attr(w, i.guid()).appendTo(t.popup.element).on(et, pt).on(tt, "td:has(.k-link)", s(t._click, t)), t.calendar = r = new f.Calendar(e), t._setOptions(u), i.calendar.makeUnselectable(r.element), r.navigate(t._value || t._current, u.start), t.value(t._value))
-            },
-            _setOptions: function(n) {
-                this.calendar.setOptions({
-                    focusOnNav: !1,
-                    change: n.change,
-                    culture: n.culture,
-                    dates: n.dates,
-                    depth: n.depth,
-                    footer: n.footer,
-                    format: n.format,
-                    max: n.max,
-                    min: n.min,
-                    month: n.month,
-                    start: n.start
-                })
-            },
-            setOptions: function(n) {
-                var t = this.options;
-                this.options = k(t, n, {
-                    change: t.change,
-                    close: t.close,
-                    open: t.open
-                });
-                this.calendar && this._setOptions(this.options)
-            },
-            destroy: function() {
-                this.popup.destroy()
-            },
-            open: function() {
-                var n = this;
-                n._calendar();
-                n.popup.open()
-            },
-            close: function() {
-                this.popup.close()
-            },
-            min: function(n) {
-                this._option(ot, n)
-            },
-            max: function(n) {
-                this._option(st, n)
-            },
-            toggle: function() {
-                var n = this;
-                n[n.popup.visible() ? a : l]()
-            },
-            move: function(n) {
-                var t = this,
-                    i = n.keyCode,
-                    r = t.calendar,
-                    f = n.ctrlKey && i == u.DOWN || i == u.ENTER;
-                if (i == u.ESC) {
-                    t.close();
-                    return
-                }
-                if (n.altKey) {
-                    i == u.DOWN ? (t.open(), n.preventDefault()) : i == u.UP && (t.close(), n.preventDefault());
-                    return
-                }
-                if (t.popup.visible()) {
-                    if (f && r._cell.hasClass(ft)) {
-                        t.close();
-                        n.preventDefault();
-                        return
-                    }
-                    t._current = r._move(n)
-                }
-            },
-            current: function(n) {
-                this._current = n;
-                this.calendar._focus(n)
-            },
-            value: function(n) {
-                var t = this,
-                    i = t.calendar,
-                    r = t.options;
-                t._value = n;
-                t._current = new yt(+vt(n, r.min, r.max));
-                i && i.value(n)
-            },
-            _click: function(n) {
-                n.currentTarget.className.indexOf(ft) !== -1 && this.close()
-            },
-            _option: function(n, t) {
-                var i = this,
-                    r = i.calendar;
-                i.options[n] = t;
-                r && r[n](t)
-            }
-        };
-        h.normalize = d;
-        i.DateView = h;
-        wt = e.extend({
-            init: function(n, t) {
-                var r = this,
-                    f, u;
-                e.fn.init.call(r, n, t);
-                n = r.element;
-                t = r.options;
-                d(t);
-                r._wrapper();
-                r.dateView = new h(k({}, t, {
-                    id: n.attr(w),
-                    anchor: r.wrapper,
-                    change: function() {
-                        r._change(this.value());
-                        r.close()
-                    },
-                    close: function(t) {
-                        r.trigger(a) ? t.preventDefault() : (n.attr(lt, !1), u.attr(b, !0))
-                    },
-                    open: function(t) {
-                        var f = r.options,
-                            i;
-                        r.trigger(l) ? t.preventDefault() : (r.element.val() !== r._oldText && (i = c(n.val(), f.parseFormats, f.culture), r.dateView[i ? "current" : "value"](i)), n.attr(lt, !0), u.attr(b, !1), r._updateARIA(i))
-                    }
-                }));
-                u = r.dateView.div;
-                r._icon();
-                try {
-                    n[0].setAttribute("type", "text")
-                } catch (o) {
-                    n[0].type = "text"
-                }
-                n.addClass("k-input").attr({
-                    role: "combobox",
-                    "aria-expanded": !1,
-                    "aria-owns": r.dateView._dateViewID
-                });
-                r._reset();
-                r._template();
-                f = n.is("[disabled]");
-                f ? r.enable(!1) : r.readonly(n.is("[readonly]"));
-                r._old = r._update(t.value || r.element.val());
-                r._oldText = n.val();
-                i.notify(r)
-            },
-            events: [l, a, v],
-            options: {
-                name: "DatePicker",
-                value: null,
-                footer: "",
-                format: "",
-                culture: "",
-                parseFormats: [],
-                min: new Date(1900, 0, 1),
-                max: new Date(2099, 11, 31),
-                start: ht,
-                depth: ht,
-                animation: {},
-                month: {},
-                dates: [],
-                ARIATemplate: 'Current focused date is #=kendo.toString(data.current, "D")#'
-            },
-            setOptions: function(n) {
-                var t = this,
-                    r = t._value;
-                e.fn.setOptions.call(t, n);
-                n = t.options;
-                d(n);
-                t.dateView.setOptions(n);
-                r && (t.element.val(i.toString(r, n.format, n.culture)), t._updateARIA(r))
-            },
-            _editable: function(n) {
-                var t = this,
-                    o = t._dateIcon.off(r),
-                    f = t.element.off(r),
-                    e = t._inputWrapper.off(r),
-                    u = n.readonly,
-                    i = n.disable;
-                if (u || i) e.addClass(i ? p : y).removeClass(i ? y : p), f.attr(it, i).attr(rt, u).attr(ct, i).attr(at, u);
-                else {
-                    e.addClass(y).removeClass(p).on(gt, t._toggleHover);
-                    f.removeAttr(it).removeAttr(rt).attr(ct, !1).attr(at, !1).on("keydown" + r, s(t._keydown, t)).on("blur" + r, s(t._blur, t)).on("focus" + r, function() {
-                        t._inputWrapper.addClass(ut)
-                    });
-                    o.on(tt, s(t._click, t)).on(et, pt)
-                }
-            },
-            readonly: function(n) {
-                this._editable({
-                    readonly: n === t ? !0 : n,
-                    disable: !1
-                })
-            },
-            enable: function(n) {
-                this._editable({
-                    readonly: !1,
-                    disable: !(n = n === t ? !0 : n)
-                })
-            },
-            destroy: function() {
-                var n = this;
-                e.fn.destroy.call(n);
-                n.dateView.destroy();
-                n.element.off(r);
-                n._dateIcon.off(r);
-                n._inputWrapper.off(r);
-                n._form && n._form.off("reset", n._resetHandler)
-            },
-            open: function() {
-                this.dateView.open()
-            },
-            close: function() {
-                this.dateView.close()
-            },
-            min: function(n) {
-                return this._option(ot, n)
-            },
-            max: function(n) {
-                return this._option(st, n)
-            },
-            value: function(n) {
-                var i = this;
-                if (n === t) return i._value;
-                i._old = i._update(n);
-                i._old === null && i.element.val("");
-                i._oldText = i.element.val()
-            },
-            _toggleHover: function(t) {
-                n(t.currentTarget).toggleClass(dt, t.type === "mouseenter")
-            },
-            _blur: function() {
-                var n = this,
-                    t = n.element.val();
-                n.close();
-                t !== n._oldText && n._change(t);
-                n._inputWrapper.removeClass(ut)
-            },
-            _click: function() {
-                var n = this,
-                    t = n.element;
-                n.dateView.toggle();
-                i.support.touch || t[0] === kt() || t.focus()
-            },
-            _change: function(n) {
-                var t = this;
-                n = t._update(n); + t._old != +n && (t._old = n, t._oldText = t.element.val(), t.trigger(v), t.element.trigger(v))
-            },
-            _keydown: function(n) {
-                var t = this,
-                    i = t.dateView,
-                    r = t.element.val();
-                i.popup.visible() || n.keyCode != u.ENTER || r === t._oldText ? (i.move(n), t._updateARIA(i._current)) : t._change(r)
-            },
-            _icon: function() {
-                var i = this,
-                    r = i.element,
-                    t;
-                t = r.next("span.k-select");
-                t[0] || (t = n('<span unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-calendar">select<\/span><\/span>').insertAfter(r));
-                i._dateIcon = t.attr({
-                    role: "button",
-                    "aria-controls": i.dateView._dateViewID
-                })
-            },
-            _option: function(n, i) {
-                var u = this,
-                    r = u.options;
-                if (i === t) return r[n];
-                (i = c(i, r.parseFormats, r.culture), i) && (r[n] = new yt(+i), u.dateView[n](i))
-            },
-            _update: function(n) {
-                var u = this,
-                    r = u.options,
-                    f = r.min,
-                    o = r.max,
-                    t = c(n, r.parseFormats, r.culture),
-                    e;
-                return +t == +u._value ? (e = i.toString(t, r.format, r.culture), e !== n && u.element.val(t === null ? n : e), t) : (t !== null && ti(t, f) ? t = vt(t, f, o) : ni(t, f, o) || (t = null), u._value = t, u.dateView.value(t), u.element.val(t ? i.toString(t, r.format, r.culture) : n), u._updateARIA(t), t)
-            },
-            _wrapper: function() {
-                var r = this,
-                    i = r.element,
-                    t;
-                t = i.parents(".k-datepicker");
-                t[0] || (t = i.wrap(nt).parent().addClass("k-picker-wrap k-state-default"), t = t.wrap(nt).parent());
-                t[0].style.cssText = i[0].style.cssText;
-                i.css({
-                    width: "100%",
-                    height: i[0].style.height
-                });
-                r.wrapper = t.addClass("k-widget k-datepicker k-header").addClass(i[0].className);
-                r._inputWrapper = n(t[0].firstChild)
-            },
-            _reset: function() {
-                var t = this,
-                    i = t.element,
-                    r = i.attr("form"),
-                    u = r ? n("#" + r) : i.closest("form");
-                u[0] && (t._resetHandler = function() {
-                    t.value(i[0].defaultValue)
-                }, t._form = u.on("reset", t._resetHandler))
-            },
-            _template: function() {
-                this._ariaTemplate = bt(this.options.ARIATemplate)
-            },
-            _updateARIA: function(n) {
-                var i, t = this,
-                    r = t.dateView.calendar;
-                t.element.removeAttr("aria-activedescendant");
-                r && (i = r._cell, i.attr("aria-label", t._ariaTemplate({
-                    current: n || r.current()
-                })), t.element.attr("aria-activedescendant", i.attr("id")))
-            }
-        });
-        f.plugin(wt)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "dropdownlist",
-        name: "DropDownList",
-        category: "web",
-        description: "The DropDownList widget displays a list of values and allows the selection of a single value from the list.",
-        depends: ["list"],
-        features: [{
-            id: "mobile-scroller",
-            name: "Mobile scroller",
-            description: "Support for kinetic scrolling in mobile device",
-            depends: ["mobile.scroller"]
-        }]
-    }),
-    function(n, t) {
-        function o(n, t, i) {
-            for (var u = 0, f = t.length - 1, r; u < f; ++u) r = t[u], r in n || (n[r] = {}), n = n[r];
-            n[t[f]] = i
-        }
-        var r = window.kendo,
-            s = r.ui,
-            u = s.Select,
-            f = r.support.mobileOS,
-            i = ".kendoDropDownList",
-            a = "disabled",
-            v = "readonly",
-            y = "change",
-            p = "k-state-focused",
-            h = "k-state-default",
-            c = "k-state-disabled",
-            w = "aria-disabled",
-            b = "aria-readonly",
-            l = "k-state-selected",
-            k = "mouseenter" + i + " mouseleave" + i,
-            e = "tabindex",
-            d = n.proxy,
-            g = u.extend({
-                init: function(f, o) {
-                    var s = this,
-                        a = o && o.index,
-                        c, l, h;
-                    s.ns = i;
-                    o = n.isArray(o) ? {
-                        dataSource: o
-                    } : o;
-                    u.fn.init.call(s, f, o);
-                    s._focusHandler = function() {
-                        s.wrapper.focus()
-                    };
-                    o = s.options;
-                    f = s.element.on("focus" + i, s._focusHandler);
-                    this._inputTemplate();
-                    s._reset();
-                    s._word = "";
-                    s._wrapper();
-                    s._tabindex();
-                    s.wrapper.data(e, s.wrapper.attr(e));
-                    s._aria();
-                    s._span();
-                    s._popup();
-                    s._mobile();
-                    s._dataSource();
-                    s._ignoreCase();
-                    s._enable();
-                    s._oldIndex = s.selectedIndex = -1;
-                    s._cascade();
-                    a !== t && (o.index = a);
-                    o.autoBind ? s.dataSource.fetch() : s.selectedIndex === -1 && (h = o.text || "", h || (c = o.optionLabel, l = c && o.index === 0, s._isSelect ? h = l ? c : f.children(":selected").text() : !f[0].value && l && (h = c)), s._textAccessor(h));
-                    r.notify(s)
-                },
-                options: {
-                    name: "DropDownList",
-                    enabled: !0,
-                    autoBind: !0,
-                    index: 0,
-                    text: null,
-                    value: null,
-                    template: "",
-                    valueTemplate: "",
-                    delay: 500,
-                    height: 200,
-                    dataTextField: "",
-                    dataValueField: "",
-                    optionLabel: "",
-                    cascadeFrom: "",
-                    cascadeFromField: "",
-                    ignoreCase: !0,
-                    animation: {}
-                },
-                events: ["open", "close", y, "select", "dataBinding", "dataBound", "cascade"],
-                setOptions: function(n) {
-                    u.fn.setOptions.call(this, n);
-                    this._template();
-                    this._inputTemplate();
-                    this._accessors();
-                    this._aria()
-                },
-                destroy: function() {
-                    var n = this;
-                    n.wrapper.off(i);
-                    n.element.off(i);
-                    n._inputWrapper.off(i);
-                    u.fn.destroy.call(n)
-                },
-                open: function() {
-                    var n = this;
-                    n.ul[0].firstChild ? (n.popup.open(), n._scroll(n._current)) : (n._open = !0, n._request || n.dataSource.fetch())
-                },
-                toggle: function(n) {
-                    this._toggle(n)
-                },
-                refresh: function() {
-                    var n = this,
-                        u = n._data(),
-                        t = u.length,
-                        i = n.options.optionLabel,
-                        e = n.element[0],
-                        f;
-                    n.trigger("dataBinding");
-                    n._current && n.current(null);
-                    n.ul[0].innerHTML = r.render(n.template, u);
-                    n._height(t);
-                    n.popup.visible() && n.popup._position();
-                    n._isSelect && (f = e.selectedIndex, i && t && (i = '<option value="">' + n._optionLabelText(i) + "<\/option>"), n._options(u, i), e.selectedIndex = f === -1 ? 0 : f);
-                    n._open && (n._open = !1, n.toggle(!!t));
-                    n._hideBusy();
-                    n._makeUnselectable();
-                    n._fetch || (t ? n._selectItem() : n._textAccessor() !== i && (n.element.val(""), n._textAccessor("")));
-                    n._bound = !!t;
-                    n.trigger("dataBound")
-                },
-                search: function(n) {
-                    if (n) {
-                        var i = this,
-                            r = i.options.ignoreCase;
-                        r && (n = n.toLowerCase());
-                        i._select(function(u) {
-                            var f = i._text(u);
-                            if (f !== t) return f = f + "", r && (f = f.toLowerCase()), f.indexOf(n) === 0
-                        })
-                    }
-                },
-                text: function(n) {
-                    var i = this,
-                        r, u, f = i.options.ignoreCase;
-                    if (n = n === null ? "" : n, n !== t) typeof n == "string" && (u = f ? n.toLowerCase() : n, r = i._select(function(n) {
-                        return n = i._text(n), f && (n = (n + "").toLowerCase()), n === u
-                    }), r && (n = r)), i._textAccessor(n);
-                    else return i._textAccessor()
-                },
-                value: function(n) {
-                    var i = this,
-                        r, u;
-                    if (n !== t) {
-                        if (n !== null && (n = n.toString()), i._selectedValue = n, u = n || i.options.optionLabel && !i.element[0].disabled && n === "", u && i._fetchItems(n)) return;
-                        r = i._index(n);
-                        i.select(r > -1 ? r : 0)
-                    } else return i._accessor()
-                },
-                _editable: function(n) {
-                    var t = this,
-                        s = t.element,
-                        o = n.disable,
-                        l = n.readonly,
-                        u = t.wrapper.off(i),
-                        f = t._inputWrapper.off(k),
-                        y = function() {
-                            f.addClass(p);
-                            t._blured = !1
-                        },
-                        g = function() {
-                            if (!t._blured) {
-                                t._triggerCascade();
-                                var n = window.self !== window.top;
-                                r.support.mobileOS.ios && n ? t._change() : t._blur();
-                                f.removeClass(p);
-                                t._blured = !0;
-                                s.blur()
-                            }
-                        };
-                    if (l || o) {
-                        if (o) u.removeAttr(e), f.addClass(c).removeClass(h);
-                        else {
-                            f.addClass(h).removeClass(c);
-                            u.on("focusin" + i, y).on("focusout" + i, g)
-                        }
-                        s.attr(a, o).attr(v, l);
-                        u.attr(w, o).attr(b, l)
-                    } else {
-                        s.removeAttr(a).removeAttr(v);
-                        f.addClass(h).removeClass(c).on(k, t._toggleHover);
-                        u.attr(e, u.data(e)).attr(w, !1).attr(b, !1).on("click" + i, function(n) {
-                            t._blured = !1;
-                            n.preventDefault();
-                            t.toggle()
-                        }).on("keydown" + i, d(t._keydown, t)).on("keypress" + i, d(t._keypress, t)).on("focusin" + i, y).on("focusout" + i, g)
-                    }
-                },
-                _accept: function(n) {
-                    this._focus(n)
-                },
-                _optionLabelText: function() {
-                    var t = this.options,
-                        i = t.dataTextField,
-                        n = t.optionLabel;
-                    return n && i && typeof n == "object" ? this._text(n) : n
-                },
-                _data: function() {
-                    var h = this,
-                        f = h.options,
-                        t = f.optionLabel,
-                        i = f.dataTextField,
-                        e = f.dataValueField,
-                        u = h.dataSource.view(),
-                        c = u.length,
-                        n = t,
-                        s = 0;
-                    if (t && c) {
-                        for (typeof t == "object" ? n = t : i && (n = {}, i = i.split("."), e = e.split("."), o(n, e, ""), o(n, i, t)), n = new r.data.ObservableArray([n]); s < c; s++) n.push(u[s]);
-                        u = n
-                    }
-                    return u
-                },
-                _selectItem: function() {
-                    u.fn._selectItem.call(this);
-                    this.current() || this.select(0)
-                },
-                _keydown: function(n) {
-                    var u = this,
-                        t = n.keyCode,
-                        i = r.keys,
-                        f = u.ul[0];
-                    t === i.LEFT ? t = i.UP : t === i.RIGHT && (t = i.DOWN);
-                    n.keyCode = t;
-                    u._move(n);
-                    t === i.HOME ? (n.preventDefault(), u._select(f.firstChild)) : t === i.END && (n.preventDefault(), u._select(f.lastChild))
-                },
-                _selectNext: function(n, t) {
-                    for (var i = this, r, f = t, u = i._data(), o = u.length, s = i.options.ignoreCase, e = function(t, r) {
-                            return t = t + "", s && (t = t.toLowerCase()), t.indexOf(n) === 0 ? (i._select(r), i._triggerEvents(), !0) : void 0
-                        }; t < o; t++)
-                        if (r = i._text(u[t]), r && e(r, t)) return !0;
-                    if (f > 0)
-                        for (t = 0; t <= f; t++)
-                            if (r = i._text(u[t]), r && e(r, t)) return !0;
-                    return !1
-                },
-                _keypress: function(n) {
-                    if (n.charCode !== 0) {
-                        var t = this,
-                            i = String.fromCharCode(n.charCode || n.keyCode),
-                            u = t.selectedIndex,
-                            r = t._word;
-                        (t.options.ignoreCase && (i = i.toLowerCase()), i === " " && n.preventDefault(), t._last === i && r.length <= 1 && u > -1 && (r || (r = i), t._selectNext(r, u + 1))) || (t._word = r + i, t._last = i, t._search())
-                    }
-                },
-                _popup: function() {
-                    u.fn._popup.call(this);
-                    this.popup.one("open", function() {
-                        this.wrapper = r.wrap(this.element).addClass("km-popup")
-                    })
-                },
-                _search: function() {
-                    var n = this,
-                        i = n.dataSource,
-                        t = n.selectedIndex,
-                        r = n._word;
-                    if (clearTimeout(n._typing), n._typing = setTimeout(function() {
-                            n._word = ""
-                        }, n.options.delay), t === -1 && (t = 0), !n.ul[0].firstChild) {
-                        i.one(y, function() {
-                            i.data()[0] && t > -1 && n._selectNext(r, t)
-                        }).fetch();
-                        return
-                    }
-                    n._selectNext(r, t);
-                    n._triggerEvents()
-                },
-                _select: function(n) {
-                    var i = this,
-                        e = i._current,
-                        r = null,
-                        f, u;
-                    return n = i._get(n), n && n[0] && !n.hasClass(l) && (e && e.removeClass(l), u = s.List.inArray(n[0], i.ul[0]), u > -1 && (r = i._data()[u], f = i._value(r), i.selectedIndex = u, i._textAccessor(r), i._accessor(f !== t ? f : i._text(r), u), i._selectedValue = i._accessor(), i.current(n.addClass(l)), i._optionID && i._current.attr("aria-selected", !0))), r
-                },
-                _triggerEvents: function() {
-                    this.popup.visible() || (this._triggerCascade(), this._change())
-                },
-                _mobile: function() {
-                    var t = this,
-                        n = t.popup,
-                        i = n.element.parents(".km-root").eq(0);
-                    i.length && f && (n.options.animation.open.effects = f.android || f.meego ? "fadeIn" : f.ios || f.wp ? "slideIn:up" : n.options.animation.open.effects)
-                },
-                _span: function() {
-                    var t = this,
-                        i = t.wrapper,
-                        u = "span.k-input",
-                        r;
-                    r = i.find(u);
-                    r[0] || (i.append('<span unselectable="on" class="k-dropdown-wrap k-state-default"><span unselectable="on" class="k-input">&nbsp;<\/span><span unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-arrow-s">select<\/span><\/span><\/span>').append(t.element), r = i.find(u));
-                    t.span = r;
-                    t._inputWrapper = n(i[0].firstChild);
-                    t._arrow = i.find(".k-icon").mousedown(function(n) {
-                        n.preventDefault()
-                    })
-                },
-                _wrapper: function() {
-                    var i = this,
-                        t = i.element,
-                        r = t[0],
-                        n;
-                    n = t.parent();
-                    n.is("span.k-widget") || (n = t.wrap("<span />").parent(), n[0].style.cssText = r.style.cssText);
-                    t.hide();
-                    i._focused = i.wrapper = n.addClass("k-widget k-dropdown k-header").addClass(r.className).css("display", "").attr({
-                        unselectable: "on",
-                        role: "listbox",
-                        "aria-haspopup": !0,
-                        "aria-expanded": !1
-                    })
-                },
-                _clearSelection: function() {
-                    var n = this,
-                        t = n.options.optionLabel;
-                    if (n.options.value = "", n._selectedValue = "", n.dataSource.view()[0] && (t || n._userTriggered)) {
-                        n.select(0);
-                        return
-                    }
-                    n.selectedIndex = -1;
-                    n.element.val("");
-                    n._textAccessor(n.options.optionLabel)
-                },
-                _inputTemplate: function() {
-                    var i = this,
-                        t = i.options.valueTemplate;
-                    t = t ? r.template(t) : n.proxy(r.template("#:this._text(data)#"), i);
-                    i.valueTemplate = t
-                },
-                _textAccessor: function(i) {
-                    var u = this.dataItem(),
-                        f = this.options,
-                        e = this.span;
-                    if (i !== t) n.isPlainObject(i) || i instanceof r.data.ObservableObject ? u = i : u && this._text(u) === i || (f.dataTextField ? (u = {}, o(u, f.dataTextField.split("."), i), o(u, f.dataValueField.split("."), this._accessor())) : u = i), e.html(this.valueTemplate(u));
-                    else return e.text()
-                }
-            });
-        s.plugin(g)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "combobox",
-        name: "ComboBox",
-        category: "web",
-        description: "The ComboBox widget allows the selection from pre-defined values or entering a new value.",
-        depends: ["list"],
-        features: [{
-            id: "mobile-scroller",
-            name: "Mobile scroller",
-            description: "Support for kinetic scrolling in mobile device",
-            depends: ["mobile.scroller"]
-        }]
-    }),
-    function(n, t) {
-        var r = window.kendo,
-            o = r.ui,
-            u = o.List,
-            f = o.Select,
-            ut = r.support,
-            v = ut.placeholder,
-            s = r._activeElement,
-            h = r.keys,
-            i = ".kendoComboBox",
-            y = "click" + i,
-            p = "mousedown" + i,
-            w = "disabled",
-            b = "readonly",
-            k = "change",
-            c = "k-state-default",
-            d = "k-state-focused",
-            l = "k-state-disabled",
-            g = "aria-disabled",
-            nt = "aria-readonly",
-            tt = "k-state-selected",
-            e = "filter",
-            a = "accept",
-            it = "rebind",
-            ft = "mouseenter" + i + " mouseleave" + i,
-            rt = null,
-            et = n.proxy,
-            ot = f.extend({
-                init: function(t, u) {
-                    var e = this,
-                        o;
-                    e.ns = i;
-                    u = n.isArray(u) ? {
-                        dataSource: u
-                    } : u;
-                    f.fn.init.call(e, t, u);
-                    e._focusHandler = function() {
-                        e.input.focus()
-                    };
-                    u = e.options;
-                    t = e.element.on("focus" + i, e._focusHandler);
-                    u.placeholder = u.placeholder || t.attr("placeholder");
-                    e._reset();
-                    e._wrapper();
-                    e._input();
-                    e._tabindex(e.input);
-                    e._popup();
-                    e._dataSource();
-                    e._ignoreCase();
-                    e._enable();
-                    e._cascade();
-                    e._aria();
-                    e._oldIndex = e.selectedIndex = -1;
-                    u.autoBind ? e._filterSource() : (o = u.text, !o && e._isSelect && (o = t.children(":selected").text()), o && (e.input.val(o), e._prev = o));
-                    o || e._placeholder();
-                    r.notify(e)
-                },
-                options: {
-                    name: "ComboBox",
-                    enabled: !0,
-                    index: -1,
-                    text: null,
-                    value: null,
-                    autoBind: !0,
-                    delay: 200,
-                    dataTextField: "",
-                    dataValueField: "",
-                    minLength: 0,
-                    height: 200,
-                    highlightFirst: !0,
-                    template: "",
-                    filter: "none",
-                    placeholder: "",
-                    suggest: !1,
-                    cascadeFrom: "",
-                    cascadeFromField: "",
-                    ignoreCase: !0,
-                    animation: {}
-                },
-                events: ["open", "close", k, "select", "dataBinding", "dataBound", "cascade"],
-                setOptions: function(n) {
-                    f.fn.setOptions.call(this, n);
-                    this._template();
-                    this._accessors();
-                    this._aria()
-                },
-                current: function(n) {
-                    var r = this,
-                        i = r._current;
-                    if (n === t) return i;
-                    i && i.removeClass(tt);
-                    f.fn.current.call(r, n)
-                },
-                destroy: function() {
-                    var n = this;
-                    n.input.off(i);
-                    n.element.off(i);
-                    n._inputWrapper.off(i);
-                    f.fn.destroy.call(n)
-                },
-                _editable: function(n) {
-                    var t = this,
-                        r = n.disable,
-                        f = n.readonly,
-                        u = t._inputWrapper.off(i),
-                        e = t.element.add(t.input.off(i)),
-                        o = t._arrow.parent().off(y + " " + p);
-                    if (f || r) u.addClass(r ? l : c).removeClass(r ? c : l), e.attr(w, r).attr(b, f).attr(g, r).attr(nt, f);
-                    else {
-                        u.addClass(c).removeClass(l).on(ft, t._toggleHover);
-                        e.removeAttr(w).removeAttr(b).attr(g, !1).attr(nt, !1);
-                        o.on(y, function() {
-                            t.toggle()
-                        }).on(p, function(n) {
-                            n.preventDefault()
-                        });
-                        t.input.on("keydown" + i, et(t._keydown, t)).on("focus" + i, function() {
-                            u.addClass(d);
-                            t._placeholder(!1)
-                        }).on("blur" + i, function() {
-                            u.removeClass(d);
-                            clearTimeout(t._typing);
-                            t.options.text !== t.input.val() && t.text(t.text());
-                            t._placeholder();
-                            t._blur();
-                            t.element.blur()
-                        })
-                    }
-                },
-                open: function() {
-                    var n = this,
-                        t = n.dataSource.options.serverFiltering;
-                    n.popup.visible() || (n.ul[0].firstChild && (n._state !== a || t) ? (n.popup.open(), n._scroll(n._current)) : (n._open = !0, n._state = it, n._filterSource()))
-                },
-                refresh: function() {
-                    var i = this,
-                        f = i.ul[0],
-                        l = i.options,
-                        a = i._state,
-                        o = i._data(),
-                        h = o.length,
-                        v = !0,
-                        y, c, u;
-                    i.trigger("dataBinding");
-                    f.innerHTML = r.render(i.template, o);
-                    i._height(h);
-                    i.popup.visible() && i.popup._position();
-                    i._isSelect && (y = i.element[0].firstChild, a === it && (i._state = ""), u = i._option, i._option = t, i._options(o), u && u[0].selected ? i._custom(u.val(), v) : i._bound || y || i._custom("", v));
-                    h && (l.highlightFirst && i.current(n(f.firstChild)), l.suggest && i.input.val() && i._request !== t && i.suggest(n(f.firstChild)));
-                    a === e || i._fetch || i._selectItem();
-                    i._open && (i._open = !1, c = !!h, i._typing && i.input[0] !== s() && (c = !1), i.toggle(c), i._typing = t);
-                    i._touchScroller && i._touchScroller.reset();
-                    i._makeUnselectable();
-                    i._hideBusy();
-                    i._bound = !0;
-                    i.trigger("dataBound")
-                },
-                search: function(n) {
-                    n = typeof n == "string" ? n : this.text();
-                    var t = this,
-                        f = n.length,
-                        i = t.options,
-                        r = i.ignoreCase,
-                        u = i.filter,
-                        o = i.dataTextField;
-                    clearTimeout(t._typing);
-                    f >= i.minLength && (t._state = e, u === "none" ? t._filter(n) : (t._open = !0, t._filterSource({
-                        value: r ? n.toLowerCase() : n,
-                        field: o,
-                        operator: u,
-                        ignoreCase: r
-                    })))
-                },
-                suggest: function(n) {
-                    var r = this,
-                        o = r.input[0],
-                        i = r.text(),
-                        e = u.caret(o),
-                        c = r._last,
-                        f;
-                    if (c == h.BACKSPACE || c == h.DELETE) {
-                        r._last = t;
-                        return
-                    }
-                    n = n || "";
-                    typeof n != "string" && (f = u.inArray(n[0], r.ul[0]), n = f > -1 ? r._text(r.dataSource.view()[f]) : "");
-                    e <= 0 && (e = i.toLowerCase().indexOf(n.toLowerCase()) + 1);
-                    n ? (f = n.toLowerCase().indexOf(i.toLowerCase()), f > -1 && (i += n.substring(f + i.length))) : i = i.substring(0, e);
-                    i.length === e && n || (o.value = i, o === s() && u.selectText(o, e, i.length))
-                },
-                text: function(n) {
-                    n = n === null ? "" : n;
-                    var i = this,
-                        u = i.input[0],
-                        e = i.options.ignoreCase,
-                        f = n,
-                        r;
-                    if (n !== t) {
-                        if (r = i.dataItem(), r && i._text(r) === n && i._value(r).toString() === i._old) {
-                            i._triggerCascade();
-                            return
-                        }
-                        e && (f = f.toLowerCase());
-                        i._select(function(n) {
-                            return n = i._text(n), e && (n = (n + "").toLowerCase()), n === f
-                        });
-                        i.selectedIndex < 0 && (i._custom(n), u.value = n);
-                        i._prev = u.value;
-                        i._triggerCascade()
-                    } else return u.value
-                },
-                toggle: function(n) {
-                    var t = this;
-                    t._toggle(n)
-                },
-                value: function(n) {
-                    var i = this,
-                        u = i.options,
-                        r;
-                    if (n !== t) {
-                        if (n !== null && (n = n.toString()), i._selectedValue = n, !i._open && n && i._fetchItems(n)) return;
-                        r = i._index(n);
-                        r > -1 ? i.select(r) : (i.current(rt), i._custom(n), (u.value !== n || u.text !== i.input.val()) && (i.text(n), i._placeholder()));
-                        i._old = i._accessor();
-                        i._oldIndex = i.selectedIndex
-                    } else return i._accessor()
-                },
-                _accept: function(n) {
-                    var t = this;
-                    n ? t._focus(n) : (t.text(t.text()), t._change())
-                },
-                _custom: function(t, i) {
-                    var r = this,
-                        f = r.element,
-                        u = r._option;
-                    r._state !== e || i || (r._state = a);
-                    r._isSelect ? (u || (u = r._option = n("<option/>"), f.append(u)), u.text(t), u[0].selected = !0) : f.val(t);
-                    r._selectedValue = t
-                },
-                _filter: function(n) {
-                    var i = this,
-                        r = i.options,
-                        u = i.dataSource,
-                        f = r.ignoreCase,
-                        e = function(r) {
-                            var u = i._text(r);
-                            if (u !== t) return (u = u + "", u !== "" && n === "") ? !1 : (f && (u = u.toLowerCase()), u.indexOf(n) === 0)
-                        };
-                    if (f && (n = n.toLowerCase()), !i.ul[0].firstChild) {
-                        u.one(k, function() {
-                            u.data()[0] && i.search(n)
-                        }).fetch();
-                        return
-                    }
-                    i._highlight(e) !== -1 && (r.suggest && i._current && i.suggest(i._current), i.open());
-                    i._hideBusy()
-                },
-                _highlight: function(i) {
-                    var r = this,
-                        f;
-                    return i === t || i === null ? -1 : (i = r._get(i), f = u.inArray(i[0], r.ul[0]), f == -1 && (r.options.highlightFirst && !r.text() ? (i = r.ul[0].firstChild, i && (i = n(i))) : i = rt), r.current(i), f)
-                },
-                _input: function() {
-                    var t = this,
-                        i = t.element.removeClass("k-input")[0],
-                        e = i.accessKey,
-                        u = t.wrapper,
-                        o = "input.k-input",
-                        f = i.name || "",
-                        r;
-                    f && (f = 'name="' + f + '_input" ');
-                    r = u.find(o);
-                    r[0] || (u.append('<span tabindex="-1" unselectable="on" class="k-dropdown-wrap k-state-default"><input ' + f + 'class="k-input" type="text" autocomplete="off"/><span tabindex="-1" unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-arrow-s">select<\/span><\/span><\/span>').append(t.element), r = u.find(o));
-                    r[0].style.cssText = i.style.cssText;
-                    i.maxLength > -1 && (r[0].maxLength = i.maxLength);
-                    r.addClass(i.className).val(this.options.text || i.value).css({
-                        width: "100%",
-                        height: i.style.height
-                    }).attr({
-                        role: "combobox",
-                        "aria-expanded": !1
-                    }).show();
-                    v && r.attr("placeholder", t.options.placeholder);
-                    e && (i.accessKey = "", r[0].accessKey = e);
-                    t._focused = t.input = r;
-                    t._inputWrapper = n(u[0].firstChild);
-                    t._arrow = u.find(".k-icon").attr({
-                        role: "button",
-                        tabIndex: -1
-                    });
-                    i.id && t._arrow.attr("aria-controls", t.ul[0].id)
-                },
-                _keydown: function(n) {
-                    var t = this,
-                        i = n.keyCode;
-                    t._last = i;
-                    clearTimeout(t._typing);
-                    i == h.TAB || t._move(n) || t._search()
-                },
-                _placeholder: function(n) {
-                    if (!v) {
-                        var f = this,
-                            i = f.input,
-                            r = f.options.placeholder,
-                            e;
-                        if (r) {
-                            if (e = f.value(), n === t && (n = !e), i.toggleClass("k-readonly", n), !n) {
-                                if (e) return;
-                                r = ""
-                            }
-                            i.val(r);
-                            r || i[0] !== s() || u.selectText(i[0], 0, 0)
-                        }
-                    }
-                },
-                _search: function() {
-                    var n = this;
-                    n._typing = setTimeout(function() {
-                        var t = n.text();
-                        n._prev !== t && (n._prev = t, n.search(t));
-                        n._typing = null
-                    }, n.options.delay)
-                },
-                _select: function(n) {
-                    var i = this,
-                        f, o, r = i._data(),
-                        u = i._highlight(n);
-                    i.selectedIndex = u;
-                    u !== -1 && (i._state === e && (i._state = a), i._current.addClass(tt), r = r[u], f = i._text(r), o = i._value(r), i._prev = i.input[0].value = f, i._accessor(o !== t ? o : f, u), i._selectedValue = i._accessor(), i._placeholder(), i._optionID && i._current.attr("aria-selected", !0))
-                },
-                _wrapper: function() {
-                    var i = this,
-                        n = i.element,
-                        t = n.parent();
-                    t.is("span.k-widget") || (t = n.hide().wrap("<span />").parent(), t[0].style.cssText = n[0].style.cssText);
-                    i.wrapper = t.addClass("k-widget k-combobox k-header").addClass(n[0].className).css("display", "")
-                },
-                _clearSelection: function(n, t) {
-                    var i = this,
-                        r = n._selectedValue || n.value(),
-                        u = r && n.selectedIndex === -1;
-                    (t || !r || u) && (i.value(""), i.options.value = "")
-                }
-            });
-        o.plugin(ot)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "multiselect",
-        name: "MultiSelect",
-        category: "web",
-        description: "The MultiSelect widget allows the selection from pre-defined values.",
-        depends: ["list"],
-        features: [{
-            id: "mobile-scroller",
-            name: "Mobile scroller",
-            description: "Support for kinetic scrolling in mobile device",
-            depends: ["mobile.scroller"]
-        }]
-    }),
-    function(n, t) {
-        function ni(n, t) {
-            var i;
-            if (n === null && t !== null || n !== null && t === null || (i = n.length, i !== t.length)) return !1;
-            while (i--)
-                if (n[i] !== t[i]) return !1;
-            return !0
-        }
-
-        function s(t) {
-            var i = t.firstChild;
-            return (i && i.style.display === "none" && (i = h(i, it)), i) ? n(i) : i
-        }
-
-        function lt(t) {
-            var i = t.lastChild;
-            return (i && i.style.display === "none" && (i = h(i, rt)), i) ? n(i) : i
-        }
-
-        function h(n, t) {
-            return n = n[t], n && n.style.display === "none" && (n = h(n, t)), n
-        }
-        var i = window.kendo,
-            d = i.ui,
-            f = d.List,
-            r = i.keys,
-            g = i._activeElement,
-            at = i.data.ObservableArray,
-            c = n.proxy,
-            e = "id",
-            v = "li",
-            y = "accept",
-            p = "filter",
-            nt = "open",
-            tt = "close",
-            o = "change",
-            vt = "progress",
-            w = "select",
-            it = "nextSibling",
-            rt = "previousSibling",
-            yt = ' style="display:none"',
-            ut = "aria-disabled",
-            ft = "aria-readonly",
-            l = "k-state-focused",
-            b = "k-loading-hidden",
-            et = "k-state-hover",
-            k = "k-state-disabled",
-            ot = "disabled",
-            st = "readonly",
-            u = ".kendoMultiSelect",
-            pt = "click" + u,
-            wt = "keydown" + u,
-            ht = "mouseenter" + u,
-            ct = "mouseleave" + u,
-            bt = ht + " " + ct,
-            kt = /"/g,
-            a = n.isArray,
-            dt = ["font-family", "font-size", "font-stretch", "font-style", "font-weight", "letter-spacing", "text-transform", "line-height"],
-            gt = f.extend({
-                init: function(t, r) {
-                    var o = this,
-                        s, h;
-                    o.ns = u;
-                    f.fn.init.call(o, t, r);
-                    o._wrapper();
-                    o._tagList();
-                    o._input();
-                    o._textContainer();
-                    o._loader();
-                    o._tabindex(o.input);
-                    t = o.element.attr("multiple", "multiple").hide();
-                    r = o.options;
-                    h = r.value;
-                    r.placeholder || (r.placeholder = t.data("placeholder"));
-                    s = t.attr(e);
-                    s && (o._tagID = s + "_tag_active", s = s + "_taglist", o.tagList.attr(e, s));
-                    o._aria(s);
-                    o._dataSource();
-                    o._ignoreCase();
-                    o._popup();
-                    o._values = [];
-                    o._dataItems = [];
-                    o._reset();
-                    o._enable();
-                    o._placeholder();
-                    r.autoBind ? o.dataSource.fetch() : h && (a(h) || (h = [h]), (n.isPlainObject(h[0]) || !r.dataValueField) && (o._retrieveData = !0, o.dataSource.data(h), o.value(o._initialValues)));
-                    i.notify(o)
-                },
-                options: {
-                    name: "MultiSelect",
-                    enabled: !0,
-                    autoBind: !0,
-                    autoClose: !0,
-                    highlightFirst: !0,
-                    dataTextField: "",
-                    dataValueField: "",
-                    filter: "startswith",
-                    ignoreCase: !0,
-                    minLength: 0,
-                    delay: 100,
-                    value: null,
-                    maxSelectedItems: null,
-                    itemTemplate: "",
-                    tagTemplate: "",
-                    placeholder: "",
-                    height: 200,
-                    animation: {}
-                },
-                events: [nt, tt, o, w, "dataBinding", "dataBound"],
-                setDataSource: function(n) {
-                    this.options.dataSource = n;
-                    this._dataSource();
-                    this.options.autoBind && this.dataSource.fetch()
-                },
-                setOptions: function(n) {
-                    f.fn.setOptions.call(this, n);
-                    this._template();
-                    this._accessors();
-                    this._aria(this.tagList.attr(e))
-                },
-                current: function(n) {
-                    return this.currentTag(null), f.fn.current.call(this, n)
-                },
-                currentTag: function(n) {
-                    var i = this;
-                    if (n !== t) i._currentTag && (i._currentTag.removeClass(l).removeAttr(e), i.input.removeAttr("aria-activedescendant")), n && (n.addClass(l).attr(e, i._tagID), i.input.attr("aria-activedescendant", i._tagID)), i._currentTag = n;
-                    else return i._currentTag
-                },
-                dataItems: function() {
-                    return this._dataItems
-                },
-                destroy: function() {
-                    var n = this,
-                        t = n.ns;
-                    n.wrapper.off(t);
-                    n.tagList.off(t);
-                    n.input.off(t);
-                    f.fn.destroy.call(n)
-                },
-                _editable: function(t) {
-                    var i = this,
-                        r = t.disable,
-                        f = t.readonly,
-                        e = i.wrapper.off(u),
-                        s = i.tagList.off(u),
-                        o = i.element.add(i.input.off(u));
-                    if (f || r) r ? e.addClass(k) : e.removeClass(k), o.attr(ot, r).attr(st, f).attr(ut, r).attr(ft, f);
-                    else {
-                        e.removeClass(k).on(bt, i._toggleHover).on("mousedown" + u, function(n) {
-                            var t = n.target.nodeName.toLowerCase() !== "input";
-                            t && n.preventDefault();
-                            n.target.className.indexOf("k-delete") === -1 && (i.input[0] !== g() && t && i.input.focus(), i.options.minLength === 0 && i.open())
-                        });
-                        i.input.on(wt, c(i._keydown, i)).on("paste" + u, c(i._search, i)).on("focus" + u, function() {
-                            i._placeholder(!1)
-                        }).on("blur" + u, function() {
-                            clearTimeout(i._typing);
-                            i._placeholder();
-                            i.close();
-                            i._state === p && (i._state = y);
-                            i.element.blur()
-                        });
-                        o.removeAttr(ot).removeAttr(st).attr(ut, !1).attr(ft, !1);
-                        s.on(ht, v, function() {
-                            n(this).addClass(et)
-                        }).on(ct, v, function() {
-                            n(this).removeClass(et)
-                        }).on(pt, ".k-delete", function(t) {
-                            i._unselect(n(t.target).closest(v));
-                            i._change();
-                            i.close()
-                        })
-                    }
-                },
-                _close: function() {
-                    var n = this;
-                    n.options.autoClose || !n._visibleItems ? n.close() : (n.current(n.options.highlightFirst ? s(n.ul[0]) : null), n.popup._position())
-                },
-                close: function() {
-                    this.popup.close();
-                    this.current(null)
-                },
-                open: function() {
-                    var n = this;
-                    !n.ul[0].firstChild || n._state === y || n._retrieveData ? (n._state = "", n._open = !0, n._retrieveData = !1, n._filterSource()) : n._visibleItems && n._allowSelection() && (n.popup.open(), n.current(n.options.highlightFirst ? s(n.ul[0]) : null))
-                },
-                toggle: function(n) {
-                    n = n !== t ? n : !this.popup.visible();
-                    this[n ? nt : tt]()
-                },
-                refresh: function() {
-                    var n = this,
-                        i = null,
-                        t;
-                    n.trigger("dataBinding");
-                    t = n._render(n.dataSource.view());
-                    n._height(t);
-                    n._setInitialValues && (n._setInitialValues = !1, n.value(n._initialValues));
-                    n._open && (n._open = !1, n.toggle(t));
-                    n.popup.visible() && (n.popup._position(), n.options.highlightFirst && (i = s(n.ul[0])));
-                    n.current(i);
-                    n._touchScroller && n._touchScroller.reset();
-                    n._makeUnselectable();
-                    n._hideBusy();
-                    n.trigger("dataBound")
-                },
-                search: function(n) {
-                    var t = this,
-                        i = t.options,
-                        u = i.ignoreCase,
-                        f = i.filter,
-                        e = i.dataTextField,
-                        r = t.input.val();
-                    i.placeholder === r && (r = "");
-                    clearTimeout(t._typing);
-                    n = typeof n == "string" ? n : r;
-                    n.length >= i.minLength && (t._state = p, t._open = !0, t._filterSource({
-                        value: u ? n.toLowerCase() : n,
-                        field: e,
-                        operator: f,
-                        ignoreCase: u
-                    }))
-                },
-                value: function(i) {
-                    var r = this,
-                        o = n(r.tagList[0].children),
-                        f = o.length,
-                        e, u = 0;
-                    if (i === t) return r._values;
-                    if (!r._fetchItems(i)) {
-                        for (; u < f; u++) r._unselect(o.eq(u));
-                        if (i !== null) {
-                            for (i = a(i) || i instanceof at ? i : [i], u = 0, f = i.length; u < f; u++) e = r._index(i[u]), e > -1 && r._select(e);
-                            r._old = r._values.slice()
-                        }
-                    }
-                },
-                _dataSource: function() {
-                    var n = this,
-                        u = n.element,
-                        r = n.options,
-                        t = r.dataSource || {};
-                    t = a(t) ? {
-                        data: t
-                    } : t;
-                    t.select = u;
-                    t.fields = [{
-                        field: r.dataTextField
-                    }, {
-                        field: r.dataValueField
-                    }];
-                    n.dataSource && n._refreshHandler ? n._unbindDataSource() : (n._refreshHandler = c(n.refresh, n), n._progressHandler = c(n._showBusy, n));
-                    n.dataSource = i.data.DataSource.create(t).bind(o, n._refreshHandler).bind(vt, n._progressHandler)
-                },
-                _fetchItems: function(t) {
-                    var i = this,
-                        r = n.isArray(t) && t.length === 0;
-                    if (!r && t && !i._fetch && !i.ul[0].firstChild) {
-                        i.dataSource.one(o, function() {
-                            i.value(t);
-                            i._fetch = !1
-                        });
-                        return i._fetch = !0, i.dataSource.fetch(), !0
-                    }
-                },
-                _reset: function() {
-                    var t = this,
-                        i = t.element,
-                        r = i.attr("form"),
-                        u = r ? n("#" + r) : i.closest("form");
-                    u[0] && (t._resetHandler = function() {
-                        setTimeout(function() {
-                            t.value(t._initialValues)
-                        })
-                    }, t._form = u.on("reset", t._resetHandler))
-                },
-                _initValue: function() {
-                    var t = this,
-                        n = t.options.value || t.element.val();
-                    n === null ? n = [] : (a(n) || (n = [n]), n = t._mapValues(n));
-                    t._old = t._initialValues = n;
-                    t._setInitialValues = !!n[0]
-                },
-                _mapValues: function(t) {
-                    var i = this;
-                    return t && n.isPlainObject(t[0]) && (t = n.map(t, function(n) {
-                        return i._value(n)
-                    })), t
-                },
-                _change: function() {
-                    var n = this,
-                        t = n.value();
-                    ni(t, n._old) || (n._old = t.slice(), n.trigger(o), n.element.trigger(o))
-                },
-                _click: function(t) {
-                    var i = this,
-                        r = n(t.currentTarget);
-                    if (!t.isDefaultPrevented()) {
-                        if (i.trigger(w, {
-                                item: r
-                            })) {
-                            i._close();
-                            return
-                        }
-                        i._select(r);
-                        i._change();
-                        i._close()
-                    }
-                },
-                _item: function(n, t) {
-                    return n = n[t](), n[0] && !n.is(":visible") && (n = this._item(n, t)), n
-                },
-                _keydown: function(t) {
-                    var u = this,
-                        e = t.keyCode,
-                        f = u._currentTag,
-                        o = u._current,
-                        l = u.input.val(),
-                        a = i.support.isRtl(u.wrapper),
-                        c = u.popup.visible();
-                    if (e === r.DOWN) {
-                        if (t.preventDefault(), !c) {
-                            u.open();
-                            return
-                        }
-                        o = o ? h(o[0], it) : s(u.ul[0]);
-                        o && u.current(n(o))
-                    } else if (e === r.UP) c && (o = o ? h(o[0], rt) : lt(u.ul[0]), u.current(n(o)), u._current[0] || u.close()), t.preventDefault();
-                    else if (e === r.LEFT && !a || e === r.RIGHT && a) l || (f = f ? f.prev() : n(u.tagList[0].lastChild), f[0] && u.currentTag(f));
-                    else if (e === r.RIGHT && !a || e === r.LEFT && a) !l && f && (f = f.next(), u.currentTag(f[0] ? f : null));
-                    else if (e === r.ENTER && c) {
-                        if (o) {
-                            if (u.trigger(w, {
-                                    item: o
-                                })) {
-                                u._close();
-                                return
-                            }
-                            u._select(o)
-                        }
-                        u._change();
-                        u._close();
-                        t.preventDefault()
-                    } else e === r.ESC ? (c ? t.preventDefault() : u.currentTag(null), u.close()) : e === r.HOME ? c ? u.current(s(u.ul[0])) : l || (f = u.tagList[0].firstChild, f && u.currentTag(n(f))) : e === r.END ? c ? u.current(lt(u.ul[0])) : l || (f = u.tagList[0].lastChild, f && u.currentTag(n(f))) : e !== r.DELETE && e !== r.BACKSPACE || l ? (clearTimeout(u._typing), setTimeout(function() {
-                        u._scale()
-                    }), u._search()) : (e !== r.BACKSPACE || f || (f = n(u.tagList[0].lastChild)), f && f[0] && (u._unselect(f), u._change(), u._close()))
-                },
-                _hideBusy: function() {
-                    var n = this;
-                    clearTimeout(n._busy);
-                    n.input.attr("aria-busy", !1);
-                    n._loading.addClass(b);
-                    n._busy = null
-                },
-                _showBusy: function() {
-                    var n = this;
-                    n._busy || (n._busy = setTimeout(function() {
-                        n.input.attr("aria-busy", !0);
-                        n._loading.removeClass(b)
-                    }, 100))
-                },
-                _placeholder: function(n) {
-                    var i = this,
-                        r = i.input,
-                        u = g();
-                    n === t ? (n = !1, r[0] !== u && (n = !i._dataItems[0]), i.wrapper.removeClass(l)) : i.wrapper.addClass(l);
-                    i._prev = "";
-                    r.toggleClass("k-readonly", n).val(n ? i.options.placeholder : "");
-                    r[0] === u && f.selectText(r[0], 0, 0);
-                    i._scale()
-                },
-                _scale: function() {
-                    var n = this,
-                        r = n.wrapper,
-                        u = r.width(),
-                        t = n._span.text(n.input.val()),
-                        i;
-                    r.is(":visible") ? i = t.width() + 25 : (t.appendTo(document.documentElement), u = i = t.width() + 25, t.appendTo(r));
-                    n.input.width(i > u ? u : i)
-                },
-                _option: function(n, r) {
-                    var f = "<option",
-                        e = this._text(n),
-                        u = this._value(n);
-                    return u !== t && (u += "", u.indexOf('"') !== -1 && (u = u.replace(kt, "&quot;")), f += ' value="' + u + '"'), r && (f += ' selected="selected"'), f += ">", e !== t && (f += i.htmlEncode(e)), f + "<\/option>"
-                },
-                _render: function(n) {
-                    for (var t = this, r = n.length, c = t.itemTemplate, e = t._dataItems.slice(0), o = 0, i = 0, s = "", h = "", u, f; i < r; i++) u = n[i], f = t._selected(e, u), h += c(u, i, f), s += t._option(u, f), f || (o += 1);
-                    if (r = e.length, r)
-                        for (i = 0; i < r; i++) s += t._option(e[i], !0);
-                    return t.ul[0].innerHTML = h, t.element.html(s), t._visibleItems = o, o
-                },
-                _selected: function(n, i) {
-                    var o = this,
-                        s = o._text,
-                        h = o._value,
-                        f = h(i),
-                        c = n.length,
-                        e = !1,
-                        r, u = 0;
-                    for (f === t && (f = s(i)); u < c; u++)
-                        if (i = n[u], r = h(i), r === t && (r = s(i)), r !== t && r === f) {
-                            e = !0;
-                            break
-                        }
-                    return e && n.splice(u, 1), e
-                },
-                _search: function() {
-                    var n = this;
-                    n._typing = setTimeout(function() {
-                        var t = n.input.val();
-                        n._prev !== t && (n._prev = t, n.search(t))
-                    }, n.options.delay)
-                },
-                _allowSelection: function() {
-                    var n = this.options.maxSelectedItems;
-                    return n === null || n > this._values.length
-                },
-                _select: function(n) {
-                    var t = this,
-                        u = t._values,
-                        r, i;
-                    t._allowSelection() && (isNaN(n) ? i = n.hide().data("idx") : (i = n, t.ul[0].children[i].style.display = "none"), t.element[0].children[i].selected = !0, r = t.dataSource.view()[i], t.tagList.append(t.tagTemplate(r)), t._dataItems.push(r), u.push(t._dataValue(r)), t._visibleItems -= 1, t.currentTag(null), t._placeholder(), t._height(t._visibleItems), t._state === p && (t._state = y))
-                },
-                _unselect: function(t) {
-                    var i = this,
-                        r = t.index(),
-                        o, u, f, e, s;
-                    if (t.remove(), i.currentTag(null), i._values.splice(r, 1), o = i._dataItems.splice(r, 1)[0], u = i._dataValue(o), r = i._index(u), r !== -1) n(i.ul[0].children[r]).show(), i.element[0].children[r].selected = !1, i._visibleItems += 1, i._height(i._visibleItems);
-                    else
-                        for (r = i.dataSource.view().length, f = i.element[0].children, s = f.length; r < s; r++)
-                            if (e = f[r], e.value == u) {
-                                e.selected = !1;
-                                break
-                            }
-                    i._placeholder()
-                },
-                _template: function() {
-                    var t = this,
-                        n = t.options,
-                        r = n.itemTemplate,
-                        u = n.tagTemplate,
-                        e = n.dataSource,
-                        f;
-                    t.element[0].length && !e && (n.dataTextField = n.dataTextField || "text", n.dataValueField = n.dataValueField || "value");
-                    f = i.template("#:" + i.expr(n.dataTextField, "data") + "#", {
-                        useWithBlock: !1
-                    });
-                    r = r ? i.template(r) : f;
-                    u = u ? i.template(u) : f;
-                    t.itemTemplate = function(n, t, i) {
-                        return '<li tabindex="-1" role="option" data-idx="' + t + '" unselectable="on" class="k-item"' + (i ? yt : "") + ">" + r(n) + "<\/li>"
-                    };
-                    t.tagTemplate = function(n) {
-                        return '<li class="k-button" unselectable="on"><span unselectable="on">' + u(n) + '<\/span><span unselectable="on" class="k-icon k-delete">delete<\/span><\/li>'
-                    }
-                },
-                _input: function() {
-                    var t = this,
-                        r = t.element[0].accessKey,
-                        i = t._innerWrapper.children("input.k-input");
-                    i[0] || (i = n('<input class="k-input" style="width: 25px" />').appendTo(t._innerWrapper));
-                    t.element.removeAttr("accesskey");
-                    t._focused = t.input = i.attr({
-                        accesskey: r,
-                        role: "listbox",
-                        "aria-expanded": !1
-                    })
-                },
-                _tagList: function() {
-                    var t = this,
-                        i = t._innerWrapper.children("ul");
-                    i[0] || (i = n('<ul role="listbox" unselectable="on" class="k-reset"/>').appendTo(t._innerWrapper));
-                    t.tagList = i
-                },
-                _loader: function() {
-                    this._loading = n('<span class="k-icon k-loading ' + b + '"><\/span>').insertAfter(this.input)
-                },
-                _textContainer: function() {
-                    var t = i.getComputedStyles(this.input[0], dt);
-                    t.position = "absolute";
-                    t.visibility = "hidden";
-                    t.top = -3333;
-                    t.left = -3333;
-                    this._span = n("<span/>").css(t).appendTo(this.wrapper)
-                },
-                _wrapper: function() {
-                    var r = this,
-                        t = r.element,
-                        i = t.parent("span.k-multiselect");
-                    i[0] || (i = t.wrap('<div class="k-widget k-multiselect k-header" unselectable="on" />').parent(), i[0].style.cssText = t[0].style.cssText, n('<div class="k-multiselect-wrap k-floatwrap" unselectable="on" />').insertBefore(t));
-                    r.wrapper = i.addClass(t[0].className).css("display", "");
-                    r._innerWrapper = n(i[0].firstChild)
-                }
-            });
-        d.plugin(gt)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "columnmenu",
-        name: "Column Menu",
-        category: "framework",
-        depends: ["popup", "filtermenu", "menu"],
-        advanced: !0
-    }),
-    function(n, t) {
-        function g(t) {
-            return n.trim(t).replace(/&nbsp;/gi, "")
-        }
-        var i = window.kendo,
-            a = i.ui,
-            e = n.proxy,
-            d = n.extend,
-            s = n.grep,
-            v = n.map,
-            h = n.inArray,
-            u = "k-state-selected",
-            c = "asc",
-            y = "desc",
-            p = "change",
-            w = "init",
-            o = "select",
-            l = "kendoPopup",
-            b = "kendoFilterMenu",
-            k = "kendoMenu",
-            r = ".kendoColumnMenu",
-            f = a.Widget,
-            nt = f.extend({
-                init: function(t, u) {
-                    var o = this,
-                        s;
-                    f.fn.init.call(o, t, u);
-                    t = o.element;
-                    u = o.options;
-                    o.owner = u.owner;
-                    o.dataSource = u.dataSource;
-                    o.field = t.attr(i.attr("field"));
-                    s = t.find(".k-header-column-menu");
-                    s[0] || (s = t.addClass("k-with-icon").prepend('<a class="k-header-column-menu" href="#"><span class="k-icon k-i-arrowhead-s"/><\/a>').find(".k-header-column-menu"));
-                    o.link = s.attr("tabindex", -1).on("click" + r, e(o._click, o));
-                    o.wrapper = n('<div class="k-column-menu"/>')
-                },
-                _init: function() {
-                    var n = this;
-                    n.pane = n.options.pane;
-                    n.pane && (n._isMobile = !0);
-                    n._isMobile ? n._createMobileMenu() : n._createMenu();
-                    n._sort();
-                    n._columns();
-                    n._filter();
-                    n.trigger(w, {
-                        field: n.field,
-                        container: n.wrapper
-                    })
-                },
-                events: [w],
-                options: {
-                    name: "ColumnMenu",
-                    messages: {
-                        sortAscending: "Sort Ascending",
-                        sortDescending: "Sort Descending",
-                        filter: "Filter",
-                        columns: "Columns",
-                        done: "Done",
-                        settings: "Column Settings"
-                    },
-                    filter: "",
-                    columns: !0,
-                    sortable: !0,
-                    filterable: !0,
-                    animations: {
-                        left: "slide"
-                    }
-                },
-                _createMenu: function() {
-                    var n = this,
-                        t = n.options;
-                    n.wrapper.html(i.template(tt)({
-                        ns: i.ns,
-                        messages: t.messages,
-                        sortable: t.sortable,
-                        filterable: t.filterable,
-                        columns: n._ownerColumns(),
-                        showColumns: t.columns
-                    }));
-                    n.popup = n.wrapper[l]({
-                        anchor: n.link,
-                        open: e(n._open, n),
-                        activate: e(n._activate, n),
-                        close: n.options.closeCallback
-                    }).data(l);
-                    n.menu = n.wrapper.children()[k]({
-                        orientation: "vertical",
-                        closeOnClick: !1
-                    }).data(k)
-                },
-                _createMobileMenu: function() {
-                    var n = this,
-                        t = n.options,
-                        r = i.template(it)({
-                            ns: i.ns,
-                            field: n.field,
-                            messages: t.messages,
-                            sortable: t.sortable,
-                            filterable: t.filterable,
-                            columns: n._ownerColumns(),
-                            showColumns: t.columns
-                        });
-                    n.view = n.pane.append(r);
-                    n.wrapper = n.view.element.find(".k-column-menu");
-                    n.menu = new rt(n.wrapper.children(), {
-                        pane: n.pane
-                    });
-                    n.view.element.on("click", ".k-done", function(t) {
-                        n.close();
-                        t.preventDefault()
-                    })
-                },
-                destroy: function() {
-                    var n = this;
-                    f.fn.destroy.call(n);
-                    n.filterMenu && n.filterMenu.destroy();
-                    n._refreshHandler && n.dataSource.unbind(p, n._refreshHandler);
-                    n.options.columns && n.owner && (n.owner.unbind("columnShow", n._updateColumnsMenuHandler), n.owner.unbind("columnHide", n._updateColumnsMenuHandler));
-                    n.menu && (n.menu.element.off(r), n.menu.destroy());
-                    n.wrapper.off(r);
-                    n.popup && n.popup.destroy();
-                    n.view && n.view.purge();
-                    n.link.off(r)
-                },
-                close: function() {
-                    this.menu.close();
-                    this.popup && (this.popup.close(), this.popup.element.off("keydown" + r))
-                },
-                _click: function(n) {
-                    n.preventDefault();
-                    n.stopPropagation();
-                    var t = this.options;
-                    t.filter && this.element.is(!t.filter) || (this.popup || this.pane || this._init(), this._isMobile ? this.pane.navigate(this.view, this.options.animations.left) : this.popup.toggle())
-                },
-                _open: function() {
-                    var t = this;
-                    n(".k-column-menu").not(t.wrapper).each(function() {
-                        n(this).data(l).close()
-                    });
-                    t.popup.element.on("keydown" + r, function(n) {
-                        n.keyCode == i.keys.ESC && t.close()
-                    })
-                },
-                _activate: function() {
-                    this.menu.element.focus()
-                },
-                _ownerColumns: function() {
-                    var n = this.owner.columns,
-                        t = s(n, function(n) {
-                            var t = !0,
-                                i = g(n.title || "");
-                            return n.menu !== !1 && (n.field || i.length) || (t = !1), t
-                        });
-                    return v(t, function(t) {
-                        return {
-                            originalField: t.field,
-                            field: t.field || t.title,
-                            title: t.title || t.field,
-                            hidden: t.hidden,
-                            index: h(t, n)
-                        }
-                    })
-                },
-                _sort: function() {
-                    var t = this;
-                    t.options.sortable && (t.refresh(), t._refreshHandler = e(t.refresh, t), t.dataSource.bind(p, t._refreshHandler), t.menu.bind(o, function(i) {
-                        var f = n(i.item),
-                            r;
-                        (f.hasClass("k-sort-asc") ? r = c : f.hasClass("k-sort-desc") && (r = y), r) && (f.parent().find(".k-sort-" + (r == c ? y : c)).removeClass(u), t._sortDataSource(f, r), t.close())
-                    }))
-                },
-                _sortDataSource: function(n, i) {
-                    var f = this,
-                        o = f.options.sortable,
-                        s = f.dataSource,
-                        e, h, r = s.sort() || [];
-                    if (n.hasClass(u) && o && o.allowUnsort !== !1 ? (n.removeClass(u), i = t) : n.addClass(u), o === !0 || o.mode === "single") r = [{
-                        field: f.field,
-                        dir: i
-                    }];
-                    else {
-                        for (e = 0, h = r.length; e < h; e++)
-                            if (r[e].field === f.field) {
-                                r.splice(e, 1);
-                                break
-                            }
-                        r.push({
-                            field: f.field,
-                            dir: i
-                        })
-                    }
-                    s.sort(r)
-                },
-                _columns: function() {
-                    var t = this;
-                    t.options.columns && (t._updateColumnsMenu(), t._updateColumnsMenuHandler = e(t._updateColumnsMenu, t), t.owner.bind(["columnHide", "columnShow"], t._updateColumnsMenuHandler), t.menu.bind(o, function(r) {
-                        var c = n(r.item),
-                            u, f, e, l = t.owner.columns,
-                            o;
-                        (t._isMobile && r.preventDefault(), c.parent().closest("li.k-columns-item")[0]) && ((u = c.find(":checkbox"), u.attr("disabled")) || (o = u.attr(i.attr("field")), e = s(l, function(n) {
-                            return n.field == o || n.title == o
-                        })[0], f = h(e, l), e.hidden === !0 ? t.owner.showColumn(f) : t.owner.hideColumn(f)))
-                    }))
-                },
-                _updateColumnsMenu: function() {
-                    var r = i.attr("field"),
-                        t = s(this._ownerColumns(), function(n) {
-                            return !n.hidden
-                        }),
-                        u = s(t, function(n) {
-                            return n.originalField
-                        }).length;
-                    t = v(t, function(n) {
-                        return n.field
-                    });
-                    this.wrapper.find(".k-columns-item input[" + r + "]").prop("checked", !1).filter(function() {
-                        return h(n(this).attr(r), t) > -1
-                    }).prop("checked", !0).prop("disabled", u == 1)
-                },
-                _filter: function() {
-                    var t = this,
-                        i = t.options;
-                    i.filterable !== !1 && (t.filterMenu = t.wrapper.find(".k-filterable")[b](d(!0, {}, {
-                        appendToElement: !0,
-                        dataSource: i.dataSource,
-                        values: i.values,
-                        field: t.field
-                    }, i.filterable)).data(b), t._isMobile && t.menu.bind(o, function(i) {
-                        var r = n(i.item);
-                        r.hasClass("k-filter-item") && t.pane.navigate(t.filterMenu.view, t.options.animations.left)
-                    }))
-                },
-                refresh: function() {
-                    var n = this,
-                        r = n.options.dataSource.sort() || [],
-                        i, e = n.field,
-                        t, f;
-                    for (n.wrapper.find(".k-sort-asc, .k-sort-desc").removeClass(u), t = 0, f = r.length; t < f; t++) i = r[t], e == i.field && n.wrapper.find(".k-sort-" + i.dir).addClass(u)
-                }
-            }),
-            tt = '<ul>#if(sortable){#<li class="k-item k-sort-asc"><span class="k-link"><span class="k-sprite k-i-sort-asc"><\/span>${messages.sortAscending}<\/span><\/li><li class="k-item k-sort-desc"><span class="k-link"><span class="k-sprite k-i-sort-desc"><\/span>${messages.sortDescending}<\/span><\/li>#if(showColumns || filterable){#<li class="k-separator"><\/li>#}##}##if(showColumns){#<li class="k-item k-columns-item"><span class="k-link"><span class="k-sprite k-i-columns"><\/span>${messages.columns}<\/span><ul>#for (var idx = 0; idx < columns.length; idx++) {#<li><input type="checkbox" data-#=ns#field="#=columns[idx].field.replace(/"/g,"&\\#34;")#" data-#=ns#index="#=columns[idx].index#"/>#=columns[idx].title#<\/li>#}#<\/ul><\/li>#if(filterable){#<li class="k-separator"><\/li>#}##}##if(filterable){#<li class="k-item k-filter-item"><span class="k-link"><span class="k-sprite k-filter"><\/span>${messages.filter}<\/span><ul><li><div class="k-filterable"><\/div><\/li><\/ul><\/li>#}#<\/ul>',
-            it = '<div data-#=ns#role="view" data-#=ns#init-widgets="false" class="k-grid-column-menu"><div data-#=ns#role="header" class="k-header">${messages.settings}<button class="k-button k-done">#=messages.done#<\/button><\/div><div class="k-column-menu k-mobile-list"><ul><li><span class="k-link">${field}<\/span><ul>#if(sortable){#<li class="k-item k-sort-asc"><span class="k-link"><span class="k-sprite k-i-sort-asc"><\/span>${messages.sortAscending}<\/span><\/li><li class="k-item k-sort-desc"><span class="k-link"><span class="k-sprite k-i-sort-desc"><\/span>${messages.sortDescending}<\/span><\/li>#}##if(filterable){#<li class="k-item k-filter-item"><span class="k-link k-filterable"><span class="k-sprite k-filter"><\/span>${messages.filter}<\/span><\/li>#}#<\/ul><\/li>#if(showColumns){#<li class="k-columns-item"><span class="k-link">${messages.columns}<\/span><ul>#for (var idx = 0; idx < columns.length; idx++) {#<li class="k-item"><label class="k-label"><input type="checkbox" class="k-check" data-#=ns#field="#=columns[idx].field.replace(/"/g,"&\\#34;")#" data-#=ns#index="#=columns[idx].index#"/>#=columns[idx].title#<\/label><\/li>#}#<\/ul><\/li>#}#<\/ul><\/div><\/div>',
-            rt = f.extend({
-                init: function(n, t) {
-                    f.fn.init.call(this, n, t);
-                    this.element.on("click" + r, "li:not(.k-separator)", "_click")
-                },
-                events: [o],
-                _click: function(n) {
-                    this.trigger(o, {
-                        item: n.currentTarget
-                    }) && n.preventDefault()
-                },
-                close: function() {
-                    this.options.pane.navigate("")
-                },
-                destroy: function() {
-                    f.fn.destroy.call(this);
-                    this.element.off(r)
-                }
-            });
-        a.plugin(nt)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "grid",
-        name: "Grid",
-        category: "web",
-        description: "The Grid widget displays tabular data and offers rich support for interacting with data,including paging, sorting, grouping, and selection.",
-        depends: ["data"],
-        features: [{
-            id: "grid-editing",
-            name: "Editing",
-            description: "Support for record editing",
-            depends: ["editable", "window"]
-        }, {
-            id: "grid-filtering",
-            name: "Filtering",
-            description: "Support for record filtering",
-            depends: ["filtermenu"]
-        }, {
-            id: "grid-columnmenu",
-            name: "Column menu",
-            description: "Support for header column menu",
-            depends: ["columnmenu"]
-        }, {
-            id: "grid-grouping",
-            name: "Grouping",
-            description: "Support for grid grouping",
-            depends: ["groupable"]
-        }, {
-            id: "grid-paging",
-            name: "Paging",
-            description: "Suppot for grid paging",
-            depends: ["pager"]
-        }, {
-            id: "grid-selection",
-            name: "Selection",
-            description: "Support for row selection",
-            depends: ["selectable"]
-        }, {
-            id: "grid-sorting",
-            name: "Sorting",
-            description: "Support for grid sorting",
-            depends: ["sortable"]
-        }, {
-            id: "grid-column-reorder",
-            name: "Column reordering",
-            description: "Support for column reordering",
-            depends: ["reorderable"]
-        }, {
-            id: "grid-column-resize",
-            name: "Column resizing",
-            description: "Support for column resizing",
-            depends: ["resizable"]
-        }, {
-            id: "grid-mobile",
-            name: "Grid adaptive rendering",
-            description: "Support for adaptive rendering",
-            depends: ["mobile.actionsheet", "mobile.pane"]
-        }]
-    }),
-    function(n, t) {
-        function pt(n) {
-            return new Array(n + 1).join('<td class="k-group-cell">&nbsp;<\/td>')
-        }
-
-        function lt(n) {
-            var t, i = " ";
-            if (n) {
-                if (typeof n === c) return n;
-                for (t in n) i += t + '="' + n[t] + '"'
-            }
-            return i
-        }
-
-        function pr(t) {
-            var i = 0;
-            return n("> .k-grouping-header, > .k-grid-toolbar", t).each(function() {
-                i += this.offsetHeight
-            }), i
-        }
-
-        function ui(t, i) {
-            n("th, th .k-grid-filter, th .k-link", t).add(document.body).css("cursor", i)
-        }
-
-        function fi(n) {
-            var t, i, r = {},
-                u = {};
-            if (!at(n))
-                for (k(n) || (n = [n]), t = 0, i = n.length; t < i; t++) r[n[t].aggregate] = 0, u[n[t].field] = r;
-            return u
-        }
-
-        function et(n, t, i) {
-            var r = n.eq(t),
-                u = n.eq(i);
-            r[t > i ? "insertBefore" : "insertAfter"](u)
-        }
-
-        function wr(n, t, i) {
-            var e, c, u, s;
-            for (i = k(i) ? i : [i], e = 0, c = i.length; e < c; e++)
-                if (u = i[e], o(u) && u.click) {
-                    s = u.name || u.text;
-                    t.on(h + r, "a.k-grid-" + (s || "").replace(/\s/g, ""), {
-                        commandName: s
-                    }, f(u.click, n))
-                }
-        }
-
-        function tt(n) {
-            return b(n, function(n) {
-                return !n.hidden
-            })
-        }
-
-        function ot(n) {
-            n = n || {};
-            var t = n.style;
-            return t ? (t = t.replace(/((.*)?display)(.*)?:([^;]*)/i, "$1:none"), t === n.style && (t = t.replace(/(.*)?/i, "display:none;$1"))) : t = "display:none", u({}, n, {
-                style: t
-            })
-        }
-
-        function ei(n) {
-            n = n || {};
-            var t = n.style;
-            return t && (n.style = t.replace(/(display\s*:\s*none\s*;?)*/ig, "")), n
-        }
-
-        function ir(t, r, u, f) {
-            var o = t.find(">colgroup"),
-                s, h = bt(r, function(n) {
-                    return (s = n.width, s && parseInt(s, 10) !== 0) ? i.format('<col style="width:{0}"/>', typeof s === c ? s : s + "px") : "<col />"
-                });
-            (u || o.find(".k-hierarchy-col").length) && h.splice(0, 0, '<col class="k-hierarchy-col" />');
-            o.length && o.remove();
-            o = n(new Array(f + 1).join('<col class="k-group-col">') + h.join(""));
-            o.is("colgroup") || (o = n("<colgroup/>").append(o));
-            t.prepend(o);
-            e.msie && e.version == 8 && (t.css("display", "inline-table"), window.setTimeout(function() {
-                t.css("display", "")
-            }, 1))
-        }
-
-        function rr(n) {
-            for (var r = {}, i, t = 0, u = n.length; t < u; t++) i = n[t], r[i.value] = i.text;
-            return r
-        }
-
-        function br(n, t, r) {
-            var f = r && r.length && o(r[0]) && "value" in r[0],
-                u = f ? rr(r)[n] : n;
-            return u = u != null ? u : "", t ? i.format(t, u) : u
-        }
-
-        function st(n, t, i) {
-            for (var u = 0, f, r = n[u]; r;) {
-                if (f = i ? !0 : r.style.display !== "none", f && !ar.test(r.className) && --t < 0) {
-                    r.style.display = i ? "" : "none";
-                    break
-                }
-                r = n[++u]
-            }
-        }
-
-        function oi(n, t) {
-            var r, u, i;
-            if (typeof n === c && n === t || o(n) && n.name === t) return n;
-            if (k(n))
-                for (r = 0, u = n.length; r < u; r++)
-                    if (i = n[r], typeof i === c && i === t || i.name === t) return i;
-            return null
-        }
-
-        function l(t, i) {
-            var u = e.msie,
-                r, f, o;
-            if (i === !0) {
-                if (t = n(t), r = u && t.parent().is(".k-grid-content,.k-grid-header-wrap"), r && (f = t.parent().scrollTop(), o = t.parent().scrollLeft()), u) try {
-                    t[0].setActive()
-                } catch (s) {
-                    t[0].focus()
-                } else t[0].focus();
-                r && (t.parent().scrollTop(f), t.parent().scrollLeft(o))
-            } else n(t).one("focusin", function(n) {
-                n.preventDefault()
-            }).focus()
-        }
-
-        function dr(t) {
-            var r = n(t.currentTarget),
-                f = r.is("th"),
-                u = r.closest("table")[0];
-            i.support.touch || (u === this.table[0] || u === this.thead.parent()[0]) && (this.current(r), (f || !n(t.target).is(":button,a,:input,a>.k-icon,textarea,span.k-icon,span.k-link,.k-input,.k-multiselect-wrap")) && setTimeout(function() {
-                yr && n(i._activeElement()).hasClass("k-widget") || l(u, !0)
-            }), f && t.preventDefault())
-        }
-        var i = window.kendo,
-            it = i.ui,
-            ur = i.data.DataSource,
-            fr = it.Groupable,
-            er = i.support.tbodyInnerHtml,
-            rt = i._activeElement,
-            w = it.Widget,
-            s = i.keys,
-            o = n.isPlainObject,
-            u = n.extend,
-            bt = n.map,
-            b = n.grep,
-            k = n.isArray,
-            d = n.inArray,
-            f = n.proxy,
-            or = i.isFunction,
-            at = n.isEmptyObject,
-            y = Math,
-            kt = "progress",
-            dt = "error",
-            g = ":not(.k-group-cell):not(.k-hierarchy-cell):visible",
-            sr = "tbody>tr:not(.k-grouping-row):not(.k-detail-row):not(.k-group-footer) > td:not(.k-group-cell):not(.k-hierarchy-cell)",
-            ut = "tr:not(.k-footer-template):visible",
-            v = ":not(.k-group-cell):not(.k-hierarchy-cell):visible",
-            ft = ut + ":first>" + v + ":first",
-            vt = "th.k-header:not(.k-group-cell,.k-hierarchy-cell)",
-            r = ".kendoGrid",
-            yt = "edit",
-            gt = "save",
-            si = "remove",
-            ni = "detailInit",
-            hi = "filterMenuInit",
-            ci = "columnMenuInit",
-            a = "change",
-            li = "columnHide",
-            ai = "columnShow",
-            vi = "saveChanges",
-            yi = "dataBound",
-            pi = "detailExpand",
-            wi = "detailCollapse",
-            ht = "k-state-focused",
-            bi = "k-state-selected",
-            ki = "columnResize",
-            di = "columnReorder",
-            h = "click",
-            ti = "height",
-            nt = "tabIndex",
-            ct = "function",
-            c = "string",
-            gi = "Are you sure you want to delete this record?",
-            hr = "Delete",
-            cr = "Cancel",
-            lr = /(\}|\#)/ig,
-            ii = /#/ig,
-            nr = "[\\x20\\t\\r\\n\\f]",
-            ar = new RegExp("(^|" + nr + ")(k-group-cell|k-hierarchy-cell)(" + nr + "|$)"),
-            vr = '<a class="k-button k-button-icontext #=className#" #=attr# href="\\#"><span class="#=iconClass# #=imageClass#"><\/span>#=text#<\/a>',
-            p = !1,
-            e = i.support.browser,
-            ri = e.msie && e.version == 7,
-            yr = e.msie && e.version == 8,
-            tr = w.extend({
-                init: function(n, t) {
-                    var i = this;
-                    w.fn.init.call(i, n, t);
-                    i._refreshHandler = f(i.refresh, i);
-                    i.setDataSource(t.dataSource);
-                    i.wrap()
-                },
-                setDataSource: function(n) {
-                    var t = this;
-                    t.dataSource && t.dataSource.unbind(a, t._refreshHandler);
-                    t.dataSource = n;
-                    t.dataSource.bind(a, t._refreshHandler)
-                },
-                options: {
-                    name: "VirtualScrollable",
-                    itemHeight: n.noop
-                },
-                destroy: function() {
-                    var n = this;
-                    w.fn.destroy.call(n);
-                    n.dataSource.unbind(a, n._refreshHandler);
-                    n.wrapper.add(n.verticalScrollbar).off(r);
-                    n.drag && n.drag.destroy()
-                },
-                wrap: function() {
-                    var t = this,
-                        o = i.support.scrollbar() + 1,
-                        u = t.element,
-                        e;
-                    u.css({
-                        width: "auto",
-                        overflow: "hidden"
-                    }).css(p ? "padding-left" : "padding-right", o);
-                    t.content = u.children().first();
-                    e = t.wrapper = t.content.wrap('<div class="k-virtual-scrollable-wrap"/>').parent().bind("DOMMouseScroll" + r + " mousewheel" + r, f(t._wheelScroll, t));
-                    i.support.kineticScrollNeeded && (t.drag = new i.UserEvents(t.wrapper, {
-                        global: !0,
-                        move: function(n) {
-                            t.verticalScrollbar.scrollTop(t.verticalScrollbar.scrollTop() - n.y.delta);
-                            e.scrollLeft(e.scrollLeft() - n.x.delta);
-                            n.preventDefault()
-                        }
-                    }));
-                    t.verticalScrollbar = n('<div class="k-scrollbar k-scrollbar-vertical" />').css({
-                        width: o
-                    }).appendTo(u).bind("scroll" + r, f(t._scroll, t))
-                },
-                _wheelScroll: function(n) {
-                    var u = this,
-                        e = u.verticalScrollbar.scrollTop(),
-                        i = n.originalEvent,
-                        f = i.wheelDeltaY,
-                        r;
-                    i.wheelDelta ? (f === t || f) && (r = i.wheelDelta) : i.detail && i.axis === i.VERTICAL_AXIS && (r = -i.detail * 10);
-                    r && (n.preventDefault(), u.verticalScrollbar.scrollTop(e + -r))
-                },
-                _scroll: function(n) {
-                    var t = this,
-                        i = n.currentTarget.scrollTop,
-                        f = t.dataSource,
-                        r = t.itemHeight,
-                        e = f.skip() || 0,
-                        o = t._rangeStart || e,
-                        s = t.element.innerHeight(),
-                        h = !!(t._scrollbarTop && t._scrollbarTop > i),
-                        u = y.max(y.floor(i / r), 0),
-                        c = y.max(u + y.floor(s / r), 0);
-                    t._scrollTop = i - o * r;
-                    t._scrollbarTop = i;
-                    t._fetch(u, c, h) || (t.wrapper[0].scrollTop = t._scrollTop)
-                },
-                _fetch: function(n, t, i) {
-                    var u = this,
-                        e = u.dataSource,
-                        h = u.itemHeight,
-                        r = e.take(),
-                        f = u._rangeStart || e.skip() || 0,
-                        o = y.floor(n / r) * r,
-                        s = !1,
-                        c = .33;
-                    return n < f ? (s = !0, f = y.max(0, t - r), u._scrollTop = (n - f) * h, u._page(f, r)) : t >= f + r && !i ? (s = !0, f = n, u._scrollTop = h, u._page(f, r)) : u._fetching || (n < o + r - r * c && n > r && e.prefetch(o - r, r), t > o + r * c && e.prefetch(o + r, r)), s
-                },
-                _page: function(n, t) {
-                    var r = this,
-                        u = r.dataSource;
-                    clearTimeout(r._timeout);
-                    r._fetching = !0;
-                    r._rangeStart = n;
-                    u.inRange(n, t) ? u.range(n, t) : (i.ui.progress(r.wrapper.parent(), !0), r._timeout = setTimeout(function() {
-                        u.range(n, t)
-                    }, 100))
-                },
-                refresh: function() {
-                    var n = this,
-                        u = "",
-                        t = 25e4,
-                        o = n.dataSource,
-                        c = n._rangeStart,
-                        l = i.support.kineticScrollNeeded ? 0 : i.support.scrollbar(),
-                        f = n.wrapper[0],
-                        r, e, s, h;
-                    for (i.ui.progress(n.wrapper.parent(), !1), clearTimeout(n._timeout), s = n.itemHeight = n.options.itemHeight() || 0, h = f.scrollWidth > f.offsetWidth ? l : 0, r = o.total() * s + h, e = 0; e < y.floor(r / t); e++) u += '<div style="width:1px;height:' + t + 'px"><\/div>';
-                    r % t && (u += '<div style="width:1px;height:' + r % t + 'px"><\/div>');
-                    n.verticalScrollbar.html(u);
-                    f.scrollTop = n._scrollTop;
-                    n.drag && n.drag.cancel();
-                    c && !n._fetching && (n._rangeStart = o.skip());
-                    n._fetching = !1
-                }
-            }),
-            wt = {
-                create: {
-                    text: "Add new record",
-                    imageClass: "k-add",
-                    className: "k-grid-add",
-                    iconClass: "k-icon"
-                },
-                cancel: {
-                    text: "Cancel changes",
-                    imageClass: "k-cancel",
-                    className: "k-grid-cancel-changes",
-                    iconClass: "k-icon"
-                },
-                save: {
-                    text: "Save changes",
-                    imageClass: "k-update",
-                    className: "k-grid-save-changes",
-                    iconClass: "k-icon"
-                },
-                destroy: {
-                    text: "Delete",
-                    imageClass: "k-delete",
-                    className: "k-grid-delete",
-                    iconClass: "k-icon"
-                },
-                edit: {
-                    text: "Edit",
-                    imageClass: "k-edit",
-                    className: "k-grid-edit",
-                    iconClass: "k-icon"
-                },
-                update: {
-                    text: "Update",
-                    imageClass: "k-update",
-                    className: "k-grid-update",
-                    iconClass: "k-icon"
-                },
-                canceledit: {
-                    text: "Cancel",
-                    imageClass: "k-cancel",
-                    className: "k-grid-cancel",
-                    iconClass: "k-icon"
-                }
-            },
-            kr = w.extend({
-                init: function(n, t) {
-                    var r = this;
-                    t = k(t) ? {
-                        dataSource: t
-                    } : t;
-                    w.fn.init.call(r, n, t);
-                    p = i.support.isRtl(n);
-                    r._element();
-                    r._aria();
-                    r._columns(r.options.columns);
-                    r._dataSource();
-                    r._tbody();
-                    r._pageable();
-                    r._thead();
-                    r._groupable();
-                    r._toolbar();
-                    r._setContentHeight();
-                    r._templates();
-                    r._navigatable();
-                    r._selectable();
-                    r._details();
-                    r._editable();
-                    r._attachCustomCommandsEvent();
-                    r.options.autoBind ? r.dataSource.fetch() : r._footer();
-                    i.notify(r)
-                },
-                events: [a, "dataBinding", "cancel", yi, pi, wi, ni, hi, ci, yt, gt, si, vi, ki, di, ai, li],
-                setDataSource: function(n) {
-                    var t = this;
-                    t.options.dataSource = n;
-                    t._dataSource();
-                    t._pageable();
-                    t.options.groupable && t._groupable();
-                    t._thead();
-                    t.virtualScrollable && t.virtualScrollable.setDataSource(t.options.dataSource);
-                    t.options.autoBind && n.fetch()
-                },
-                options: {
-                    name: "Grid",
-                    columns: [],
-                    toolbar: null,
-                    autoBind: !0,
-                    filterable: !1,
-                    scrollable: !0,
-                    sortable: !1,
-                    selectable: !1,
-                    navigatable: !1,
-                    pageable: !1,
-                    editable: !1,
-                    groupable: !1,
-                    rowTemplate: "",
-                    altRowTemplate: "",
-                    dataSource: {},
-                    height: null,
-                    resizable: !1,
-                    reorderable: !1,
-                    columnMenu: !1,
-                    detailTemplate: null,
-                    columnResizeHandleWidth: 3,
-                    mobile: ""
-                },
-                destroy: function() {
-                    var t = this,
-                        u;
-                    w.fn.destroy.call(t);
-                    t.pager && t.pager.destroy();
-                    t.groupable && t.groupable.destroy();
-                    t.options.reorderable && t.wrapper.data("kendoReorderable").destroy();
-                    t.selectable && t.selectable.destroy();
-                    t.resizable && (t.resizable.destroy(), t._resizeUserEvents && (t._resizeHandleDocumentClickHandler && n(document).off("click", t._resizeHandleDocumentClickHandler), t._resizeUserEvents.destroy()));
-                    t.virtualScrollable && t.virtualScrollable.destroy();
-                    t._destroyColumnAttachments();
-                    t._destroyEditable();
-                    t.dataSource.unbind(a, t._refreshHandler).unbind(kt, t._progressHandler).unbind(dt, t._errorHandler);
-                    u = t.element.add(t.wrapper).add(t.table).add(t.thead).add(t.wrapper.find(">.k-grid-toolbar"));
-                    t.content && (u = u.add(t.content).add(t.content.find(">.k-virtual-scrollable-wrap")));
-                    t.pane && t.pane.destroy();
-                    u.off(r);
-                    i.destroy(t.wrapper)
-                },
-                setOptions: function(n) {
-                    var t = this;
-                    w.fn.setOptions.call(this, n);
-                    t._templates()
-                },
-                items: function() {
-                    return this.tbody.children(":not(.k-grouping-row,.k-detail-row,.k-group-footer)")
-                },
-                _destroyColumnAttachments: function() {
-                    var t = this;
-                    t.resizeHandle = null;
-                    t.thead.find("th").each(function() {
-                        var t = n(this),
-                            i = t.data("kendoFilterMenu"),
-                            r = t.data("kendoSortable"),
-                            u = t.data("kendoColumnMenu");
-                        i && i.destroy();
-                        r && r.destroy();
-                        u && u.destroy()
-                    })
-                },
-                _attachCustomCommandsEvent: function() {
-                    for (var t = this, r = t.columns || [], i, n = 0, u = r.length; n < u; n++) i = r[n].command, i && wr(t, t.wrapper, i)
-                },
-                _aria: function() {
-                    var n = this.element.attr("id") || "aria";
-                    n && (this._cellId = n + "_active_cell")
-                },
-                _element: function() {
-                    var t = this,
-                        i = t.element;
-                    i.is("table") || (i = t.options.scrollable ? t.element.find("> .k-grid-content > table") : t.element.children("table"), i.length || (i = n("<table />").appendTo(t.element)));
-                    ri && i.attr("cellspacing", 0);
-                    t.table = i.attr("role", t._hasDetails() ? "treegrid" : "grid");
-                    t._wrapper()
-                },
-                _createResizeHandle: function(t, i) {
-                    var u = this,
-                        s = u.options.columnResizeHandleWidth,
-                        h = u.options.scrollable,
-                        f = u.resizeHandle,
-                        o;
-                    if (f || (f = u.resizeHandle = n('<div class="k-resize-handle"><div class="k-resize-handle-inner"><\/div><\/div>'), t.append(f)), p) {
-                        var r = i.closest(".k-grid-header-wrap"),
-                            c = e.msie ? r.scrollLeft() : 0,
-                            l = e.webkit ? r[0].scrollWidth - r[0].offsetWidth - r.scrollLeft() : 0,
-                            a = e.mozilla ? r[0].scrollWidth - r[0].offsetWidth - (r[0].scrollWidth - r[0].offsetWidth - r.scrollLeft()) : 0;
-                        o = i.position().left - l + a - c
-                    } else o = i[0].offsetWidth, i.prevAll(":visible").each(function() {
-                        o += this.offsetWidth
-                    });
-                    f.css({
-                        top: h ? 0 : pr(u.wrapper),
-                        left: o - s,
-                        height: i.outerHeight(),
-                        width: s * 3
-                    }).data("th", i).show()
-                },
-                _positionColumnResizeHandle: function(t) {
-                    var i = this,
-                        u = i.resizeHandle,
-                        f = i.options.columnResizeHandleWidth;
-                    i.thead.on("mousemove" + r, "th:not(.k-group-cell,.k-hierarchy-cell)", function(r) {
-                        var e = n(this),
-                            o = r.clientX,
-                            s = n(window).scrollLeft(),
-                            h = e.offset().left + (p ? 0 : this.offsetWidth);
-                        o + s > h - f && o + s < h + f ? i._createResizeHandle(t, e) : u ? u.hide() : ui(i.wrapper, "")
-                    })
-                },
-                _resizeHandleDocumentClick: function(t) {
-                    n(t.target).closest(".k-column-active").length || (n(document).off(t), this._hideResizeHandle())
-                },
-                _hideResizeHandle: function() {
-                    this.resizeHandle && (this.resizeHandle.data("th").removeClass("k-column-active"), this.resizeHandle.hide())
-                },
-                _positionColumnResizeHandleTouch: function(t) {
-                    var r = this;
-                    r._resizeUserEvents = new i.UserEvents(r.thead, {
-                        filter: "th:not(.k-group-cell,.k-hierarchy-cell)",
-                        threshold: 10,
-                        hold: function(i) {
-                            var u = n(i.target);
-                            i.preventDefault();
-                            u.addClass("k-column-active");
-                            r._createResizeHandle(t, u);
-                            r._resizeHandleDocumentClickHandler || (r._resizeHandleDocumentClickHandler = f(r._resizeHandleDocumentClick, r));
-                            n(document).on("click", r._resizeHandleDocumentClickHandler)
-                        }
-                    })
-                },
-                _resizable: function() {
-                    var t = this,
-                        r = t.options,
-                        u, e, f, o, h = this._isMobile,
-                        s, i;
-                    r.resizable && (u = r.scrollable ? t.wrapper.find(".k-grid-header-wrap:first") : t.wrapper, h ? t._positionColumnResizeHandleTouch(u) : t._positionColumnResizeHandle(u), t.resizable = new it.Resizable(u, {
-                        handle: ".k-resize-handle",
-                        hint: function(i) {
-                            return n('<div class="k-grid-resize-indicator" />').css({
-                                height: i.data("th").outerHeight() + t.tbody.attr("clientHeight")
-                            })
-                        },
-                        start: function(u) {
-                            i = n(u.currentTarget).data("th");
-                            h && t._hideResizeHandle();
-                            var c = n.inArray(i[0], i.parent().children(":visible")),
-                                l = t.tbody.parent(),
-                                a = t.footer || n();
-                            ui(t.wrapper, "col-resize");
-                            s = r.scrollable ? t.thead.parent().find("col:eq(" + c + ")").add(l.children("colgroup").find("col:eq(" + c + ")")).add(a.find("colgroup").find("col:eq(" + c + ")")) : l.children("colgroup").find("col:eq(" + c + ")");
-                            e = u.x.location;
-                            f = i.outerWidth();
-                            o = t.tbody.outerWidth()
-                        },
-                        resize: function(i) {
-                            var u = p ? -1 : 1,
-                                h = f + i.x.location * u - e * u,
-                                c = t.footer || n();
-                            h > 10 && (s.css("width", h), r.scrollable && o && (t._footerWidth = o + i.x.location * u - e * u, t.tbody.parent().add(t.thead.parent()).add(c.find("table")).css("width", t._footerWidth)))
-                        },
-                        resizeend: function() {
-                            var n = i.outerWidth(),
-                                r;
-                            ui(t.wrapper, "");
-                            f != n && (r = t.columns[i.parent().find("th:not(.k-group-cell,.k-hierarchy-cell)").index(i)], r.width = n, t.trigger(ki, {
-                                column: r,
-                                oldWidth: f,
-                                newWidth: n
-                            }));
-                            t._hideResizeHandle();
-                            i = null
-                        }
-                    }))
-                },
-                _draggable: function() {
-                    var t = this;
-                    t.options.reorderable && (t._draggableInstance && t._draggableInstance.destroy(), t._draggableInstance = t.wrapper.kendoDraggable({
-                        group: i.guid(),
-                        filter: t.content ? ".k-grid-header:first " + vt : "table:first>.k-grid-header " + vt,
-                        drag: function() {
-                            t._hideResizeHandle()
-                        },
-                        hint: function(t) {
-                            return n('<div class="k-header k-drag-clue" />').css({
-                                width: t.width(),
-                                paddingLeft: t.css("paddingLeft"),
-                                paddingRight: t.css("paddingRight"),
-                                lineHeight: t.height() + "px",
-                                paddingTop: t.css("paddingTop"),
-                                paddingBottom: t.css("paddingBottom")
-                            }).html(t.attr(i.attr("title")) || t.attr(i.attr("field")) || t.text()).prepend('<span class="k-icon k-drag-status k-denied" />')
-                        }
-                    }).data("kendoDraggable"))
-                },
-                _reorderable: function() {
-                    var n = this;
-                    n.options.reorderable && n.wrapper.kendoReorderable({
-                        draggable: n._draggableInstance,
-                        change: function(t) {
-                            var r = d(n.columns[t.newIndex], n.columns),
-                                i = n.columns[t.oldIndex];
-                            n.trigger(di, {
-                                newIndex: r,
-                                oldIndex: d(i, n.columns),
-                                column: i
-                            });
-                            n.reorderColumn(r, i)
-                        }
-                    })
-                },
-                reorderColumn: function(n, t) {
-                    var i = this,
-                        r = d(t, i.columns),
-                        e = d(t, tt(i.columns)),
-                        o = d(i.columns[n], tt(i.columns)),
-                        s, u, h, f = i.footer || i.wrapper.find(".k-grid-footer");
-                    if (r !== n)
-                        for (i._hideResizeHandle(), i.columns.splice(r, 1), i.columns.splice(n, 0, t), i._templates(), et(i.thead.prev().find("col:not(.k-group-col,.k-hierarchy-col)"), e, o), i.options.scrollable && et(i.tbody.prev().find("col:not(.k-group-col,.k-hierarchy-col)"), e, o), et(i.thead.find(".k-header:not(.k-group-cell,.k-hierarchy-cell)"), r, n), f && f.length && (et(f.find(".k-grid-footer-wrap>table>colgroup>col:not(.k-group-col,.k-hierarchy-col)"), e, o), et(f.find(".k-footer-template>td:not(.k-group-cell,.k-hierarchy-cell)"), r, n)), s = i.tbody.children(":not(.k-grouping-row,.k-detail-row)"), u = 0, h = s.length; u < h; u += 1) et(s.eq(u).find(">td:not(.k-group-cell,.k-hierarchy-cell)"), r, n)
-                },
-                cellIndex: function(t) {
-                    return n(t).parent().children("td:not(.k-group-cell,.k-hierarchy-cell)").index(t)
-                },
-                _modelForContainer: function(t) {
-                    t = n(t);
-                    t.is("tr") || this._editMode() === "popup" || (t = t.closest("tr"));
-                    var r = t.attr(i.attr("uid"));
-                    return this.dataSource.getByUid(r)
-                },
-                _editable: function() {
-                    var t = this,
-                        f = t.selectable && t.selectable.options.multiple,
-                        i = t.options.editable,
-                        e = function() {
-                            var i = rt(),
-                                r = t._editContainer;
-                            !r || n.contains(r[0], i) || r[0] === i || n(i).closest(".k-animation-container").length || t.editable.end() && t.closeCell()
-                        },
-                        u;
-                    if (i) {
-                        if (u = t._editMode(), u === "incell") {
-                            if (i.update !== !1) t.wrapper.on(h + r, "tr:not(.k-grouping-row) > td", function(i) {
-                                var r = n(this);
-                                r.hasClass("k-hierarchy-cell") || r.hasClass("k-detail-cell") || r.hasClass("k-group-cell") || r.hasClass("k-edit-cell") || r.has("a.k-grid-delete").length || r.has("button.k-grid-delete").length || r.closest("tbody")[0] !== t.tbody[0] || n(i.target).is(":input") || (t.editable ? t.editable.end() && (f && n(rt()).blur(), t.closeCell(), t.editCell(r)) : t.editCell(r))
-                            }).on("focusin" + r, function() {
-                                clearTimeout(t.timer);
-                                t.timer = null
-                            }).on("focusout" + r, function() {
-                                t.timer = setTimeout(e, 1)
-                            })
-                        } else if (i.update !== !1) t.wrapper.on(h + r, "tbody>tr:not(.k-detail-row,.k-grouping-row):visible a.k-grid-edit", function(i) {
-                            i.preventDefault();
-                            t.editRow(n(this).closest("tr"))
-                        });
-                        if (i.destroy !== !1) t.wrapper.on(h + r, "tbody>tr:not(.k-detail-row,.k-grouping-row):visible .k-grid-delete", function(i) {
-                            i.preventDefault();
-                            i.stopPropagation();
-                            t.removeRow(n(this).closest("tr"))
-                        });
-                        else t.wrapper.on(h + r, "tbody>tr:not(.k-detail-row,.k-grouping-row):visible button.k-grid-delete", function(n) {
-                            n.stopPropagation();
-                            t._confirmation() || n.preventDefault()
-                        })
-                    }
-                },
-                editCell: function(t) {
-                    t = n(t);
-                    var i = this,
-                        r = i.columns[i.cellIndex(t)],
-                        u = i._modelForContainer(t);
-                    u && (!u.editable || u.editable(r.field)) && !r.command && r.field && (i._attachModelChange(u), i._editContainer = t, i.editable = t.addClass("k-edit-cell").kendoEditable({
-                        fields: {
-                            field: r.field,
-                            format: r.format,
-                            editor: r.editor,
-                            values: r.values
-                        },
-                        model: u,
-                        change: function(n) {
-                            i.trigger(gt, {
-                                values: n.values,
-                                container: t,
-                                model: u
-                            }) && n.preventDefault()
-                        }
-                    }).data("kendoEditable"), t.parent().addClass("k-grid-edit-row"), i.trigger(yt, {
-                        container: t,
-                        model: u
-                    }))
-                },
-                _destroyEditable: function() {
-                    var n = this,
-                        t = function() {
-                            n.editable && (n._detachModelChange(), n.editable.destroy(), n.editable = null, n._editContainer = null, n._destroyEditView())
-                        };
-                    n.editable && (n._editMode() !== "popup" || n._isMobile ? t() : n._editContainer.data("kendoWindow").bind("deactivate", t).close());
-                    n._actionSheet && (n._actionSheet.destroy(), n._actionSheet = null)
-                },
-                _destroyEditView: function() {
-                    this.editView && (this.editView.purge(), this.editView = null, this.pane.navigate(""))
-                },
-                _attachModelChange: function(n) {
-                    var t = this;
-                    t._modelChangeHandler = function(n) {
-                        t._modelChange({
-                            field: n.field,
-                            model: this
-                        })
-                    };
-                    n.bind("change", t._modelChangeHandler)
-                },
-                _detachModelChange: function() {
-                    var n = this,
-                        i = n._editContainer,
-                        t = n._modelForContainer(i);
-                    t && t.unbind(a, n._modelChangeHandler)
-                },
-                closeCell: function(t) {
-                    var u = this,
-                        r = u._editContainer,
-                        e, o, f;
-                    r && ((e = r.closest("tr").attr(i.attr("uid")), f = u.dataSource.getByUid(e), t && u.trigger("cancel", {
-                        container: r,
-                        model: f
-                    })) || (r.removeClass("k-edit-cell"), o = u.columns[u.cellIndex(r)], r.parent().removeClass("k-grid-edit-row"), u._destroyEditable(), u._displayCell(r, o, f), r.hasClass("k-dirty-cell") && n('<span class="k-dirty"/>').prependTo(r)))
-                },
-                _displayCell: function(n, t, r) {
-                    var s = this,
-                        e = {
-                            storage: {},
-                            count: 0
-                        },
-                        h = u({}, i.Template, s.options.templateSettings),
-                        o = i.template(s._cellTmpl(t, e), h);
-                    e.count > 0 && (o = f(o, e.storage));
-                    n.empty().html(o(r))
-                },
-                removeRow: function(n) {
-                    this._confirmation(n) && this._removeRow(n)
-                },
-                _removeRow: function(t) {
-                    var i = this,
-                        r, u;
-                    t = n(t).hide();
-                    r = i._modelForContainer(t);
-                    r && !i.trigger(si, {
-                        row: t,
-                        model: r
-                    }) && (u = i._editMode(), u !== "incell" && i.cancelRow(), i.dataSource.remove(r), (u === "inline" || u === "popup") && i.dataSource.sync())
-                },
-                _editMode: function() {
-                    var t = "incell",
-                        n = this.options.editable;
-                    return n !== !0 && (t = typeof n == "string" ? n : n.mode || t), t
-                },
-                editRow: function(t) {
-                    var f, u = this,
-                        e, s, o;
-                    if (t instanceof i.data.ObservableObject ? f = t : (t = n(t), f = u._modelForContainer(t)), e = u._editMode(), s = u.options.navigatable, u.cancelRow(), f) {
-                        u._attachModelChange(f);
-                        e === "popup" ? u._createPopupEditor(f) : e === "inline" ? u._createInlineEditor(t, f) : e === "incell" && n(t).children(g).each(function() {
-                            var t = n(this),
-                                i = u.columns[t.index()];
-                            return f = u._modelForContainer(t), f && (!f.editable || f.editable(i.field)) && i.field ? (u.editCell(t), !1) : void 0
-                        });
-                        o = u.editView ? u.editView.element : u._editContainer;
-                        o.on(h + r, "a.k-grid-cancel", function(t) {
-                            if (t.preventDefault(), t.stopPropagation(), !u.trigger("cancel", {
-                                    container: o,
-                                    model: f
-                                })) {
-                                var i = u.items().index(n(u.current()).parent());
-                                u.cancelRow();
-                                s && (u.current(u.items().eq(i).children().filter(v).first()), l(u.table, !0))
-                            }
-                        });
-                        o.on(h + r, "a.k-grid-update", function(n) {
-                            n.preventDefault();
-                            n.stopPropagation();
-                            u.saveRow()
-                        })
-                    }
-                },
-                _createPopupEditor: function(t) {
-                    var r = this,
-                        s = "<div " + i.attr("uid") + '="' + t.uid + '" class="k-popup-edit-form' + (r._isMobile ? " k-mobile-list" : "") + '"><div class="k-edit-form-container">',
-                        e, h, ut = [],
-                        a, k, d, tt, it, y, p, rt = r.options.editable,
-                        w = rt.template,
-                        g = o(rt) ? rt.window : {},
-                        ft = u({}, i.Template, r.options.templateSettings),
-                        nt, b;
-                    if (g = g || {}, w)
-                        for (typeof w === c && (w = window.unescape(w)), s += i.template(w, ft)(t), a = 0, k = r.columns.length; a < k; a++) e = r.columns[a], e.command && (y = oi(e.command, "edit"), y && (h = y));
-                    else
-                        for (a = 0, k = r.columns.length; a < k; a++) e = r.columns[a], e.command ? e.command && (y = oi(e.command, "edit"), y && (h = y)) : (s += '<div class="k-edit-label"><label for="' + e.field + '">' + (e.title || e.field || "") + "<\/label><\/div>", (!t.editable || t.editable(e.field)) && e.field ? (ut.push({
-                            field: e.field,
-                            format: e.format,
-                            editor: e.editor,
-                            values: e.values
-                        }), s += "<div " + i.attr("container-for") + '="' + e.field + '" class="k-edit-field"><\/div>') : (nt = {
-                            storage: {},
-                            count: 0
-                        }, d = i.template(r._cellTmpl(e, nt), ft), nt.count > 0 && (d = f(d, nt.storage)), s += '<div class="k-edit-field">' + d(t) + "<\/div>"));
-                    h && o(h) && (h.text && o(h.text) && (tt = h.text.update, it = h.text.cancel), h.attr && (p = h.attr));
-                    r._isMobile ? (s += "<\/div><\/div>", r.editView = r.pane.append("<div data-" + i.ns + 'role="view" data-' + i.ns + 'init-widgets="false" class="k-grid-edit-form"><div data-' + i.ns + 'role="header" class="k-header">' + r._createButton({
-                        name: "update",
-                        text: tt,
-                        attr: p
-                    }) + (g.title || "Edit") + r._createButton({
-                        name: "canceledit",
-                        text: it,
-                        attr: p
-                    }) + "<\/div>" + s + "<\/div>"), b = r._editContainer = r.editView.element.find(".k-popup-edit-form")) : (s += '<div class="k-edit-buttons k-state-default">', s += r._createButton({
-                        name: "update",
-                        text: tt,
-                        attr: p
-                    }) + r._createButton({
-                        name: "canceledit",
-                        text: it,
-                        attr: p
-                    }), s += "<\/div><\/div><\/div>", b = r._editContainer = n(s).appendTo(r.wrapper).eq(0).kendoWindow(u({
-                        modal: !0,
-                        resizable: !1,
-                        draggable: !0,
-                        title: "Edit",
-                        visible: !1,
-                        close: function(i) {
-                            if (i.userTriggered) {
-                                if (i.sender.element.focus(), r.trigger("cancel", {
-                                        container: b,
-                                        model: t
-                                    })) {
-                                    i.preventDefault();
-                                    return
-                                }
-                                var u = r.items().index(n(r.current()).parent());
-                                r.cancelRow();
-                                r.options.navigatable && (r.current(r.items().eq(u).children().filter(v).first()), l(r.table, !0))
-                            }
-                        }
-                    }, g)));
-                    r.editable = r._editContainer.kendoEditable({
-                        fields: ut,
-                        model: t,
-                        clearContainer: !1
-                    }).data("kendoEditable");
-                    r._isMobile && b.find("input[type=checkbox],input[type=radio]").parent(".k-edit-field").addClass("k-check").prev(".k-edit-label").addClass("k-check").click(function() {
-                        n(this).next().children("input").click()
-                    });
-                    r._openPopUpEditor();
-                    r.trigger(yt, {
-                        container: b,
-                        model: t
-                    })
-                },
-                _openPopUpEditor: function() {
-                    this._isMobile ? this.pane.navigate(this.editView, this._editAnimation) : this._editContainer.data("kendoWindow").center().open()
-                },
-                _createInlineEditor: function(t, r) {
-                    var e = this,
-                        u, s, f, h = [];
-                    t.children(":not(.k-group-cell,.k-hierarchy-cell)").each(function() {
-                        if (s = n(this), u = e.columns[e.cellIndex(s)], !u.command && u.field && (!r.editable || r.editable(u.field))) h.push({
-                            field: u.field,
-                            format: u.format,
-                            editor: u.editor,
-                            values: u.values
-                        }), s.attr(i.attr("container-for"), u.field), s.empty();
-                        else if (u.command && (f = oi(u.command, "edit"), f)) {
-                            s.empty();
-                            var c, l, t;
-                            o(f) && (f.text && o(f.text) && (c = f.text.update, l = f.text.cancel), f.attr && (t = f.attr));
-                            n(e._createButton({
-                                name: "update",
-                                text: c,
-                                attr: t
-                            }) + e._createButton({
-                                name: "canceledit",
-                                text: l,
-                                attr: t
-                            })).appendTo(s)
-                        }
-                    });
-                    e._editContainer = t;
-                    e.editable = t.addClass("k-grid-edit-row").kendoEditable({
-                        fields: h,
-                        model: r,
-                        clearContainer: !1
-                    }).data("kendoEditable");
-                    e.trigger(yt, {
-                        container: t,
-                        model: r
-                    })
-                },
-                cancelRow: function() {
-                    var n = this,
-                        t = n._editContainer,
-                        r;
-                    t && (r = n._modelForContainer(t), n._destroyEditable(), n.dataSource.cancelChanges(r), n._editMode() !== "popup" ? n._displayRow(t) : n._displayRow(n.items().filter("[" + i.attr("uid") + "=" + r.uid + "]")))
-                },
-                saveRow: function() {
-                    var n = this,
-                        t = n._editContainer,
-                        r = n._modelForContainer(t),
-                        i = n.editable;
-                    t && i && i.end() && !n.trigger(gt, {
-                        container: t,
-                        model: r
-                    }) && n.dataSource.sync()
-                },
-                _displayRow: function(t) {
-                    var i = this,
-                        r = i._modelForContainer(t);
-                    r && t.replaceWith(n((t.hasClass("k-alt") ? i.altRowTemplate : i.rowTemplate)(r)))
-                },
-                _showMessage: function(t, r) {
-                    var u = this;
-                    if (!u._isMobile) return window.confirm(t.title);
-                    var f = i.template('<ul><li class="km-actionsheet-title">#:title#<\/li><li><a href="\\#" class="k-button k-grid-delete">#:confirmDelete#<\/a><\/li><\/ul>'),
-                        e = n(f(t)).appendTo(u.view.element),
-                        o = u._actionSheet = new i.mobile.ui.ActionSheet(e, {
-                            cancel: t.cancelDelete,
-                            cancelTemplate: '<li class="km-actionsheet-cancel"><a class="k-button" href="\\#">#:cancel#<\/a><\/li>',
-                            close: function() {
-                                this.destroy()
-                            },
-                            command: function(t) {
-                                var i = n(t.currentTarget).parent();
-                                i.hasClass("km-actionsheet-cancel") || u._removeRow(r)
-                            },
-                            popup: u._actionSheetPopupOptions
-                        });
-                    return o.open(r), !1
-                },
-                _confirmation: function(n) {
-                    var r = this,
-                        t = r.options.editable,
-                        i = t === !0 || typeof t === c ? gi : t.confirmation;
-                    return i !== !1 && i != null ? r._showMessage({
-                        confirmDelete: t.confirmDelete || hr,
-                        cancelDelete: t.cancelDelete || cr,
-                        title: i === !0 ? gi : i
-                    }, n) : !0
-                },
-                cancelChanges: function() {
-                    this.dataSource.cancelChanges()
-                },
-                saveChanges: function() {
-                    var n = this;
-                    (n.editable && n.editable.end() || !n.editable) && !n.trigger(vi) && n.dataSource.sync()
-                },
-                addRow: function() {
-                    var n = this,
-                        r, t = n.dataSource,
-                        f = n._editMode(),
-                        c = n.options.editable.createAt || "",
-                        e = t.pageSize(),
-                        o = t.view() || [];
-                    if (n.editable && n.editable.end() || !n.editable) {
-                        f != "incell" && n.cancelRow();
-                        r = t.indexOf(o[0]);
-                        c.toLowerCase() == "bottom" && (r += o.length, e && !t.options.serverPaging && e <= o.length && (r -= 1));
-                        r < 0 && (r = t.page() > t.totalPages() ? (t.page() - 1) * e : 0);
-                        var s = t.insert(r, {}),
-                            l = s.uid,
-                            u = n.table.find("tr[" + i.attr("uid") + "=" + l + "]"),
-                            h = u.children("td:not(.k-group-cell,.k-hierarchy-cell)").eq(n._firstEditableColumnIndex(u));
-                        f === "inline" && u.length ? n.editRow(u) : f === "popup" ? n.editRow(s) : h.length && n.editCell(h)
-                    }
-                },
-                _firstEditableColumnIndex: function(n) {
-                    for (var u = this, i, f = u.columns, r = u._modelForContainer(n), t = 0, e = f.length; t < e; t++)
-                        if (i = f[t], r && (!r.editable || r.editable(i.field)) && !i.command && i.field) return t;
-                    return -1
-                },
-                _toolbar: function() {
-                    var t = this,
-                        s = t.wrapper,
-                        u = t.options.toolbar,
-                        o = t.options.editable,
-                        e;
-                    if (u && (e = t.wrapper.find(".k-grid-toolbar"), e.length || (or(u) || (u = typeof u === c ? u : t._toolbarTmpl(u).replace(ii, "\\#"), u = f(i.template(u), t)), e = n('<div class="k-toolbar k-grid-toolbar" />').html(u({})).prependTo(s)), o && o.create !== !1)) e.on(h + r, ".k-grid-add", function(n) {
-                        n.preventDefault();
-                        t.addRow()
-                    }).on(h + r, ".k-grid-cancel-changes", function(n) {
-                        n.preventDefault();
-                        t.cancelChanges()
-                    }).on(h + r, ".k-grid-save-changes", function(n) {
-                        n.preventDefault();
-                        t.saveChanges()
-                    })
-                },
-                _toolbarTmpl: function(n) {
-                    var u = this,
-                        t, i, r = "";
-                    if (k(n))
-                        for (t = 0, i = n.length; t < i; t++) r += u._createButton(n[t]);
-                    return r
-                },
-                _createButton: function(n) {
-                    var f = n.template || vr,
-                        t = typeof n === c ? n : n.name || n.text,
-                        e = wt[t] ? wt[t].className : "k-grid-" + (t || "").replace(/\s/g, ""),
-                        r = {
-                            className: e,
-                            text: t,
-                            imageClass: "",
-                            attr: "",
-                            iconClass: ""
-                        };
-                    if (!t && !(o(n) && n.template)) throw new Error("Custom commands should have name specified");
-                    return o(n) ? (n.className && (n.className += " " + r.className), t === "edit" && o(n.text) && (n = u(!0, {}, n), n.text = n.text.edit), n.attr && o(n.attr) && (n.attr = lt(n.attr)), r = u(!0, r, wt[t], n)) : r = u(!0, r, wt[t]), i.template(f)(r)
-                },
-                _hasFooters: function() {
-                    for (var t = this.columns, i = t.length, n = 0; n < i; n++)
-                        if (t[n].footerTemplate !== "" || t[n].groupFooterTemplate !== "") return !0;
-                    return !1
-                },
-                _groupable: function() {
-                    var t = this;
-                    t._groupableClickHandler ? t.table.off(h + r, t._groupableClickHandler) : t._groupableClickHandler = function(i) {
-                        var r = n(this),
-                            u = r.closest("tr");
-                        r.hasClass("k-i-collapse") ? t.collapseGroup(u) : t.expandGroup(u);
-                        i.preventDefault();
-                        i.stopPropagation()
-                    };
-                    t.table.on(h + r, ".k-grouping-row .k-i-collapse, .k-grouping-row .k-i-expand", t._groupableClickHandler);
-                    t._attachGroupable()
-                },
-                _attachGroupable: function() {
-                    var t = this,
-                        r = t.wrapper,
-                        f = t.options.groupable,
-                        e = vt + ":visible[" + i.attr("field") + "]",
-                        o = vt + "[" + i.attr("field") + "]";
-                    f && (r.has("div.k-grouping-header")[0] || n("<div>&nbsp;<\/div>").addClass("k-grouping-header").prependTo(r), t.groupable && t.groupable.destroy(), t.groupable = new fr(r, u({}, f, {
-                        draggable: t._draggableInstance,
-                        groupContainer: ">div.k-grouping-header",
-                        dataSource: t.dataSource,
-                        draggableElements: t.content ? ".k-grid-header:first " + e : "table:first>.k-grid-header " + e,
-                        filter: t.content ? ".k-grid-header:first " + o : "table:first>.k-grid-header " + o,
-                        allowDrag: t.options.reorderable
-                    })))
-                },
-                _selectable: function() {
-                    var n = this,
-                        f, e, t = [],
-                        u = n.options.selectable;
-                    if (u && (f = typeof u === c && u.toLowerCase().indexOf("multiple") > -1, e = typeof u === c && u.toLowerCase().indexOf("cell") > -1, n._hasDetails() && (t[t.length] = ".k-detail-row"), (n.options.groupable || n._hasFooters()) && (t[t.length] = ".k-grouping-row,.k-group-footer"), t = t.join(","), t !== "" && (t = ":not(" + t + ")"), n.selectable = new i.ui.Selectable(n.table, {
-                            filter: ">" + (e ? sr : "tbody>tr" + t),
-                            aria: !0,
-                            multiple: f,
-                            change: function() {
-                                n.trigger(a)
-                            }
-                        }), n.options.navigatable)) n.table.on("keydown" + r, function(t) {
-                        var i = n.current();
-                        if (t.keyCode === s.SPACEBAR && t.target == n.table[0] && !i.is(".k-edit-cell,.k-header") && i.parent().is(":not(.k-grouping-row,.k-detail-row,.k-group-footer)")) {
-                            if (t.preventDefault(), t.stopPropagation(), i = e ? i : i.parent(), f)
-                                if (t.ctrlKey) {
-                                    if (i.hasClass(bi)) {
-                                        i.removeClass(bi);
-                                        n.trigger(a);
-                                        return
-                                    }
-                                } else n.selectable.clear();
-                            else n.selectable.clear();
-                            n.selectable.value(i)
-                        }
-                    })
-                },
-                clearSelection: function() {
-                    var n = this;
-                    n.selectable.clear();
-                    n.trigger(a)
-                },
-                select: function(t) {
-                    var r = this,
-                        i = r.selectable;
-                    if (t = n(t), t.length) {
-                        i.options.multiple || (i.clear(), t = t.first());
-                        i.value(t);
-                        return
-                    }
-                    return i.value()
-                },
-                current: function(i) {
-                    var r = this,
-                        f = r.options.scrollable,
-                        u = r._current,
-                        e = r.table.add(r.thead.parent());
-                    return i !== t && i.length && (u && u[0] === i[0] || (u && (u.removeClass(ht).removeAttr("id"), e.removeAttr("aria-activedescendant")), i.attr("id", r._cellId), r._current = i.addClass(ht), e.attr("aria-activedescendant", r._cellId), i.length && f && (n.contains(r.content[0], i[0]) && r._scrollTo(i.parent()[0], r.content[0]), f.virtual ? r._scrollTo(i[0], r.content.find(">.k-virtual-scrollable-wrap")[0]) : r._scrollTo(i[0], r.content[0])))), r._current
-                },
-                _removeCurrent: function() {
-                    this._current && (this._current.removeClass(ht), this._current = null)
-                },
-                _scrollTo: function(n, t) {
-                    var e = n.tagName.toLowerCase(),
-                        i = e === "td" || e === "th",
-                        r = n[i ? "offsetLeft" : "offsetTop"],
-                        o = n[i ? "offsetWidth" : "offsetHeight"],
-                        u = t[i ? "scrollLeft" : "scrollTop"],
-                        f = t[i ? "clientWidth" : "clientHeight"],
-                        s = r + o,
-                        h = 0;
-                    h = u > r ? r : s > u + f ? o <= f ? s - f : r : u;
-                    t[i ? "scrollLeft" : "scrollTop"] = h
-                },
-                _navigatable: function() {
-                    var t = this,
-                        o = f(t.current, t),
-                        u = t.table,
-                        h = t.thead.parent(),
-                        c = u,
-                        a = i.support.isRtl(t.element);
-                    if (t.options.navigatable) {
-                        t.options.scrollable && (c = u.add(h), h.attr(nt, -1));
-                        h.on("keydown" + r, function(n) {
-                            n.altKey && n.keyCode == s.DOWN && (o().find(".k-grid-filter, .k-header-column-menu").click(), n.stopImmediatePropagation())
-                        }).find("a.k-link").attr("tabIndex", -1);
-                        u.attr(nt, y.max(u.attr(nt) || 0, 0)).on("mousedown" + r + " keydown" + r, ".k-detail-cell", function(n) {
-                            n.target !== n.currentTarget && n.stopImmediatePropagation()
-                        });
-                        c.on(i.support.touch ? "touchstart" + r : "mousedown" + r, ut + ">" + v, f(dr, t)).on("focus" + r, function() {
-                            if (!i.support.touch) {
-                                var t = o();
-                                t && t.is(":visible") ? t.addClass(ht) : o(n(this).find(ft));
-                                this == u[0] ? (h.attr(nt, -1), u.attr(nt, 0)) : (u.attr(nt, -1), h.attr(nt, 0))
-                            }
-                        }).on("focusout" + r, function() {
-                            var n = o();
-                            n && n.removeClass(ht)
-                        }).on("keydown" + r, function(i) {
-                            var h = i.keyCode,
-                                f = !1,
-                                p = !i.isDefaultPrevented() && !n(i.target).is(":button,a,:input,a>.k-icon"),
-                                st = t.options.pageable,
-                                w = t.dataSource,
-                                nt = t._editMode() == "incell",
-                                b, tt, c, k, it, et = i.shiftKey,
-                                r = o(),
-                                ot, d, y;
-                            r && r.is("th") && (p = !0);
-                            p && h == s.UP ? (r ? (c = r.parent().prevAll(ut).first(), c[0] || (it = t.thead.parent(), l(it, !0), c = it.find(ut).first()), k = r.index(), r = c.children().eq(k), r[0] && r.is(v) || (r = c.children(v).first())) : r = u.find(ft), f = !0, o(r)) : p && h == s.DOWN ? (r ? (c = r.parent().nextAll(ut).first(), !c[0] && r.is("th") && (l(t.tbody.parent()), c = t.tbody.find(ut).first()), k = r.index(), r = c.children().eq(k), r[0] && r.is(v) || (r = c.children(v).first())) : r = u.find(ft), f = !0, o(r)) : p && h == (a ? s.RIGHT : s.LEFT) ? (o(r ? r.prevAll(g + ":first") : u.find(ft)), f = !0) : p && h == (a ? s.LEFT : s.RIGHT) ? (r ? r.next()[0] && (r = r.nextAll(g + ":first")) : r = u.find(ft), f = !0, o(r)) : p && st && s.PAGEDOWN == h ? (w.page(w.page() + 1), f = !0) : p && st && s.PAGEUP == h ? (w.page(w.page() - 1), f = !0) : h == s.ENTER || s.F2 == h ? (r = r ? r : u.find(ft), r.is("th") ? (r.find(".k-link").click(), f = !0) : r.parent().is(".k-master-row,.k-grouping-row") ? (r.parent().find(".k-icon:first").click(), f = !0) : (ot = r.find(":kendoFocusable:first"), !r.hasClass("k-edit-cell") && ot[0] && r.hasClass("k-state-focused") ? (ot.focus(), f = !0) : t.options.editable && !n(i.target).is(":button,.k-button,textarea") && (d = n(i.target).closest("[role=gridcell]"), d[0] || (d = r), t._handleEditing(d), f = !0))) : s.ESC == h ? (b = rt(), r && n.contains(r[0], b) && !r.hasClass("k-edit-cell") && !r.parent().hasClass("k-grid-edit-row") ? (l(t.table[0], !0), f = !0) : t._editContainer && (!r || t._editContainer.has(r[0]) || r[0] === t._editContainer[0]) && (nt ? t.closeCell(!0) : (tt = t.items().index(n(r).parent()), b && b.blur(), t.cancelRow(), tt >= 0 && t.current(t.items().eq(tt).children().filter(v).first())), e.msie && e.version < 9 && document.body.focus(), l(u, !0), f = !0)) : s.TAB == h && (r = n(r), t.options.editable && nt && (y = n(rt()).closest(".k-edit-cell"), y[0] && y[0] !== r[0] && (r = y)), y = et ? r.prevAll(g + ":first") : r.nextAll(":visible:first"), y.length || (y = r.parent()[et ? "prevAll" : "nextAll"]("tr:not(.k-grouping-row):not(.k-detail-row):visible:first").children(g + (et ? ":last" : ":first"))), !r.is("th") && y.length && t.options.editable && nt && (t._handleEditing(r, y), f = !0));
-                            f && (i.preventDefault(), i.stopPropagation())
-                        })
-                    }
-                },
-                _handleEditing: function(t, i) {
-                    var r = this,
-                        u = n(rt()),
-                        f = r._editMode(),
-                        c = e.msie,
-                        a = c && e.version < 9,
-                        o = r._editContainer,
-                        s, h;
-                    if (h = f == "incell" ? t.hasClass("k-edit-cell") : t.parent().hasClass("k-grid-edit-row"), r.editable) {
-                        if (n.contains(o[0], u[0]) && (e.opera || a ? u.change().triggerHandler("blur") : (u.blur(), c && u.blur())), !r.editable) {
-                            l(r.table);
-                            return
-                        }
-                        if (r.editable.end()) f == "incell" ? r.closeCell() : (r.saveRow(), h = !0);
-                        else {
-                            f == "incell" ? r.current(o) : r.current(o.children().filter(g).first());
-                            s = o.find(":kendoFocusable:first")[0];
-                            s && s.focus();
-                            return
-                        }
-                    }
-                    i && r.current(i);
-                    a && document.body.focus();
-                    l(r.table, !0);
-                    (h || i) && !i || (f == "incell" ? r.editCell(r.current()) : r.editRow(r.current().parent()))
-                },
-                _wrapper: function() {
-                    var n = this,
-                        r = n.table,
-                        i = n.options.height,
-                        t = n.element;
-                    t.is("div") || (t = t.wrap("<div/>").parent());
-                    n.wrapper = t.addClass("k-grid k-widget k-secondary");
-                    i && (n.wrapper.css(ti, i), r.css(ti, "auto"));
-                    n._initMobile()
-                },
-                _initMobile: function() {
-                    var t = this.options,
-                        r;
-                    this._isMobile = t.mobile === !0 && i.support.mobileOS || t.mobile === "phone" || t.mobile === "tablet";
-                    this._isMobile && (r = this.wrapper.addClass("k-grid-mobile").wrap("<div data-" + i.ns + 'role="view" data-' + i.ns + 'init-widgets="false"><\/div>').parent(), this.pane = i.mobile.ui.Pane.wrap(r), this.view = this.pane.view(), this._actionSheetPopupOptions = n(document.documentElement).hasClass("km-root") ? {
-                        modal: !1
-                    } : {
-                        align: "bottom center",
-                        position: "bottom center",
-                        effect: "slideIn:up"
-                    }, t.height && this.pane.element.parent().css(ti, t.height), this._editAnimation = "slide")
-                },
-                _tbody: function() {
-                    var i = this,
-                        r = i.table,
-                        t;
-                    t = r.find(">tbody");
-                    t.length || (t = n("<tbody/>").appendTo(r));
-                    i.tbody = t
-                },
-                _scrollable: function() {
-                    var t = this,
-                        u, s, y = t.options,
-                        o = y.scrollable,
-                        v = o !== !0 && o.virtual && !t.virtualScrollable,
-                        c = !i.support.kineticScrollNeeded || v ? i.support.scrollbar() : 0,
-                        l, a, h;
-                    o && (u = t.wrapper.children(".k-grid-header"), u[0] || (u = n('<div class="k-grid-header" />').insertBefore(t.table)), u.css(p ? "padding-left" : "padding-right", o.virtual ? c + 1 : c), s = n('<table role="grid" />'), ri && s.attr("cellspacing", 0), s.append(t.thead), u.empty().append(n('<div class="k-grid-header-wrap" />').append(s)), t.content = t.table.parent(), t.content.is(".k-virtual-scrollable-wrap") && (t.content = t.content.parent()), t.content.is(".k-grid-content, .k-virtual-scrollable-wrap") || (t.content = t.table.wrap('<div class="k-grid-content" />').parent()), v && (t.virtualScrollable = new tr(t.content, {
-                        dataSource: t.dataSource,
-                        itemHeight: f(t._averageRowHeight, t)
-                    })), t.scrollables = u.children(".k-grid-header-wrap"), l = t.wrapper.find(".k-grid-footer"), a = p && e.webkit ? c : 0, l.length && (t.scrollables = t.scrollables.add(l.children(".k-grid-footer-wrap"))), o.virtual ? t.content.find(">.k-virtual-scrollable-wrap").bind("scroll" + r, function() {
-                        t.scrollables.scrollLeft(this.scrollLeft + a)
-                    }) : (t.content.bind("scroll" + r, function() {
-                        t.scrollables.scrollLeft(this.scrollLeft + a)
-                    }), h = i.touchScroller(t.content), h && h.movable && h.movable.bind("change", function(n) {
-                        t.scrollables.scrollLeft(-n.sender.x)
-                    })))
-                },
-                _setContentWidth: function() {
-                    var t = this,
-                        u = "k-grid-content-expander",
-                        e = '<div class="' + u + '"><\/div>',
-                        r = t.resizable,
-                        i;
-                    t.options.scrollable && t.wrapper.is(":visible") && (i = t.table.parent().children("." + u), t._setContentWidthHandler = f(t._setContentWidth, t), t.dataSource && t.dataSource.view().length ? i[0] && (i.remove(), r && r.unbind("resize", t._setContentWidthHandler)) : (i[0] || (i = n(e).appendTo(t.table.parent()), r && r.bind("resize", t._setContentWidthHandler)), t.thead && i.width(t.thead.width())))
-                },
-                _setContentHeight: function() {
-                    var n = this,
-                        r = n.options,
-                        t = n.wrapper.innerHeight(),
-                        e = n.wrapper.children(".k-grid-header"),
-                        u = i.support.scrollbar(),
-                        f;
-                    r.scrollable && n.wrapper.is(":visible") && (t -= e.outerHeight(), n.pager && (t -= n.pager.element.outerHeight()), r.groupable && (t -= n.wrapper.children(".k-grouping-header").outerHeight()), r.toolbar && (t -= n.wrapper.children(".k-grid-toolbar").outerHeight()), n.footerTemplate && (t -= n.wrapper.children(".k-grid-footer").outerHeight()), f = function(n) {
-                        var t, i;
-                        return n[0].style.height ? !0 : (t = n.height(), n.height("auto"), i = n.height(), t != i) ? (n.height(""), !0) : (n.height(""), !1)
-                    }, f(n.wrapper) && (t > u * 2 ? n.content.height(t) : n.content.height(u * 2 + 1)))
-                },
-                _averageRowHeight: function() {
-                    var n = this,
-                        t = n._rowHeight,
-                        i;
-                    return n._rowHeight || (n._rowHeight = t = n.table.outerHeight() / n.items().length, n._sum = t, n._measures = 1), i = n.table.outerHeight() / n.items().length, t !== i && (n._measures++, n._sum += i, n._rowHeight = n._sum / n._measures), t
-                },
-                _dataSource: function() {
-                    var n = this,
-                        e = n.options,
-                        r, i = e.dataSource;
-                    i = k(i) ? {
-                        data: i
-                    } : i;
-                    o(i) && (u(i, {
-                        table: n.table,
-                        fields: n.columns
-                    }), r = e.pageable, o(r) && r.pageSize !== t && (i.pageSize = r.pageSize));
-                    n.dataSource && n._refreshHandler ? n.dataSource.unbind(a, n._refreshHandler).unbind(kt, n._progressHandler).unbind(dt, n._errorHandler) : (n._refreshHandler = f(n.refresh, n), n._progressHandler = f(n._requestStart, n), n._errorHandler = f(n._error, n));
-                    n.dataSource = ur.create(i).bind(a, n._refreshHandler).bind(kt, n._progressHandler).bind(dt, n._errorHandler)
-                },
-                _error: function() {
-                    this._progress(!1)
-                },
-                _requestStart: function() {
-                    this._progress(!0)
-                },
-                _modelChange: function(t) {
-                    var r = this,
-                        h = t.model,
-                        f = r.tbody.find("tr[" + i.attr("uid") + "=" + h.uid + "]"),
-                        u, o, l = f.hasClass("k-alt"),
-                        s, e = r.items().index(f),
-                        c;
-                    if (f.children(".k-edit-cell").length && !r.options.rowTemplate) f.children(":not(.k-group-cell,.k-hierarchy-cell)").each(function() {
-                        u = n(this);
-                        o = r.columns[r.cellIndex(u)];
-                        o.field === t.field && (u.hasClass("k-edit-cell") ? u.addClass("k-dirty-cell") : (r._displayCell(u, o, h), n('<span class="k-dirty"/>').prependTo(u)))
-                    });
-                    else if (!f.hasClass("k-grid-edit-row")) {
-                        for (s = (l ? r.altRowTemplate : r.rowTemplate)(h), f.replaceWith(s), s = r.items().eq(e), e = 0, c = r.columns.length; e < c; e++) o = r.columns[e], o.field === t.field && (u = s.children(":not(.k-group-cell,.k-hierarchy-cell)").eq(e), n('<span class="k-dirty"/>').prependTo(u));
-                        r.trigger("itemChange", {
-                            item: s,
-                            data: h,
-                            ns: it
-                        })
-                    }
-                },
-                _pageable: function() {
-                    var t = this,
-                        f, r = t.options.pageable;
-                    r && (f = t.wrapper.children("div.k-grid-pager"), f.length || (f = n('<div class="k-pager-wrap k-grid-pager"/>').appendTo(t.wrapper)), t.pager && t.pager.destroy(), t.pager = typeof r == "object" && r instanceof i.ui.Pager ? r : new i.ui.Pager(f, u({}, r, {
-                        dataSource: t.dataSource
-                    })))
-                },
-                _footer: function() {
-                    var t = this,
-                        u = t.dataSource.aggregates(),
-                        r = "",
-                        s = t.footerTemplate,
-                        e = t.options,
-                        f, i = t.footer || t.wrapper.find(".k-grid-footer"),
-                        o;
-                    s ? (u = at(u) ? fi(t.dataSource.aggregate()) : u, r = n(t._wrapFooter(s(u))), i.length ? (o = r, i.replaceWith(o), i = t.footer = o) : i = e.scrollable ? t.footer = e.pageable ? r.insertBefore(t.wrapper.children("div.k-grid-pager")) : r.appendTo(t.wrapper) : t.footer = r.insertBefore(t.tbody)) : i && !t.footer && (t.footer = i);
-                    i.length && (e.scrollable && (f = i.attr("tabindex", -1).children(".k-grid-footer-wrap"), t.scrollables = t.scrollables.not(".k-grid-footer-wrap").add(f)), t._footerWidth && i.find("table").css("width", t._footerWidth), f && f.scrollLeft(t.content.scrollLeft()))
-                },
-                _wrapFooter: function(t) {
-                    var u = this,
-                        r = "",
-                        f = i.support.mobileOS ? 0 : i.support.scrollbar();
-                    return u.options.scrollable ? (r = n('<div class="k-grid-footer"><div class="k-grid-footer-wrap"><table' + (ri ? ' cellspacing="0"' : "") + "><tbody>" + t + "<\/tbody><\/table><\/div><\/div>"), u._appendCols(r.find("table")), r.css(p ? "padding-left" : "padding-right", f), r) : '<tfoot class="k-grid-footer">' + t + "<\/tfoot>"
-                },
-                _columnMenu: function() {
-                    var t = this,
-                        s, v = t.columns,
-                        r, e = t.options,
-                        f = e.columnMenu,
-                        h, c, a, y = this._isMobile,
-                        p = function() {
-                            l(t.thead.parent(), !0)
-                        },
-                        w = function(n) {
-                            t.trigger(ci, {
-                                field: n.field,
-                                container: n.container
-                            })
-                        },
-                        o;
-                    f && (typeof f == "boolean" && (f = {}), t.thead.find("th:not(.k-hierarchy-cell,.k-group-cell)").each(function(l) {
-                        r = v[l];
-                        o = n(this);
-                        !r.command && (r.field || o.attr("data-" + i.ns + "field")) && (s = o.data("kendoColumnMenu"), s && s.destroy(), c = r.sortable !== !1 && f.sortable !== !1 ? e.sortable : !1, a = e.filterable && r.filterable !== !1 && f.filterable !== !1 ? u({
-                            pane: t.pane
-                        }, r.filterable, e.filterable) : !1, h = {
-                            dataSource: t.dataSource,
-                            values: r.values,
-                            columns: f.columns,
-                            sortable: c,
-                            filterable: a,
-                            messages: f.messages,
-                            owner: t,
-                            closeCallback: p,
-                            init: w,
-                            pane: t.pane,
-                            filter: y ? ":not(.k-column-active)" : ""
-                        }, o.kendoColumnMenu(h))
-                    }))
-                },
-                _filterable: function() {
-                    var t = this,
-                        r = t.columns,
-                        f, e, s = function() {
-                            l(t.thead.parent(), !0)
-                        },
-                        o = t.options.filterable;
-                    o && !t.options.columnMenu && t.thead.find("th:not(.k-hierarchy-cell,.k-group-cell)").each(function(h) {
-                        if (f = n(this), r[h].filterable !== !1 && !r[h].command && (r[h].field || f.attr("data-" + i.ns + "field"))) {
-                            e = f.data("kendoFilterMenu");
-                            e && e.destroy();
-                            var c = r[h].filterable,
-                                l = u({}, o, c, {
-                                    dataSource: t.dataSource,
-                                    values: r[h].values,
-                                    closeCallback: s,
-                                    init: function(n) {
-                                        t.trigger(hi, {
-                                            field: n.field,
-                                            container: n.container
-                                        })
-                                    },
-                                    pane: t.pane
-                                });
-                            c && c.messages && (l.messages = u(!0, {}, o.messages, c.messages));
-                            f.kendoFilterMenu(l)
-                        }
-                    })
-                },
-                _sortable: function() {
-                    var r = this,
-                        s = r.columns,
-                        t, f, e, o = r.options.sortable;
-                    o && r.thead.find("th:not(.k-hierarchy-cell,.k-group-cell)").each(function(h) {
-                        t = s[h];
-                        t.sortable !== !1 && !t.command && t.field && (f = n(this), e = f.data("kendoSortable"), e && e.destroy(), f.attr("data-" + i.ns + "field", t.field).kendoSortable(u({}, o, t.sortable, {
-                            dataSource: r.dataSource,
-                            aria: !0,
-                            filter: ":not(.k-column-active)"
-                        })))
-                    })
-                },
-                _columns: function(t) {
-                    var r = this,
-                        f = r.table,
-                        e, s = f.find("col"),
-                        o = r.options.dataSource;
-                    t = t.length ? t : bt(f.find("th"), function(t, r) {
-                        t = n(t);
-                        var f = t.attr(i.attr("sortable")),
-                            e = t.attr(i.attr("filterable")),
-                            o = t.attr(i.attr("type")),
-                            h = t.attr(i.attr("groupable")),
-                            u = t.attr(i.attr("field")),
-                            c = t.attr(i.attr("menu"));
-                        return u || (u = t.text().replace(/\s|[^A-z0-9]/g, "")), {
-                            field: u,
-                            type: o,
-                            sortable: f !== "false",
-                            filterable: e !== "false",
-                            groupable: h !== "false",
-                            menu: c,
-                            template: t.attr(i.attr("template")),
-                            width: s.eq(r).css("width")
-                        }
-                    });
-                    e = !(r.table.find("tbody tr").length > 0 && (!o || !o.transport));
-                    r.columns = bt(t, function(n) {
-                        return n = typeof n === c ? {
-                            field: n
-                        } : n, n.hidden && (n.attributes = ot(n.attributes), n.footerAttributes = ot(n.footerAttributes), n.headerAttributes = ot(n.headerAttributes)), u({
-                            encoded: e
-                        }, n)
-                    })
-                },
-                _groups: function() {
-                    var n = this.dataSource.group();
-                    return n ? n.length : 0
-                },
-                _tmpl: function(n, t) {
-                    var r = this,
-                        c = u({}, i.Template, r.options.templateSettings),
-                        e, l = r.columns.length,
-                        a, h = {
-                            storage: {},
-                            count: 0
-                        },
-                        o, p, v = r._hasDetails(),
-                        s = [],
-                        y = r._groups();
-                    if (!n) {
-                        for (n = "<tr", t && s.push("k-alt"), v && s.push("k-master-row"), s.length && (n += ' class="' + s.join(" ") + '"'), l && (n += " " + i.attr("uid") + '="#=' + i.expr("uid", c.paramName) + '#"'), n += " role='row'>", y > 0 && (n += pt(y)), v && (n += '<td class="k-hierarchy-cell"><a class="k-icon k-plus" href="\\#" tabindex="-1"><\/a><\/td>'), e = 0; e < l; e++) o = r.columns[e], a = o.template, p = typeof a, n += "<td" + lt(o.attributes) + " role='gridcell'>", n += r._cellTmpl(o, h), n += "<\/td>";
-                        n += "<\/tr>"
-                    }
-                    return (n = i.template(n, c), h.count > 0) ? f(n, h.storage) : n
-                },
-                _headerCellText: function(n) {
-                    var e = this,
-                        o = u({}, i.Template, e.options.templateSettings),
-                        t = n.headerTemplate,
-                        f = typeof t,
-                        r = n.title || n.field || "";
-                    return f === ct ? r = i.template(t, o)({}) : f === c && (r = t), r
-                },
-                _cellTmpl: function(n, t) {
-                    var h = this,
-                        y = u({}, i.Template, h.options.templateSettings),
-                        l = n.template,
-                        a = y.paramName,
-                        f = n.field,
-                        r = "",
-                        s, p, v = n.format,
-                        w = typeof l,
-                        e = n.values;
-                    if (n.command) {
-                        if (k(n.command)) {
-                            for (s = 0, p = n.command.length; s < p; s++) r += h._createButton(n.command[s]);
-                            return r.replace(ii, "\\#")
-                        }
-                        return h._createButton(n.command).replace(ii, "\\#")
-                    }
-                    return w === ct ? (t.storage["tmpl" + t.count] = l, r += "#=this.tmpl" + t.count + "(" + a + ")#", t.count++) : w === c ? r += l : e && e.length && o(e[0]) && "value" in e[0] && f ? (r += "#var v =" + i.stringify(rr(e)) + "#", r += "#var f = v[", y.useWithBlock || (r += a + "."), r += f + "]#", r += "${f != null ? f : ''}") : (r += n.encoded ? "#:" : "#=", v && (r += 'kendo.format("' + v.replace(lr, "\\$1") + '",'), f ? (f = i.expr(f, a), r += f + "==null?'':" + f) : r += "''", v && (r += ")"), r += "#"), r
-                },
-                _templates: function() {
-                    var t = this,
-                        r = t.options,
-                        u = t.dataSource,
-                        f = u.group(),
-                        e = t.footer || t.wrapper.find(".k-grid-footer"),
-                        i = u.aggregate();
-                    t.rowTemplate = t._tmpl(r.rowTemplate);
-                    t.altRowTemplate = t._tmpl(r.altRowTemplate || r.rowTemplate, !0);
-                    t._hasDetails() && (t.detailTemplate = t._detailTmpl(r.detailTemplate || ""));
-                    (!t._group || at(i)) && (at(i) || e.length) && !b(t.columns, function(n) {
-                        return n.footerTemplate
-                    }).length || (t.footerTemplate = t._footerTmpl(i, "footerTemplate", "k-footer-template"));
-                    f && b(t.columns, function(n) {
-                        return n.groupFooterTemplate
-                    }).length && (i = n.map(f, function(n) {
-                        return n.aggregates
-                    }), t.groupFooterTemplate = t._footerTmpl(i, "groupFooterTemplate", "k-group-footer"))
-                },
-                _footerTmpl: function(n, t, r) {
-                    var s = this,
-                        a = u({}, i.Template, s.options.templateSettings),
-                        v = a.paramName,
-                        e = "",
-                        c, y, d = s.columns,
-                        o, p, w = {},
-                        l = 0,
-                        b = {},
-                        k = s._groups(),
-                        g = fi(n),
-                        h;
-                    for (e += '<tr class="' + r + '">', k > 0 && (e += pt(k)), s._hasDetails() && (e += '<td class="k-hierarchy-cell">&nbsp;<\/td>'), c = 0, y = s.columns.length; c < y; c++) h = d[c], o = h[t], p = typeof o, e += "<td" + lt(h.footerAttributes) + ">", o ? (p !== ct && (b = g[h.field] ? u({}, a, {
-                        paramName: v + "." + h.field
-                    }) : {}, o = i.template(o, b)), w["tmpl" + l] = o, e += "#=this.tmpl" + l + "(" + v + ")#", l++) : e += "&nbsp;", e += "<\/td>";
-                    return (e += "<\/tr>", e = i.template(e, a), l > 0) ? f(e, w) : e
-                },
-                _detailTmpl: function(n) {
-                    var e = this,
-                        t = "",
-                        o = u({}, i.Template, e.options.templateSettings),
-                        l = o.paramName,
-                        s = {},
-                        r = 0,
-                        h = e._groups(),
-                        c = tt(e.columns).length,
-                        a = typeof n;
-                    return (t += '<tr class="k-detail-row">', h > 0 && (t += pt(h)), t += '<td class="k-hierarchy-cell"><\/td><td class="k-detail-cell"' + (c ? ' colspan="' + c + '"' : "") + ">", a === ct ? (s["tmpl" + r] = n, t += "#=this.tmpl" + r + "(" + l + ")#", r++) : t += n, t += "<\/td><\/tr>", t = i.template(t, o), r > 0) ? f(t, s) : t
-                },
-                _hasDetails: function() {
-                    var n = this;
-                    return n.options.detailTemplate !== null || (n._events[ni] || []).length
-                },
-                _details: function() {
-                    var t = this;
-                    t.table.on(h + r, ".k-hierarchy-cell .k-plus, .k-hierarchy-cell .k-minus", function(i) {
-                        var f = n(this),
-                            u = f.hasClass("k-plus"),
-                            r = f.closest("tr.k-master-row"),
-                            e, s = t.detailTemplate,
-                            o, h = t._hasDetails();
-                        return f.toggleClass("k-plus", !u).toggleClass("k-minus", u), h && !r.next().hasClass("k-detail-row") && (o = t.dataItem(r), n(s(o)).addClass(r.hasClass("k-alt") ? "k-alt" : "").insertAfter(r), t.trigger(ni, {
-                            masterRow: r,
-                            detailRow: r.next(),
-                            data: o,
-                            detailCell: r.next().find(".k-detail-cell")
-                        })), e = r.next(), t.trigger(u ? pi : wi, {
-                            masterRow: r,
-                            detailRow: e
-                        }), e.toggle(u), t._current && t._current.attr("aria-expanded", u), i.preventDefault(), !1
-                    })
-                },
-                dataItem: function(t) {
-                    if (t = n(t)[0], !t) return null;
-                    for (var f = this.tbody.children(), u = t.sectionRowIndex, r = u, i = 0; i < u; i++) /k-grouping-row|k-detail-row|k-group-footer/.test(f[i].className) && r--;
-                    return this._data[r]
-                },
-                expandRow: function(t) {
-                    n(t).find("> td .k-plus, > td .k-i-expand").click()
-                },
-                collapseRow: function(t) {
-                    n(t).find("> td .k-minus, > td .k-i-collapse").click()
-                },
-                _thead: function() {
-                    var r = this,
-                        h = r.columns,
-                        l = r._hasDetails() && h.length,
-                        s, a, e = "",
-                        o = r.table.find(">thead"),
-                        f, c, u;
-                    if (o.length || (o = n("<thead/>").insertBefore(r.tbody)), f = r.element.find("tr:has(th):first"), f.length || (f = o.children().first(), f.length || (f = n("<tr/>"))), f.children().length) l && !f.find(".k-hierarchy-cell")[0] && f.prepend('<th class="k-hierarchy-cell">&nbsp;<\/th>');
-                    else {
-                        for (l && (e += '<th class="k-hierarchy-cell">&nbsp;<\/th>'), s = 0, a = h.length; s < a; s++) u = h[s], c = r._headerCellText(u), u.command ? e += "<th" + lt(u.headerAttributes) + ">" + c + "<\/th>" : (e += "<th role='columnheader' " + i.attr("field") + "='" + (u.field || "") + "' ", u.title && (e += i.attr("title") + '="' + u.title.replace(/'/g, "'") + '" '), u.groupable !== t && (e += i.attr("groupable") + "='" + u.groupable + "' "), u.aggregates && (e += i.attr("aggregates") + "='" + u.aggregates + "'"), e += lt(u.headerAttributes), e += ">" + c + "<\/th>");
-                        f.html(e)
-                    }
-                    f.find("th").addClass("k-header");
-                    r.options.scrollable || o.addClass("k-grid-header");
-                    f.find("script").remove().end().appendTo(o);
-                    r.thead && r._destroyColumnAttachments();
-                    r.thead = o;
-                    r._sortable();
-                    r._filterable();
-                    r._scrollable();
-                    r._updateCols();
-                    r._resizable();
-                    r._draggable();
-                    r._reorderable();
-                    r.groupable && r._attachGroupable();
-                    r._columnMenu()
-                },
-                _updateCols: function() {
-                    var n = this;
-                    n._appendCols(n.thead.parent().add(n.table))
-                },
-                _appendCols: function(n) {
-                    var t = this;
-                    ir(n, tt(t.columns), t._hasDetails(), t._groups())
-                },
-                _autoColumns: function(n) {
-                    if (n && n.toJSON) {
-                        var t = this,
-                            i;
-                        n = n.toJSON();
-                        for (i in n) t.columns.push({
-                            field: i
-                        });
-                        t._thead();
-                        t._templates()
-                    }
-                },
-                _rowsHtml: function(n) {
-                    for (var i = this, r = "", f = i.rowTemplate, e = i.altRowTemplate, t = 0, u = n.length; t < u; t++) r += t % 2 ? e(n[t]) : f(n[t]), i._data.push(n[t]);
-                    return r
-                },
-                _groupRowHtml: function(n, t, r) {
-                    var f = this,
-                        e = "",
-                        o, l, a = n.field,
-                        s = b(f.columns, function(n) {
-                            return n.field == a
-                        })[0] || {},
-                        h = s.groupHeaderTemplate,
-                        v = (s.title || a) + ": " + br(n.value, s.format, s.values),
-                        y = u({}, {
-                            field: n.field,
-                            value: n.value
-                        }, n.aggregates[n.field]),
-                        p = f._groupAggregatesDefaultObject || {},
-                        c = n.items;
-                    if (h && (v = typeof h === ct ? h(y) : i.template(h)(y)), e += '<tr class="k-grouping-row">' + pt(r) + '<td colspan="' + t + '" aria-expanded="true"><p class="k-reset"><a class="k-icon k-i-collapse" href="#" tabindex="-1"><\/a>' + v + "<\/p><\/td><\/tr>", n.hasSubgroups)
-                        for (o = 0, l = c.length; o < l; o++) e += f._groupRowHtml(c[o], t - 1, r + 1);
-                    else e += f._rowsHtml(c);
-                    return f.groupFooterTemplate && (e += f.groupFooterTemplate(u(p, n.aggregates))), e
-                },
-                collapseGroup: function(t) {
-                    t = n(t).find(".k-icon").addClass("k-i-expand").removeClass("k-i-collapse").end();
-                    var f = t.find(".k-group-cell").length,
-                        r = 1,
-                        u, i;
-                    t.find("td:first").attr("aria-expanded", !1);
-                    t.nextAll("tr").each(function() {
-                        if (i = n(this), u = i.find(".k-group-cell").length, i.hasClass("k-grouping-row") ? r++ : i.hasClass("k-group-footer") && r--, u <= f || i.hasClass("k-group-footer") && r < 0) return !1;
-                        i.hide()
-                    })
-                },
-                expandGroup: function(t) {
-                    t = n(t).find(".k-icon").addClass("k-i-collapse").removeClass("k-i-expand").end();
-                    var e = this,
-                        f = t.find(".k-group-cell").length,
-                        i, r, u = 1;
-                    t.find("td:first").attr("aria-expanded", !0);
-                    t.nextAll("tr").each(function() {
-                        if (i = n(this), r = i.find(".k-group-cell").length, r <= f) return !1;
-                        r != f + 1 || i.hasClass("k-detail-row") || (i.show(), i.hasClass("k-grouping-row") && i.find(".k-icon").hasClass("k-i-collapse") && e.expandGroup(i), i.hasClass("k-master-row") && i.find(".k-icon").hasClass("k-minus") && i.next().show());
-                        i.hasClass("k-grouping-row") && u++;
-                        i.hasClass("k-group-footer") && (u == 1 ? i.show() : u--)
-                    })
-                },
-                _updateHeader: function(t) {
-                    var r = this,
-                        u = r.thead.find("th.k-group-cell"),
-                        i = u.length;
-                    t > i ? n(new Array(t - i + 1).join('<th class="k-group-cell k-header">&nbsp;<\/th>')).prependTo(r.thead.find("tr")) : t < i && (i = i - t, n(b(u, function(n, t) {
-                        return i > t
-                    })).remove())
-                },
-                _firstDataItem: function(n, t) {
-                    return n && t && (n = n.hasSubgroups ? this._firstDataItem(n.items[0], t) : n.items[0]), n
-                },
-                hideColumn: function(t) {
-                    var i = this,
-                        a, f, r, h, u, v, c, o = 0,
-                        l, y = i.footer || i.wrapper.find(".k-grid-footer"),
-                        p = i.columns,
-                        s;
-                    if (t = typeof t == "number" ? p[t] : b(p, function(n) {
-                            return n.field === t
-                        })[0], t && !t.hidden) {
-                        for (s = d(t, tt(p)), t.hidden = !0, t.attributes = ot(t.attributes), t.footerAttributes = ot(t.footerAttributes), t.headerAttributes = ot(t.headerAttributes), i._templates(), i._updateCols(), st(i.thead.find(">tr")[0].cells, s, !1), y[0] && (i._appendCols(y.find("table:first")), st(y.find(".k-footer-template")[0].cells, s, !1)), a = i.tbody.children(), u = 0, l = a.length; u < l; u += 1) f = a.eq(u), f.is(".k-grouping-row,.k-detail-row") ? (r = f.children(":not(.k-group-cell):first,.k-detail-cell").last(), r.attr("colspan", parseInt(r.attr("colspan"), 10) - 1)) : (f.hasClass("k-grid-edit-row") && (r = f.children(".k-edit-container")[0]) && (r = n(r), r.attr("colspan", parseInt(r.attr("colspan"), 10) - 1), r.find("col").eq(s).remove(), f = r.find("tr:first")), st(f[0].cells, s, !1));
-                        for (v = i.thead.prev().find("col"), u = 0, l = v.length; u < l; u += 1)
-                            if (c = v[u].style.width, c && c.indexOf("%") == -1) o += parseInt(c, 10);
-                            else {
-                                o = 0;
-                                break
-                            }
-                        h = n(">.k-grid-header table:first,>.k-grid-footer table:first", i.wrapper).add(i.table);
-                        i._footerWidth = null;
-                        o && (h.width(o), i._footerWidth = o);
-                        e.msie && e.version == 8 && (h.css("display", "inline-table"), setTimeout(function() {
-                            h.css("display", "table")
-                        }, 1));
-                        i.trigger(li, {
-                            column: t
-                        })
-                    }
-                },
-                showColumn: function(t) {
-                    var i = this,
-                        c, u, o, f, r, l, e, a, v, s = i.columns,
-                        y = i.footer || i.wrapper.find(".k-grid-footer"),
-                        h;
-                    if (t = typeof t == "number" ? s[t] : b(s, function(n) {
-                            return n.field === t
-                        })[0], t && t.hidden) {
-                        for (h = d(t, s), t.hidden = !1, t.attributes = ei(t.attributes), t.footerAttributes = ei(t.footerAttributes), t.headerAttributes = ei(t.headerAttributes), i._templates(), i._updateCols(), st(i.thead.find(">tr")[0].cells, h, !0), y[0] && (i._appendCols(y.find("table:first")), st(y.find(".k-footer-template")[0].cells, h, !0)), c = i.tbody.children(), u = 0, o = c.length; u < o; u += 1) f = c.eq(u), f.is(".k-grouping-row,.k-detail-row") ? (r = f.children(":not(.k-group-cell):first,.k-detail-cell").last(), r.attr("colspan", parseInt(r.attr("colspan"), 10) + 1)) : (f.hasClass("k-grid-edit-row") && (r = f.children(".k-edit-container")[0]) && (r = n(r), r.attr("colspan", parseInt(r.attr("colspan"), 10) + 1), ir(r.find(">form>table"), tt(s), !1, 0), f = r.find("tr:first")), st(f[0].cells, h, !0));
-                        if (l = n(">.k-grid-header table:first,>.k-grid-footer table:first", i.wrapper).add(i.table), t.width) {
-                            for (e = 0, v = i.thead.prev().find("col"), u = 0, o = v.length; u < o; u += 1) {
-                                if (a = v[u].style.width, a.indexOf("%") > -1) {
-                                    e = 0;
-                                    break
-                                }
-                                e += parseInt(a, 10)
-                            }
-                            i._footerWidth = null;
-                            e && (l.width(e), i._footerWidth = e)
-                        } else l.width("");
-                        i.trigger(ai, {
-                            column: t
-                        })
-                    }
-                },
-                _progress: function(n) {
-                    var t = this,
-                        r = t.element.is("table") ? t.element.parent() : t.content && t.content.length ? t.content : t.element;
-                    i.ui.progress(r, n)
-                },
-                _resize: function() {
-                    this.content && (this._setContentHeight(), this._setContentWidth())
-                },
-                refresh: function(t) {
-                    var i = this,
-                        y, f, e = "",
-                        o = i.dataSource.view(),
-                        w = i.options.navigatable,
-                        s, h, u, p = n(i.current()),
-                        c = !1,
-                        r = (i.dataSource.group() || []).length,
-                        a = r + tt(i.columns).length,
-                        v;
-                    if ((!t || t.action !== "itemchange" || !i.editable) && (t = t || {}, !i.trigger("dataBinding", {
-                            action: t.action || "rebind",
-                            index: t.index,
-                            items: t.items
-                        }))) {
-                        if (v = rt(), w && (i.table[0] === v || n.contains(i.table[0], v) || i._editContainer && i._editContainer.data("kendoWindow")) && (c = p.is("th"), u = 0, c && (u = i.thead.find("th:not(.k-group-cell)").index(p))), i._destroyEditable(), i._progress(!1), i._hideResizeHandle(), i._data = [], i.columns.length || (i._autoColumns(i._firstDataItem(o[0], r)), a = r + i.columns.length), i._group = r > 0 || i._group, i._group && (i._templates(), i._updateCols(), i._updateHeader(r), i._group = r > 0), r > 0)
-                            for (i.detailTemplate && a++, i.groupFooterTemplate && (i._groupAggregatesDefaultObject = fi(i.dataSource.aggregate())), f = 0, y = o.length; f < y; f++) e += i._groupRowHtml(o[f], a, 0);
-                        else e += i._rowsHtml(o);
-                        er ? i.tbody[0].innerHTML = e : (h = document.createElement("div"), h.innerHTML = "<table><tbody>" + e + "<\/tbody><\/table>", s = h.firstChild.firstChild, i.table[0].replaceChild(s, i.tbody[0]), i.tbody = n(s));
-                        i._footer();
-                        i._setContentHeight();
-                        i._setContentWidth();
-                        u >= 0 && (i._removeCurrent(), c ? i.current(i.thead.find("th:not(.k-group-cell)").eq(u)) : i.current(i.items().eq(u).children().filter(g).first()), i._current && l(i._current.closest("table")[0], !0));
-                        i.trigger(yi)
-                    }
-                }
-            });
-        it.plugin(kr);
-        it.plugin(tr)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "listview",
-        name: "ListView",
-        category: "web",
-        description: "The ListView widget offers rich support for interacting with data.",
-        depends: ["data"],
-        features: [{
-            id: "listview-editing",
-            name: "Editing",
-            description: "Support for record editing",
-            depends: ["editable"]
-        }, {
-            id: "listview-selection",
-            name: "Selection",
-            description: "Support for selection",
-            depends: ["selectable"]
-        }]
-    }),
-    function(n, t) {
-        var i = window.kendo,
-            f = "change",
-            c = "cancel",
-            l = "dataBound",
-            a = "dataBinding",
-            e = i.ui.Widget,
-            r = i.keys,
-            v = ">*",
-            y = "progress",
-            p = "error",
-            s = "k-state-focused",
-            w = "k-state-selected",
-            h = "k-edit-item",
-            tt = "string",
-            b = "edit",
-            k = "remove",
-            d = "save",
-            it = "click",
-            u = ".kendoListView",
-            o = n.proxy,
-            g = i._activeElement,
-            nt = i.ui.progress,
-            rt = i.data.DataSource,
-            ut = e.extend({
-                init: function(t, r) {
-                    var u = this;
-                    r = n.isArray(r) ? {
-                        dataSource: r
-                    } : r;
-                    e.fn.init.call(u, t, r);
-                    r = u.options;
-                    u.wrapper = t = u.element;
-                    t[0].id && (u._itemId = t[0].id + "_lv_active");
-                    u._element();
-                    u._dataSource();
-                    u._templates();
-                    u._navigatable();
-                    u._selectable();
-                    u._pageable();
-                    u._crudHandlers();
-                    u.options.autoBind && u.dataSource.fetch();
-                    i.notify(u)
-                },
-                events: [f, c, a, l, b, k, d],
-                options: {
-                    name: "ListView",
-                    autoBind: !0,
-                    selectable: !1,
-                    navigatable: !1,
-                    template: "",
-                    altTemplate: "",
-                    editTemplate: ""
-                },
-                setOptions: function(n) {
-                    e.fn.setOptions.call(this, n);
-                    this._templates()
-                },
-                _templates: function() {
-                    var n = this.options;
-                    this.template = i.template(n.template || "");
-                    this.altTemplate = i.template(n.altTemplate || n.template);
-                    this.editTemplate = i.template(n.editTemplate || "")
-                },
-                _item: function(n) {
-                    return this.element.children()[n]()
-                },
-                items: function() {
-                    return this.element.children()
-                },
-                setDataSource: function(n) {
-                    this.options.dataSource = n;
-                    this._dataSource();
-                    this.options.autoBind && n.fetch()
-                },
-                _unbindDataSource: function() {
-                    var n = this;
-                    n.dataSource.unbind(f, n._refreshHandler).unbind(y, n._progressHandler).unbind(p, n._errorHandler)
-                },
-                _dataSource: function() {
-                    var n = this;
-                    n.dataSource && n._refreshHandler ? n._unbindDataSource() : (n._refreshHandler = o(n.refresh, n), n._progressHandler = o(n._progress, n), n._errorHandler = o(n._error, n));
-                    n.dataSource = rt.create(n.options.dataSource).bind(f, n._refreshHandler).bind(y, n._progressHandler).bind(p, n._errorHandler)
-                },
-                _progress: function() {
-                    nt(this.element, !0)
-                },
-                _error: function() {
-                    nt(this.element, !1)
-                },
-                _element: function() {
-                    this.element.addClass("k-widget k-listview").attr("role", "listbox")
-                },
-                refresh: function(n) {
-                    var t = this,
-                        f = t.dataSource.view(),
-                        e, s, u, h = "",
-                        r, o, c = t.template,
-                        v = t.altTemplate,
-                        y = g();
-                    if (n = n || {}, n.action === "itemchange") {
-                        t._hasBindingTarget() || t.editable || (e = n.items[0], u = t.items().filter("[" + i.attr("uid") + "=" + e.uid + "]"), u.length > 0 && (r = u.index(), u.replaceWith(c(e)), u = t.items().eq(r), u.attr(i.attr("uid"), e.uid), t.trigger("itemChange", {
-                            item: u,
-                            data: e
-                        })));
-                        return
-                    }
-                    if (!t.trigger(a, {
-                            action: n.action || "rebind",
-                            items: n.items,
-                            index: n.index
-                        })) {
-                        for (t._destroyEditable(), r = 0, o = f.length; r < o; r++) h += r % 2 ? v(f[r]) : c(f[r]);
-                        for (t.element.html(h), s = t.items(), r = 0, o = f.length; r < o; r++) s.eq(r).attr(i.attr("uid"), f[r].uid).attr("role", "option").attr("aria-selected", "false");
-                        t.element[0] === y && t.options.navigatable && t.current(s.eq(0));
-                        t.trigger(l)
-                    }
-                },
-                _pageable: function() {
-                    var t = this,
-                        r = t.options.pageable,
-                        u, f;
-                    n.isPlainObject(r) && (f = r.pagerId, u = n.extend({}, r, {
-                        dataSource: t.dataSource,
-                        pagerId: null
-                    }), t.pager = new i.ui.Pager(n("#" + f), u))
-                },
-                _selectable: function() {
-                    var n = this,
-                        e, t, o = n.options.selectable,
-                        s = n.options.navigatable;
-                    if (o && (e = typeof o === tt && o.toLowerCase().indexOf("multiple") > -1, e && n.element.attr("aria-multiselectable", !0), n.selectable = new i.ui.Selectable(n.element, {
-                            aria: !0,
-                            multiple: e,
-                            filter: v,
-                            change: function() {
-                                n.trigger(f)
-                            }
-                        }), s)) n.element.on("keydown" + u, function(i) {
-                        if (i.keyCode === r.SPACEBAR) {
-                            if (t = n.current(), i.target == i.currentTarget && i.preventDefault(), e)
-                                if (i.ctrlKey) {
-                                    if (t && t.hasClass(w)) {
-                                        t.removeClass(w);
-                                        return
-                                    }
-                                } else n.selectable.clear();
-                            else n.selectable.clear();
-                            n.selectable.value(t)
-                        }
-                    })
-                },
-                current: function(n) {
-                    var r = this,
-                        f = r.element,
-                        i = r._current,
-                        u = r._itemId;
-                    if (n === t) return i;
-                    i && i[0] && (i[0].id === u && i.removeAttr("id"), i.removeClass(s), f.removeAttr("aria-activedescendant"));
-                    n && n[0] && (u = n[0].id || u, r._scrollTo(n[0]), f.attr("aria-activedescendant", u), n.addClass(s).attr("id", u));
-                    r._current = n
-                },
-                _scrollTo: function(t) {
-                    var u = this,
-                        i, e = !1,
-                        r = "scroll",
-                        f;
-                    u.wrapper.css("overflow") == "auto" || u.wrapper.css("overflow") == r ? i = u.wrapper[0] : (i = window, e = !0);
-                    f = function(u, f) {
-                        var o = e ? n(t).offset()[u.toLowerCase()] : t["offset" + u],
-                            s = t["client" + f],
-                            h = n(i)[r + u](),
-                            c = n(i)[f.toLowerCase()]();
-                        o + s > h + c ? n(i)[r + u](o + s - c) : o < h && n(i)[r + u](o)
-                    };
-                    f("Top", "Height");
-                    f("Left", "Width")
-                },
-                _navigatable: function() {
-                    var t = this,
-                        e = t.options.navigatable,
-                        f = t.element,
-                        c = function(i) {
-                            t.current(n(i.currentTarget));
-                            n(i.target).is(":button,a,:input,a>.k-icon,textarea") || f.focus()
-                        };
-                    if (e) {
-                        t._tabindex();
-                        f.on("focus" + u, function() {
-                            var n = t._current;
-                            n && n.is(":visible") || (n = t._item("first"));
-                            t.current(n)
-                        }).on("focusout" + u, function() {
-                            t._current && t._current.removeClass(s)
-                        }).on("keydown" + u, function(u) {
-                            var e = u.keyCode,
-                                o = t.current(),
-                                v = n(u.target),
-                                y = !v.is(":button,textarea,a,a>.t-icon,input"),
-                                a = v.is(":text"),
-                                s = i.preventDefault,
-                                c = f.find("." + h),
-                                p = g(),
-                                l, w;
-                            if ((y || a || r.ESC == e) && (!a || r.ESC == e || r.ENTER == e))
-                                if (r.UP === e || r.LEFT === e) o && (o = o.prev()), t.current(!o || !o[0] ? t._item("last") : o), s(u);
-                                else if (r.DOWN === e || r.RIGHT === e) o && (o = o.next()), t.current(!o || !o[0] ? t._item("first") : o), s(u);
-                            else if (r.PAGEUP === e) t.current(null), t.dataSource.page(t.dataSource.page() - 1), s(u);
-                            else if (r.PAGEDOWN === e) t.current(null), t.dataSource.page(t.dataSource.page() + 1), s(u);
-                            else if (r.HOME === e) t.current(t._item("first")), s(u);
-                            else if (r.END === e) t.current(t._item("last")), s(u);
-                            else if (r.ENTER === e)
-                                if (c.length !== 0 && (y || a)) {
-                                    l = t.items().index(c);
-                                    p && p.blur();
-                                    t.save();
-                                    w = function() {
-                                        t.element.trigger("focus");
-                                        t.current(t.items().eq(l))
-                                    };
-                                    t.one("dataBound", w)
-                                } else t.options.editTemplate !== "" && t.edit(o);
-                            else if (r.ESC === e) {
-                                if (c = f.find("." + h), c.length === 0) return;
-                                l = t.items().index(c);
-                                t.cancel();
-                                t.element.trigger("focus");
-                                t.current(t.items().eq(l))
-                            }
-                        });
-                        f.on("mousedown" + u + " touchstart" + u, v, o(c, t))
-                    }
-                },
-                clearSelection: function() {
-                    var n = this;
-                    n.selectable.clear();
-                    n.trigger(f)
-                },
-                select: function(t) {
-                    var r = this,
-                        i = r.selectable;
-                    if (t = n(t), t.length) {
-                        i.options.multiple || (i.clear(), t = t.first());
-                        i.value(t);
-                        return
-                    }
-                    return i.value()
-                },
-                _destroyEditable: function() {
-                    var n = this;
-                    n.editable && (n.editable.destroy(), delete n.editable)
-                },
-                _modelFromElement: function(n) {
-                    var t = n.attr(i.attr("uid"));
-                    return this.dataSource.getByUid(t)
-                },
-                _closeEditable: function(n) {
-                    var t = this,
-                        r = t.editable,
-                        u, e, o = t.template,
-                        f = !0;
-                    return r && (n && (f = r.end()), f && (r.element.index() % 2 && (o = t.altTemplate), u = t._modelFromElement(r.element), t._destroyEditable(), e = r.element.index(), r.element.replaceWith(o(u)), t.items().eq(e).attr(i.attr("uid"), u.uid))), f
-                },
-                edit: function(n) {
-                    var t = this,
-                        r = t._modelFromElement(n),
-                        u, e = r.uid,
-                        f;
-                    t.cancel();
-                    n = t.items().filter("[" + i.attr("uid") + "=" + e + "]");
-                    f = n.index();
-                    n.replaceWith(t.editTemplate(r));
-                    u = t.items().eq(f).addClass(h).attr(i.attr("uid"), r.uid);
-                    t.editable = u.kendoEditable({
-                        model: r,
-                        clearContainer: !1,
-                        errorTemplate: !1
-                    }).data("kendoEditable");
-                    t.trigger(b, {
-                        model: r,
-                        item: u
-                    })
-                },
-                save: function() {
-                    var n = this,
-                        t = n.editable,
-                        i;
-                    t && (t = t.element, i = n._modelFromElement(t), !n.trigger(d, {
-                        model: i,
-                        item: t
-                    }) && n._closeEditable(!0) && n.dataSource.sync())
-                },
-                remove: function(n) {
-                    var t = this,
-                        i = t.dataSource,
-                        r = t._modelFromElement(n);
-                    t.trigger(k, {
-                        model: r,
-                        item: n
-                    }) || (n.hide(), i.remove(r), i.sync())
-                },
-                add: function() {
-                    var n = this,
-                        t = n.dataSource,
-                        i = t.indexOf((t.view() || [])[0]);
-                    i < 0 && (i = 0);
-                    n.cancel();
-                    t.insert(i, {});
-                    n.edit(n.element.children().first())
-                },
-                cancel: function() {
-                    var n = this,
-                        r = n.dataSource,
-                        t, i;
-                    n.editable && (t = n.editable.element, i = n._modelFromElement(t), n.trigger(c, {
-                        model: i,
-                        container: t
-                    }) || (r.cancelChanges(i), n._closeEditable(!1)))
-                },
-                _crudHandlers: function() {
-                    var t = this,
-                        r = it + u;
-                    t.element.on(r, ".k-edit-button", function(r) {
-                        var u = n(this).closest("[" + i.attr("uid") + "]");
-                        t.edit(u);
-                        r.preventDefault()
-                    });
-                    t.element.on(r, ".k-delete-button", function(r) {
-                        var u = n(this).closest("[" + i.attr("uid") + "]");
-                        t.remove(u);
-                        r.preventDefault()
-                    });
-                    t.element.on(r, ".k-update-button", function(n) {
-                        t.save();
-                        n.preventDefault()
-                    });
-                    t.element.on(r, ".k-cancel-button", function(n) {
-                        t.cancel();
-                        n.preventDefault()
-                    })
-                },
-                destroy: function() {
-                    var n = this;
-                    e.fn.destroy.call(n);
-                    n._unbindDataSource();
-                    n._destroyEditable();
-                    n.element.off(u);
-                    n.pager && n.pager.destroy();
-                    n.selectable && n.selectable.destroy();
-                    i.destroy(n.element)
-                }
-            });
-        i.ui.plugin(ut)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "numerictextbox",
-        name: "NumericTextBox",
-        category: "web",
-        description: "The NumericTextBox widget can format and display numeric, percentage or currency textbox.",
-        depends: ["core", "userevents"]
-    }),
-    function(n, t) {
-        function ut(n, t) {
-            return '<span unselectable="on" class="k-link"><span unselectable="on" class="k-icon k-i-arrow-' + n + '" title="' + t + '">' + t + "<\/span><\/span>"
-        }
-
-        function y(i, r) {
-            var f, s = r !== t,
-                u, e, o, h;
-            return i.selectionStart !== t ? s ? (i.focus(), i.setSelectionRange(r, r)) : r = [i.selectionStart, i.selectionEnd] : document.selection && (n(i).is(":visible") && i.focus(), f = document.selection.createRange(), s ? (f.move("character", r), f.select()) : (u = i.createTextRange(), e = u.duplicate(), u.moveToBookmark(f.getBookmark()), e.setEndPoint("EndToStart", u), o = e.text.length, h = o + u.text.length, r = [o, h])), r
-        }
-        var r = window.kendo,
-            e = r.keys,
-            p = r.ui,
-            s = p.Widget,
-            ft = r._activeElement,
-            et = r._extractFormat,
-            ot = r.parseFloat,
-            st = r.support.placeholder,
-            ht = r.getCulture,
-            w = r._round,
-            h = "change",
-            b = "disabled",
-            k = "readonly",
-            ct = "k-input",
-            d = "spin",
-            u = ".kendoNumericTextBox",
-            lt = "touchend",
-            at = "mouseleave" + u,
-            g = "mouseenter" + u + " " + at,
-            c = "k-state-default",
-            nt = "k-state-focused",
-            tt = "k-state-hover",
-            l = "focus",
-            f = ".",
-            a = "k-state-selected",
-            v = "k-state-disabled",
-            it = "aria-disabled",
-            rt = "aria-readonly",
-            vt = /^(-)?(\d*)$/,
-            i = null,
-            o = n.proxy,
-            yt = s.extend({
-                init: function(n, f) {
-                    var e = this,
-                        p = f && f.step !== t,
-                        h, c, a, v, y;
-                    if (s.fn.init.call(e, n, f), f = e.options, n = e.element.on("blur" + u, o(e._focusout, e)).attr("role", "spinbutton"), f.placeholder = f.placeholder || n.attr("placeholder"), e._reset(), e._wrapper(), e._arrows(), e._input(), r.support.mobileOS) e._text.on(lt + u + " " + l + u, function(t) {
-                        e._toggleText(!1);
-                        t.type === l && n.focus()
-                    });
-                    else e._text.on(l + u, o(e._click, e));
-                    h = e.min(n.attr("min"));
-                    c = e.max(n.attr("max"));
-                    a = e._parse(n.attr("step"));
-                    f.min === i && h !== i && (f.min = h);
-                    f.max === i && c !== i && (f.max = c);
-                    p || a === i || (f.step = a);
-                    n.attr("aria-valuemin", f.min).attr("aria-valuemax", f.max);
-                    f.format = et(f.format);
-                    v = f.value;
-                    e.value(v !== i ? v : n.val());
-                    y = n.is("[disabled]");
-                    y ? e.enable(!1) : e.readonly(n.is("[readonly]"));
-                    r.notify(e)
-                },
-                options: {
-                    name: "NumericTextBox",
-                    decimals: i,
-                    min: i,
-                    max: i,
-                    value: i,
-                    step: 1,
-                    culture: "",
-                    format: "n",
-                    spinners: !0,
-                    placeholder: "",
-                    upArrowText: "Increase value",
-                    downArrowText: "Decrease value"
-                },
-                events: [h, d],
-                _editable: function(n) {
-                    var t = this,
-                        f = t.element,
-                        i = n.disable,
-                        r = n.readonly,
-                        e = t._text.add(f),
-                        s = t._inputWrapper.off(g);
-                    if (t._toggleText(!0), t._upArrowEventHandler.unbind("press"), t._downArrowEventHandler.unbind("press"), f.off("keydown" + u).off("keypress" + u).off("paste" + u), r || i) s.addClass(i ? v : c).removeClass(i ? c : v), e.attr(b, i).attr(k, r).attr(it, i).attr(rt, r);
-                    else {
-                        s.addClass(c).removeClass(v).on(g, t._toggleHover);
-                        e.removeAttr(b).removeAttr(k).attr(it, !1).attr(rt, !1);
-                        t._upArrowEventHandler.bind("press", function(n) {
-                            n.preventDefault();
-                            t._spin(1);
-                            t._upArrow.addClass(a)
-                        });
-                        t._downArrowEventHandler.bind("press", function(n) {
-                            n.preventDefault();
-                            t._spin(-1);
-                            t._downArrow.addClass(a)
-                        });
-                        t.element.on("keydown" + u, o(t._keydown, t)).on("keypress" + u, o(t._keypress, t)).on("paste" + u, o(t._paste, t))
-                    }
-                },
-                readonly: function(n) {
-                    this._editable({
-                        readonly: n === t ? !0 : n,
-                        disable: !1
-                    })
-                },
-                enable: function(n) {
-                    this._editable({
-                        readonly: !1,
-                        disable: !(n = n === t ? !0 : n)
-                    })
-                },
-                destroy: function() {
-                    var n = this;
-                    n.element.add(n._text).add(n._upArrow).add(n._downArrow).add(n._inputWrapper).off(u);
-                    n._upArrowEventHandler.destroy();
-                    n._downArrowEventHandler.destroy();
-                    n._form && n._form.off("reset", n._resetHandler);
-                    s.fn.destroy.call(n)
-                },
-                min: function(n) {
-                    return this._option("min", n)
-                },
-                max: function(n) {
-                    return this._option("max", n)
-                },
-                step: function(n) {
-                    return this._option("step", n)
-                },
-                value: function(n) {
-                    var i = this,
-                        r;
-                    if (n === t) return i._value;
-                    (n = i._parse(n), r = i._adjust(n), n === r) && (i._update(n), i._old = i._value)
-                },
-                focus: function() {
-                    this._focusin()
-                },
-                _adjust: function(n) {
-                    var f = this,
-                        u = f.options,
-                        t = u.min,
-                        r = u.max;
-                    return n === i ? n : (t !== i && n < t ? n = t : r !== i && n > r && (n = r), n)
-                },
-                _arrows: function() {
-                    var t = this,
-                        i, f = function() {
-                            clearTimeout(t._spinning);
-                            i.removeClass(a)
-                        },
-                        u = t.options,
-                        e = u.spinners,
-                        o = t.element;
-                    i = o.siblings(".k-icon");
-                    i[0] || (i = n(ut("n", u.upArrowText) + ut("s", u.downArrowText)).insertAfter(o), i.wrapAll('<span class="k-select"/>'));
-                    e || (i.parent().toggle(e), t._inputWrapper.addClass("k-expand-padding"));
-                    t._upArrow = i.eq(0);
-                    t._upArrowEventHandler = new r.UserEvents(t._upArrow, {
-                        release: f
-                    });
-                    t._downArrow = i.eq(1);
-                    t._downArrowEventHandler = new r.UserEvents(t._downArrow, {
-                        release: f
-                    })
-                },
-                _blur: function() {
-                    var n = this;
-                    n._toggleText(!0);
-                    n._change(n.element.val())
-                },
-                _click: function(n) {
-                    var t = this;
-                    clearTimeout(t._focusing);
-                    t._focusing = setTimeout(function() {
-                        var o = n.target,
-                            l = y(o)[0],
-                            s = o.value.substring(0, l),
-                            h = t._format(t.options.format),
-                            i = h[","],
-                            r, c, u, e = 0;
-                        i && (c = new RegExp("\\" + i, "g"), u = new RegExp("([\\d\\" + i + "]+)(\\" + h[f] + ")?(\\d+)?"));
-                        u && (r = u.exec(s));
-                        r && (e = r[0].replace(c, "").length, s.indexOf("(") != -1 && t._value < 0 && e++);
-                        t._focusin();
-                        y(t.element[0], e)
-                    })
-                },
-                _change: function(n) {
-                    var t = this;
-                    t._update(n);
-                    n = t._value;
-                    t._old != n && (t._old = n, t.trigger(h), t.element.trigger(h))
-                },
-                _culture: function(n) {
-                    return n || ht(this.options.culture)
-                },
-                _focusin: function() {
-                    var n = this;
-                    n._inputWrapper.addClass(nt);
-                    n._toggleText(!1);
-                    n.element[0].focus()
-                },
-                _focusout: function() {
-                    var n = this;
-                    clearTimeout(n._focusing);
-                    n._inputWrapper.removeClass(nt).removeClass(tt);
-                    n._blur()
-                },
-                _format: function(n, t) {
-                    var i = this._culture(t).numberFormat;
-                    return n = n.toLowerCase(), n.indexOf("c") > -1 ? i = i.currency : n.indexOf("p") > -1 && (i = i.percent), i
-                },
-                _input: function() {
-                    var r = this,
-                        u = "k-formatted-value",
-                        t = r.element.addClass(ct).show()[0],
-                        e = t.accessKey,
-                        o = r.wrapper,
-                        i;
-                    i = o.find(f + u);
-                    i[0] || (i = n('<input type="text"/>').insertBefore(t).addClass(u));
-                    try {
-                        t.setAttribute("type", "text")
-                    } catch (s) {
-                        t.type = "text"
-                    }
-                    i[0].tabIndex = t.tabIndex;
-                    i[0].style.cssText = t.style.cssText;
-                    i.prop("placeholder", r.options.placeholder);
-                    e && (i.attr("accesskey", e), t.accessKey = "");
-                    r._text = i.addClass(t.className)
-                },
-                _keydown: function(n) {
-                    var t = this,
-                        i = n.keyCode;
-                    i == e.DOWN ? t._step(-1) : i == e.UP ? t._step(1) : i == e.ENTER && t._change(t.element.val())
-                },
-                _keypress: function(n) {
-                    if (n.which !== 0 && n.keyCode !== e.BACKSPACE && n.keyCode !== e.ENTER) {
-                        var i = this.element,
-                            f = String.fromCharCode(n.which),
-                            r = y(i[0]),
-                            o = r[0],
-                            s = r[1],
-                            u = this.options.min,
-                            t = i.val();
-                        t = t.substring(0, o) + f + t.substring(s);
-                        (u !== null && u >= 0 && t.charAt(0) === "-" || !this._numericRegex().test(t)) && n.preventDefault()
-                    }
-                },
-                _numericRegex: function() {
-                    var t = this,
-                        u = t.options,
-                        e = t._format(u.format),
-                        n = e[f],
-                        r = u.decimals;
-                    return (n === f && (n = "\\" + n), r === i && (r = e.decimals), r === 0) ? vt : (t._separator !== n && (t._separator = n, t._floatRegExp = new RegExp("^(-)?(((\\d+(" + n + "\\d*)?)|(" + n + "\\d*)))?$")), t._floatRegExp)
-                },
-                _paste: function(n) {
-                    var t = this,
-                        r = n.target,
-                        u = r.value;
-                    setTimeout(function() {
-                        t._parse(r.value) === i && t._update(u)
-                    })
-                },
-                _option: function(n, i) {
-                    var r = this,
-                        u = r.options;
-                    if (i === t) return u[n];
-                    (i = r._parse(i), i || n !== "step") && (u[n] = i, r.element.attr("aria-value" + n, i).attr(n, i))
-                },
-                _spin: function(n, t) {
-                    var i = this;
-                    t = t || 500;
-                    clearTimeout(i._spinning);
-                    i._spinning = setTimeout(function() {
-                        i._spin(n, 50)
-                    }, t);
-                    i._step(n)
-                },
-                _step: function(n) {
-                    var t = this,
-                        i = t.element,
-                        r = t._parse(i.val()) || 0;
-                    ft() != i[0] && t._focusin();
-                    r += t.options.step * n;
-                    t._update(t._adjust(r));
-                    t.trigger(d)
-                },
-                _toggleHover: function(t) {
-                    n(t.currentTarget).toggleClass(tt, t.type === "mouseenter")
-                },
-                _toggleText: function(n) {
-                    var t = this;
-                    t._text.toggle(n);
-                    t.element.toggle(!n)
-                },
-                _parse: function(n, t) {
-                    return ot(n, this._culture(t), this.options.format)
-                },
-                _update: function(n) {
-                    var t = this,
-                        s = t.options,
-                        h = s.format,
-                        u = s.decimals,
-                        e = t._culture(),
-                        c = t._format(h, e),
-                        o;
-                    u === i && (u = c.decimals);
-                    n = t._parse(n, e);
-                    o = n !== i;
-                    o && (n = parseFloat(w(n, u)));
-                    t._value = n = t._adjust(n);
-                    t._placeholder(r.toString(n, h, e));
-                    o ? (n = n.toString(), n.indexOf("e") !== -1 && (n = w(+n, u)), n = n.replace(f, c[f])) : n = "";
-                    t.element.val(n).attr("aria-valuenow", n)
-                },
-                _placeholder: function(n) {
-                    this._text.val(n);
-                    st || n || this._text.val(this.options.placeholder)
-                },
-                _wrapper: function() {
-                    var i = this,
-                        r = i.element,
-                        u = r[0],
-                        t;
-                    t = r.parents(".k-numerictextbox");
-                    t.is("span.k-numerictextbox") || (t = r.hide().wrap('<span class="k-numeric-wrap k-state-default" />').parent(), t = t.wrap("<span/>").parent());
-                    t[0].style.cssText = u.style.cssText;
-                    u.style.width = "";
-                    i.wrapper = t.addClass("k-widget k-numerictextbox").addClass(u.className).css("display", "");
-                    i._inputWrapper = n(t[0].firstChild)
-                },
-                _reset: function() {
-                    var t = this,
-                        i = t.element,
-                        r = i.attr("form"),
-                        u = r ? n("#" + r) : i.closest("form");
-                    u[0] && (t._resetHandler = function() {
-                        setTimeout(function() {
-                            t.value(i[0].value)
-                        })
-                    }, t._form = u.on("reset", t._resetHandler))
-                }
-            });
-        p.plugin(yt)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "menu",
-        name: "Menu",
-        category: "web",
-        description: "The Menu widget displays hierarchical data as a multi-level menu.",
-        depends: ["popup"]
-    }),
-    function(n, t) {
-        function yi(n, t) {
-            return n = n.split(" ")[!t + 0] || n, n.replace("top", "up").replace("bottom", "down")
-        }
-
-        function pi(n, t, r) {
-            n = n.split(" ")[!t + 0] || n;
-            var u = {
-                    origin: ["bottom", r ? "right" : "left"],
-                    position: ["top", r ? "right" : "left"]
-                },
-                f = /left|right/.test(n);
-            return f ? (u.origin = ["top", n], u.position[1] = i.directions[n].reverse) : (u.origin[0] = n, u.position[0] = i.directions[n].reverse), u.origin = u.origin.join(" "), u.position = u.position.join(" "), u
-        }
-
-        function d(t, i) {
-            try {
-                return n.contains(t, i)
-            } catch (r) {
-                return !1
-            }
-        }
-
-        function oi(t) {
-            t = n(t);
-            t.addClass("k-item").children(pt).addClass(kt);
-            t.children("a").addClass(k).children(pt).addClass(kt);
-            t.filter(":not([disabled])").addClass(ui);
-            t.filter(".k-separator:empty").append("&nbsp;");
-            t.filter("li[disabled]").addClass(y).removeAttr("disabled").attr("aria-disabled", !0);
-            t.filter("[role]").length || t.attr("role", "menuitem");
-            t.children("." + k).length || t.contents().filter(function() {
-                return !this.nodeName.match(ci) && !(this.nodeType == 3 && !n.trim(this.nodeValue))
-            }).wrapAll("<span class='" + k + "'/>");
-            b(t);
-            c(t)
-        }
-
-        function b(t) {
-            t = n(t);
-            t.find("> .k-link > [class*=k-i-arrow]:not(.k-sprite)").remove();
-            t.filter(":has(.k-group)").children(".k-link:not(:has([class*=k-i-arrow]:not(.k-sprite)))").each(function() {
-                var t = n(this),
-                    i = t.parent().parent();
-                t.append("<span class='k-icon " + (i.hasClass(h + "-horizontal") ? "k-i-arrow-s" : "k-i-arrow-e") + "'/>")
-            })
-        }
-
-        function c(t) {
-            t = n(t);
-            t.filter(".k-first:not(:first-child)").removeClass(bt);
-            t.filter(".k-last:not(:last-child)").removeClass(wt);
-            t.filter(":first-child").addClass(bt);
-            t.filter(":last-child").addClass(wt)
-        }
-        var i = window.kendo,
-            si = i.ui,
-            hi = i._activeElement,
-            ft = i.support.touch && i.support.mobileOS,
-            et = "mousedown",
-            ot = "click",
-            f = n.extend,
-            u = n.proxy,
-            st = n.each,
-            o = i.template,
-            e = i.keys,
-            g = si.Widget,
-            ci = /^(ul|a|div)$/i,
-            r = ".kendoMenu",
-            pt = "img",
-            ht = "open",
-            h = "k-menu",
-            k = "k-link",
-            wt = "k-last",
-            nt = "close",
-            tt = "timer",
-            bt = "k-first",
-            kt = "k-image",
-            dt = "select",
-            a = "zIndex",
-            gt = "activate",
-            ni = "deactivate",
-            ti = "touchstart" + r + " MSPointerDown" + r + " pointerdown" + r,
-            it = i.support.pointers,
-            rt = i.support.msPointers,
-            ct = it ? "pointerover" : rt ? "MSPointerOver" : "mouseenter",
-            ii = it ? "pointerout" : rt ? "MSPointerOut" : "mouseleave",
-            ri = ft || rt || it,
-            ut = "kendoPopup",
-            ui = "k-state-default",
-            lt = "k-state-hover",
-            v = "k-state-focused",
-            y = "k-state-disabled",
-            at = ".k-group",
-            p = ":not(.k-list) > .k-item",
-            li = ".k-item.k-state-disabled",
-            vt = ".k-item:not(.k-state-disabled)",
-            ai = ".k-item:not(.k-state-disabled) > .k-link",
-            fi = ":not(.k-item.k-separator)",
-            w = fi + ":eq(0)",
-            ei = fi + ":last",
-            vi = "div:not(.k-animation-container,.k-list-container)",
-            s = {
-                content: o("<div class='k-content k-group' tabindex='-1'>#= content(item) #<\/div>"),
-                group: o("<ul class='#= groupCssClass(group) #'#= groupAttributes(group) # role='menu' aria-hidden='true'>#= renderItems(data) #<\/ul>"),
-                itemWrapper: o("<#= tag(item) # class='#= textClass(item) #'#= textAttributes(item) #>#= image(item) ##= sprite(item) ##= text(item) ##= arrow(data) #<\/#= tag(item) #>"),
-                item: o("<li class='#= wrapperCssClass(group, item) #' role='menuitem' #=item.items ? \"aria-haspopup='true'\": \"\"##=item.enabled === false ? \"aria-disabled='true'\" : ''#>#= itemWrapper(data) ## if (item.items) { ##= subGroup({ items: item.items, menu: menu, group: { expanded: item.expanded } }) ## } else if (item.content || item.contentUrl) { ##= renderContent(data) ## } #<\/li>"),
-                image: o("<img class='k-image' alt='' src='#= imageUrl #' />"),
-                arrow: o("<span class='#= arrowClass(item, group) #'><\/span>"),
-                sprite: o("<span class='k-sprite #= spriteCssClass #'><\/span>"),
-                empty: o("")
-            },
-            yt = {
-                wrapperCssClass: function(n, t) {
-                    var i = "k-item",
-                        r = t.index;
-                    return i += t.enabled === !1 ? " k-state-disabled" : " k-state-default", n.firstLevel && r === 0 && (i += " k-first"), r == n.length - 1 && (i += " k-last"), t.cssClass && (i += " " + t.cssClass), i
-                },
-                textClass: function() {
-                    return k
-                },
-                textAttributes: function(n) {
-                    return n.url ? " href='" + n.url + "'" : ""
-                },
-                arrowClass: function(n, t) {
-                    return "k-icon" + (t.horizontal ? " k-i-arrow-s" : " k-i-arrow-e")
-                },
-                text: function(n) {
-                    return n.encoded === !1 ? n.text : i.htmlEncode(n.text)
-                },
-                tag: function(n) {
-                    return n.url ? "a" : "span"
-                },
-                groupAttributes: function(n) {
-                    return n.expanded !== !0 ? " style='display:none'" : ""
-                },
-                groupCssClass: function() {
-                    return "k-group"
-                },
-                content: function(n) {
-                    return n.content ? n.content : "&nbsp;"
-                }
-            },
-            l = g.extend({
-                init: function(t, f) {
-                    var e = this;
-                    g.fn.init.call(e, t, f);
-                    t = e.wrapper = e.element;
-                    f = e.options;
-                    e._initData(f);
-                    e._updateClasses();
-                    e._animations(f);
-                    e.nextItemZIndex = 100;
-                    e._tabindex();
-                    e._focusProxy = u(e._focusHandler, e);
-                    t.on(ti, e._focusProxy).on(ot + r, li, !1).on(ot + r, vt, u(e._click, e)).on("keydown" + r, u(e._keydown, e)).on("focus" + r, u(e._focus, e)).on("focus" + r, ".k-content", u(e._focus, e)).on(ti + " " + et + r, ".k-content", u(e._preventClose, e)).on("blur" + r, u(e._removeHoverItem, e)).on("blur" + r, "[tabindex]", u(e._checkActiveElement, e)).on(ct + r, vt, u(e._mouseenter, e)).on(ii + r, vt, u(e._mouseleave, e)).on(ct + r + " " + ii + r + " " + et + r + " " + ot + r, ai, u(e._toggleHover, e));
-                    f.openOnClick && (e.clicked = !1, e._documentClickHandler = u(e._documentClick, e), n(document).click(e._documentClickHandler));
-                    t.attr("role", "menubar");
-                    t[0].id && (e._ariaId = i.format("{0}_mn_active", t[0].id));
-                    i.notify(e)
-                },
-                events: [ht, nt, gt, ni, dt],
-                options: {
-                    name: "Menu",
-                    animation: {
-                        open: {
-                            duration: 200
-                        },
-                        close: {
-                            duration: 100
-                        }
-                    },
-                    orientation: "horizontal",
-                    direction: "default",
-                    openOnClick: !1,
-                    closeOnClick: !0,
-                    hoverDelay: 100
-                },
-                _initData: function(n) {
-                    var t = this;
-                    n.dataSource && (t.element.empty(), t.append(n.dataSource, t.element))
-                },
-                setOptions: function(n) {
-                    var t = this.options.animation;
-                    this._animations(n);
-                    n.animation = f(!0, t, n.animation);
-                    "dataSource" in n && this._initData(n);
-                    g.fn.setOptions.call(this, n)
-                },
-                destroy: function() {
-                    var t = this;
-                    g.fn.destroy.call(t);
-                    t.element.off(r);
-                    t._documentClickHandler && n(document).unbind("click", t._documentClickHandler);
-                    i.destroy(t.element)
-                },
-                enable: function(n, t) {
-                    return this._toggleDisabled(n, t !== !1), this
-                },
-                disable: function(n) {
-                    return this._toggleDisabled(n, !1), this
-                },
-                append: function(n, t) {
-                    t = this.element.find(t);
-                    var i = this._insert(n, t, t.length ? t.find("> .k-group, > .k-animation-container > .k-group") : null);
-                    return st(i.items, function() {
-                        i.group.append(this);
-                        b(this)
-                    }), b(t), c(i.group.find(".k-first, .k-last").add(i.items)), this
-                },
-                insertBefore: function(n, t) {
-                    t = this.element.find(t);
-                    var i = this._insert(n, t, t.parent());
-                    return st(i.items, function() {
-                        t.before(this);
-                        b(this);
-                        c(this)
-                    }), c(t), this
-                },
-                insertAfter: function(n, t) {
-                    t = this.element.find(t);
-                    var i = this._insert(n, t, t.parent());
-                    return st(i.items, function() {
-                        t.after(this);
-                        b(this);
-                        c(this)
-                    }), c(t), this
-                },
-                _insert: function(t, i, r) {
-                    var c = this,
-                        u, s, e, o;
-                    return i && i.length || (r = c.element), e = n.isPlainObject(t), o = {
-                        firstLevel: r.hasClass(h),
-                        horizontal: r.hasClass(h + "-horizontal"),
-                        expanded: !0,
-                        length: r.children().length
-                    }, i && !r.length && (r = n(l.renderGroup({
-                        group: o
-                    })).appendTo(i)), e || n.isArray(t) ? u = n(n.map(e ? [t] : t, function(t, i) {
-                        return typeof t == "string" ? n(t).get() : n(l.renderItem({
-                            group: o,
-                            item: f(t, {
-                                index: i
-                            })
-                        })).get()
-                    })) : (u = n(t), s = u.find("> ul").addClass("k-group").attr("role", "menu"), u = u.filter("li"), u.add(s.find("> li")).each(function() {
-                        oi(this)
-                    })), {
-                        items: u,
-                        group: r
-                    }
-                },
-                remove: function(n) {
-                    var r;
-                    n = this.element.find(n);
-                    var u = this,
-                        t = n.parentsUntil(u.element, p),
-                        i = n.parent("ul:not(.k-menu)");
-                    return n.remove(), i && !i.children(p).length && (r = i.parent(".k-animation-container"), r.length ? r.remove() : i.remove()), t.length && (t = t.eq(0), b(t), c(t)), u
-                },
-                open: function(r) {
-                    var u = this,
-                        e = u.options,
-                        s = e.orientation == "horizontal",
-                        o = e.direction,
-                        c = i.support.isRtl(u.wrapper);
-                    return r = u.element.find(r), /^(top|bottom|default)$/.test(o) && (o = c ? s ? (o + " left").replace("default", "bottom") : "left" : s ? (o + " right").replace("default", "bottom") : "right"), r.siblings().find(">.k-popup:visible,>.k-animation-container>.k-popup:visible").each(function() {
-                        var t = n(this).data("kendoPopup");
-                        t && t.close()
-                    }), r.each(function() {
-                        var i = n(this);
-                        clearTimeout(i.data(tt));
-                        i.data(tt, setTimeout(function() {
-                            var r = i.find(".k-group:first:hidden"),
-                                l;
-                            if (r[0] && u.trigger(ht, {
-                                    item: i[0]
-                                }) === !1) {
-                                !r.find(".k-group")[0] && r.children(".k-item").length > 1 ? setTimeout(function() {
-                                    r.css({
-                                        maxHeight: n(window).height(),
-                                        overflow: "auto"
-                                    })
-                                }) : r.css({
-                                    maxHeight: "",
-                                    overflow: ""
-                                });
-                                i.data(a, i.css(a));
-                                i.css(a, u.nextItemZIndex++);
-                                l = r.data(ut);
-                                var y = i.parent().hasClass(h),
-                                    b = y && s,
-                                    v = pi(o, y, c),
-                                    p = e.animation.open.effects,
-                                    w = p !== t ? p : "slideIn:" + yi(o, y);
-                                l ? (l = r.data(ut), l.options.origin = v.origin, l.options.position = v.position, l.options.animation.open.effects = w) : l = r.kendoPopup({
-                                    activate: function() {
-                                        u.trigger(gt, {
-                                            item: this.wrapper.parent()
-                                        })
-                                    },
-                                    deactivate: function() {
-                                        u.trigger(ni, {
-                                            item: this.wrapper.parent()
-                                        })
-                                    },
-                                    origin: v.origin,
-                                    position: v.position,
-                                    collision: e.popupCollision !== t ? e.popupCollision : b ? "fit" : "fit flip",
-                                    anchor: i,
-                                    appendTo: i,
-                                    animation: {
-                                        open: f(!0, {
-                                            effects: w
-                                        }, e.animation.open),
-                                        close: e.animation.close
-                                    },
-                                    close: function(n) {
-                                        var t = n.sender.wrapper.parent();
-                                        u.trigger(nt, {
-                                            item: t[0]
-                                        }) ? n.preventDefault() : (t.css(a, t.data(a)), t.removeData(a), ri && (t.removeClass(lt), u._removeHoverItem()))
-                                    }
-                                }).data(ut);
-                                r.removeAttr("aria-hidden");
-                                l.open()
-                            }
-                        }, u.options.hoverDelay))
-                    }), u
-                },
-                close: function(t) {
-                    var i = this,
-                        r = i.element;
-                    return t = r.find(t), t.length || (t = r.find(">.k-item")), t.each(function() {
-                        var t = n(this);
-                        i._isRootItem(t) && (i.clicked = !1);
-                        clearTimeout(t.data(tt));
-                        t.data(tt, setTimeout(function() {
-                            var n = t.find(".k-group:not(.k-list-container):not(.k-calendar-container):first:visible").data(ut);
-                            n && (n.close(), n.element.attr("aria-hidden", !0))
-                        }, i.options.hoverDelay))
-                    }), i
-                },
-                _toggleDisabled: function(t, i) {
-                    this.element.find(t).each(function() {
-                        n(this).toggleClass(ui, i).toggleClass(y, !i).attr("aria-disabled", !i)
-                    })
-                },
-                _toggleHover: function(t) {
-                    var r = n(i.eventTarget(t) || t.target).closest(p),
-                        u = t.type == ct || et.indexOf(t.type) !== -1;
-                    r.parents("li." + y).length || r.toggleClass(lt, u || t.type == "mousedown" || t.type == "click");
-                    this._removeHoverItem()
-                },
-                _preventClose: function() {
-                    this.options.closeOnClick || (this._closurePrevented = !0)
-                },
-                _checkActiveElement: function(t) {
-                    var u = this,
-                        f = n(t ? t.currentTarget : this._hoverItem()),
-                        r = u._findRootParent(f)[0];
-                    this._closurePrevented || setTimeout(function() {
-                        document.hasFocus() && (d(r, i._activeElement()) || !t || d(r, t.currentTarget)) || u.close(r)
-                    }, 0);
-                    this._closurePrevented = !1
-                },
-                _removeHoverItem: function() {
-                    var n = this._hoverItem();
-                    n && n.hasClass(v) && (n.removeClass(v), this._oldHoverItem = null)
-                },
-                _updateClasses: function() {
-                    var n = this.element,
-                        t;
-                    n.addClass("k-widget k-reset k-header " + h).addClass(h + "-" + this.options.orientation);
-                    n.find("li > ul").addClass("k-group").attr("role", "menu").attr("aria-hidden", n.is(":visible")).end().find("li > div").addClass("k-content").attr("tabindex", "-1");
-                    t = n.find("> li,.k-group > li");
-                    t.each(function() {
-                        oi(this)
-                    })
-                },
-                _mouseenter: function(t) {
-                    var i = this,
-                        r = n(t.currentTarget),
-                        f = r.children(".k-animation-container").length || r.children(at).length;
-                    t.delegateTarget == r.parents(".k-menu")[0] && (i.options.openOnClick && !i.clicked || ft || !d(t.currentTarget, t.relatedTarget) && f && i.open(r), (i.options.openOnClick && i.clicked || ri) && r.siblings().each(u(function(n, t) {
-                        i.close(t)
-                    }, i)))
-                },
-                _mouseleave: function(t) {
-                    var r = this,
-                        i = n(t.currentTarget),
-                        u = i.children(".k-animation-container").length || i.children(at).length;
-                    if (i.parentsUntil(".k-animation-container", ".k-list-container,.k-calendar-container")[0]) {
-                        t.stopImmediatePropagation();
-                        return
-                    }
-                    r.options.openOnClick || ft || (it || rt) && t.originalEvent.pointerType == t.originalEvent.MSPOINTER_TYPE_TOUCH || d(t.currentTarget, t.relatedTarget || t.target) || !u || r.close(i)
-                },
-                _click: function(t) {
-                    var r = this,
-                        c, f = r.options,
-                        e = n(i.eventTarget(t)),
-                        o = e[0] ? e[0].nodeName.toUpperCase() : "",
-                        v = o == "INPUT" || o == "SELECT" || o == "BUTTON" || o == "LABEL",
-                        l = e.closest("." + k),
-                        u = e.closest(p),
-                        w = l.attr("href"),
-                        s, b, a = !!w && w !== n("<a href='#' />").attr("href");
-                    if (!u.children(vi)[0]) {
-                        if (u.hasClass(y)) {
-                            t.preventDefault();
-                            return
-                        }
-                        if (t.handled || !r.trigger(dt, {
-                                item: u[0]
-                            }) || v || t.preventDefault(), t.handled = !0, s = u.children(at + ",.k-animation-container"), b = s.is(":visible"), f.closeOnClick && !a && (!s.length || f.openOnClick && b)) {
-                            u.removeClass(lt).css("height");
-                            r._oldHoverItem = r._findRootParent(u);
-                            r.close(l.parentsUntil(r.element, p));
-                            r.clicked = !1;
-                            "MSPointerUp".indexOf(t.type) != -1 && t.preventDefault();
-                            return
-                        }(a && t.enterKey && l[0].click(), u.parent().hasClass(h) && f.openOnClick || i.support.touch) && (a || v || t.preventDefault(), r.clicked = !0, c = s.is(":visible") ? nt : ht, f.closeOnClick || c != nt) && r[c](u)
-                    }
-                },
-                _documentClick: function(n) {
-                    d(this.element[0], n.target) || (this.clicked = !1)
-                },
-                _focus: function(t) {
-                    var i = this,
-                        r = t.target,
-                        u = i._hoverItem(),
-                        f = hi();
-                    if (r != i.wrapper[0] && !n(r).is(":kendoFocusable")) {
-                        t.stopPropagation();
-                        n(r).closest(".k-content").closest(".k-group").closest(".k-item").addClass(v);
-                        i.wrapper.focus();
-                        return
-                    }
-                    f === t.currentTarget && (u.length ? i._moveHover([], u) : i._oldHoverItem || i._moveHover([], i.wrapper.children().first()))
-                },
-                _keydown: function(n) {
-                    var t = this,
-                        f = n.keyCode,
-                        r = t._oldHoverItem,
-                        u, o, s, h = i.support.isRtl(t.wrapper);
-                    if (n.target == n.currentTarget || f == e.ESC) {
-                        if (r || (r = t._oldHoverItem = t._hoverItem()), o = t._itemBelongsToVertival(r), s = t._itemHasChildren(r), f == e.RIGHT) u = t[h ? "_itemLeft" : "_itemRight"](r, o, s);
-                        else if (f == e.LEFT) u = t[h ? "_itemRight" : "_itemLeft"](r, o, s);
-                        else if (f == e.DOWN) u = t._itemDown(r, o, s);
-                        else if (f == e.UP) u = t._itemUp(r, o, s);
-                        else if (f == e.ESC) u = t._itemEsc(r, o);
-                        else if (f == e.ENTER || f == e.SPACEBAR) u = r.children(".k-link"), u.length > 0 && (t._click({
-                            target: u[0],
-                            preventDefault: function() {},
-                            enterKey: !0
-                        }), t._moveHover(r, t._findRootParent(r)));
-                        else if (f == e.TAB) {
-                            u = t._findRootParent(r);
-                            t._moveHover(r, u);
-                            t._checkActiveElement();
-                            return
-                        }
-                        u && u[0] && (n.preventDefault(), n.stopPropagation())
-                    }
-                },
-                _hoverItem: function() {
-                    return this.wrapper.find(".k-item.k-state-hover,.k-item.k-state-focused").filter(":visible")
-                },
-                _itemBelongsToVertival: function(n) {
-                    var t = this.wrapper.hasClass("k-menu-vertical");
-                    return n.length ? n.parent().hasClass("k-group") || t : t
-                },
-                _itemHasChildren: function(n) {
-                    return n.length ? n.children("ul.k-group, div.k-animation-container").length > 0 : !1
-                },
-                _moveHover: function(n, t) {
-                    var r = this,
-                        i = r._ariaId;
-                    n.length && t.length && (n.removeClass(v), n[0].id === i && n.removeAttr("id"));
-                    t.length && (t[0].id && (i = t[0].id), t.addClass(v), r._oldHoverItem = t, i && (r.element.removeAttr("aria-activedescendant"), t.attr("id", i), r.element.attr("aria-activedescendant", i)))
-                },
-                _findRootParent: function(n) {
-                    return n.parent().hasClass("k-menu") ? n : n.parentsUntil(".k-menu", "li.k-item").last()
-                },
-                _isRootItem: function(n) {
-                    return n.parent().hasClass("k-menu")
-                },
-                _itemRight: function(n, t, i) {
-                    var u = this,
-                        r, f;
-                    if (!n.hasClass(y)) return t ? i ? (u.open(n), r = n.find(".k-group").children().first()) : u.options.orientation == "horizontal" && (f = u._findRootParent(n), u.close(f), r = f.nextAll(w)) : (r = n.nextAll(w), r.length || (r = n.prevAll(ei))), r && !r.length ? r = u.wrapper.children(".k-item").first() : r || (r = []), u._moveHover(n, r), r
-                },
-                _itemLeft: function(n, t) {
-                    var r = this,
-                        i;
-                    return t ? (i = n.parent().closest(".k-item"), r.close(i), r._isRootItem(i) && r.options.orientation == "horizontal" && (i = i.prevAll(w))) : (i = n.prevAll(w), i.length || (i = n.nextAll(ei))), i.length || (i = r.wrapper.children(".k-item").last()), r._moveHover(n, i), i
-                },
-                _itemDown: function(n, t, i) {
-                    var u = this,
-                        r;
-                    if (t) r = n.nextAll(w);
-                    else {
-                        if (!i || n.hasClass(y)) return;
-                        u.open(n);
-                        r = n.find(".k-group").children().first()
-                    }
-                    return !r.length && n.length ? r = n.parent().children().first() : n.length || (r = u.wrapper.children(".k-item").first()), u._moveHover(n, r), r
-                },
-                _itemUp: function(n, t) {
-                    var r = this,
-                        i;
-                    if (t) i = n.prevAll(w);
-                    else return;
-                    return !i.length && n.length ? i = n.parent().children().last() : n.length || (i = r.wrapper.children(".k-item").last()), r._moveHover(n, i), i
-                },
-                _itemEsc: function(n, t) {
-                    var r = this,
-                        i;
-                    if (t) i = n.parent().closest(".k-item"), r.close(i), r._moveHover(n, i);
-                    else return n;
-                    return i
-                },
-                _focusHandler: function(t) {
-                    var u = this,
-                        r = n(i.eventTarget(t)).closest(p);
-                    setTimeout(function() {
-                        u._moveHover([], r);
-                        r.children(".k-content")[0] && r.parent().closest(".k-item").removeClass(v)
-                    }, 200)
-                },
-                _animations: function(n) {
-                    n && "animation" in n && !n.animation && (n.animation = {
-                        open: {
-                            effects: {}
-                        },
-                        close: {
-                            hide: !0,
-                            effects: {}
-                        }
-                    })
-                }
-            });
-        f(l, {
-            renderItem: function(n) {
-                n = f({
-                    menu: {},
-                    group: {}
-                }, n);
-                var i = s.empty,
-                    t = n.item;
-                return s.item(f(n, {
-                    image: t.imageUrl ? s.image : i,
-                    sprite: t.spriteCssClass ? s.sprite : i,
-                    itemWrapper: s.itemWrapper,
-                    renderContent: l.renderContent,
-                    arrow: t.items || t.content ? s.arrow : i,
-                    subGroup: l.renderGroup
-                }, yt))
-            },
-            renderGroup: function(n) {
-                return s.group(f({
-                    renderItems: function(n) {
-                        for (var r = "", t = 0, i = n.items, u = i ? i.length : 0, e = f({
-                                length: u
-                            }, n.group); t < u; t++) r += l.renderItem(f(n, {
-                            group: e,
-                            item: f({
-                                index: t
-                            }, i[t])
-                        }));
-                        return r
-                    }
-                }, n, yt))
-            },
-            renderContent: function(n) {
-                return s.content(f(n, yt))
-            }
-        });
-        i.ui.plugin(l)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "filtermenu",
-        name: "Filtering Menu",
-        category: "framework",
-        depends: ["datepicker", "numerictextbox", "dropdownlist"],
-        advanced: !0
-    }),
-    function(n) {
-        function c(t, i) {
-            t.filters && (t.filters = n.grep(t.filters, function(n) {
-                return c(n, i), n.filters ? n.filters.length : n.field != i
-            }))
-        }
-
-        function l(n) {
-            var i, u, t, f, e, r;
-            if (n && n.length)
-                for (r = [], i = 0, u = n.length; i < u; i++) t = n[i], e = t.text || t.value || t, f = t.value == null ? t.text || t : t.value, r[i] = {
-                    text: e,
-                    value: f
-                };
-            return r
-        }
-
-        function d(t, i) {
-            return n.grep(t, function(t) {
-                return t.filters ? (t.filters = n.grep(t.filters, function(n) {
-                    return n.field != i
-                }), t.filters.length) : t.field != i
-            })
-        }
-        var t = window.kendo,
-            s = t.ui,
-            i = n.proxy,
-            u = "kendoPopup",
-            h = "init",
-            r = ".kendoFilterMenu",
-            f = "Is equal to",
-            e = "Is not equal to",
-            a = {
-                number: "numerictextbox",
-                date: "datepicker"
-            },
-            v = {
-                string: "text",
-                number: "number",
-                date: "date"
-            },
-            y = t.isFunction,
-            o = s.Widget,
-            p = '<div><div class="k-filter-help-text">#=messages.info#<\/div><label><input type="radio" data-#=ns#bind="checked: filters[0].value" value="true" name="filters[0].value"/>#=messages.isTrue#<\/label><label><input type="radio" data-#=ns#bind="checked: filters[0].value" value="false" name="filters[0].value"/>#=messages.isFalse#<\/label><div><button type="submit" class="k-button">#=messages.filter#<\/button><button type="reset" class="k-button">#=messages.clear#<\/button><\/div><\/div>',
-            w = '<div><div class="k-filter-help-text">#=messages.info#<\/div><select data-#=ns#bind="value: filters[0].operator" data-#=ns#role="dropdownlist">#for(var op in operators){#<option value="#=op#">#=operators[op]#<\/option>#}#<\/select>#if(values){#<select data-#=ns#bind="value:filters[0].value" data-#=ns#text-field="text" data-#=ns#value-field="value" data-#=ns#source=\'#=kendo.stringify(values).replace(/\'/g,"&\\#39;")#\' data-#=ns#role="dropdownlist" data-#=ns#option-label="#=messages.selectValue#"><\/select>#}else{#<input data-#=ns#bind="value:filters[0].value" class="k-textbox" type="text" #=role ? "data-" + ns + "role=\'" + role + "\'" : ""# />#}##if(extra){#<select class="k-filter-and" data-#=ns#bind="value: logic" data-#=ns#role="dropdownlist"><option value="and">#=messages.and#<\/option><option value="or">#=messages.or#<\/option><\/select><select data-#=ns#bind="value: filters[1].operator" data-#=ns#role="dropdownlist">#for(var op in operators){#<option value="#=op#">#=operators[op]#<\/option>#}#<\/select>#if(values){#<select data-#=ns#bind="value:filters[1].value" data-#=ns#text-field="text" data-#=ns#value-field="value" data-#=ns#source=\'#=kendo.stringify(values).replace(/\'/g,"&\\#39;")#\' data-#=ns#role="dropdownlist" data-#=ns#option-label="#=messages.selectValue#"><\/select>#}else{#<input data-#=ns#bind="value: filters[1].value" class="k-textbox" type="text" #=role ? "data-" + ns + "role=\'" + role + "\'" : ""#/>#}##}#<div><button type="submit" class="k-button">#=messages.filter#<\/button><button type="reset" class="k-button">#=messages.clear#<\/button><\/div><\/div>',
-            b = '<div data-#=ns#role="view" data-#=ns#init-widgets="false" class="k-grid-filter-menu"><div data-#=ns#role="header" class="k-header"><button class="k-button k-cancel">#=messages.cancel#<\/button>#=field#<button type="submit" class="k-button k-submit">#=messages.filter#<\/button><\/div><form class="k-filter-menu k-mobile-list k-secondary"><ul class="k-filter-help-text"><li><span class="k-link">#=messages.info#<\/span><ul><li class="k-item"><label class="k-label">#=messages.operator#<select data-#=ns#bind="value: filters[0].operator">#for(var op in operators){#<option value="#=op#">#=operators[op]#<\/option>#}#<\/select><\/label><\/li><li class="k-item"><label class="k-label">#=messages.value##if(values){#<select data-#=ns#bind="value:filters[0].value"><option value="">#=messages.selectValue#<\/option>#for(var val in values){#<option value="#=values[val].value#">#=values[val].text#<\/option>#}#<\/select>#}else{#<input data-#=ns#bind="value:filters[0].value" class="k-textbox" type="#=inputType#" #=useRole ? "data-" + ns + "role=\'" + role + "\'" : ""# />#}#<\/label><\/li>#if(extra){#<\/ul><ul class="k-filter-help-text"><li><span class="k-link"><\/span><li class="k-item"><label class="k-label"><input type="radio" name="logic" class="k-check" data-#=ns#bind="checked: logic" value="and" />#=messages.and#<\/label><\/li><li class="k-item"><label class="k-label"><input type="radio" name="logic" class="k-check" data-#=ns#bind="checked: logic" value="or" />#=messages.or#<\/label><\/li><\/ul><ul class="k-filter-help-text"><li><span class="k-link"><\/span><li class="k-item"><label class="k-label">#=messages.operator#<select data-#=ns#bind="value: filters[1].operator">#for(var op in operators){#<option value="#=op#">#=operators[op]#<\/option>#}#<\/select><\/label><\/li><li class="k-item"><label class="k-label">#=messages.value##if(values){#<select data-#=ns#bind="value:filters[1].value"><option value="">#=messages.selectValue#<\/option>#for(var val in values){#<option value="#=values[val].value#">#=values[val].text#<\/option>#}#<\/select>#}else{#<input data-#=ns#bind="value:filters[1].value" class="k-textbox" type="#=inputType#" #=useRole ? "data-" + ns + "role=\'" + role + "\'" : ""# />#}#<\/label><\/li>#}#<\/ul><\/li><li class="k-button-container"><button type="reset" class="k-button">#=messages.clear#<\/button><\/li><\/ul><\/div><\/form><\/div>',
-            k = '<div data-#=ns#role="view" data-#=ns#init-widgets="false" class="k-grid-filter-menu"><div data-#=ns#role="header" class="k-header"><button class="k-button k-cancel">#=messages.cancel#<\/button>#=field#<button type="submit" class="k-button k-submit">#=messages.filter#<\/button><\/div><form class="k-filter-menu k-mobile-list k-secondary"><ul class="k-filter-help-text"><li><span class="k-link">#=messages.info#<\/span><ul><li class="k-item"><label class="k-label"><input class="k-check" type="radio" data-#=ns#bind="checked: filters[0].value" value="true" name="filters[0].value"/>#=messages.isTrue#<\/label><\/li><li class="k-item"><label class="k-label"><input class="k-check" type="radio" data-#=ns#bind="checked: filters[0].value" value="false" name="filters[0].value"/>#=messages.isFalse#<\/label><\/li><\/ul><\/li><li class="k-button-container"><button type="reset" class="k-button">#=messages.clear#<\/button><\/li><\/ul><\/form><\/div>',
-            g = o.extend({
-                init: function(u, f) {
-                    var e = this,
-                        h = "string",
-                        l, a, c, s;
-                    if (o.fn.init.call(e, u, f), l = e.operators = f.operators || {}, u = e.element, f = e.options, !f.appendToElement) {
-                        c = u.addClass("k-with-icon k-filterable").find(".k-grid-filter");
-                        c[0] || (c = u.prepend('<a class="k-grid-filter" href="#"><span class="k-icon k-filter"/><\/a>').find(".k-grid-filter"));
-                        c.attr("tabindex", -1).on("click" + r, i(e._click, e))
-                    }
-                    e.link = c || n();
-                    e.dataSource = f.dataSource;
-                    e.field = f.field || u.attr(t.attr("field"));
-                    e.model = e.dataSource.reader.model;
-                    e._parse = function(n) {
-                        return n + ""
-                    };
-                    e.model && e.model.fields && (s = e.model.fields[e.field], s && (h = s.type || "string", s.parse && (e._parse = i(s.parse, s))));
-                    f.values && (h = "enums");
-                    e.type = h;
-                    l = l[h] || f.operators[h];
-                    for (a in l) break;
-                    e._defaultFilter = function() {
-                        return {
-                            field: e.field,
-                            operator: a || "eq",
-                            value: ""
-                        }
-                    };
-                    e._refreshHandler = i(e.refresh, e);
-                    e.dataSource.bind("change", e._refreshHandler);
-                    f.appendToElement ? e._init() : e.refresh()
-                },
-                _init: function() {
-                    var u = this,
-                        f = u.options.ui,
-                        o = y(f),
-                        e;
-                    u.pane = u.options.pane;
-                    u.pane && (u._isMobile = !0);
-                    o || (e = f || a[u.type]);
-                    u._isMobile ? u._createMobileForm(e) : u._createForm(e);
-                    u.form.on("submit" + r, i(u._submit, u)).on("reset" + r, i(u._reset, u));
-                    o && u.form.find(".k-textbox").removeClass("k-textbox").each(function() {
-                        f(n(this))
-                    });
-                    u.form.find("[" + t.attr("role") + "=numerictextbox]").removeClass("k-textbox").end().find("[" + t.attr("role") + "=datetimepicker]").removeClass("k-textbox").end().find("[" + t.attr("role") + "=timepicker]").removeClass("k-textbox").end().find("[" + t.attr("role") + "=datepicker]").removeClass("k-textbox");
-                    u.refresh();
-                    u.trigger(h, {
-                        field: u.field,
-                        container: u.form
-                    })
-                },
-                _createForm: function(f) {
-                    var e = this,
-                        o = e.options,
-                        h = e.operators || {},
-                        s = e.type;
-                    h = h[s] || o.operators[s];
-                    e.form = n('<form class="k-filter-menu k-secondary"/>').html(t.template(s === "boolean" ? p : w)({
-                        field: e.field,
-                        format: o.format,
-                        ns: t.ns,
-                        messages: o.messages,
-                        extra: o.extra,
-                        operators: h,
-                        type: s,
-                        role: f,
-                        values: l(o.values)
-                    }));
-                    o.appendToElement ? (e.element.append(e.form), e.popup = e.element.closest(".k-popup").data(u)) : e.popup = e.form[u]({
-                        anchor: e.link,
-                        open: i(e._open, e),
-                        activate: i(e._activate, e),
-                        close: e.options.closeCallback
-                    }).data(u);
-                    e.form.on("keydown" + r, i(e._keydown, e))
-                },
-                _createMobileForm: function(i) {
-                    var r = this,
-                        f = r.options,
-                        e = r.operators || {},
-                        u = r.type;
-                    e = e[u] || f.operators[u];
-                    r.form = n("<div />").html(t.template(u === "boolean" ? k : b)({
-                        field: r.field,
-                        format: f.format,
-                        ns: t.ns,
-                        messages: f.messages,
-                        extra: f.extra,
-                        operators: e,
-                        type: u,
-                        role: i,
-                        useRole: !t.support.input.date && u === "date" || u === "number",
-                        inputType: v[u],
-                        values: l(f.values)
-                    }));
-                    r.view = r.pane.append(r.form.html());
-                    r.form = r.view.element.find("form");
-                    r.view.element.on("click", ".k-submit", function(n) {
-                        r.form.submit();
-                        n.preventDefault()
-                    }).on("click", ".k-cancel", function(n) {
-                        r._closeForm();
-                        n.preventDefault()
-                    })
-                },
-                refresh: function() {
-                    var n = this,
-                        i = n.dataSource.filter() || {
-                            filters: [],
-                            logic: "and"
-                        };
-                    n.filterModel = t.observable({
-                        logic: "and",
-                        filters: [n._defaultFilter(), n._defaultFilter()]
-                    });
-                    n.form && t.bind(n.form.children().first(), n.filterModel);
-                    n._bind(i) ? n.link.addClass("k-state-active") : n.link.removeClass("k-state-active")
-                },
-                destroy: function() {
-                    var n = this;
-                    o.fn.destroy.call(n);
-                    n.form && (t.unbind(n.form), t.destroy(n.form), n.form.unbind(r), n.popup && n.popup.destroy());
-                    n.view && n.view.purge();
-                    n.link.unbind(r);
-                    n._refreshHandler && n.dataSource.unbind("change", n._refreshHandler)
-                },
-                _bind: function(n) {
-                    for (var i = this, s = n.filters, f = !1, o = 0, e = i.filterModel, r, t, u = 0, h = s.length; u < h; u++) t = s[u], t.field == i.field ? (e.set("logic", n.logic), r = e.filters[o], r || (e.filters.push({
-                        field: i.field
-                    }), r = e.filters[o]), r.set("value", i._parse(t.value)), r.set("operator", t.operator), o++, f = !0) : t.filters && (f = f || i._bind(t));
-                    return f
-                },
-                _merge: function(t) {
-                    var f = this,
-                        s = t.logic || "and",
-                        r = t.filters,
-                        e, i = f.dataSource.filter() || {
-                            filters: [],
-                            logic: "and"
-                        },
-                        u, o;
-                    for (c(i, f.field), r = n.grep(r, function(n) {
-                            return n.value !== "" && n.value != null
-                        }), u = 0, o = r.length; u < o; u++) e = r[u], e.value = f._parse(e.value);
-                    return r.length && (i.filters.length ? (t.filters = r, i.logic !== "and" && (i.filters = [{
-                        logic: i.logic,
-                        filters: i.filters
-                    }], i.logic = "and"), r.length > 1 ? i.filters.push(t) : i.filters.push(r[0])) : (i.filters = r, i.logic = s)), i
-                },
-                filter: function(n) {
-                    n = this._merge(n);
-                    n.filters.length && this.dataSource.filter(n)
-                },
-                clear: function() {
-                    var i = this,
-                        t = i.dataSource.filter() || {
-                            filters: []
-                        };
-                    t.filters = n.grep(t.filters, function(n) {
-                        return n.filters ? (n.filters = d(n.filters, i.field), n.filters.length) : n.field != i.field
-                    });
-                    t.filters.length || (t = null);
-                    i.dataSource.filter(t)
-                },
-                _submit: function(n) {
-                    n.preventDefault();
-                    n.stopPropagation();
-                    this.filter(this.filterModel.toJSON());
-                    this._closeForm()
-                },
-                _reset: function() {
-                    this.clear();
-                    this._closeForm()
-                },
-                _closeForm: function() {
-                    this._isMobile ? this.pane.navigate("", this.options.animations.right) : this.popup.close()
-                },
-                _click: function(n) {
-                    n.preventDefault();
-                    n.stopPropagation();
-                    this.popup || this.pane || this._init();
-                    this._isMobile ? this.pane.navigate(this.view, this.options.animations.left) : this.popup.toggle()
-                },
-                _open: function() {
-                    var t;
-                    n(".k-filter-menu").not(this.form).each(function() {
-                        t = n(this).data(u);
-                        t && t.close()
-                    })
-                },
-                _activate: function() {
-                    this.form.find(":kendoFocusable:first").focus()
-                },
-                _keydown: function(n) {
-                    n.keyCode == t.keys.ESC && this.popup.close()
-                },
-                events: [h],
-                options: {
-                    name: "FilterMenu",
-                    extra: !0,
-                    appendToElement: !1,
-                    type: "string",
-                    operators: {
-                        string: {
-                            eq: f,
-                            neq: e,
-                            startswith: "Starts with",
-                            contains: "Contains",
-                            doesnotcontain: "Does not contain",
-                            endswith: "Ends with"
-                        },
-                        number: {
-                            eq: f,
-                            neq: e,
-                            gte: "Is greater than or equal to",
-                            gt: "Is greater than",
-                            lte: "Is less than or equal to",
-                            lt: "Is less than"
-                        },
-                        date: {
-                            eq: f,
-                            neq: e,
-                            gte: "Is after or equal to",
-                            gt: "Is after",
-                            lte: "Is before or equal to",
-                            lt: "Is before"
-                        },
-                        enums: {
-                            eq: f,
-                            neq: e
-                        }
-                    },
-                    messages: {
-                        info: "Show items with value that:",
-                        isTrue: "is true",
-                        isFalse: "is false",
-                        filter: "Filter",
-                        clear: "Clear",
-                        and: "And",
-                        or: "Or",
-                        selectValue: "-Select value-",
-                        operator: "Operator",
-                        value: "Value",
-                        cancel: "Cancel"
-                    },
-                    animations: {
-                        left: "slide",
-                        right: "slide:right"
-                    }
-                }
-            });
-        s.plugin(g)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "panelbar",
-        name: "PanelBar",
-        category: "web",
-        description: "The PanelBar widget displays hierarchical data as a multi-level expandable panel bar.",
-        depends: ["core"]
-    }),
-    function(n, t) {
-        function wt(t) {
-            t = n(t);
-            t.children(r).children(".k-icon").remove();
-            t.filter(":has(.k-panel),:has(.k-content)").children(".k-link:not(:has([class*=k-i-arrow]))").each(function() {
-                var t = n(this),
-                    i = t.parent();
-                t.append("<span class='k-icon " + (i.hasClass(w) ? "k-i-arrow-n k-panelbar-collapse" : "k-i-arrow-s k-panelbar-expand") + "'/>")
-            })
-        }
-
-        function a(t) {
-            t = n(t);
-            t.filter(".k-first:not(:first-child)").removeClass(ct);
-            t.filter(".k-last:not(:last-child)").removeClass(ht);
-            t.filter(":first-child").addClass(ct);
-            t.filter(":last-child").addClass(ht)
-        }
-        var e = window.kendo,
-            oi = e.ui,
-            o = e.keys,
-            i = n.extend,
-            ot = n.each,
-            s = e.template,
-            nt = oi.Widget,
-            si = /^(ul|a|div)$/i,
-            h = ".kendoPanelBar",
-            bt = "img",
-            st = "href",
-            ht = "k-last",
-            tt = "k-link",
-            r = "." + tt,
-            kt = "error",
-            u = ".k-item",
-            b = ".k-group:visible",
-            dt = "k-image",
-            ct = "k-first",
-            lt = "expand",
-            at = "select",
-            it = "k-content",
-            gt = "activate",
-            rt = "collapse",
-            ni = "mouseenter",
-            hi = "mouseleave",
-            ti = "contentLoad",
-            w = "k-state-active",
-            v = "> .k-panel",
-            k = "> .k-content",
-            ii = "k-state-focused",
-            f = "k-state-disabled",
-            d = "k-state-selected",
-            ut = "." + d,
-            c = "k-state-highlight",
-            ft = u + ":not(.k-state-disabled)",
-            ri = ft + " > .k-link",
-            ci = u + ".k-state-disabled > .k-link",
-            ui = "> li > " + ut + ", .k-panel > li > " + ut,
-            fi = "k-state-default",
-            vt = "aria-disabled",
-            g = "aria-expanded",
-            yt = "aria-hidden",
-            et = "aria-selected",
-            y = ":visible",
-            li = ":empty",
-            ei = "single",
-            l = {
-                content: s("<div role='region' class='k-content'#= contentAttributes(data) #>#= content(item) #<\/div>"),
-                group: s("<ul role='group' aria-hidden='true' class='#= groupCssClass(group) #'#= groupAttributes(group) #>#= renderItems(data) #<\/ul>"),
-                itemWrapper: s("<#= tag(item) # class='#= textClass(item, group) #' #= contentUrl(item) ##= textAttributes(item) #>#= image(item) ##= sprite(item) ##= text(item) ##= arrow(data) #<\/#= tag(item) #>"),
-                item: s("<li role='menuitem' #=aria(item)#class='#= wrapperCssClass(group, item) #'>#= itemWrapper(data) ## if (item.items) { ##= subGroup({ items: item.items, panelBar: panelBar, group: { expanded: item.expanded } }) ## } else if (item.content || item.contentUrl) { ##= renderContent(data) ## } #<\/li>"),
-                image: s("<img class='k-image' alt='' src='#= imageUrl #' />"),
-                arrow: s("<span class='#= arrowClass(item) #'><\/span>"),
-                sprite: s("<span class='k-sprite #= spriteCssClass #'><\/span>"),
-                empty: s("")
-            },
-            pt = {
-                aria: function(n) {
-                    var t = "";
-                    return (n.items || n.content || n.contentUrl) && (t += g + "='" + (n.expanded ? "true" : "false") + "' "), n.enabled === !1 && (t += vt + "='true'"), t
-                },
-                wrapperCssClass: function(n, t) {
-                    var i = "k-item",
-                        r = t.index;
-                    return i += t.enabled === !1 ? " " + f : t.expanded === !0 ? " " + w : " k-state-default", r === 0 && (i += " k-first"), r == n.length - 1 && (i += " k-last"), t.cssClass && (i += " " + t.cssClass), i
-                },
-                textClass: function(n, t) {
-                    var i = tt;
-                    return t.firstLevel && (i += " k-header"), i
-                },
-                textAttributes: function(n) {
-                    return n.url ? " href='" + n.url + "'" : ""
-                },
-                arrowClass: function(n) {
-                    return "k-icon" + (n.expanded ? " k-i-arrow-n k-panelbar-collapse" : " k-i-arrow-s k-panelbar-expand")
-                },
-                text: function(n) {
-                    return n.encoded === !1 ? n.text : e.htmlEncode(n.text)
-                },
-                tag: function(n) {
-                    return n.url || n.contentUrl ? "a" : "span"
-                },
-                groupAttributes: function(n) {
-                    return n.expanded !== !0 ? " style='display:none'" : ""
-                },
-                groupCssClass: function() {
-                    return "k-group k-panel"
-                },
-                contentAttributes: function(n) {
-                    return n.item.expanded !== !0 ? " style='display:none'" : ""
-                },
-                content: function(n) {
-                    return n.content ? n.content : n.contentUrl ? "" : "&nbsp;"
-                },
-                contentUrl: function(n) {
-                    return n.contentUrl ? 'href="' + n.contentUrl + '"' : ""
-                }
-            },
-            p = nt.extend({
-                init: function(t, i) {
-                    var r = this,
-                        u;
-                    nt.fn.init.call(r, t, i);
-                    t = r.wrapper = r.element.addClass("k-widget k-reset k-header k-panelbar");
-                    i = r.options;
-                    t[0].id && (r._itemId = t[0].id + "_pb_active");
-                    r._tabindex();
-                    r._initData(i);
-                    r._updateClasses();
-                    r._animations(i);
-                    t.on("click" + h, ri, function(t) {
-                        r._click(n(t.currentTarget)) && t.preventDefault()
-                    }).on(ni + h + " " + hi + h, ri, r._toggleHover).on("click" + h, ci, !1).on("keydown" + h, n.proxy(r._keydown, r)).on("focus" + h, function() {
-                        var n = r.select();
-                        r._current(n[0] ? n : r._first())
-                    }).on("blur" + h, function() {
-                        r._current(null)
-                    }).attr("role", "menu");
-                    u = t.find("li." + w + " > ." + it);
-                    u[0] && r.expand(u.parent(), !1);
-                    e.notify(r)
-                },
-                events: [lt, rt, at, gt, kt, ti],
-                options: {
-                    name: "PanelBar",
-                    animation: {
-                        expand: {
-                            effects: "expand:vertical",
-                            duration: 200
-                        },
-                        collapse: {
-                            duration: 200
-                        }
-                    },
-                    expandMode: "multiple"
-                },
-                destroy: function() {
-                    nt.fn.destroy.call(this);
-                    this.element.off(h);
-                    e.destroy(this.element)
-                },
-                _initData: function(n) {
-                    var t = this;
-                    n.dataSource && (t.element.empty(), t.append(n.dataSource, t.element))
-                },
-                setOptions: function(n) {
-                    var t = this.options.animation;
-                    this._animations(n);
-                    n.animation = i(!0, t, n.animation);
-                    "dataSource" in n && this._initData(n);
-                    nt.fn.setOptions.call(this, n)
-                },
-                expand: function(t, i) {
-                    var r = this,
-                        u = {};
-                    return i = i !== !1, t = this.element.find(t), t.each(function(e, o) {
-                        o = n(o);
-                        var s = o.find(v).add(o.find(k));
-                        if (!o.hasClass(f) && s.length > 0) {
-                            if (r.options.expandMode == ei && r._collapseAllExpanded(o)) return r;
-                            t.find("." + c).removeClass(c);
-                            o.addClass(c);
-                            i || (u = r.options.animation, r.options.animation = {
-                                expand: {
-                                    effects: {}
-                                },
-                                collapse: {
-                                    hide: !0,
-                                    effects: {}
-                                }
-                            });
-                            r._triggerEvent(lt, o) || r._toggleItem(o, !1);
-                            i || (r.options.animation = u)
-                        }
-                    }), r
-                },
-                collapse: function(t, i) {
-                    var r = this,
-                        u = {};
-                    return i = i !== !1, t = r.element.find(t), t.each(function(t, e) {
-                        e = n(e);
-                        var o = e.find(v).add(e.find(k));
-                        !e.hasClass(f) && o.is(y) && (e.removeClass(c), i || (u = r.options.animation, r.options.animation = {
-                            expand: {
-                                effects: {}
-                            },
-                            collapse: {
-                                hide: !0,
-                                effects: {}
-                            }
-                        }), r._triggerEvent(rt, e) || r._toggleItem(e, !0), i || (r.options.animation = u))
-                    }), r
-                },
-                _toggleDisabled: function(n, t) {
-                    n = this.element.find(n);
-                    n.toggleClass(fi, t).toggleClass(f, !t).attr(vt, !t)
-                },
-                select: function(i) {
-                    var u = this;
-                    return i === t ? u.element.find(ui).parent() : (u.element.find(i).each(function() {
-                        var t = n(this),
-                            i = t.children(r);
-                        if (t.hasClass(f)) return u;
-                        u._triggerEvent(at, t) || u._updateSelected(i)
-                    }), u)
-                },
-                enable: function(n, t) {
-                    return this._toggleDisabled(n, t !== !1), this
-                },
-                disable: function(n) {
-                    return this._toggleDisabled(n, !1), this
-                },
-                append: function(n, t) {
-                    t = this.element.find(t);
-                    var i = this._insert(n, t, t.length ? t.find(v) : null);
-                    return ot(i.items, function() {
-                        i.group.append(this);
-                        a(this)
-                    }), wt(t), a(i.group.find(".k-first, .k-last")), i.group.height("auto"), this
-                },
-                insertBefore: function(n, t) {
-                    t = this.element.find(t);
-                    var i = this._insert(n, t, t.parent());
-                    return ot(i.items, function() {
-                        t.before(this);
-                        a(this)
-                    }), a(t), i.group.height("auto"), this
-                },
-                insertAfter: function(n, t) {
-                    t = this.element.find(t);
-                    var i = this._insert(n, t, t.parent());
-                    return ot(i.items, function() {
-                        t.after(this);
-                        a(this)
-                    }), a(t), i.group.height("auto"), this
-                },
-                remove: function(n) {
-                    n = this.element.find(n);
-                    var r = this,
-                        t = n.parentsUntil(r.element, u),
-                        i = n.parent("ul");
-                    return n.remove(), !i || i.hasClass("k-panelbar") || i.children(u).length || i.remove(), t.length && (t = t.eq(0), wt(t), a(t)), r
-                },
-                reload: function(t) {
-                    var i = this;
-                    t = i.element.find(t);
-                    t.each(function() {
-                        var t = n(this);
-                        i._ajaxRequest(t, t.children("." + it), !t.is(y))
-                    })
-                },
-                _first: function() {
-                    return this.element.children(ft).first()
-                },
-                _last: function() {
-                    var n = this.element.children(ft).last(),
-                        t = n.children(b);
-                    return t[0] ? t.children(ft).last() : n
-                },
-                _current: function(n) {
-                    var i = this,
-                        u = i._focused,
-                        f = i._itemId;
-                    if (n === t) return u;
-                    i.element.removeAttr("aria-activedescendant");
-                    u && (u[0].id === f && u.removeAttr("id"), u.children(r).removeClass(ii));
-                    n && (f = n[0].id || f, n.attr("id", f).children(r).addClass(ii), i.element.attr("aria-activedescendant", f));
-                    i._focused = n
-                },
-                _keydown: function(n) {
-                    var t = this,
-                        i = n.keyCode,
-                        u = t._current();
-                    n.target == n.currentTarget && (i == o.DOWN || i == o.RIGHT ? (t._current(t._nextItem(u)), n.preventDefault()) : i == o.UP || i == o.LEFT ? (t._current(t._prevItem(u)), n.preventDefault()) : i == o.ENTER || i == o.SPACEBAR ? (t._click(u.children(r)), n.preventDefault()) : i == o.HOME ? (t._current(t._first()), n.preventDefault()) : i == o.END && (t._current(t._last()), n.preventDefault()))
-                },
-                _nextItem: function(n) {
-                    if (!n) return this._first();
-                    var i = n.children(b),
-                        t = n.next();
-                    return i[0] && (t = i.children("." + ct)), t[0] || (t = n.parent(b).parent(u).next()), t[0] && t.is(":visible") || (t = this._first()), t.hasClass(f) && (t = this._nextItem(t)), t
-                },
-                _prevItem: function(n) {
-                    if (!n) return this._last();
-                    var t = n.prev(),
-                        i;
-                    if (t[0])
-                        for (i = t; i[0];) i = i.children(b).children("." + ht), i[0] && (t = i);
-                    else t = n.parent(b).parent(u), t[0] || (t = this._last());
-                    return t.hasClass(f) && (t = this._prevItem(t)), t
-                },
-                _insert: function(t, r, u) {
-                    var s = this,
-                        f, h = n.isPlainObject(t),
-                        e = r && r[0],
-                        o;
-                    return e || (u = s.element), o = {
-                        firstLevel: u.hasClass("k-panelbar"),
-                        expanded: u.parent().hasClass(w),
-                        length: u.children().length
-                    }, e && !u.length && (u = n(p.renderGroup({
-                        group: o
-                    })).appendTo(r)), h || n.isArray(t) ? (f = n.map(h ? [t] : t, function(t, r) {
-                        return typeof t == "string" ? n(t) : n(p.renderItem({
-                            group: o,
-                            item: i(t, {
-                                index: r
-                            })
-                        }))
-                    }), e && r.attr(g, !1)) : (f = n(t), s._updateItemsClasses(f)), {
-                        items: f,
-                        group: u
-                    }
-                },
-                _toggleHover: function(t) {
-                    var i = n(t.currentTarget);
-                    i.parents("li." + f).length || i.toggleClass("k-state-hover", t.type == ni)
-                },
-                _updateClasses: function() {
-                    var i = this,
-                        r, t;
-                    r = i.element.find("li > ul").not(function() {
-                        return n(this).parentsUntil(".k-panelbar", "div").length
-                    }).addClass("k-group k-panel").attr("role", "group");
-                    r.parent().attr(g, !1).not("." + w).children("ul").attr(yt, !0).hide();
-                    t = i.element.add(r).children();
-                    i._updateItemsClasses(t);
-                    wt(t);
-                    a(t)
-                },
-                _updateItemsClasses: function(n) {
-                    for (var i = n.length, t = 0; t < i; t++) this._updateItemClasses(n[t], t)
-                },
-                _updateItemClasses: function(t, i) {
-                    var s = this._selected,
-                        f = this.options.contentUrls,
-                        h = f && f[i],
-                        c = this.element[0],
-                        o, u;
-                    t = n(t).addClass("k-item").attr("role", "menuitem");
-                    e.support.browser.msie && t.css("list-style-position", "inside").css("list-style-position", "");
-                    t.children(bt).addClass(dt);
-                    u = t.children("a").addClass(tt);
-                    u[0] && (u.attr("href", h), u.children(bt).addClass(dt));
-                    t.filter(":not([disabled]):not([class*=k-state])").addClass("k-state-default");
-                    t.filter("li[disabled]").addClass("k-state-disabled").attr(vt, !0).removeAttr("disabled");
-                    t.children("div").addClass(it).attr("role", "region").attr(yt, !0).hide().parent().attr(g, !1);
-                    u = t.children(ut);
-                    u[0] && (s && s.removeAttr(et).children(ut).removeClass(d), u.addClass(d), this._selected = t.attr(et, !0));
-                    t.children(r)[0] || (o = "<span class='" + tt + "'/>", f && f[i] && t[0].parentNode == c && (o = '<a class="k-link k-header" href="' + f[i] + '"/>'), t.contents().filter(function() {
-                        return !this.nodeName.match(si) && !(this.nodeType == 3 && !n.trim(this.nodeValue))
-                    }).wrapAll(o));
-                    t.parent(".k-panelbar")[0] && t.children(r).addClass("k-header")
-                },
-                _click: function(n) {
-                    var t = this,
-                        a = t.element,
-                        i, o, s, l, h, e, c;
-                    if (!n.parents("li." + f).length) return n.closest(".k-widget")[0] != a[0] ? void 0 : (h = n.closest(r), e = h.closest(u), t._updateSelected(h), o = e.find(v).add(e.find(k)), s = h.attr(st), l = s && (s.charAt(s.length - 1) == "#" || s.indexOf("#" + t.element[0].id + "-") != -1), i = !!(l || o.length), o.data("animating")) ? i : (t._triggerEvent(at, e) && (i = !0), i === !1) ? void 0 : t.options.expandMode == ei && t._collapseAllExpanded(e) ? i : (o.length && (c = o.is(y), t._triggerEvent(c ? rt : lt, e) || (i = t._toggleItem(e, c))), i)
-                },
-                _toggleItem: function(n, i) {
-                    var e = this,
-                        o = n.find(v),
-                        s = n.find(r),
-                        h = s.attr(st),
-                        f, u;
-                    return o.length ? (this._toggleGroup(o, i), f = !0) : (u = n.children("." + it), u.length && (f = !0, u.is(li) && h !== t ? e._ajaxRequest(n, u, i) : e._toggleGroup(u, i))), f
-                },
-                _toggleGroup: function(n, t) {
-                    var e = this,
-                        o = e.options.animation,
-                        r = o.expand,
-                        f = i({}, o.collapse),
-                        s = f && "effects" in f;
-                    n.is(y) == t && (n.parent().attr(g, !t).attr(yt, t).toggleClass(fi, t).toggleClass(w, !t).find("> .k-link > .k-icon").toggleClass("k-i-arrow-n", !t).toggleClass("k-panelbar-collapse", !t).toggleClass("k-i-arrow-s", t).toggleClass("k-panelbar-expand", t), r = t ? i(s ? f : i({
-                        reverse: !0
-                    }, r), {
-                        hide: !0
-                    }) : i({
-                        complete: function(n) {
-                            e._triggerEvent(gt, n.closest(u))
-                        }
-                    }, r), n.kendoStop(!0, !0).kendoAnimate(r))
-                },
-                _collapseAllExpanded: function(t) {
-                    var e = this,
-                        o, i = !1,
-                        f;
-                    if (t.children(r).hasClass("k-header")) return f = t.find(v).add(t.find(k)), f.is(y) && (i = !0), f.is(y) || f.length === 0 || (o = n(e.element).children(), o.find(v).add(o.find(k)).filter(function() {
-                        return n(this).is(y)
-                    }).each(function(t, r) {
-                        r = n(r);
-                        i = e._triggerEvent(rt, r.closest(u));
-                        i || e._toggleGroup(r, !0)
-                    })), i
-                },
-                _ajaxRequest: function(t, i, u) {
-                    var f = this,
-                        e = t.find(".k-panelbar-collapse, .k-panelbar-expand"),
-                        s = t.find(r),
-                        h = setTimeout(function() {
-                            e.addClass("k-loading")
-                        }, 100),
-                        o = s.attr(st);
-                    n.ajax({
-                        type: "GET",
-                        cache: !1,
-                        url: o,
-                        dataType: "html",
-                        data: {},
-                        error: function(n, t) {
-                            e.removeClass("k-loading");
-                            f.trigger(kt, {
-                                xhr: n,
-                                status: t
-                            }) && this.complete()
-                        },
-                        complete: function() {
-                            clearTimeout(h);
-                            e.removeClass("k-loading")
-                        },
-                        success: function(n) {
-                            try {
-                                i.html(n)
-                            } catch (e) {
-                                var r = window.console;
-                                r && r.error && r.error(e.name + ": " + e.message + " in " + o);
-                                this.error(this.xhr, "error")
-                            }
-                            f._toggleGroup(i, u);
-                            f.trigger(ti, {
-                                item: t[0],
-                                contentElement: i[0]
-                            })
-                        }
-                    })
-                },
-                _triggerEvent: function(n, t) {
-                    var i = this;
-                    return i.trigger(n, {
-                        item: t[0]
-                    })
-                },
-                _updateSelected: function(n) {
-                    var t = this,
-                        i = t.element,
-                        r = n.parent(u),
-                        f = t._selected;
-                    f && f.removeAttr(et);
-                    t._selected = r.attr(et, !0);
-                    i.find(ui).removeClass(d);
-                    i.find("> ." + c + ", .k-panel > ." + c).removeClass(c);
-                    n.addClass(d);
-                    n.parentsUntil(i, u).filter(":has(.k-header)").addClass(c);
-                    t._current(r)
-                },
-                _animations: function(n) {
-                    n && "animation" in n && !n.animation && (n.animation = {
-                        expand: {
-                            effects: {}
-                        },
-                        collapse: {
-                            hide: !0,
-                            effects: {}
-                        }
-                    })
-                }
-            });
-        i(p, {
-            renderItem: function(n) {
-                n = i({
-                    panelBar: {},
-                    group: {}
-                }, n);
-                var r = l.empty,
-                    t = n.item;
-                return l.item(i(n, {
-                    image: t.imageUrl ? l.image : r,
-                    sprite: t.spriteCssClass ? l.sprite : r,
-                    itemWrapper: l.itemWrapper,
-                    renderContent: p.renderContent,
-                    arrow: t.items || t.content || t.contentUrl ? l.arrow : r,
-                    subGroup: p.renderGroup
-                }, pt))
-            },
-            renderGroup: function(n) {
-                return l.group(i({
-                    renderItems: function(n) {
-                        for (var u = "", t = 0, r = n.items, f = r ? r.length : 0, e = i({
-                                length: f
-                            }, n.group); t < f; t++) u += p.renderItem(i(n, {
-                            group: e,
-                            item: i({
-                                index: t
-                            }, r[t])
-                        }));
-                        return u
-                    }
-                }, n, pt))
-            },
-            renderContent: function(n) {
-                return l.content(i(n, pt))
-            }
-        });
-        e.ui.plugin(p)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "timepicker",
-        name: "TimePicker",
-        category: "web",
-        description: "The TimePicker widget allows the end user to select a value from a list of predefined values or to type a new value.",
-        depends: ["popup"]
-    }),
-    function(n, t) {
-        function ui(n, t, i) {
-            var u = n.getTimezoneOffset(),
-                r;
-            n.setTime(n.getTime() + t);
-            i || (r = n.getTimezoneOffset() - u, n.setTime(n.getTime() + r * h))
-        }
-
-        function fi() {
-            var n = new u,
-                t = new u(n.getFullYear(), n.getMonth(), n.getDate(), 0, 0, 0),
-                i = new u(n.getFullYear(), n.getMonth(), n.getDate(), 12, 0, 0);
-            return -1 * (t.getTimezoneOffset() - i.getTimezoneOffset())
-        }
-
-        function e(n) {
-            return n.getHours() * 60 * h + n.getMinutes() * h + n.getSeconds() * 1e3 + n.getMilliseconds()
-        }
-
-        function kt(n, t, i) {
-            var u = e(t),
-                f = e(i),
-                r;
-            return !n || u == f ? !0 : (r = e(n), u > r && (r += s), f < u && (f += s), r >= u && r <= f)
-        }
-
-        function gt(n) {
-            var t = n.parseFormats;
-            n.format = ii(n.format || r.getCulture(n.culture).calendars.standard.patterns.t);
-            t = bt(t) ? t : [t];
-            t.splice(0, 0, n.format);
-            n.parseFormats = t
-        }
-
-        function ni(n) {
-            n.preventDefault()
-        }
-        var r = window.kendo,
-            o = r.keys,
-            ti = r._activeElement,
-            ii = r._extractFormat,
-            l = r.support,
-            tt = l.browser,
-            p = r.ui,
-            a = p.Widget,
-            it = "open",
-            rt = "close",
-            w = "change",
-            i = ".kendoTimePicker",
-            ut = "click" + i,
-            b = "k-state-default",
-            ft = "disabled",
-            et = "readonly",
-            k = "li",
-            ot = "<span/>",
-            st = "k-state-focused",
-            d = "k-state-hover",
-            ri = "mouseenter" + i + " mouseleave" + i,
-            ht = "mousedown" + i,
-            h = 6e4,
-            s = 864e5,
-            ct = "k-state-selected",
-            g = "k-state-disabled",
-            lt = "aria-selected",
-            at = "aria-expanded",
-            vt = "aria-hidden",
-            yt = "aria-disabled",
-            pt = "aria-readonly",
-            wt = "aria-activedescendant",
-            v = "id",
-            bt = n.isArray,
-            nt = n.extend,
-            y = n.proxy,
-            u = Date,
-            f = new u,
-            c, dt;
-        f = new u(f.getFullYear(), f.getMonth(), f.getDate(), 0, 0, 0);
-        c = function(t) {
-            var u = this,
-                f = t.id;
-            u.options = t;
-            u.ul = n('<ul tabindex="-1" role="listbox" aria-hidden="true" unselectable="on" class="k-list k-reset"/>').css({
-                overflow: l.kineticScrollNeeded ? "" : "auto"
-            }).on(ut, k, y(u._click, u)).on("mouseenter" + i, k, function() {
-                n(this).addClass(d)
-            }).on("mouseleave" + i, k, function() {
-                n(this).removeClass(d)
-            });
-            u.list = n("<div class='k-list-container'/>").append(u.ul).on(ht, ni);
-            f && (u._timeViewID = f + "_timeview", u._optionID = f + "_option_selected", u.ul.attr(v, u._timeViewID));
-            u._popup();
-            u.template = r.template('<li tabindex="-1" role="option" class="k-item" unselectable="on">#=data#<\/li>', {
-                useWithBlock: !1
-            })
-        };
-        c.prototype = {
-            current: function(i) {
-                var r = this,
-                    u = r.options.active;
-                if (i !== t) r._current && r._current.removeClass(ct).removeAttr(lt).removeAttr(v), i && (i = n(i).addClass(ct).attr(v, r._optionID).attr(lt, !0), r.scroll(i[0])), r._current = i, u && u(i);
-                else return r._current
-            },
-            close: function() {
-                this.popup.close()
-            },
-            destroy: function() {
-                var n = this;
-                n.ul.off(i);
-                n.list.off(i);
-                n._touchScroller && n._touchScroller.destroy();
-                n.popup.destroy()
-            },
-            open: function() {
-                var n = this;
-                n.ul[0].firstChild || n.bind();
-                n.popup.open();
-                n._current && n.scroll(n._current[0])
-            },
-            dataBind: function(n) {
-                for (var i = this, t = i.options, s = t.format, h = r.toString, c = i.template, e = n.length, u = 0, f, o = ""; u < e; u++) f = n[u], kt(f, t.min, t.max) && (o += c(h(f, s, t.culture)));
-                i._html(o, e)
-            },
-            refresh: function() {
-                var l = this,
-                    i = l.options,
-                    g = i.format,
-                    y = fi(),
-                    p = y < 0,
-                    w = i.min,
-                    b = i.max,
-                    a = e(w),
-                    n = e(b),
-                    o = i.interval * h,
-                    nt = r.toString,
-                    tt = l.template,
-                    t = new u(+w),
-                    it = t.getDate(),
-                    v, k, c = 0,
-                    f, d = "";
-                for (f = p ? (s + y * h) / o : s / o, a != n && (a > n && (n += s), f = (n - a) / o + 1), k = parseInt(f, 10); c < f; c++) c && ui(t, o, p), n && k == c && (v = e(t), it < t.getDate() && (v += s), v > n && (t = new u(+b))), d += tt(nt(t, g, i.culture));
-                l._html(d, f)
-            },
-            bind: function() {
-                var n = this,
-                    t = n.options.dates;
-                t && t[0] ? n.dataBind(t) : n.refresh()
-            },
-            _html: function(n, t) {
-                var i = this;
-                i.ul[0].innerHTML = n;
-                i._height(t);
-                i.current(null);
-                i.select(i._value)
-            },
-            scroll: function(n) {
-                if (n) {
-                    var i = this.ul[0],
-                        t = n.offsetTop,
-                        f = n.offsetHeight,
-                        r = i.scrollTop,
-                        e = i.clientHeight,
-                        o = t + f,
-                        s = this._touchScroller,
-                        u;
-                    s ? (u = this.list.height(), t > u && (t = t - u + f), s.scrollTo(0, -t)) : i.scrollTop = r > t ? t : o > r + e ? o - e : r
-                }
-            },
-            select: function(t) {
-                var i = this,
-                    f = i.options,
-                    u = i._current;
-                t instanceof Date && (t = r.toString(t, f.format, f.culture));
-                typeof t == "string" && (u && u.text() === t ? t = u : (t = n.grep(i.ul[0].childNodes, function(n) {
-                    return (n.textContent || n.innerText) == t
-                }), t = t[0] ? t : null));
-                i.current(t)
-            },
-            setOptions: function(n) {
-                var t = this.options;
-                this.options = nt(t, n, {
-                    active: t.active,
-                    change: t.change,
-                    close: t.close,
-                    open: t.open
-                });
-                this.bind()
-            },
-            toggle: function() {
-                var n = this;
-                n.popup.visible() ? n.close() : n.open()
-            },
-            value: function(n) {
-                var t = this;
-                t._value = n;
-                t.ul[0].firstChild && t.select(n)
-            },
-            _click: function(t) {
-                var i = this,
-                    r = n(t.currentTarget);
-                t.isDefaultPrevented() || (i.select(r), i.options.change(r.text(), !0), i.close())
-            },
-            _height: function(n) {
-                if (n) {
-                    var t = this,
-                        i = t.list,
-                        u = i.parent(".k-animation-container"),
-                        r = t.options.height;
-                    i.add(u).show().height(t.ul[0].scrollHeight > r ? r : "auto").hide()
-                }
-            },
-            _parse: function(n) {
-                var o = this,
-                    s = o.options,
-                    t = o._value || f,
-                    i, e;
-                return n instanceof u ? n : (n != null && (i = n.indexOf(":"), i == -1 ? n = n.length <= 2 ? n + ":00" : n.slice(2).length == 1 ? n.slice(0, 2) + ":" + n.slice(2) + "0" : n.slice(0, 2) + ":" + n.slice(2) : i == 0 ? n = "00" + n : (e = n.split(":"), e[1].length == 0 ? n = n + "00" : e[1].length == 1 && (n = n + "0"))), n = r.parseDate(n, s.parseFormats, s.culture), n && (n = new u(t.getFullYear(), t.getMonth(), t.getDate(), n.getHours(), n.getMinutes(), n.getSeconds(), n.getMilliseconds())), n)
-            },
-            _adjustListWidth: function() {
-                var t = this.list,
-                    i = t[0].style.width,
-                    r = this.options.anchor,
-                    n, u;
-                (t.data("width") || !i) && (n = window.getComputedStyle ? window.getComputedStyle(r[0], null) : 0, u = n ? parseFloat(n.width) : r.outerWidth(), n && (tt.mozilla || tt.msie) && (u += parseFloat(n.paddingLeft) + parseFloat(n.paddingRight) + parseFloat(n.borderLeftWidth) + parseFloat(n.borderRightWidth)), i = u - (t.outerWidth() - t.width()), t.css({
-                    fontFamily: r.css("font-family"),
-                    width: i
-                }).data("width", i))
-            },
-            _popup: function() {
-                var t = this,
-                    i = t.list,
-                    n = t.options,
-                    u = n.anchor;
-                t.popup = new p.Popup(i, nt(n.popup, {
-                    anchor: u,
-                    open: n.open,
-                    close: n.close,
-                    animation: n.animation,
-                    isRtl: l.isRtl(n.anchor)
-                }));
-                t._touchScroller = r.touchScroller(t.popup.element)
-            },
-            move: function(n) {
-                var i = this,
-                    r = n.keyCode,
-                    f = i.ul[0],
-                    t = i._current,
-                    u = r === o.DOWN;
-                if (r === o.UP || u) {
-                    if (n.altKey) {
-                        i.toggle(u);
-                        return
-                    }
-                    t = u ? t ? t[0].nextSibling : f.firstChild : t ? t[0].previousSibling : f.lastChild;
-                    t && i.select(t);
-                    i.options.change(i._current.text());
-                    n.preventDefault()
-                } else(r === o.ENTER || r === o.TAB || r === o.ESC) && (n.preventDefault(), t && i.options.change(t.text(), !0), i.close())
-            }
-        };
-        c.getMilliseconds = e;
-        r.TimeView = c;
-        dt = a.extend({
-            init: function(n, t) {
-                var i = this,
-                    f, u, e;
-                a.fn.init.call(i, n, t);
-                n = i.element;
-                t = i.options;
-                gt(t);
-                i._wrapper();
-                i.timeView = u = new c(nt({}, t, {
-                    id: n.attr(v),
-                    anchor: i.wrapper,
-                    format: t.format,
-                    change: function(t, r) {
-                        r ? i._change(t) : n.val(t)
-                    },
-                    open: function(t) {
-                        i.timeView._adjustListWidth();
-                        i.trigger(it) ? t.preventDefault() : (n.attr(at, !0), f.attr(vt, !1))
-                    },
-                    close: function(t) {
-                        i.trigger(rt) ? t.preventDefault() : (n.attr(at, !1), f.attr(vt, !0))
-                    },
-                    active: function(t) {
-                        n.removeAttr(wt);
-                        t && n.attr(wt, u._optionID)
-                    }
-                }));
-                f = u.ul;
-                i._icon();
-                i._reset();
-                try {
-                    n[0].setAttribute("type", "text")
-                } catch (o) {
-                    n[0].type = "text"
-                }
-                n.addClass("k-input").attr({
-                    role: "combobox",
-                    "aria-expanded": !1,
-                    "aria-owns": u._timeViewID
-                });
-                e = n.is("[disabled]");
-                e ? i.enable(!1) : i.readonly(n.is("[readonly]"));
-                i._old = i._update(t.value || i.element.val());
-                i._oldText = n.val();
-                r.notify(i)
-            },
-            options: {
-                name: "TimePicker",
-                min: f,
-                max: f,
-                format: "",
-                dates: [],
-                parseFormats: [],
-                value: null,
-                interval: 30,
-                height: 200,
-                animation: {}
-            },
-            events: [it, rt, w],
-            setOptions: function(n) {
-                var t = this,
-                    i = t._value;
-                a.fn.setOptions.call(t, n);
-                n = t.options;
-                gt(n);
-                t.timeView.setOptions(n);
-                i && t.element.val(r.toString(i, n.format, n.culture))
-            },
-            dataBind: function(n) {
-                bt(n) && this.timeView.dataBind(n)
-            },
-            _editable: function(n) {
-                var t = this,
-                    r = n.disable,
-                    u = n.readonly,
-                    o = t._arrow.off(i),
-                    f = t.element.off(i),
-                    e = t._inputWrapper.off(i);
-                if (u || r) e.addClass(r ? g : b).removeClass(r ? b : g), f.attr(ft, r).attr(et, u).attr(yt, r).attr(pt, u);
-                else {
-                    e.addClass(b).removeClass(g).on(ri, t._toggleHover);
-                    f.removeAttr(ft).removeAttr(et).attr(yt, !1).attr(pt, !1).on("keydown" + i, y(t._keydown, t)).on("blur" + i, y(t._blur, t)).on("focus" + i, function() {
-                        t._inputWrapper.addClass(st)
-                    });
-                    o.on(ut, y(t._click, t)).on(ht, ni)
-                }
-            },
-            readonly: function(n) {
-                this._editable({
-                    readonly: n === t ? !0 : n,
-                    disable: !1
-                })
-            },
-            enable: function(n) {
-                this._editable({
-                    readonly: !1,
-                    disable: !(n = n === t ? !0 : n)
-                })
-            },
-            destroy: function() {
-                var n = this;
-                a.fn.destroy.call(n);
-                n.timeView.destroy();
-                n.element.off(i);
-                n._arrow.off(i);
-                n._inputWrapper.off(i);
-                n._form && n._form.off("reset", n._resetHandler)
-            },
-            close: function() {
-                this.timeView.close()
-            },
-            open: function() {
-                this.timeView.open()
-            },
-            min: function(n) {
-                return this._option("min", n)
-            },
-            max: function(n) {
-                return this._option("max", n)
-            },
-            value: function(n) {
-                var i = this;
-                if (n === t) return i._value;
-                i._old = i._update(n);
-                i._old === null && i.element.val("");
-                i._oldText = i.element.val()
-            },
-            _blur: function() {
-                var n = this,
-                    t = n.element.val();
-                n.close();
-                t !== n._oldText && n._change(t);
-                n._inputWrapper.removeClass(st)
-            },
-            _click: function() {
-                var n = this,
-                    t = n.element;
-                n.timeView.toggle();
-                l.touch || t[0] === ti() || t.focus()
-            },
-            _change: function(n) {
-                var t = this;
-                n = t._update(n); + t._old != +n && (t._old = n, t._oldText = t.element.val(), t.trigger(w), t.element.trigger(w))
-            },
-            _icon: function() {
-                var i = this,
-                    r = i.element,
-                    t;
-                t = r.next("span.k-select");
-                t[0] || (t = n('<span unselectable="on" class="k-select"><span unselectable="on" class="k-icon k-i-clock">select<\/span><\/span>').insertAfter(r));
-                i._arrow = t.attr({
-                    role: "button",
-                    "aria-controls": i.timeView._timeViewID
-                })
-            },
-            _keydown: function(n) {
-                var t = this,
-                    u = n.keyCode,
-                    i = t.timeView,
-                    r = t.element.val();
-                i.popup.visible() || n.altKey ? i.move(n) : u === o.ENTER && r !== t._oldText && t._change(r)
-            },
-            _option: function(n, i) {
-                var r = this,
-                    f = r.options;
-                if (i === t) return f[n];
-                (i = r.timeView._parse(i), i) && (i = new u(+i), f[n] = i, r.timeView.options[n] = i, r.timeView.bind())
-            },
-            _toggleHover: function(t) {
-                n(t.currentTarget).toggleClass(d, t.type === "mouseenter")
-            },
-            _update: function(n) {
-                var i = this,
-                    u = i.options,
-                    f = i.timeView,
-                    t = f._parse(n);
-                return kt(t, u.min, u.max) || (t = null), i._value = t, i.element.val(t ? r.toString(t, u.format, u.culture) : n), f.value(t), t
-            },
-            _wrapper: function() {
-                var r = this,
-                    i = r.element,
-                    t;
-                t = i.parents(".k-timepicker");
-                t[0] || (t = i.wrap(ot).parent().addClass("k-picker-wrap k-state-default"), t = t.wrap(ot).parent());
-                t[0].style.cssText = i[0].style.cssText;
-                r.wrapper = t.addClass("k-widget k-timepicker k-header").addClass(i[0].className);
-                i.css({
-                    width: "100%",
-                    height: i[0].style.height
-                });
-                r._inputWrapper = n(t[0].firstChild)
-            },
-            _reset: function() {
-                var t = this,
-                    i = t.element,
-                    r = i.attr("form"),
-                    u = r ? n("#" + r) : i.closest("form");
-                u[0] && (t._resetHandler = function() {
-                    t.value(i[0].defaultValue)
-                }, t._form = u.on("reset", t._resetHandler))
-            }
-        });
-        p.plugin(dt)
-    }(window.kendo.jQuery);
-kendo_module({
-        id: "window",
-        name: "Window",
-        category: "web",
-        description: "The Window widget displays content in a modal or non-modal HTML window.",
-        depends: ["draganddrop"]
-    }),
-    function(n, t) {
-        function rt(n) {
-            return typeof n != "undefined"
-        }
-
-        function o(n, t, i) {
-            return Math.max(Math.min(parseInt(n, 10), i === Infinity ? i : parseInt(i, 10)), parseInt(t, 10))
-        }
-
-        function ii(n, t) {
-            return function() {
-                var i = this,
-                    r = i.wrapper,
-                    f = r[0].style,
-                    o = i.options;
-                if (!o.isMaximized && !o.isMinimized) return i.restoreOptions = {
-                    width: f.width,
-                    height: f.height
-                }, r.children(h).hide().end().children(e).find(gt).parent().hide().eq(0).before(u.action({
-                    name: "Restore"
-                })), t.call(i), n == "maximize" ? i.wrapper.children(e).find(st).parent().hide() : i.wrapper.children(e).find(st).parent().show(), i
-            }
-        }
-
-        function ri(n) {
-            var t = this;
-            t.owner = n;
-            t._draggable = new ht(n.wrapper, {
-                filter: h,
-                group: n.wrapper.id + "-resizing",
-                dragstart: f(t.dragstart, t),
-                drag: f(t.drag, t),
-                dragend: f(t.dragend, t)
-            })
-        }
-
-        function ui(n, t) {
-            var i = this;
-            i.owner = n;
-            i._draggable = new ht(n.wrapper, {
-                filter: t,
-                group: n.wrapper.id + "-moving",
-                dragstart: f(i.dragstart, i),
-                drag: f(i.drag, i),
-                dragend: f(i.dragend, i),
-                dragcancel: f(i.dragcancel, i)
-            });
-            i._draggable.userEvents.stopPropagation = !1
-        }
-        var i = window.kendo,
-            d = i.ui.Widget,
-            ht = i.ui.Draggable,
-            ct = n.isPlainObject,
-            fi = i._activeElement,
-            f = n.proxy,
-            l = n.extend,
-            ut = n.each,
-            s = i.template,
-            g = "body",
-            u, r = ".kendoWindow",
-            a = ".k-window",
-            ft = ".k-window-title",
-            e = ft + "bar",
-            v = ".k-window-content",
-            h = ".k-resize-handle",
-            nt = ".k-overlay",
-            w = "k-content-frame",
-            lt = "k-loading",
-            at = "k-state-hover",
-            vt = "k-state-focused",
-            yt = "k-window-maximized",
-            y = ":visible",
-            tt = "hidden",
-            p = "cursor",
-            et = "open",
-            ot = "activate",
-            pt = "deactivate",
-            wt = "close",
-            it = "refresh",
-            bt = "dragstart",
-            kt = "dragend",
-            dt = "error",
-            c = "overflow",
-            b = "zIndex",
-            gt = ".k-window-actions .k-i-minimize,.k-window-actions .k-i-maximize",
-            ni = ".k-i-pin",
-            ti = ".k-i-unpin",
-            st = ni + "," + ti,
-            k = ".k-window-titlebar .k-window-action",
-            ei = i.isLocalUrl,
-            oi = d.extend({
-                init: function(u, o) {
-                    var s = this,
-                        h, w = {},
-                        g, nt, c, it = !1,
-                        l, b, ut = o && o.actions && !o.actions.length,
-                        p;
-                    d.fn.init.call(s, u, o);
-                    o = s.options;
-                    c = o.position;
-                    u = s.element;
-                    l = o.content;
-                    ut && (o.actions = []);
-                    s.appendTo = n(o.appendTo);
-                    s._animations();
-                    l && !ct(l) && (l = o.content = {
-                        url: l
-                    });
-                    u.find("script").filter(function() {
-                        return !this.type || this.type.toLowerCase().indexOf("script") >= 0
-                    }).remove();
-                    u.parent().is(s.appendTo) || c.top !== t && c.left !== t || (u.is(y) ? (w = u.offset(), it = !0) : (g = u.css("visibility"), nt = u.css("display"), u.css({
-                        visibility: tt,
-                        display: ""
-                    }), w = u.offset(), u.css({
-                        visibility: g,
-                        display: nt
-                    })), c.top === t && (c.top = w.top), c.left === t && (c.left = w.left));
-                    rt(o.visible) && o.visible !== null || (o.visible = u.is(y));
-                    h = s.wrapper = u.closest(a);
-                    u.is(".k-content") && h[0] || (u.addClass("k-window-content k-content"), s._createWindow(u, o), h = s.wrapper = u.closest(a), s._dimensions());
-                    s._position();
-                    o.pinned && s.pin(!0);
-                    l && s.refresh(l);
-                    o.visible && s.toFront();
-                    b = h.children(v);
-                    s._tabindex(b);
-                    o.visible && o.modal && s._overlay(h.is(y)).css({
-                        opacity: .5
-                    });
-                    h.on("mouseenter" + r, k, function() {
-                        n(this).addClass(at)
-                    }).on("mouseleave" + r, k, function() {
-                        n(this).removeClass(at)
-                    }).on("click" + r, "> " + k, f(s._windowActionHandler, s));
-                    b.on("keydown" + r, f(s._keydown, s)).on("focus" + r, function() {
-                        h.addClass(vt)
-                    }).on("blur" + r, function() {
-                        h.removeClass(vt)
-                    });
-                    this._resizable();
-                    this._draggable();
-                    p = u.attr("id");
-                    p && (p = p + "_wnd_title", h.children(e).children(ft).attr("id", p), b.attr({
-                        role: "dialog",
-                        "aria-labelledby": p
-                    }));
-                    h.add(h.children(".k-resize-handle," + e)).on("mousedown" + r, f(s.toFront, s));
-                    s.touchScroller = i.touchScroller(u);
-                    s._resizeHandler = function(n) {
-                        return s._onDocumentResize(n)
-                    };
-                    n(window).on("resize", s._resizeHandler);
-                    o.visible && (s.trigger(et), s.trigger(ot));
-                    i.notify(s)
-                },
-                _dimensions: function() {
-                    var i = this,
-                        t = i.wrapper,
-                        n = i.options,
-                        r = n.width,
-                        u = n.height,
-                        f = n.maxHeight;
-                    i.title(n.title);
-                    ut(["minWidth", "minHeight", "maxWidth", "maxHeight"], function(i, r) {
-                        var u = n[r];
-                        u && u != Infinity && t.css(r, u)
-                    });
-                    f && f != Infinity && i.element.css("maxHeight", f);
-                    r && (r.toString().indexOf("%") > 0 ? t.width(r) : t.width(o(r, n.minWidth, n.maxWidth)));
-                    u && (u.toString().indexOf("%") > 0 ? t.height(u) : t.height(o(u, n.minHeight, n.maxHeight)));
-                    n.visible || t.hide()
-                },
-                _position: function() {
-                    var t = this,
-                        i = t.wrapper,
-                        n = t.options.position;
-                    n.top === 0 && (n.top = n.top.toString());
-                    n.left === 0 && (n.left = n.left.toString());
-                    i.css({
-                        top: n.top || "",
-                        left: n.left || ""
-                    })
-                },
-                _animations: function() {
-                    var n = this.options;
-                    n.animation === !1 && (n.animation = {
-                        open: {
-                            effects: {}
-                        },
-                        close: {
-                            hide: !0,
-                            effects: {}
-                        }
-                    })
-                },
-                _resize: function() {
-                    i.resize(this.element.children())
-                },
-                _resizable: function() {
-                    var i = this.options.resizable,
-                        t = this.wrapper;
-                    if (this.resizing && (t.off("dblclick" + r).children(h).remove(), this.resizing.destroy(), this.resizing = null), i) {
-                        t.on("dblclick" + r, e, f(function(t) {
-                            n(t.target).closest(".k-window-action").length || this.toggleMaximization()
-                        }, this));
-                        ut("n e s w se sw ne nw".split(" "), function(n, i) {
-                            t.append(u.resizeHandle(i))
-                        });
-                        this.resizing = new ri(this)
-                    }
-                },
-                _draggable: function() {
-                    var n = this.options.draggable;
-                    this.dragging && (this.dragging.destroy(), this.dragging = null);
-                    n && (this.dragging = new ui(this, n.dragHandle || e))
-                },
-                setOptions: function(n) {
-                    var t = this;
-                    d.fn.setOptions.call(t, n);
-                    t._animations();
-                    t._dimensions();
-                    t._position();
-                    t._resizable();
-                    t._draggable()
-                },
-                events: [et, ot, pt, wt, it, "resize", bt, kt, dt],
-                options: {
-                    name: "Window",
-                    animation: {
-                        open: {
-                            effects: {
-                                zoom: {
-                                    direction: "in"
-                                },
-                                fade: {
-                                    direction: "in"
-                                }
-                            },
-                            duration: 350
-                        },
-                        close: {
-                            effects: {
-                                zoom: {
-                                    direction: "out",
-                                    properties: {
-                                        scale: .7
-                                    }
-                                },
-                                fade: {
-                                    direction: "out"
-                                }
-                            },
-                            duration: 350,
-                            hide: !0
-                        }
-                    },
-                    title: "",
-                    actions: ["Close"],
-                    autoFocus: !0,
-                    modal: !1,
-                    resizable: !0,
-                    draggable: !0,
-                    minWidth: 90,
-                    minHeight: 50,
-                    maxWidth: Infinity,
-                    maxHeight: Infinity,
-                    pinned: !1,
-                    position: {},
-                    content: null,
-                    visible: null,
-                    height: null,
-                    width: null,
-                    appendTo: "body"
-                },
-                _closable: function() {
-                    return n.inArray("close", n.map(this.options.actions, function(n) {
-                        return n.toLowerCase()
-                    })) > -1
-                },
-                _keydown: function(n) {
-                    var u = this,
-                        h = u.options,
-                        f = i.keys,
-                        e = n.keyCode,
-                        t = u.wrapper,
-                        c, r, s = 10,
-                        p = u.options.isMaximized,
-                        v, y, l, a;
-                    n.target != n.currentTarget || u._closing || (e == f.ESC && u._closable() && u._close(!0), !h.draggable || n.ctrlKey || p || (c = i.getOffset(t), e == f.UP ? r = t.css("top", c.top - s) : e == f.DOWN ? r = t.css("top", c.top + s) : e == f.LEFT ? r = t.css("left", c.left - s) : e == f.RIGHT && (r = t.css("left", c.left + s))), h.resizable && n.ctrlKey && !p && (e == f.UP ? (r = !0, y = t.height() - s) : e == f.DOWN && (r = !0, y = t.height() + s), e == f.LEFT ? (r = !0, v = t.width() - s) : e == f.RIGHT && (r = !0, v = t.width() + s), r && (l = o(v, h.minWidth, h.maxWidth), a = o(y, h.minHeight, h.maxHeight), isNaN(l) || (t.width(l), u.options.width = l + "px"), isNaN(a) || (t.height(a), u.options.height = a + "px"), u.resize())), r && n.preventDefault())
-                },
-                _overlay: function(t) {
-                    var i = this.appendTo.children(nt),
-                        r = this.wrapper;
-                    return i.length || (i = n("<div class='k-overlay' />")), i.insertBefore(r[0]).toggle(t).css(b, parseInt(r.css(b), 10) - 1), i
-                },
-                _windowActionHandler: function(t) {
-                    var r = n(t.target).closest(".k-window-action").find(".k-icon"),
-                        i = this;
-                    i._closing || ut({
-                        "k-i-close": function() {
-                            i._close(!0)
-                        },
-                        "k-i-maximize": i.maximize,
-                        "k-i-minimize": i.minimize,
-                        "k-i-restore": i.restore,
-                        "k-i-refresh": i.refresh,
-                        "k-i-pin": i.pin,
-                        "k-i-unpin": i.unpin
-                    }, function(n, u) {
-                        if (r.hasClass(n)) return t.preventDefault(), u.call(i), !1
-                    })
-                },
-                _modals: function() {
-                    var t = this;
-                    return n(a).filter(function() {
-                        var i = n(this),
-                            r = t._object(i).options;
-                        return r.modal && r.visible && i.is(y)
-                    }).sort(function(t, i) {
-                        return +n(t).css("zIndex") - +n(i).css("zIndex")
-                    })
-                },
-                _object: function(n) {
-                    var t = n.children(v);
-                    return t.data("kendoWindow") || t.data("kendo" + this.options.name)
-                },
-                center: function() {
-                    var t = this,
-                        e = t.options.position,
-                        r = t.wrapper,
-                        i = n(window),
-                        o = 0,
-                        s = 0,
-                        u, f;
-                    return t.options.isMaximized ? t : (t.options.pinned || (o = i.scrollTop(), s = i.scrollLeft()), f = s + Math.max(0, (i.width() - r.width()) / 2), u = o + Math.max(0, (i.height() - r.height()) / 2), r.css({
-                        left: f,
-                        top: u
-                    }), e.top = u, e.left = f, t)
-                },
-                title: function(n) {
-                    var i = this,
-                        r = i.wrapper,
-                        s = i.options,
-                        t = r.children(e),
-                        f = t.children(ft),
-                        o = t.outerHeight();
-                    return arguments.length ? (n === !1 ? (r.addClass("k-window-titleless"), t.remove()) : (t.length || r.prepend(u.titlebar(l(u, s))), r.css("padding-top", o), t.css("margin-top", -o)), f.text(n), i.options.title = n, i) : f.text()
-                },
-                content: function(n) {
-                    var t = this.wrapper.children(v),
-                        r = t.children(".km-scroll-container");
-                    return (t = r[0] ? r : t, !rt(n)) ? t.html() : (i.destroy(this.element.children()), t.html(n), this)
-                },
-                open: function() {
-                    var t = this,
-                        f = t.wrapper,
-                        r = t.options,
-                        e = r.animation.open,
-                        s = f.children(v),
-                        h = s.css(c),
-                        u, o;
-                    return t.trigger(et) || (t._closing && f.kendoStop(!0, !0), t._closing = !1, t.toFront(), r.autoFocus && t.element.focus(), r.visible = !0, r.modal && (u = t._overlay(!1), u.kendoStop(!0, !0), e.duration && i.effects.Fade ? (o = i.fx(u).fadeIn(), o.duration(e.duration || 0), o.endValue(.5), o.play()) : u.css("opacity", .5), u.show()), f.is(y) || (s.css(c, tt), f.show().kendoStop().kendoAnimate({
-                        effects: e.effects,
-                        duration: e.duration,
-                        complete: function() {
-                            r.autoFocus && t.element.focus();
-                            t.trigger(ot);
-                            s.css(c, h)
-                        }
-                    }))), r.isMaximized && (t._documentScrollTop = n(document).scrollTop(), n("html, body").css(c, tt)), t
-                },
-                _removeOverlay: function(r) {
-                    var f = this._modals(),
-                        e = this.options,
-                        s = e.modal && !f.length,
-                        h = e.modal ? this._overlay(!0) : n(t),
-                        o = e.animation.close,
-                        u;
-                    s ? !r && o.duration && i.effects.Fade ? (u = i.fx(h).fadeOut(), u.duration(o.duration || 0), u.startValue(.5), u.play()) : this._overlay(!1).remove() : f.length && this._object(f.last())._overlay(!0)
-                },
-                _close: function(t) {
-                    var i = this,
-                        r = i.wrapper,
-                        u = i.options,
-                        e = u.animation.open,
-                        f = u.animation.close;
-                    r.is(y) && !i.trigger(wt, {
-                        userTriggered: !!t
-                    }) && (i._closing = !0, u.visible = !1, n(a).each(function(t, i) {
-                        var u = n(i).children(v);
-                        i != r && u.find("> ." + w).length > 0 && u.children(nt).remove()
-                    }), this._removeOverlay(), r.kendoStop().kendoAnimate({
-                        effects: f.effects || e.effects,
-                        reverse: f.reverse === !0,
-                        duration: f.duration,
-                        complete: function() {
-                            r.hide().css("opacity", "");
-                            i.trigger(pt);
-                            var n = i._object(i._modals().last());
-                            n && n.toFront()
-                        }
-                    }));
-                    i.options.isMaximized && (n("html, body").css(c, ""), i._documentScrollTop && i._documentScrollTop > 0 && n(document).scrollTop(i._documentScrollTop))
-                },
-                close: function() {
-                    return this._close(!1), this
-                },
-                _actionable: function(t) {
-                    return n(t).is(k + "," + k + " .k-icon,:input,a")
-                },
-                _shouldFocus: function(t) {
-                    var r = fi(),
-                        i = this.element;
-                    return this.options.autoFocus && !n(r).is(i) && !this._actionable(t) && (!i.find(r).length || !i.find(t).length)
-                },
-                toFront: function(t) {
-                    var r = this,
-                        i = r.wrapper,
-                        s = i[0],
-                        f = +i.css(b),
-                        h = f,
-                        c = t && t.target || null,
-                        e, o;
-                    return n(a).each(function(t, i) {
-                        var r = n(i),
-                            e = r.css(b),
-                            o = r.children(v);
-                        isNaN(e) || (f = Math.max(+e, f));
-                        i != s && o.find("> ." + w).length > 0 && o.append(u.overlay)
-                    }), (!i[0].style.zIndex || h < f) && i.css(b, f + 2), r.element.find("> .k-overlay").remove(), r._shouldFocus(c) && (r.element.focus(), e = n(window).scrollTop(), o = parseInt(i.position().top, 10), o > 0 && o < e && (e > 0 ? n(window).scrollTop(o) : i.css("top", e))), r
-                },
-                toggleMaximization: function() {
-                    return this._closing ? this : this[this.options.isMaximized ? "restore" : "maximize"]()
-                },
-                restore: function() {
-                    var t = this,
-                        i = t.options,
-                        u = i.minHeight,
-                        r = t.restoreOptions;
-                    return !i.isMaximized && !i.isMinimized ? t : (u && u != Infinity && t.wrapper.css("min-height", u), t.wrapper.css({
-                        position: i.pinned ? "fixed" : "absolute",
-                        left: r.left,
-                        top: r.top,
-                        width: r.width,
-                        height: r.height
-                    }).removeClass(yt).find(".k-window-content,.k-resize-handle").show().end().find(".k-window-titlebar .k-i-restore").parent().remove().end().end().find(gt).parent().show().end().end().find(st).parent().show(), t.options.width = r.width, t.options.height = r.height, n("html, body").css(c, ""), this._documentScrollTop && this._documentScrollTop > 0 && n(document).scrollTop(this._documentScrollTop), i.isMaximized = i.isMinimized = !1, t.resize(), t)
-                },
-                maximize: ii("maximize", function() {
-                    var t = this,
-                        i = t.wrapper,
-                        r = i.position();
-                    l(t.restoreOptions, {
-                        left: r.left,
-                        top: r.top
-                    });
-                    i.css({
-                        left: 0,
-                        top: 0,
-                        position: "fixed"
-                    }).addClass(yt);
-                    this._documentScrollTop = n(document).scrollTop();
-                    n("html, body").css(c, tt);
-                    t.options.isMaximized = !0;
-                    t._onDocumentResize()
-                }),
-                minimize: ii("minimize", function() {
-                    var n = this;
-                    n.wrapper.css({
-                        height: "",
-                        minHeight: ""
-                    });
-                    n.element.hide();
-                    n.options.isMinimized = !0
-                }),
-                pin: function(t) {
-                    var i = this,
-                        u = n(window),
-                        r = i.wrapper,
-                        f = parseInt(r.css("top"), 10),
-                        o = parseInt(r.css("left"), 10);
-                    !t && (i.options.pinned || i.options.isMaximized) || (r.css({
-                        position: "fixed",
-                        top: f - u.scrollTop(),
-                        left: o - u.scrollLeft()
-                    }), r.children(e).find(ni).addClass("k-i-unpin").removeClass("k-i-pin"), i.options.pinned = !0)
-                },
-                unpin: function() {
-                    var t = this,
-                        r = n(window),
-                        i = t.wrapper,
-                        u = parseInt(i.css("top"), 10),
-                        f = parseInt(i.css("left"), 10);
-                    t.options.pinned && !t.options.isMaximized && (i.css({
-                        position: "",
-                        top: u + r.scrollTop(),
-                        left: f + r.scrollLeft()
-                    }), i.children(e).find(ti).addClass("k-i-pin").removeClass("k-i-unpin"), t.options.pinned = !1)
-                },
-                _onDocumentResize: function() {
-                    var t = this,
-                        u = t.wrapper,
-                        f = n(window),
-                        i, r;
-                    t.options.isMaximized && (i = f.width(), r = f.height() - parseInt(u.css("padding-top"), 10), u.css({
-                        width: i,
-                        height: r
-                    }), t.options.width = i, t.options.height = r, t.resize())
-                },
-                refresh: function(t) {
-                    var i = this,
-                        e = i.options,
-                        o = n(i.element),
-                        h, f, c;
-                    if (ct(t) || (t = {
-                            url: t
-                        }), t = l({}, e.content, t), f = rt(e.iframe) ? e.iframe : t.iframe, c = t.url, c)
-                        if (rt(f) || (f = !ei(c)), f) {
-                            h = o.find("." + w)[0];
-                            h ? h.src = c || h.src : o.html(u.contentFrame(l({}, e, {
-                                content: t
-                            })));
-                            o.find("." + w).unbind("load" + r).on("load" + r, function() {
-                                i.trigger(it)
-                            })
-                        } else i._ajaxRequest(t);
-                    else t.template && i.content(s(t.template)({})), i.trigger(it);
-                    return o.toggleClass("k-window-iframecontent", f), i
-                },
-                _ajaxRequest: function(t) {
-                    var i = this,
-                        r = t.template,
-                        u = i.wrapper.find(".k-window-titlebar .k-i-refresh"),
-                        f = setTimeout(function() {
-                            u.addClass(lt)
-                        }, 100);
-                    n.ajax(l({
-                        type: "GET",
-                        dataType: "html",
-                        cache: !1,
-                        error: function(n, t) {
-                            i.trigger(dt, {
-                                status: t,
-                                xhr: n
-                            })
-                        },
-                        complete: function() {
-                            clearTimeout(f);
-                            u.removeClass(lt)
-                        },
-                        success: function(n) {
-                            r && (n = s(r)(n || {}));
-                            i.content(n);
-                            i.element.prop("scrollTop", 0);
-                            i.trigger(it)
-                        }
-                    }, t))
-                },
-                destroy: function() {
-                    var t = this.wrapper;
-                    d.fn.destroy.call(this);
-                    i.destroy(t);
-                    this.resizing && this.resizing.destroy();
-                    this.dragging && this.dragging.destroy();
-                    this.element.children("iframe").remove();
-                    t.find(".k-resize-handle,.k-window-titlebar").off(r);
-                    t.remove().off(r);
-                    n(window).off("resize", this._resizeHandler);
-                    this._removeOverlay(!0)
-                },
-                _createWindow: function() {
-                    var e = this,
-                        t = e.element,
-                        f = e.options,
-                        o, r, s = i.support.isRtl(t);
-                    f.scrollable === !1 && t.attr("style", "overflow:hidden;");
-                    r = n(u.wrapper(f));
-                    f.title !== !1 && r.append(u.titlebar(l(u, f)));
-                    o = t.find("iframe:not(.k-content)").map(function() {
-                        var n = this.getAttribute("src");
-                        return this.src = "", n
-                    });
-                    r.toggleClass("k-rtl", s).appendTo(e.appendTo).append(t).find("iframe:not(.k-content)").each(function(n) {
-                        this.src = o[n]
-                    });
-                    r.find(".k-window-title").css(s ? "left" : "right", r.find(".k-window-actions").outerWidth() + 10);
-                    t.show();
-                    t.find("[data-role=editor]").each(function() {
-                        var t = n(this).data("kendoEditor");
-                        t && t.refresh()
-                    })
-                }
-            });
-        u = {
-            wrapper: s("<div class='k-widget k-window' />"),
-            action: s("<a role='button' href='\\#' class='k-window-action k-link'><span role='presentation' class='k-icon k-i-#= name.toLowerCase() #'>#= name #<\/span><\/a>"),
-            titlebar: s("<div class='k-window-titlebar k-header'>&nbsp;<span class='k-window-title'>#= title #<\/span><div class='k-window-actions'># for (var i = 0; i < actions.length; i++) { ##= action({ name: actions[i] }) ## } #<\/div><\/div>"),
-            overlay: "<div class='k-overlay' />",
-            contentFrame: s("<iframe frameborder='0' title='#= title #' class='" + w + "' src='#= content.url #'>This page requires frames in order to show content<\/iframe>"),
-            resizeHandle: s("<div class='k-resize-handle k-resize-#= data #'><\/div>")
-        };
-        ri.prototype = {
-            dragstart: function(t) {
-                var r = this,
-                    e = r.owner,
-                    f = e.wrapper;
-                r.elementPadding = parseInt(e.wrapper.css("padding-top"), 10);
-                r.initialCursorPosition = i.getOffset(f, "position");
-                r.resizeDirection = t.currentTarget.prop("className").replace("k-resize-handle k-resize-", "");
-                r.initialSize = {
-                    width: f.width(),
-                    height: f.height()
-                };
-                r.containerOffset = i.getOffset(e.appendTo);
-                f.append(u.overlay).children(h).not(t.currentTarget).hide();
-                n(g).css(p, t.currentTarget.css(p))
-            },
-            drag: function(n) {
-                var u = this,
-                    f = u.owner,
-                    e = f.wrapper,
-                    t = f.options,
-                    s = u.resizeDirection,
-                    h = u.containerOffset,
-                    c = u.initialCursorPosition,
-                    v = u.initialSize,
-                    i, r, l, a, y = Math.max(n.x.location, h.left),
-                    p = Math.max(n.y.location, h.top);
-                s.indexOf("e") >= 0 ? (i = y - c.left, e.width(o(i, t.minWidth, t.maxWidth))) : s.indexOf("w") >= 0 && (a = c.left + v.width, i = o(a - y, t.minWidth, t.maxWidth), e.css({
-                    left: a - i - h.left,
-                    width: i
-                }));
-                s.indexOf("s") >= 0 ? (r = p - c.top - u.elementPadding, e.height(o(r, t.minHeight, t.maxHeight))) : s.indexOf("n") >= 0 && (l = c.top + v.height, r = o(l - p, t.minHeight, t.maxHeight), e.css({
-                    top: l - r - h.top,
-                    height: r
-                }));
-                i && (f.options.width = i + "px");
-                r && (f.options.height = r + "px");
-                f.resize()
-            },
-            dragend: function(t) {
-                var i = this,
-                    r = i.owner,
-                    u = r.wrapper;
-                return u.find(nt).remove().end().children(h).not(t.currentTarget).show(), n(g).css(p, ""), r.touchScroller && r.touchScroller.reset(), t.keyCode == 27 && u.css(i.initialCursorPosition).css(i.initialSize), !1
-            },
-            destroy: function() {
-                this._draggable.destroy()
-            }
-        };
-        ui.prototype = {
-            dragstart: function(t) {
-                var r = this.owner,
-                    f = r.element,
-                    e = f.find(".k-window-actions"),
-                    o = i.getOffset(r.appendTo);
-                r.trigger(bt);
-                r.initialWindowPosition = i.getOffset(r.wrapper, "position");
-                r.startPosition = {
-                    left: t.x.client - r.initialWindowPosition.left,
-                    top: t.y.client - r.initialWindowPosition.top
-                };
-                r.minLeftPosition = e.length > 0 ? e.outerWidth() + parseInt(e.css("right"), 10) - f.outerWidth() : 20 - f.outerWidth();
-                r.minLeftPosition -= o.left;
-                r.minTopPosition = -o.top;
-                r.wrapper.append(u.overlay).children(h).hide();
-                n(g).css(p, t.currentTarget.css(p))
-            },
-            drag: function(t) {
-                var i = this.owner,
-                    r = i.options.position,
-                    u = Math.max(t.y.client - i.startPosition.top, i.minTopPosition),
-                    f = Math.max(t.x.client - i.startPosition.left, i.minLeftPosition),
-                    e = {
-                        left: f,
-                        top: u
-                    };
-                n(i.wrapper).css(e);
-                r.top = u;
-                r.left = f
-            },
-            _finishDrag: function() {
-                var t = this.owner;
-                t.wrapper.children(h).toggle(!t.options.isMinimized).end().find(nt).remove();
-                n(g).css(p, "")
-            },
-            dragcancel: function(n) {
-                this._finishDrag();
-                n.currentTarget.closest(a).css(this.owner.initialWindowPosition)
-            },
-            dragend: function() {
-                return this._finishDrag(), this.owner.trigger(kt), !1
-            },
-            destroy: function() {
-                this._draggable.destroy()
-            }
-        };
-        i.ui.plugin(oi)
-    }(window.kendo.jQuery);
-! function(n) {
-    return n(["./kendo.data.min", "./kendo.combobox.min", "./kendo.multiselect.min", "./kendo.validator.min"], function() {
-        ! function(n, t) {
-            function u(t, i, r, u) {
-                var f = {};
-                return t.sort ? (f[this.options.prefix + "sort"] = n.map(t.sort, function(n) {
-                    return n.field + "-" + n.dir
-                }).join("~"), delete t.sort) : f[this.options.prefix + "sort"] = "", t.page && (f[this.options.prefix + "page"] = t.page, delete t.page), t.pageSize && (f[this.options.prefix + "pageSize"] = t.pageSize, delete t.pageSize), t.group ? (f[this.options.prefix + "group"] = n.map(t.group, function(n) {
-                    return n.field + "-" + n.dir
-                }).join("~"), delete t.group) : f[this.options.prefix + "group"] = "", t.aggregate && (f[this.options.prefix + "aggregate"] = n.map(t.aggregate, function(n) {
-                    return n.field + "-" + n.aggregate
-                }).join("~"), delete t.aggregate), t.filter ? (f[this.options.prefix + "filter"] = o(t.filter, r), delete t.filter) : (f[this.options.prefix + "filter"] = "", delete t.filter), delete t.take, delete t.skip, e(f, t, "", u), f
-            }
-
-            function c(n) {
-                var t = i.culture().numberFormat[h];
-                return ("" + n).replace(h, t)
-            }
-
-            function l(n, t) {
-                return n instanceof Date ? n = t ? i.stringify(n).replace(/"/g, "") : i.format("{0:G}", n) : "number" == typeof n && (n = c(n)), n
-            }
-
-            function f(n, i, r, u, f, o) {
-                b(i) ? a(n, i, f, o) : k(i) ? e(n, i, f, o) : n[f] === t && (n[f] = r[u] = l(i, o))
-            }
-
-            function e(n, t, i, r) {
-                var u, e, o;
-                for (u in t) e = i ? i + "." + u : u, o = t[u], f(n, o, t, u, e, r)
-            }
-
-            function a(n, t, i, r) {
-                for (var s, o, h, u = 0, e = 0; u < t.length; u++) s = t[u], o = "[" + e + "]", h = i + o, f(n, s, t, o, h, r), e++
-            }
-
-            function o(i, r) {
-                return i.filters ? n.map(i.filters, function(n) {
-                    var i = n.filters && n.filters.length > 1,
-                        t = o(n, r);
-                    return t && i && (t = "(" + t + ")"), t
-                }).join("~" + i.logic + "~") : i.field ? i.field + "~" + i.operator + "~" + v(i.value, r) : t
-            }
-
-            function v(n, t) {
-                if ("string" == typeof n) {
-                    if (!(n.indexOf("Date(") > -1)) return n = n.replace(w, "''"), t && (n = encodeURIComponent(n)), "'" + n + "'";
-                    n = new Date(parseInt(n.replace(/^\/Date\((.*?)\)\/$/, "$1"), 10))
-                }
-                return n && n.getTime ? "datetime'" + i.format("{0:yyyy-MM-ddTHH-mm-ss}", n) + "'" : n
-            }
-
-            function s(i) {
-                return {
-                    value: t !== i.Key ? i.Key : i.value,
-                    field: i.Member || i.field,
-                    hasSubgroups: i.HasSubgroups || i.hasSubgroups || !1,
-                    aggregates: p(i.Aggregates || i.aggregates),
-                    items: i.HasSubgroups ? n.map(i.Items || i.items, s) : i.Items || i.items
-                }
-            }
-
-            function y(n) {
-                var t = {};
-                return t[n.AggregateMethodName.toLowerCase()] = n.Value, t
-            }
-
-            function p(n) {
-                var t, i, r, u = {};
-                for (t in n) {
-                    u = {};
-                    r = n[t];
-                    for (i in r) u[i.toLowerCase()] = r[i];
-                    n[t] = u
-                }
-                return n
-            }
-            var i = window.kendo,
-                w = /'/gi,
-                r = n.extend,
-                b = n.isArray,
-                k = n.isPlainObject,
-                h = ".";
-            r(!0, i.data, {
-                schemas: {
-                    "aspnetmvc-ajax": {
-                        groups: function(t) {
-                            return n.map(this.data(t), s)
-                        },
-                        aggregates: function(n) {
-                            n = n.d || n;
-                            for (var t, u = {}, e = n.AggregateResults || [], i = 0, f = e.length; f > i; i++) t = e[i], u[t.Member] = r(!0, u[t.Member], y(t));
-                            return u
-                        }
-                    }
-                }
-            });
-            r(!0, i.data, {
-                transports: {
-                    "aspnetmvc-ajax": i.data.RemoteTransport.extend({
-                        init: function(n) {
-                            var t = this,
-                                f = (n || {}).stringifyDates;
-                            i.data.RemoteTransport.fn.init.call(this, r(!0, {}, this.options, n, {
-                                parameterMap: function(n, i) {
-                                    return u.call(t, n, i, !1, f)
-                                }
-                            }))
-                        },
-                        read: function(n) {
-                            var t = this.options.data,
-                                r = this.options.read.url;
-                            t ? (r && (this.options.data = null), !t.Data.length && r ? i.data.RemoteTransport.fn.read.call(this, n) : n.success(t)) : i.data.RemoteTransport.fn.read.call(this, n)
-                        },
-                        options: {
-                            read: {
-                                type: "POST"
-                            },
-                            update: {
-                                type: "POST"
-                            },
-                            create: {
-                                type: "POST"
-                            },
-                            destroy: {
-                                type: "POST"
-                            },
-                            parameterMap: u,
-                            prefix: ""
-                        }
-                    })
-                }
-            });
-            r(!0, i.data, {
-                transports: {
-                    "aspnetmvc-server": i.data.RemoteTransport.extend({
-                        init: function(n) {
-                            var t = this;
-                            i.data.RemoteTransport.fn.init.call(this, r(n, {
-                                parameterMap: function(n, i) {
-                                    return u.call(t, n, i, !0)
-                                }
-                            }))
-                        },
-                        read: function(t) {
-                            var r, i, u = this.options.prefix,
-                                f = [u + "sort", u + "page", u + "pageSize", u + "group", u + "aggregate", u + "filter"],
-                                e = RegExp("(" + f.join("|") + ")=[^&]*&?", "g");
-                            i = location.search.replace(e, "").replace("?", "");
-                            i.length && !/&$/.test(i) && (i += "&");
-                            t = this.setup(t, "read");
-                            r = t.url;
-                            r.indexOf("?") >= 0 ? (i = i.replace(/(.*?=.*?)&/g, function(n) {
-                                return r.indexOf(n.substr(0, n.indexOf("="))) >= 0 ? "" : n
-                            }), r += "&" + i) : r += "?" + i;
-                            r += n.map(t.data, function(n, t) {
-                                return t + "=" + n
-                            }).join("&");
-                            location.href = r
-                        }
-                    })
-                }
-            })
-        }(window.kendo.jQuery),
-        function(n) {
-            var i = window.kendo,
-                t = i.ui;
-            t && t.ComboBox && (t.ComboBox.requestData = function(t) {
-                var i = n(t).data("kendoComboBox"),
-                    u = i.dataSource.filter(),
-                    r = i.input.val();
-                return u || (r = ""), {
-                    text: r
-                }
-            })
-        }(window.kendo.jQuery),
-        function(n) {
-            var i = window.kendo,
-                t = i.ui;
-            t && t.MultiSelect && (t.MultiSelect.requestData = function(t) {
-                var i = n(t).data("kendoMultiSelect"),
-                    r = i.input.val();
-                return {
-                    text: r !== i.options.placeholder ? r : ""
-                }
-            })
-        }(window.kendo.jQuery),
-        function(n) {
-            var t = window.kendo,
-                i = (t.ui, n.extend),
-                r = n.isFunction;
-            i(!0, t.data, {
-                schemas: {
-                    "imagebrowser-aspnetmvc": {
-                        data: function(n) {
-                            return n || []
-                        },
-                        model: {
-                            id: "name",
-                            fields: {
-                                name: {
-                                    field: "Name"
-                                },
-                                size: {
-                                    field: "Size"
-                                },
-                                type: {
-                                    field: "EntryType",
-                                    parse: function(n) {
-                                        return 0 == n ? "f" : "d"
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            });
-            i(!0, t.data, {
-                transports: {
-                    "imagebrowser-aspnetmvc": t.data.RemoteTransport.extend({
-                        init: function(i) {
-                            t.data.RemoteTransport.fn.init.call(this, n.extend(!0, {}, this.options, i))
-                        },
-                        _call: function(i, u) {
-                            u.data = n.extend({}, u.data, {
-                                path: this.options.path()
-                            });
-                            r(this.options[i]) ? this.options[i].call(this, u) : t.data.RemoteTransport.fn[i].call(this, u)
-                        },
-                        read: function(n) {
-                            this._call("read", n)
-                        },
-                        create: function(n) {
-                            this._call("create", n)
-                        },
-                        destroy: function(n) {
-                            this._call("destroy", n)
-                        },
-                        update: function() {},
-                        options: {
-                            read: {
-                                type: "POST"
-                            },
-                            update: {
-                                type: "POST"
-                            },
-                            create: {
-                                type: "POST"
-                            },
-                            destroy: {
-                                type: "POST"
-                            },
-                            parameterMap: function(n, t) {
-                                return "read" != t && (n.EntryType = "f" === n.EntryType ? 0 : 1), n
-                            }
-                        }
-                    })
-                }
-            })
-        }(window.kendo.jQuery),
-        function(n) {
-            function r() {
-                var n, i = {};
-                for (n in t) i["mvc" + n] = s(n);
-                return i
-            }
-
-            function u() {
-                var n, i = {};
-                for (n in t) i["mvc" + n] = h(n);
-                return i
-            }
-
-            function f(n, t) {
-                var u, i, r, f = {},
-                    e = n.data(),
-                    o = t.length;
-                for (r in e) i = r.toLowerCase(), u = i.indexOf(t), u > -1 && (i = i.substring(u + o, r.length), i && (f[i] = e[r]));
-                return f
-            }
-
-            function e(t) {
-                for (var u = t.Fields || [], f = {}, i = 0, r = u.length; r > i; i++) n.extend(!0, f, o(u[i]));
-                return f
-            }
-
-            function o(n) {
-                for (var i, f, o = {}, s = {}, u = n.FieldName, r = n.ValidationRules, t = 0, e = r.length; e > t; t++) i = r[t].ValidationType, f = r[t].ValidationParameters, o[u + i] = l(u, i, f), s[u + i] = c(r[t].ErrorMessage);
-                return {
-                    rules: o,
-                    messages: s
-                }
-            }
-
-            function s(n) {
-                return function(t) {
-                    return t.attr("data-val-" + n)
-                }
-            }
-
-            function h(n) {
-                return function(i) {
-                    return i.filter("[data-val-" + n + "]").length ? t[n](i, f(i, n)) : !0
-                }
-            }
-
-            function c(n) {
-                return function() {
-                    return n
-                }
-            }
-
-            function l(n, i, r) {
-                return function(u) {
-                    return u.filter("[name=" + n + "]").length ? t[i](u, r) : !0
-                }
-            }
-
-            function a(n, t) {
-                return "string" == typeof t && (t = RegExp("^(?:" + t + ")$")), t.test(n)
-            }
-            var i = /("|\%|'|\[|\]|\$|\.|\,|\:|\;|\+|\*|\&|\!|\#|\(|\)|<|>|\=|\?|\@|\^|\{|\}|\~|\/|\||`)/g,
-                t = {
-                    required: function(n) {
-                        var f, t, r = n.val(),
-                            u = n.filter("[type=checkbox]");
-                        return u.length && (f = u[0].name.replace(i, "\\$1"), t = u.next("input:hidden[name='" + f + "']"), r = t.length ? t.val() : "checked" === n.attr("checked")), !("" === r || !r)
-                    },
-                    number: function(n) {
-                        return "" === n.val() || null !== kendo.parseFloat(n.val())
-                    },
-                    regex: function(n, t) {
-                        return "" !== n.val() ? a(n.val(), t.pattern) : !0
-                    },
-                    range: function(n, t) {
-                        return "" !== n.val() ? this.min(n, t) && this.max(n, t) : !0
-                    },
-                    min: function(n, t) {
-                        var i = parseFloat(t.min) || 0,
-                            r = kendo.parseFloat(n.val());
-                        return r >= i
-                    },
-                    max: function(n, t) {
-                        var i = parseFloat(t.max) || 0,
-                            r = kendo.parseFloat(n.val());
-                        return i >= r
-                    },
-                    date: function(n) {
-                        return "" === n.val() || null !== kendo.parseDate(n.val())
-                    },
-                    length: function(t, i) {
-                        if ("" !== t.val()) {
-                            var r = n.trim(t.val()).length;
-                            return (!i.min || r >= (i.min || 0)) && (!i.max || r <= (i.max || 0))
-                        }
-                        return !0
-                    }
-                };
-            n.extend(!0, kendo.ui.validator, {
-                rules: u(),
-                messages: r(),
-                messageLocators: {
-                    mvcLocator: {
-                        locate: function(n, t) {
-                            return t = t.replace(i, "\\$1"), n.find(".field-validation-valid[data-valmsg-for=" + t + "], .field-validation-error[data-valmsg-for=" + t + "]")
-                        },
-                        decorate: function(n, t) {
-                            n.addClass("field-validation-error").attr("data-valmsg-for", t || "")
-                        }
-                    },
-                    mvcMetadataLocator: {
-                        locate: function(n, t) {
-                            return t = t.replace(i, "\\$1"), n.find("#" + t + "_validationMessage.field-validation-valid")
-                        },
-                        decorate: function(n, t) {
-                            n.addClass("field-validation-error").attr("id", t + "_validationMessage")
-                        }
-                    }
-                },
-                ruleResolvers: {
-                    mvcMetaDataResolver: {
-                        resolve: function(t) {
-                            var i, r = window.mvcClientValidationMetadata || [];
-                            if (r.length)
-                                for (t = n(t), i = 0; i < r.length; i++)
-                                    if (r[i].FormId == t.attr("id")) return e(r[i]);
-                            return {}
-                        }
-                    }
-                }
-            })
-        }(window.kendo.jQuery)
-    })
-}("function" == typeof define && define.amd ? define : function(n, t) {
-    return t()
-});
-! function(n) {
-    return n([], function() {
-        ! function(n) {
-            var t = n.kendo || (n.kendo = {
-                cultures: {}
-            });
-            t.cultures["pl-PL"] = {
-                name: "pl-PL",
-                numberFormat: {
-                    pattern: ["-n"],
-                    decimals: 2,
-                    ",": " ",
-                    ".": ",",
-                    groupSize: [3],
-                    percent: {
-                        pattern: ["-n%", "n%"],
-                        decimals: 2,
-                        ",": " ",
-                        ".": ",",
-                        groupSize: [3],
-                        symbol: "%"
-                    },
-                    currency: {
-                        pattern: ["-n $", "n $"],
-                        decimals: 2,
-                        ",": " ",
-                        ".": ",",
-                        groupSize: [3],
-                        symbol: "zł"
-                    }
-                },
-                calendars: {
-                    standard: {
-                        days: {
-                            names: ["niedziela", "poniedziałek", "wtorek", "środa", "czwartek", "piątek", "sobota"],
-                            namesAbbr: ["N", "Pn", "Wt", "Śr", "Cz", "Pt", "So"],
-                            namesShort: ["N", "Pn", "Wt", "Śr", "Cz", "Pt", "So"]
-                        },
-                        months: {
-                            names: ["styczeń", "luty", "marzec", "kwiecień", "maj", "czerwiec", "lipiec", "sierpień", "wrzesień", "październik", "listopad", "grudzień", ""],
-                            namesAbbr: ["sty", "lut", "mar", "kwi", "maj", "cze", "lip", "sie", "wrz", "paź", "lis", "gru", ""]
-                        },
-                        AM: [""],
-                        PM: [""],
-                        patterns: {
-                            d: "yyyy-MM-dd",
-                            D: "d MMMM yyyy",
-                            F: "d MMMM yyyy HH:mm:ss",
-                            g: "yyyy-MM-dd HH:mm",
-                            G: "yyyy-MM-dd HH:mm:ss",
-                            m: "d MMMM",
-                            M: "d MMMM",
-                            s: "yyyy'-'MM'-'dd'T'HH':'mm':'ss",
-                            t: "HH:mm",
-                            T: "HH:mm:ss",
-                            u: "yyyy'-'MM'-'dd HH':'mm':'ss'Z'",
-                            y: "MMMM yyyy",
-                            Y: "MMMM yyyy"
-                        },
-                        "/": "-",
-                        ":": ":",
-                        firstDay: 1
-                    }
-                }
-            }
-        }(this)
-    })
-}("function" == typeof define && define.amd ? define : function(n, t) {
-    return t()
-}),
-function() {
-    function n(n) {
-        return function() {
-            return n
-        }
-    }(function(t) {
-        var u = this || eval("this"),
-            r = u.document,
-            e = u.navigator,
-            i = u.jQuery,
-            f = u.JSON;
-        (function(n) {
-            "function" == typeof require && "object" == typeof exports && "object" == typeof module ? n(module.exports || exports) : "function" == typeof define && define.amd ? define(["exports"], n) : n(u.ko = {})
-        })(function(o) {
-            function c(n, t, i, r) {
-                s.d[n] = {
-                    init: function(n) {
-                        return s.a.f.set(n, a, {}), {
-                            controlsDescendantBindings: !0
-                        }
-                    },
-                    update: function(n, u, f, e, o) {
-                        f = s.a.f.get(n, a);
-                        u = s.a.c(u());
-                        e = !i != !u;
-                        var h = !f.fb;
-                        (h || t || e !== f.vb) && (h && (f.fb = s.a.Oa(s.e.childNodes(n), !0)), e ? (h || s.e.P(n, s.a.Oa(f.fb)), s.Ja(r ? r(o, u) : o, n)) : s.e.ba(n), f.vb = e)
-                    }
-                };
-                s.g.S[n] = !1;
-                s.e.L[n] = !0
-            }
-
-            function v(n, t, i) {
-                i && t !== s.h.n(n) && s.h.W(n, t);
-                t !== s.h.n(n) && s.q.I(s.a.Ga, null, [n, "change"])
-            }
-            var s = "undefined" != typeof o ? o : {},
-                y, h, l, a;
-            s.b = function(n, t) {
-                for (var i = n.split("."), r = s, u = 0; u < i.length - 1; u++) r = r[i[u]];
-                r[i[i.length - 1]] = t
-            };
-            s.r = function(n, t, i) {
-                n[t] = i
-            };
-            s.version = "2.3.0";
-            s.b("version", s.version);
-            s.a = function() {
-                function o(n, t) {
-                    for (var i in n) n.hasOwnProperty(i) && t(i, n[i])
-                }
-
-                function h(n, t) {
-                    if ("input" !== s.a.u(n) || !n.type || "click" != t.toLowerCase()) return !1;
-                    var i = n.type;
-                    return "checkbox" == i || "radio" == i
-                }
-                var c = {},
-                    l = {},
-                    a, n;
-                return c[e && /Firefox\/2/i.test(e.userAgent) ? "KeyboardEvent" : "UIEvents"] = ["keyup", "keydown", "keypress"], c.MouseEvents = "click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave".split(" "), o(c, function(n, t) {
-                    if (t.length)
-                        for (var i = 0, r = t.length; i < r; i++) l[t[i]] = n
-                }), a = {
-                    propertychange: !0
-                }, n = r && function() {
-                    for (var n = 3, i = r.createElement("div"), u = i.getElementsByTagName("i"); i.innerHTML = "<!--[if gt IE " + ++n + "]><i><\/i><![endif]-->", u[0];);
-                    return 4 < n ? n : t
-                }(), {
-                    Ta: ["authenticity_token", /^__RequestVerificationToken(_.*)?$/],
-                    p: function(n, t) {
-                        for (var i = 0, r = n.length; i < r; i++) t(n[i])
-                    },
-                    k: function(n, t) {
-                        if ("function" == typeof Array.prototype.indexOf) return Array.prototype.indexOf.call(n, t);
-                        for (var i = 0, r = n.length; i < r; i++)
-                            if (n[i] === t) return i;
-                        return -1
-                    },
-                    La: function(n, t, i) {
-                        for (var r = 0, u = n.length; r < u; r++)
-                            if (t.call(i, n[r])) return n[r];
-                        return null
-                    },
-                    ka: function(n, t) {
-                        var i = s.a.k(n, t);
-                        0 <= i && n.splice(i, 1)
-                    },
-                    Ma: function(n) {
-                        n = n || [];
-                        for (var i = [], t = 0, r = n.length; t < r; t++) 0 > s.a.k(i, n[t]) && i.push(n[t]);
-                        return i
-                    },
-                    Z: function(n, t) {
-                        n = n || [];
-                        for (var r = [], i = 0, u = n.length; i < u; i++) r.push(t(n[i]));
-                        return r
-                    },
-                    Y: function(n, t) {
-                        n = n || [];
-                        for (var r = [], i = 0, u = n.length; i < u; i++) t(n[i]) && r.push(n[i]);
-                        return r
-                    },
-                    R: function(n, t) {
-                        if (t instanceof Array) n.push.apply(n, t);
-                        else
-                            for (var i = 0, r = t.length; i < r; i++) n.push(t[i]);
-                        return n
-                    },
-                    ja: function(n, t, i) {
-                        var r = n.indexOf ? n.indexOf(t) : s.a.k(n, t);
-                        0 > r ? i && n.push(t) : i || n.splice(r, 1)
-                    },
-                    extend: function(n, t) {
-                        if (t)
-                            for (var i in t) t.hasOwnProperty(i) && (n[i] = t[i]);
-                        return n
-                    },
-                    w: o,
-                    oa: function(n) {
-                        for (; n.firstChild;) s.removeNode(n.firstChild)
-                    },
-                    Mb: function(n) {
-                        n = s.a.N(n);
-                        for (var i = r.createElement("div"), t = 0, u = n.length; t < u; t++) i.appendChild(s.H(n[t]));
-                        return i
-                    },
-                    Oa: function(n, t) {
-                        for (var r, i = 0, f = n.length, u = []; i < f; i++) r = n[i].cloneNode(!0), u.push(t ? s.H(r) : r);
-                        return u
-                    },
-                    P: function(n, t) {
-                        if (s.a.oa(n), t)
-                            for (var i = 0, r = t.length; i < r; i++) n.appendChild(t[i])
-                    },
-                    eb: function(n, t) {
-                        var r = n.nodeType ? [n] : n;
-                        if (0 < r.length) {
-                            for (var f = r[0], e = f.parentNode, i = 0, u = t.length; i < u; i++) e.insertBefore(t[i], f);
-                            for (i = 0, u = r.length; i < u; i++) s.removeNode(r[i])
-                        }
-                    },
-                    hb: function(t, i) {
-                        7 > n ? t.setAttribute("selected", i) : t.selected = i
-                    },
-                    F: function(n) {
-                        return null === n || n === t ? "" : n.trim ? n.trim() : n.toString().replace(/^[\s\xa0]+|[\s\xa0]+$/g, "")
-                    },
-                    Wb: function(n, t) {
-                        for (var r, u = [], f = (n || "").split(t), i = 0, e = f.length; i < e; i++) r = s.a.F(f[i]), "" !== r && u.push(r);
-                        return u
-                    },
-                    Tb: function(n, t) {
-                        return n = n || "", t.length > n.length ? !1 : n.substring(0, t.length) === t
-                    },
-                    yb: function(n, t) {
-                        if (t.compareDocumentPosition) return 16 == (t.compareDocumentPosition(n) & 16);
-                        for (; null != n;) {
-                            if (n == t) return !0;
-                            n = n.parentNode
-                        }
-                        return !1
-                    },
-                    aa: function(n) {
-                        return s.a.yb(n, n.ownerDocument)
-                    },
-                    pb: function(n) {
-                        return !!s.a.La(n, s.a.aa)
-                    },
-                    u: function(n) {
-                        return n && n.tagName && n.tagName.toLowerCase()
-                    },
-                    o: function(t, r, u) {
-                        var o = n && a[r],
-                            f, e, c;
-                        if (o || "undefined" == typeof i)
-                            if (o || "function" != typeof t.addEventListener)
-                                if ("undefined" != typeof t.attachEvent) f = function(n) {
-                                    u.call(t, n)
-                                }, e = "on" + r, t.attachEvent(e, f), s.a.C.ia(t, function() {
-                                    t.detachEvent(e, f)
-                                });
-                                else throw Error("Browser doesn't support addEventListener or attachEvent");
-                        else t.addEventListener(r, u, !1);
-                        else h(t, r) && (c = u, u = function(n, t) {
-                            var i = this.checked;
-                            t && (this.checked = !0 !== t.sb);
-                            c.call(this, n);
-                            this.checked = i
-                        }), i(t).bind(r, u)
-                    },
-                    Ga: function(n, t) {
-                        if (!n || !n.nodeType) throw Error("element must be a DOM node when calling triggerEvent");
-                        if ("undefined" != typeof i) {
-                            var f = [];
-                            h(n, t) && f.push({
-                                sb: n.checked
-                            });
-                            i(n).trigger(t, f)
-                        } else if ("function" == typeof r.createEvent)
-                            if ("function" == typeof n.dispatchEvent) f = r.createEvent(l[t] || "HTMLEvents"), f.initEvent(t, !0, !0, u, 0, 0, 0, 0, 0, !1, !1, !1, !1, 0, n), n.dispatchEvent(f);
-                            else throw Error("The supplied element doesn't support dispatchEvent");
-                        else if ("undefined" != typeof n.fireEvent) h(n, t) && (n.checked = !0 !== n.checked), n.fireEvent("on" + t);
-                        else throw Error("Browser doesn't support triggering events");
-                    },
-                    c: function(n) {
-                        return s.T(n) ? n() : n
-                    },
-                    ya: function(n) {
-                        return s.T(n) ? n.t() : n
-                    },
-                    ga: function(n, t, i) {
-                        if (t) {
-                            var r = /\S+/g,
-                                u = n.className.match(r) || [];
-                            s.a.p(t.match(r), function(n) {
-                                s.a.ja(u, n, i)
-                            });
-                            n.className = u.join(" ")
-                        }
-                    },
-                    ib: function(n, i) {
-                        var u = s.a.c(i),
-                            f;
-                        (null === u || u === t) && (u = "");
-                        f = s.e.firstChild(n);
-                        !f || 3 != f.nodeType || s.e.nextSibling(f) ? s.e.P(n, [r.createTextNode(u)]) : f.data = u;
-                        s.a.Bb(n)
-                    },
-                    gb: function(t, i) {
-                        if (t.name = i, 7 >= n) try {
-                            t.mergeAttributes(r.createElement("<input name='" + t.name + "'/>"), !1)
-                        } catch (u) {}
-                    },
-                    Bb: function(t) {
-                        9 <= n && (t = 1 == t.nodeType ? t : t.parentNode, t.style && (t.style.zoom = t.style.zoom))
-                    },
-                    zb: function(t) {
-                        if (n) {
-                            var i = t.style.width;
-                            t.style.width = 0;
-                            t.style.width = i
-                        }
-                    },
-                    Qb: function(n, t) {
-                        n = s.a.c(n);
-                        t = s.a.c(t);
-                        for (var r = [], i = n; i <= t; i++) r.push(i);
-                        return r
-                    },
-                    N: function(n) {
-                        for (var i = [], t = 0, r = n.length; t < r; t++) i.push(n[t]);
-                        return i
-                    },
-                    Ub: 6 === n,
-                    Vb: 7 === n,
-                    ca: n,
-                    Ua: function(n, t) {
-                        for (var r = s.a.N(n.getElementsByTagName("input")).concat(s.a.N(n.getElementsByTagName("textarea"))), f = "string" == typeof t ? function(n) {
-                                return n.name === t
-                            } : function(n) {
-                                return t.test(n.name)
-                            }, u = [], i = r.length - 1; 0 <= i; i--) f(r[i]) && u.push(r[i]);
-                        return u
-                    },
-                    Nb: function(n) {
-                        return "string" == typeof n && (n = s.a.F(n)) ? f && f.parse ? f.parse(n) : new Function("return " + n)() : null
-                    },
-                    Ca: function(n, t, i) {
-                        if (!f || !f.stringify) throw Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
-                        return f.stringify(s.a.c(n), t, i)
-                    },
-                    Ob: function(n, t, i) {
-                        var v, e, h, f, u, c;
-                        i = i || {};
-                        var l = i.params || {},
-                            a = i.includeFields || this.Ta,
-                            v = n;
-                        if ("object" == typeof n && "form" === s.a.u(n))
-                            for (v = n.action, e = a.length - 1; 0 <= e; e--)
-                                for (h = s.a.Ua(n, a[e]), f = h.length - 1; 0 <= f; f--) l[h[f].name] = h[f].value;
-                        t = s.a.c(t);
-                        u = r.createElement("form");
-                        u.style.display = "none";
-                        u.action = v;
-                        u.method = "post";
-                        for (c in t) n = r.createElement("input"), n.name = c, n.value = s.a.Ca(s.a.c(t[c])), u.appendChild(n);
-                        o(l, function(n, t) {
-                            var i = r.createElement("input");
-                            i.name = n;
-                            i.value = t;
-                            u.appendChild(i)
-                        });
-                        r.body.appendChild(u);
-                        i.submitter ? i.submitter(u) : u.submit();
-                        setTimeout(function() {
-                            u.parentNode.removeChild(u)
-                        }, 0)
-                    }
-                }
-            }();
-            s.b("utils", s.a);
-            s.b("utils.arrayForEach", s.a.p);
-            s.b("utils.arrayFirst", s.a.La);
-            s.b("utils.arrayFilter", s.a.Y);
-            s.b("utils.arrayGetDistinctValues", s.a.Ma);
-            s.b("utils.arrayIndexOf", s.a.k);
-            s.b("utils.arrayMap", s.a.Z);
-            s.b("utils.arrayPushAll", s.a.R);
-            s.b("utils.arrayRemoveItem", s.a.ka);
-            s.b("utils.extend", s.a.extend);
-            s.b("utils.fieldsIncludedWithJsonPost", s.a.Ta);
-            s.b("utils.getFormFields", s.a.Ua);
-            s.b("utils.peekObservable", s.a.ya);
-            s.b("utils.postJson", s.a.Ob);
-            s.b("utils.parseJson", s.a.Nb);
-            s.b("utils.registerEventHandler", s.a.o);
-            s.b("utils.stringifyJson", s.a.Ca);
-            s.b("utils.range", s.a.Qb);
-            s.b("utils.toggleDomNodeCssClass", s.a.ga);
-            s.b("utils.triggerEvent", s.a.Ga);
-            s.b("utils.unwrapObservable", s.a.c);
-            s.b("utils.objectForEach", s.a.w);
-            s.b("utils.addOrRemoveItem", s.a.ja);
-            s.b("unwrap", s.a.c);
-            Function.prototype.bind || (Function.prototype.bind = function(n) {
-                var i = this,
-                    t = Array.prototype.slice.call(arguments);
-                return n = t.shift(),
-                    function() {
-                        return i.apply(n, t.concat(Array.prototype.slice.call(arguments)))
-                    }
-            });
-            s.a.f = new function() {
-                var r = 0,
-                    n = "__ko__" + (new Date).getTime(),
-                    i = {};
-                return {
-                    get: function(n, i) {
-                        var r = s.a.f.pa(n, !1);
-                        return r === t ? t : r[i]
-                    },
-                    set: function(n, i, r) {
-                        (r !== t || s.a.f.pa(n, !1) !== t) && (s.a.f.pa(n, !0)[i] = r)
-                    },
-                    pa: function(u, f) {
-                        var e = u[n];
-                        if (!e || "null" === e || !i[e]) {
-                            if (!f) return t;
-                            e = u[n] = "ko" + r++;
-                            i[e] = {}
-                        }
-                        return i[e]
-                    },
-                    clear: function(t) {
-                        var r = t[n];
-                        return r ? (delete i[r], t[n] = null, !0) : !1
-                    }
-                }
-            };
-            s.b("utils.domData", s.a.f);
-            s.b("utils.domData.clear", s.a.f.clear);
-            s.a.C = new function() {
-                function n(n, i) {
-                    var r = s.a.f.get(n, u);
-                    return r === t && i && (r = [], s.a.f.set(n, u, r)), r
-                }
-
-                function r(t) {
-                    var u = n(t, !1),
-                        e;
-                    if (u)
-                        for (u = u.slice(0), e = 0; e < u.length; e++) u[e](t);
-                    if (s.a.f.clear(t), "function" == typeof i && "function" == typeof i.cleanData && i.cleanData([t]), f[t.nodeType])
-                        for (u = t.firstChild; t = u;) u = t.nextSibling, 8 === t.nodeType && r(t)
-                }
-                var u = "__ko_domNodeDisposal__" + (new Date).getTime(),
-                    e = {
-                        1: !0,
-                        8: !0,
-                        9: !0
-                    },
-                    f = {
-                        1: !0,
-                        9: !0
-                    };
-                return {
-                    ia: function(t, i) {
-                        if ("function" != typeof i) throw Error("Callback must be a function");
-                        n(t, !0).push(i)
-                    },
-                    cb: function(i, r) {
-                        var f = n(i, !1);
-                        f && (s.a.ka(f, r), 0 == f.length && s.a.f.set(i, u, t))
-                    },
-                    H: function(n) {
-                        var t, i, u;
-                        if (e[n.nodeType] && (r(n), f[n.nodeType]))
-                            for (t = [], s.a.R(t, n.getElementsByTagName("*")), i = 0, u = t.length; i < u; i++) r(t[i]);
-                        return n
-                    },
-                    removeNode: function(n) {
-                        s.H(n);
-                        n.parentNode && n.parentNode.removeChild(n)
-                    }
-                }
-            };
-            s.H = s.a.C.H;
-            s.removeNode = s.a.C.removeNode;
-            s.b("cleanNode", s.H);
-            s.b("removeNode", s.removeNode);
-            s.b("utils.domNodeDisposal", s.a.C);
-            s.b("utils.domNodeDisposal.addDisposeCallback", s.a.C.ia);
-            s.b("utils.domNodeDisposal.removeDisposeCallback", s.a.C.cb),
-                function() {
-                    s.a.xa = function(n) {
-                        var t, f;
-                        if ("undefined" != typeof i) {
-                            if (i.parseHTML) t = i.parseHTML(n) || [];
-                            else if ((t = i.clean([n])) && t[0]) {
-                                for (n = t[0]; n.parentNode && 11 !== n.parentNode.nodeType;) n = n.parentNode;
-                                n.parentNode && n.parentNode.removeChild(n)
-                            }
-                        } else {
-                            for (f = s.a.F(n).toLowerCase(), t = r.createElement("div"), f = f.match(/^<(thead|tbody|tfoot)/) && [1, "<table>", "<\/table>"] || !f.indexOf("<tr") && [2, "<table><tbody>", "<\/tbody><\/table>"] || (!f.indexOf("<td") || !f.indexOf("<th")) && [3, "<table><tbody><tr>", "<\/tr><\/tbody><\/table>"] || [0, "", ""], n = "ignored<div>" + f[1] + n + f[2] + "<\/div>", "function" == typeof u.innerShiv ? t.appendChild(u.innerShiv(n)) : t.innerHTML = n; f[0]--;) t = t.lastChild;
-                            t = s.a.N(t.lastChild.childNodes)
-                        }
-                        return t
-                    };
-                    s.a.fa = function(n, r) {
-                        if (s.a.oa(n), r = s.a.c(r), null !== r && r !== t)
-                            if ("string" != typeof r && (r = r.toString()), "undefined" != typeof i) i(n).html(r);
-                            else
-                                for (var f = s.a.xa(r), u = 0; u < f.length; u++) n.appendChild(f[u])
-                    }
-                }();
-            s.b("utils.parseHtmlFragment", s.a.xa);
-            s.b("utils.setHtml", s.a.fa);
-            s.s = function() {
-                function i(n, t) {
-                    var r;
-                    if (n)
-                        if (8 == n.nodeType) r = s.s.$a(n.nodeValue), null != r && t.push({
-                            xb: n,
-                            Kb: r
-                        });
-                        else if (1 == n.nodeType)
-                        for (var r = 0, u = n.childNodes, f = u.length; r < f; r++) i(u[r], t)
-                }
-                var n = {};
-                return {
-                    va: function(t) {
-                        if ("function" != typeof t) throw Error("You can only pass a function to ko.memoization.memoize()");
-                        var i = (4294967296 * (1 + Math.random()) | 0).toString(16).substring(1) + (4294967296 * (1 + Math.random()) | 0).toString(16).substring(1);
-                        return n[i] = t, "<!--[ko_memo:" + i + "]-->"
-                    },
-                    mb: function(i, r) {
-                        var u = n[i];
-                        if (u === t) throw Error("Couldn't find any memo with ID " + i + ". Perhaps it's already been unmemoized.");
-                        try {
-                            return u.apply(null, r || []), !0
-                        } finally {
-                            delete n[i]
-                        }
-                    },
-                    nb: function(n, t) {
-                        var f = [],
-                            u, o, r, e;
-                        for (i(n, f), u = 0, o = f.length; u < o; u++) r = f[u].xb, e = [r], t && s.a.R(e, t), s.s.mb(f[u].Kb, e), r.nodeValue = "", r.parentNode && r.parentNode.removeChild(r)
-                    },
-                    $a: function(n) {
-                        return (n = n.match(/^\[ko_memo\:(.*?)\]$/)) ? n[1] : null
-                    }
-                }
-            }();
-            s.b("memoization", s.s);
-            s.b("memoization.memoize", s.s.va);
-            s.b("memoization.unmemoize", s.s.mb);
-            s.b("memoization.parseMemoText", s.s.$a);
-            s.b("memoization.unmemoizeDomNodeAndDescendants", s.s.nb);
-            s.Sa = {
-                throttle: function(n, t) {
-                    n.throttleEvaluation = t;
-                    var i = null;
-                    return s.j({
-                        read: n,
-                        write: function(r) {
-                            clearTimeout(i);
-                            i = setTimeout(function() {
-                                n(r)
-                            }, t)
-                        }
-                    })
-                },
-                notify: function(t, i) {
-                    return t.equalityComparer = "always" == i ? n(!1) : s.m.fn.equalityComparer, t
-                }
-            };
-            s.b("extenders", s.Sa);
-            s.kb = function(n, t, i) {
-                this.target = n;
-                this.la = t;
-                this.wb = i;
-                s.r(this, "dispose", this.B)
-            };
-            s.kb.prototype.B = function() {
-                this.Hb = !0;
-                this.wb()
-            };
-            s.V = function() {
-                this.G = {};
-                s.a.extend(this, s.V.fn);
-                s.r(this, "subscribe", this.Da);
-                s.r(this, "extend", this.extend);
-                s.r(this, "getSubscriptionsCount", this.Db)
-            };
-            s.V.fn = {
-                Da: function(n, t, i) {
-                    i = i || "change";
-                    var r = new s.kb(this, t ? n.bind(t) : n, function() {
-                        s.a.ka(this.G[i], r)
-                    }.bind(this));
-                    return this.G[i] || (this.G[i] = []), this.G[i].push(r), r
-                },
-                notifySubscribers: function(n, t) {
-                    t = t || "change";
-                    this.G[t] && s.q.I(function() {
-                        s.a.p(this.G[t].slice(0), function(t) {
-                            t && !0 !== t.Hb && t.la(n)
-                        })
-                    }, this)
-                },
-                Db: function() {
-                    var n = 0;
-                    return s.a.w(this.G, function(t, i) {
-                        n += i.length
-                    }), n
-                },
-                extend: function(n) {
-                    var t = this;
-                    return n && s.a.w(n, function(n, i) {
-                        var r = s.Sa[n];
-                        "function" == typeof r && (t = r(t, i))
-                    }), t
-                }
-            };
-            s.Wa = function(n) {
-                return null != n && "function" == typeof n.Da && "function" == typeof n.notifySubscribers
-            };
-            s.b("subscribable", s.V);
-            s.b("isSubscribable", s.Wa);
-            s.q = function() {
-                var n = [];
-                return {
-                    rb: function(t) {
-                        n.push({
-                            la: t,
-                            Ra: []
-                        })
-                    },
-                    end: function() {
-                        n.pop()
-                    },
-                    bb: function(t) {
-                        if (!s.Wa(t)) throw Error("Only subscribable things can act as dependencies");
-                        if (0 < n.length) {
-                            var i = n[n.length - 1];
-                            !i || 0 <= s.a.k(i.Ra, t) || (i.Ra.push(t), i.la(t))
-                        }
-                    },
-                    I: function(t, i, r) {
-                        try {
-                            return n.push(null), t.apply(i, r || [])
-                        } finally {
-                            n.pop()
-                        }
-                    }
-                }
-            }();
-            y = {
-                undefined: !0,
-                boolean: !0,
-                number: !0,
-                string: !0
-            };
-            s.m = function(n) {
-                function t() {
-                    return 0 < arguments.length ? (t.equalityComparer && t.equalityComparer(i, arguments[0]) || (t.K(), i = arguments[0], t.J()), this) : (s.q.bb(t), i)
-                }
-                var i = n;
-                return s.V.call(t), t.t = function() {
-                    return i
-                }, t.J = function() {
-                    t.notifySubscribers(i)
-                }, t.K = function() {
-                    t.notifySubscribers(i, "beforeChange")
-                }, s.a.extend(t, s.m.fn), s.r(t, "peek", t.t), s.r(t, "valueHasMutated", t.J), s.r(t, "valueWillMutate", t.K), t
-            };
-            s.m.fn = {
-                equalityComparer: function(n, t) {
-                    return null === n || typeof n in y ? n === t : !1
-                }
-            };
-            h = s.m.Pb = "__ko_proto__";
-            s.m.fn[h] = s.m;
-            s.qa = function(n, i) {
-                return null === n || n === t || n[h] === t ? !1 : n[h] === i ? !0 : s.qa(n[h], i)
-            };
-            s.T = function(n) {
-                return s.qa(n, s.m)
-            };
-            s.Xa = function(n) {
-                return "function" == typeof n && n[h] === s.m || "function" == typeof n && n[h] === s.j && n.Eb ? !0 : !1
-            };
-            s.b("observable", s.m);
-            s.b("isObservable", s.T);
-            s.b("isWriteableObservable", s.Xa);
-            s.U = function(n) {
-                if (n = n || [], "object" != typeof n || !("length" in n)) throw Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
-                return n = s.m(n), s.a.extend(n, s.U.fn), n
-            };
-            s.U.fn = {
-                remove: function(n) {
-                    for (var u, r = this.t(), i = [], f = "function" == typeof n ? n : function(t) {
-                            return t === n
-                        }, t = 0; t < r.length; t++) u = r[t], f(u) && (0 === i.length && this.K(), i.push(u), r.splice(t, 1), t--);
-                    return i.length && this.J(), i
-                },
-                removeAll: function(n) {
-                    if (n === t) {
-                        var i = this.t(),
-                            r = i.slice(0);
-                        return this.K(), i.splice(0, i.length), this.J(), r
-                    }
-                    return n ? this.remove(function(t) {
-                        return 0 <= s.a.k(n, t)
-                    }) : []
-                },
-                destroy: function(n) {
-                    var i = this.t(),
-                        r = "function" == typeof n ? n : function(t) {
-                            return t === n
-                        },
-                        t;
-                    for (this.K(), t = i.length - 1; 0 <= t; t--) r(i[t]) && (i[t]._destroy = !0);
-                    this.J()
-                },
-                destroyAll: function(i) {
-                    return i === t ? this.destroy(n(!0)) : i ? this.destroy(function(n) {
-                        return 0 <= s.a.k(i, n)
-                    }) : []
-                },
-                indexOf: function(n) {
-                    var t = this();
-                    return s.a.k(t, n)
-                },
-                replace: function(n, t) {
-                    var i = this.indexOf(n);
-                    0 <= i && (this.K(), this.t()[i] = t, this.J())
-                }
-            };
-            s.a.p("pop push reverse shift sort splice unshift".split(" "), function(n) {
-                s.U.fn[n] = function() {
-                    var t = this.t();
-                    return this.K(), t = t[n].apply(t, arguments), this.J(), t
-                }
-            });
-            s.a.p(["slice"], function(n) {
-                s.U.fn[n] = function() {
-                    var t = this();
-                    return t[n].apply(t, arguments)
-                }
-            });
-            s.b("observableArray", s.U);
-            s.j = function(i, r, u) {
-                function w() {
-                    s.a.p(o, function(n) {
-                        n.B()
-                    });
-                    o = []
-                }
-
-                function nt() {
-                    var n = f.throttleEvaluation;
-                    n && 0 <= n ? (clearTimeout(d), d = setTimeout(c, n)) : c()
-                }
-
-                function c() {
-                    var n, u, i;
-                    if (!y)
-                        if (a && p()) h();
-                        else {
-                            y = !0;
-                            try {
-                                for (n = s.a.Z(o, function(n) {
-                                        return n.target
-                                    }), s.q.rb(function(i) {
-                                        var r;
-                                        0 <= (r = s.a.k(n, i)) ? n[r] = t : o.push(i.Da(nt))
-                                    }), u = e.call(r), i = n.length - 1; 0 <= i; i--) n[i] && o.splice(i, 1)[0].B();
-                                a = !0;
-                                f.notifySubscribers(l, "beforeChange");
-                                l = u;
-                                f.notifySubscribers(l)
-                            } finally {
-                                s.q.end();
-                                y = !1
-                            }
-                            o.length || h()
-                        }
-                }
-
-                function f() {
-                    if (0 < arguments.length) {
-                        if ("function" == typeof k) k.apply(r, arguments);
-                        else throw Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
-                        return this
-                    }
-                    return a || c(), s.q.bb(f), l
-                }
-
-                function b() {
-                    return !a || 0 < o.length
-                }
-                var l, a = !1,
-                    y = !1,
-                    e = i,
-                    g, p;
-                if (e && "object" == typeof e ? (u = e, e = u.read) : (u = u || {}, e || (e = u.read)), "function" != typeof e) throw Error("Pass a function that returns the value of the ko.computed");
-                var k = u.write,
-                    v = u.disposeWhenNodeIsRemoved || u.$ || null,
-                    p = u.disposeWhen || u.Qa || n(!1),
-                    h = w,
-                    o = [],
-                    d = null;
-                return r || (r = u.owner), f.t = function() {
-                    return a || c(), l
-                }, f.Cb = function() {
-                    return o.length
-                }, f.Eb = "function" == typeof u.write, f.B = function() {
-                    h()
-                }, f.ta = b, s.V.call(f), s.a.extend(f, s.j.fn), s.r(f, "peek", f.t), s.r(f, "dispose", f.B), s.r(f, "isActive", f.ta), s.r(f, "getDependenciesCount", f.Cb), !0 !== u.deferEvaluation && c(), v && b() && (h = function() {
-                    s.a.C.cb(v, h);
-                    w()
-                }, s.a.C.ia(v, h), g = p, p = function() {
-                    return !s.a.aa(v) || g()
-                }), f
-            };
-            s.Gb = function(n) {
-                return s.qa(n, s.j)
-            };
-            o = s.m.Pb;
-            s.j[o] = s.m;
-            s.j.fn = {};
-            s.j.fn[o] = s.j;
-            s.b("dependentObservable", s.j);
-            s.b("computed", s.j);
-            s.b("isComputed", s.Gb),
-                function() {
-                    function n(u, f, e) {
-                        if (e = e || new i, u = f(u), "object" != typeof u || null === u || u === t || u instanceof Date || u instanceof String || u instanceof Number || u instanceof Boolean) return u;
-                        var o = u instanceof Array ? [] : {};
-                        return e.save(u, o), r(u, function(i) {
-                            var r = f(u[i]),
-                                s;
-                            switch (typeof r) {
-                                case "boolean":
-                                case "number":
-                                case "string":
-                                case "function":
-                                    o[i] = r;
-                                    break;
-                                case "object":
-                                case "undefined":
-                                    s = e.get(r);
-                                    o[i] = s !== t ? s : n(r, f, e)
-                            }
-                        }), o
-                    }
-
-                    function r(n, t) {
-                        if (n instanceof Array) {
-                            for (var i = 0; i < n.length; i++) t(i);
-                            "function" == typeof n.toJSON && t("toJSON")
-                        } else
-                            for (i in n) t(i)
-                    }
-
-                    function i() {
-                        this.keys = [];
-                        this.Ha = []
-                    }
-                    s.lb = function(t) {
-                        if (0 == arguments.length) throw Error("When calling ko.toJS, pass the object you want to convert.");
-                        return n(t, function(n) {
-                            for (var t = 0; s.T(n) && 10 > t; t++) n = n();
-                            return n
-                        })
-                    };
-                    s.toJSON = function(n, t, i) {
-                        return n = s.lb(n), s.a.Ca(n, t, i)
-                    };
-                    i.prototype = {
-                        save: function(n, t) {
-                            var i = s.a.k(this.keys, n);
-                            0 <= i ? this.Ha[i] = t : (this.keys.push(n), this.Ha.push(t))
-                        },
-                        get: function(n) {
-                            return n = s.a.k(this.keys, n), 0 <= n ? this.Ha[n] : t
-                        }
-                    }
-                }();
-            s.b("toJS", s.lb);
-            s.b("toJSON", s.toJSON),
-                function() {
-                    s.h = {
-                        n: function(n) {
-                            switch (s.a.u(n)) {
-                                case "option":
-                                    return !0 === n.__ko__hasDomDataOptionValue__ ? s.a.f.get(n, s.d.options.wa) : 7 >= s.a.ca ? n.getAttributeNode("value") && n.getAttributeNode("value").specified ? n.value : n.text : n.value;
-                                case "select":
-                                    return 0 <= n.selectedIndex ? s.h.n(n.options[n.selectedIndex]) : t;
-                                default:
-                                    return n.value
-                            }
-                        },
-                        W: function(n, i) {
-                            switch (s.a.u(n)) {
-                                case "option":
-                                    switch (typeof i) {
-                                        case "string":
-                                            s.a.f.set(n, s.d.options.wa, t);
-                                            "__ko__hasDomDataOptionValue__" in n && delete n.__ko__hasDomDataOptionValue__;
-                                            n.value = i;
-                                            break;
-                                        default:
-                                            s.a.f.set(n, s.d.options.wa, i);
-                                            n.__ko__hasDomDataOptionValue__ = !0;
-                                            n.value = "number" == typeof i ? i : ""
-                                    }
-                                    break;
-                                case "select":
-                                    "" === i && (i = t);
-                                    (null === i || i === t) && (n.selectedIndex = -1);
-                                    for (var r = n.options.length - 1; 0 <= r; r--)
-                                        if (s.h.n(n.options[r]) == i) {
-                                            n.selectedIndex = r;
-                                            break
-                                        }
-                                    1 < n.size || -1 !== n.selectedIndex || (n.selectedIndex = 0);
-                                    break;
-                                default:
-                                    (null === i || i === t) && (i = "");
-                                    n.value = i
-                            }
-                        }
-                    }
-                }();
-            s.b("selectExtensions", s.h);
-            s.b("selectExtensions.readValue", s.h.n);
-            s.b("selectExtensions.writeValue", s.h.W);
-            s.g = function() {
-                function n(n, i) {
-                    for (var r = null; n != r;) r = n, n = n.replace(t, function(n, t) {
-                        return i[t]
-                    });
-                    return n
-                }
-                var t = /\@ko_token_(\d+)\@/g,
-                    i = ["true", "false", "null", "undefined"],
-                    r = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
-                return {
-                    S: [],
-                    da: function(t) {
-                        var i = s.a.F(t),
-                            f, e, r, u;
-                        if (3 > i.length) return [];
-                        for ("{" === i.charAt(0) && (i = i.substring(1, i.length - 1)), t = [], f = null, r = 0; r < i.length; r++)
-                            if (u = i.charAt(r), null === f) switch (u) {
-                                case '"':
-                                case "'":
-                                case "/":
-                                    f = r;
-                                    e = u
-                            } else if (u == e && "\\" !== i.charAt(r - 1)) {
-                                u = i.substring(f, r + 1);
-                                t.push(u);
-                                var c = "@ko_token_" + (t.length - 1) + "@",
-                                    i = i.substring(0, f) + c + i.substring(r + 1),
-                                    r = r - (u.length - c.length),
-                                    f = null
-                            }
-                        e = f = null;
-                        for (var o = 0, h = null, r = 0; r < i.length; r++) {
-                            if (u = i.charAt(r), null === f) switch (u) {
-                                case "{":
-                                    f = r;
-                                    h = u;
-                                    e = "}";
-                                    break;
-                                case "(":
-                                    f = r;
-                                    h = u;
-                                    e = ")";
-                                    break;
-                                case "[":
-                                    f = r;
-                                    h = u;
-                                    e = "]"
-                            }
-                            u === h ? o++ : u === e && (o--, 0 === o && (u = i.substring(f, r + 1), t.push(u), c = "@ko_token_" + (t.length - 1) + "@", i = i.substring(0, f) + c + i.substring(r + 1), r -= u.length - c.length, f = null))
-                        }
-                        for (e = [], i = i.split(","), f = 0, r = i.length; f < r; f++) o = i[f], h = o.indexOf(":"), 0 < h && h < o.length - 1 ? (u = o.substring(h + 1), e.push({
-                            key: n(o.substring(0, h), t),
-                            value: n(u, t)
-                        })) : e.push({
-                            unknown: n(o, t)
-                        });
-                        return e
-                    },
-                    ea: function(n) {
-                        var e = "string" == typeof n ? s.g.da(n) : n,
-                            f = [],
-                            t, h, o, u;
-                        for (n = [], h = 0; t = e[h]; h++)
-                            if (0 < f.length && f.push(","), t.key) {
-                                n: {
-                                    o = t.key;u = s.a.F(o);
-                                    switch (u.length && u.charAt(0)) {
-                                        case "'":
-                                        case '"':
-                                            break n;
-                                        default:
-                                            o = "'" + u + "'"
-                                    }
-                                }
-                                t = t.value;f.push(o);f.push(":");f.push(t);t = s.a.F(t);0 <= s.a.k(i, s.a.F(t).toLowerCase()) ? t = !1 : (u = t.match(r), t = null === u ? !1 : u[1] ? "Object(" + u[1] + ")" + u[2] : t);t && (0 < n.length && n.push(", "), n.push(o + " : function(__ko_value) { " + t + " = __ko_value; }"))
-                            }
-                        else t.unknown && f.push(t.unknown);
-                        return e = f.join(""), 0 < n.length && (e = e + ", '_ko_property_writers' : { " + n.join("") + " } "), e
-                    },
-                    Jb: function(n, t) {
-                        for (var i = 0; i < n.length; i++)
-                            if (s.a.F(n[i].key) == t) return !0;
-                        return !1
-                    },
-                    ha: function(n, t, i, r, u) {
-                        n && s.T(n) ? !s.Xa(n) || u && n.t() === r || n(r) : (n = t()._ko_property_writers) && n[i] && n[i](r)
-                    }
-                }
-            }();
-            s.b("expressionRewriting", s.g);
-            s.b("expressionRewriting.bindingRewriteValidators", s.g.S);
-            s.b("expressionRewriting.parseObjectLiteral", s.g.da);
-            s.b("expressionRewriting.preProcessBindings", s.g.ea);
-            s.b("jsonExpressionRewriting", s.g);
-            s.b("jsonExpressionRewriting.insertPropertyAccessorsIntoJson", s.g.ea),
-                function() {
-                    function n(n) {
-                        return 8 == n.nodeType && (i ? n.text : n.nodeValue).match(e)
-                    }
-
-                    function t(n) {
-                        return 8 == n.nodeType && (i ? n.text : n.nodeValue).match(o)
-                    }
-
-                    function u(i, r) {
-                        for (var u = i, f = 1, e = []; u = u.nextSibling;) {
-                            if (t(u) && (f--, 0 === f)) return e;
-                            e.push(u);
-                            n(u) && f++
-                        }
-                        if (!r) throw Error("Cannot find closing comment tag to match: " + i.nodeValue);
-                        return null
-                    }
-
-                    function f(n, t) {
-                        var i = u(n, t);
-                        return i ? 0 < i.length ? i[i.length - 1].nextSibling : n.nextSibling : null
-                    }
-                    var i = r && "<!--test-->" === r.createComment("test").text,
-                        e = i ? /^\x3c!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*--\x3e$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/,
-                        o = i ? /^\x3c!--\s*\/ko\s*--\x3e$/ : /^\s*\/ko\s*$/,
-                        h = {
-                            ul: !0,
-                            ol: !0
-                        };
-                    s.e = {
-                        L: {},
-                        childNodes: function(t) {
-                            return n(t) ? u(t) : t.childNodes
-                        },
-                        ba: function(t) {
-                            if (n(t)) {
-                                t = s.e.childNodes(t);
-                                for (var i = 0, r = t.length; i < r; i++) s.removeNode(t[i])
-                            } else s.a.oa(t)
-                        },
-                        P: function(t, i) {
-                            if (n(t)) {
-                                s.e.ba(t);
-                                for (var u = t.nextSibling, r = 0, f = i.length; r < f; r++) u.parentNode.insertBefore(i[r], u)
-                            } else s.a.P(t, i)
-                        },
-                        ab: function(t, i) {
-                            n(t) ? t.parentNode.insertBefore(i, t.nextSibling) : t.firstChild ? t.insertBefore(i, t.firstChild) : t.appendChild(i)
-                        },
-                        Va: function(t, i, r) {
-                            r ? n(t) ? t.parentNode.insertBefore(i, r.nextSibling) : r.nextSibling ? t.insertBefore(i, r.nextSibling) : t.appendChild(i) : s.e.ab(t, i)
-                        },
-                        firstChild: function(i) {
-                            return n(i) ? !i.nextSibling || t(i.nextSibling) ? null : i.nextSibling : i.firstChild
-                        },
-                        nextSibling: function(i) {
-                            return n(i) && (i = f(i)), i.nextSibling && t(i.nextSibling) ? null : i.nextSibling
-                        },
-                        ob: function(t) {
-                            return (t = n(t)) ? t[1] : null
-                        },
-                        Za: function(i) {
-                            var o, r, u, e;
-                            if (h[s.a.u(i)] && (o = i.firstChild, o))
-                                do
-                                    if (1 === o.nodeType) {
-                                        if (r = o.firstChild, u = null, r)
-                                            do u ? u.push(r) : n(r) ? (e = f(r, !0), e ? r = e : u = [r]) : t(r) && (u = [r]); while (r = r.nextSibling);
-                                        if (r = u)
-                                            for (u = o.nextSibling, e = 0; e < r.length; e++) u ? i.insertBefore(r[e], u) : i.appendChild(r[e])
-                                    }
-                            while (o = o.nextSibling)
-                        }
-                    }
-                }();
-            s.b("virtualElements", s.e);
-            s.b("virtualElements.allowedBindings", s.e.L);
-            s.b("virtualElements.emptyNode", s.e.ba);
-            s.b("virtualElements.insertAfter", s.e.Va);
-            s.b("virtualElements.prepend", s.e.ab);
-            s.b("virtualElements.setDomNodeChildren", s.e.P),
-                function() {
-                    s.M = function() {
-                        this.Na = {}
-                    };
-                    s.a.extend(s.M.prototype, {
-                        nodeHasBindings: function(n) {
-                            switch (n.nodeType) {
-                                case 1:
-                                    return null != n.getAttribute("data-bind");
-                                case 8:
-                                    return null != s.e.ob(n);
-                                default:
-                                    return !1
-                            }
-                        },
-                        getBindings: function(n, t) {
-                            var i = this.getBindingsString(n, t);
-                            return i ? this.parseBindingsString(i, t, n) : null
-                        },
-                        getBindingsString: function(n) {
-                            switch (n.nodeType) {
-                                case 1:
-                                    return n.getAttribute("data-bind");
-                                case 8:
-                                    return s.e.ob(n);
-                                default:
-                                    return null
-                            }
-                        },
-                        parseBindingsString: function(n, t, i) {
-                            var r, f, e, o;
-                            try {
-                                return (r = this.Na[n]) || (f = this.Na, o = "with($context){with($data||{}){return{" + s.g.ea(n) + "}}}", e = new Function("$context", "$element", o), r = f[n] = e), r(t, i)
-                            } catch (u) {
-                                throw u.message = "Unable to parse bindings.\nBindings value: " + n + "\nMessage: " + u.message, u;
-                            }
-                        }
-                    });
-                    s.M.instance = new s.M
-                }();
-            s.b("bindingProvider", s.M),
-                function() {
-                    function n(n, t, r) {
-                        for (var u = s.e.firstChild(t); t = u;) u = s.e.nextSibling(t), i(n, t, r)
-                    }
-
-                    function i(t, i, u) {
-                        var e = !0,
-                            f = 1 === i.nodeType;
-                        f && s.e.Za(i);
-                        (f && u || s.M.instance.nodeHasBindings(i)) && (e = r(i, null, t, u).Sb);
-                        e && n(t, i, !f)
-                    }
-
-                    function r(n, i, r, u) {
-                        function c(n) {
-                            return function() {
-                                return e[n]
-                            }
-                        }
-
-                        function l() {
-                            return e
-                        }
-                        var o = 0,
-                            e, h, a = s.a.f.get(n, f);
-                        if (!i) {
-                            if (a) throw Error("You cannot apply bindings multiple times to the same element.");
-                            s.a.f.set(n, f, !0)
-                        }
-                        return s.j(function() {
-                            var f = r && r instanceof s.A ? r : new s.A(s.a.c(r)),
-                                v = f.$data;
-                            !a && u && s.jb(n, f);
-                            (e = ("function" == typeof i ? i(f, n) : i) || s.M.instance.getBindings(n, f)) && (0 === o && (o = 1, s.a.w(e, function(i) {
-                                var r = s.d[i];
-                                if (r && 8 === n.nodeType && !s.e.L[i]) throw Error("The binding '" + i + "' cannot be used with virtual elements");
-                                if (r && "function" == typeof r.init && (r = r.init(n, c(i), l, v, f)) && r.controlsDescendantBindings) {
-                                    if (h !== t) throw Error("Multiple bindings (" + h + " and " + i + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
-                                    h = i
-                                }
-                            }), o = 2), 2 === o && s.a.w(e, function(t) {
-                                var i = s.d[t];
-                                i && "function" == typeof i.update && i.update(n, c(t), l, v, f)
-                            }))
-                        }, null, {
-                            $: n
-                        }), {
-                            Sb: h === t
-                        }
-                    }
-                    s.d = {};
-                    s.A = function(n, t, i) {
-                        t ? (s.a.extend(this, t), this.$parentContext = t, this.$parent = t.$data, this.$parents = (t.$parents || []).slice(0), this.$parents.unshift(this.$parent)) : (this.$parents = [], this.$root = n, this.ko = s);
-                        this.$data = n;
-                        i && (this[i] = n)
-                    };
-                    s.A.prototype.createChildContext = function(n, t) {
-                        return new s.A(n, this, t)
-                    };
-                    s.A.prototype.extend = function(n) {
-                        var t = s.a.extend(new s.A, this);
-                        return s.a.extend(t, n)
-                    };
-                    var f = "__ko_boundElement";
-                    s.jb = function(n, t) {
-                        if (2 == arguments.length) s.a.f.set(n, "__ko_bindingContext__", t);
-                        else return s.a.f.get(n, "__ko_bindingContext__")
-                    };
-                    s.Ka = function(n, t, i) {
-                        return 1 === n.nodeType && s.e.Za(n), r(n, t, i, !0)
-                    };
-                    s.Ja = function(t, i) {
-                        1 !== i.nodeType && 8 !== i.nodeType || n(t, i, !0)
-                    };
-                    s.Ia = function(n, t) {
-                        if (t && 1 !== t.nodeType && 8 !== t.nodeType) throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
-                        t = t || u.document.body;
-                        i(n, t, !0)
-                    };
-                    s.na = function(n) {
-                        switch (n.nodeType) {
-                            case 1:
-                            case 8:
-                                var i = s.jb(n);
-                                if (i) return i;
-                                if (n.parentNode) return s.na(n.parentNode)
-                        }
-                        return t
-                    };
-                    s.ub = function(n) {
-                        return (n = s.na(n)) ? n.$data : t
-                    };
-                    s.b("bindingHandlers", s.d);
-                    s.b("applyBindings", s.Ia);
-                    s.b("applyBindingsToDescendants", s.Ja);
-                    s.b("applyBindingsToNode", s.Ka);
-                    s.b("contextFor", s.na);
-                    s.b("dataFor", s.ub)
-                }();
-            l = {
-                "class": "className",
-                "for": "htmlFor"
-            };
-            s.d.attr = {
-                update: function(n, i) {
-                    var r = s.a.c(i()) || {};
-                    s.a.w(r, function(i, r) {
-                        r = s.a.c(r);
-                        var u = !1 === r || null === r || r === t;
-                        u && n.removeAttribute(i);
-                        8 >= s.a.ca && i in l ? (i = l[i], u ? n.removeAttribute(i) : n[i] = r) : u || n.setAttribute(i, r.toString());
-                        "name" === i && s.a.gb(n, u ? "" : r.toString())
-                    })
-                }
-            };
-            s.d.checked = {
-                init: function(t, i, r) {
-                    s.a.o(t, "click", function() {
-                        var u, n, f;
-                        if ("checkbox" == t.type) u = t.checked;
-                        else if ("radio" == t.type && t.checked) u = t.value;
-                        else return;
-                        n = i();
-                        f = s.a.c(n);
-                        "checkbox" == t.type && f instanceof Array ? s.a.ja(n, t.value, t.checked) : s.g.ha(n, r, "checked", u, !0)
-                    });
-                    "radio" != t.type || t.name || s.d.uniqueName.init(t, n(!0))
-                },
-                update: function(n, t) {
-                    var i = s.a.c(t());
-                    "checkbox" == n.type ? n.checked = i instanceof Array ? 0 <= s.a.k(i, n.value) : i : "radio" == n.type && (n.checked = n.value == i)
-                }
-            };
-            s.d.css = {
-                update: function(n, t) {
-                    var i = s.a.c(t());
-                    "object" == typeof i ? s.a.w(i, function(t, i) {
-                        i = s.a.c(i);
-                        s.a.ga(n, t, i)
-                    }) : (i = String(i || ""), s.a.ga(n, n.__ko__cssValue, !1), n.__ko__cssValue = i, s.a.ga(n, i, !0))
-                }
-            };
-            s.d.enable = {
-                update: function(n, t) {
-                    var i = s.a.c(t());
-                    i && n.disabled ? n.removeAttribute("disabled") : i || n.disabled || (n.disabled = !0)
-                }
-            };
-            s.d.disable = {
-                update: function(n, t) {
-                    s.d.enable.update(n, function() {
-                        return !s.a.c(t())
-                    })
-                }
-            };
-            s.d.event = {
-                init: function(n, t, i, r) {
-                    var u = t() || {};
-                    s.a.w(u, function(u) {
-                        "string" == typeof u && s.a.o(n, u, function(n) {
-                            var e, o = t()[u],
-                                h, f;
-                            if (o) {
-                                h = i();
-                                try {
-                                    f = s.a.N(arguments);
-                                    f.unshift(r);
-                                    e = o.apply(r, f)
-                                } finally {
-                                    !0 !== e && (n.preventDefault ? n.preventDefault() : n.returnValue = !1)
-                                }!1 === h[u + "Bubble"] && (n.cancelBubble = !0, n.stopPropagation && n.stopPropagation())
-                            }
-                        })
-                    })
-                }
-            };
-            s.d.foreach = {
-                Ya: function(n) {
-                    return function() {
-                        var i = n(),
-                            t = s.a.ya(i);
-                        return !t || "number" == typeof t.length ? {
-                            foreach: i,
-                            templateEngine: s.D.sa
-                        } : (s.a.c(i), {
-                            foreach: t.data,
-                            as: t.as,
-                            includeDestroyed: t.includeDestroyed,
-                            afterAdd: t.afterAdd,
-                            beforeRemove: t.beforeRemove,
-                            afterRender: t.afterRender,
-                            beforeMove: t.beforeMove,
-                            afterMove: t.afterMove,
-                            templateEngine: s.D.sa
-                        })
-                    }
-                },
-                init: function(n, t) {
-                    return s.d.template.init(n, s.d.foreach.Ya(t))
-                },
-                update: function(n, t, i, r, u) {
-                    return s.d.template.update(n, s.d.foreach.Ya(t), i, r, u)
-                }
-            };
-            s.g.S.foreach = !1;
-            s.e.L.foreach = !0;
-            s.d.hasfocus = {
-                init: function(n, t, i) {
-                    function r(r) {
-                        var u, f;
-                        if (n.__ko_hasfocusUpdating = !0, u = n.ownerDocument, "activeElement" in u) {
-                            try {
-                                f = u.activeElement
-                            } catch (e) {
-                                f = u.body
-                            }
-                            r = f === n
-                        }
-                        u = t();
-                        s.g.ha(u, i, "hasfocus", r, !0);
-                        n.__ko_hasfocusLastValue = r;
-                        n.__ko_hasfocusUpdating = !1
-                    }
-                    var u = r.bind(null, !0),
-                        f = r.bind(null, !1);
-                    s.a.o(n, "focus", u);
-                    s.a.o(n, "focusin", u);
-                    s.a.o(n, "blur", f);
-                    s.a.o(n, "focusout", f)
-                },
-                update: function(n, t) {
-                    var i = !!s.a.c(t());
-                    n.__ko_hasfocusUpdating || n.__ko_hasfocusLastValue === i || (i ? n.focus() : n.blur(), s.q.I(s.a.Ga, null, [n, i ? "focusin" : "focusout"]))
-                }
-            };
-            s.d.hasFocus = s.d.hasfocus;
-            s.d.html = {
-                init: function() {
-                    return {
-                        controlsDescendantBindings: !0
-                    }
-                },
-                update: function(n, t) {
-                    s.a.fa(n, t())
-                }
-            };
-            a = "__ko_withIfBindingData";
-            c("if");
-            c("ifnot", !1, !0);
-            c("with", !0, !1, function(n, t) {
-                return n.createChildContext(t)
-            });
-            s.d.options = {
-                init: function(n) {
-                    if ("select" !== s.a.u(n)) throw Error("options binding applies only to SELECT elements");
-                    for (; 0 < n.length;) n.remove(0);
-                    return {
-                        controlsDescendantBindings: !0
-                    }
-                },
-                update: function(n, i, u) {
-                    function a(n, t, i) {
-                        var r = typeof t;
-                        return "function" == r ? t(n) : "string" == r ? n[t] : i
-                    }
-
-                    function y(n, t) {
-                        if (e) {
-                            var i = 0 <= s.a.k(e, s.h.n(t[0]));
-                            s.a.hb(t[0], i)
-                        }
-                    }
-                    var p = 0 == n.length,
-                        h = !p && n.multiple ? n.scrollTop : null,
-                        l;
-                    i = s.a.c(i());
-                    var f = u(),
-                        w = f.optionsIncludeDestroyed,
-                        c = {},
-                        o, e;
-                    n.multiple ? e = s.a.Z(n.selectedOptions || s.a.Y(n.childNodes, function(n) {
-                        return n.tagName && "option" === s.a.u(n) && n.selected
-                    }), function(n) {
-                        return s.h.n(n)
-                    }) : 0 <= n.selectedIndex && (e = [s.h.n(n.options[n.selectedIndex])]);
-                    i ? ("undefined" == typeof i.length && (i = [i]), l = s.a.Y(i, function(n) {
-                        return w || n === t || null === n || !s.a.c(n._destroy)
-                    }), "optionsCaption" in f && (o = s.a.c(f.optionsCaption), null !== o && o !== t && l.unshift(c))) : i = [];
-                    u = y;
-                    f.optionsAfterRender && (u = function(n, i) {
-                        y(0, i);
-                        s.q.I(f.optionsAfterRender, null, [i[0], n !== c ? n : t])
-                    });
-                    s.a.Aa(n, l, function(n, i, u) {
-                        return u.length && (e = u[0].selected && [s.h.n(u[0])]), i = r.createElement("option"), n === c ? (s.a.fa(i, o), s.h.W(i, t)) : (u = a(n, f.optionsValue, n), s.h.W(i, s.a.c(u)), n = a(n, f.optionsText, u), s.a.ib(i, n)), [i]
-                    }, null, u);
-                    e = null;
-                    p && "value" in f && v(n, s.a.ya(f.value), !0);
-                    s.a.zb(n);
-                    h && 20 < Math.abs(h - n.scrollTop) && (n.scrollTop = h)
-                }
-            };
-            s.d.options.wa = "__ko.optionValueDomData__";
-            s.d.selectedOptions = {
-                init: function(n, t, i) {
-                    s.a.o(n, "change", function() {
-                        var u = t(),
-                            r = [];
-                        s.a.p(n.getElementsByTagName("option"), function(n) {
-                            n.selected && r.push(s.h.n(n))
-                        });
-                        s.g.ha(u, i, "selectedOptions", r)
-                    })
-                },
-                update: function(n, t) {
-                    if ("select" != s.a.u(n)) throw Error("values binding applies only to SELECT elements");
-                    var i = s.a.c(t());
-                    i && "number" == typeof i.length && s.a.p(n.getElementsByTagName("option"), function(n) {
-                        var t = 0 <= s.a.k(i, s.h.n(n));
-                        s.a.hb(n, t)
-                    })
-                }
-            };
-            s.d.style = {
-                update: function(n, t) {
-                    var i = s.a.c(t() || {});
-                    s.a.w(i, function(t, i) {
-                        i = s.a.c(i);
-                        n.style[t] = i || ""
-                    })
-                }
-            };
-            s.d.submit = {
-                init: function(n, t, i, r) {
-                    if ("function" != typeof t()) throw Error("The value for a submit binding must be a function");
-                    s.a.o(n, "submit", function(i) {
-                        var u, f = t();
-                        try {
-                            u = f.call(r, n)
-                        } finally {
-                            !0 !== u && (i.preventDefault ? i.preventDefault() : i.returnValue = !1)
-                        }
-                    })
-                }
-            };
-            s.d.text = {
-                update: function(n, t) {
-                    s.a.ib(n, t())
-                }
-            };
-            s.e.L.text = !0;
-            s.d.uniqueName = {
-                init: function(n, t) {
-                    if (t()) {
-                        var i = "ko_unique_" + ++s.d.uniqueName.tb;
-                        s.a.gb(n, i)
-                    }
-                }
-            };
-            s.d.uniqueName.tb = 0;
-            s.d.value = {
-                init: function(n, t, i) {
-                    function f() {
-                        e = !1;
-                        var r = t(),
-                            u = s.h.n(n);
-                        s.g.ha(r, i, "value", u)
-                    }
-                    var r = ["change"],
-                        u = i().valueUpdate,
-                        e = !1;
-                    u && ("string" == typeof u && (u = [u]), s.a.R(r, u), r = s.a.Ma(r));
-                    !s.a.ca || "input" != n.tagName.toLowerCase() || "text" != n.type || "off" == n.autocomplete || n.form && "off" == n.form.autocomplete || -1 != s.a.k(r, "propertychange") || (s.a.o(n, "propertychange", function() {
-                        e = !0
-                    }), s.a.o(n, "blur", function() {
-                        e && f()
-                    }));
-                    s.a.p(r, function(t) {
-                        var i = f;
-                        s.a.Tb(t, "after") && (i = function() {
-                            setTimeout(f, 0)
-                        }, t = t.substring(5));
-                        s.a.o(n, t, i)
-                    })
-                },
-                update: function(n, t) {
-                    var u = "select" === s.a.u(n),
-                        r = s.a.c(t()),
-                        i = s.h.n(n);
-                    r !== i && (i = function() {
-                        s.h.W(n, r)
-                    }, i(), u && setTimeout(i, 0));
-                    u && 0 < n.length && v(n, r, !1)
-                }
-            };
-            s.d.visible = {
-                    update: function(n, t) {
-                        var i = s.a.c(t()),
-                            r = "none" != n.style.display;
-                        i && !r ? n.style.display = "" : !i && r && (n.style.display = "none")
-                    }
-                },
-                function(n) {
-                    s.d[n] = {
-                        init: function(t, i, r, u) {
-                            return s.d.event.init.call(this, t, function() {
-                                var t = {};
-                                return t[n] = i(), t
-                            }, r, u)
-                        }
-                    }
-                }("click");
-            s.v = function() {};
-            s.v.prototype.renderTemplateSource = function() {
-                throw Error("Override renderTemplateSource");
-            };
-            s.v.prototype.createJavaScriptEvaluatorBlock = function() {
-                throw Error("Override createJavaScriptEvaluatorBlock");
-            };
-            s.v.prototype.makeTemplateSource = function(n, t) {
-                if ("string" == typeof n) {
-                    t = t || r;
-                    var i = t.getElementById(n);
-                    if (!i) throw Error("Cannot find template with ID " + n);
-                    return new s.l.i(i)
-                }
-                if (1 == n.nodeType || 8 == n.nodeType) return new s.l.Q(n);
-                throw Error("Unknown template type: " + n);
-            };
-            s.v.prototype.renderTemplate = function(n, t, i, r) {
-                return n = this.makeTemplateSource(n, r), this.renderTemplateSource(n, t, i)
-            };
-            s.v.prototype.isTemplateRewritten = function(n, t) {
-                return !1 === this.allowTemplateRewriting ? !0 : this.makeTemplateSource(n, t).data("isRewritten")
-            };
-            s.v.prototype.rewriteTemplate = function(n, t, i) {
-                n = this.makeTemplateSource(n, i);
-                t = t(n.text());
-                n.text(t);
-                n.data("isRewritten", !0)
-            };
-            s.b("templateEngine", s.v);
-            s.Ea = function() {
-                function n(n, t, i, r) {
-                    var o, f, u, e;
-                    for (n = s.g.da(n), o = s.g.S, f = 0; f < n.length; f++)
-                        if (u = n[f].key, o.hasOwnProperty(u))
-                            if (e = o[u], "function" == typeof e) {
-                                if (u = e(n[f].value)) throw Error(u);
-                            } else if (!e) throw Error("This template engine does not support the '" + u + "' binding within its templates");
-                    return i = "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + s.g.ea(n) + " } })()},'" + i.toLowerCase() + "')", r.createJavaScriptEvaluatorBlock(i) + t
-                }
-                var t = /(<([a-z]+\d*)(?:\s+(?!data-bind\s*=\s*)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind\s*=\s*(["'])([\s\S]*?)\3/gi,
-                    i = /\x3c!--\s*ko\b\s*([\s\S]*?)\s*--\x3e/g;
-                return {
-                    Ab: function(n, t, i) {
-                        t.isTemplateRewritten(n, i) || t.rewriteTemplate(n, function(n) {
-                            return s.Ea.Lb(n, t)
-                        }, i)
-                    },
-                    Lb: function(r, u) {
-                        return r.replace(t, function(t, i, r, f, e) {
-                            return n(e, i, r, u)
-                        }).replace(i, function(t, i) {
-                            return n(i, "<!-- ko -->", "#comment", u)
-                        })
-                    },
-                    qb: function(n, t) {
-                        return s.s.va(function(i, r) {
-                            var u = i.nextSibling;
-                            u && u.nodeName.toLowerCase() === t && s.Ka(u, n, r)
-                        })
-                    }
-                }
-            }();
-            s.b("__tr_ambtns", s.Ea.qb),
-                function() {
-                    s.l = {};
-                    s.l.i = function(n) {
-                        this.i = n
-                    };
-                    s.l.i.prototype.text = function() {
-                        var n = s.a.u(this.i),
-                            n = "script" === n ? "text" : "textarea" === n ? "value" : "innerHTML",
-                            t;
-                        if (0 == arguments.length) return this.i[n];
-                        t = arguments[0];
-                        "innerHTML" === n ? s.a.fa(this.i, t) : this.i[n] = t
-                    };
-                    s.l.i.prototype.data = function(n) {
-                        if (1 === arguments.length) return s.a.f.get(this.i, "templateSourceData_" + n);
-                        s.a.f.set(this.i, "templateSourceData_" + n, arguments[1])
-                    };
-                    s.l.Q = function(n) {
-                        this.i = n
-                    };
-                    s.l.Q.prototype = new s.l.i;
-                    s.l.Q.prototype.text = function() {
-                        if (0 == arguments.length) {
-                            var n = s.a.f.get(this.i, "__ko_anon_template__") || {};
-                            return n.Fa === t && n.ma && (n.Fa = n.ma.innerHTML), n.Fa
-                        }
-                        s.a.f.set(this.i, "__ko_anon_template__", {
-                            Fa: arguments[0]
-                        })
-                    };
-                    s.l.i.prototype.nodes = function() {
-                        if (0 == arguments.length) return (s.a.f.get(this.i, "__ko_anon_template__") || {}).ma;
-                        s.a.f.set(this.i, "__ko_anon_template__", {
-                            ma: arguments[0]
-                        })
-                    };
-                    s.b("templateSources", s.l);
-                    s.b("templateSources.domElement", s.l.i);
-                    s.b("templateSources.anonymousTemplate", s.l.Q)
-                }(),
-                function() {
-                    function r(n, t, i) {
-                        var r;
-                        for (t = s.e.nextSibling(t); n && (r = n) !== t;) n = s.e.nextSibling(r), 1 !== r.nodeType && 8 !== r.nodeType || i(r)
-                    }
-
-                    function u(n, t) {
-                        if (n.length) {
-                            var i = n[0],
-                                u = n[n.length - 1];
-                            r(i, u, function(n) {
-                                s.Ia(t, n)
-                            });
-                            r(i, u, function(n) {
-                                s.s.nb(n, [t])
-                            })
-                        }
-                    }
-
-                    function n(n) {
-                        return n.nodeType ? n : 0 < n.length ? n[0] : null
-                    }
-
-                    function f(t, r, f, e, o) {
-                        o = o || {};
-                        var h = t && n(t),
-                            h = h && h.ownerDocument,
-                            c = o.templateEngine || i;
-                        if (s.Ea.Ab(f, c, h), f = c.renderTemplate(f, e, o, h), "number" != typeof f.length || 0 < f.length && "number" != typeof f[0].nodeType) throw Error("Template engine must return an array of DOM nodes");
-                        h = !1;
-                        switch (r) {
-                            case "replaceChildren":
-                                s.e.P(t, f);
-                                h = !0;
-                                break;
-                            case "replaceNode":
-                                s.a.eb(t, f);
-                                h = !0;
-                                break;
-                            case "ignoreTargetNode":
-                                break;
-                            default:
-                                throw Error("Unknown renderMode: " + r);
-                        }
-                        return h && (u(f, e), o.afterRender && s.q.I(o.afterRender, null, [f, e.$data])), f
-                    }
-                    var i;
-                    s.Ba = function(n) {
-                        if (n != t && !(n instanceof s.v)) throw Error("templateEngine must inherit from ko.templateEngine");
-                        i = n
-                    };
-                    s.za = function(r, u, e, o, h) {
-                        if (e = e || {}, (e.templateEngine || i) == t) throw Error("Set a template engine before calling renderTemplate");
-                        if (h = h || "replaceChildren", o) {
-                            var c = n(o);
-                            return s.j(function() {
-                                var t = u && u instanceof s.A ? u : new s.A(s.a.c(u)),
-                                    i = "function" == typeof r ? r(t.$data, t) : r,
-                                    t = f(o, h, i, t, e);
-                                "replaceNode" == h && (o = t, c = n(o))
-                            }, null, {
-                                Qa: function() {
-                                    return !c || !s.a.aa(c)
-                                },
-                                $: c && "replaceNode" == h ? c.parentNode : c
-                            })
-                        }
-                        return s.s.va(function(n) {
-                            s.za(r, u, e, n, "replaceNode")
-                        })
-                    };
-                    s.Rb = function(n, i, r, e, o) {
-                        function c(n, t) {
-                            u(t, h);
-                            r.afterRender && r.afterRender(t, n)
-                        }
-
-                        function l(t, i) {
-                            h = o.createChildContext(s.a.c(t), r.as);
-                            h.$index = i;
-                            var u = "function" == typeof n ? n(t, h) : n;
-                            return f(null, "ignoreTargetNode", u, h, r)
-                        }
-                        var h;
-                        return s.j(function() {
-                            var n = s.a.c(i) || [];
-                            "undefined" == typeof n.length && (n = [n]);
-                            n = s.a.Y(n, function(n) {
-                                return r.includeDestroyed || n === t || null === n || !s.a.c(n._destroy)
-                            });
-                            s.q.I(s.a.Aa, null, [e, n, l, r, c])
-                        }, null, {
-                            $: e
-                        })
-                    };
-                    s.d.template = {
-                        init: function(n, t) {
-                            var i = s.a.c(t());
-                            return "string" == typeof i || i.name || 1 != n.nodeType && 8 != n.nodeType || (i = 1 == n.nodeType ? n.childNodes : s.e.childNodes(n), i = s.a.Mb(i), new s.l.Q(n).nodes(i)), {
-                                controlsDescendantBindings: !0
-                            }
-                        },
-                        update: function(n, i, r, u, f) {
-                            i = s.a.c(i());
-                            r = {};
-                            u = !0;
-                            var e, o = null;
-                            "string" != typeof i && (r = i, i = s.a.c(r.name), "if" in r && (u = s.a.c(r["if"])), u && "ifnot" in r && (u = !s.a.c(r.ifnot)), e = s.a.c(r.data));
-                            "foreach" in r ? o = s.Rb(i || n, u && r.foreach || [], r, n, f) : u ? (f = "data" in r ? f.createChildContext(e, r.as) : f, o = s.za(i || n, f, r, n)) : s.e.ba(n);
-                            f = o;
-                            (e = s.a.f.get(n, "__ko__templateComputedDomDataKey__")) && "function" == typeof e.B && e.B();
-                            s.a.f.set(n, "__ko__templateComputedDomDataKey__", f && f.ta() ? f : t)
-                        }
-                    };
-                    s.g.S.template = function(n) {
-                        return n = s.g.da(n), 1 == n.length && n[0].unknown || s.g.Jb(n, "name") ? null : "This template engine does not support anonymous templates nested within its templates"
-                    };
-                    s.e.L.template = !0
-                }();
-            s.b("setTemplateEngine", s.Ba);
-            s.b("renderTemplate", s.za);
-            s.a.Pa = function() {
-                function n(n, t, i, r, u) {
-                    for (var o = Math.min, l = Math.max, s = [], a = n.length, f, h = t.length, c = h - a || 1, w = a + h + 1, v, p, b, y, e = 0; e <= a; e++)
-                        for (p = v, s.push(v = []), b = o(h, e + c), f = l(0, e - 1); f <= b; f++) v[f] = f ? e ? n[e - 1] === t[f - 1] ? p[f - 1] : o(p[f] || w, v[f - 1] || w) + 1 : f + 1 : e + 1;
-                    for (o = [], l = [], c = [], e = a, f = h; e || f;) h = s[e][f] - 1, f && h === s[e][f - 1] ? l.push(o[o.length] = {
-                        status: i,
-                        value: t[--f],
-                        index: f
-                    }) : e && h === s[e - 1][f] ? c.push(o[o.length] = {
-                        status: r,
-                        value: n[--e],
-                        index: e
-                    }) : (o.push({
-                        status: "retained",
-                        value: t[--f]
-                    }), --e);
-                    if (l.length && c.length)
-                        for (n = 10 * a, t = i = 0;
-                            (u || t < n) && (y = l[i]); i++) {
-                            for (r = 0; s = c[r]; r++)
-                                if (y.value === s.value) {
-                                    y.moved = s.index;
-                                    s.moved = y.index;
-                                    c.splice(r, 1);
-                                    t = r = 0;
-                                    break
-                                }
-                            t += r
-                        }
-                    return o.reverse()
-                }
-                return function(t, i, r) {
-                    return t = t || [], i = i || [], t.length <= i.length ? n(t, i, "added", "deleted", r) : n(i, t, "deleted", "added", r)
-                }
-            }();
-            s.b("utils.compareArrays", s.a.Pa),
-                function() {
-                    function n(n) {
-                        for (; n.length && !s.a.aa(n[0]);) n.splice(0, 1);
-                        if (1 < n.length) {
-                            for (var t = n[0], r = n[n.length - 1], i = [t]; t !== r;) {
-                                if (t = t.nextSibling, !t) return;
-                                i.push(t)
-                            }
-                            Array.prototype.splice.apply(n, [0, n.length].concat(i))
-                        }
-                        return n
-                    }
-
-                    function i(i, r, u, f, e) {
-                        var o = [];
-                        return i = s.j(function() {
-                            var t = r(u, e, n(o)) || [];
-                            0 < o.length && (s.a.eb(o, t), f && s.q.I(f, null, [u, t, e]));
-                            o.splice(0, o.length);
-                            s.a.R(o, t)
-                        }, null, {
-                            $: i,
-                            Qa: function() {
-                                return !s.a.pb(o)
-                            }
-                        }), {
-                            O: o,
-                            j: i.ta() ? i : t
-                        }
-                    }
-                    s.a.Aa = function(r, u, f, e, o) {
-                        function rt(t, i) {
-                            h = k[i];
-                            nt !== i && (it[t] = h);
-                            h.ra(nt++);
-                            n(h.O);
-                            g.push(h);
-                            p.push(h)
-                        }
-
-                        function v(n, t) {
-                            if (n)
-                                for (var i = 0, r = t.length; i < r; i++) t[i] && s.a.p(t[i].O, function(r) {
-                                    n(r, i, t[i].X)
-                                })
-                        }
-                        var c, y, ut;
-                        u = u || [];
-                        e = e || {};
-                        var y = s.a.f.get(r, "setDomNodeChildrenFromArrayMapping_lastMappingResult") === t,
-                            k = s.a.f.get(r, "setDomNodeChildrenFromArrayMapping_lastMappingResult") || [],
-                            d = s.a.Z(k, function(n) {
-                                return n.X
-                            }),
-                            l = s.a.Pa(d, u, e.dontLimitMoves),
-                            g = [],
-                            a = 0,
-                            nt = 0,
-                            tt = [],
-                            p = [];
-                        u = [];
-                        for (var it = [], d = [], h, c = 0, w, b; w = l[c]; c++) switch (b = w.moved, w.status) {
-                            case "deleted":
-                                b === t && (h = k[a], h.j && h.j.B(), tt.push.apply(tt, n(h.O)), e.beforeRemove && (u[c] = h, p.push(h)));
-                                a++;
-                                break;
-                            case "retained":
-                                rt(c, a++);
-                                break;
-                            case "added":
-                                b !== t ? rt(c, b) : (h = {
-                                    X: w.value,
-                                    ra: s.m(nt++)
-                                }, g.push(h), p.push(h), y || (d[c] = h))
-                        }
-                        for (v(e.beforeMove, it), s.a.p(tt, e.beforeRemove ? s.H : s.removeNode), c = 0, y = s.e.firstChild(r); h = p[c]; c++) {
-                            for (h.O || s.a.extend(h, i(r, f, h.X, o, h.ra)), a = 0; l = h.O[a]; y = l.nextSibling, ut = l, a++) l !== y && s.e.Va(r, l, ut);
-                            !h.Fb && o && (o(h.X, h.O, h.ra), h.Fb = !0)
-                        }
-                        v(e.beforeRemove, u);
-                        v(e.afterMove, it);
-                        v(e.afterAdd, d);
-                        s.a.f.set(r, "setDomNodeChildrenFromArrayMapping_lastMappingResult", g)
-                    }
-                }();
-            s.b("utils.setDomNodeChildrenFromArrayMapping", s.a.Aa);
-            s.D = function() {
-                this.allowTemplateRewriting = !1
-            };
-            s.D.prototype = new s.v;
-            s.D.prototype.renderTemplateSource = function(n) {
-                var t = (9 > s.a.ca ? 0 : n.nodes) ? n.nodes() : null;
-                return t ? s.a.N(t.cloneNode(!0).childNodes) : (n = n.text(), s.a.xa(n))
-            };
-            s.D.sa = new s.D;
-            s.Ba(s.D.sa);
-            s.b("nativeTemplateEngine", s.D),
-                function() {
-                    s.ua = function() {
-                        var n = this.Ib = function() {
-                            if ("undefined" == typeof i || !i.tmpl) return 0;
-                            try {
-                                if (0 <= i.tmpl.tag.tmpl.open.toString().indexOf("__")) return 2
-                            } catch (n) {}
-                            return 1
-                        }();
-                        this.renderTemplateSource = function(t, u, f) {
-                            if (f = f || {}, 2 > n) throw Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
-                            var e = t.data("precompiled");
-                            return e || (e = t.text() || "", e = i.template(null, "{{ko_with $item.koBindingContext}}" + e + "{{/ko_with}}"), t.data("precompiled", e)), t = [u.$data], u = i.extend({
-                                koBindingContext: u
-                            }, f.templateOptions), u = i.tmpl(e, t, u), u.appendTo(r.createElement("div")), i.fragments = {}, u
-                        };
-                        this.createJavaScriptEvaluatorBlock = function(n) {
-                            return "{{ko_code ((function() { return " + n + " })()) }}"
-                        };
-                        this.addTemplate = function(n, t) {
-                            r.write("<script type='text/html' id='" + n + "'>" + t + "<\/script>")
-                        };
-                        0 < n && (i.tmpl.tag.ko_code = {
-                            open: "__.push($1 || '');"
-                        }, i.tmpl.tag.ko_with = {
-                            open: "with($1) {",
-                            close: "} "
-                        })
-                    };
-                    s.ua.prototype = new s.v;
-                    var n = new s.ua;
-                    0 < n.Ib && s.Ba(n);
-                    s.b("jqueryTmplTemplateEngine", s.ua)
-                }()
-        })
-    })()
-}();
-! function(n) {
-    "function" == typeof require && "object" == typeof exports && "object" == typeof module ? n(require("knockout"), require("jquery"), require("kendo")) : "function" == typeof define && define.amd ? define(["knockout", "jquery", "kendo"], n) : n(window.ko, window.jQuery, window.kendo)
-}(function(n, t, i, r) {
-    var y;
-    i = i || window.kendo;
-    n.kendo = n.kendo || {};
-    n.kendo.BindingFactory = function() {
-        var u = this,
-            f;
-        this.createBinding = function(i) {
-            if (t()[i.parent || i.name]) {
-                var r = {};
-                r.init = function(n, t, f, e, o) {
-                    var s = u.buildOptions(i, t);
-                    return s.async === !0 || i.async === !0 && s.async !== !1 ? (setTimeout(function() {
-                        r.setup(n, s, o)
-                    }, 0), void 0) : (r.setup(n, s, o), s && s.useKOTemplates ? {
-                        controlsDescendantBindings: !0
-                    } : void 0)
-                };
-                r.setup = function(r, f, e) {
-                    var o, s = t(r);
-                    u.setupTemplates(i.templates, f, r, e);
-                    o = u.getWidget(i, f, s);
-                    u.handleEvents(f, i, r, o, e);
-                    u.watchValues(o, f, i, r);
-                    o.destroy && n.utils.domNodeDisposal.addDisposeCallback(r, function() {
-                        o.destroy()
-                    })
-                };
-                r.options = {};
-                r.widgetConfig = i;
-                n.bindingHandlers[i.bindingName || i.name] = r
-            }
-        };
-        this.buildOptions = function(t, r) {
-            var f = t.defaultOption,
-                e = n.utils.extend({}, n.bindingHandlers[t.name].options),
-                u = n.utils.unwrapObservable(r());
-            return u instanceof i.data.DataSource || "object" != typeof u || null === u || f && !(f in u) ? e[f] = r() : n.utils.extend(e, u), e
-        };
-        f = function(t, i) {
-            return function(r) {
-                return n.renderTemplate(t, i.createChildContext(r._raw && r._raw() || r))
-            }
-        };
-        this.setupTemplates = function(t, i, r, u) {
-            var e, h, o, s;
-            if (t && i && i.useKOTemplates) {
-                for (e = 0, h = t.length; h > e; e++) o = t[e], i[o] && (i[o] = f(i[o], u));
-                s = i.dataBound;
-                i.dataBound = function() {
-                    n.memoization.unmemoizeDomNodeAndDescendants(r);
-                    s && s.apply(this, arguments)
-                }
-            }
-        };
-        this.unwrapOneLevel = function(t) {
-            var r, u = {};
-            if (t)
-                if (t instanceof i.data.DataSource) u = t;
-                else if ("object" == typeof t)
-                for (r in t) u[r] = n.utils.unwrapObservable(t[r]);
-            return u
-        };
-        this.getWidget = function(t, i, r) {
-            var u, f;
-            return t.parent ? (f = r.closest("[data-bind*='" + t.parent + ":']"), u = f.length ? f.data(t.parent) : null) : u = r[t.name](this.unwrapOneLevel(i)).data(t.name), n.isObservable(i.widget) && i.widget(u), u
-        };
-        this.watchValues = function(n, t, i, r) {
-            var f, e = i.watch;
-            if (e)
-                for (f in e) e.hasOwnProperty(f) && u.watchOneValue(f, n, t, i, r)
-        };
-        this.watchOneValue = function(i, u, f, e, o) {
-            var s = n.computed({
-                read: function() {
-                    var a, l, s = e.watch[i],
-                        h = n.utils.unwrapObservable(f[i]),
-                        c = e.parent ? [o] : [];
-                    t.isArray(s) ? s = u[h ? s[0] : s[1]] : "string" == typeof s ? s = u[s] : l = !0;
-                    s && f[i] !== r && (l ? c.push(h, f) : (a = s.apply(u, c), c.push(h)), (l || a !== h) && s.apply(u, c))
-                },
-                disposeWhenNodeIsRemoved: o
-            }).extend({
-                throttle: f.throttle || 0 === f.throttle ? f.throttle : 1
-            });
-            n.isObservable(f[i]) || s.dispose()
-        };
-        this.handleEvents = function(n, t, i, r, f) {
-            var o, e, s = t.events;
-            if (s)
-                for (o in s) s.hasOwnProperty(o) && (e = s[o], "string" == typeof e && (e = {
-                    value: e,
-                    writeTo: e
-                }), u.handleOneEvent(o, e, n, i, r, t.childProp, f))
-        };
-        this.handleOneEvent = function(t, i, r, u, f, e, o) {
-            var s = "function" == typeof i ? i : r[i.call];
-            "function" == typeof i ? s = s.bind(o.$data, r) : i.call && "function" == typeof r[i.call] ? s = r[i.call].bind(o.$data, o.$data) : i.writeTo && n.isWriteableObservable(r[i.writeTo]) && (s = function(n) {
-                var t, f;
-                e && n[e] && n[e] !== u || (t = i.value, f = "string" == typeof t && this[t] ? this[t](e && u) : t, r[i.writeTo](f))
-            });
-            s && f.bind(t, s)
-        }
-    };
-    n.kendo.bindingFactory = new n.kendo.BindingFactory;
-    n.kendo.setDataSource = function(t, r, u) {
-            var f, e;
-            return r instanceof i.data.DataSource ? (t.setDataSource(r), void 0) : (u && u.useKOTemplates || (f = n.mapping && r && r.__ko_mapping__, e = r && f ? n.mapping.toJS(r) : n.toJS(r)), t.dataSource.data(e || r), void 0)
-        },
-        function() {
-            var n = i.data.ObservableArray.fn.wrap;
-            i.data.ObservableArray.fn.wrap = function(t) {
-                var i = n.apply(this, arguments);
-                return i._raw = function() {
-                    return t
-                }, i
-            }
-        }();
-    var c = function(t) {
-            return function(i) {
-                i && (n.utils.extend(this.options[t], i), this.redraw(), this.value(.001 + this.value()))
-            }
-        },
-        f = n.kendo.bindingFactory.createBinding.bind(n.kendo.bindingFactory),
-        d = "clicked",
-        s = "close",
-        p = "collapse",
-        g = "content",
-        w = "data",
-        e = "enable",
-        b = "expand",
-        l = "expanded",
-        rt = "error",
-        ut = "info",
-        o = "isOpen",
-        a = "max",
-        v = "min",
-        h = "open",
-        nt = "search",
-        tt = "selected",
-        ft = "success",
-        it = "size",
-        u = "value",
-        k = "values",
-        et = "warning";
-    f({
-        name: "kendoAutoComplete",
-        events: {
-            change: u,
-            open: {
-                writeTo: o,
-                value: !0
-            },
-            close: {
-                writeTo: o,
-                value: !1
-            }
-        },
-        watch: {
-            enabled: e,
-            search: [nt, s],
-            data: function(t) {
-                n.kendo.setDataSource(this, t)
-            },
-            value: u
-        }
-    });
-    f({
-        name: "kendoButton",
-        defaultOption: d,
-        events: {
-            click: {
-                call: d
-            }
-        },
-        watch: {
-            enabled: e
-        }
-    });
-    f({
-        name: "kendoCalendar",
-        defaultOption: u,
-        events: {
-            change: u
-        },
-        watch: {
-            max: a,
-            min: v,
-            value: u
-        }
-    });
-    f({
-        name: "kendoColorPicker",
-        events: {
-            change: u,
-            open: {
-                writeTo: o,
-                value: !0
-            },
-            close: {
-                writeTo: o,
-                value: !1
-            }
-        },
-        watch: {
-            enabled: e,
-            value: u,
-            color: u,
-            palette: "palette"
-        }
-    });
-    f({
-        name: "kendoComboBox",
-        events: {
-            change: u,
-            open: {
-                writeTo: o,
-                value: !0
-            },
-            close: {
-                writeTo: o,
-                value: !1
-            }
-        },
-        watch: {
-            enabled: e,
-            isOpen: [h, s],
-            data: function(t) {
-                n.kendo.setDataSource(this, t)
-            },
-            value: u
-        }
-    });
-    f({
-        name: "kendoDatePicker",
-        defaultOption: u,
-        events: {
-            change: u,
-            open: {
-                writeTo: o,
-                value: !0
-            },
-            close: {
-                writeTo: o,
-                value: !1
-            }
-        },
-        watch: {
-            enabled: e,
-            max: a,
-            min: v,
-            value: u,
-            isOpen: [h, s]
-        }
-    });
-    f({
-        name: "kendoDateTimePicker",
-        defaultOption: u,
-        events: {
-            change: u,
-            open: {
-                writeTo: o,
-                value: !0
-            },
-            close: {
-                writeTo: o,
-                value: !1
-            }
-        },
-        watch: {
-            enabled: e,
-            max: a,
-            min: v,
-            value: u,
-            isOpen: [h, s]
-        }
-    });
-    f({
-        name: "kendoDropDownList",
-        events: {
-            change: u,
-            open: {
-                writeTo: o,
-                value: !0
-            },
-            close: {
-                writeTo: o,
-                value: !1
-            }
-        },
-        watch: {
-            enabled: e,
-            isOpen: [h, s],
-            data: function(t) {
-                n.kendo.setDataSource(this, t);
-                t.length && this.options.optionLabel && this.select() < 0 && this.select(0)
-            },
-            value: u
-        }
-    });
-    f({
-        name: "kendoEditor",
-        defaultOption: u,
-        events: {
-            change: u
-        },
-        watch: {
-            enabled: e,
-            value: u
-        }
-    });
-    f({
-        name: "kendoGrid",
-        defaultOption: w,
-        watch: {
-            data: function(t, i) {
-                n.kendo.setDataSource(this, t, i)
-            }
-        },
-        templates: ["rowTemplate", "altRowTemplate"]
-    });
-    f({
-        name: "kendoListView",
-        defaultOption: w,
-        watch: {
-            data: function(t, i) {
-                n.kendo.setDataSource(this, t, i)
-            }
-        },
-        templates: ["template"]
-    });
-    f({
-        name: "kendoMaskedTextBox",
-        defaultOption: u,
-        events: {
-            change: u
-        },
-        watch: {
-            enabled: e,
-            isReadOnly: "readonly",
-            value: u
-        }
-    });
-    f({
-        name: "kendoMenu",
-        async: !0
-    });
-    f({
-        name: "kendoMenuItem",
-        parent: "kendoMenu",
-        watch: {
-            enabled: e,
-            isOpen: [h, s]
-        },
-        async: !0
-    });
-    f({
-        name: "kendoMultiSelect",
-        events: {
-            change: u,
-            open: {
-                writeTo: o,
-                value: !0
-            },
-            close: {
-                writeTo: o,
-                value: !1
-            }
-        },
-        watch: {
-            enabled: e,
-            search: [nt, s],
-            data: function(t) {
-                n.kendo.setDataSource(this, t)
-            },
-            value: u
-        }
-    });
-    y = function(n, t) {
-        t || 0 === t ? this.show(t, n) : this.hide()
-    };
-    f({
-        name: "kendoNotification",
-        watch: {
-            error: function(n) {
-                y.call(this, rt, n)
-            },
-            info: function(n) {
-                y.call(this, ut, n)
-            },
-            success: function(n) {
-                y.call(this, ft, n)
-            },
-            warning: function(n) {
-                y.call(this, et, n)
-            }
-        }
-    });
-    f({
-        name: "kendoNumericTextBox",
-        defaultOption: u,
-        events: {
-            change: u
-        },
-        watch: {
-            enabled: e,
-            value: u,
-            max: function(n) {
-                this.options.max = n;
-                var t = this.value();
-                (t || 0 === t) && t > n && this.value(n)
-            },
-            min: function(n) {
-                this.options.min = n;
-                var t = this.value();
-                (t || 0 === t) && n > t && this.value(n)
-            }
-        }
-    });
-    f({
-        name: "kendoPanelBar",
-        async: !0
-    });
-    f({
-        name: "kendoPanelItem",
-        parent: "kendoPanelBar",
-        watch: {
-            enabled: e,
-            expanded: [b, p],
-            selected: ["select"]
-        },
-        childProp: "item",
-        events: {
-            expand: {
-                writeTo: l,
-                value: !0
-            },
-            collapse: {
-                writeTo: l,
-                value: !1
-            },
-            select: {
-                writeTo: tt,
-                value: u
-            }
-        },
-        async: !0
-    });
-    f({
-        name: "kendoProgressBar",
-        defaultOption: u,
-        events: {
-            change: u
-        },
-        watch: {
-            enabled: e,
-            value: u
-        }
-    });
-    f({
-        name: "kendoRangeSlider",
-        defaultOption: k,
-        events: {
-            change: k
-        },
-        watch: {
-            values: k,
-            enabled: e
-        }
-    });
-    f({
-        async: !0,
-        name: "kendoScheduler",
-        watch: {
-            data: function(t, i) {
-                n.kendo.setDataSource(this, t, i)
-            }
-        }
-    });
-    f({
-        name: "kendoSlider",
-        defaultOption: u,
-        events: {
-            change: u
-        },
-        watch: {
-            value: u,
-            enabled: e
-        }
-    });
-    f({
-        name: "kendoSortable",
-        defaultOption: w,
-        events: {
-            end: function(i, r) {
-                var u = "__ko_kendo_sortable_data__",
-                    f = "receive" !== r.action ? n.dataFor(r.item[0]) : r.draggableEvent[u],
-                    o = i.data,
-                    e = i.data;
-                ("sort" === r.action || "remove" === r.action) && (e.splice(r.oldIndex, 1), "remove" === r.action && (r.draggableEvent[u] = f));
-                ("sort" === r.action || "receive" === r.action) && (e.splice(r.newIndex, 0, f), delete r.draggableEvent[u], t(r.draggableEvent.target).hide(), r.preventDefault());
-                o.valueHasMutated()
-            }
-        }
-    });
-    f({
-        name: "kendoSplitter",
-        async: !0
-    });
-    f({
-        name: "kendoSplitterPane",
-        parent: "kendoSplitter",
-        watch: {
-            max: a,
-            min: v,
-            size: it,
-            expanded: [b, p]
-        },
-        childProp: "pane",
-        events: {
-            collapse: {
-                writeTo: l,
-                value: !1
-            },
-            expand: {
-                writeTo: l,
-                value: !0
-            },
-            resize: it
-        },
-        async: !0
-    });
-    f({
-        name: "kendoTabStrip",
-        async: !0
-    });
-    f({
-        name: "kendoTab",
-        parent: "kendoTabStrip",
-        watch: {
-            enabled: e
-        },
-        childProp: "item",
-        async: !0
-    });
-    f({
-        name: "kendoTooltip",
-        events: {},
-        watch: {
-            content: g,
-            filter: "filter"
-        }
-    });
-    f({
-        name: "kendoTimePicker",
-        defaultOption: u,
-        events: {
-            change: u
-        },
-        watch: {
-            max: a,
-            min: v,
-            value: u,
-            enabled: e,
-            isOpen: [h, s]
-        }
-    });
-    f({
-        name: "kendoTreeView",
-        async: !0
-    });
-    f({
-        name: "kendoTreeItem",
-        parent: "kendoTreeView",
-        watch: {
-            enabled: e,
-            expanded: [b, p],
-            selected: function(n, t) {
-                t ? this.select(n) : this.select()[0] == n && this.select(null)
-            }
-        },
-        childProp: "node",
-        events: {
-            collapse: {
-                writeTo: l,
-                value: !1
-            },
-            expand: {
-                writeTo: l,
-                value: !0
-            },
-            select: {
-                writeTo: tt,
-                value: !0
-            }
-        },
-        async: !0
-    });
-    f({
-        name: "kendoUpload",
-        watch: {
-            enabled: e
-        }
-    });
-    f({
-        async: !0,
-        name: "kendoWindow",
-        events: {
-            open: {
-                writeTo: o,
-                value: !0
-            },
-            close: {
-                writeTo: o,
-                value: !1
-            }
-        },
-        watch: {
-            content: g,
-            title: "title",
-            isOpen: [h, s]
-        }
-    });
-    f({
-        name: "kendoChart",
-        watch: {
-            data: function(t) {
-                n.kendo.setDataSource(this, t)
-            }
-        }
-    });
-    f({
-        name: "kendoLinearGauge",
-        defaultOption: u,
-        watch: {
-            value: u,
-            gaugeArea: c("gaugeArea"),
-            pointer: c("pointer"),
-            scale: c("scale")
-        }
-    });
-    f({
-        name: "kendoRadialGauge",
-        defaultOption: u,
-        watch: {
-            value: u,
-            gaugeArea: c("gaugeArea"),
-            pointer: c("pointer"),
-            scale: c("scale")
-        }
-    })
-});
-Raphael = function() {
-    function n() {
-        var r;
-        if (n.is(arguments[0], et)) {
-            for (var i = arguments[0], f = rr[b](n, i.splice(0, 3 + n.is(i[0], nt))), e = f.set(), u = 0, o = i[t]; u < o; u++) r = i[u] || {}, ku.test(r.type) && e[a](f[r.type]().attr(r));
-            return e
-        }
-        return rr[b](n, arguments)
-    }
-
-    function y() {}
-
-    function si(t) {
-        var u, i;
-        return n.vml ? (u = /^\s+|\s+$/g, si = ut(function(n) {
-            var f, t, i;
-            n = (n + r)[w](u, r);
-            try {
-                t = new st.ActiveXObject("htmlfile");
-                t.write("<body>");
-                t.close();
-                f = t.body
-            } catch (e) {
-                f = st.createPopup().document.body
-            }
-            t = f.createTextRange();
-            try {
-                return f.style.color = n, i = t.queryCommandValue("ForeColor"), i = (i & 255) << 16 | i & 65280 | (i & 16711680) >>> 16, "#" + ("000000" + i[d](16)).slice(-6)
-            } catch (o) {
-                return "none"
-            }
-        })) : (i = c.createElement("i"), i.title = "Raphaël Colour Picker", i.style.display = "none", c.body[o](i), si = ut(function(n) {
-            return i.style.color = n, c.defaultView.getComputedStyle(i, r).getPropertyValue("color")
-        })), si(t)
-    }
-
-    function nf() {
-        return "hsb(" + [this.h, this.s, this.b] + ")"
-    }
-
-    function tf() {
-        return this.hex
-    }
-
-    function ut(n, r, u) {
-        function f() {
-            var c = Array[i].slice.call(arguments, 0),
-                e = c[tt]("►"),
-                o = f.cache = f.cache || {},
-                h = f.count = f.count || [];
-            return o[s](e) ? u ? u(o[e]) : o[e] : (h[t] >= 1e3 && delete o[h.shift()], h[a](e), o[e] = n[b](r, c), u ? u(o[e]) : o[e])
-        }
-        return f
-    }
-
-    function ci(i) {
-        var f = [],
-            r, e, u, o;
-        for (n.is(i, et) && n.is(i && i[0], et) || (i = n.parsePathString(i)), r = 0, e = i[t]; r < e; r++)
-            for (f[r] = [], u = 0, o = i[r][t]; u < o; u++) f[r][u] = i[r][u];
-        return f[d] = n._path2string, f
-    }
-
-    function li(n, t, i, r) {
-        return [n, t, i, r, i, r]
-    }
-
-    function vr(n, t, i, r, u, f) {
-        var e = 1 / 3,
-            o = 2 / 3;
-        return [e * n + o * i, e * t + o * r, e * u + o * i, e * f + o * r, u, f]
-    }
-
-    function yr(n, i, r, u, f, o, s, h, c, l) {
-        var y = e.PI,
-            it = y * 120 / 180,
-            g = y / 180 * (+f || 0),
-            b = [],
-            a, nt = ut(function(n, t, i) {
-                var r = n * e.cos(i) - t * e.sin(i);
-                return n = n * e.sin(i) + t * e.cos(i), {
-                    x: r,
-                    y: n
-                }
-            }),
-            d, w, v;
-        if (l ? (v = l[0], a = l[1], o = l[2], w = l[3]) : (a = nt(n, i, -g), n = a.x, i = a.y, a = nt(h, c, -g), h = a.x, c = a.y, e.cos(y / 180 * f), e.sin(y / 180 * f), a = (n - h) / 2, v = (i - c) / 2, w = a * a / (r * r) + v * v / (u * u), w > 1 && (w = e.sqrt(w), r = w * r, u = w * u), w = r * r, d = u * u, w = (o == s ? -1 : 1) * e.sqrt(e.abs((w * d - w * v * v - d * a * a) / (w * v * v + d * a * a))), o = w * r * v / u + (n + h) / 2, w = w * -u * a / r + (i + c) / 2, v = e.asin(((i - w) / u).toFixed(7)), a = e.asin(((c - w) / u).toFixed(7)), v = n < o ? y - v : v, a = h < o ? y - a : a, v < 0 && (v = y * 2 + v), a < 0 && (a = y * 2 + a), s && v > a && (v -= y * 2), !s && a > v && (a -= y * 2)), y = a - v, e.abs(y) > it && (b = a, y = h, d = c, a = v + it * (s && a > v ? 1 : -1), h = o + r * e.cos(a), c = w + u * e.sin(a), b = yr(h, c, r, u, f, 0, s, y, d, [a, b, o, w])), y = a - v, f = e.cos(v), o = e.sin(v), s = e.cos(a), a = e.sin(a), y = e.tan(y / 4), r = 4 / 3 * r * y, y = 4 / 3 * u * y, u = [n, i], n = [n + r * o, i - y * f], i = [h + r * a, c - y * s], h = [h, c], n[0] = 2 * u[0] - n[0], n[1] = 2 * u[1] - n[1], l) return [n, i, h][k](b);
-        for (b = [n, i, h][k](b)[tt]()[p](","), l = [], h = 0, c = b[t]; h < c; h++) l[h] = h % 2 ? nt(b[h - 1], b[h], g).y : nt(b[h], b[h + 1], g).x;
-        return l
-    }
-
-    function ii(n, t, i, r, u, f, e, o, s) {
-        var h = 1 - s;
-        return {
-            x: l(h, 3) * n + l(h, 2) * 3 * s * i + h * 3 * s * s * u + l(s, 3) * e,
-            y: l(h, 3) * t + l(h, 2) * 3 * s * r + h * 3 * s * s * f + l(s, 3) * o
-        }
-    }
-
-    function wr(t, i, r, u) {
-        if (n.is(t, wt) || n.is(t, "object")) {
-            if (t = n.is(t, wt) ? c.getElementById(t) : t, t.tagName) return i == null ? {
-                container: t,
-                width: t.style.pixelWidth || t.offsetWidth,
-                height: t.style.pixelHeight || t.offsetHeight
-            } : {
-                container: t,
-                width: i,
-                height: r
-            }
-        } else return {
-            container: 1,
-            x: t,
-            y: i,
-            width: r,
-            height: u
-        }
-    }
-
-    function nr(n, t) {
-        var r = this;
-        for (var i in t)
-            if (t[s](i) && !(i in n)) switch (typeof t[i]) {
-                case "function":
-                    (function(t) {
-                        n[i] = n === r ? t : function() {
-                            return t[b](r, arguments)
-                        }
-                    })(t[i]);
-                    break;
-                case "object":
-                    n[i] = n[i] || {};
-                    nr.call(this, n[i], t[i]);
-                    break;
-                default:
-                    n[i] = t[i]
-            }
-    }
-
-    function gt(n, t) {
-        n == t.top && (t.top = n.prev);
-        n == t.bottom && (t.bottom = n.next);
-        n.next && (n.next.prev = n.prev);
-        n.prev && (n.prev.next = n.next)
-    }
-
-    function br(n, t) {
-        t.top !== n && (gt(n, t), n.next = null, n.prev = t.top, t.top.next = n, t.top = n)
-    }
-
-    function kr(n, t) {
-        t.bottom !== n && (gt(n, t), n.next = t.bottom, n.prev = null, t.bottom.prev = n, t.bottom = n)
-    }
-
-    function dr(n, t, i) {
-        gt(n, i);
-        t == i.top && (i.top = n);
-        t.next && (t.next.prev = n);
-        n.next = t.next;
-        n.prev = t;
-        t.next = n
-    }
-
-    function gr(n, t, i) {
-        gt(n, i);
-        t == i.bottom && (i.bottom = n);
-        t.prev && (t.prev.next = n);
-        n.prev = t.prev;
-        t.prev = n;
-        n.next = t
-    }
-
-    function nu(n) {
-        return function() {
-            throw new Error("Raphaël: you are calling to method “" + n + "” of removed object");
-        }
-    }
-
-    function cf() {
-        this.returnValue = !1
-    }
-
-    function lf() {
-        return this.originalEvent.preventDefault()
-    }
-
-    function af() {
-        this.cancelBubble = !0
-    }
-
-    function vf() {
-        return this.originalEvent.stopPropagation()
-    }
-
-    function vu() {
-        return this.x + g + this.y
-    }
-
-    function fr(t, i) {
-        return function(r, u, f) {
-            r = ai(r);
-            for (var o, s, e, l, h = "", a = {}, c = 0, v = 0, y = r.length; v < y; v++) {
-                if (e = r[v], e[0] == "M") o = +e[1], s = +e[2];
-                else {
-                    if (l = yf(o, s, e[1], e[2], e[3], e[4], e[5], e[6]), c + l > u) {
-                        if (i && !a.start) {
-                            if (o = ur(o, s, e[1], e[2], e[3], e[4], e[5], e[6], u - c), h += ["C", o.start.x, o.start.y, o.m.x, o.m.y, o.x, o.y], f) return h;
-                            a.start = h;
-                            h = ["M", o.x, o.y + "C", o.n.x, o.n.y, o.end.x, o.end.y, e[5], e[6]][tt]();
-                            c += l;
-                            o = +e[5];
-                            s = +e[6];
-                            continue
-                        }
-                        if (!t && !i) return o = ur(o, s, e[1], e[2], e[3], e[4], e[5], e[6], u - c), {
-                            x: o.x,
-                            y: o.y,
-                            alpha: o.alpha
-                        }
-                    }
-                    c += l;
-                    o = +e[5];
-                    s = +e[6]
-                }
-                h += e
-            }
-            return a.end = h, o = t ? c : i ? a : n.findDotsAtSegment(o, s, e[1], e[2], e[3], e[4], e[5], e[6], 1), o.alpha && (o = {
-                x: o.x,
-                y: o.y,
-                alpha: o.alpha
-            }), o
-        }
-    }
-
-    function pu() {
-        var et = +new Date,
-            p, l, i, ut, k, ft;
-        for (p in rt)
-            if (p != "length" && rt[s](p))
-                if (l = rt[p], l.stop || l.el.removed) delete rt[p], rt[t]--;
-                else {
-                    var w = et - l.start,
-                        a = l.ms,
-                        u = l.easing,
-                        o = l.from,
-                        f = l.diff,
-                        h = l.to,
-                        b = l.t,
-                        d = l.prev || 0,
-                        c = l.el,
-                        y = l.callback,
-                        it = {},
-                        e;
-                    if (w < a) {
-                        y = n.easing_formulas[u] ? n.easing_formulas[u](w / a) : w / a;
-                        for (i in o)
-                            if (o[s](i)) {
-                                switch (di[i]) {
-                                    case "along":
-                                        e = y * a * f[i];
-                                        h.back && (e = h.len - e);
-                                        u = vi(h[i], e);
-                                        c.translate(f.sx - f.x || 0, f.sy - f.y || 0);
-                                        f.x = u.x;
-                                        f.y = u.y;
-                                        c.translate(u.x - f.sx, u.y - f.sy);
-                                        h.rot && c.rotate(f.r + u.alpha, u.x, u.y);
-                                        break;
-                                    case nt:
-                                        e = +o[i] + y * a * f[i];
-                                        break;
-                                    case "colour":
-                                        e = "rgb(" + [or(v(o[i].r + y * a * f[i].r)), or(v(o[i].g + y * a * f[i].g)), or(v(o[i].b + y * a * f[i].b))][tt](",") + ")";
-                                        break;
-                                    case "path":
-                                        for (e = [], u = 0, ut = o[i][t]; u < ut; u++) {
-                                            for (e[u] = [o[i][u][0]], k = 1, ft = o[i][u][t]; k < ft; k++) e[u][k] = +o[i][u][k] + y * a * f[i][u][k];
-                                            e[u] = e[u][tt](g)
-                                        }
-                                        e = e[tt](g);
-                                        break;
-                                    case "csv":
-                                        switch (i) {
-                                            case "translation":
-                                                e = f[i][0] * (w - d);
-                                                u = f[i][1] * (w - d);
-                                                b.x += e;
-                                                b.y += u;
-                                                e = e + g + u;
-                                                break;
-                                            case "rotation":
-                                                e = +o[i][0] + y * a * f[i][0];
-                                                o[i][1] && (e += "," + o[i][1] + "," + o[i][2]);
-                                                break;
-                                            case "scale":
-                                                e = [+o[i][0] + y * a * f[i][0], +o[i][1] + y * a * f[i][1], 2 in h[i] ? h[i][2] : r, 3 in h[i] ? h[i][3] : r][tt](g);
-                                                break;
-                                            case "clip-rect":
-                                                for (e = [], u = 4; u--;) e[u] = +o[i][u] + y * a * f[i][u]
-                                        }
-                                }
-                                it[i] = e
-                            }
-                        c.attr(it);
-                        c._run && c._run.call(c)
-                    } else h.along && (u = vi(h.along, h.len * !h.back), c.translate(f.sx - (f.x || 0) + u.x - f.sx, f.sy - (f.y || 0) + u.y - f.sy), h.rot && c.rotate(f.r + u.alpha, u.x, u.y)), (b.x || b.y) && c.translate(-b.x, -b.y), h.scale && (h.scale += r), c.attr(h), delete rt[p], rt[t]--, c.in_animation = null, n.is(y, "function") && y.call(c);
-                    l.prev = w
-                }
-        n.svg && c && c.paper && c.paper.safari();
-        rt[t] && st.setTimeout(pu)
-    }
-
-    function or(n) {
-        return ht(lt(n, 255), 0)
-    }
-
-    function yi(n, t) {
-        if (n == null) return {
-            x: this._.tx,
-            y: this._.ty,
-            toString: vu
-        };
-        this._.tx += +n;
-        this._.ty += +t;
-        switch (this.type) {
-            case "circle":
-            case "ellipse":
-                this.attr({
-                    cx: +n + this.attrs.cx,
-                    cy: +t + this.attrs.cy
-                });
-                break;
-            case "rect":
-            case "image":
-            case "text":
-                this.attr({
-                    x: +n + this.attrs.x,
-                    y: +t + this.attrs.y
-                });
-                break;
-            case "path":
-                var i = gi(this.attrs.path);
-                i[0][1] += +n;
-                i[0][2] += +t;
-                this.attr({
-                    path: i
-                })
-        }
-        return this
-    }
-
-    function wu(t) {
-        return function(i, r, f, e) {
-            var o = {
-                back: t
-            };
-            return n.is(f, "function") ? e = f : o.rot = f, i && i.constructor == u && (i = i.attrs.path), i && (o.along = i), this.animate(o, r, e)
-        }
-    }
-
-    function ct(n) {
-        if (this.items = [], this[t] = 0, this.type = "set", n)
-            for (var i = 0, r = n[t]; i < r; i++) n[i] && (n[i].constructor == u || n[i].constructor == ct) && (this[this.items[t]] = this.items[this.items[t]] = n[i], this[t]++)
-    }
-    var bt, lr, ar, ti, gi, dt, tr, f, cu, it, au, ur, rt, pi, bu;
-    n.version = "1.4.3";
-    var ft = /[, ]+/,
-        ku = /^(circle|rect|path|ellipse|text|image)$/,
-        i = "prototype",
-        s = "hasOwnProperty",
-        c = document,
-        st = window,
-        sr = {
-            was: Object[i][s].call(st, "Raphael"),
-            is: st.Raphael
-        };
-    var o = "appendChild",
-        b = "apply",
-        k = "concat",
-        wi = "createTouch" in c,
-        r = "",
-        g = " ",
-        p = "split",
-        hr = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend orientationchange touchcancel gesturestart gesturechange gestureend" [p](g),
-        bi = {
-            mousedown: "touchstart",
-            mousemove: "touchmove",
-            mouseup: "touchend"
-        },
-        tt = "join",
-        t = "length",
-        yt = String[i].toLowerCase,
-        e = Math,
-        ht = e.max,
-        lt = e.min,
-        nt = "number",
-        wt = "string",
-        et = "array",
-        d = "toString",
-        at = "fill",
-        du = Object[i][d],
-        l = e.pow,
-        a = "push",
-        kt = /^(?=[\da-f]$)/,
-        cr = /^url\(['"]?([^\)]+?)['"]?\)$/i,
-        gu = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+(?:\s*,\s*[\d\.]+)?)\s*\)|rgba?\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%(?:\s*,\s*[\d\.]+%))\s*\)|hs[bl]\(\s*([\d\.]+\s*,\s*[\d\.]+\s*,\s*[\d\.]+)\s*\)|hs[bl]\(\s*([\d\.]+%\s*,\s*[\d\.]+%\s*,\s*[\d\.]+%)\s*\))\s*$/i,
-        v = e.round,
-        ot = "setAttribute",
-        h = parseFloat,
-        pt = parseInt,
-        ki = " progid:DXImageTransform.Microsoft",
-        ei = String[i].toUpperCase,
-        oi = {
-            blur: 0,
-            "clip-rect": "0 0 1e9 1e9",
-            cursor: "default",
-            cx: 0,
-            cy: 0,
-            fill: "#fff",
-            "fill-opacity": 1,
-            font: '10px "Arial"',
-            "font-family": '"Arial"',
-            "font-size": "10",
-            "font-style": "normal",
-            "font-weight": 400,
-            gradient: 0,
-            height: 0,
-            href: "http://raphaeljs.com/",
-            opacity: 1,
-            path: "M0,0",
-            r: 0,
-            rotation: 0,
-            rx: 0,
-            ry: 0,
-            scale: "1 1",
-            src: "",
-            stroke: "#000",
-            "stroke-dasharray": "",
-            "stroke-linecap": "butt",
-            "stroke-linejoin": "butt",
-            "stroke-miterlimit": 0,
-            "stroke-opacity": 1,
-            "stroke-width": 1,
-            target: "_blank",
-            "text-anchor": "middle",
-            title: "Raphael",
-            translation: "0 0",
-            width: 0,
-            x: 0,
-            y: 0
-        },
-        di = {
-            along: "along",
-            blur: nt,
-            "clip-rect": "csv",
-            cx: nt,
-            cy: nt,
-            fill: "colour",
-            "fill-opacity": nt,
-            "font-size": nt,
-            height: nt,
-            opacity: nt,
-            path: "path",
-            r: nt,
-            rotation: "csv",
-            rx: nt,
-            ry: nt,
-            scale: "csv",
-            stroke: "colour",
-            "stroke-opacity": nt,
-            "stroke-width": nt,
-            translation: "csv",
-            width: nt,
-            x: nt,
-            y: nt
-        },
-        w = "replace";
-    if (n.type = st.SVGAngle || c.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML", n.type == "VML") {
-        if (bt = c.createElement("div"), bt.innerHTML = "<!--[if vml]><br><br><![endif]-->", bt.childNodes[t] != 2) return n.type = null;
-        bt = null
-    }
-    n.svg = !(n.vml = n.type == "VML");
-    y[i] = n[i];
-    n._id = 0;
-    n._oid = 0;
-    n.fn = {};
-    n.is = function(n, t) {
-        return t = yt.call(t), t == "object" && n === Object(n) || t == "undefined" && typeof n == t || t == "null" && n == null || yt.call(du.call(n).slice(8, -1)) == t
-    };
-    n.setWindow = function(n) {
-        st = n;
-        c = st.document
-    };
-    n.hsb2rgb = ut(function(t, i, r) {
-        var u;
-        if (n.is(t, "object") && "h" in t && "s" in t && "b" in t && (r = t.b, i = t.s, t = t.h), r == 0) return {
-            r: 0,
-            g: 0,
-            b: 0,
-            hex: "#000"
-        };
-        (t > 1 || i > 1 || r > 1) && (t /= 255, i /= 255, r /= 255);
-        u = ~~(t * 6);
-        t = t * 6 - u;
-        var f = r * (1 - i),
-            o = r * (1 - i * t),
-            e = r * (1 - i * (1 - t));
-        return t = [r, o, f, f, e, r, r][u], i = [e, r, r, o, f, f, e][u], u = [f, f, e, r, r, o, f][u], t *= 255, i *= 255, u *= 255, r = {
-            r: t,
-            g: i,
-            b: u,
-            toString: tf
-        }, t = (~~t)[d](16), i = (~~i)[d](16), u = (~~u)[d](16), t = t[w](kt, "0"), i = i[w](kt, "0"), u = u[w](kt, "0"), r.hex = "#" + t + i + u, r
-    }, n);
-    n.rgb2hsb = ut(function(t, i, r) {
-        var f, u, e, o;
-        return (n.is(t, "object") && "r" in t && "g" in t && "b" in t && (r = t.b, i = t.g, t = t.r), n.is(t, wt) && (f = n.getRGB(t), t = f.r, i = f.g, r = f.b), (t > 1 || i > 1 || r > 1) && (t /= 255, i /= 255, r /= 255), u = ht(t, i, r), e = lt(t, i, r), f = u, e == u) ? {
-            h: 0,
-            s: 0,
-            b: u
-        } : (o = u - e, e = o / u, t = t == u ? (i - r) / o : i == u ? 2 + (r - t) / o : 4 + (t - i) / o, t /= 6, t < 0 && t++, t > 1 && t--, {
-            h: t,
-            s: e,
-            b: f,
-            toString: nf
-        })
-    }, n);
-    var rf = /,?([achlmqrstvxz]),?/gi,
-        hi = /\s*,\s*/,
-        uf = {
-            hs: 1,
-            rg: 1
-        };
-    n._path2string = function() {
-        return this.join(",")[w](rf, "$1")
-    };
-    n.getRGB = ut(function(t) {
-        if (!t || (t += r).indexOf("-") + 1) return {
-            r: -1,
-            g: -1,
-            b: -1,
-            hex: "none",
-            error: 1
-        };
-        if (t == "none") return {
-            r: -1,
-            g: -1,
-            b: -1,
-            hex: "none"
-        };
-        uf[s](t.substring(0, 2)) || t.charAt() == "#" || (t = si(t));
-        var i, u, f, o, e;
-        return (t = t.match(gu)) ? (t[2] && (f = pt(t[2].substring(5), 16), u = pt(t[2].substring(3, 5), 16), i = pt(t[2].substring(1, 3), 16)), t[3] && (f = pt((e = t[3].charAt(3)) + e, 16), u = pt((e = t[3].charAt(2)) + e, 16), i = pt((e = t[3].charAt(1)) + e, 16)), t[4] && (t = t[4][p](hi), i = h(t[0]), u = h(t[1]), f = h(t[2]), o = h(t[3])), t[5] && (t = t[5][p](hi), i = h(t[0]) * 2.55, u = h(t[1]) * 2.55, f = h(t[2]) * 2.55, o = h(t[3])), t[6]) ? (t = t[6][p](hi), i = h(t[0]), u = h(t[1]), f = h(t[2]), n.hsb2rgb(i, u, f)) : t[7] ? (t = t[7][p](hi), i = h(t[0]) * 2.55, u = h(t[1]) * 2.55, f = h(t[2]) * 2.55, n.hsb2rgb(i, u, f)) : (t = {
-            r: i,
-            g: u,
-            b: f
-        }, i = (~~i)[d](16), u = (~~u)[d](16), f = (~~f)[d](16), i = i[w](kt, "0"), u = u[w](kt, "0"), f = f[w](kt, "0"), t.hex = "#" + i + u + f, isFinite(h(o)) && (t.o = o), t) : {
-            r: -1,
-            g: -1,
-            b: -1,
-            hex: "none",
-            error: 1
-        }
-    }, n);
-    n.getColor = function(n) {
-        n = this.getColor.start = this.getColor.start || {
-            h: 0,
-            s: 1,
-            b: n || .75
-        };
-        var t = this.hsb2rgb(n.h, n.s, n.b);
-        return n.h += .075, n.h > 1 && (n.h = 0, n.s -= .2, n.s <= 0 && (this.getColor.start = {
-            h: 0,
-            s: 1,
-            b: n.b
-        })), t.hex
-    };
-    n.getColor.reset = function() {
-        delete this.start
-    };
-    lr = /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig;
-    ar = /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig;
-    n.parsePathString = ut(function(i) {
-        if (!i) return null;
-        var f = {
-                a: 7,
-                c: 6,
-                h: 1,
-                l: 2,
-                m: 2,
-                q: 4,
-                s: 4,
-                t: 2,
-                v: 1,
-                z: 0
-            },
-            u = [];
-        return n.is(i, et) && n.is(i[0], et) && (u = ci(i)), u[t] || (i + r)[w](lr, function(n, i, r) {
-            var e = [];
-            for (n = yt.call(i), r[w](ar, function(n, t) {
-                    t && e[a](+t)
-                }), n == "m" && e[t] > 2 && (u[a]([i][k](e.splice(0, 2))), n = "l", i = i == "m" ? "l" : "L"); e[t] >= f[n];)
-                if (u[a]([i][k](e.splice(0, f[n]))), !f[n]) break
-        }), u[d] = n._path2string, u
-    });
-    n.findDotsAtSegment = function(n, t, i, r, u, f, o, s, h) {
-        var c = 1 - h,
-            w = l(c, 3) * n + l(c, 2) * 3 * h * i + c * 3 * h * h * u + l(h, 3) * o;
-        c = l(c, 3) * t + l(c, 2) * 3 * h * r + c * 3 * h * h * f + l(h, 3) * s;
-        var a = n + 2 * h * (i - n) + h * h * (u - 2 * i + n),
-            v = t + 2 * h * (r - t) + h * h * (f - 2 * r + t),
-            y = i + 2 * h * (u - i) + h * h * (o - 2 * u + i),
-            p = r + 2 * h * (f - r) + h * h * (s - 2 * f + r);
-        return n = (1 - h) * n + h * i, t = (1 - h) * t + h * r, u = (1 - h) * u + h * o, f = (1 - h) * f + h * s, s = 90 - e.atan((a - y) / (v - p)) * 180 / e.PI, (a > y || v < p) && (s += 180), {
-            x: w,
-            y: c,
-            m: {
-                x: a,
-                y: v
-            },
-            n: {
-                x: y,
-                y: p
-            },
-            start: {
-                x: n,
-                y: t
-            },
-            end: {
-                x: u,
-                y: f
-            },
-            alpha: s
-        }
-    };
-    ti = ut(function(n) {
-        if (!n) return {
-            x: 0,
-            y: 0,
-            width: 0,
-            height: 0
-        };
-        n = ai(n);
-        for (var r = 0, e = 0, u = [], f = [], i, o = 0, s = n[t]; o < s; o++) i = n[o], i[0] == "M" ? (r = i[1], e = i[2], u[a](r), f[a](e)) : (r = ff(r, e, i[1], i[2], i[3], i[4], i[5], i[6]), u = u[k](r.min.x, r.max.x), f = f[k](r.min.y, r.max.y), r = i[5], e = i[6]);
-        return n = lt[b](0, u), i = lt[b](0, f), {
-            x: n,
-            y: i,
-            width: ht[b](0, u) - n,
-            height: ht[b](0, f) - i
-        }
-    });
-    gi = ut(function(i) {
-        var v, u, r, h, y;
-        n.is(i, et) && n.is(i && i[0], et) || (i = n.parsePathString(i));
-        var e = [],
-            s = 0,
-            o = 0,
-            c = 0,
-            l = 0,
-            f = 0;
-        for (i[0][0] == "M" && (s = i[0][1], o = i[0][2], c = s, l = o, f++, e[a](["M", s, o])), f = f, v = i[t]; f < v; f++) {
-            if (u = e[f] = [], r = i[f], r[0] != yt.call(r[0])) {
-                u[0] = yt.call(r[0]);
-                switch (u[0]) {
-                    case "a":
-                        u[1] = r[1];
-                        u[2] = r[2];
-                        u[3] = r[3];
-                        u[4] = r[4];
-                        u[5] = r[5];
-                        u[6] = +(r[6] - s).toFixed(3);
-                        u[7] = +(r[7] - o).toFixed(3);
-                        break;
-                    case "v":
-                        u[1] = +(r[1] - o).toFixed(3);
-                        break;
-                    case "m":
-                        c = r[1];
-                        l = r[2];
-                    default:
-                        for (h = 1, y = r[t]; h < y; h++) u[h] = +(r[h] - (h % 2 ? s : o)).toFixed(3)
-                }
-            } else
-                for (e[f] = [], r[0] == "m" && (c = r[1] + s, l = r[2] + o), u = 0, h = r[t]; u < h; u++) e[f][u] = r[u];
-            r = e[f][t];
-            switch (e[f][0]) {
-                case "z":
-                    s = c;
-                    o = l;
-                    break;
-                case "h":
-                    s += +e[f][r - 1];
-                    break;
-                case "v":
-                    o += +e[f][r - 1];
-                    break;
-                default:
-                    s += +e[f][r - 2];
-                    o += +e[f][r - 1]
-            }
-        }
-        return e[d] = n._path2string, e
-    }, 0, ci);
-    dt = ut(function(i) {
-        var v, u, r, e, c;
-        n.is(i, et) && n.is(i && i[0], et) || (i = n.parsePathString(i));
-        var h = [],
-            o = 0,
-            s = 0,
-            l = 0,
-            a = 0,
-            f = 0;
-        for (i[0][0] == "M" && (o = +i[0][1], s = +i[0][2], l = o, a = s, f++, h[0] = ["M", o, s]), f = f, v = i[t]; f < v; f++) {
-            if (u = h[f] = [], r = i[f], r[0] != ei.call(r[0])) {
-                u[0] = ei.call(r[0]);
-                switch (u[0]) {
-                    case "A":
-                        u[1] = r[1];
-                        u[2] = r[2];
-                        u[3] = r[3];
-                        u[4] = r[4];
-                        u[5] = r[5];
-                        u[6] = +(r[6] + o);
-                        u[7] = +(r[7] + s);
-                        break;
-                    case "V":
-                        u[1] = +r[1] + s;
-                        break;
-                    case "H":
-                        u[1] = +r[1] + o;
-                        break;
-                    case "M":
-                        l = +r[1] + o;
-                        a = +r[2] + s;
-                    default:
-                        for (e = 1, c = r[t]; e < c; e++) u[e] = +r[e] + (e % 2 ? o : s)
-                }
-            } else
-                for (e = 0, c = r[t]; e < c; e++) h[f][e] = r[e];
-            switch (u[0]) {
-                case "Z":
-                    o = l;
-                    s = a;
-                    break;
-                case "H":
-                    o = u[1];
-                    break;
-                case "V":
-                    s = u[1];
-                    break;
-                default:
-                    o = h[f][h[f][t] - 2];
-                    s = h[f][h[f][t] - 1]
-            }
-        }
-        return h[d] = n._path2string, h
-    }, null, ci);
-    var ff = ut(function(n, t, i, r, u, f, o, s) {
-            var c = u - 2 * i + n - (o - 2 * u + i),
-                l = 2 * (i - n) - 2 * (u - i),
-                p = n - i,
-                h = (-l + e.sqrt(l * l - 4 * c * p)) / 2 / c,
-                v, y;
-            return c = (-l - e.sqrt(l * l - 4 * c * p)) / 2 / c, v = [t, s], y = [n, o], e.abs(h) > 1e12 && (h = .5), e.abs(c) > 1e12 && (c = .5), h > 0 && h < 1 && (h = ii(n, t, i, r, u, f, o, s, h), y[a](h.x), v[a](h.y)), c > 0 && c < 1 && (h = ii(n, t, i, r, u, f, o, s, c), y[a](h.x), v[a](h.y)), c = f - 2 * r + t - (s - 2 * f + r), l = 2 * (r - t) - 2 * (f - r), p = t - r, h = (-l + e.sqrt(l * l - 4 * c * p)) / 2 / c, c = (-l - e.sqrt(l * l - 4 * c * p)) / 2 / c, e.abs(h) > 1e12 && (h = .5), e.abs(c) > 1e12 && (c = .5), h > 0 && h < 1 && (h = ii(n, t, i, r, u, f, o, s, h), y[a](h.x), v[a](h.y)), c > 0 && c < 1 && (h = ii(n, t, i, r, u, f, o, s, c), y[a](h.x), v[a](h.y)), {
-                min: {
-                    x: lt[b](0, y),
-                    y: lt[b](0, v)
-                },
-                max: {
-                    x: ht[b](0, y),
-                    y: ht[b](0, v)
-                }
-            }
-        }),
-        ai = ut(function(n, i) {
-            function a(n, t) {
-                var i;
-                if (!n) return ["C", t.x, t.y, t.x, t.y, t.x, t.y];
-                n[0] in {
-                    T: 1,
-                    Q: 1
-                } || (t.qx = t.qy = null);
-                switch (n[0]) {
-                    case "M":
-                        t.X = n[1];
-                        t.Y = n[2];
-                        break;
-                    case "A":
-                        n = ["C"][k](yr[b](0, [t.x, t.y][k](n.slice(1))));
-                        break;
-                    case "S":
-                        i = t.x + (t.x - (t.bx || t.x));
-                        t = t.y + (t.y - (t.by || t.y));
-                        n = ["C", i, t][k](n.slice(1));
-                        break;
-                    case "T":
-                        t.qx = t.x + (t.x - (t.qx || t.x));
-                        t.qy = t.y + (t.y - (t.qy || t.y));
-                        n = ["C"][k](vr(t.x, t.y, t.qx, t.qy, n[1], n[2]));
-                        break;
-                    case "Q":
-                        t.qx = n[1];
-                        t.qy = n[2];
-                        n = ["C"][k](vr(t.x, t.y, n[1], n[2], n[3], n[4]));
-                        break;
-                    case "L":
-                        n = ["C"][k](li(t.x, t.y, n[1], n[2]));
-                        break;
-                    case "H":
-                        n = ["C"][k](li(t.x, t.y, n[1], t.y));
-                        break;
-                    case "V":
-                        n = ["C"][k](li(t.x, t.y, t.x, n[1]));
-                        break;
-                    case "Z":
-                        n = ["C"][k](li(t.x, t.y, t.X, t.Y))
-                }
-                return n
-            }
-
-            function v(n, i) {
-                if (n[i][t] > 7) {
-                    n[i].shift();
-                    for (var u = n[i]; u[t];) n.splice(i++, 0, ["C"][k](u.splice(0, 6)));
-                    n.splice(i, 1);
-                    s = ht(f[t], r && r[t] || 0)
-                }
-            }
-
-            function y(n, i, u, e, o) {
-                n && i && n[o][0] == "M" && i[o][0] != "M" && (i.splice(o, 0, ["M", e.x, e.y]), u.bx = 0, u.by = 0, u.x = n[o][1], u.y = n[o][2], s = ht(f[t], r && r[t] || 0))
-            }
-            var f = dt(n),
-                r = i && dt(i),
-                u, s;
-            for (n = {
-                    x: 0,
-                    y: 0,
-                    bx: 0,
-                    by: 0,
-                    X: 0,
-                    Y: 0,
-                    qx: null,
-                    qy: null
-                }, i = {
-                    x: 0,
-                    y: 0,
-                    bx: 0,
-                    by: 0,
-                    X: 0,
-                    Y: 0,
-                    qx: null,
-                    qy: null
-                }, u = 0, s = ht(f[t], r && r[t] || 0); u < s; u++) {
-                f[u] = a(f[u], n);
-                v(f, u);
-                r && (r[u] = a(r[u], i));
-                r && v(r, u);
-                y(f, r, n, i, u);
-                y(r, f, i, n, u);
-                var e = f[u],
-                    o = r && r[u],
-                    c = e[t],
-                    l = r && o[t];
-                n.x = e[c - 2];
-                n.y = e[c - 1];
-                n.bx = h(e[c - 4]) || n.x;
-                n.by = h(e[c - 3]) || n.y;
-                i.bx = r && (h(o[l - 4]) || i.x);
-                i.by = r && (h(o[l - 3]) || i.y);
-                i.x = r && o[l - 2];
-                i.y = r && o[l - 1]
-            }
-            return r ? [f, r] : f
-        }, null, ci),
-        pr = ut(function(i) {
-            for (var r, f, e = [], u = 0, o = i[t]; u < o; u++) {
-                if (r = {}, f = i[u].match(/^([^:]*):?([\d\.]*)/), r.color = n.getRGB(f[1]), r.color.error) return null;
-                r.color = r.color.hex;
-                f[2] && (r.offset = f[2] + "%");
-                e[a](r)
-            }
-            for (u = 1, o = e[t] - 1; u < o; u++)
-                if (!e[u].offset) {
-                    for (i = h(e[u - 1].offset || 0), f = 0, r = u + 1; r < o; r++)
-                        if (e[r].offset) {
-                            f = e[r].offset;
-                            break
-                        }
-                    for (f || (f = 100, r = o), f = h(f), f = (f - i) / (r - u + 1); u < r; u++) i += f, e[u].offset = i + "%"
-                }
-            return e
-        });
-    if (tr = /^r(?:\(([^,]+?)\s*,\s*([^\)]+?)\))?/, n.svg) {
-        y[i].svgns = "http://www.w3.org/2000/svg";
-        y[i].xlink = "http://www.w3.org/1999/xlink";
-        v = function(n) {
-            return +n + (~~n === n) * .5
-        };
-        f = function(n, t) {
-            if (t)
-                for (var u in t) t[s](u) && n[ot](u, t[u] + r);
-            else return n = c.createElementNS(y[i].svgns, n), n.style.webkitTapHighlightColor = "rgba(0,0,0,0)", n
-        };
-        n[d] = function() {
-            return "Your browser supports SVG.\nYou are running Raphaël " + this.version
-        };
-        var tu = function(n, t) {
-                var i = f("path");
-                return t.canvas && t.canvas[o](i), t = new u(i, t), t.type = "path", vt(t, {
-                    fill: "none",
-                    stroke: "#000",
-                    path: n
-                }), t
-            },
-            ri = function(i, u, s) {
-                var b = "linear",
-                    k = .5,
-                    y = .5,
-                    g = i.style,
-                    a, v, nt;
-                if (u = (u + r)[w](tr, function(n, t, i) {
-                        return b = "radial", t && i && (k = h(t), y = h(i), n = (y > .5) * 2 - 1, l(k - .5, 2) + l(y - .5, 2) > .25 && (y = e.sqrt(.25 - l(k - .5, 2)) * n + .5) && y != .5 && (y = y.toFixed(5) - 1e-5 * n)), r
-                    }), u = u[p](/\s*\-\s*/), b == "linear") {
-                    if (a = u.shift(), a = -h(a), isNaN(a)) return null;
-                    a = [0, 0, e.cos(a * e.PI / 180), e.sin(a * e.PI / 180)];
-                    v = 1 / (ht(e.abs(a[2]), e.abs(a[3])) || 1);
-                    a[2] *= v;
-                    a[3] *= v;
-                    a[2] < 0 && (a[0] = -a[2], a[2] = 0);
-                    a[3] < 0 && (a[1] = -a[3], a[3] = 0)
-                }
-                if (u = pr(u), !u) return null;
-                for (v = i.getAttribute(at), (v = v.match(/^url\(#(.*)\)$/)) && s.defs.removeChild(c.getElementById(v[1])), v = f(b + "Gradient"), v.id = "r" + (n._id++)[d](36), f(v, b == "radial" ? {
-                        fx: k,
-                        fy: y
-                    } : {
-                        x1: a[0],
-                        y1: a[1],
-                        x2: a[2],
-                        y2: a[3]
-                    }), s.defs[o](v), s = 0, a = u[t]; s < a; s++) nt = f("stop"), f(nt, {
-                    offset: u[s].offset ? u[s].offset : s ? "100%" : "0%",
-                    "stop-color": u[s].color || "#fff"
-                }), v[o](nt);
-                return f(i, {
-                    fill: "url(#" + v.id + ")",
-                    opacity: 1,
-                    "fill-opacity": 1
-                }), g.fill = r, g.opacity = 1, g.fillOpacity = 1
-            },
-            ir = function(t) {
-                var i = t.getBBox();
-                f(t.pattern, {
-                    patternTransform: n.format("translate({0},{1})", i.x, i.y)
-                })
-            },
-            vt = function(i, u) {
-                function et(n, i) {
-                    var e, o, r;
-                    if (i = st[yt.call(i)]) {
-                        for (e = n.attrs["stroke-width"] || "1", n = {
-                                round: e,
-                                square: e,
-                                butt: 0
-                            }[n.attrs["stroke-linecap"] || u["stroke-linecap"]] || 0, o = [], r = i[t]; r--;) o[r] = i[r] * e + (r % 2 ? 1 : -1) * n;
-                        f(l, {
-                            "stroke-dasharray": o[tt](",")
-                        })
-                    }
-                }
-                var st = {
-                        "": [0],
-                        none: [0],
-                        "-": [3, 1],
-                        ".": [1, 1],
-                        "-.": [3, 1, 1, 1],
-                        "-..": [3, 1, 1, 1, 1, 1],
-                        ". ": [1, 3],
-                        "- ": [4, 3],
-                        "--": [8, 3],
-                        "- .": [4, 3, 1, 3],
-                        "--.": [8, 3, 1, 3],
-                        "--..": [8, 3, 1, 3, 1, 3]
-                    },
-                    l = i.node,
-                    b = i.attrs,
-                    rt = i.rotate(),
-                    k, y, e, a, it, nt, ut;
-                u[s]("rotation") && (rt = u.rotation);
-                k = (rt + r)[p](ft);
-                k.length - 1 ? (k[1] = +k[1], k[2] = +k[2]) : k = null;
-                h(rt) && i.rotate(0, !0);
-                for (y in u)
-                    if (u[s](y) && oi[s](y)) {
-                        e = u[y];
-                        b[y] = e;
-                        switch (y) {
-                            case "blur":
-                                i.blur(e);
-                                break;
-                            case "rotation":
-                                i.rotate(e, !0);
-                                break;
-                            case "href":
-                            case "title":
-                            case "target":
-                                a = l.parentNode;
-                                yt.call(a.tagName) != "a" && (it = f("a"), a.insertBefore(it, l), it[o](l), a = it);
-                                a.setAttributeNS(i.paper.xlink, y, e);
-                                break;
-                            case "cursor":
-                                l.style.cursor = e;
-                                break;
-                            case "clip-rect":
-                                a = (e + r)[p](ft);
-                                a[t] == 4 && (i.clip && i.clip.parentNode.parentNode.removeChild(i.clip.parentNode), nt = f("clipPath"), it = f("rect"), nt.id = "r" + (n._id++)[d](36), f(it, {
-                                    x: a[0],
-                                    y: a[1],
-                                    width: a[2],
-                                    height: a[3]
-                                }), nt[o](it), i.paper.defs[o](nt), f(l, {
-                                    "clip-path": "url(#" + nt.id + ")"
-                                }), i.clip = it);
-                                e || ((e = c.getElementById(l.getAttribute("clip-path")[w](/(^url\(#|\)$)/g, r))) && e.parentNode.removeChild(e), f(l, {
-                                    "clip-path": r
-                                }), delete i.clip);
-                                break;
-                            case "path":
-                                i.type == "path" && f(l, {
-                                    d: e ? b.path = dt(e) : "M0,0"
-                                });
-                                break;
-                            case "width":
-                                if (l[ot](y, e), b.fx) y = "x", e = b.x;
-                                else break;
-                            case "x":
-                                b.fx && (e = -b.x - (b.width || 0));
-                            case "rx":
-                                if (y == "rx" && i.type == "rect") break;
-                            case "cx":
-                                k && (y == "x" || y == "cx") && (k[1] += e - b[y]);
-                                l[ot](y, v(e));
-                                i.pattern && ir(i);
-                                break;
-                            case "height":
-                                if (l[ot](y, e), b.fy) y = "y", e = b.y;
-                                else break;
-                            case "y":
-                                b.fy && (e = -b.y - (b.height || 0));
-                            case "ry":
-                                if (y == "ry" && i.type == "rect") break;
-                            case "cy":
-                                k && (y == "y" || y == "cy") && (k[2] += e - b[y]);
-                                l[ot](y, v(e));
-                                i.pattern && ir(i);
-                                break;
-                            case "r":
-                                i.type == "rect" ? f(l, {
-                                    rx: e,
-                                    ry: e
-                                }) : l[ot](y, e);
-                                break;
-                            case "src":
-                                i.type == "image" && l.setAttributeNS(i.paper.xlink, "href", e);
-                                break;
-                            case "stroke-width":
-                                l.style.strokeWidth = e;
-                                l[ot](y, e);
-                                b["stroke-dasharray"] && et(i, b["stroke-dasharray"]);
-                                break;
-                            case "stroke-dasharray":
-                                et(i, e);
-                                break;
-                            case "translation":
-                                e = (e + r)[p](ft);
-                                e[0] = +e[0] || 0;
-                                e[1] = +e[1] || 0;
-                                k && (k[1] += e[0], k[2] += e[1]);
-                                yi.call(i, e[0], e[1]);
-                                break;
-                            case "scale":
-                                e = (e + r)[p](ft);
-                                i.scale(+e[0] || 1, +e[1] || +e[0] || 1, isNaN(h(e[2])) ? null : +e[2], isNaN(h(e[3])) ? null : +e[3]);
-                                break;
-                            case at:
-                                if (a = (e + r).match(cr)) {
-                                    nt = f("pattern");
-                                    ut = f("image");
-                                    nt.id = "r" + (n._id++)[d](36);
-                                    f(nt, {
-                                        x: 0,
-                                        y: 0,
-                                        patternUnits: "userSpaceOnUse",
-                                        height: 1,
-                                        width: 1
-                                    });
-                                    f(ut, {
-                                        x: 0,
-                                        y: 0
-                                    });
-                                    ut.setAttributeNS(i.paper.xlink, "href", a[1]);
-                                    nt[o](ut);
-                                    e = c.createElement("img");
-                                    e.style.cssText = "position:absolute;left:-9999em;top-9999em";
-                                    e.onload = function() {
-                                        f(nt, {
-                                            width: this.offsetWidth,
-                                            height: this.offsetHeight
-                                        });
-                                        f(ut, {
-                                            width: this.offsetWidth,
-                                            height: this.offsetHeight
-                                        });
-                                        c.body.removeChild(this);
-                                        i.paper.safari()
-                                    };
-                                    c.body[o](e);
-                                    e.src = a[1];
-                                    i.paper.defs[o](nt);
-                                    l.style.fill = "url(#" + nt.id + ")";
-                                    f(l, {
-                                        fill: "url(#" + nt.id + ")"
-                                    });
-                                    i.pattern = nt;
-                                    i.pattern && ir(i);
-                                    break
-                                }
-                                if (a = n.getRGB(e), a.error) {
-                                    if (({
-                                            circle: 1,
-                                            ellipse: 1
-                                        }[s](i.type) || (e + r).charAt() != "r") && ri(l, e, i.paper)) {
-                                        b.gradient = e;
-                                        b.fill = "none";
-                                        break
-                                    }
-                                } else delete u.gradient, delete b.gradient, !n.is(b.opacity, "undefined") && n.is(u.opacity, "undefined") && f(l, {
-                                    opacity: b.opacity
-                                }), !n.is(b["fill-opacity"], "undefined") && n.is(u["fill-opacity"], "undefined") && f(l, {
-                                    "fill-opacity": b["fill-opacity"]
-                                });
-                                a[s]("o") && f(l, {
-                                    "fill-opacity": a.o / 100
-                                });
-                            case "stroke":
-                                a = n.getRGB(e);
-                                l[ot](y, a.hex);
-                                y == "stroke" && a[s]("o") && f(l, {
-                                    "stroke-opacity": a.o / 100
-                                });
-                                break;
-                            case "gradient":
-                                ({
-                                    circle: 1,
-                                    ellipse: 1
-                                }[s](i.type) || (e + r).charAt() != "r") && ri(l, e, i.paper);
-                                break;
-                            case "opacity":
-                            case "fill-opacity":
-                                if (b.gradient) {
-                                    (a = c.getElementById(l.getAttribute(at)[w](/^url\(#|\)$/g, r))) && (a = a.getElementsByTagName("stop"), a[a[t] - 1][ot]("stop-opacity", e));
-                                    break
-                                }
-                            default:
-                                y == "font-size" && (e = pt(e, 10) + "px");
-                                a = y[w](/(\-.)/g, function(n) {
-                                    return ei.call(n.substring(1))
-                                });
-                                l.style[a] = e;
-                                l[ot](y, e)
-                        }
-                    }
-                ef(i, u);
-                k ? i.rotate(k.join(g)) : h(rt) && i.rotate(rt, !0)
-            },
-            iu = 1.2,
-            ef = function(n, i) {
-                var u, l, a;
-                if (!(n.type != "text" || !(i[s]("text") || i[s]("font") || i[s]("font-size") || i[s]("x") || i[s]("y")))) {
-                    var h = n.attrs,
-                        e = n.node,
-                        v = e.firstChild ? pt(c.defaultView.getComputedStyle(e.firstChild, r).getPropertyValue("font-size"), 10) : 10;
-                    if (i[s]("text")) {
-                        for (h.text = i.text; e.firstChild;) e.removeChild(e.firstChild);
-                        for (i = (i.text + r)[p]("\n"), u = 0, l = i[t]; u < l; u++) i[u] && (a = f("tspan"), u && f(a, {
-                            dy: v * iu,
-                            x: h.x
-                        }), a[o](c.createTextNode(i[u])), e[o](a))
-                    } else
-                        for (i = e.getElementsByTagName("tspan"), u = 0, l = i[t]; u < l; u++) u && f(i[u], {
-                            dy: v * iu,
-                            x: h.x
-                        });
-                    f(e, {
-                        y: h.y
-                    });
-                    n = n.getBBox();
-                    (n = h.y - (n.y + n.height / 2)) && isFinite(n) && f(e, {
-                        y: h.y + n
-                    })
-                }
-            },
-            u = function(t, i) {
-                this[0] = t;
-                this.id = n._oid++;
-                this.node = t;
-                t.raphael = this;
-                this.paper = i;
-                this.attrs = this.attrs || {};
-                this.transformations = [];
-                this._ = {
-                    tx: 0,
-                    ty: 0,
-                    rt: {
-                        deg: 0,
-                        cx: 0,
-                        cy: 0
-                    },
-                    sx: 1,
-                    sy: 1
-                };
-                i.bottom || (i.bottom = this);
-                (this.prev = i.top) && (i.top.next = this);
-                i.top = this;
-                this.next = null
-            };
-        u[i].rotate = function(i, u, e) {
-            if (this.removed) return this;
-            if (i == null) return this._.rt.cx ? [this._.rt.deg, this._.rt.cx, this._.rt.cy][tt](g) : this._.rt.deg;
-            var o = this.getBBox();
-            return i = (i + r)[p](ft), i[t] - 1 && (u = h(i[1]), e = h(i[2])), i = h(i[0]), u != null ? this._.rt.deg = i : this._.rt.deg += i, e == null && (u = null), this._.rt.cx = u, this._.rt.cy = e, u = u == null ? o.x + o.width / 2 : u, e = e == null ? o.y + o.height / 2 : e, this._.rt.deg ? (this.transformations[0] = n.format("rotate({0} {1} {2})", this._.rt.deg, u, e), this.clip && f(this.clip, {
-                transform: n.format("rotate({0} {1} {2})", -this._.rt.deg, u, e)
-            })) : (this.transformations[0] = r, this.clip && f(this.clip, {
-                transform: r
-            })), f(this.node, {
-                transform: this.transformations[tt](g)
-            }), this
-        };
-        u[i].hide = function() {
-            return this.removed || (this.node.style.display = "none"), this
-        };
-        u[i].show = function() {
-            return this.removed || (this.node.style.display = ""), this
-        };
-        u[i].remove = function() {
-            if (!this.removed) {
-                gt(this, this.paper);
-                this.node.parentNode.removeChild(this.node);
-                for (var n in this) delete this[n];
-                this.removed = !0
-            }
-        };
-        u[i].getBBox = function() {
-            var r, n, i, u, t;
-            if (this.removed) return this;
-            if (this.type == "path") return ti(this.attrs.path);
-            this.node.style.display == "none" && (this.show(), r = !0);
-            n = {};
-            try {
-                n = this.node.getBBox()
-            } catch (f) {} finally {
-                n = n || {}
-            }
-            if (this.type == "text")
-                for (n = {
-                        x: n.x,
-                        y: Infinity,
-                        width: 0,
-                        height: 0
-                    }, i = 0, u = this.node.getNumberOfChars(); i < u; i++) t = this.node.getExtentOfChar(i), t.y < n.y && (n.y = t.y), t.y + t.height - n.y > n.height && (n.height = t.y + t.height - n.y), t.x + t.width - n.x > n.width && (n.width = t.x + t.width - n.x);
-            return r && this.hide(), n
-        };
-        u[i].attr = function(t, i) {
-            var r, u;
-            if (this.removed) return this;
-            if (t == null) {
-                t = {};
-                for (r in this.attrs) this.attrs[s](r) && (t[r] = this.attrs[r]);
-                return this._.rt.deg && (t.rotation = this.rotate()), (this._.sx != 1 || this._.sy != 1) && (t.scale = this.scale()), t.gradient && t.fill == "none" && (t.fill = t.gradient) && delete t.gradient, t
-            }
-            if (i == null && n.is(t, wt)) return t == "translation" ? yi.call(this) : t == "rotation" ? this.rotate() : t == "scale" ? this.scale() : t == at && this.attrs.fill == "none" && this.attrs.gradient ? this.attrs.gradient : this.attrs[t];
-            if (i == null && n.is(t, et)) {
-                for (i = {}, r = 0, u = t.length; r < u; r++) i[t[r]] = this.attr(t[r]);
-                return i
-            }
-            return i != null ? (r = {}, r[t] = i, vt(this, r)) : t != null && n.is(t, "object") && vt(this, t), this
-        };
-        u[i].toFront = function() {
-            if (this.removed) return this;
-            this.node.parentNode[o](this.node);
-            var n = this.paper;
-            return n.top != this && br(this, n), this
-        };
-        u[i].toBack = function() {
-            return this.removed ? this : (this.node.parentNode.firstChild != this.node && (this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild), kr(this, this.paper)), this)
-        };
-        u[i].insertAfter = function(n) {
-            if (this.removed) return this;
-            var t = n.node;
-            return t.nextSibling ? t.parentNode.insertBefore(this.node, t.nextSibling) : t.parentNode[o](this.node), dr(this, n, this.paper), this
-        };
-        u[i].insertBefore = function(n) {
-            if (this.removed) return this;
-            var t = n.node;
-            return t.parentNode.insertBefore(this.node, t), gr(this, n, this.paper), this
-        };
-        u[i].blur = function(t) {
-            var i = this,
-                r, u; + t != 0 ? (r = f("filter"), u = f("feGaussianBlur"), i.attrs.blur = t, r.id = "r" + (n._id++)[d](36), f(u, {
-                stdDeviation: +t || 1.5
-            }), r.appendChild(u), i.paper.defs.appendChild(r), i._blur = r, f(i.node, {
-                filter: "url(#" + r.id + ")"
-            })) : (i._blur && (i._blur.parentNode.removeChild(i._blur), delete i._blur, delete i.attrs.blur), i.node.removeAttribute("filter"))
-        };
-        var ru = function(n, t, i, r) {
-                t = v(t);
-                i = v(i);
-                var e = f("circle");
-                return n.canvas && n.canvas[o](e), n = new u(e, n), n.attrs = {
-                    cx: t,
-                    cy: i,
-                    r: r,
-                    fill: "none",
-                    stroke: "#000"
-                }, n.type = "circle", f(e, n.attrs), n
-            },
-            uu = function(n, t, i, r, e, s) {
-                t = v(t);
-                i = v(i);
-                var h = f("rect");
-                return n.canvas && n.canvas[o](h), n = new u(h, n), n.attrs = {
-                    x: t,
-                    y: i,
-                    width: r,
-                    height: e,
-                    r: s || 0,
-                    rx: s || 0,
-                    ry: s || 0,
-                    fill: "none",
-                    stroke: "#000"
-                }, n.type = "rect", f(h, n.attrs), n
-            },
-            fu = function(n, t, i, r, e) {
-                t = v(t);
-                i = v(i);
-                var s = f("ellipse");
-                return n.canvas && n.canvas[o](s), n = new u(s, n), n.attrs = {
-                    cx: t,
-                    cy: i,
-                    rx: r,
-                    ry: e,
-                    fill: "none",
-                    stroke: "#000"
-                }, n.type = "ellipse", f(s, n.attrs), n
-            },
-            eu = function(n, t, i, r, e, s) {
-                var h = f("image");
-                return f(h, {
-                    x: i,
-                    y: r,
-                    width: e,
-                    height: s,
-                    preserveAspectRatio: "none"
-                }), h.setAttributeNS(n.xlink, "href", t), n.canvas && n.canvas[o](h), n = new u(h, n), n.attrs = {
-                    x: i,
-                    y: r,
-                    width: e,
-                    height: s,
-                    src: t
-                }, n.type = "image", n
-            },
-            ou = function(n, t, i, r) {
-                var e = f("text");
-                return f(e, {
-                    x: t,
-                    y: i,
-                    "text-anchor": "middle"
-                }), n.canvas && n.canvas[o](e), n = new u(e, n), n.attrs = {
-                    x: t,
-                    y: i,
-                    "text-anchor": "middle",
-                    text: r,
-                    font: oi.font,
-                    stroke: "none",
-                    fill: "#000"
-                }, n.type = "text", vt(n, n.attrs), n
-            },
-            su = function(n, t) {
-                return this.width = n || this.width, this.height = t || this.height, this.canvas[ot]("width", this.width), this.canvas[ot]("height", this.height), this
-            },
-            rr = function() {
-                var i = wr[b](0, arguments),
-                    t = i && i.container,
-                    e = i.x,
-                    s = i.y,
-                    u = i.width,
-                    r;
-                if (i = i.height, !t) throw new Error("SVG container not found.");
-                return r = f("svg"), e = e || 0, s = s || 0, u = u || 512, i = i || 342, f(r, {
-                    xmlns: "http://www.w3.org/2000/svg",
-                    version: 1.1,
-                    width: u,
-                    height: i
-                }), t == 1 ? (r.style.cssText = "position:absolute;left:" + e + "px;top:" + s + "px", c.body[o](r)) : t.firstChild ? t.insertBefore(r, t.firstChild) : t[o](r), t = new y, t.width = u, t.height = i, t.canvas = r, nr.call(t, t, n.fn), t.clear(), t
-            };
-        y[i].clear = function() {
-            for (var n = this.canvas; n.firstChild;) n.removeChild(n.firstChild);
-            this.bottom = this.top = null;
-            (this.desc = f("desc"))[o](c.createTextNode("Created with Raphaël"));
-            n[o](this.desc);
-            n[o](this.defs = f("defs"))
-        };
-        y[i].remove = function() {
-            this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
-            for (var n in this) this[n] = nu(n)
-        }
-    }
-    if (n.vml) {
-        var hu = {
-                M: "m",
-                L: "l",
-                C: "c",
-                Z: "x",
-                m: "t",
-                l: "r",
-                c: "v",
-                z: "x"
-            },
-            of = /([clmz]),?([^clmz]*)/gi,
-            sf = /-?[^,\s-]+/g,
-            ui = 1e3 + g + 1e3,
-            ni = 10,
-            fi = {
-                path: 1,
-                rect: 1
-            },
-            hf = function(n) {
-                var i = /[ahqstv]/ig,
-                    u = dt,
-                    f, e, h, o, s;
-                if ((n + r).match(i) && (u = ai), i = /[clmz]/g, u == dt && !(n + r).match(i)) return (n + r)[w]( of , function(n, i, r) {
-                    var u = [],
-                        e = yt.call(i) == "m",
-                        f = hu[i];
-                    return r[w](sf, function(n) {
-                        e && u[t] == 2 && (f += u + hu[i == "m" ? "l" : "L"], u = []);
-                        u[a](v(n * ni))
-                    }), f + u
-                });
-                for (i = u(n), n = [], e = 0, h = i[t]; e < h; e++) {
-                    for (u = i[e], f = yt.call(i[e][0]), f == "z" && (f = "x"), o = 1, s = u[t]; o < s; o++) f += v(u[o] * ni) + (o != s - 1 ? "," : r);
-                    n[a](f)
-                }
-                return n[tt](g)
-            };
-        n[d] = function() {
-            return "Your browser doesn’t support SVG. Falling down to VML.\nYou are running Raphaël " + this.version
-        };
-        tu = function(n, t) {
-            var f = it("group"),
-                i, e;
-            return f.style.cssText = "position:absolute;left:0;top:0;width:" + t.width + "px;height:" + t.height + "px", f.coordsize = t.coordsize, f.coordorigin = t.coordorigin, i = it("shape"), e = i.style, e.width = t.width + "px", e.height = t.height + "px", i.coordsize = ui, i.coordorigin = t.coordorigin, f[o](i), i = new u(i, f, t), e = {
-                fill: "none",
-                stroke: "#000"
-            }, n && (e.path = n), i.isAbsolute = !0, i.type = "path", i.path = [], i.Path = r, vt(i, e), t.canvas[o](f), i
-        };
-        vt = function(i, u) {
-            var y, b, k, d;
-            i.attrs = i.attrs || {};
-            var a = i.node,
-                e = i.attrs,
-                f = a.style,
-                l;
-            l = (u.x != e.x || u.y != e.y || u.width != e.width || u.height != e.height || u.r != e.r) && i.type == "rect";
-            y = i;
-            for (b in u) u[s](b) && (e[b] = u[b]);
-            if (l && (e.path = lu(e.x, e.y, e.width, e.height, e.r), i.X = e.x, i.Y = e.y, i.W = e.width, i.H = e.height), u.href && (a.href = u.href), u.title && (a.title = u.title), u.target && (a.target = u.target), u.cursor && (f.cursor = u.cursor), "blur" in u && i.blur(u.blur), (u.path && i.type == "path" || l) && (a.path = hf(e.path)), u.rotation != null && i.rotate(u.rotation, !0), u.translation && (l = (u.translation + r)[p](ft), yi.call(i, l[0], l[1]), i._.rt.cx != null && (i._.rt.cx += +l[0], i._.rt.cy += +l[1], i.setBox(i.attrs, l[0], l[1]))), u.scale && (l = (u.scale + r)[p](ft), i.scale(+l[0] || 1, +l[1] || +l[0] || 1, +l[2] || null, +l[3] || null)), "clip-rect" in u && (l = (u["clip-rect"] + r)[p](ft), l[t] == 4 && (l[2] = +l[2] + +l[0], l[3] = +l[3] + +l[1], b = a.clipRect || c.createElement("div"), k = b.style, d = a.parentNode, k.clip = n.format("rect({1}px {2}px {3}px {0}px)", l), a.clipRect || (k.position = "absolute", k.top = 0, k.left = 0, k.width = i.paper.width + "px", k.height = i.paper.height + "px", d.parentNode.insertBefore(b, d), b[o](d), a.clipRect = b)), u["clip-rect"] || a.clipRect && (a.clipRect.style.clip = r)), i.type == "image" && u.src && (a.src = u.src), i.type == "image" && u.opacity && (a.filterOpacity = ki + ".Alpha(opacity=" + u.opacity * 100 + ")", f.filter = (a.filterMatrix || r) + (a.filterOpacity || r)), u.font && (f.font = u.font), u["font-family"] && (f.fontFamily = '"' + u["font-family"][p](",")[0][w](/^['"]+|['"]+$/g, r) + '"'), u["font-size"] && (f.fontSize = u["font-size"]), u["font-weight"] && (f.fontWeight = u["font-weight"]), u["font-style"] && (f.fontStyle = u["font-style"]), (u.opacity != null || u["stroke-width"] != null || u.fill != null || u.stroke != null || u["stroke-width"] != null || u["stroke-opacity"] != null || u["fill-opacity"] != null || u["stroke-dasharray"] != null || u["stroke-miterlimit"] != null || u["stroke-linejoin"] != null || u["stroke-linecap"] != null) && (a = i.shape || a, f = a.getElementsByTagName(at) && a.getElementsByTagName(at)[0], l = !1, f || (l = f = it(at)), ("fill-opacity" in u || "opacity" in u) && (i = ((+e["fill-opacity"] + 1 || 2) - 1) * ((+e.opacity + 1 || 2) - 1) * ((+n.getRGB(u.fill).o + 1 || 2) - 1), i < 0 && (i = 0), i > 1 && (i = 1), f.opacity = i), u.fill && (f.on = !0), (f.on == null || u.fill == "none") && (f.on = !1), f.on && u.fill && ((i = u.fill.match(cr)) ? (f.src = i[1], f.type = "tile") : (f.color = n.getRGB(u.fill).hex, f.src = r, f.type = "solid", n.getRGB(u.fill).error && (y.type in {
-                    circle: 1,
-                    ellipse: 1
-                } || (u.fill + r).charAt() != "r") && ri(y, u.fill) && (e.fill = "none", e.gradient = u.fill))), l && a[o](f), f = a.getElementsByTagName("stroke") && a.getElementsByTagName("stroke")[0], l = !1, f || (l = f = it("stroke")), (u.stroke && u.stroke != "none" || u["stroke-width"] || u["stroke-opacity"] != null || u["stroke-dasharray"] || u["stroke-miterlimit"] || u["stroke-linejoin"] || u["stroke-linecap"]) && (f.on = !0), (u.stroke == "none" || f.on == null || u.stroke == 0 || u["stroke-width"] == 0) && (f.on = !1), i = n.getRGB(u.stroke), f.on && u.stroke && (f.color = i.hex), i = ((+e["stroke-opacity"] + 1 || 2) - 1) * ((+e.opacity + 1 || 2) - 1) * ((+i.o + 1 || 2) - 1), b = (h(u["stroke-width"]) || 1) * .75, i < 0 && (i = 0), i > 1 && (i = 1), u["stroke-width"] == null && (b = e["stroke-width"]), u["stroke-width"] && (f.weight = b), b && b < 1 && (i *= b) && (f.weight = 1), f.opacity = i, u["stroke-linejoin"] && (f.joinstyle = u["stroke-linejoin"] || "miter"), f.miterlimit = u["stroke-miterlimit"] || 8, u["stroke-linecap"] && (f.endcap = u["stroke-linecap"] == "butt" ? "flat" : u["stroke-linecap"] == "square" ? "square" : "round"), u["stroke-dasharray"] && (i = {
-                    "-": "shortdash",
-                    ".": "shortdot",
-                    "-.": "shortdashdot",
-                    "-..": "shortdashdotdot",
-                    ". ": "dot",
-                    "- ": "dash",
-                    "--": "longdash",
-                    "- .": "dashdot",
-                    "--.": "longdashdot",
-                    "--..": "longdashdotdot"
-                }, f.dashstyle = i[s](u["stroke-dasharray"]) ? i[u["stroke-dasharray"]] : r), l && a[o](f)), y.type == "text") {
-                f = y.paper.span.style;
-                e.font && (f.font = e.font);
-                e["font-family"] && (f.fontFamily = e["font-family"]);
-                e["font-size"] && (f.fontSize = e["font-size"]);
-                e["font-weight"] && (f.fontWeight = e["font-weight"]);
-                e["font-style"] && (f.fontStyle = e["font-style"]);
-                y.node.string && (y.paper.span.innerHTML = (y.node.string + r)[w](/</g, "&#60;")[w](/&/g, "&#38;")[w](/\n/g, "<br>"));
-                y.W = e.w = y.paper.span.offsetWidth;
-                y.H = e.h = y.paper.span.offsetHeight;
-                y.X = e.x;
-                y.Y = e.y + v(y.H / 2);
-                switch (e["text-anchor"]) {
-                    case "start":
-                        y.node.style["v-text-align"] = "left";
-                        y.bbx = v(y.W / 2);
-                        break;
-                    case "end":
-                        y.node.style["v-text-align"] = "right";
-                        y.bbx = -v(y.W / 2);
-                        break;
-                    default:
-                        y.node.style["v-text-align"] = "center"
-                }
-            }
-        };
-        ri = function(n, i) {
-            var s, c, o, u, f, v;
-            if ((n.attrs = n.attrs || {}, s = "linear", c = ".5 .5", n.attrs.gradient = i, i = (i + r)[w](tr, function(n, t, i) {
-                    return s = "radial", t && i && (t = h(t), i = h(i), l(t - .5, 2) + l(i - .5, 2) > .25 && (i = e.sqrt(.25 - l(t - .5, 2)) * ((i > .5) * 2 - 1) + .5), c = t + g + i), r
-                }), i = i[p](/\s*\-\s*/), s == "linear" && (o = i.shift(), o = -h(o), isNaN(o))) || (u = pr(i), !u)) return null;
-            if (n = n.shape || n.node, i = n.getElementsByTagName(at)[0] || it(at), i.parentNode || n.appendChild(i), u[t]) {
-                for (i.on = !0, i.method = "none", i.color = u[0].color, i.color2 = u[u[t] - 1].color, n = [], f = 0, v = u[t]; f < v; f++) u[f].offset && n[a](u[f].offset + g + u[f].color);
-                i.colors && (i.colors.value = n[t] ? n[tt]() : "0% " + i.color);
-                s == "radial" ? (i.type = "gradientradial", i.focus = "100%", i.focussize = c, i.focusposition = c) : (i.type = "gradient", i.angle = (270 - o) % 360)
-            }
-            return 1
-        };
-        u = function(t, i, r) {
-            this[0] = t;
-            this.id = n._oid++;
-            this.node = t;
-            t.raphael = this;
-            this.Y = this.X = 0;
-            this.attrs = {};
-            this.Group = i;
-            this.paper = r;
-            this._ = {
-                tx: 0,
-                ty: 0,
-                rt: {
-                    deg: 0
-                },
-                sx: 1,
-                sy: 1
-            };
-            r.bottom || (r.bottom = this);
-            (this.prev = r.top) && (r.top.next = this);
-            r.top = this;
-            this.next = null
-        };
-        u[i].rotate = function(n, i, u) {
-            return this.removed ? this : n == null ? this._.rt.cx ? [this._.rt.deg, this._.rt.cx, this._.rt.cy][tt](g) : this._.rt.deg : (n = (n + r)[p](ft), n[t] - 1 && (i = h(n[1]), u = h(n[2])), n = h(n[0]), i != null ? this._.rt.deg = n : this._.rt.deg += n, u == null && (i = null), this._.rt.cx = i, this._.rt.cy = u, this.setBox(this.attrs, i, u), this.Group.style.rotation = this._.rt.deg, this)
-        };
-        u[i].setBox = function(n, t, i) {
-            var c, e, o, u, h, f;
-            if (this.removed) return this;
-            c = this.Group.style;
-            e = this.shape && this.shape.style || this.node.style;
-            n = n || {};
-            for (o in n) n[s](o) && (this.attrs[o] = n[o]);
-            t = t || this._.rt.cx;
-            i = i || this._.rt.cy;
-            u = this.attrs;
-            switch (this.type) {
-                case "circle":
-                    n = u.cx - u.r;
-                    o = u.cy - u.r;
-                    h = u = u.r * 2;
-                    break;
-                case "ellipse":
-                    n = u.cx - u.rx;
-                    o = u.cy - u.ry;
-                    h = u.rx * 2;
-                    u = u.ry * 2;
-                    break;
-                case "image":
-                    n = +u.x;
-                    o = +u.y;
-                    h = u.width || 0;
-                    u = u.height || 0;
-                    break;
-                case "text":
-                    this.textpath.v = ["m", v(u.x), ", ", v(u.y - 2), "l", v(u.x) + 1, ", ", v(u.y - 2)][tt](r);
-                    n = u.x - v(this.W / 2);
-                    o = u.y - this.H / 2;
-                    h = this.W;
-                    u = this.H;
-                    break;
-                case "rect":
-                case "path":
-                    this.attrs.path ? (u = ti(this.attrs.path), n = u.x, o = u.y, h = u.width, u = u.height) : (o = n = 0, h = this.paper.width, u = this.paper.height);
-                    break;
-                default:
-                    o = n = 0;
-                    h = this.paper.width;
-                    u = this.paper.height
-            }
-            t = t == null ? n + h / 2 : t;
-            i = i == null ? o + u / 2 : i;
-            t = t - this.paper.width / 2;
-            i = i - this.paper.height / 2;
-            c.left != (f = t + "px") && (c.left = f);
-            c.top != (f = i + "px") && (c.top = f);
-            this.X = fi[s](this.type) ? -t : n;
-            this.Y = fi[s](this.type) ? -i : o;
-            this.W = h;
-            this.H = u;
-            fi[s](this.type) ? (e.left != (f = -t * ni + "px") && (e.left = f), e.top != (f = -i * ni + "px") && (e.top = f)) : this.type == "text" ? (e.left != (f = -t + "px") && (e.left = f), e.top != (f = -i + "px") && (e.top = f)) : (c.width != (f = this.paper.width + "px") && (c.width = f), c.height != (f = this.paper.height + "px") && (c.height = f), e.left != (f = n - t + "px") && (e.left = f), e.top != (f = o - i + "px") && (e.top = f), e.width != (f = h + "px") && (e.width = f), e.height != (f = u + "px") && (e.height = f))
-        };
-        u[i].hide = function() {
-            return this.removed || (this.Group.style.display = "none"), this
-        };
-        u[i].show = function() {
-            return this.removed || (this.Group.style.display = "block"), this
-        };
-        u[i].getBBox = function() {
-            return this.removed ? this : fi[s](this.type) ? ti(this.attrs.path) : {
-                x: this.X + (this.bbx || 0),
-                y: this.Y,
-                width: this.W,
-                height: this.H
-            }
-        };
-        u[i].remove = function() {
-            if (!this.removed) {
-                gt(this, this.paper);
-                this.node.parentNode.removeChild(this.node);
-                this.Group.parentNode.removeChild(this.Group);
-                this.shape && this.shape.parentNode.removeChild(this.shape);
-                for (var n in this) delete this[n];
-                this.removed = !0
-            }
-        };
-        u[i].attr = function(i, u) {
-            var e, f;
-            if (this.removed) return this;
-            if (i == null) {
-                i = {};
-                for (e in this.attrs) this.attrs[s](e) && (i[e] = this.attrs[e]);
-                return this._.rt.deg && (i.rotation = this.rotate()), (this._.sx != 1 || this._.sy != 1) && (i.scale = this.scale()), i.gradient && i.fill == "none" && (i.fill = i.gradient) && delete i.gradient, i
-            }
-            if (u == null && n.is(i, wt)) return i == "translation" ? yi.call(this) : i == "rotation" ? this.rotate() : i == "scale" ? this.scale() : i == at && this.attrs.fill == "none" && this.attrs.gradient ? this.attrs.gradient : this.attrs[i];
-            if (this.attrs && u == null && n.is(i, et)) {
-                for (f = {}, e = 0, u = i[t]; e < u; e++) f[i[e]] = this.attr(i[e]);
-                return f
-            }
-            return u != null && (f = {}, f[i] = u), u == null && n.is(i, "object") && (f = i), f && (f.text && this.type == "text" && (this.node.string = f.text), vt(this, f), f.gradient && ({
-                circle: 1,
-                ellipse: 1
-            }[s](this.type) || (f.gradient + r).charAt() != "r") && ri(this, f.gradient), (!fi[s](this.type) || this._.rt.deg) && this.setBox(this.attrs)), this
-        };
-        u[i].toFront = function() {
-            return this.removed || this.Group.parentNode[o](this.Group), this.paper.top != this && br(this, this.paper), this
-        };
-        u[i].toBack = function() {
-            return this.removed ? this : (this.Group.parentNode.firstChild != this.Group && (this.Group.parentNode.insertBefore(this.Group, this.Group.parentNode.firstChild), kr(this, this.paper)), this)
-        };
-        u[i].insertAfter = function(n) {
-            return this.removed ? this : (n.Group.nextSibling ? n.Group.parentNode.insertBefore(this.Group, n.Group.nextSibling) : n.Group.parentNode[o](this.Group), dr(this, n, this.paper), this)
-        };
-        u[i].insertBefore = function(n) {
-            return this.removed ? this : (n.Group.parentNode.insertBefore(this.Group, n.Group), gr(this, n, this.paper), this)
-        };
-        cu = / progid:\S+Blur\([^\)]+\)/g;
-        u[i].blur = function(n) {
-            var t = this.node.style,
-                i = t.filter;
-            i = i.replace(cu, ""); + n != 0 ? (this.attrs.blur = n, t.filter = i + ki + ".Blur(pixelradius=" + (+n || 1.5) + ")", t.margin = Raphael.format("-{0}px 0 0 -{0}px", Math.round(+n || 1.5))) : (t.filter = i, t.margin = 0, delete this.attrs.blur)
-        };
-        ru = function(n, t, i, r) {
-            var e = it("group"),
-                f = it("oval");
-            return e.style.cssText = "position:absolute;left:0;top:0;width:" + n.width + "px;height:" + n.height + "px", e.coordsize = ui, e.coordorigin = n.coordorigin, e[o](f), f = new u(f, e, n), f.type = "circle", vt(f, {
-                stroke: "#000",
-                fill: "none"
-            }), f.attrs.cx = t, f.attrs.cy = i, f.attrs.r = r, f.setBox({
-                x: t - r,
-                y: i - r,
-                width: r * 2,
-                height: r * 2
-            }), n.canvas[o](e), f
-        };
-
-        function lu(t, i, r, u, f) {
-            return f ? n.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z", t + f, i, r - f * 2, f, -f, u - f * 2, f * 2 - r, f * 2 - u) : n.format("M{0},{1}l{2},0,0,{3},{4},0z", t, i, r, u, -r)
-        }
-        uu = function(n, t, i, r, u, f) {
-            var o = lu(t, i, r, u, f),
-                e;
-            return n = n.path(o), e = n.attrs, n.X = e.x = t, n.Y = e.y = i, n.W = e.width = r, n.H = e.height = u, e.r = f, e.path = o, n.type = "rect", n
-        };
-        fu = function(n, t, i, r, f) {
-            var s = it("group"),
-                e = it("oval");
-            return s.style.cssText = "position:absolute;left:0;top:0;width:" + n.width + "px;height:" + n.height + "px", s.coordsize = ui, s.coordorigin = n.coordorigin, s[o](e), e = new u(e, s, n), e.type = "ellipse", vt(e, {
-                stroke: "#000"
-            }), e.attrs.cx = t, e.attrs.cy = i, e.attrs.rx = r, e.attrs.ry = f, e.setBox({
-                x: t - r,
-                y: i - f,
-                width: r * 2,
-                height: f * 2
-            }), n.canvas[o](s), e
-        };
-        eu = function(n, t, i, r, f, e) {
-            var h = it("group"),
-                s = it("image");
-            return h.style.cssText = "position:absolute;left:0;top:0;width:" + n.width + "px;height:" + n.height + "px", h.coordsize = ui, h.coordorigin = n.coordorigin, s.src = t, h[o](s), s = new u(s, h, n), s.type = "image", s.attrs.src = t, s.attrs.x = i, s.attrs.y = r, s.attrs.w = f, s.attrs.h = e, s.setBox({
-                x: i,
-                y: r,
-                width: f,
-                height: e
-            }), n.canvas[o](h), s
-        };
-        ou = function(t, i, f, e) {
-            var h = it("group"),
-                c = it("shape"),
-                s = c.style,
-                l = it("path"),
-                a = it("textpath");
-            return h.style.cssText = "position:absolute;left:0;top:0;width:" + t.width + "px;height:" + t.height + "px", h.coordsize = ui, h.coordorigin = t.coordorigin, l.v = n.format("m{0},{1}l{2},{1}", v(i * 10), v(f * 10), v(i * 10) + 1), l.textpathok = !0, s.width = t.width, s.height = t.height, a.string = e + r, a.on = !0, c[o](a), c[o](l), h[o](c), s = new u(a, h, t), s.shape = c, s.textpath = l, s.type = "text", s.attrs.text = e, s.attrs.x = i, s.attrs.y = f, s.attrs.w = 1, s.attrs.h = 1, vt(s, {
-                font: oi.font,
-                stroke: "none",
-                fill: "#000"
-            }), s.setBox(), t.canvas[o](h), s
-        };
-        su = function(n, t) {
-            var i = this.canvas.style;
-            return n == +n && (n += "px"), t == +t && (t += "px"), i.width = n, i.height = t, i.clip = "rect(0 " + n + " " + t + " 0)", this
-        };
-        c.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
-        try {
-            c.namespaces.rvml || c.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
-            it = function(n) {
-                return c.createElement("<rvml:" + n + ' class="rvml">')
-            }
-        } catch (pf) {
-            it = function(n) {
-                return c.createElement("<" + n + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">')
-            }
-        }
-        rr = function() {
-            var i = wr[b](0, arguments),
-                r = i.container,
-                u = i.height,
-                f = i.width,
-                h = i.x;
-            if (i = i.y, !r) throw new Error("VML container not found.");
-            var t = new y,
-                e = t.canvas = c.createElement("div"),
-                s = e.style;
-            return h = h || 0, i = i || 0, f = f || 512, u = u || 342, f == +f && (f += "px"), u == +u && (u += "px"), t.width = 1e3, t.height = 1e3, t.coordsize = ni * 1e3 + g + ni * 1e3, t.coordorigin = "0 0", t.span = c.createElement("span"), t.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;", e[o](t.span), s.cssText = n.format("width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", f, u), r == 1 ? (c.body[o](e), s.left = h + "px", s.top = i + "px", s.position = "absolute") : r.firstChild ? r.insertBefore(e, r.firstChild) : r[o](e), nr.call(t, t, n.fn), t
-        };
-        y[i].clear = function() {
-            this.canvas.innerHTML = r;
-            this.span = c.createElement("span");
-            this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
-            this.canvas[o](this.span);
-            this.bottom = this.top = null
-        };
-        y[i].remove = function() {
-            this.canvas.parentNode.removeChild(this.canvas);
-            for (var n in this) this[n] = nu(n);
-            return !0
-        }
-    }
-    for (y[i].safari = /^Apple|^Google/.test(st.navigator.vendor) && (!(st.navigator.userAgent.indexOf("Version/4.0") + 1) || st.navigator.platform.slice(0, 2) == "iP") ? function() {
-            var n = this.rect(-99, -99, this.width + 99, this.height + 99);
-            st.setTimeout(function() {
-                n.remove()
-            })
-        } : function() {}, au = function() {
-            return c.addEventListener ? function(n, t, i, r) {
-                function f(u) {
-                    if (wi && bi[s](t))
-                        for (var f = 0, e = u.targetTouches && u.targetTouches.length; f < e; f++)
-                            if (u.targetTouches[f].target == n) {
-                                e = u;
-                                u = u.targetTouches[f];
-                                u.originalEvent = e;
-                                u.preventDefault = lf;
-                                u.stopPropagation = vf;
-                                break
-                            }
-                    return i.call(r, u)
-                }
-                var u = wi && bi[t] ? bi[t] : t;
-                return n.addEventListener(u, f, !1),
-                    function() {
-                        return n.removeEventListener(u, f, !1), !0
-                    }
-            } : c.attachEvent ? function(n, t, i, r) {
-                function u(n) {
-                    return n = n || st.event, n.preventDefault = n.preventDefault || cf, n.stopPropagation = n.stopPropagation || af, i.call(r, n)
-                }
-
-                function f() {
-                    return n.detachEvent("on" + t, u), !0
-                }
-                return n.attachEvent("on" + t, u), f
-            } : void 0
-        }(), bt = hr[t]; bt--;)(function(r) {
-        n[r] = u[i][r] = function(t) {
-            return n.is(t, "function") && (this.events = this.events || [], this.events.push({
-                name: r,
-                f: t,
-                unbind: au(this.shape || this.node || c, r, t, this)
-            })), this
-        };
-        n["un" + r] = u[i]["un" + r] = function(n) {
-            for (var i = this.events, u = i[t]; u--;)
-                if (i[u].name == r && i[u].f == n) return i[u].unbind(), i.splice(u, 1), i.length || delete this.events, this;
-            return this
-        }
-    })(hr[bt]);
-    u[i].hover = function(n, t) {
-        return this.mouseover(n).mouseout(t)
-    };
-    u[i].unhover = function(n, t) {
-        return this.unmouseover(n).unmouseout(t)
-    };
-    u[i].drag = function(n, t, i) {
-        function u(t) {
-            var u = t.clientX,
-                f = t.clientY,
-                e, i;
-            if (wi) {
-                for (e = t.touches.length; e--;)
-                    if (i = t.touches[e], i.identifier == r._drag.id) {
-                        u = i.clientX;
-                        f = i.clientY;
-                        (t.originalEvent ? t.originalEvent : t).preventDefault();
-                        break
-                    }
-            } else t.preventDefault();
-            n && n.call(r, u - r._drag.x, f - r._drag.y, u, f)
-        }
-
-        function f() {
-            r._drag = {};
-            Raphael.unmousemove(u).unmouseup(f);
-            i && i.call(r)
-        }
-        this._drag = {};
-        var r = this.mousedown(function(n) {
-            (n.originalEvent ? n.originalEvent : n).preventDefault();
-            this._drag.x = n.clientX;
-            this._drag.y = n.clientY;
-            this._drag.id = n.identifier;
-            t && t.call(this, n.clientX, n.clientY);
-            Raphael.mousemove(u).mouseup(f)
-        });
-        return this
-    };
-    y[i].circle = function(n, t, i) {
-        return ru(this, n || 0, t || 0, i || 0)
-    };
-    y[i].rect = function(n, t, i, r, u) {
-        return uu(this, n || 0, t || 0, i || 0, r || 0, u || 0)
-    };
-    y[i].ellipse = function(n, t, i, r) {
-        return fu(this, n || 0, t || 0, i || 0, r || 0)
-    };
-    y[i].path = function(t) {
-        return !t || n.is(t, wt) || n.is(t[0], et) || (t += r), tu(n.format[b](n, arguments), this)
-    };
-    y[i].image = function(n, t, i, r, u) {
-        return eu(this, n || "about:blank", t || 0, i || 0, r || 0, u || 0)
-    };
-    y[i].text = function(n, t, i) {
-        return ou(this, n || 0, t || 0, i || r)
-    };
-    y[i].set = function(n) {
-        return arguments[t] > 1 && (n = Array[i].splice.call(arguments, 0, arguments[t])), new ct(n)
-    };
-    y[i].setSize = su;
-    y[i].top = y[i].bottom = null;
-    y[i].raphael = n;
-    u[i].resetScale = function() {
-        if (this.removed) return this;
-        this._.sx = 1;
-        this._.sy = 1;
-        this.attrs.scale = "1 1"
-    };
-    u[i].scale = function(n, i, u, f) {
-        var a, o, h, nt, it, l, s, w;
-        if (this.removed) return this;
-        if (n == null && i == null) return {
-            x: this._.sx,
-            y: this._.sy,
-            toString: vu
-        };
-        if (i = i || n, +i || (i = n), h = this.attrs, n != 0) {
-            var c = this.getBBox(),
-                v = c.x + c.width / 2,
-                p = c.y + c.height / 2;
-            a = n / this._.sx;
-            o = i / this._.sy;
-            u = +u || u == 0 ? u : v;
-            f = +f || f == 0 ? f : p;
-            c = ~~(n / e.abs(n));
-            var y = ~~(i / e.abs(i)),
-                rt = this.node.style,
-                d = u + (v - u) * a;
-            p = f + (p - f) * o;
-            switch (this.type) {
-                case "rect":
-                case "image":
-                    nt = h.width * c * a;
-                    it = h.height * y * o;
-                    this.attr({
-                        height: it,
-                        r: h.r * lt(c * a, y * o),
-                        width: nt,
-                        x: d - nt / 2,
-                        y: p - it / 2
-                    });
-                    break;
-                case "circle":
-                case "ellipse":
-                    this.attr({
-                        rx: h.rx * c * a,
-                        ry: h.ry * y * o,
-                        r: h.r * lt(c * a, y * o),
-                        cx: d,
-                        cy: p
-                    });
-                    break;
-                case "text":
-                    this.attr({
-                        x: d,
-                        y: p
-                    });
-                    break;
-                case "path":
-                    v = gi(h.path);
-                    for (var ut = !0, b = 0, ft = v[t]; b < ft; b++)
-                        if (l = v[b], s = ei.call(l[0]), !(s == "M" && ut))
-                            if (ut = !1, s == "A") l[v[b][t] - 2] *= a, l[v[b][t] - 1] *= o, l[1] *= c * a, l[2] *= y * o, l[5] = +!(c + y ? !+l[5] : +l[5]);
-                            else if (s == "H")
-                        for (s = 1, w = l[t]; s < w; s++) l[s] *= a;
-                    else if (s == "V")
-                        for (s = 1, w = l[t]; s < w; s++) l[s] *= o;
-                    else
-                        for (s = 1, w = l[t]; s < w; s++) l[s] *= s % 2 ? a : o;
-                    o = ti(v);
-                    a = d - o.x - o.width / 2;
-                    o = p - o.y - o.height / 2;
-                    v[0][1] += a;
-                    v[0][2] += o;
-                    this.attr({
-                        path: v
-                    })
-            }
-            this.type in {
-                text: 1,
-                image: 1
-            } && (c != 1 || y != 1) ? this.transformations ? (this.transformations[2] = "scale(" [k](c, ",", y, ")"), this.node[ot]("transform", this.transformations[tt](g)), a = c == -1 ? -h.x - (nt || 0) : h.x, o = y == -1 ? -h.y - (it || 0) : h.y, this.attr({
-                x: a,
-                y: o
-            }), h.fx = c - 1, h.fy = y - 1) : (this.node.filterMatrix = ki + ".Matrix(M11=" [k](c, ", M12=0, M21=0, M22=", y, ", Dx=0, Dy=0, sizingmethod='auto expand', filtertype='bilinear')"), rt.filter = (this.node.filterMatrix || r) + (this.node.filterOpacity || r)) : this.transformations ? (this.transformations[2] = r, this.node[ot]("transform", this.transformations[tt](g)), h.fx = 0, h.fy = 0) : (this.node.filterMatrix = r, rt.filter = (this.node.filterMatrix || r) + (this.node.filterOpacity || r));
-            h.scale = [n, i, u, f][tt](g);
-            this._.sx = n;
-            this._.sy = i
-        }
-        return this
-    };
-    u[i].clone = function() {
-        if (this.removed) return null;
-        var n = this.attr();
-        return delete n.scale, delete n.translation, this.paper[this.type]().attr(n)
-    };
-    ur = ut(function(t, i, r, u, f, e, o, s, h) {
-        for (var y, a, v = 0, c = 0; c < 1.001; c += .001) {
-            if (a = n.findDotsAtSegment(t, i, r, u, f, e, o, s, c), c && (v += l(l(y.x - a.x, 2) + l(y.y - a.y, 2), .5)), v >= h) return a;
-            y = a
-        }
-    });
-    var yf = ut(function(n, t, i, r, u, f, e, o) {
-            for (var h, c = {
-                    x: 0,
-                    y: 0
-                }, a = 0, s = 0; s < 1.01; s += .01) h = ii(n, t, i, r, u, f, e, o, s), s && (a += l(l(c.x - h.x, 2) + l(c.y - h.y, 2), .5)), c = h;
-            return a
-        }),
-        yu = fr(1),
-        vi = fr(),
-        er = fr(0, 1);
-    u[i].getTotalLength = function() {
-        if (this.type == "path") return this.node.getTotalLength ? this.node.getTotalLength() : yu(this.attrs.path)
-    };
-    u[i].getPointAtLength = function(n) {
-        if (this.type == "path") return vi(this.attrs.path, n)
-    };
-    u[i].getSubpath = function(n, t) {
-        if (this.type == "path") return e.abs(this.getTotalLength() - t) < 1e-6 ? er(this.attrs.path, n).end : (t = er(this.attrs.path, t, 1), n ? er(t, n).end : t)
-    };
-    n.easing_formulas = {
-        linear: function(n) {
-            return n
-        },
-        "<": function(n) {
-            return l(n, 3)
-        },
-        ">": function(n) {
-            return l(n - 1, 3) + 1
-        },
-        "<>": function(n) {
-            return (n *= 2, n < 1) ? l(n, 3) / 2 : (n -= 2, (l(n, 3) + 2) / 2)
-        },
-        backIn: function(n) {
-            var t = 1.70158;
-            return n * n * ((t + 1) * n - t)
-        },
-        backOut: function(n) {
-            n -= 1;
-            var t = 1.70158;
-            return n * n * ((t + 1) * n + t) + 1
-        },
-        elastic: function(n) {
-            if (n == 0 || n == 1) return n;
-            var t = .3,
-                i = t / 4;
-            return l(2, -10 * n) * e.sin((n - i) * 2 * e.PI / t) + 1
-        },
-        bounce: function(n) {
-            var i = 7.5625,
-                t = 2.75;
-            return n < 1 / t ? n = i * n * n : n < 2 / t ? (n -= 1.5 / t, n = i * n * n + .75) : n < 2.5 / t ? (n -= 2.25 / t, n = i * n * n + .9375) : (n -= 2.625 / t, n = i * n * n + .984375), n
-        }
-    };
-    rt = {
-        length: 0
-    };
-    u[i].animateWith = function(n, t, i, r, u) {
-        return rt[n.id] && (t.start = rt[n.id].start), this.animate(t, i, r, u)
-    };
-    u[i].animateAlong = wu();
-    u[i].animateAlongBack = wu(1);
-    u[i].onAnimation = function(n) {
-        return this._run = n || 0, this
-    };
-    u[i].animate = function(i, u, f, e) {
-        var o, w, k;
-        (n.is(f, "function") || !f) && (e = f || null);
-        var l = {},
-            y = {},
-            a = {};
-        for (o in i)
-            if (i[s](o) && di[s](o)) {
-                l[o] = this.attr(o);
-                l[o] == null && (l[o] = oi[o]);
-                y[o] = i[o];
-                switch (di[o]) {
-                    case "along":
-                        var c = yu(i[o]),
-                            v = vi(i[o], c * !!i.back),
-                            b = this.getBBox();
-                        a[o] = c / u;
-                        a.tx = b.x;
-                        a.ty = b.y;
-                        a.sx = v.x;
-                        a.sy = v.y;
-                        y.rot = i.rot;
-                        y.back = i.back;
-                        y.len = c;
-                        i.rot && (a.r = h(this.rotate()) || 0);
-                        break;
-                    case nt:
-                        a[o] = (y[o] - l[o]) / u;
-                        break;
-                    case "colour":
-                        l[o] = n.getRGB(l[o]);
-                        c = n.getRGB(y[o]);
-                        a[o] = {
-                            r: (c.r - l[o].r) / u,
-                            g: (c.g - l[o].g) / u,
-                            b: (c.b - l[o].b) / u
-                        };
-                        break;
-                    case "path":
-                        for (c = ai(l[o], y[o]), l[o] = c[0], v = c[1], a[o] = [], c = 0, b = l[o][t]; c < b; c++)
-                            for (a[o][c] = [0], w = 1, k = l[o][c][t]; w < k; w++) a[o][c][w] = (v[c][w] - l[o][c][w]) / u;
-                        break;
-                    case "csv":
-                        v = (i[o] + r)[p](ft);
-                        c = (l[o] + r)[p](ft);
-                        switch (o) {
-                            case "translation":
-                                l[o] = [0, 0];
-                                a[o] = [v[0] / u, v[1] / u];
-                                break;
-                            case "rotation":
-                                l[o] = c[1] == v[1] && c[2] == v[2] ? c : [0, v[1], v[2]];
-                                a[o] = [(v[0] - l[o][0]) / u, 0, 0];
-                                break;
-                            case "scale":
-                                i[o] = v;
-                                l[o] = (l[o] + r)[p](ft);
-                                a[o] = [(v[0] - l[o][0]) / u, (v[1] - l[o][1]) / u, 0, 0];
-                                break;
-                            case "clip-rect":
-                                for (l[o] = (l[o] + r)[p](ft), a[o] = [], c = 4; c--;) a[o][c] = (v[c] - l[o][c]) / u
-                        }
-                        y[o] = v
-                }
-            }
-        return this.stop(), this.in_animation = 1, rt[this.id] = {
-            start: i.start || +new Date,
-            ms: u,
-            easing: f,
-            from: l,
-            diff: a,
-            to: y,
-            el: this,
-            callback: e,
-            t: {
-                x: 0,
-                y: 0
-            }
-        }, ++rt[t] == 1 && pu(), this
-    };
-    u[i].stop = function() {
-        return rt[this.id] && rt[t]--, delete rt[this.id], this
-    };
-    u[i].translate = function(n, t) {
-        return this.attr({
-            translation: n + " " + t
-        })
-    };
-    u[i][d] = function() {
-        return "Raphaël’s object"
-    };
-    n.ae = rt;
-    ct[i][a] = function() {
-        for (var n, i, r = 0, f = arguments[t]; r < f; r++)(n = arguments[r]) && (n.constructor == u || n.constructor == ct) && (i = this.items[t], this[i] = this.items[i] = n, this[t]++);
-        return this
-    };
-    ct[i].pop = function() {
-        return delete this[this[t]--], this.items.pop()
-    };
-    for (pi in u[i]) u[i][s](pi) && (ct[i][pi] = function(n) {
-        return function() {
-            for (var i = 0, r = this.items[t]; i < r; i++) this.items[i][n][b](this.items[i], arguments);
-            return this
-        }
-    }(pi));
-    return ct[i].attr = function(i, r) {
-        var u, f;
-        if (i && n.is(i, et) && n.is(i[0], "object"))
-            for (r = 0, u = i[t]; r < u; r++) this.items[r].attr(i[r]);
-        else
-            for (u = 0, f = this.items[t]; u < f; u++) this.items[u].attr(i, r);
-        return this
-    }, ct[i].animate = function(i, r, u, f) {
-        (n.is(u, "function") || !u) && (f = u || null);
-        var s = this.items[t],
-            o = s,
-            h, c = this,
-            e;
-        for (f && (e = function() {
-                --s || f.call(c)
-            }), u = n.is(u, wt) ? u : e, h = this.items[--o].animate(i, r, u, e); o--;) this.items[o].animateWith(h, i, r, u, e);
-        return this
-    }, ct[i].insertAfter = function(n) {
-        for (var i = this.items[t]; i--;) this.items[i].insertAfter(n);
-        return this
-    }, ct[i].getBBox = function() {
-        for (var n, i = [], r = [], u = [], f = [], e = this.items[t]; e--;) n = this.items[e].getBBox(), i[a](n.x), r[a](n.y), u[a](n.x + n.width), f[a](n.y + n.height);
-        return i = lt[b](0, i), r = lt[b](0, r), {
-            x: i,
-            y: r,
-            width: ht[b](0, u) - i,
-            height: ht[b](0, f) - r
-        }
-    }, ct[i].clone = function(n) {
-        n = new ct;
-        for (var i = 0, r = this.items[t]; i < r; i++) n[a](this.items[i].clone());
-        return n
-    }, n.registerFont = function(n) {
-        var i, t, u, r, f;
-        if (!n.face) return n;
-        this.fonts = this.fonts || {};
-        i = {
-            w: n.w,
-            face: {},
-            glyphs: {}
-        };
-        t = n.face["font-family"];
-        for (u in n.face) n.face[s](u) && (i.face[u] = n.face[u]);
-        if (this.fonts[t] ? this.fonts[t][a](i) : this.fonts[t] = [i], !n.svg) {
-            i.face["units-per-em"] = pt(n.face["units-per-em"], 10);
-            for (r in n.glyphs)
-                if (n.glyphs[s](r) && (t = n.glyphs[r], i.glyphs[r] = {
-                        w: t.w,
-                        k: {},
-                        d: t.d && "M" + t.d[w](/[mlcxtrv]/g, function(n) {
-                            return {
-                                l: "L",
-                                c: "C",
-                                x: "z",
-                                t: "m",
-                                r: "l",
-                                v: "c"
-                            }[n] || "M"
-                        }) + "z"
-                    }, t.k))
-                    for (f in t.k) t[s](f) && (i.glyphs[r].k[f] = t.k[f])
-        }
-        return n
-    }, y[i].getFont = function(i, u, f, e) {
-        var h, o, c;
-        if (e = e || "normal", f = f || "normal", u = +u || {
-                normal: 400,
-                bold: 700,
-                lighter: 300,
-                bolder: 800
-            }[u] || 400, n.fonts) {
-            if (h = n.fonts[i], !h) {
-                i = new RegExp("(^|\\s)" + i[w](/[^\w\d\s+!~.:_-]/g, r) + "(\\s|$)", "i");
-                for (o in n.fonts)
-                    if (n.fonts[s](o) && i.test(o)) {
-                        h = n.fonts[o];
-                        break
-                    }
-            }
-            if (h)
-                for (o = 0, i = h[t]; o < i; o++)
-                    if (c = h[o], c.face["font-weight"] == u && (c.face["font-style"] == f || !c.face["font-style"]) && c.face["font-stretch"] == e) break;
-            return c
-        }
-    }, y[i].print = function(i, u, f, e, o, s) {
-        var h, b, l, v;
-        s = s || "middle";
-        var y = this.set(),
-            c = (f + r)[p](r),
-            w = 0;
-        if (n.is(e, f) && (e = this.getFont(e)), e) {
-            for (f = (o || 16) / e.face["units-per-em"], h = e.face.bbox.split(ft), o = +h[0], s = +h[1] + (s == "baseline" ? h[3] - h[1] + +e.face.descent : (h[3] - h[1]) / 2), h = 0, b = c[t]; h < b; h++) l = h && e.glyphs[c[h - 1]] || {}, v = e.glyphs[c[h]], w += h ? (l.w || e.w) + (l.k && l.k[c[h]] || 0) : 0, v && v.d && y[a](this.path(v.d).attr({
-                fill: "#000",
-                stroke: "none",
-                translation: [w, 0]
-            }));
-            y.scale(f, f, o, s).translate(i - o, u - s)
-        }
-        return y
-    }, bu = /\{(\d+)\}/g, n.format = function(i, u) {
-        var f = n.is(u, et) ? [0][k](u) : arguments;
-        return i && n.is(i, wt) && f[t] - 1 && (i = i[w](bu, function(n, t) {
-            return f[++t] == null ? r : f[t]
-        })), i || r
-    }, n.ninja = function() {
-        return sr.was ? Raphael = sr.is : delete Raphael, n
-    }, n.el = u[i], n
-}();
-dateTimeFromServer = new Date;
-dateTimeFromClient = new Date;
-$(document).ready(function() {
-    function n(n) {
-        return n < 10 ? "0" + n.toString() : n.toString()
-    }
-    $(".multiMenu").hover(function() {
-        mouse_is_inside = !0
-    }, function() {
-        mouse_is_inside = !1
-    });
-    $("body").mouseup(function() {
-        mouse_is_inside || $(".multiMenu .layer").slideUp(function() {
-            $(this).parent("div").removeClass("active")
-        })
-    });
-    try {
-        $.ajax({
-            url: "/Home/BiezacaDataGodzina",
-            type: "GET",
-            async: !1,
-            cache: !1,
-            success: function(n) {
-                dateTimeFromServer = new Date(parseInt(n.substr(6)));
-                dateTimeFromClient = new Date
-            }
-        })
-    } catch (t) {}
-    setInterval(function() {
-        var u = dateTimeFromServer - dateTimeFromClient,
-            f = (new Date).getTime(),
-            r = new Date,
-            t, i;
-        r.setTime(f + u);
-        t = r;
-        t.setDate(t.getDate());
-        var e = t.getDate(),
-            o = t.getMonth() + 1,
-            s = t.getFullYear(),
-            h = n(e) + " - " + n(o) + " - " + s;
-        $("#date").html(h);
-        i = r;
-        i.setDate(i.getDate());
-        var c = i.getHours(),
-            l = i.getMinutes(),
-            a = n(c) + ":" + n(l);
-        $("#time").html(a)
-    }, 1e3);
-    $(".showDetails").click(function() {
-        $(this).prev(".details").slideToggle();
-        $(this).find(".gui").toggleClass("icoDArrDown icoDArrUp");
-        $(this).toggleClass("act")
-    });
-    indirectStation()
-});
-mouse_is_inside = !1,
-    function(n) {
-        n.cookies = {
-            render: function(t) {
-                var i = "";
-                i += '<div id="cookiesBar"><div id="cookiesBarWrap"><p>' + C_Cookie_Tekst_1;
-                i += t.privacyPolicy ? ' <a href="' + t.cookiesPageURL + '" title="' + C_Cookie_PolitykaPrywatnosciTitle + '">' + C_Cookie_PolitykaPrywatnosci + "<\/a>.<\/p>" : ' <a href="' + t.cookiesPageURL + '" title="' + C_Cookie_RegulaminSerwisu + '">' + C_Cookie_RegulaminSerwisu + "<\/a>.<\/p>";
-                i += "<p>" + C_Cookie_Tekst_2 + '<\/p><a id="cookiesBarClose" href="#" title="' + C_Cookie_Zamknij + '">' + C_Cookie_Zamknij + "<\/a><\/div><\/div>";
-                n.cookie("cookie") || (n("body").append(i), n.fn.delegate ? n("#cookiesBar").delegate("#cookiesBarClose", "click", function(t) {
-                    n.cookies.closeCallback(t)
-                }) : n("#cookiesBarClose").bind("click", function(t) {
-                    n.cookies.closeCallback(t)
-                }))
-            },
-            closeCallback: function(t) {
-                return n("#cookiesBar").fadeOut(), n.cookie("cookie") || n.cookie("cookie", !0, {
-                    path: "/",
-                    expires: 30
-                }), t.preventDefault(), !1
-            }
-        }
-    }(jQuery);
-String.prototype.replaceAll = function(n, t) {
-    return this.split(n).join(t)
-};
-$.ajaxSetup({
-    headers: {
-        "X-Kendo-Ui-Version": "r3-2016-sp2"
-    }
-});
-! function(n) {
-    function i() {
-        var i = document.createElement("smartbanner"),
-            n = {
-                WebkitTransition: "webkitTransitionEnd",
-                MozTransition: "transitionend",
-                OTransition: "oTransitionEnd otransitionend",
-                transition: "transitionend"
-            };
-        for (var t in n)
-            if (i.style[t] !== undefined) return {
-                end: n[t]
-            };
-        return !1
-    }
-    var t = function(t) {
-        var f, i, r, u;
-        if ((this.origHtmlMargin = parseFloat(n("html").css("margin-top")), this.options = n.extend({}, n.smartbanner.defaults, t), f = navigator.standalone, i = navigator.userAgent, this.options.force ? this.type = this.options.force : i.match(/Windows Phone 8/i) != null && i.match(/Touch/i) !== null ? this.type = "windows" : i.match(/iPhone|iPod/i) != null || i.match(/iPad/) && this.options.iOSUniversalApp ? i.match(/Safari/i) != null && (i.match(/CriOS/i) != null || window.Number(i.substr(i.indexOf("OS ") + 3, 3).replace("_", ".")) < 6) && (this.type = "ios") : i.match(/\bSilk\/(.*\bMobile Safari\b)?/) || i.match(/\bKF\w/) || i.match("Kindle Fire") ? this.type = "kindle" : i.match(/Android/i) != null && (this.type = "android"), this.type && !f && !this.getCookie("sb-closed") && !this.getCookie("sb-installed")) && (this.scale = this.options.scale == "auto" ? n(window).width() / window.screen.width : this.options.scale, this.scale < 1 && (this.scale = 1), r = n(this.type == "android" ? 'meta[name="google-play-app"]' : this.type == "ios" ? 'meta[name="apple-itunes-app"]' : this.type == "kindle" ? 'meta[name="kindle-fire-app"]' : 'meta[name="msApplication-ID"]'), r.length != 0)) {
-            if (this.type == "windows") this.appId = n('meta[name="msApplication-PackageFamilyName"]').attr("content");
-            else if (u = /app-id=([^\s,]+)/.exec(r.attr("content")), u) this.appId = u[1];
-            else return;
-            this.title = this.options.title ? this.options.title : r.data("title") || n("title").text().replace(/\s*[|\-·].*$/, "");
-            this.author = this.options.author ? this.options.author : r.data("author") || (n('meta[name="author"]').length ? n('meta[name="author"]').attr("content") : window.location.hostname);
-            this.iconUrl = r.data("icon-url");
-            this.price = r.data("price");
-            this.create();
-            this.show();
-            this.listen()
-        }
-    };
-    (t.prototype = {
-        constructor: t,
-        create: function() {
-            var t, i = this.options.url ? this.options.url : (this.type == "windows" ? "ms-windows-store:navigate?appid=" : this.type == "android" ? "market://details?id=" : this.type == "kindle" ? "amzn://apps/android?asin=" : "https://itunes.apple.com/" + this.options.appStoreLanguage + "/app/id") + this.appId,
-                u = this.price || this.options.price,
-                e = u ? u + " - " + (this.type == "android" ? this.options.inGooglePlay : this.type == "kindle" ? this.options.inAmazonAppStore : this.type == "ios" ? this.options.inAppStore : this.options.inWindowsStore) : "",
-                f = this.options.iconGloss === null ? this.type == "ios" : this.options.iconGloss,
-                r;
-            this.type == "android" && this.options.GooglePlayParams && (i = i + "&referrer=" + this.options.GooglePlayParams);
-            r = '<div id="smartbanner" class="' + this.type + '"><div class="sb-container"><a href="#" class="sb-close">&times;<\/a><span class="sb-icon"><\/span><div class="sb-info"><strong>' + this.title + "<\/strong><span>" + this.author + "<\/span><span>" + e + '<\/span><\/div><a href="' + i + '" class="sb-button"><span>' + this.options.button + "<\/span><\/a><\/div><\/div>";
-            this.options.layer ? n(this.options.appendToSelector).append(r) : n(this.options.appendToSelector).prepend(r);
-            this.options.icon ? t = this.options.icon : this.iconUrl ? t = this.iconUrl : n('link[rel="apple-touch-icon-precomposed"]').length > 0 ? (t = n('link[rel="apple-touch-icon-precomposed"]').attr("href"), this.options.iconGloss === null && (f = !1)) : n('link[rel="apple-touch-icon"]').length > 0 ? t = n('link[rel="apple-touch-icon"]').attr("href") : n('meta[name="msApplication-TileImage"]').length > 0 ? t = n('meta[name="msApplication-TileImage"]').attr("content") : n('meta[name="msapplication-TileImage"]').length > 0 && (t = n('meta[name="msapplication-TileImage"]').attr("content"));
-            t ? (n("#smartbanner .sb-icon").css("background-image", "url(" + t + ")"), f && n("#smartbanner .sb-icon").addClass("gloss")) : n("#smartbanner").addClass("no-icon");
-            this.bannerHeight = n("#smartbanner").outerHeight() + 2;
-            this.scale > 1 && (n("#smartbanner").css("top", parseFloat(n("#smartbanner").css("top")) * this.scale).css("height", parseFloat(n("#smartbanner").css("height")) * this.scale).hide(), n("#smartbanner .sb-container").css("-webkit-transform", "scale(" + this.scale + ")").css("-msie-transform", "scale(" + this.scale + ")").css("-moz-transform", "scale(" + this.scale + ")").css("width", n(window).width() / this.scale));
-            n("#smartbanner").css("position", this.options.layer ? "absolute" : "static")
-        },
-        listen: function() {
-            n("#smartbanner .sb-close").on("click", n.proxy(this.close, this));
-            n("#smartbanner .sb-button").on("click", n.proxy(this.install, this))
-        },
-        show: function(t) {
-            var i = n("#smartbanner"),
-                r;
-            i.stop();
-            this.options.layer ? (i.animate({
-                top: 0,
-                display: "block"
-            }, this.options.speedIn).addClass("shown").show(), n(this.pushSelector).animate({
-                paddingTop: this.origHtmlMargin + this.bannerHeight * this.scale
-            }, this.options.speedIn, "swing", t)) : n.support.transition ? (i.animate({
-                top: 0
-            }, this.options.speedIn).addClass("shown"), r = function() {
-                n("html").removeClass("sb-animation");
-                t && t()
-            }, n(this.pushSelector).addClass("sb-animation").one(n.support.transition.end, r).emulateTransitionEnd(this.options.speedIn).css("margin-top", this.origHtmlMargin + this.bannerHeight * this.scale)) : i.slideDown(this.options.speedIn).addClass("shown")
-        },
-        hide: function(t) {
-            var i = n("#smartbanner"),
-                r;
-            i.stop();
-            this.options.layer ? (i.animate({
-                top: -1 * this.bannerHeight * this.scale,
-                display: "block"
-            }, this.options.speedIn).removeClass("shown"), n(this.pushSelector).animate({
-                paddingTop: this.origHtmlMargin
-            }, this.options.speedIn, "swing", t)) : n.support.transition ? (this.type !== "android" ? i.css("top", -1 * this.bannerHeight * this.scale).removeClass("shown") : i.css({
-                display: "none"
-            }).removeClass("shown"), r = function() {
-                n("html").removeClass("sb-animation");
-                t && t()
-            }, n(this.pushSelector).addClass("sb-animation").one(n.support.transition.end, r).emulateTransitionEnd(this.options.speedOut).css("margin-top", this.origHtmlMargin)) : i.slideUp(this.options.speedOut).removeClass("shown")
-        },
-        close: function(n) {
-            n.preventDefault();
-            this.hide();
-            this.setCookie("sb-closed", "true", this.options.daysHidden)
-        },
-        install: function() {
-            this.options.hideOnInstall && this.hide();
-            this.setCookie("sb-installed", "true", this.options.daysReminder)
-        },
-        setCookie: function(n, t, i) {
-            var r = new Date;
-            r.setDate(r.getDate() + i);
-            t = encodeURI(t) + (i == null ? "" : "; expires=" + r.toUTCString());
-            document.cookie = n + "=" + t + "; path=/;"
-        },
-        getCookie: function(n) {
-            for (var r, u, i = document.cookie.split(";"), t = 0; t < i.length; t++)
-                if (r = i[t].substr(0, i[t].indexOf("=")), u = i[t].substr(i[t].indexOf("=") + 1), r = r.replace(/^\s+|\s+$/g, ""), r == n) return decodeURI(u);
-            return null
-        },
-        switchType: function() {
-            var t = this;
-            this.hide(function() {
-                t.type = t.type == "android" ? "ios" : "android";
-                var i = n(t.type == "android" ? 'meta[name="google-play-app"]' : 'meta[name="apple-itunes-app"]').attr("content");
-                t.appId = /app-id=([^\s,]+)/.exec(i)[1];
-                n("#smartbanner").detach();
-                t.create();
-                t.show()
-            })
-        }
-    }, n.smartbanner = function(i) {
-        var u = n(window),
-            r = u.data("smartbanner"),
-            f = typeof i == "object" && i;
-        r || u.data("smartbanner", r = new t(f));
-        typeof i == "string" && r[i]()
-    }, n.smartbanner.defaults = {
-        title: null,
-        author: null,
-        price: "FREE",
-        appStoreLanguage: "us",
-        inAppStore: "On the App Store",
-        inGooglePlay: "In Google Play",
-        inAmazonAppStore: "In the Amazon Appstore",
-        inWindowsStore: "In the Windows Store",
-        GooglePlayParams: null,
-        icon: null,
-        iconGloss: null,
-        button: "VIEW",
-        url: null,
-        scale: "auto",
-        speedIn: 300,
-        speedOut: 400,
-        daysHidden: 15,
-        daysReminder: 90,
-        force: null,
-        hideOnInstall: !0,
-        layer: !1,
-        iOSUniversalApp: !0,
-        appendToSelector: "body",
-        pushSelector: "html"
-    }, n.smartbanner.Constructor = t, n.support.transition === undefined) && (n.fn.emulateTransitionEnd = function(t) {
-        var i = !1,
-            u = this,
-            r;
-        n(this).one(n.support.transition.end, function() {
-            i = !0
-        });
-        return r = function() {
-            i || n(u).trigger(n.support.transition.end)
-        }, setTimeout(r, t), this
-    }, n(function() {
-        n.support.transition = i()
-    }):)
-}(window.jQuery)




diff --git a/research/Specyfikacja-GTFS-07.12.2017.pdf b/research/Specyfikacja-GTFS-07.12.2017.pdf
deleted file mode 100644
index 0655f1a852018ad8d5a55c9aaa09360f3097e118..0000000000000000000000000000000000000000
Binary files a/research/Specyfikacja-GTFS-07.12.2017.pdf and /dev/null differ




diff --git a/research/datasources.md b/research/datasources.md
deleted file mode 100644
index 80149196a6eed388c865b5e4a69baef698bdef38..0000000000000000000000000000000000000000
--- a/research/datasources.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# Poznań API
-
-* bicycles: http://egov.psnc.pl/node/29#stacje-rowerow-miejskich
-* tickets: http://egov.psnc.pl/node/29#punkty-sprzedazy-biletow & http://egov.psnc.pl/node/29#biletomaty
-* car park automats: http://egov.psnc.pl/node/29#parkomaty
-* real-time timetable: http://egov.psnc.pl/node/29#przystanki
-* wireless: http://egov.psnc.pl/node/29#wireless_poznan
-* tourism: http://egov.psnc.pl/node/29#turystyka
-* P&R: https://www.peka.poznan.pl/SOP/parkings/getAvailableSpaces.jspb
-* accidents: https://mympk.mpk.poznan.pl/web/menu
-* 
-* news:
-*   https://mympk.mpk.poznan.pl/web/categories/aktualnosci [json/html]
-*   https://ztm.poznan.pl/aktualnosci/rss [rss/html]
-* accidents:
-*   https://mympk.mpk.poznan.pl/web/categories/zdarzenia-komunikacyjne [json/html]
-*   https://ztm.poznan.pl/komunikaty/rss [rss/html]




diff --git a/research/peka-vm-api.md b/research/peka-vm-api.md
deleted file mode 100644
index d459a9f1fead3f2bf7e1c98bc8c50f18d19eb012..0000000000000000000000000000000000000000
--- a/research/peka-vm-api.md
+++ /dev/null
@@ -1,524 +0,0 @@
-# Ostrzeżenie
-
-Autor tego dokumentu nie jest w jakikolwiek sposób powiązany z ZTM, a informacje służące do jego napisania zostały pozyskane przez analizę kodu wykorzystywanego przez stronę http://www.peka.poznan.pl/vm oraz pakietów wymienianych między serwerem i klientem podczas korzystania z niej.
-
-# Zapytanie
-
-Zapytanie wykonywane jest przez HTTP do hosta www.peka.poznan.pl i zasobu `/vm/method.vm` , z parametrem `ts` przekazywanym przez `GET` i zawierającym wynik javascriptowej `new Date().getTime()`. `Content-Type` zapytania musi być ustawione na `application/x-www-form-urlencoded; charset=UTF-8`, w przeciwnym razie znaki spoza standardowego zakresu ASCII nie będą działały poprawnie.
-
-Wszystkie znaki kodowane są jako UTF-8.
-
-Dane `POST` zapytania instruują serwer odnośnie funkcji, którą ma on wykonać. Nazwa funkcji mieści się w parametrze `method`, natomiast jej parametry jako JSON w `p0`. Implementacja przepuszcza jeszcze to, co idzie do `p0` przez `Object.toJSON`, ale serwer nie zdaje się zwracać na to uwagi.
-
-Wygląda na to, że serwer zawsze zwraca 200 OK, nawet gdy wywoła się funkcję, której nie posiada : jako wynik zapytania jest wtedy zwracany pusty JSON.
-
-Podanie niepoprawnych parametrów do funkcji kończy się zwróceniem obiektu JSON zawierającego komunikat błędu w atrybucie `failure`, np. :
-```javascript
-{  
-   "failure":"error: java.lang.reflect.InvocationTargetException"
-}
-```
-
-Poprawne wywołanie funkcji kończy się przesłaniem obiektu zawierającego w sobie obiekt `success`, którego znaczenie jest uzależnione od wywołanej funkcji. Obiekt ten jest pomijany w tym dokumencie w opisie wyjścia danej funkcji.
-
-W przykładach wykorzystywana jest funkcja `peka_vm_get`, której definicja w Bashu wygląda następująco :
-```bash
-peka_vm_get()
-{
-  curl -H 'Content-Type:application/x-www-form-urlencoded; charset=UTF-8' \
-    http://www.peka.poznan.pl/vm/method.vm?ts=$(($(date +'%s') * 1000)) \
-    -d "method=$1" \
-    -d "p0=$2"
-}
-```
-
-Jeśli parametr wejściowy jakiejś funkcji jest "wzorcem", należy go rozumieć jak wyszukiwanie z glob-gwiazdkami po obu stronach wzorca. Wielkość liter jest ignorowana. Powinno być to widoczne w przykładach.
-
-# Słowniczek
-* *bollard* - coś, co najwygodniej chyba wytłumaczyć jako "słupek". Jest to fizyczne miejsce, w którym zatrzymują się pojazdy. Na jeden przystanek może przypadać więcej niż jeden bollard : jeden dla pojazdów jadących w jednym kierunku, a drugi - w drugim. Dochodzą do tego jeszcze osobne punkty przystankowe dla linii nocnych. Przystanek AWF ma na przykład aż siedem takich punktów : dwa tramwajowe na Królowej Jadwigi, jeden tramwajowy na Garbarach, i autobusowe rozrzucone w różnych miejscach.
-
-# Funkcje
-## `getStopPoints`
-Pobiera listę przystanków o nazwie pasującej do zadanego wzorca.
-### Wejście
-* `pattern` - wzorzec, według którego serwer ma szukać przystanku.
-
-### Wyjście
-Tablica zawierająca obiekty, w których mamy :
-* `symbol` - identyfikator przystanku używany do późniejszych zapytań
-* `name` - pełna nazwa przystanku.
-
-### Przykład
-```
-peka_vm_get getStopPoints '{"pattern":"Pół"}'
-```
-```javascript
-{  
-   "success":[  
-      {  
-         "symbol":"BOZSZ",
-         "name":"Bolechowo-Os./Zespół Szkół"
-      },
-      {  
-         "symbol":"PRPLN",
-         "name":"Promnice/Północna"
-      },
-      {  
-         "symbol":"POLW",
-         "name":"Półwiejska"
-      }
-   ]
-}
-```
-
-## `getBollards`
-Chyba nieużywana. Dla pustego obiektu przesłanego w zapytaniu pobiera wszystkie bollardy.
-
-## `getBollardsByStopPoint`
-Zwraca listę bollardów dla danego przystanku i listę linii odjeżdżających z niego.
-
-### Wejście
-* `name` : nazwa przystanku, zwrócona w `getStopPoints`
-
-### Wyjście
-Obiekt `bollards`, będący tablicą obiektów `bollard` (opisanym w `getTimes`) i `directions`, który sam jest tablicą obiektów zawierających :
-* `returnVariant` : jakiś bool, z tego co widziałem prawie zawsze false.
-* `lineName` : nazwa linii odjeżdżającej z danego punktu,
-* `direction` : kierunek tejże linii.
-
-### Przykład
-```
-peka_vm_get getBollardsByStopPoint '{"name":"Termy Maltańskie"}'
-```
-```javascript
-{  
-   "success":{  
-      "bollards":[  
-         {  
-            "directions":[  
-               {  
-                  "returnVariant":false,
-                  "direction":"Rondo Rataje",
-                  "lineName":"84"
-               },
-               {  
-                  "returnVariant":false,
-                  "direction":"Termy Maltańskie",
-                  "lineName":"84"
-               },
-               {  
-                  "returnVariant":false,
-                  "direction":"Rondo Śródka",
-                  "lineName":"84"
-               },
-               {  
-                  "returnVariant":false,
-                  "direction":"Nowe ZOO",
-                  "lineName":"84"
-               }
-            ],
-            "bollard":{  
-               "symbol":"TEMA22",
-               "tag":"TEMA01",
-               "name":"Termy Maltańskie",
-               "mainBollard":false
-            }
-         }
-      ]
-   }
-}
-```
-
-## `getBollardsByStreet`
-Zwraca listę bollardów znajdujących się przy zadanej ulicy.
-
-### Wejście
-* `name` : nazwa ulicy
-
-### Wyjście
-To samo, co przy `getBollardsByStopPoint`.
-
-### Przykład
-```
-peka_vm_get getBollardsByStreet '{"name":"Lutycka"}'
-```
-```javascript
-{  
-   "success":{  
-      "bollards":[  
-         {  
-            "directions":[  
-               {  
-                  "returnVariant":false,
-                  "direction":"Szarych Szeregów",
-                  "lineName":"83"
-               }
-            ],
-            "bollard":{  
-               "symbol":"LU I21",
-               "tag":"LU I01",
-               "name":"Lutycka I n/ż",
-               "mainBollard":false
-            }
-         },
-         {  
-            "directions":[  
-               {  
-                  "returnVariant":false,
-                  "direction":"Szarych Szeregów",
-                  "lineName":"83"
-               }
-            ],
-            "bollard":{  
-               "symbol":"LUII21",
-               "tag":"LUII01",
-               "name":"Lutycka II n/ż",
-               "mainBollard":false
-            }
-         },
-         {  
-            "directions":[  
-               {  
-                  "returnVariant":false,
-                  "direction":"Rondo Śródka",
-                  "lineName":"83"
-               }
-            ],
-            "bollard":{  
-               "symbol":"LUII22",
-               "tag":"LUII02",
-               "name":"Lutycka II n/ż",
-               "mainBollard":false
-            }
-         },
-         {  
-            "directions":[  
-               {  
-                  "returnVariant":false,
-                  "direction":"Rondo Śródka",
-                  "lineName":"83"
-               }
-            ],
-            "bollard":{  
-               "symbol":"LU I22",
-               "tag":"LU I02",
-               "name":"Lutycka I n/ż",
-               "mainBollard":false
-            }
-         },
-         {  
-            "directions":[  
-               {  
-                  "returnVariant":false,
-                  "direction":"Poznań Główny",
-                  "lineName":"236"
-               }
-            ],
-            "bollard":{  
-               "symbol":"ROOB22",
-               "tag":"ROOB02",
-               "name":"Rondo Obornicka",
-               "mainBollard":false
-            }
-         },
-         {  
-            "directions":[  
-               {  
-                  "returnVariant":false,
-                  "direction":"Poznań Główny",
-                  "lineName":"246"
-               }
-            ],
-            "bollard":{  
-               "symbol":"ROOB21",
-               "tag":"ROOB01",
-               "name":"Rondo Obornicka",
-               "mainBollard":false
-            }
-         }
-      ]
-   }
-}
-```
-
-## `getBollardsByLine`
-Zwraca bollardy, przy których zatrzymuje się dana linia, włącznie z jej wariacjami wynikającymi z wyjazdami/zjazdami z/do zajezdni.
-
-### Wejście
-* `name` : nazwa linii
-
-### Wyjście
-Obiekt `directions`, będący tablicą obiektów zawierających w sobie obiekt `direction` i `bollards`. `direction` zawiera :
-* `returnVariant` - chyba `true` dla "powracającego", chociaż trudno mi się domyślić, jakie to ma naprawdę znaczenie.
-* `direction` - kierunek jazdy
-* `lineName` - nazwę linii.
-
-`bollards` to natomiast tablica obiektów zawierających wszystkie bollardy, przy których zatrzymuje się dana wariacja linii. Każdy z tych obiektów zawiera to samo, co `bollard` znajdujący się w wyniku `getBollardsByStopPoint`, ale z dodanym `orderNo`, czyli - chyba - kolejny numer przystanku dla linii. Atrybut ten pewnie być użyty do zrekonstruowania trasy danej linii i jej wariacji, ale nie udało mi się znaleźć na to jakiegoś algorytmu.
-
-### Przykład
-Pominięty ze względu na zbyt duży rozmiar.
-
-## `getLines`
-Pobiera linie komunikacji pasujące do zadanego wzorca.
-
-### Wejście
-* `pattern`
-
-### Wyjście
-Tablica zawierająca obiekty, których `name` zawiera pełną nazwę linii.
-
-### Przykład
-```
-peka_vm_get getLines '{"pattern":"16"}'
-```
-```javascript
-{  
-   "success":[  
-      {  
-         "name":"16"
-      },
-      {  
-         "name":"616"
-      },
-      {  
-         "name":"716"
-      }
-   ]
-}
-```
-## `getStreets`
-Pobiera listę ulic razem z ich identyfikatorami, pasującymi do zadanego wzorca.
-
-### Wejście
-* `pattern` : wzorzec.
-
-### Wyjście
-Tablica obiektów zawierających `id` ulicy do użycia w późniejszych zapytaniach, oraz `name`, czyli ich pełną nazwę.
-
-### Przykład
-```
-peka_vm_get getStreets '{"pattern":"Gło"}'
-```
-```javascript
-{  
-   "success":[  
-      {  
-         "id":3,
-         "name":"Głogowska"
-      },
-      {  
-         "id":159,
-         "name":"Koziegłowy/Gdyńska"
-      },
-      {  
-         "id":270,
-         "name":"Koziegłowy/Piaskowa"
-      },
-      {  
-         "id":167,
-         "name":"Koziegłowy/Piłsudskiego"
-      },
-      {  
-         "id":166,
-         "name":"Koziegłowy/Poznańska"
-      },
-      {  
-         "id":165,
-         "name":"Koziegłowy/Taczaka"
-      },
-      {  
-         "id":319,
-         "name":"Kórnik/pl. Niepodległości"
-      },
-      {  
-         "id":277,
-         "name":"Luboń/Niepodległości"
-      },
-      {  
-         "id":143,
-         "name":"al. Niepodległości"
-      },
-      {  
-         "id":6,
-         "name":"zajezdnia Głogowska"
-      }
-   ]
-}
-```
-
-## `getTimes`
-Pobiera szacowane czasy przyjazdu kolejnych pojazdów na zadany bollard.
-
-### Wejście
-* `symbol` : `tag` bollarda (niestety nie `symbol`, jak mogłoby się wydawać) wyciągnięty przez którąś z wariacji funkcji `getBollards`, dla którego pobrać listę przyjazdów.
-
-### Wyjście
-Dwa obiekty : `bollard` opisujący bollarda i zawierający :
- * `symbol` - identyfikator bollarda w systemie,
- *  `tag` - alternatywny identyfikator?,
- *  `name` - nazwę przystanku, do którego należy bollard,
- *  `mainBollard` - na razie widziałem tutaj tylko `false`, ale domyślam się, że może to być `true` dla "jednobollardowych" przystanków.
-
-Oraz obiekt `times` będący tablicą obiektów zawierających :
-* `realTime` - czy przyjazd jest podany w oparciu o położenie pojazdu na podstawie odczytu jego lokalizacji,
-* `minutes` - ile minut zostało do przyjazdu,
-* `direction` - kierunek trasy,
-* `onStopPoint` - czy pojazd aktualnie znajduje się na bollardzie,
-* `departure` - szacowany czas odjazdu podany jako `yyyy-MM-dd'T'HH:mm:ss.SSS'Z'`. **Nie** jest to ISO 8601, ponieważ końcowe `Z` sugerowałoby wtedy, że jest on podany w UTC. Tak się jednak nie dzieje : godzina podawana jest w czasie lokalnym , czyli CET albo CEST.
-* `line` - linia, którą obsługuje pojazd.
-
-### Przykład
-```
-peka_vm_get getTimes '{"symbol":"AWF03"}'
-```
-```javascript
-{
-   "success":{
-      "bollard":{
-         "symbol":"AWF03",
-         "tag":"AWF21",
-         "name":"AWF",
-         "mainBollard":false
-      },
-      "times":[
-         {  
-            "realTime":true,
-            "minutes":0,
-            "direction":"Os. Orła Białego",
-            "onStopPoint":true,
-            "departure":"2016-11-25T21:48:00.000Z",
-            "line":"74"
-         },
-         {  
-            "realTime":true,
-            "minutes":20,
-            "direction":"Os. Orła Białego",
-            "onStopPoint":false,
-            "departure":"2016-11-25T22:08:00.000Z",
-            "line":"74"
-         }
-      ]
-   }
-}
-```
-
-## `getTimesForAllBollards`
-Pobiera czasy przyjazdu na wszystkich bollardach przypisanych do danego przystanku. Swoiste połączenie `getBollardsByStopPoint` i `getTimes`.
-
-### Wejście
-* `name` : nazwa przystanku.
-
-### Wyjście
-Obiekt `bollardsWithTimes`, będący tablicą struktur opisanych w `getTimes`.
-
-### Przykład
-```
-peka_vm_get getTimesForAllBollards '{"name":"Katowicka"}'
-```
-```javascript
-{  
-   "success":{  
-      "bollardsWithTimes":[  
-         {  
-            "bollard":{  
-               "symbol":"KATO22",
-               "tag":"KATO02",
-               "name":"Katowicka",
-               "mainBollard":false
-            },
-            "times":[  
-               {  
-                  "realTime":true,
-                  "minutes":8,
-                  "direction":"Rondo Śródka",
-                  "onStopPoint":false,
-                  "departure":"2016-11-25T22:48:00.000Z",
-                  "line":"57"
-               },
-               {  
-                  "realTime":true,
-                  "minutes":13,
-                  "direction":"Termy Maltańskie",
-                  "onStopPoint":false,
-                  "departure":"2016-11-25T22:53:00.000Z",
-                  "line":"84"
-               }
-            ]
-         },
-         {  
-            "bollard":{  
-               "symbol":"KATO21",
-               "tag":"KATO01",
-               "name":"Katowicka",
-               "mainBollard":false
-            },
-            "times":[  
-               {  
-                  "realTime":false,
-                  "minutes":13,
-                  "direction":"Rondo Rataje",
-                  "onStopPoint":false,
-                  "departure":"2016-11-25T22:53:00.000Z",
-                  "line":"84"
-               },
-               {  
-                  "realTime":false,
-                  "minutes":24,
-                  "direction":"Mogileńska",
-                  "onStopPoint":false,
-                  "departure":"2016-11-25T23:04:00.000Z",
-                  "line":"57"
-               }
-            ]
-         }
-      ]
-   }
-}
-```
-
-## `getServerTime`
-Pobiera aktualny czas na serwerze jako coś, co wygląda na liczbę milisekund od 1. stycznia 1970. Na wejściu pusty obiekt.
-
-### Przykład
-```
-peka_vm_get getServerTime '{}'
-```
-```javascript
-{"success":1480110116917}
-```
-
-## `findMessagesForBollard`
-Zwraca wiadomości zapisane przez administrację serwisu, skojarzone z danym bollardem. Z reguły wykorzystywane do zakomunikowania czasowych zmian w rozkładzie.
-
-### Wejście
-* `symbol` : identyfikator bollarda
-
-### Wyjście
-Tablica obiektów zawierających następujące pola :
-* `content` : wiadomość, która ma zostać wyświetlona, jako HTML,
-* `startHour`, `stopsGroups` i `endHour` : przeznaczenie nieznane, nie są używane w ogóle przez kod renderujący oficjalną stronę,
-* `startDate` : data oznaczająca początek okresu, kiedy komunikat ma zacząć zostać wyświetlany,
-* `endDate` : j.w., ale oznaczająca koniec tego okresu.
-
-Format daty jest taki sam jak ten używany przez pole `departure` w `getTimes`.
-
-### Przykład
-```
-peka_vm_get findMessagesForBollard '{"symbol":"RJEZ04"}'
-```
-```javascript
-{  
-   "success":[  
-      {  
-         "content":"INFO: Od 9 kwietnia, w związku z remontem torowiska na ul. 28 Czerwca 1956 r., zmianie ulegną trasy linii tramwajowych nr 2, 9, 10 i 11. Uruchomiona zostanie komunikacja zastępcza. Szczegóły na stronie <a href=\"http://tiny.pl/g5dss\">www.ztm.poznan.pl<\/a>.",
-         "startDate":"2017-04-06T01:00:00.000Z",
-         "stopsGroups":[  
-
-         ],
-         "startHour":60,
-         "endDate":"2017-04-11T23:00:00.000Z",
-         "endHour":1380
-      }
-   ]
-}
-```




diff --git a/research/pkp b/research/pkp
deleted file mode 100644
index 230f97e801f615336f910c6647a0500d61df3088..0000000000000000000000000000000000000000
--- a/research/pkp
+++ /dev/null
@@ -1,37 +0,0 @@
-https://github.com/bartekmp/infopasazer
-
-stacja:
-curl 'https://portalpasazera.pl/WyszukiwaniePolaczen/StacjeFiltrRead?wprowadzonyTekst=Warszawa' \
--XGET \
--H '387693: 764f49' \
--H 'Referer: https://portalpasazera.pl/WyszukiwaniePolaczen/' \
--H 'Accept: */*' \
--H 'Connection: Keep-Alive' \
--H 'Accept-Encoding: gzip, deflate' \
--H 'Accept-Language: en-gb, en;q=0.90' \
--H 'DNT: 1' \
--H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1 (KHTML, like Gecko) Version/11.0 Safari/605.1 Epiphany/3.26.5.1' \
--H 'Cookie: ASP.NET_SessionId=d4pkbz3xwzewshdm5dqvjxyi; __RequestVerificationToken=XiuyWQvHFRmudTBK2Ke_484x-LZC91Q-1fOwP_AzGT3szmmvdCUVDmNJNpMP6z_HrxjXBy_duOm1l1FP2Asg6Tz1DttmvE8rJc_X0XwOtfY1' \
--H 'aa7cbb: 7d52cc' \
--H 'X-Requested-With: XMLHttpRequest' \
--H 'X-Kendo-Ui-Version: r3-2016-sp2'
-
-połączenie:
-curl 'https://portalpasazera.pl/WyszukiwaniePolaczen/WyszukajPolaczenia' \
--XPOST \
--H 'Referer: https://portalpasazera.pl/WyszukiwaniePolaczen/' \
--H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
--H 'Origin: https://portalpasazera.pl' \
--H 'Accept: */*' \
--H 'Connection: Keep-Alive' \
--H 'Accept-Encoding: gzip, deflate' \
--H 'Accept-Language: en-gb, en;q=0.90' \
--H 'DNT: 1' \
--H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/605.1 (KHTML, like Gecko) Version/11.0 Safari/605.1 Epiphany/3.26.5.1' \
--H 'Cookie: Section_WP_ThroughStations=1; ASP.NET_SessionId=q43u4zrurf2oh12fcy2td1no; __RequestVerificationToken=6V9CETnBIOhA61_KpfNlmxazzjfjEqk1ZHTKpZQkjn24rtLDqnFpJbCVNi7ariHdA38gslZhTpziDp6kC9EcLLZnHj0vn9BcA1WIEdjGrsk1; cookie=true' \               # Proste do uzyskania Podaje przy dowolnym połączeniu (można zrobić GET / >/dev/null)
--H 'Content-Length: 1058' \
--H 'c2e09f: 44952b' \                       # to i następna linia musi się zgadzać ze stacjami (jest deterministyczne, zależne od stacji można sprawdzić wszystkie interesujące stacje i zahardcodować (nie wiem, może to się jakoś ma do wyniku StacjeFiltrRead?)
--H 'aa7cbb: 7d52cc' \                       # To jest poznań Główny
--H 'X-Requested-With: XMLHttpRequest' \
--H 'X-Kendo-Ui-Version: r3-2016-sp2' \
---data 'sort=&group=&filter=&kryteria=%7B%22IdStacjiPoczatkowej%22%3A%22356503%22%2C%22NazwaStacjiPoczatkowej%22%3A%22Lubo%C5%84+ko%C5%82o+Poznania%22%2C%22StacjePosrednie%22%3A%5B%5D%2C%22IdStacjiKoncowej%22%3A%22356701%22%2C%22NazwaStacjiKoncowej%22%3A%22Pozna%C5%84+G%C5%82%C3%B3wny%22%2C%22KategorieSzybkosci%22%3A%5B%22SZ%22%2C%22DA%22%2C%22LO%22%2C%22AG%22%5D%2C%22Uslugi%22%3A%5B%5D%2C%22PolaczenieBezposrednie%22%3Afalse%2C%22GlobalneParametryPolaczenia%22%3Atrue%2C%22Data%22%3A%222018-02-07%22%2C%22Czas%22%3A%2220%3A51%22%2C%22PociagCzynnosc%22%3A%22Odjazd%22%2C%22Przewoznicy%22%3A%5B%22KM%22%2C%22PR%22%2C%22KM%C5%81%22%2C%22%C5%81KA%22%2C%22IC%22%2C%22AR%22%2C%22KD%22%2C%22KS%22%2C%22KW%22%2C%22LEO%22%2C%22ODEG%22%2C%22CARGO%22%2C%22SKMT%22%2C%22SKPL%22%2C%22SKM%22%5D%2C%22MinimalnyCzasNaPrzesiadke%22%3A%2200%3A10%22%2C%22grc%22%3A%22%22%2C%22p%22%3A%22ok%22%7D&rodzaj=NoweWyszukiwanie&zapamietanePolaczenia=null&__RequestVerificationToken=arWI_CJhi7iighRQMaB7eWLKYMUMvW5kA2ObVpS0KjEslYMd1fSBSkrY4Ipi978ZUEktfFvHurtV6XWxk5zF0PORcxv_q0XZp3K6SGYKOnM1'




diff --git a/research/svg/departure_timetable.svg b/research/svg/departure_timetable.svg
deleted file mode 100644
index 6029c7740978a518e1d4acdd31de22fabd2986a5..0000000000000000000000000000000000000000
--- a/research/svg/departure_timetable.svg
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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"
-   fill="#000000"
-   height="24"
-   viewBox="0 0 24 24"
-   width="24"
-   version="1.1"
-   id="svg6">
-  <metadata
-     id="metadata12">
-    <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>
-  <defs
-     id="defs10" />
-  <path
-     d="M0 0h24v24H0z"
-     fill="none"
-     id="path2" />
-  <path
-     d="M 19,3 C 12,2.4802944 12,2.481597 5,3 3.89,3 3.01,3.9 3.01,5 L 3,19 c 0,1.1 0.89,2 2,2 h 14 c 1.1,0 2,-0.9 2,-2 V 5 C 21,3.9 20.1,3 19,3 Z m 0,16 H 5 V 8 h 14 z"
-     id="path4" />
-  <path
-     id="path2-6"
-     d="m 17,12 h -5 v 5 h 5 z" />
-</svg>




diff --git a/research/svg/download.svg b/research/svg/download.svg
deleted file mode 100644
index 6e3674ba7937318b725e8eaf6f4d24ca9e570366..0000000000000000000000000000000000000000
--- a/research/svg/download.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-    <path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
-    <path d="M0 0h24v24H0z" fill="none"/>
-</svg>
\ No newline at end of file




diff --git a/research/svg/favourite.svg b/research/svg/favourite.svg
deleted file mode 100644
index 742e71af5c709a7bae7e5f54190ee88a5cbc90fb..0000000000000000000000000000000000000000
--- a/research/svg/favourite.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-    <path d="M0 0h24v24H0z" fill="none"/>
-    <path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/>
-    <path d="M0 0h24v24H0z" fill="none"/>
-</svg>
\ No newline at end of file




diff --git a/research/svg/info.svg b/research/svg/info.svg
deleted file mode 100644
index 5c09d08bd5bd7c3fde49fa77d2878ba4362b21d9..0000000000000000000000000000000000000000
--- a/research/svg/info.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-    <path d="M0 0h24v24H0z" fill="none"/>
-    <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/>
-</svg>
\ No newline at end of file




diff --git a/research/svg/more.svg b/research/svg/more.svg
deleted file mode 100644
index eba41f0af5c5d918f21ca4f9dd456c684c6bcebc..0000000000000000000000000000000000000000
--- a/research/svg/more.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
-    <path d="M0 0h24v24H0z" fill="none"/>
-    <path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
-</svg>
\ No newline at end of file




diff --git a/research/svg/nodb.svg b/research/svg/nodb.svg
deleted file mode 100644
index 2473baef81e7aad05f75eb66fa272c1d0e321717..0000000000000000000000000000000000000000
--- a/research/svg/nodb.svg
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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"
-   id="svg8"
-   version="1.1"
-   viewBox="0 0 285.74999 508.00001"
-   height="1920"
-   width="1080">
-  <defs
-     id="defs2" />
-  <metadata
-     id="metadata5">
-    <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
-     transform="translate(0,211.00002)"
-     id="layer1">
-    <rect
-       y="-211.00002"
-       x="0"
-       height="508"
-       width="285.75"
-       id="rect4485"
-       style="opacity:1;fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:2.96499991;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-    <rect
-       y="130.19077"
-       x="136.12813"
-       height="166.80922"
-       width="13.49375"
-       id="rect4495"
-       style="opacity:1;fill:#aaaaaa;fill-opacity:1;stroke:none;stroke-width:5.5416379;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
-    <g
-       id="g5093"
-       transform="matrix(0.28222223,0,0,0.28222223,100.54167,47.749918)">
-      <circle
-         id="blauwe_cirkel"
-         cx="150"
-         cy="150"
-         r="150"
-         style="fill:#0e518d;stroke:none" />
-      <g
-         id="symbool_voetpad" />
-      <path
-         style="fill:#ffffff;stroke:none"
-         id="tram_zwart"
-         d="m 110.21944,84.81961 -38.897406,26.63158 32.087416,21.98037 H 45.043711 l 1.079393,6.82962 L 40,163.6742 v 29.88939 h 18.545941 l 1.609278,-7.2025 h 62.663691 l 1.60927,7.2025 h 51.14363 l 1.60928,-7.2025 h 62.66369 l 1.60928,7.2025 H 260 V 163.6742 l -6.12311,-23.41302 1.09902,-6.82962 H 117.02943 l 32.0678,-21.98037 z m 0,6.12311 29.90901,20.48884 v 0.0589 l -29.90901,20.50847 -29.909003,-20.50847 v -0.0589 z M 49.891168,140.26118 H 66.454951 V 163.6742 H 43.78769 Z m 20.900982,0 H 98.876004 V 163.6742 H 70.79215 Z m 32.40142,0 h 28.08385 v 23.41302 h -28.08385 z m 32.40143,0 h 28.80999 V 163.6742 H 135.595 Z m 33.12757,0 h 28.08385 v 23.41302 h -28.08385 z m 32.42105,0 h 28.08385 v 23.41302 h -28.08385 z m 32.40143,0 h 16.56378 l 6.10348,23.41302 H 233.54505 Z M 65.885816,191.03192 v 2.45316 c 0,5.35876 4.336163,9.69492 9.694915,9.69492 4.304046,0 7.956129,-2.80368 9.223907,-6.69224 h 13.541476 c 1.26777,3.88856 4.919856,6.69224 9.223906,6.69224 5.35874,0 9.69491,-4.33616 9.69491,-9.69492 l -0.0392,-2.45316 H 65.885867 Z m 116.888494,0 -0.0393,2.45316 c 0,5.35876 4.33617,9.69492 9.69492,9.69492 4.30405,0 7.95613,-2.80368 9.22391,-6.69224 h 13.54148 c 1.26778,3.88856 4.91986,6.69224 9.2239,6.69224 5.35876,0 9.69492,-4.33616 9.69492,-9.69492 v -2.45316 h -51.33987 z" />
-      <circle
-         id="circle3774"
-         cx="150"
-         cy="150"
-         r="141.942"
-         style="fill:none;stroke:#f7fbf5;stroke-width:6.73600006" />
-    </g>
-  </g>
-</svg>




diff --git a/research/svg/textHandle_left.svg b/research/svg/textHandle_left.svg
deleted file mode 100644
index e929f21ce40749c272b2386ffcb847e25d98f78d..0000000000000000000000000000000000000000
--- a/research/svg/textHandle_left.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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"
-   viewBox="0 0 176 88"
-   height="88"
-   width="176"
-   id="svg2"
-   version="1.1">
-  <metadata
-     id="metadata8">
-    <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>
-  <defs
-     id="defs6" />
-  <path
-     id="path817"
-     d="M 88,0 A 44,44 0 0 0 44,44 44,44 0 0 0 88,88 44,44 0 0 0 132,44 V 0 Z"
-     style="opacity:1;fill:#54af39;fill-opacity:1;stroke:none;stroke-width:0.01982322;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
-</svg>




diff --git a/research/svg/textHandle_middle.svg b/research/svg/textHandle_middle.svg
deleted file mode 100644
index 4e8b5c388a1d204b1f2f0c44766b611759e23728..0000000000000000000000000000000000000000
--- a/research/svg/textHandle_middle.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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"
-   viewBox="0 0 87.999999 87.999998"
-   height="88"
-   width="88"
-   id="svg2"
-   version="1.1">
-  <metadata
-     id="metadata8">
-    <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>
-  <defs
-     id="defs6" />
-  <path
-     id="path817"
-     d="m 69.774698,25.774604 a 36.450926,36.45079 0 0 1 0,51.549207 36.450926,36.45079 0 0 1 -51.549395,0 36.450926,36.45079 0 0 1 0,-51.549207 L 44,0 Z"
-     style="opacity:1;fill:#54af39;fill-opacity:1;stroke:none;stroke-width:0.01642212;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
-</svg>




diff --git a/research/svg/textHandle_right.svg b/research/svg/textHandle_right.svg
deleted file mode 100644
index 6db4aeec1cbb7dc1696d4d3db08884a2708e7873..0000000000000000000000000000000000000000
--- a/research/svg/textHandle_right.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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"
-   viewBox="0 0 176 88"
-   height="88"
-   width="176"
-   id="svg2"
-   version="1.1">
-  <metadata
-     id="metadata8">
-    <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>
-  <defs
-     id="defs6" />
-  <path
-     id="path817"
-     d="M 88,0 A 44,44 0 0 1 132,44 44,44 0 0 1 88,88 44,44 0 0 1 44,44 V 0 Z"
-     style="opacity:1;fill:#54af39;fill-opacity:1;stroke:none;stroke-width:0.01982322;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
-</svg>




diff --git a/research/svg/timetable_full.svg b/research/svg/timetable_full.svg
deleted file mode 100644
index 426d183ff1bf2bb4135985e6d2a9826fea215d52..0000000000000000000000000000000000000000
--- a/research/svg/timetable_full.svg
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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"
-   id="svg6"
-   version="1.1"
-   width="24"
-   viewBox="0 0 24 24"
-   height="24"
-   fill="#000000">
-  <metadata
-     id="metadata12">
-    <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>
-  <defs
-     id="defs10" />
-  <path
-     id="path2"
-     fill="none"
-     d="M0 0h24v24H0z" />
-  <path
-     id="path4"
-     d="M 17,10 H 7 v 2 H 17 Z M 19,3 C 12,2.4802944 12,2.481597 5,3 3.89,3 3.01,3.9 3.01,5 L 3,19 c 0,1.1 0.89,2 2,2 h 14 c 1.1,0 2,-0.9 2,-2 V 5 C 21,3.9 20.1,3 19,3 Z m 0,16 H 5 V 8 H 19 Z M 14,14 H 7 v 2 h 7 z" />
-</svg>




diff --git a/research/svg/vm.svg b/research/svg/vm.svg
deleted file mode 100644
index e22fcf65b5ff9e600b9354f88bfdaa59d09e04c3..0000000000000000000000000000000000000000
--- a/research/svg/vm.svg
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<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:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   id="svg6"
-   version="1.1"
-   width="24"
-   viewBox="0 0 24 24"
-   height="24"
-   fill="#000000"
-   sodipodi:docname="vm.svg"
-   inkscape:version="0.92.1 r">
-  <sodipodi:namedview
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1"
-     objecttolerance="10"
-     gridtolerance="10"
-     guidetolerance="10"
-     inkscape:pageopacity="0"
-     inkscape:pageshadow="2"
-     inkscape:window-width="1368"
-     inkscape:window-height="744"
-     id="namedview64"
-     showgrid="false"
-     inkscape:zoom="21.166667"
-     inkscape:cx="12"
-     inkscape:cy="12"
-     inkscape:window-x="0"
-     inkscape:window-y="24"
-     inkscape:window-maximized="0"
-     inkscape:current-layer="svg6" />
-  <metadata
-     id="metadata12">
-    <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 />
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs10" />
-  <path
-     id="path2"
-     fill="none"
-     d="M0 0h24v24H0z" />
-  <path
-     d="M 12 4 C 9.11 4 6.5996094 5.6390625 5.3496094 8.0390625 C 2.3396094 8.3590625 -1.1842379e-15 10.91 0 14 C 0 17.31 2.69 20 6 20 L 19 20 C 21.76 20 24 17.76 24 15 C 24 12.36 21.949609 10.219062 19.349609 10.039062 C 18.669609 6.5890625 15.64 4 12 4 z M 4.4042969 10.652344 L 5.921875 10.652344 L 7.4179688 15.642578 L 8.921875 10.652344 L 10.443359 10.652344 L 8.1328125 17.289062 L 6.7070312 17.289062 L 4.4042969 10.652344 z M 11.072266 10.652344 L 12.859375 10.652344 L 14.5625 15.464844 L 16.257812 10.652344 L 18.054688 10.652344 L 18.054688 17.289062 L 16.681641 17.289062 L 16.681641 15.474609 L 16.818359 12.34375 L 15.027344 17.289062 L 14.089844 17.289062 L 12.302734 12.347656 L 12.439453 15.474609 L 12.439453 17.289062 L 11.072266 17.289062 L 11.072266 10.652344 z "
-     id="path4" />
-</svg>




diff --git a/settings.gradle b/settings.gradle
index e7b4def49cb53d9aa04228dd3edb14c9e635e003..65d6741bf7ac4b9016dfb6c839a41deb33027086 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,18 @@
+pluginManagement {
+    repositories {
+        gradlePluginPortal()
+        google()
+        mavenCentral()
+    }
+}
+dependencyResolutionManagement {
+    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+    repositories {
+        google()
+        mavenCentral()
+        maven { url "https://jitpack.io" }
+    }
+}
+rootProject.name = "Bimba"
 include ':app'
+include ':fruchtfleisch'




diff --git a/todo b/todo
deleted file mode 100644
index 5c7be496093f80354c8a4ec93be87fcd0494c742..0000000000000000000000000000000000000000
--- a/todo
+++ /dev/null
@@ -1,19 +0,0 @@
-- acra: https://stackoverflow.com/questions/601503/how-do-i-obtain-crash-data-from-my-android-application
-v empty search result
-- search results loading [?]
-- search results history [?]
-v shed loading
-v departures loading
-v departures empty
-- search result retry
-- shed retry
-- departures retry
-x search results flickering
-- favourite cache
-v in a moment
-v departures sort (timeTill, onStop) : StopActivity
-v sort and limit search results
-T PEKA info
-- check update (only in APK builds)
-- settings day/night
-- ‘no conn…’ only w/o timetable