summaryrefslogtreecommitdiff
authorGiulio Cesare Solaroli <giulio.cesare@clipperz.com>2013-04-21 15:55:07 (UTC)
committer Giulio Cesare Solaroli <giulio.cesare@clipperz.com>2013-04-21 15:55:07 (UTC)
commit959c262afc598c4eeb58fe8fccf90ea8305c0eec (patch) (unidiff)
treeaae9cb7821e59704240751e5b2878a374d21ea91
parent1906ddfb5d3887edeedaf8e07d14ad89abbd214d (diff)
downloadclipperz-959c262afc598c4eeb58fe8fccf90ea8305c0eec.zip
clipperz-959c262afc598c4eeb58fe8fccf90ea8305c0eec.tar.gz
clipperz-959c262afc598c4eeb58fe8fccf90ea8305c0eec.tar.bz2
Updated mobile prototype
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--frontend/gamma/css/mobile.css8062
-rw-r--r--frontend/gamma/html/mobile_template.html54
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/BaseComponent.js249
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardList.js25
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js142
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/Overlay.js136
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/Preferences.js77
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js159
-rw-r--r--frontend/gamma/js/Clipperz/PM/UI/Mobile/CustomizeJQueryMobile.js50
-rw-r--r--frontend/gamma/js/JQuery/1.9.1/jquery.js9620
-rw-r--r--frontend/gamma/js/JQuery/Mobile/1.3.0-rc.1/jquery.mobile.js11113
-rw-r--r--frontend/gamma/js/main.mobile.js35
12 files changed, 23698 insertions, 6024 deletions
diff --git a/frontend/gamma/css/mobile.css b/frontend/gamma/css/mobile.css
index 36b2b21..ecdeeab 100644
--- a/frontend/gamma/css/mobile.css
+++ b/frontend/gamma/css/mobile.css
@@ -1,6191 +1,2569 @@
1/* 1/*
2 2
3Copyright 2008-2013 Clipperz Srl 3Copyright 2008-2013 Clipperz Srl
4 4
5This file is part of Clipperz, the online password manager. 5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please 6For further information about its features and functionalities please
7refer to http://www.clipperz.com. 7refer to http://www.clipperz.com.
8 8
9* Clipperz is free software: you can redistribute it and/or modify it 9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published 10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or 11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version. 12 (at your option) any later version.
13 13
14* Clipperz is distributed in the hope that it will be useful, but 14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of 15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details. 17 See the GNU Affero General Public License for more details.
18 18
19* You should have received a copy of the GNU Affero General Public 19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/. 20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21 21
22*/ 22*/
23 23
24article, 24/*
25aside, 25
26details, 26Color list:
27figcaption, 27- login box:
28figure, 28 light#ff9955
29footer, 29 dark#ff6622
30header, 30- login button:
31hgroup, 31 regular#dd5500
32nav, 32 hover#773311
33section { 33- login translations:
34 display: block; 34 box: #cc6622;
35} 35 not-selected:
36audio, 36 color: #ddaa99
37canvas, 37 background:#994422
38video { 38 selected: #772211;
39 display: inline-block; 39*/
40 *display: inline;
41 *zoom: 1;
42}
43audio:not([controls]) {
44 display: none;
45}
46html { 40html {
47 font-size: 100%; 41 height: 100%;
48 -webkit-text-size-adjust: 100%; 42 -webkit-text-size-adjust: none;
49 -ms-text-size-adjust: 100%; 43 -ms-text-size-adjust: none;
50}
51a:focus {
52 outline: thin dotted #333;
53 outline: 5px auto -webkit-focus-ring-color;
54 outline-offset: -2px;
55}
56a:hover,
57a:active {
58 outline: 0;
59}
60sub,
61sup {
62 position: relative;
63 font-size: 75%;
64 line-height: 0;
65 vertical-align: baseline;
66} 44}
67sup { 45body {
68 top: -0.5em; 46 font-family: Helvetica-Neue, Helvetica, Arial, Geneva, sans-serif;
47 margin: 0px;
69} 48}
70sub { 49.ellipsis {
71 bottom: -0.25em; 50 text-overflow: ellipsis;
51 overflow: hidden;
52 white-space: nowrap;
72} 53}
73img { 54/**
74 /* Responsive images (ensure images don't scale beyond their parents) */ 55 * Background noise recipe
75 56 *
76 max-width: 100%; 57 * This recipe use a sass function to generate a .png file
77 /* Part 1: Set a maxium relative to the parent */ 58 *
78 59 * Inspired by a jQuery plugin "Noisy" by Daniel Rapp @DanielRapp
79 width: auto\9; 60 * @link https://github.com/DanielRapp/Noisy
80 /* IE7-8 need help adjusting responsive images */ 61 *
81 62 * Converted using Sass by Aaron Russell @aaronrussell & Philipp Bosch @philippbosch
82 height: auto; 63 * @link https://gist.github.com/1021332
83 /* Part 2: Scale the height according to the width, otherwise you get stretching */ 64 *
65 * Ported to a sass gem by Antti Salonen @antsa
66 * @link https://github.com/antsa/sassy_noise
67 *
68 * Mixin: background-noise
69 * Function: background_noise
70 *
71 * @author Daniel Rapp @DanielRapp
72 * @author Aaron Russell @aaronrussell
73 * @author Philipp Bosch @philippbosch
74 * @author Antti Salonen @antsa
75 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
76 */
77/**
78 *
79 * @class Gradients
80 * @author David Kaneda http://www.davidkaneda.com/
81 *
82 */
83/**
84 * Adds a background gradient into a specified selector.
85 *
86 * @include background-gradient(#444, 'glossy');
87 *
88 * You can also use color-stops if you want full control of the gradient:
89 *
90 * @include background-gradient(#444, color-stops(#333, #222, #111));
91 *
92 * @param {color} $bg-color
93 * The base color of the gradient.
94 *
95 * @param {string/list} $type
96 * The style of the gradient, one of five pre-defined options: matte, bevel, glossy, recessed, or linear:
97 *
98 * @include background-gradient(red, 'glossy');
99 *
100 * It can also accept a list of color-stop values:;
101 *
102 * @include background-gradient(black, color-stops(#333, #111, #000));
103 *
104 * @param {string} $direction
105 * The direction of the gradient.
106 */
107/**
108 * Blueprint grid background pattern
109 *
110 * @link http://lea.verou.me/css3patterns/#blueprint-grid
111 *
112 * @author Lea Verou http://lea.verou.me/ for the original pattern
113 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx for the sass mixin
114 */
115/**
116 * Background overlay inspired by Google Chrome modal overlay
117 *
118 * @author Maxime Thirouin @MoOx maxime.thirouin@gmail.com
119 */
120/**
121 * Striped background pattern
122 *
123 * @link http://lea.verou.me/css3patterns/
124 *
125 * @author Lea Verou http://lea.verou.me/ for the original pattern
126 * @author David Kaneda http://www.davidkaneda.com @davidkaneda for the sass mixin
127 */
128/**
129 *
130 * Before compass 0.11.5, you need to add
131 * Compass::BrowserSupport.add_support("repeating-linear-gradient", "webkit", "moz", "o", "ms")
132 * To your configuration (config.rb)
133 * @see https://github.com/chriseppstein/compass/issues/401
134 *
135 * @link http://lea.verou.me/css3patterns/#tartan
136 *
137 * @author Marta Armada http://swwweet.com/ for the original pattern
138 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx for the sass mixin
139 */
140/**
141 * Carbon Fiber background pattern
142 *
143 * @author Lea Verou http://lea.verou.me/ for the original pattern
144 * @author David Kaneda http://www.davidkaneda.com/ for the Sass mixin
145 *
146 * @link http://lea.verou.me/css3patterns/
147 *
148 */
149/**
150 * Normalize.css
151 * Opposite approche from CSS reset
152 *
153 * Based on normalize.css commit 9576d48fc234c5224b1fc4dccba2f5965243843d
154 *
155 * @link http://github.com/necolas/normalize.css
156 */
157/* normalize.css 2011-07-12T10:51 UTC · http://github.com/necolas/normalize.css */
158/* =============================================================================
159 HTML5 element display
160 ========================================================================== */
161/* =============================================================================
162 Base
163 ========================================================================== */
164/* =============================================================================
165 Links
166 ========================================================================== */
167/* =============================================================================
168 Typography
169 ========================================================================== */
170/* =============================================================================
171 Lists
172 ========================================================================== */
173/* =============================================================================
174 Embedded content
175 ========================================================================== */
176/* =============================================================================
177 Figures
178 ========================================================================== */
179/* =============================================================================
180 Forms
181 ========================================================================== */
182/* =============================================================================
183 Tables
184 ========================================================================== */
185/**
186 *
187 * @author David Kaneda - http://www.davidkaneda.com
188 *
189 */
190/**
191 * @class Color
192 */
193/**
194 * Returns the brightness (out of 100) of a specified color.
195 * @todo explain why this is useful
196 * @param {color} $color The color you want the brightness value of
197 * @return {measurement}
198 */
199/**
200 * Returns the luminosity for a specified color
201 * @todo explain why this is useful
202 * @param {color} The color to check
203 * @return {measurement}
204 */
205/**
206 * Glass effect
207 * Use this on image for better effect render
208 *
209 * Inspired from Simurai's IMDB redisign
210 *
211 * @link http://lab.simurai.com/redesign/imdb
212 * @thanks Simurai @simurai
213 */
214/**
215 * Note IE7/6 doesn't understand pseudo element as ::before and ::after
216 * IE8 need to have :before and not ::before
217 * So use only : and not :: if you want to support IE8
218 * IE9 Webkit Firefox Opera understand ::
219 */
220/**
221 * Scotch tape effect with pure CSS
222 *
223 * @thanks Nick La @nickla for original concept
224 * @link http://webdesignerwall.com/tutorials/css3-image-styles
225 *
226 * @author David Kaneda http://www.davidkaneda.com
227 *
228 */
229/**
230 * Note IE7/6 doesn't understand pseudo element as ::before and ::after
231 * IE8 need to have :before and not ::before
232 * So use only : and not :: if you want to support IE8
233 * IE9 Webkit Firefox Opera understand ::
234 */
235/**
236 * Corner folded with pure CSS
237 *
238 * Known support: Firefox 3.5+, Chrome 4+, Safari 4+, Opera 10+, IE 9+.
239 * IE8 is not supported because it not render properly box-shadow and
240 * pseudo element should be selected with ::element and not :element
241 *
242 * @thanks Nicolas Gallagher @necolas
243 * @link http://nicolasgallagher.com/pure-css-folded-corner-effect/demo/
244 * @todo Nix in .4
245 */
246/**
247 * Note IE7/6 doesn't understand pseudo element as ::before and ::after
248 * IE8 need to have :before and not ::before
249 * So use only : and not :: if you want to support IE8
250 * IE9 Webkit Firefox Opera understand ::
251 */
252/**
253 * Corner folded with pure CSS
254 *
255 * Known support: Firefox 3.5+, Chrome 4+, Safari 4+, Opera 10+, IE 9+.
256 * IE8 is not supported because it not render properly box-shadow and
257 * pseudo element should be selected with ::element and not :element
258 *
259 * @thanks Nicolas Gallagher @necolas
260 * @link http://nicolasgallagher.com/pure-css-folded-corner-effect/demo/
261 */
262/**
263 * Note IE7/6 doesn't understand pseudo element as ::before and ::after
264 * IE8 need to have :before and not ::before
265 * So use only : and not :: if you want to support IE8
266 * IE9 Webkit Firefox Opera understand ::
267 */
268/**
269 * Form element inline mixin
270 * This mixin allow you to have a label inline with your input
271 * It's simply based on inline-block behavior
272 *
273 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
274 */
275/**
276 * Vertical alignement for page
277 * Inspired by http://css-tricks.com/snippets/css/center-div-with-dynamic-height/
278 *
279 * Usage:
280 *
281 * SCSS
282 * @include vertical-align-requirement;
283 * .v-align-container { @include vertical-align-container }
284 * .v-align-content-container { @include vertical-align-content-container }
285 * .v-align-content { @include vertical-align-content }
286 *
287 * HTML
288 * <body>
289 * <div class="v-align-container">
290 * <div class="v-align-content-container">
291 * <div class="v-align-content">
292 * Your content !
293 * </div>
294 * </div>
295 * </div>
296 * </body>
297 *
298 * @thanks Chris Coyier @chriscoyier
299 * @autor Maxime Thirouin maxime.thirouin@gmail.com @MoOx
300 */
301/**
302 * Media Queries Mixins
303 *
304 * @todo Do we have to take care of print ?
305 *
306 * @require sass-3.2 (you need eventually to do "sudo gem install sass --pre")
307 * @author Maxime Thirouin <maxime.thirouin@gmail.com>
308 */
309/*
310$media-query-width-big: 1280px;
311$media-query-width-medium: 960px;
312$media-query-width-small: 480px;
313*/
314/**
315 * Drop shadow mixins from Nicolas Gallagher demo
316 *
317 * @thanks Nicolas Gallagher @necolas, @simurai, @cameronmoll, @matthamm
318 *
319 * @link http://nicolasgallagher.com/css-drop-shadows-without-images/demo/
320 */
321/**
322 * Drop shadow curled
323 *
324 * @thanks Nicolas Gallagher @necolas
325 * @link http://nicolasgallagher.com/css-drop-shadows-without-images/demo/
326 */
327/**
328 * Drop shadow curved
329 *
330 * @thanks Nicolas Gallagher @necolas
331 * @link http://nicolasgallagher.com/css-drop-shadows-without-images/demo/
332 */
333/**
334 * Drop shadow flying
335 *
336 * @thanks Geoffrey Crofte @geoffrey_crofte
337 * @link http://www.creativejuiz.fr/trytotry/css3-box-shadow-after-before/
338 */
339/**
340 * Drop shadow w/ lifted corners
341 *
342 * @thanks Nicolas Gallagher @necolas
343 * @link http://nicolasgallagher.com/css-drop-shadows-without-images/demo/
344 */
345/**
346 * Drop shadow w/ perspective
347 *
348 * @thanks Nicolas Gallagher @necolas
349 * @link http://nicolasgallagher.com/css-drop-shadows-without-images/demo/
350 */
351/**
352 * Drop shadow raised
353 *
354 * @thanks Nicolas Gallagher @necolas
355 * @link http://nicolasgallagher.com/css-drop-shadows-without-images/demo/
356 */
357/**
358 * Drop shadow rules required for transform on drop shadow
359 *
360 * /!\ This is required if you want to apply some transform on the element using drop shadow
361 *
362 * @thanks Nicolas Gallagher @necolas
363 * @link http://nicolasgallagher.com/css-drop-shadows-without-images/demo/
364 */
365/**
366 * Shadow along the top edge of the browser viewport
367 *
368 * @link http://playground.genelocklin.com/depth/
369 */
370/**
371* Shapes !
372* Polygons, ellipses and symbols
373*
374* @thanks Chris Coyier @chriscoyier
375* @link http://css-tricks.com/examples/ShapesOfCSS/
376* @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
377*/
378/**
379 * Shape/Ellipse
380 *
381 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
382 */
383/**
384 * Shape/Polygon
385 *
386 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
387 */
388/**
389 * Shape/Polygon/Hexagon
390 *
391 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
392 */
393/**
394 * Shape/Polygon/Octagon
395 *
396 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
397 */
398/**
399 * Shape/Polygon/Parallelogram
400 *
401 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
402 */
403/**
404 * Shape/Polygon/Pentagon
405 *
406 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
407 */
408/**
409 * Shape/Polygon/Rectangle
410 *
411 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
412 */
413/**
414 * Shape/Polygon/Rhombus
415 *
416 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
417 */
418/**
419 * Shape/Polygon/Square
420 *
421 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
422 */
423/**
424 * Shape/Polygon/Star
425 *
426 * @todo check if setting a z-index by default is a good thing
427 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
428 */
429/**
430 * Shape/Polygon/Trapezoid
431 *
432 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
433 */
434/**
435 * Shape/Polygon/Triangle
436 *
437 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
438 */
439/**
440 * Shape/Symbol
441 *
442 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
443 */
444/**
445 * Shape/Symbol/Diamond
446 *
447 * @todo add height support
448 *
449 * @author Alexander Futekov
450 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
451 */
452/**
453 * Shape/Symbol/Egg
454 *
455 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
456 */
457/**
458 * Shape/Symbol/Heart
459 *
460 * @author Nicolas Gallagher @necolas
461 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
462 */
463/**
464 * Shape/Symbol/Infinity
465 *
466 * @author Nicolas Gallagher @necolas
467 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
468 */
469/**
470 * Shape/Symbol/Pacman
471 *
472 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
473 */
474/**
475 * Shape/Symbol/Yin-yang
476 *
477 * @author Alexander Futekov
478 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
479 */
480/**
481 * Micro clearfix hack
482 *
483 * The clearfix hack is a popular way to clear floats without resorting to using presentational markup. This article presents an update to the clearfix method that further reduces the amount of CSS required.
484 * Known support: Firefox 2+, Safari 2+, Chrome, Opera 9.27+, IE 6+, IE Mac.
485 *
486 * @thanks Nicolas Gallagher @necolas
487 * @link http://nicolasgallagher.com/micro-clearfix-hack/
488 */
489/**
490 * Note IE7/6 doesn't understand pseudo element as ::before and ::after
491 * IE8 need to have :before and not ::before
492 * So use only : and not :: if you want to support IE8
493 * IE9 Webkit Firefox Opera understand ::
494 */
495/**
496 * UI convex effect from one color
497 *
498 * @todo merge with ui-button ?
499 *
500 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
501 */
502/**
503 * UI Glossy helper
504 *
505 * @deprecated
506 * @todo Remove in 0.4
507 * @see background/gradients
508 *
509 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
510 */
511/**
512 * UI simple gradient from one color
513 *
514 * @todo merge with ui-button ?
515 *
516 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
517 */
518/**
519 * Shape/Polygon/Triangle
520 *
521 * @author Maxime Thirouin maxime.thirouin@gmail.com @MoOx
522 */
523/**
524 * Keyboard key touch
525 * A simple stylesheet for rendering beautiful keyboard-style elements.
84 526
85 vertical-align: middle; 527 * @author Michael Hüneburg http://michaelhue.com/keyscss
86 border: 0; 528 * @link https://github.com/michaelhue/keyscss (commit 76bb603e921d0145362e0f60eabb79d4f69cbda0)
87 -ms-interpolation-mode: bicubic; 529 *
88} 530 * @author Maxime Thirouin @MoOx maxime.thirouin@gmail.com
89#map_canvas img, 531*/
90.google-maps img { 532/**
91 max-width: none; 533 * Menu dropdown helper
92} 534 *
93button, 535 * @author Maxime Thirouin @MoOx maxime.thirouin@gmail.com
94input, 536*/
95select, 537/**
96textarea { 538 * Ui background overlay inspired by Google Chrome modal overlay
539 *
540 * @author Maxime Thirouin @MoOx maxime.thirouin@gmail.com
541 */
542/**
543 * Background overlay inspired by Google Chrome modal overlay
544 *
545 * @author Maxime Thirouin @MoOx maxime.thirouin@gmail.com
546 */
547/**
548 * <hr /> separator style
549 *
550 * @author Chris Coyier @chriscoyier
551 * @link http://jsfiddle.net/chriscoyier/GaEzp/35/
552 *
553 * @author Maxime Thirouin @MoOx maxime.thirouin@gmail.com
554 */
555/**
556 * Micro clearfix hack
557 *
558 * The clearfix hack is a popular way to clear floats without resorting to using presentational markup. This article presents an update to the clearfix method that further reduces the amount of CSS required.
559 * Known support: Firefox 2+, Safari 2+, Chrome, Opera 9.27+, IE 6+, IE Mac.
560 *
561 * @thanks Nicolas Gallagher @necolas
562 * @link http://nicolasgallagher.com/micro-clearfix-hack/
563 */
564/**
565 * Note IE7/6 doesn't understand pseudo element as ::before and ::after
566 * IE8 need to have :before and not ::before
567 * So use only : and not :: if you want to support IE8
568 * IE9 Webkit Firefox Opera understand ::
569 */
570/**
571 *
572 * @class Gradients
573 * @author David Kaneda http://www.davidkaneda.com/
574 *
575 */
576/**
577 * Adds a background gradient into a specified selector.
578 *
579 * @include background-gradient(#444, 'glossy');
580 *
581 * You can also use color-stops if you want full control of the gradient:
582 *
583 * @include background-gradient(#444, color-stops(#333, #222, #111));
584 *
585 * @param {color} $bg-color
586 * The base color of the gradient.
587 *
588 * @param {string/list} $type
589 * The style of the gradient, one of five pre-defined options: matte, bevel, glossy, recessed, or linear:
590 *
591 * @include background-gradient(red, 'glossy');
592 *
593 * It can also accept a list of color-stop values:;
594 *
595 * @include background-gradient(black, color-stops(#333, #111, #000));
596 *
597 * @param {string} $direction
598 * The direction of the gradient.
599 */
600/**
601 * @class Webfont Icon
602 * Great to use with the [Pictos font](http://pictos.drewwilson.com/)
603 *
604 */
605/**
606 * @cfg {color} $webfont-icon-base-color
607 * The default color of icons when using the {@link #webfont-icon} mixin.
608 *
609 * Defaults to `white`.
610 */
611/**
612 * @cfg {color} $webfont-icon-default-stroke
613 * The default color to use on the border of icons, when using the {@link #webfont-icon} mixin.
614 *
615 * Defaults to `null`.
616 */
617/**
618 * @cfg {string} $webfont-icon-default-gradient
619 * The default gradient to use when using the {@link #webfont-icon} mixin.
620 *
621 * Defaults to `matte`.
622 */
623/* line 41, ../compass-recipes/stylesheets/recipes/_webfont-icon.scss */
624.webfont-icon-base {
625 color: transparent;
626 -webkit-background-clip: text;
627 background-clip: text;
628 position: absolute;
629 top: 0;
630 left: 0;
631 text-indent: 0;
632 text-shadow: none;
633 -webkit-user-select: none;
634 user-select: none;
635}
636/**
637 * Includes a character into the specified selector, styled as an icon.
638 *
639 * @include webfont-icon('a');
640 *
641 * @param {color} $color
642 * The color of the icon. Defaults to {@link #$webfont-icon-default-background $webfont-icon-default-background}.
643 *
644 * @param {measurement} $size
645 * The size of the icon
646 *
647 * @param {color} $stroke
648 * The color of the border. Defautls to {@link #$webfont-icon-default-border $webfont-icon-default-border}.
649 *
650 * @param {boolean} $include-staes
651 * True to include states for hover and active. Defaults to `true`.
652 */
653/* line 1, ../scss/include/_base.scss */
654* {
97 margin: 0; 655 margin: 0;
98 font-size: 100%;
99 vertical-align: middle;
100}
101button,
102input {
103 *overflow: visible;
104 line-height: normal;
105}
106button::-moz-focus-inner,
107input::-moz-focus-inner {
108 padding: 0; 656 padding: 0;
109 border: 0;
110}
111button,
112html input[type="button"],
113input[type="reset"],
114input[type="submit"] {
115 -webkit-appearance: button;
116 cursor: pointer;
117}
118label,
119select,
120button,
121input[type="button"],
122input[type="reset"],
123input[type="submit"],
124input[type="radio"],
125input[type="checkbox"] {
126 cursor: pointer;
127}
128input[type="search"] {
129 -webkit-box-sizing: content-box;
130 -moz-box-sizing: content-box;
131 box-sizing: content-box;
132 -webkit-appearance: textfield;
133}
134input[type="search"]::-webkit-search-decoration,
135input[type="search"]::-webkit-search-cancel-button {
136 -webkit-appearance: none;
137}
138textarea {
139 overflow: auto;
140 vertical-align: top;
141}
142@media print {
143 * {
144 text-shadow: none !important;
145 color: #000 !important;
146 background: transparent !important;
147 box-shadow: none !important;
148 }
149 a,
150 a:visited {
151 text-decoration: underline;
152 } 657 }
153 a[href]:after { 658/* line 6, ../scss/include/_base.scss */
154 content: " (" attr(href) ")"; 659body {
155 } 660 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
156 abbr[title]:after { 661 -webkit-touch-callout: none;
157 content: " (" attr(title) ")"; 662}
158 } 663/* line 11, ../scss/include/_base.scss */
159 .ir a:after, 664#jqt {
160 a[href^="javascript:"]:after, 665 -webkit-text-size-adjust: none;
161 a[href^="#"]:after { 666 -webkit-user-select: none;
162 content: ""; 667 user-select: none;
163 } 668 font-family: "Helvetica Neue", Helvetica;
164 pre, 669 position: absolute;
165 blockquote { 670 right: 0;
166 border: 1px solid #999; 671 top: 0;
167 page-break-inside: avoid; 672 left: 0;
168 } 673 bottom: 0;
169 thead {
170 display: table-header-group;
171 }
172 tr,
173 img {
174 page-break-inside: avoid;
175 }
176 img {
177 max-width: 100% !important;
178 }
179 @page {
180 margin: 0.5cm;
181 }
182 p,
183 h2,
184 h3 {
185 orphans: 3;
186 widows: 3;
187 }
188 h2,
189 h3 {
190 page-break-after: avoid;
191 }
192}
193.clearfix {
194 *zoom: 1;
195} 674}
196.clearfix:before, 675/* line 21, ../scss/include/_base.scss */
197.clearfix:after { 676#jqt a {
198 display: table; 677 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
199 content: ""; 678 -webkit-user-drag: none;
200 line-height: 0;
201} 679}
202.clearfix:after { 680/* line 26, ../scss/include/_base.scss */
203 clear: both; 681#jqt .selectable,
682#jqt input,
683#jqt textarea {
684 -webkit-user-select: auto;
204} 685}
205.hide-text { 686/* line 30, ../scss/include/_base.scss */
206 font: 0/0 a; 687#jqt.notransform {
207 color: transparent; 688 -webkit-transform: none !important;
208 text-shadow: none;
209 background-color: transparent;
210 border: 0;
211} 689}
212.input-block-level { 690/* line 35, ../scss/include/_base.scss */
691#jqt > * {
213 display: block; 692 display: block;
693 left: 0;
694 top: 0;
695 min-height: 100%;
214 width: 100%; 696 width: 100%;
215 min-height: 30px; 697 overflow-x: hidden;
216 -webkit-box-sizing: border-box; 698 position: absolute;
217 -moz-box-sizing: border-box; 699 z-index: 0;
218 box-sizing: border-box; 700 display: -webkit-box;
701 display: box;
702 -webkit-box-orient: vertical;
703 box-orient: vertical;
704 -webkit-box-flex: 1;
705 box-flex: 1;
706}
707/* line 49, ../scss/include/_base.scss */
708#jqt > .current {
709 z-index: 10;
710}
711/* line 53, ../scss/include/_base.scss */
712#jqt > :not(.current) {
713 display: none;
219} 714}
220body { 715/* line 57, ../scss/include/_base.scss */
221 margin: 0; 716#jqt.touchscroll:not(.animating3d) {
222 font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 717 overflow-y: auto;
223 font-size: 14px; 718 -webkit-overflow-scrolling: touch;
224 line-height: 20px;
225 color: #333333;
226 background-color: #ffffff;
227} 719}
228a { 720/* line 61, ../scss/include/_base.scss */
229 color: #0088cc; 721#jqt.touchscroll:not(.animating3d) > * {
230 text-decoration: none; 722 height: 100%;
231} 723}
232a:hover { 724/* line 64, ../scss/include/_base.scss */
233 color: #005580; 725#jqt.touchscroll:not(.animating3d) .scroll {
234 text-decoration: underline; 726 position: relative;
235} 727 -webkit-box-flex: 1;
236.img-rounded { 728 box-flex: 1;
237 -webkit-border-radius: 6px; 729 overflow-y: auto;
238 -moz-border-radius: 6px; 730 -webkit-overflow-scrolling: touch;
239 border-radius: 6px;
240}
241.img-polaroid {
242 padding: 4px;
243 background-color: #fff;
244 border: 1px solid #ccc;
245 border: 1px solid rgba(0, 0, 0, 0.2);
246 -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
247 -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
248 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
249}
250.img-circle {
251 -webkit-border-radius: 500px;
252 -moz-border-radius: 500px;
253 border-radius: 500px;
254} 731}
255.row { 732/* line 72, ../scss/include/_base.scss */
256 margin-left: -20px; 733#jqt .scroll {
257 *zoom: 1; 734 -webkit-margin-collapse: separate;
258} 735}
259.row:before, 736/* line 76, ../scss/include/_base.scss */
260.row:after { 737#jqt .in,
261 display: table; 738#jqt .out {
262 content: ""; 739 -webkit-animation-duration: 250ms;
263 line-height: 0; 740 -webkit-animation-fill-mode: both;
741 -webkit-animation-timing-function: ease-in-out;
264} 742}
265.row:after { 743/* line 82, ../scss/include/_base.scss */
266 clear: both; 744#jqt .in {
745 z-index: 10;
267} 746}
268[class*="span"] { 747/* line 85, ../scss/include/_base.scss */
269 float: left; 748#jqt .in:after {
270 min-height: 1px; 749 content: "";
271 margin-left: 20px; 750 position: absolute;
751 display: block;
752 top: 0;
753 left: 0;
754 bottom: 0;
755 right: 0;
272} 756}
273.container, 757/* line 94, ../scss/include/_base.scss */
274.navbar-static-top .container, 758#jqt .out {
275.navbar-fixed-top .container, 759 z-index: 0 !important;
276.navbar-fixed-bottom .container {
277 width: 940px;
278} 760}
279.span12 { 761/* line 98, ../scss/include/_base.scss */
280 width: 940px; 762#jqt.supports3d {
763 -webkit-perspective: 1000;
281} 764}
282.span11 { 765/* line 101, ../scss/include/_base.scss */
283 width: 860px; 766#jqt.supports3d > * {
767 -webkit-transform: translate3d(0, 0, 0) rotate(0) scale(1);
284} 768}
285.span10 { 769/* Fade */
286 width: 780px; 770/* line 3, ../scss/include/_animations.scss */
771#jqt .fade.in {
772 -webkit-animation-name: fadeIn;
287} 773}
288.span9 { 774/* line 7, ../scss/include/_animations.scss */
289 width: 700px; 775#jqt .fade.out {
776 z-index: 10;
777 -webkit-animation-name: fadeOut;
290} 778}
291.span8 { 779@-webkit-keyframes fadeIn {
292 width: 620px; 780 /* line 13, ../scss/include/_animations.scss */
781 0% {
782 opacity: 0;
293} 783}
294.span7 { 784 /* line 16, ../scss/include/_animations.scss */
295 width: 540px; 785 100% {
786 opacity: 1;
296} 787}
297.span6 {
298 width: 460px;
299} 788}
300.span5 { 789@-webkit-keyframes fadeOut {
301 width: 380px; 790 /* line 22, ../scss/include/_animations.scss */
791 0% {
792 opacity: 1;
302} 793}
303.span4 { 794 /* line 25, ../scss/include/_animations.scss */
304 width: 300px; 795 100% {
796 opacity: 1;
305} 797}
306.span3 {
307 width: 220px;
308} 798}
309.span2 { 799/* Disolve */
310 width: 140px; 800/* line 34, ../scss/include/_animations.scss */
801#jqt .dissolve.in {
802 -webkit-animation-name: dissolveIn;
311} 803}
312.span1 { 804/* line 38, ../scss/include/_animations.scss */
313 width: 60px; 805#jqt .dissolve.out {
806 -webkit-animation-name: dissolveOut;
314} 807}
315.offset12 { 808@-webkit-keyframes dissolveIn {
316 margin-left: 980px; 809 /* line 43, ../scss/include/_animations.scss */
810 0% {
811 opacity: 0;
317} 812}
318.offset11 { 813 /* line 46, ../scss/include/_animations.scss */
319 margin-left: 900px; 814 100% {
815 opacity: 1;
320} 816}
321.offset10 {
322 margin-left: 820px;
323} 817}
324.offset9 { 818@-webkit-keyframes dissolveOut {
325 margin-left: 740px; 819 /* line 52, ../scss/include/_animations.scss */
820 0% {
821 opacity: 1;
326} 822}
327.offset8 { 823 /* line 55, ../scss/include/_animations.scss */
328 margin-left: 660px; 824 100% {
825 opacity: 0;
329} 826}
330.offset7 {
331 margin-left: 580px;
332} 827}
333.offset6 { 828/* #Popin' */
334 margin-left: 500px; 829/* line 64, ../scss/include/_animations.scss */
830#jqt .pop.in {
831 -webkit-animation-name: popIn;
335} 832}
336.offset5 { 833/* line 68, ../scss/include/_animations.scss */
337 margin-left: 420px; 834#jqt .pop.out {
835 -webkit-animation-name: popOut;
338} 836}
339.offset4 { 837@-webkit-keyframes popIn {
340 margin-left: 340px; 838 /* line 73, ../scss/include/_animations.scss */
839 0% {
840 -webkit-transform: scale(0.2);
841 opacity: 0;
341} 842}
342.offset3 { 843 /* line 77, ../scss/include/_animations.scss */
343 margin-left: 260px; 844 100% {
845 -webkit-transform: scale(1);
846 opacity: 1;
344} 847}
345.offset2 {
346 margin-left: 180px;
347} 848}
348.offset1 { 849@-webkit-keyframes popOut {
349 margin-left: 100px; 850 /* line 84, ../scss/include/_animations.scss */
851 0% {
852 -webkit-transform: scale(1);
853 opacity: 1;
350} 854}
351.row-fluid { 855 /* line 88, ../scss/include/_animations.scss */
352 width: 100%; 856 100% {
353 *zoom: 1; 857 -webkit-transform: scale(0.2);
858 opacity: 0;
354} 859}
355.row-fluid:before,
356.row-fluid:after {
357 display: table;
358 content: "";
359 line-height: 0;
360} 860}
361.row-fluid:after { 861/* Slide Left */
362 clear: both; 862/* line 98, ../scss/include/_animations.scss */
863#jqt .slideleft.in {
864 -webkit-animation-name: slideLeftIn;
363} 865}
364.row-fluid [class*="span"] { 866/* line 102, ../scss/include/_animations.scss */
365 display: block; 867#jqt .slideleft.out {
366 width: 100%; 868 -webkit-animation-name: slideLeftOut;
367 min-height: 30px;
368 -webkit-box-sizing: border-box;
369 -moz-box-sizing: border-box;
370 box-sizing: border-box;
371 float: left;
372 margin-left: 2.127659574468085%;
373 *margin-left: 2.074468085106383%;
374} 869}
375.row-fluid [class*="span"]:first-child { 870@-webkit-keyframes slideLeftIn {
376 margin-left: 0; 871 /* line 107, ../scss/include/_animations.scss */
872 0% {
873 -webkit-transform: translateX(100%);
377} 874}
378.row-fluid .controls-row [class*="span"] + [class*="span"] { 875 /* line 110, ../scss/include/_animations.scss */
379 margin-left: 2.127659574468085%; 876 100% {
877 -webkit-transform: translateX(0);
380} 878}
381.row-fluid .span12 {
382 width: 100%;
383 *width: 99.94680851063829%;
384} 879}
385.row-fluid .span11 { 880@-webkit-keyframes slideLeftOut {
386 width: 91.48936170212765%; 881 /* line 116, ../scss/include/_animations.scss */
387 *width: 91.43617021276594%; 882 0% {
883 -webkit-transform: translateX(0px);
388} 884}
389.row-fluid .span10 { 885 /* line 119, ../scss/include/_animations.scss */
390 width: 82.97872340425532%; 886 100% {
391 *width: 82.92553191489361%; 887 -webkit-transform: translateX(-100%);
392} 888}
393.row-fluid .span9 {
394 width: 74.46808510638297%;
395 *width: 74.41489361702126%;
396} 889}
397.row-fluid .span8 { 890/* Slide Right */
398 width: 65.95744680851064%; 891/* line 128, ../scss/include/_animations.scss */
399 *width: 65.90425531914893%; 892#jqt .slideright.in {
893 -webkit-animation-name: slideRightIn;
400} 894}
401.row-fluid .span7 { 895/* line 132, ../scss/include/_animations.scss */
402 width: 57.44680851063829%; 896#jqt .slideright.out {
403 *width: 57.39361702127659%; 897 -webkit-animation-name: slideRightOut;
404} 898}
405.row-fluid .span6 { 899@-webkit-keyframes slideRightIn {
406 width: 48.93617021276595%; 900 /* line 137, ../scss/include/_animations.scss */
407 *width: 48.88297872340425%; 901 0% {
902 -webkit-transform: translateX(-100%);
408} 903}
409.row-fluid .span5 { 904 /* line 140, ../scss/include/_animations.scss */
410 width: 40.42553191489362%; 905 100% {
411 *width: 40.37234042553192%; 906 -webkit-transform: translateX(0);
412} 907}
413.row-fluid .span4 {
414 width: 31.914893617021278%;
415 *width: 31.861702127659576%;
416} 908}
417.row-fluid .span3 { 909@-webkit-keyframes slideRightOut {
418 width: 23.404255319148934%; 910 /* line 146, ../scss/include/_animations.scss */
419 *width: 23.351063829787233%; 911 0% {
912 -webkit-transform: translateX(0);
420} 913}
421.row-fluid .span2 { 914 /* line 149, ../scss/include/_animations.scss */
422 width: 14.893617021276595%; 915 100% {
423 *width: 14.840425531914894%; 916 -webkit-transform: translateX(100%);
424} 917}
425.row-fluid .span1 {
426 width: 6.382978723404255%;
427 *width: 6.329787234042553%;
428} 918}
429.row-fluid .offset12 { 919/* Slide Up */
430 margin-left: 104.25531914893617%; 920/* line 158, ../scss/include/_animations.scss */
431 *margin-left: 104.14893617021275%; 921#jqt .slideup.in {
922 z-index: 10;
923 -webkit-animation-name: slideUpIn;
432} 924}
433.row-fluid .offset12:first-child { 925/* line 162, ../scss/include/_animations.scss */
434 margin-left: 102.12765957446808%; 926#jqt .slideup.out {
435 *margin-left: 102.02127659574467%; 927 z-index: 0;
928 -webkit-animation-name: slideUpOut;
436} 929}
437.row-fluid .offset11 { 930@-webkit-keyframes slideUpIn {
438 margin-left: 95.74468085106382%; 931 /* line 168, ../scss/include/_animations.scss */
439 *margin-left: 95.6382978723404%; 932 0% {
933 -webkit-transform: translateY(100%);
440} 934}
441.row-fluid .offset11:first-child { 935 /* line 171, ../scss/include/_animations.scss */
442 margin-left: 93.61702127659574%; 936 100% {
443 *margin-left: 93.51063829787232%; 937 -webkit-transform: translateY(0);
444} 938}
445.row-fluid .offset10 {
446 margin-left: 87.23404255319149%;
447 *margin-left: 87.12765957446807%;
448} 939}
449.row-fluid .offset10:first-child { 940@-webkit-keyframes slideUpOut {
450 margin-left: 85.1063829787234%; 941 /* line 177, ../scss/include/_animations.scss */
451 *margin-left: 84.99999999999999%; 942 0% {
943 -webkit-transform: translateY(0);
452} 944}
453.row-fluid .offset9 { 945 /* line 180, ../scss/include/_animations.scss */
454 margin-left: 78.72340425531914%; 946 100% {
455 *margin-left: 78.61702127659572%; 947 -webkit-transform: translateY(0);
456} 948}
457.row-fluid .offset9:first-child {
458 margin-left: 76.59574468085106%;
459 *margin-left: 76.48936170212764%;
460} 949}
461.row-fluid .offset8 { 950/* Slide Down */
462 margin-left: 70.2127659574468%; 951/* line 189, ../scss/include/_animations.scss */
463 *margin-left: 70.10638297872339%; 952#jqt .slidedown.in {
953 z-index: 0;
954 -webkit-animation-name: slideDownIn;
464} 955}
465.row-fluid .offset8:first-child { 956/* line 193, ../scss/include/_animations.scss */
466 margin-left: 68.08510638297872%; 957#jqt .slidedown.out {
467 *margin-left: 67.9787234042553%; 958 z-index: 10;
959 -webkit-animation-name: slideDownOut;
468} 960}
469.row-fluid .offset7 { 961@-webkit-keyframes slideDownIn {
470 margin-left: 61.70212765957446%; 962 /* line 199, ../scss/include/_animations.scss */
471 *margin-left: 61.59574468085106%; 963 0% {
964 -webkit-transform: translateY(0);
472} 965}
473.row-fluid .offset7:first-child { 966 /* line 202, ../scss/include/_animations.scss */
474 margin-left: 59.574468085106375%; 967 100% {
475 *margin-left: 59.46808510638297%; 968 -webkit-transform: translateY(0);
476} 969}
477.row-fluid .offset6 {
478 margin-left: 53.191489361702125%;
479 *margin-left: 53.085106382978715%;
480} 970}
481.row-fluid .offset6:first-child { 971@-webkit-keyframes slideDownOut {
482 margin-left: 51.063829787234035%; 972 /* line 208, ../scss/include/_animations.scss */
483 *margin-left: 50.95744680851063%; 973 0% {
974 -webkit-transform: translateY(0);
484} 975}
485.row-fluid .offset5 { 976 /* line 211, ../scss/include/_animations.scss */
486 margin-left: 44.68085106382979%; 977 100% {
487 *margin-left: 44.57446808510638%; 978 -webkit-transform: translateY(100%);
488} 979}
489.row-fluid .offset5:first-child {
490 margin-left: 42.5531914893617%;
491 *margin-left: 42.4468085106383%;
492} 980}
493.row-fluid .offset4 { 981/* Flip Left */
494 margin-left: 36.170212765957444%; 982/* line 220, ../scss/include/_animations.scss */
495 *margin-left: 36.06382978723405%; 983#jqt .flipleft {
984 -webkit-backface-visibility: hidden;
496} 985}
497.row-fluid .offset4:first-child { 986/* line 224, ../scss/include/_animations.scss */
498 margin-left: 34.04255319148936%; 987#jqt .flipleft.in {
499 *margin-left: 33.93617021276596%; 988 -webkit-animation-name: flipLeftIn;
500} 989}
501.row-fluid .offset3 { 990/* line 228, ../scss/include/_animations.scss */
502 margin-left: 27.659574468085104%; 991#jqt .flipleft.out {
503 *margin-left: 27.5531914893617%; 992 -webkit-animation-name: flipLeftOut;
504} 993}
505.row-fluid .offset3:first-child { 994@-webkit-keyframes flipLeftIn {
506 margin-left: 25.53191489361702%; 995 /* line 233, ../scss/include/_animations.scss */
507 *margin-left: 25.425531914893618%; 996 0% {
997 -webkit-transform: rotateY(180deg) scale(0.8);
508} 998}
509.row-fluid .offset2 { 999 /* line 236, ../scss/include/_animations.scss */
510 margin-left: 19.148936170212764%; 1000 100% {
511 *margin-left: 19.04255319148936%; 1001 -webkit-transform: rotateY(0deg) scale(1);
512} 1002}
513.row-fluid .offset2:first-child {
514 margin-left: 17.02127659574468%;
515 *margin-left: 16.914893617021278%;
516} 1003}
517.row-fluid .offset1 { 1004@-webkit-keyframes flipLeftOut {
518 margin-left: 10.638297872340425%; 1005 /* line 242, ../scss/include/_animations.scss */
519 *margin-left: 10.53191489361702%; 1006 0% {
1007 -webkit-transform: rotateY(0deg) scale(1);
520} 1008}
521.row-fluid .offset1:first-child { 1009 /* line 245, ../scss/include/_animations.scss */
522 margin-left: 8.51063829787234%; 1010 100% {
523 *margin-left: 8.404255319148938%; 1011 -webkit-transform: rotateY(-180deg) scale(0.8);
524} 1012}
525[class*="span"].hide,
526.row-fluid [class*="span"].hide {
527 display: none;
528} 1013}
529[class*="span"].pull-right, 1014/* Flip Right */
530.row-fluid [class*="span"].pull-right { 1015/* line 254, ../scss/include/_animations.scss */
531 float: right; 1016#jqt .flipright {
1017 -webkit-backface-visibility: hidden;
532} 1018}
533.container { 1019/* line 258, ../scss/include/_animations.scss */
534 margin-right: auto; 1020#jqt .flipright.in {
535 margin-left: auto; 1021 -webkit-animation-name: flipRightIn;
536 *zoom: 1;
537} 1022}
538.container:before, 1023/* line 262, ../scss/include/_animations.scss */
539.container:after { 1024#jqt .flipright.out {
540 display: table; 1025 -webkit-animation-name: flipRightOut;
541 content: "";
542 line-height: 0;
543} 1026}
544.container:after { 1027@-webkit-keyframes flipRightIn {
545 clear: both; 1028 /* line 267, ../scss/include/_animations.scss */
1029 0% {
1030 -webkit-transform: rotateY(-180deg) scale(0.8);
546} 1031}
547.container-fluid { 1032 /* line 270, ../scss/include/_animations.scss */
548 padding-right: 20px; 1033 100% {
549 padding-left: 20px; 1034 -webkit-transform: rotateY(0deg) scale(1);
550 *zoom: 1;
551} 1035}
552.container-fluid:before,
553.container-fluid:after {
554 display: table;
555 content: "";
556 line-height: 0;
557} 1036}
558.container-fluid:after { 1037@-webkit-keyframes flipRightOut {
559 clear: both; 1038 /* line 276, ../scss/include/_animations.scss */
1039 0% {
1040 -webkit-transform: rotateY(0deg) scale(1);
560} 1041}
561p { 1042 /* line 279, ../scss/include/_animations.scss */
562 margin: 0 0 10px; 1043 100% {
1044 -webkit-transform: rotateY(180deg) scale(0.8);
563} 1045}
564.lead {
565 margin-bottom: 20px;
566 font-size: 21px;
567 font-weight: 200;
568 line-height: 30px;
569} 1046}
570small { 1047/* Swap Right */
571 font-size: 85%; 1048/* line 288, ../scss/include/_animations.scss */
1049#jqt .swapright {
1050 -webkit-animation-duration: .7s;
1051 -webkit-transform: perspective(800);
1052 -webkit-animation-timing-function: ease-out;
572} 1053}
573strong { 1054/* line 293, ../scss/include/_animations.scss */
574 font-weight: bold; 1055#jqt .swapright.in {
1056 -webkit-animation-name: swapRightIn;
575} 1057}
576em { 1058/* line 296, ../scss/include/_animations.scss */
577 font-style: italic; 1059#jqt .swapright.out {
1060 -webkit-animation-name: swapRightOut;
578} 1061}
579cite { 1062@-webkit-keyframes swapRightIn {
580 font-style: normal; 1063 /* line 301, ../scss/include/_animations.scss */
1064 0% {
1065 -webkit-transform: translate3d(0px, 0px, -800px) rotateY(70deg);
1066 opacity: 0;
581} 1067}
582.muted { 1068 /* line 305, ../scss/include/_animations.scss */
583 color: #999999; 1069 35% {
1070 -webkit-transform: translate3d(-180px, 0px, -400px) rotateY(20deg);
1071 opacity: 1;
584} 1072}
585a.muted:hover { 1073 /* line 309, ../scss/include/_animations.scss */
586 color: #808080; 1074 100% {
1075 -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
1076 opacity: 1;
587} 1077}
588.text-warning {
589 color: #c09853;
590} 1078}
591a.text-warning:hover { 1079@-webkit-keyframes swapRightOut {
592 color: #a47e3c; 1080 /* line 316, ../scss/include/_animations.scss */
1081 0% {
1082 -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
1083 opacity: 1;
593} 1084}
594.text-error { 1085 /* line 320, ../scss/include/_animations.scss */
595 color: #b94a48; 1086 35% {
1087 -webkit-transform: translate3d(180px, 0px, -400px) rotateY(-20deg);
1088 opacity: .5;
596} 1089}
597a.text-error:hover { 1090 /* line 324, ../scss/include/_animations.scss */
598 color: #953b39; 1091 100% {
1092 -webkit-transform: translate3d(0px, 0px, -800px) rotateY(-70deg);
1093 opacity: 0;
599} 1094}
600.text-info {
601 color: #3a87ad;
602} 1095}
603a.text-info:hover { 1096/* Swap Left */
604 color: #2d6987; 1097/* line 332, ../scss/include/_animations.scss */
1098#jqt .swapleft {
1099 -webkit-animation-duration: .7s;
1100 -webkit-transform: perspective(800);
1101 -webkit-animation-timing-function: ease-out;
605} 1102}
606.text-success { 1103/* line 337, ../scss/include/_animations.scss */
607 color: #468847; 1104#jqt .swapleft.in {
1105 -webkit-animation-name: swapLeftIn;
608} 1106}
609a.text-success:hover { 1107/* line 340, ../scss/include/_animations.scss */
610 color: #356635; 1108#jqt .swapleft.out {
1109 -webkit-animation-name: swapLeftOut;
611} 1110}
612h1, 1111@-webkit-keyframes swapLeftIn {
613h2, 1112 /* line 345, ../scss/include/_animations.scss */
614h3, 1113 0% {
615h4, 1114 -webkit-transform: translate3d(0px, 0px, -800px) rotateY(-70deg);
616h5, 1115 opacity: 0;
617h6 {
618 margin: 10px 0;
619 font-family: inherit;
620 font-weight: bold;
621 line-height: 20px;
622 color: inherit;
623 text-rendering: optimizelegibility;
624}
625h1 small,
626h2 small,
627h3 small,
628h4 small,
629h5 small,
630h6 small {
631 font-weight: normal;
632 line-height: 1;
633 color: #999999;
634} 1116}
635h1, 1117 /* line 349, ../scss/include/_animations.scss */
636h2, 1118 35% {
637h3 { 1119 -webkit-transform: translate3d(180px, 0px, -400px) rotateY(-20deg);
638 line-height: 40px; 1120 opacity: 1;
639} 1121}
640h1 { 1122 /* line 353, ../scss/include/_animations.scss */
641 font-size: 38.5px; 1123 100% {
1124 opacity: 1;
1125 -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
642} 1126}
643h2 {
644 font-size: 31.5px;
645} 1127}
646h3 { 1128@-webkit-keyframes swapLeftOut {
647 font-size: 24.5px; 1129 /* line 360, ../scss/include/_animations.scss */
1130 0% {
1131 -webkit-transform: translate3d(0px, 0px, 0px) rotateY(0deg);
1132 opacity: 1;
648} 1133}
649h4 { 1134 /* line 364, ../scss/include/_animations.scss */
650 font-size: 17.5px; 1135 35% {
1136 -webkit-transform: translate3d(-180px, 0px, -400px) rotateY(20deg);
1137 opacity: .5;
651} 1138}
652h5 { 1139 /* line 368, ../scss/include/_animations.scss */
653 font-size: 14px; 1140 100% {
1141 -webkit-transform: translate3d(0px, 0px, -800px) rotateY(70deg);
1142 opacity: 0;
654} 1143}
655h6 {
656 font-size: 11.9px;
657} 1144}
658h1 small { 1145/* Cube Left */
659 font-size: 24.5px; 1146/* line 382, ../scss/include/_animations.scss */
1147#jqt .cubeleft.in,
1148#jqt .cubeleft.out,
1149#jqt .cuberight.in,
1150#jqt .cuberight.out {
1151 -webkit-animation-duration: .6s;
1152 -webkit-transform: perspective(800);
1153}
1154/* line 389, ../scss/include/_animations.scss */
1155#jqt .cubeleft.in {
1156 -webkit-transform-origin: 0% 50%;
1157 -webkit-animation-name: cubeLeftIn;
1158}
1159/* line 394, ../scss/include/_animations.scss */
1160#jqt .cubeleft.out {
1161 -webkit-transform-origin: 100% 50%;
1162 -webkit-animation-name: cubeLeftOut;
1163}
1164@-webkit-keyframes cubeLeftIn {
1165 /* line 400, ../scss/include/_animations.scss */
1166 0% {
1167 -webkit-transform: rotateY(90deg) translateZ(320px);
1168 opacity: .5;
1169 }
1170 /* line 404, ../scss/include/_animations.scss */
1171 100% {
1172 -webkit-transform: rotateY(0deg) translateZ(0) translateX(0);
1173 opacity: 1;
660} 1174}
661h2 small {
662 font-size: 17.5px;
663} 1175}
664h3 small { 1176@-webkit-keyframes cubeLeftOut {
665 font-size: 14px; 1177 /* line 411, ../scss/include/_animations.scss */
1178 0% {
1179 -webkit-transform: rotateY(0deg) translateZ(0) translateX(0);
1180 opacity: 1;
666} 1181}
667h4 small { 1182 /* line 415, ../scss/include/_animations.scss */
668 font-size: 14px; 1183 100% {
1184 -webkit-transform: rotateY(-90deg) translateZ(320px);
1185 opacity: .5;
669} 1186}
670.page-header {
671 padding-bottom: 9px;
672 margin: 20px 0 30px;
673 border-bottom: 1px solid #eeeeee;
674} 1187}
675ul, 1188/* Cube Right */
676ol { 1189/* line 423, ../scss/include/_animations.scss */
677 padding: 0; 1190#jqt .cuberight.in {
678 margin: 0 0 10px 25px; 1191 -webkit-transform-origin: 100% 50%;
1192 -webkit-animation-name: cubeRightIn;
679} 1193}
680ul ul, 1194/* line 428, ../scss/include/_animations.scss */
681ul ol, 1195#jqt .cuberight.out {
682ol ol, 1196 -webkit-transform-origin: 0% 50%;
683ol ul { 1197 -webkit-animation-name: cubeRightOut;
684 margin-bottom: 0;
685} 1198}
686li { 1199@-webkit-keyframes cubeRightIn {
687 line-height: 20px; 1200 /* line 434, ../scss/include/_animations.scss */
1201 0% {
1202 -webkit-transform: rotateY(-90deg) translateZ(320px);
1203 opacity: .5;
688} 1204}
689ul.unstyled, 1205 /* line 438, ../scss/include/_animations.scss */
690ol.unstyled { 1206 100% {
691 margin-left: 0; 1207 -webkit-transform: rotateY(0deg) translateZ(0) translateX(0);
692 list-style: none; 1208 opacity: 1;
693} 1209}
694ul.inline,
695ol.inline {
696 margin-left: 0;
697 list-style: none;
698} 1210}
699ul.inline > li, 1211@-webkit-keyframes cubeRightOut {
700ol.inline > li { 1212 /* line 445, ../scss/include/_animations.scss */
701 display: inline-block; 1213 0% {
702 padding-left: 5px; 1214 -webkit-transform: rotateY(0deg) translateZ(0) translateX(0);
703 padding-right: 5px; 1215 opacity: 1;
704} 1216}
705dl { 1217 /* line 449, ../scss/include/_animations.scss */
706 margin-bottom: 20px; 1218 100% {
1219 -webkit-transform: rotateY(90deg) translateZ(320px);
1220 opacity: .5;
707} 1221}
708dt,
709dd {
710 line-height: 20px;
711} 1222}
712dt { 1223/* line 5, ../scss/include/_skeleton.scss */
1224body {
1225 background: black;
1226}
1227/* line 9, ../scss/include/_skeleton.scss */
1228.base-chevron,
1229#jqt ul li.arrow:after,
1230#jqt ul li.forward:after {
1231 content: '›';
1232 width: 22px;
1233 height: 100%;
1234 vertical-align: middle;
1235 font-size: 30px;
1236 line-height: 38px;
1237 font-family: Futura, "Futura Condensed", Helvetica, Arial, sans-serif;
713 font-weight: bold; 1238 font-weight: bold;
1239 filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60);
1240 opacity: 0.6;
1241 position: absolute;
1242 right: 0;
1243 top: 0;
1244 pointer-events: none;
1245 z-index: 10;
1246}
1247/* line 26, ../scss/include/_skeleton.scss */
1248.base-flatlists,
1249#jqt ul.metal,
1250#jqt ul.edgetoedge,
1251#jqt ul.plastic {
1252 margin: 0;
1253 padding: 0;
1254 border-width: 0 0 0 1px;
1255 -webkit-border-radius: 0;
1256 border-radius: 0;
714} 1257}
715dd { 1258/* line 35, ../scss/include/_skeleton.scss */
716 margin-left: 10px; 1259#jqt h1,
717} 1260#jqt h2 {
718.dl-horizontal { 1261 font: bold 18px "Helvetica Neue", Helvetica;
719 *zoom: 1; 1262 margin: 10px 20px 6px;
720} 1263 color: #bbbcbe;
721.dl-horizontal:before, 1264 text-shadow: #3c3d3e 0 -1px 0;
722.dl-horizontal:after {
723 display: table;
724 content: "";
725 line-height: 0;
726} 1265}
727.dl-horizontal:after { 1266/* line 41, ../scss/include/_skeleton.scss */
728 clear: both; 1267#jqt .toolbar {
1268 -webkit-box-sizing: border-box;
1269 box-sizing: border-box;
1270 -webkit-box-shadow: rgba(0, 0, 0, 0.4) 0 1px 6px;
1271 box-shadow: rgba(0, 0, 0, 0.4) 0 1px 6px;
1272 border-bottom: 1px solid black;
1273 z-index: 10;
1274 position: relative;
1275 padding: 10px;
1276 height: 44px;
729} 1277}
730.dl-horizontal dt { 1278/* line 52, ../scss/include/_skeleton.scss */
731 float: left; 1279#jqt .toolbar > h1 {
732 width: 160px; 1280 position: absolute;
733 clear: left;
734 text-align: right;
735 overflow: hidden; 1281 overflow: hidden;
1282 left: 50%;
1283 bottom: 9px;
1284 margin: 1px 0 0 -75px;
1285 width: 150px;
1286 font-size: 20px;
1287 font-weight: bold;
1288 line-height: 1.3em;
1289 text-align: center;
736 text-overflow: ellipsis; 1290 text-overflow: ellipsis;
737 white-space: nowrap; 1291 white-space: nowrap;
1292 color: white;
1293 text-shadow: #161717 0 -1px 0;
1294}
1295/* line 71, ../scss/include/_skeleton.scss */
1296#jqt.black-translucent .toolbar {
1297 padding-top: 30px;
1298 height: 64px;
1299}
1300/* line 75, ../scss/include/_skeleton.scss */
1301#jqt.landscape .toolbar > h1 {
1302 margin-left: -125px;
1303 width: 250px;
1304}
1305/* line 80, ../scss/include/_skeleton.scss */
1306#jqt .button,
1307#jqt .back,
1308#jqt .cancel,
1309#jqt .add {
1310 position: absolute;
1311 overflow: hidden;
1312 width: auto;
1313 height: 30px;
1314 font-family: inherit;
1315 font-size: 12px;
1316 font-weight: bold;
1317 line-height: 30px;
1318 text-overflow: ellipsis;
1319 text-decoration: none;
1320 white-space: nowrap;
1321 background: none;
1322 bottom: 6px;
1323 right: 10px;
1324 margin: 0;
1325 padding: 0 10px;
1326 color: #e2e3e3;
1327 text-shadow: #000000 0 -1px 0;
1328 -webkit-box-shadow: rgba(255, 255, 255, 0.2) 0 1px 0, rgba(0, 0, 0, 0.2) 0 1px 2px inset;
1329 box-shadow: rgba(255, 255, 255, 0.2) 0 1px 0, rgba(0, 0, 0, 0.2) 0 1px 2px inset;
1330 border: 1px solid black;
1331 -webkit-border-radius: 5px;
1332 border-radius: 5px;
1333 background-image: none;
1334 background-color: #0a0a0a;
1335 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2f3031), color-stop(50%, #161717), color-stop(51%, #0a0a0a), color-stop(100%, #000000));
1336 background-image: -webkit-linear-gradient(top, #2f3031, #161717 50%, #0a0a0a 51%, #000000);
1337 background-image: linear-gradient(top, #2f3031, #161717 50%, #0a0a0a 51%, #000000);
1338}
1339/* line 107, ../scss/include/_skeleton.scss */
1340#jqt .button.active,
1341#jqt .back.active,
1342#jqt .cancel.active,
1343#jqt .add.active {
1344 border-color: black;
1345 background-image: none;
1346 background-color: black;
1347 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #262627), color-stop(50%, #0d0d0d), color-stop(51%, #000000), color-stop(100%, #000000));
1348 background-image: -webkit-linear-gradient(top, #262627, #0d0d0d 50%, #000000 51%, #000000);
1349 background-image: linear-gradient(top, #262627, #0d0d0d 50%, #000000 51%, #000000);
1350 color: #d8d9d9;
1351 text-shadow: #000000 0 -1px 0;
1352}
1353/* line 114, ../scss/include/_skeleton.scss */
1354#jqt .back {
1355 max-width: 60px;
1356 margin-left: 15px;
1357 overflow: visible;
1358 padding-left: 5px;
738} 1359}
739.dl-horizontal dd { 1360/* line 121, ../scss/include/_skeleton.scss */
740 margin-left: 180px; 1361#jqt .back:after,
741} 1362#jqt .back:before {
742hr { 1363 content: '';
743 margin: 20px 0; 1364 position: absolute;
744 border: 0; 1365 width: 20px;
745 border-top: 1px solid #eeeeee; 1366 height: 20px;
746 border-bottom: 1px solid #ffffff; 1367 top: 1px;
747} 1368 left: 1px;
748abbr[title], 1369 -webkit-transform: rotate(45deg) translate3d(0.2px, 0, 0);
749abbr[data-original-title] { 1370 transform: rotate(45deg) translate3d(0.2px, 0, 0);
750 cursor: help; 1371 -webkit-transform-origin: 0 0;
751 border-bottom: 1px dotted #999999; 1372 transform-origin: 0 0;
1373 background-image: none;
1374 background-color: #0a0a0a;
1375 background-image: -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, #2f3031), color-stop(50%, #161717), color-stop(51%, #0a0a0a), color-stop(100%, #000000));
1376 background-image: -webkit-linear-gradient(top left, #2f3031, #161717 50%, #0a0a0a 51%, #000000);
1377 background-image: linear-gradient(top left, #2f3031, #161717 50%, #0a0a0a 51%, #000000);
1378 background-size: 100% 98%;
1379 -webkit-border-radius: 0 0 0 2px;
1380 border-radius: 0 0 0 2px;
1381 -webkit-mask-image: -webkit-linear-gradient(45deg, #000000, #000000 15px, rgba(0, 0, 0, 0) 15px);
1382 -webkit-mask-image: -webkit-gradient(linear, left bottom, right top, from(#000000), color-stop(50%, #000000), color-stop(50%, rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0)));
1383 -webkit-mask-clip: border-box;
1384 -webkit-background-clip: content-box;
1385}
1386/* line 149, ../scss/include/_skeleton.scss */
1387#jqt .back:after {
1388 -webkit-box-shadow: rgba(0, 0, 0, 0.2) 1px 0 0 inset, rgba(0, 0, 0, 0.2) 0 -1px 0 inset;
1389 box-shadow: rgba(0, 0, 0, 0.2) 1px 0 0 inset, rgba(0, 0, 0, 0.2) 0 -1px 0 inset;
1390}
1391/* line 152, ../scss/include/_skeleton.scss */
1392#jqt .back:before {
1393 margin-left: -1px;
1394 background: black none;
752} 1395}
753abbr.initialism { 1396/* line 157, ../scss/include/_skeleton.scss */
754 font-size: 90%; 1397#jqt .back.active:after {
755 text-transform: uppercase; 1398 background-image: none;
1399 background-color: black;
1400 background-image: -webkit-gradient(linear, 0% 0%, 100% 100%, color-stop(0%, #262627), color-stop(50%, #0d0d0d), color-stop(51%, #000000), color-stop(100%, #000000));
1401 background-image: -webkit-linear-gradient(left top, #262627, #0d0d0d 50%, #000000 51%, #000000);
1402 background-image: linear-gradient(left top, #262627, #0d0d0d 50%, #000000 51%, #000000);
1403}
1404/* line 160, ../scss/include/_skeleton.scss */
1405#jqt .back.active:before {
1406 background-color: black;
1407}
1408/* line 166, ../scss/include/_skeleton.scss */
1409#jqt .blueButton {
1410 background-image: #2f7ce3, glossy;
1411 color: white;
1412 text-shadow: #1a63c5 0 -1px 0;
1413}
1414/* line 170, ../scss/include/_skeleton.scss */
1415#jqt .whiteButton,
1416#jqt .grayButton,
1417#jqt .redButton,
1418#jqt .blueButton,
1419#jqt .greenButton {
1420 display: block;
1421 font-size: 20px;
1422 font-weight: bold;
1423 margin: 10px 20px;
1424 padding: 10px;
1425 text-align: center;
1426 text-decoration: inherit;
1427 -webkit-border-radius: 8px;
1428 border-radius: 8px;
1429 -webkit-box-shadow: rgba(0, 0, 0, 0.4) 0 1px 3px, rgba(0, 0, 0, 0.4) 0 0 0 5px, rgba(255, 255, 255, 0.3) 0 1px 0 5px;
1430 box-shadow: rgba(0, 0, 0, 0.4) 0 1px 3px, rgba(0, 0, 0, 0.4) 0 0 0 5px, rgba(255, 255, 255, 0.3) 0 1px 0 5px;
1431}
1432/* line 185, ../scss/include/_skeleton.scss */
1433#jqt .whiteButton.active,
1434#jqt .whiteButton:active,
1435#jqt .grayButton.active,
1436#jqt .grayButton:active,
1437#jqt .redButton.active,
1438#jqt .redButton:active,
1439#jqt .blueButton.active,
1440#jqt .blueButton:active,
1441#jqt .greenButton.active,
1442#jqt .greenButton:active {
1443 background-image: none;
1444 background-color: #3c8101;
1445 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #5fcd01), color-stop(50%, #479b01), color-stop(51%, #3c8101), color-stop(100%, #306801));
1446 background-image: -webkit-linear-gradient(top, #5fcd01, #479b01 50%, #3c8101 51%, #306801);
1447 background-image: linear-gradient(top, #5fcd01, #479b01 50%, #3c8101 51%, #306801);
1448 color: white;
1449 text-shadow: #244f00 0 -1px 0;
1450}
1451/* line 191, ../scss/include/_skeleton.scss */
1452#jqt .whiteButton {
1453 background-image: none;
1454 background-color: #eeeeee;
1455 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(50%, #fbfbfb), color-stop(51%, #eeeeee), color-stop(100%, #e1e1e1));
1456 background-image: -webkit-linear-gradient(top, #ffffff, #fbfbfb 50%, #eeeeee 51%, #e1e1e1);
1457 background-image: linear-gradient(top, #ffffff, #fbfbfb 50%, #eeeeee 51%, #e1e1e1);
1458 color: #151515;
1459 text-shadow: white 0 1px 0;
1460}
1461/* line 195, ../scss/include/_skeleton.scss */
1462#jqt .grayButton {
1463 background-image: none;
1464 background-color: #444444;
1465 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #6a6a6a), color-stop(50%, #515151), color-stop(51%, #444444), color-stop(100%, #373737));
1466 background-image: -webkit-linear-gradient(top, #6a6a6a, #515151 50%, #444444 51%, #373737);
1467 background-image: linear-gradient(top, #6a6a6a, #515151 50%, #444444 51%, #373737);
1468 color: white;
1469 text-shadow: #2b2b2b 0 -1px 0;
1470}
1471/* line 200, ../scss/include/_skeleton.scss */
1472#jqt .redButton {
1473 background-image: none;
1474 background-color: #d83b38;
1475 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e57a78), color-stop(50%, #dc504d), color-stop(51%, #d83b38), color-stop(100%, #ce2c28));
1476 background-image: -webkit-linear-gradient(top, #e57a78, #dc504d 50%, #d83b38 51%, #ce2c28);
1477 background-image: linear-gradient(top, #e57a78, #dc504d 50%, #d83b38 51%, #ce2c28);
1478 color: white;
1479 text-shadow: #b92724 0 -1px 0;
1480}
1481/* line 204, ../scss/include/_skeleton.scss */
1482#jqt .redButton.active,
1483#jqt .redButton:active {
1484 background-image: none;
1485 background-color: #c12926;
1486 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #de5856), color-stop(50%, #d52e2b), color-stop(51%, #c12926), color-stop(100%, #ac2422));
1487 background-image: -webkit-linear-gradient(top, #de5856, #d52e2b 50%, #c12926 51%, #ac2422);
1488 background-image: linear-gradient(top, #de5856, #d52e2b 50%, #c12926 51%, #ac2422);
1489 color: white;
1490 text-shadow: #97201e 0 -1px 0;
1491}
1492/* line 211, ../scss/include/_skeleton.scss */
1493#jqt .greenButton {
1494 background-image: none;
1495 background-color: #53b401;
1496 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #76fe04), color-stop(50%, #5fcd01), color-stop(51%, #53b401), color-stop(100%, #479b01));
1497 background-image: -webkit-linear-gradient(top, #76fe04, #5fcd01 50%, #53b401 51%, #479b01);
1498 background-image: linear-gradient(top, #76fe04, #5fcd01 50%, #53b401 51%, #479b01);
1499 color: white;
1500 text-shadow: #3c8101 0 -1px 0;
1501}
1502/* line 216, ../scss/include/_skeleton.scss */
1503#jqt .leftButton,
1504#jqt .cancel,
1505#jqt .back {
1506 left: 6px;
1507 right: auto;
1508}
1509/* line 221, ../scss/include/_skeleton.scss */
1510#jqt .add {
1511 font-size: 24px;
1512 line-height: 24px;
1513 font-weight: bold;
756} 1514}
757blockquote { 1515/* line 229, ../scss/include/_skeleton.scss */
758 padding: 0 0 0 15px; 1516#jqt ul {
759 margin: 0 0 20px; 1517 padding: 0;
760 border-left: 5px solid #eeeeee; 1518 margin: 5px 10px 10px 10px;
1519 -webkit-margin-collapse: separate;
1520}
1521/* line 231, ../scss/include/_skeleton.scss */
1522#jqt ul,
1523#jqt ul.individual li {
1524 background-color: #555658;
1525 color: #d5d6d7;
1526 text-shadow: #3c3d3e 0 -1px 0;
1527 border: 1px solid #2f3031;
1528 font: bold 18px "Helvetica Neue", Helvetica;
1529}
1530/* line 240, ../scss/include/_skeleton.scss */
1531#jqt ul:first-child {
1532 margin-top: 15px;
761} 1533}
762blockquote p { 1534/* line 246, ../scss/include/_skeleton.scss */
763 margin-bottom: 0; 1535#jqt ul li {
764 font-size: 16px; 1536 border-top: 1px solid #48494b;
765 font-weight: 300; 1537 list-style-type: none;
766 line-height: 25px; 1538 overflow: hidden;
1539 padding: 10px;
1540 -webkit-transform: translate3d(0, 0, 0);
1541 /* expensive way to avoid flickr */
1542
767} 1543}
768blockquote small { 1544/* line 253, ../scss/include/_skeleton.scss */
1545#jqt ul li a {
1546 text-decoration: none;
1547 text-overflow: ellipsis;
1548 white-space: nowrap;
1549 overflow: hidden;
769 display: block; 1550 display: block;
770 line-height: 20px; 1551 padding: 10px;
771 color: #999999; 1552 margin: -10px;
772} 1553 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
773blockquote small:before { 1554 -webkit-transform: translateZ(0);
774 content: '\2014 \00A0'; 1555 color: white;
775} 1556 text-shadow: #3c3d3e 0 -1px 0;
776blockquote.pull-right {
777 float: right;
778 padding-right: 15px;
779 padding-left: 0;
780 border-right: 5px solid #eeeeee;
781 border-left: 0;
782} 1557}
783blockquote.pull-right p, 1558/* line 265, ../scss/include/_skeleton.scss */
784blockquote.pull-right small { 1559#jqt ul li a.active {
1560 background-image: none;
1561 background-color: #53b401;
1562 -webkit-box-shadow: #5cc801 0 1px 0px inset;
1563 box-shadow: #5cc801 0 1px 0px inset;
1564 color: white;
1565 text-shadow: #3c8101 0 -1px 0;
1566}
1567/* line 270, ../scss/include/_skeleton.scss */
1568#jqt ul li a.active small {
1569 color: #a0fe50;
1570 text-shadow: #000000 0 -1px 0;
1571}
1572/* line 271, ../scss/include/_skeleton.scss */
1573#jqt ul li a.active small.counter {
1574 background-color: #306801;
1575}
1576/* line 280, ../scss/include/_skeleton.scss */
1577#jqt ul li small {
1578 color: #53b401;
1579 font: 16px "Helvetica Neue", Helvetica;
785 text-align: right; 1580 text-align: right;
786} 1581 text-overflow: ellipsis;
787blockquote.pull-right small:before { 1582 white-space: nowrap;
788 content: ''; 1583 overflow: hidden;
789}
790blockquote.pull-right small:after {
791 content: '\00A0 \2014';
792}
793q:before,
794q:after,
795blockquote:before,
796blockquote:after {
797 content: "";
798}
799address {
800 display: block; 1584 display: block;
801 margin-bottom: 20px; 1585 width: 23%;
802 font-style: normal; 1586 position: relative;
803 line-height: 20px; 1587 z-index: 20;
804} 1588 float: right;
805code, 1589 line-height: 16px;
806pre { 1590 padding: 2px 8px 4px 8px;
807 padding: 0 3px 2px; 1591}
808 font-family: Monaco, Menlo, Consolas, "Courier New", monospace; 1592/* line 295, ../scss/include/_skeleton.scss */
809 font-size: 12px; 1593#jqt ul li small.counter {
810 color: #333333; 1594 background: #2f3031;
1595 color: #949698;
1596 text-shadow: #0a0a0a 0 -1px 0;
1597 z-index: 10;
1598 font-size: 16px;
1599 font-weight: bold;
811 -webkit-border-radius: 3px; 1600 -webkit-border-radius: 3px;
812 -moz-border-radius: 3px;
813 border-radius: 3px; 1601 border-radius: 3px;
814}
815code {
816 padding: 2px 4px;
817 color: #d14;
818 background-color: #f7f7f9;
819 border: 1px solid #e1e1e8;
820 white-space: nowrap;
821}
822pre {
823 display: block; 1602 display: block;
824 padding: 9.5px; 1603 width: auto;
825 margin: 0 0 10px;
826 font-size: 13px;
827 line-height: 20px;
828 word-break: break-all;
829 word-wrap: break-word;
830 white-space: pre;
831 white-space: pre-wrap;
832 background-color: #f5f5f5;
833 border: 1px solid #ccc;
834 border: 1px solid rgba(0, 0, 0, 0.15);
835 -webkit-border-radius: 4px;
836 -moz-border-radius: 4px;
837 border-radius: 4px;
838}
839pre.prettyprint {
840 margin-bottom: 20px;
841} 1604}
842pre code { 1605/* line 311, ../scss/include/_skeleton.scss */
843 padding: 0; 1606#jqt ul li ::-webkit-input-placeholder {
844 color: inherit; 1607 color: #949698;
845 white-space: pre; 1608 text-shadow: #3c3d3e 0 -1px 0;
846 white-space: pre-wrap; 1609}
847 background-color: transparent; 1610/* line 322, ../scss/include/_skeleton.scss */
1611#jqt ul li input[type="text"],
1612#jqt ul li input[type="password"],
1613#jqt ul li input[type="tel"],
1614#jqt ul li input[type="number"],
1615#jqt ul li input[type="search"],
1616#jqt ul li input[type="email"],
1617#jqt ul li input[type="url"],
1618#jqt ul li textarea,
1619#jqt ul li select {
1620 color: white;
1621 text-shadow: #3c3d3e 0 -1px 0;
1622 background: transparent url("data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==");
848 border: 0; 1623 border: 0;
849} 1624 font: normal 17px "Helvetica Neue", Helvetica;
850.pre-scrollable {
851 max-height: 340px;
852 overflow-y: scroll;
853}
854form {
855 margin: 0 0 20px;
856}
857fieldset {
858 padding: 0; 1625 padding: 0;
859 margin: 0; 1626 display: inline-block;
860 border: 0; 1627 margin-left: 0px;
861}
862legend {
863 display: block;
864 width: 100%; 1628 width: 100%;
865 padding: 0; 1629 -webkit-appearance: textarea;
866 margin-bottom: 20px;
867 font-size: 21px;
868 line-height: 40px;
869 color: #333333;
870 border: 0;
871 border-bottom: 1px solid #e5e5e5;
872}
873legend small {
874 font-size: 15px;
875 color: #999999;
876} 1630}
877label, 1631/* line 333, ../scss/include/_skeleton.scss */
878input, 1632#jqt ul li textarea {
879button, 1633 height: 120px;
880select, 1634 padding: 0;
881textarea { 1635 text-indent: -2px;
882 font-size: 14px;
883 font-weight: normal;
884 line-height: 20px;
885} 1636}
886input, 1637/* line 338, ../scss/include/_skeleton.scss */
887button, 1638#jqt ul li input[type="checkbox"],
888select, 1639#jqt ul li input[type="radio"] {
889textarea { 1640 margin: 0;
890 font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 1641 padding: 10px;
891} 1642}
892label { 1643/* line 342, ../scss/include/_skeleton.scss */
1644#jqt ul li input[type="checkbox"]:after,
1645#jqt ul li input[type="radio"]:after {
1646 content: attr(title);
1647 position: absolute;
893 display: block; 1648 display: block;
894 margin-bottom: 5px; 1649 width: 0;
895} 1650 left: 21px;
896select, 1651 top: 12px;
897textarea, 1652 font-family: "Helvetica Neue", Helvetica;
898input[type="text"], 1653 font-size: 17px;
899input[type="password"], 1654 line-height: 21px;
900input[type="datetime"], 1655 width: 246px;
901input[type="datetime-local"], 1656 margin: 0 0 0 17px;
902input[type="date"], 1657 color: white;
903input[type="month"], 1658 text-shadow: #3c3d3e 0 -1px 0;
904input[type="time"], 1659}
905input[type="week"], 1660/* line 355, ../scss/include/_skeleton.scss */
906input[type="number"], 1661#jqt ul li input[type='submit'] {
907input[type="email"],
908input[type="url"],
909input[type="search"],
910input[type="tel"],
911input[type="color"],
912.uneditable-input {
913 display: inline-block;
914 height: 20px;
915 padding: 4px 6px;
916 margin-bottom: 10px;
917 font-size: 14px;
918 line-height: 20px;
919 color: #555555;
920 -webkit-border-radius: 4px; 1662 -webkit-border-radius: 4px;
921 -moz-border-radius: 4px;
922 border-radius: 4px; 1663 border-radius: 4px;
923 vertical-align: middle; 1664 background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#eeeeee), to(#9c9ea0));
924} 1665 border: 1px outset #aaa;
925input, 1666 display: block;
926textarea, 1667 font-size: inherit;
927.uneditable-input { 1668 font-weight: inherit;
928 width: 206px; 1669 padding: 10px;
929}
930textarea {
931 height: auto;
932}
933textarea,
934input[type="text"],
935input[type="password"],
936input[type="datetime"],
937input[type="datetime-local"],
938input[type="date"],
939input[type="month"],
940input[type="time"],
941input[type="week"],
942input[type="number"],
943input[type="email"],
944input[type="url"],
945input[type="search"],
946input[type="tel"],
947input[type="color"],
948.uneditable-input {
949 background-color: #ffffff;
950 border: 1px solid #cccccc;
951 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
952 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
953 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
954 -webkit-transition: border linear .2s, box-shadow linear .2s;
955 -moz-transition: border linear .2s, box-shadow linear .2s;
956 -o-transition: border linear .2s, box-shadow linear .2s;
957 transition: border linear .2s, box-shadow linear .2s;
958}
959textarea:focus,
960input[type="text"]:focus,
961input[type="password"]:focus,
962input[type="datetime"]:focus,
963input[type="datetime-local"]:focus,
964input[type="date"]:focus,
965input[type="month"]:focus,
966input[type="time"]:focus,
967input[type="week"]:focus,
968input[type="number"]:focus,
969input[type="email"]:focus,
970input[type="url"]:focus,
971input[type="search"]:focus,
972input[type="tel"]:focus,
973input[type="color"]:focus,
974.uneditable-input:focus {
975 border-color: rgba(82, 168, 236, 0.8);
976 outline: 0;
977 outline: thin dotted \9;
978 /* IE6-9 */
979
980 -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
981 -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
982 box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(82,168,236,.6);
983}
984input[type="radio"],
985input[type="checkbox"] {
986 margin: 4px 0 0;
987 *margin-top: 0;
988 /* IE7 */
989
990 margin-top: 1px \9;
991 /* IE8-9 */
992
993 line-height: normal;
994}
995input[type="file"],
996input[type="image"],
997input[type="submit"],
998input[type="reset"],
999input[type="button"],
1000input[type="radio"],
1001input[type="checkbox"] {
1002 width: auto;
1003}
1004select,
1005input[type="file"] {
1006 height: 30px;
1007 /* In IE7, the height of the select element cannot be changed by height, only font-size */
1008
1009 *margin-top: 4px;
1010 /* For IE7, add top margin to align select with labels */
1011
1012 line-height: 30px;
1013}
1014select {
1015 width: 220px;
1016 border: 1px solid #cccccc;
1017 background-color: #ffffff;
1018}
1019select[multiple],
1020select[size] {
1021 height: auto;
1022}
1023select:focus,
1024input[type="file"]:focus,
1025input[type="radio"]:focus,
1026input[type="checkbox"]:focus {
1027 outline: thin dotted #333;
1028 outline: 5px auto -webkit-focus-ring-color;
1029 outline-offset: -2px;
1030}
1031.uneditable-input,
1032.uneditable-textarea {
1033 color: #999999;
1034 background-color: #fcfcfc;
1035 border-color: #cccccc;
1036 -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
1037 -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
1038 box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.025);
1039 cursor: not-allowed;
1040}
1041.uneditable-input {
1042 overflow: hidden;
1043 white-space: nowrap;
1044}
1045.uneditable-textarea {
1046 width: auto;
1047 height: auto;
1048}
1049input:-moz-placeholder,
1050textarea:-moz-placeholder {
1051 color: #999999;
1052}
1053input:-ms-input-placeholder,
1054textarea:-ms-input-placeholder {
1055 color: #999999;
1056}
1057input::-webkit-input-placeholder,
1058textarea::-webkit-input-placeholder {
1059 color: #999999;
1060}
1061.radio,
1062.checkbox {
1063 min-height: 20px;
1064 padding-left: 20px;
1065}
1066.radio input[type="radio"],
1067.checkbox input[type="checkbox"] {
1068 float: left;
1069 margin-left: -20px;
1070}
1071.controls > .radio:first-child,
1072.controls > .checkbox:first-child {
1073 padding-top: 5px;
1074}
1075.radio.inline,
1076.checkbox.inline {
1077 display: inline-block;
1078 padding-top: 5px;
1079 margin-bottom: 0;
1080 vertical-align: middle;
1081}
1082.radio.inline + .radio.inline,
1083.checkbox.inline + .checkbox.inline {
1084 margin-left: 10px;
1085}
1086.input-mini {
1087 width: 60px;
1088}
1089.input-small {
1090 width: 90px;
1091}
1092.input-medium {
1093 width: 150px;
1094}
1095.input-large {
1096 width: 210px;
1097}
1098.input-xlarge {
1099 width: 270px;
1100}
1101.input-xxlarge {
1102 width: 530px;
1103}
1104input[class*="span"],
1105select[class*="span"],
1106textarea[class*="span"],
1107.uneditable-input[class*="span"],
1108.row-fluid input[class*="span"],
1109.row-fluid select[class*="span"],
1110.row-fluid textarea[class*="span"],
1111.row-fluid .uneditable-input[class*="span"] {
1112 float: none;
1113 margin-left: 0;
1114}
1115.input-append input[class*="span"],
1116.input-append .uneditable-input[class*="span"],
1117.input-prepend input[class*="span"],
1118.input-prepend .uneditable-input[class*="span"],
1119.row-fluid input[class*="span"],
1120.row-fluid select[class*="span"],
1121.row-fluid textarea[class*="span"],
1122.row-fluid .uneditable-input[class*="span"],
1123.row-fluid .input-prepend [class*="span"],
1124.row-fluid .input-append [class*="span"] {
1125 display: inline-block;
1126}
1127input,
1128textarea,
1129.uneditable-input {
1130 margin-left: 0;
1131}
1132.controls-row [class*="span"] + [class*="span"] {
1133 margin-left: 20px;
1134}
1135input.span12, textarea.span12, .uneditable-input.span12 {
1136 width: 926px;
1137}
1138input.span11, textarea.span11, .uneditable-input.span11 {
1139 width: 846px;
1140}
1141input.span10, textarea.span10, .uneditable-input.span10 {
1142 width: 766px;
1143}
1144input.span9, textarea.span9, .uneditable-input.span9 {
1145 width: 686px;
1146}
1147input.span8, textarea.span8, .uneditable-input.span8 {
1148 width: 606px;
1149}
1150input.span7, textarea.span7, .uneditable-input.span7 {
1151 width: 526px;
1152}
1153input.span6, textarea.span6, .uneditable-input.span6 {
1154 width: 446px;
1155}
1156input.span5, textarea.span5, .uneditable-input.span5 {
1157 width: 366px;
1158}
1159input.span4, textarea.span4, .uneditable-input.span4 {
1160 width: 286px;
1161}
1162input.span3, textarea.span3, .uneditable-input.span3 {
1163 width: 206px;
1164}
1165input.span2, textarea.span2, .uneditable-input.span2 {
1166 width: 126px;
1167}
1168input.span1, textarea.span1, .uneditable-input.span1 {
1169 width: 46px;
1170} 1670}
1171.controls-row { 1671/* line 368, ../scss/include/_skeleton.scss */
1172 *zoom: 1; 1672#jqt ul li.arrow small,
1673#jqt ul li.forward small {
1674 margin-right: 24px;
1173} 1675}
1174.controls-row:before, 1676/* line 380, ../scss/include/_skeleton.scss */
1175.controls-row:after { 1677#jqt ul li.forward:before {
1176 display: table;
1177 content: ""; 1678 content: "";
1679 position: absolute;
1680 display: block;
1681 top: 50%;
1682 right: 6px;
1683 margin-top: -12px;
1684 width: 24px;
1685 height: 24px;
1686 -webkit-border-radius: 12px;
1687 border-radius: 12px;
1688 background-image: none;
1689 background-color: #53b401;
1690 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #76fe04), color-stop(50%, #5fcd01), color-stop(51%, #53b401), color-stop(100%, #479b01));
1691 background-image: -webkit-linear-gradient(top, #76fe04, #5fcd01 50%, #53b401 51%, #479b01);
1692 background-image: linear-gradient(top, #76fe04, #5fcd01 50%, #53b401 51%, #479b01);
1693 border: 2px solid #fff;
1694 -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
1695 box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
1696 -webkit-box-sizing: border-box;
1697 padding: 0;
1698 z-index: 10;
1178 line-height: 0; 1699 line-height: 0;
1700 pointer-events: none;
1179} 1701}
1180.controls-row:after { 1702/* line 395, ../scss/include/_skeleton.scss */
1181 clear: both; 1703#jqt ul li.forward:after {
1182} 1704 color: white;
1183.controls-row [class*="span"], 1705 text-shadow: #3c8101 0 -1px 0;
1184.row-fluid .controls-row [class*="span"] { 1706 filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
1185 float: left; 1707 opacity: 1;
1708 font-size: 24px;
1709}
1710/* line 404, ../scss/include/_skeleton.scss */
1711#jqt ul.rounded,
1712#jqt ul.individual li {
1713 -webkit-box-shadow: rgba(255, 255, 255, 0.15) 0 1px 0;
1714 box-shadow: rgba(255, 255, 255, 0.15) 0 1px 0;
1715 border: 1px solid #2f3031;
1716}
1717/* line 409, ../scss/include/_skeleton.scss */
1718#jqt ul.rounded {
1719 -webkit-border-radius: 8px;
1720 border-radius: 8px;
1721}
1722/* line 412, ../scss/include/_skeleton.scss */
1723#jqt ul.rounded li:first-child,
1724#jqt ul.rounded li:first-child a {
1725 border-top: 0;
1726 -webkit-border-top-left-radius: 8px;
1727 border-top-left-radius: 8px;
1728 -webkit-border-top-right-radius: 8px;
1729 border-top-right-radius: 8px;
1730}
1731/* line 416, ../scss/include/_skeleton.scss */
1732#jqt ul.rounded li:last-child,
1733#jqt ul.rounded li:last-child a {
1734 -webkit-border-bottom-left-radius: 8px;
1735 border-bottom-left-radius: 8px;
1736 -webkit-border-bottom-right-radius: 8px;
1737 border-bottom-right-radius: 8px;
1738}
1739/* line 422, ../scss/include/_skeleton.scss */
1740#jqt ul.form li {
1741 padding: 7px 10px;
1186} 1742}
1187.controls-row .checkbox[class*="span"], 1743/* line 425, ../scss/include/_skeleton.scss */
1188.controls-row .radio[class*="span"] { 1744#jqt ul.form li.error {
1189 padding-top: 5px; 1745 border: 2px solid red;
1190}
1191input[disabled],
1192select[disabled],
1193textarea[disabled],
1194input[readonly],
1195select[readonly],
1196textarea[readonly] {
1197 cursor: not-allowed;
1198 background-color: #eeeeee;
1199} 1746}
1200input[type="radio"][disabled], 1747/* line 428, ../scss/include/_skeleton.scss */
1201input[type="checkbox"][disabled], 1748#jqt ul.form li.error + #jqt ul.form li.error {
1202input[type="radio"][readonly], 1749 border-top: 0;
1203input[type="checkbox"][readonly] {
1204 background-color: transparent;
1205}
1206.control-group.warning .control-label,
1207.control-group.warning .help-block,
1208.control-group.warning .help-inline {
1209 color: #c09853;
1210}
1211.control-group.warning .checkbox,
1212.control-group.warning .radio,
1213.control-group.warning input,
1214.control-group.warning select,
1215.control-group.warning textarea {
1216 color: #c09853;
1217}
1218.control-group.warning input,
1219.control-group.warning select,
1220.control-group.warning textarea {
1221 border-color: #c09853;
1222 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1223 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1224 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1225}
1226.control-group.warning input:focus,
1227.control-group.warning select:focus,
1228.control-group.warning textarea:focus {
1229 border-color: #a47e3c;
1230 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
1231 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
1232 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
1233}
1234.control-group.warning .input-prepend .add-on,
1235.control-group.warning .input-append .add-on {
1236 color: #c09853;
1237 background-color: #fcf8e3;
1238 border-color: #c09853;
1239}
1240.control-group.error .control-label,
1241.control-group.error .help-block,
1242.control-group.error .help-inline {
1243 color: #b94a48;
1244}
1245.control-group.error .checkbox,
1246.control-group.error .radio,
1247.control-group.error input,
1248.control-group.error select,
1249.control-group.error textarea {
1250 color: #b94a48;
1251}
1252.control-group.error input,
1253.control-group.error select,
1254.control-group.error textarea {
1255 border-color: #b94a48;
1256 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1257 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1258 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1259}
1260.control-group.error input:focus,
1261.control-group.error select:focus,
1262.control-group.error textarea:focus {
1263 border-color: #953b39;
1264 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
1265 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
1266 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
1267}
1268.control-group.error .input-prepend .add-on,
1269.control-group.error .input-append .add-on {
1270 color: #b94a48;
1271 background-color: #f2dede;
1272 border-color: #b94a48;
1273}
1274.control-group.success .control-label,
1275.control-group.success .help-block,
1276.control-group.success .help-inline {
1277 color: #468847;
1278}
1279.control-group.success .checkbox,
1280.control-group.success .radio,
1281.control-group.success input,
1282.control-group.success select,
1283.control-group.success textarea {
1284 color: #468847;
1285}
1286.control-group.success input,
1287.control-group.success select,
1288.control-group.success textarea {
1289 border-color: #468847;
1290 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1291 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1292 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1293}
1294.control-group.success input:focus,
1295.control-group.success select:focus,
1296.control-group.success textarea:focus {
1297 border-color: #356635;
1298 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
1299 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
1300 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
1301}
1302.control-group.success .input-prepend .add-on,
1303.control-group.success .input-append .add-on {
1304 color: #468847;
1305 background-color: #dff0d8;
1306 border-color: #468847;
1307}
1308.control-group.info .control-label,
1309.control-group.info .help-block,
1310.control-group.info .help-inline {
1311 color: #3a87ad;
1312}
1313.control-group.info .checkbox,
1314.control-group.info .radio,
1315.control-group.info input,
1316.control-group.info select,
1317.control-group.info textarea {
1318 color: #3a87ad;
1319}
1320.control-group.info input,
1321.control-group.info select,
1322.control-group.info textarea {
1323 border-color: #3a87ad;
1324 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1325 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1326 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
1327}
1328.control-group.info input:focus,
1329.control-group.info select:focus,
1330.control-group.info textarea:focus {
1331 border-color: #2d6987;
1332 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
1333 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
1334 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7ab5d3;
1335}
1336.control-group.info .input-prepend .add-on,
1337.control-group.info .input-append .add-on {
1338 color: #3a87ad;
1339 background-color: #d9edf7;
1340 border-color: #3a87ad;
1341}
1342input:focus:invalid,
1343textarea:focus:invalid,
1344select:focus:invalid {
1345 color: #b94a48;
1346 border-color: #ee5f5b;
1347}
1348input:focus:invalid:focus,
1349textarea:focus:invalid:focus,
1350select:focus:invalid:focus {
1351 border-color: #e9322d;
1352 -webkit-box-shadow: 0 0 6px #f8b9b7;
1353 -moz-box-shadow: 0 0 6px #f8b9b7;
1354 box-shadow: 0 0 6px #f8b9b7;
1355}
1356.form-actions {
1357 padding: 19px 20px 20px;
1358 margin-top: 20px;
1359 margin-bottom: 20px;
1360 background-color: #f5f5f5;
1361 border-top: 1px solid #e5e5e5;
1362 *zoom: 1;
1363}
1364.form-actions:before,
1365.form-actions:after {
1366 display: table;
1367 content: "";
1368 line-height: 0;
1369} 1750}
1370.form-actions:after { 1751/* line 438, ../scss/include/_skeleton.scss */
1371 clear: both; 1752#jqt ul.metal li {
1753 background-image: none;
1754 border-top: 1px solid #fff;
1755 border-bottom: 1px solid #666;
1756 font-size: 26px;
1372} 1757}
1373.help-block, 1758/* line 445, ../scss/include/_skeleton.scss */
1374.help-inline { 1759#jqt ul.metal li a {
1375 color: #595959; 1760 line-height: 26px;
1761 margin: 0;
1762 padding: 13px 0;
1376} 1763}
1377.help-block { 1764/* line 451, ../scss/include/_skeleton.scss */
1765#jqt ul.metal li em {
1378 display: block; 1766 display: block;
1379 margin-bottom: 10px;
1380}
1381.help-inline {
1382 display: inline-block;
1383 *display: inline;
1384 /* IE7 inline-block hack */
1385
1386 *zoom: 1;
1387 vertical-align: middle;
1388 padding-left: 5px;
1389}
1390.input-append,
1391.input-prepend {
1392 margin-bottom: 5px;
1393 font-size: 0;
1394 white-space: nowrap;
1395}
1396.input-append input,
1397.input-prepend input,
1398.input-append select,
1399.input-prepend select,
1400.input-append .uneditable-input,
1401.input-prepend .uneditable-input,
1402.input-append .dropdown-menu,
1403.input-prepend .dropdown-menu {
1404 font-size: 14px; 1767 font-size: 14px;
1768 font-style: normal;
1769 width: 50%;
1770 line-height: 14px;
1405} 1771}
1406.input-append input, 1772/* line 459, ../scss/include/_skeleton.scss */
1407.input-prepend input, 1773#jqt ul.metal li small {
1408.input-append select, 1774 float: right;
1409.input-prepend select,
1410.input-append .uneditable-input,
1411.input-prepend .uneditable-input {
1412 position: relative; 1775 position: relative;
1413 margin-bottom: 0;
1414 *margin-left: 0;
1415 vertical-align: top;
1416 -webkit-border-radius: 0 4px 4px 0;
1417 -moz-border-radius: 0 4px 4px 0;
1418 border-radius: 0 4px 4px 0;
1419}
1420.input-append input:focus,
1421.input-prepend input:focus,
1422.input-append select:focus,
1423.input-prepend select:focus,
1424.input-append .uneditable-input:focus,
1425.input-prepend .uneditable-input:focus {
1426 z-index: 2;
1427}
1428.input-append .add-on,
1429.input-prepend .add-on {
1430 display: inline-block;
1431 width: auto;
1432 height: 20px;
1433 min-width: 16px;
1434 padding: 4px 5px;
1435 font-size: 14px;
1436 font-weight: normal;
1437 line-height: 20px;
1438 text-align: center;
1439 text-shadow: 0 1px 0 #ffffff;
1440 background-color: #eeeeee;
1441 border: 1px solid #ccc;
1442}
1443.input-append .add-on,
1444.input-prepend .add-on,
1445.input-append .btn,
1446.input-prepend .btn,
1447.input-append .btn-group > .dropdown-toggle,
1448.input-prepend .btn-group > .dropdown-toggle {
1449 vertical-align: top;
1450 -webkit-border-radius: 0;
1451 -moz-border-radius: 0;
1452 border-radius: 0;
1453}
1454.input-append .active,
1455.input-prepend .active {
1456 background-color: #a9dba9;
1457 border-color: #46a546;
1458}
1459.input-prepend .add-on,
1460.input-prepend .btn {
1461 margin-right: -1px;
1462}
1463.input-prepend .add-on:first-child,
1464.input-prepend .btn:first-child {
1465 -webkit-border-radius: 4px 0 0 4px;
1466 -moz-border-radius: 4px 0 0 4px;
1467 border-radius: 4px 0 0 4px;
1468}
1469.input-append input,
1470.input-append select,
1471.input-append .uneditable-input {
1472 -webkit-border-radius: 4px 0 0 4px;
1473 -moz-border-radius: 4px 0 0 4px;
1474 border-radius: 4px 0 0 4px;
1475}
1476.input-append input + .btn-group .btn:last-child,
1477.input-append select + .btn-group .btn:last-child,
1478.input-append .uneditable-input + .btn-group .btn:last-child {
1479 -webkit-border-radius: 0 4px 4px 0;
1480 -moz-border-radius: 0 4px 4px 0;
1481 border-radius: 0 4px 4px 0;
1482}
1483.input-append .add-on,
1484.input-append .btn,
1485.input-append .btn-group {
1486 margin-left: -1px;
1487}
1488.input-append .add-on:last-child,
1489.input-append .btn:last-child,
1490.input-append .btn-group:last-child > .dropdown-toggle {
1491 -webkit-border-radius: 0 4px 4px 0;
1492 -moz-border-radius: 0 4px 4px 0;
1493 border-radius: 0 4px 4px 0;
1494}
1495.input-prepend.input-append input,
1496.input-prepend.input-append select,
1497.input-prepend.input-append .uneditable-input {
1498 -webkit-border-radius: 0;
1499 -moz-border-radius: 0;
1500 border-radius: 0;
1501}
1502.input-prepend.input-append input + .btn-group .btn,
1503.input-prepend.input-append select + .btn-group .btn,
1504.input-prepend.input-append .uneditable-input + .btn-group .btn {
1505 -webkit-border-radius: 0 4px 4px 0;
1506 -moz-border-radius: 0 4px 4px 0;
1507 border-radius: 0 4px 4px 0;
1508}
1509.input-prepend.input-append .add-on:first-child,
1510.input-prepend.input-append .btn:first-child {
1511 margin-right: -1px;
1512 -webkit-border-radius: 4px 0 0 4px;
1513 -moz-border-radius: 4px 0 0 4px;
1514 border-radius: 4px 0 0 4px;
1515}
1516.input-prepend.input-append .add-on:last-child,
1517.input-prepend.input-append .btn:last-child {
1518 margin-left: -1px;
1519 -webkit-border-radius: 0 4px 4px 0;
1520 -moz-border-radius: 0 4px 4px 0;
1521 border-radius: 0 4px 4px 0;
1522}
1523.input-prepend.input-append .btn-group:first-child {
1524 margin-left: 0;
1525}
1526input.search-query {
1527 padding-right: 14px;
1528 padding-right: 4px \9;
1529 padding-left: 14px;
1530 padding-left: 4px \9;
1531 /* IE7-8 doesn't have border-radius, so don't indent the padding */
1532
1533 margin-bottom: 0;
1534 -webkit-border-radius: 15px;
1535 -moz-border-radius: 15px;
1536 border-radius: 15px;
1537}
1538/* Allow for input prepend/append in search forms */
1539.form-search .input-append .search-query,
1540.form-search .input-prepend .search-query {
1541 -webkit-border-radius: 0;
1542 -moz-border-radius: 0;
1543 border-radius: 0;
1544}
1545.form-search .input-append .search-query {
1546 -webkit-border-radius: 14px 0 0 14px;
1547 -moz-border-radius: 14px 0 0 14px;
1548 border-radius: 14px 0 0 14px;
1549}
1550.form-search .input-append .btn {
1551 -webkit-border-radius: 0 14px 14px 0;
1552 -moz-border-radius: 0 14px 14px 0;
1553 border-radius: 0 14px 14px 0;
1554}
1555.form-search .input-prepend .search-query {
1556 -webkit-border-radius: 0 14px 14px 0;
1557 -moz-border-radius: 0 14px 14px 0;
1558 border-radius: 0 14px 14px 0;
1559}
1560.form-search .input-prepend .btn {
1561 -webkit-border-radius: 14px 0 0 14px;
1562 -moz-border-radius: 14px 0 0 14px;
1563 border-radius: 14px 0 0 14px;
1564}
1565.form-search input,
1566.form-inline input,
1567.form-horizontal input,
1568.form-search textarea,
1569.form-inline textarea,
1570.form-horizontal textarea,
1571.form-search select,
1572.form-inline select,
1573.form-horizontal select,
1574.form-search .help-inline,
1575.form-inline .help-inline,
1576.form-horizontal .help-inline,
1577.form-search .uneditable-input,
1578.form-inline .uneditable-input,
1579.form-horizontal .uneditable-input,
1580.form-search .input-prepend,
1581.form-inline .input-prepend,
1582.form-horizontal .input-prepend,
1583.form-search .input-append,
1584.form-inline .input-append,
1585.form-horizontal .input-append {
1586 display: inline-block;
1587 *display: inline;
1588 /* IE7 inline-block hack */
1589
1590 *zoom: 1;
1591 margin-bottom: 0;
1592 vertical-align: middle;
1593}
1594.form-search .hide,
1595.form-inline .hide,
1596.form-horizontal .hide {
1597 display: none;
1598}
1599.form-search label,
1600.form-inline label,
1601.form-search .btn-group,
1602.form-inline .btn-group {
1603 display: inline-block;
1604}
1605.form-search .input-append,
1606.form-inline .input-append,
1607.form-search .input-prepend,
1608.form-inline .input-prepend {
1609 margin-bottom: 0;
1610}
1611.form-search .radio,
1612.form-search .checkbox,
1613.form-inline .radio,
1614.form-inline .checkbox {
1615 padding-left: 0;
1616 margin-bottom: 0;
1617 vertical-align: middle;
1618}
1619.form-search .radio input[type="radio"],
1620.form-search .checkbox input[type="checkbox"],
1621.form-inline .radio input[type="radio"],
1622.form-inline .checkbox input[type="checkbox"] {
1623 float: left;
1624 margin-right: 3px;
1625 margin-left: 0;
1626}
1627.control-group {
1628 margin-bottom: 10px;
1629}
1630legend + .control-group {
1631 margin-top: 20px;
1632 -webkit-margin-top-collapse: separate;
1633}
1634.form-horizontal .control-group {
1635 margin-bottom: 20px;
1636 *zoom: 1;
1637}
1638.form-horizontal .control-group:before,
1639.form-horizontal .control-group:after {
1640 display: table;
1641 content: "";
1642 line-height: 0;
1643}
1644.form-horizontal .control-group:after {
1645 clear: both;
1646}
1647.form-horizontal .control-label {
1648 float: left;
1649 width: 160px;
1650 padding-top: 5px;
1651 text-align: right;
1652}
1653.form-horizontal .controls {
1654 *display: inline-block;
1655 *padding-left: 20px;
1656 margin-left: 180px;
1657 *margin-left: 0;
1658}
1659.form-horizontal .controls:first-child {
1660 *padding-left: 180px;
1661}
1662.form-horizontal .help-block {
1663 margin-bottom: 0;
1664}
1665.form-horizontal input + .help-block,
1666.form-horizontal select + .help-block,
1667.form-horizontal textarea + .help-block,
1668.form-horizontal .uneditable-input + .help-block,
1669.form-horizontal .input-prepend + .help-block,
1670.form-horizontal .input-append + .help-block {
1671 margin-top: 10px; 1776 margin-top: 10px;
1672}
1673.form-horizontal .form-actions {
1674 padding-left: 180px;
1675}
1676table {
1677 max-width: 100%;
1678 background-color: transparent;
1679 border-collapse: collapse;
1680 border-spacing: 0;
1681}
1682.table {
1683 width: 100%;
1684 margin-bottom: 20px;
1685}
1686.table th,
1687.table td {
1688 padding: 8px;
1689 line-height: 20px;
1690 text-align: left;
1691 vertical-align: top;
1692 border-top: 1px solid #dddddd;
1693}
1694.table th {
1695 font-weight: bold; 1777 font-weight: bold;
1696} 1778}
1697.table thead th { 1779/* line 473, ../scss/include/_skeleton.scss */
1698 vertical-align: bottom; 1780#jqt ul.edgetoedge li {
1781 font-size: 20px;
1699} 1782}
1700.table caption + thead tr:first-child th, 1783/* line 476, ../scss/include/_skeleton.scss */
1701.table caption + thead tr:first-child td, 1784#jqt ul.edgetoedge li:first-child {
1702.table colgroup + thead tr:first-child th,
1703.table colgroup + thead tr:first-child td,
1704.table thead:first-child tr:first-child th,
1705.table thead:first-child tr:first-child td {
1706 border-top: 0; 1785 border-top: 0;
1707} 1786}
1708.table tbody + tbody { 1787/* line 480, ../scss/include/_skeleton.scss */
1709 border-top: 2px solid #dddddd; 1788#jqt ul.edgetoedge li.sep {
1789 font-size: 16px;
1790 padding: 2px 10px;
1710} 1791}
1711.table .table { 1792/* line 485, ../scss/include/_skeleton.scss */
1712 background-color: #ffffff; 1793#jqt ul.edgetoedge li em {
1794 font-weight: normal;
1795 font-style: normal;
1713} 1796}
1714.table-condensed th, 1797/* line 494, ../scss/include/_skeleton.scss */
1715.table-condensed td { 1798#jqt ul.plastic {
1716 padding: 4px 5px; 1799 font-size: 18px;
1717} 1800}
1718.table-bordered { 1801/* line 498, ../scss/include/_skeleton.scss */
1719 border: 1px solid #dddddd; 1802#jqt ul.plastic li {
1720 border-collapse: separate; 1803 border-width: 1px 0;
1721 *border-collapse: collapse; 1804 border-style: solid;
1722 border-left: 0; 1805 background-image: none;
1723 -webkit-border-radius: 4px; 1806 background-color: #2a2b2c;
1724 -moz-border-radius: 4px; 1807 border-top-color: #2f3031;
1725 border-radius: 4px; 1808 border-bottom-color: #232324;
1726} 1809}
1727.table-bordered th, 1810/* line 506, ../scss/include/_skeleton.scss */
1728.table-bordered td { 1811#jqt ul.plastic li:nth-child(odd) {
1729 border-left: 1px solid #dddddd; 1812 background-image: none;
1730} 1813 background-color: #2f3031;
1731.table-bordered caption + thead tr:first-child th,
1732.table-bordered caption + tbody tr:first-child th,
1733.table-bordered caption + tbody tr:first-child td,
1734.table-bordered colgroup + thead tr:first-child th,
1735.table-bordered colgroup + tbody tr:first-child th,
1736.table-bordered colgroup + tbody tr:first-child td,
1737.table-bordered thead:first-child tr:first-child th,
1738.table-bordered tbody:first-child tr:first-child th,
1739.table-bordered tbody:first-child tr:first-child td {
1740 border-top: 0;
1741} 1814}
1742.table-bordered thead:first-child tr:first-child > th:first-child, 1815/* line 510, ../scss/include/_skeleton.scss */
1743.table-bordered tbody:first-child tr:first-child > td:first-child { 1816#jqt ul.plastic li a.active.loading {
1744 -webkit-border-top-left-radius: 4px; 1817 background-image: url(img/loading.gif);
1745 -moz-border-radius-topleft: 4px; 1818 background-position: 95% center;
1746 border-top-left-radius: 4px;
1747}
1748.table-bordered thead:first-child tr:first-child > th:last-child,
1749.table-bordered tbody:first-child tr:first-child > td:last-child {
1750 -webkit-border-top-right-radius: 4px;
1751 -moz-border-radius-topright: 4px;
1752 border-top-right-radius: 4px;
1753}
1754.table-bordered thead:last-child tr:last-child > th:first-child,
1755.table-bordered tbody:last-child tr:last-child > td:first-child,
1756.table-bordered tfoot:last-child tr:last-child > td:first-child {
1757 -webkit-border-bottom-left-radius: 4px;
1758 -moz-border-radius-bottomleft: 4px;
1759 border-bottom-left-radius: 4px;
1760}
1761.table-bordered thead:last-child tr:last-child > th:last-child,
1762.table-bordered tbody:last-child tr:last-child > td:last-child,
1763.table-bordered tfoot:last-child tr:last-child > td:last-child {
1764 -webkit-border-bottom-right-radius: 4px;
1765 -moz-border-radius-bottomright: 4px;
1766 border-bottom-right-radius: 4px;
1767}
1768.table-bordered tfoot + tbody:last-child tr:last-child td:first-child {
1769 -webkit-border-bottom-left-radius: 0;
1770 -moz-border-radius-bottomleft: 0;
1771 border-bottom-left-radius: 0;
1772}
1773.table-bordered tfoot + tbody:last-child tr:last-child td:last-child {
1774 -webkit-border-bottom-right-radius: 0;
1775 -moz-border-radius-bottomright: 0;
1776 border-bottom-right-radius: 0;
1777}
1778.table-bordered caption + thead tr:first-child th:first-child,
1779.table-bordered caption + tbody tr:first-child td:first-child,
1780.table-bordered colgroup + thead tr:first-child th:first-child,
1781.table-bordered colgroup + tbody tr:first-child td:first-child {
1782 -webkit-border-top-left-radius: 4px;
1783 -moz-border-radius-topleft: 4px;
1784 border-top-left-radius: 4px;
1785}
1786.table-bordered caption + thead tr:first-child th:last-child,
1787.table-bordered caption + tbody tr:first-child td:last-child,
1788.table-bordered colgroup + thead tr:first-child th:last-child,
1789.table-bordered colgroup + tbody tr:first-child td:last-child {
1790 -webkit-border-top-right-radius: 4px;
1791 -moz-border-radius-topright: 4px;
1792 border-top-right-radius: 4px;
1793}
1794.table-striped tbody > tr:nth-child(odd) > td,
1795.table-striped tbody > tr:nth-child(odd) > th {
1796 background-color: #f9f9f9;
1797}
1798.table-hover tbody tr:hover td,
1799.table-hover tbody tr:hover th {
1800 background-color: #f5f5f5;
1801}
1802table td[class*="span"],
1803table th[class*="span"],
1804.row-fluid table td[class*="span"],
1805.row-fluid table th[class*="span"] {
1806 display: table-cell;
1807 float: none;
1808 margin-left: 0;
1809}
1810.table td.span1,
1811.table th.span1 {
1812 float: none;
1813 width: 44px;
1814 margin-left: 0;
1815}
1816.table td.span2,
1817.table th.span2 {
1818 float: none;
1819 width: 124px;
1820 margin-left: 0;
1821}
1822.table td.span3,
1823.table th.span3 {
1824 float: none;
1825 width: 204px;
1826 margin-left: 0;
1827}
1828.table td.span4,
1829.table th.span4 {
1830 float: none;
1831 width: 284px;
1832 margin-left: 0;
1833}
1834.table td.span5,
1835.table th.span5 {
1836 float: none;
1837 width: 364px;
1838 margin-left: 0;
1839}
1840.table td.span6,
1841.table th.span6 {
1842 float: none;
1843 width: 444px;
1844 margin-left: 0;
1845}
1846.table td.span7,
1847.table th.span7 {
1848 float: none;
1849 width: 524px;
1850 margin-left: 0;
1851}
1852.table td.span8,
1853.table th.span8 {
1854 float: none;
1855 width: 604px;
1856 margin-left: 0;
1857}
1858.table td.span9,
1859.table th.span9 {
1860 float: none;
1861 width: 684px;
1862 margin-left: 0;
1863}
1864.table td.span10,
1865.table th.span10 {
1866 float: none;
1867 width: 764px;
1868 margin-left: 0;
1869}
1870.table td.span11,
1871.table th.span11 {
1872 float: none;
1873 width: 844px;
1874 margin-left: 0;
1875}
1876.table td.span12,
1877.table th.span12 {
1878 float: none;
1879 width: 924px;
1880 margin-left: 0;
1881}
1882.table tbody tr.success td {
1883 background-color: #dff0d8;
1884}
1885.table tbody tr.error td {
1886 background-color: #f2dede;
1887}
1888.table tbody tr.warning td {
1889 background-color: #fcf8e3;
1890}
1891.table tbody tr.info td {
1892 background-color: #d9edf7;
1893}
1894.table-hover tbody tr.success:hover td {
1895 background-color: #d0e9c6;
1896}
1897.table-hover tbody tr.error:hover td {
1898 background-color: #ebcccc;
1899}
1900.table-hover tbody tr.warning:hover td {
1901 background-color: #faf2cc;
1902}
1903.table-hover tbody tr.info:hover td {
1904 background-color: #c4e3f3;
1905}
1906[class^="icon-"],
1907[class*=" icon-"] {
1908 display: inline-block;
1909 width: 14px;
1910 height: 14px;
1911 *margin-right: .3em;
1912 line-height: 14px;
1913 vertical-align: text-top;
1914 background-image: url("../img/glyphicons-halflings.png");
1915 background-position: 14px 14px;
1916 background-repeat: no-repeat; 1819 background-repeat: no-repeat;
1917 margin-top: 1px;
1918}
1919/* White icons with optional class, or on hover/active states of certain elements */
1920.icon-white,
1921.nav-pills > .active > a > [class^="icon-"],
1922.nav-pills > .active > a > [class*=" icon-"],
1923.nav-list > .active > a > [class^="icon-"],
1924.nav-list > .active > a > [class*=" icon-"],
1925.navbar-inverse .nav > .active > a > [class^="icon-"],
1926.navbar-inverse .nav > .active > a > [class*=" icon-"],
1927.dropdown-menu > li > a:hover > [class^="icon-"],
1928.dropdown-menu > li > a:hover > [class*=" icon-"],
1929.dropdown-menu > .active > a > [class^="icon-"],
1930.dropdown-menu > .active > a > [class*=" icon-"],
1931.dropdown-submenu:hover > a > [class^="icon-"],
1932.dropdown-submenu:hover > a > [class*=" icon-"] {
1933 background-image: url("../img/glyphicons-halflings-white.png");
1934}
1935.icon-glass {
1936 background-position: 0 0;
1937}
1938.icon-music {
1939 background-position: -24px 0;
1940}
1941.icon-search {
1942 background-position: -48px 0;
1943}
1944.icon-envelope {
1945 background-position: -72px 0;
1946}
1947.icon-heart {
1948 background-position: -96px 0;
1949}
1950.icon-star {
1951 background-position: -120px 0;
1952}
1953.icon-star-empty {
1954 background-position: -144px 0;
1955}
1956.icon-user {
1957 background-position: -168px 0;
1958}
1959.icon-film {
1960 background-position: -192px 0;
1961}
1962.icon-th-large {
1963 background-position: -216px 0;
1964}
1965.icon-th {
1966 background-position: -240px 0;
1967}
1968.icon-th-list {
1969 background-position: -264px 0;
1970}
1971.icon-ok {
1972 background-position: -288px 0;
1973}
1974.icon-remove {
1975 background-position: -312px 0;
1976}
1977.icon-zoom-in {
1978 background-position: -336px 0;
1979}
1980.icon-zoom-out {
1981 background-position: -360px 0;
1982}
1983.icon-off {
1984 background-position: -384px 0;
1985}
1986.icon-signal {
1987 background-position: -408px 0;
1988}
1989.icon-cog {
1990 background-position: -432px 0;
1991}
1992.icon-trash {
1993 background-position: -456px 0;
1994}
1995.icon-home {
1996 background-position: 0 -24px;
1997}
1998.icon-file {
1999 background-position: -24px -24px;
2000}
2001.icon-time {
2002 background-position: -48px -24px;
2003}
2004.icon-road {
2005 background-position: -72px -24px;
2006}
2007.icon-download-alt {
2008 background-position: -96px -24px;
2009}
2010.icon-download {
2011 background-position: -120px -24px;
2012}
2013.icon-upload {
2014 background-position: -144px -24px;
2015}
2016.icon-inbox {
2017 background-position: -168px -24px;
2018}
2019.icon-play-circle {
2020 background-position: -192px -24px;
2021}
2022.icon-repeat {
2023 background-position: -216px -24px;
2024}
2025.icon-refresh {
2026 background-position: -240px -24px;
2027}
2028.icon-list-alt {
2029 background-position: -264px -24px;
2030}
2031.icon-lock {
2032 background-position: -287px -24px;
2033}
2034.icon-flag {
2035 background-position: -312px -24px;
2036}
2037.icon-headphones {
2038 background-position: -336px -24px;
2039}
2040.icon-volume-off {
2041 background-position: -360px -24px;
2042}
2043.icon-volume-down {
2044 background-position: -384px -24px;
2045}
2046.icon-volume-up {
2047 background-position: -408px -24px;
2048}
2049.icon-qrcode {
2050 background-position: -432px -24px;
2051}
2052.icon-barcode {
2053 background-position: -456px -24px;
2054}
2055.icon-tag {
2056 background-position: 0 -48px;
2057}
2058.icon-tags {
2059 background-position: -25px -48px;
2060}
2061.icon-book {
2062 background-position: -48px -48px;
2063}
2064.icon-bookmark {
2065 background-position: -72px -48px;
2066}
2067.icon-print {
2068 background-position: -96px -48px;
2069}
2070.icon-camera {
2071 background-position: -120px -48px;
2072}
2073.icon-font {
2074 background-position: -144px -48px;
2075}
2076.icon-bold {
2077 background-position: -167px -48px;
2078}
2079.icon-italic {
2080 background-position: -192px -48px;
2081}
2082.icon-text-height {
2083 background-position: -216px -48px;
2084}
2085.icon-text-width {
2086 background-position: -240px -48px;
2087}
2088.icon-align-left {
2089 background-position: -264px -48px;
2090}
2091.icon-align-center {
2092 background-position: -288px -48px;
2093}
2094.icon-align-right {
2095 background-position: -312px -48px;
2096}
2097.icon-align-justify {
2098 background-position: -336px -48px;
2099} 1820}
2100.icon-list { 1821/* line 515, ../scss/include/_skeleton.scss */
2101 background-position: -360px -48px; 1822#jqt ul.plastic li small {
2102} 1823 color: #949698;
2103.icon-indent-left { 1824 font-size: 13px;
2104 background-position: -384px -48px; 1825 font-weight: bold;
2105} 1826 text-transform: uppercase;
2106.icon-indent-right {
2107 background-position: -408px -48px;
2108}
2109.icon-facetime-video {
2110 background-position: -432px -48px;
2111}
2112.icon-picture {
2113 background-position: -456px -48px;
2114}
2115.icon-pencil {
2116 background-position: 0 -72px;
2117}
2118.icon-map-marker {
2119 background-position: -24px -72px;
2120}
2121.icon-adjust {
2122 background-position: -48px -72px;
2123}
2124.icon-tint {
2125 background-position: -72px -72px;
2126}
2127.icon-edit {
2128 background-position: -96px -72px;
2129}
2130.icon-share {
2131 background-position: -120px -72px;
2132}
2133.icon-check {
2134 background-position: -144px -72px;
2135}
2136.icon-move {
2137 background-position: -168px -72px;
2138}
2139.icon-step-backward {
2140 background-position: -192px -72px;
2141}
2142.icon-fast-backward {
2143 background-position: -216px -72px;
2144}
2145.icon-backward {
2146 background-position: -240px -72px;
2147}
2148.icon-play {
2149 background-position: -264px -72px;
2150}
2151.icon-pause {
2152 background-position: -288px -72px;
2153}
2154.icon-stop {
2155 background-position: -312px -72px;
2156}
2157.icon-forward {
2158 background-position: -336px -72px;
2159}
2160.icon-fast-forward {
2161 background-position: -360px -72px;
2162}
2163.icon-step-forward {
2164 background-position: -384px -72px;
2165}
2166.icon-eject {
2167 background-position: -408px -72px;
2168}
2169.icon-chevron-left {
2170 background-position: -432px -72px;
2171}
2172.icon-chevron-right {
2173 background-position: -456px -72px;
2174}
2175.icon-plus-sign {
2176 background-position: 0 -96px;
2177}
2178.icon-minus-sign {
2179 background-position: -24px -96px;
2180}
2181.icon-remove-sign {
2182 background-position: -48px -96px;
2183}
2184.icon-ok-sign {
2185 background-position: -72px -96px;
2186}
2187.icon-question-sign {
2188 background-position: -96px -96px;
2189}
2190.icon-info-sign {
2191 background-position: -120px -96px;
2192}
2193.icon-screenshot {
2194 background-position: -144px -96px;
2195}
2196.icon-remove-circle {
2197 background-position: -168px -96px;
2198}
2199.icon-ok-circle {
2200 background-position: -192px -96px;
2201}
2202.icon-ban-circle {
2203 background-position: -216px -96px;
2204}
2205.icon-arrow-left {
2206 background-position: -240px -96px;
2207}
2208.icon-arrow-right {
2209 background-position: -264px -96px;
2210}
2211.icon-arrow-up {
2212 background-position: -289px -96px;
2213}
2214.icon-arrow-down {
2215 background-position: -312px -96px;
2216}
2217.icon-share-alt {
2218 background-position: -336px -96px;
2219}
2220.icon-resize-full {
2221 background-position: -360px -96px;
2222}
2223.icon-resize-small {
2224 background-position: -384px -96px;
2225}
2226.icon-plus {
2227 background-position: -408px -96px;
2228}
2229.icon-minus {
2230 background-position: -433px -96px;
2231}
2232.icon-asterisk {
2233 background-position: -456px -96px;
2234}
2235.icon-exclamation-sign {
2236 background-position: 0 -120px;
2237}
2238.icon-gift {
2239 background-position: -24px -120px;
2240}
2241.icon-leaf {
2242 background-position: -48px -120px;
2243}
2244.icon-fire {
2245 background-position: -72px -120px;
2246}
2247.icon-eye-open {
2248 background-position: -96px -120px;
2249}
2250.icon-eye-close {
2251 background-position: -120px -120px;
2252}
2253.icon-warning-sign {
2254 background-position: -144px -120px;
2255}
2256.icon-plane {
2257 background-position: -168px -120px;
2258}
2259.icon-calendar {
2260 background-position: -192px -120px;
2261}
2262.icon-random {
2263 background-position: -216px -120px;
2264 width: 16px;
2265}
2266.icon-comment {
2267 background-position: -240px -120px;
2268}
2269.icon-magnet {
2270 background-position: -264px -120px;
2271}
2272.icon-chevron-up {
2273 background-position: -288px -120px;
2274}
2275.icon-chevron-down {
2276 background-position: -313px -119px;
2277}
2278.icon-retweet {
2279 background-position: -336px -120px;
2280}
2281.icon-shopping-cart {
2282 background-position: -360px -120px;
2283}
2284.icon-folder-close {
2285 background-position: -384px -120px;
2286}
2287.icon-folder-open {
2288 background-position: -408px -120px;
2289 width: 16px;
2290}
2291.icon-resize-vertical {
2292 background-position: -432px -119px;
2293}
2294.icon-resize-horizontal {
2295 background-position: -456px -118px;
2296}
2297.icon-hdd {
2298 background-position: 0 -144px;
2299}
2300.icon-bullhorn {
2301 background-position: -24px -144px;
2302}
2303.icon-bell {
2304 background-position: -48px -144px;
2305}
2306.icon-certificate {
2307 background-position: -72px -144px;
2308}
2309.icon-thumbs-up {
2310 background-position: -96px -144px;
2311}
2312.icon-thumbs-down {
2313 background-position: -120px -144px;
2314}
2315.icon-hand-right {
2316 background-position: -144px -144px;
2317}
2318.icon-hand-left {
2319 background-position: -168px -144px;
2320}
2321.icon-hand-up {
2322 background-position: -192px -144px;
2323}
2324.icon-hand-down {
2325 background-position: -216px -144px;
2326}
2327.icon-circle-arrow-right {
2328 background-position: -240px -144px;
2329}
2330.icon-circle-arrow-left {
2331 background-position: -264px -144px;
2332}
2333.icon-circle-arrow-up {
2334 background-position: -288px -144px;
2335}
2336.icon-circle-arrow-down {
2337 background-position: -312px -144px;
2338}
2339.icon-globe {
2340 background-position: -336px -144px;
2341}
2342.icon-wrench {
2343 background-position: -360px -144px;
2344}
2345.icon-tasks {
2346 background-position: -384px -144px;
2347}
2348.icon-filter {
2349 background-position: -408px -144px;
2350}
2351.icon-briefcase {
2352 background-position: -432px -144px;
2353}
2354.icon-fullscreen {
2355 background-position: -456px -144px;
2356}
2357.dropup,
2358.dropdown {
2359 position: relative;
2360}
2361.dropdown-toggle {
2362 *margin-bottom: -3px;
2363}
2364.dropdown-toggle:active,
2365.open .dropdown-toggle {
2366 outline: 0;
2367}
2368.caret {
2369 display: inline-block;
2370 width: 0;
2371 height: 0;
2372 vertical-align: top;
2373 border-top: 4px solid #000000;
2374 border-right: 4px solid transparent;
2375 border-left: 4px solid transparent;
2376 content: "";
2377}
2378.dropdown .caret {
2379 margin-top: 8px;
2380 margin-left: 2px;
2381}
2382.dropdown-menu {
2383 position: absolute;
2384 top: 100%;
2385 left: 0;
2386 z-index: 1000;
2387 display: none;
2388 float: left;
2389 min-width: 160px;
2390 padding: 5px 0;
2391 margin: 2px 0 0;
2392 list-style: none;
2393 background-color: #ffffff;
2394 border: 1px solid #ccc;
2395 border: 1px solid rgba(0, 0, 0, 0.2);
2396 *border-right-width: 2px;
2397 *border-bottom-width: 2px;
2398 -webkit-border-radius: 6px;
2399 -moz-border-radius: 6px;
2400 border-radius: 6px;
2401 -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
2402 -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
2403 box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
2404 -webkit-background-clip: padding-box;
2405 -moz-background-clip: padding;
2406 background-clip: padding-box;
2407}
2408.dropdown-menu.pull-right {
2409 right: 0;
2410 left: auto;
2411}
2412.dropdown-menu .divider {
2413 *width: 100%;
2414 height: 1px;
2415 margin: 9px 1px;
2416 *margin: -5px 0 5px;
2417 overflow: hidden;
2418 background-color: #e5e5e5;
2419 border-bottom: 1px solid #ffffff;
2420} 1827}
2421.dropdown-menu li > a { 1828/* line 525, ../scss/include/_skeleton.scss */
2422 display: block; 1829#jqt ul.individual {
2423 padding: 3px 20px; 1830 border: 0;
1831 background: none;
2424 clear: both; 1832 clear: both;
2425 font-weight: normal; 1833 overflow: hidden;
2426 line-height: 20px;
2427 color: #333333;
2428 white-space: nowrap;
2429}
2430.dropdown-menu li > a:hover,
2431.dropdown-menu li > a:focus,
2432.dropdown-submenu:hover > a {
2433 text-decoration: none;
2434 color: #ffffff;
2435 background-color: #0081c2;
2436 background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
2437 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
2438 background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
2439 background-image: -o-linear-gradient(top, #0088cc, #0077b3);
2440 background-image: linear-gradient(to bottom, #0088cc, #0077b3);
2441 background-repeat: repeat-x;
2442 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
2443}
2444.dropdown-menu .active > a,
2445.dropdown-menu .active > a:hover {
2446 color: #ffffff;
2447 text-decoration: none;
2448 outline: 0;
2449 background-color: #0081c2;
2450 background-image: -moz-linear-gradient(top, #0088cc, #0077b3);
2451 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0077b3));
2452 background-image: -webkit-linear-gradient(top, #0088cc, #0077b3);
2453 background-image: -o-linear-gradient(top, #0088cc, #0077b3);
2454 background-image: linear-gradient(to bottom, #0088cc, #0077b3);
2455 background-repeat: repeat-x;
2456 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0077b3', GradientType=0);
2457}
2458.dropdown-menu .disabled > a,
2459.dropdown-menu .disabled > a:hover {
2460 color: #999999;
2461}
2462.dropdown-menu .disabled > a:hover {
2463 text-decoration: none;
2464 background-color: transparent;
2465 background-image: none;
2466 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2467 cursor: default;
2468}
2469.open {
2470 *z-index: 1000;
2471} 1834}
2472.open > .dropdown-menu { 1835/* line 531, ../scss/include/_skeleton.scss */
1836#jqt ul.individual li {
1837 font-size: 14px;
1838 text-align: center;
1839 -webkit-border-radius: 8px;
1840 border-radius: 8px;
1841 -webkit-box-sizing: border-box;
1842 box-sizing: border-box;
1843 width: 48%;
1844 float: left;
2473 display: block; 1845 display: block;
1846 padding: 11px 10px 14px 10px;
2474} 1847}
2475.pull-right > .dropdown-menu { 1848/* line 541, ../scss/include/_skeleton.scss */
2476 right: 0; 1849#jqt ul.individual li + li {
2477 left: auto; 1850 float: right;
2478}
2479.dropup .caret,
2480.navbar-fixed-bottom .dropdown .caret {
2481 border-top: 0;
2482 border-bottom: 4px solid #000000;
2483 content: "";
2484}
2485.dropup .dropdown-menu,
2486.navbar-fixed-bottom .dropdown .dropdown-menu {
2487 top: auto;
2488 bottom: 100%;
2489 margin-bottom: 1px;
2490} 1851}
2491.dropdown-submenu { 1852/* line 546, ../scss/include/_skeleton.scss */
1853#jqt ul.individual a {
1854 line-height: 16px;
1855 margin: -11px -10px -14px -10px;
1856 padding: 11px 10px 14px 10px;
1857 -webkit-border-radius: 8px;
1858 border-radius: 8px;
1859}
1860/* line 555, ../scss/include/_skeleton.scss */
1861#jqt .toggle {
1862 width: 94px;
2492 position: relative; 1863 position: relative;
2493} 1864 height: 27px;
2494.dropdown-submenu > .dropdown-menu {
2495 top: 0;
2496 left: 100%;
2497 margin-top: -6px;
2498 margin-left: -1px;
2499 -webkit-border-radius: 0 6px 6px 6px;
2500 -moz-border-radius: 0 6px 6px 6px;
2501 border-radius: 0 6px 6px 6px;
2502}
2503.dropdown-submenu:hover > .dropdown-menu {
2504 display: block; 1865 display: block;
2505} 1866 overflow: hidden;
2506.dropup .dropdown-submenu > .dropdown-menu {
2507 top: auto;
2508 bottom: 0;
2509 margin-top: 0;
2510 margin-bottom: -2px;
2511 -webkit-border-radius: 5px 5px 5px 0;
2512 -moz-border-radius: 5px 5px 5px 0;
2513 border-radius: 5px 5px 5px 0;
2514}
2515.dropdown-submenu > a:after {
2516 display: block;
2517 content: " ";
2518 float: right; 1867 float: right;
2519 width: 0;
2520 height: 0;
2521 border-color: transparent;
2522 border-style: solid;
2523 border-width: 5px 0 5px 5px;
2524 border-left-color: #cccccc;
2525 margin-top: 5px;
2526 margin-right: -10px;
2527}
2528.dropdown-submenu:hover > a:after {
2529 border-left-color: #ffffff;
2530}
2531.dropdown-submenu.pull-left {
2532 float: none;
2533}
2534.dropdown-submenu.pull-left > .dropdown-menu {
2535 left: -100%;
2536 margin-left: 10px;
2537 -webkit-border-radius: 6px 0 6px 6px;
2538 -moz-border-radius: 6px 0 6px 6px;
2539 border-radius: 6px 0 6px 6px;
2540}
2541.dropdown .dropdown-menu .nav-header {
2542 padding-left: 20px;
2543 padding-right: 20px;
2544}
2545.typeahead {
2546 z-index: 1051;
2547 margin-top: 2px;
2548 -webkit-border-radius: 4px;
2549 -moz-border-radius: 4px;
2550 border-radius: 4px;
2551} 1868}
2552.well { 1869/* line 563, ../scss/include/_skeleton.scss */
2553 min-height: 20px; 1870#jqt .toggle input[type="checkbox"] {
2554 padding: 19px; 1871 margin: 0;
2555 margin-bottom: 20px; 1872 -webkit-border-radius: 5px;
2556 background-color: #f5f5f5; 1873 border-radius: 5px;
2557 border: 1px solid #e3e3e3; 1874 height: 27px;
2558 -webkit-border-radius: 4px;
2559 -moz-border-radius: 4px;
2560 border-radius: 4px;
2561 -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
2562 -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
2563 box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
2564}
2565.well blockquote {
2566 border-color: #ddd;
2567 border-color: rgba(0, 0, 0, 0.15);
2568}
2569.well-large {
2570 padding: 24px;
2571 -webkit-border-radius: 6px;
2572 -moz-border-radius: 6px;
2573 border-radius: 6px;
2574}
2575.well-small {
2576 padding: 9px;
2577 -webkit-border-radius: 3px;
2578 -moz-border-radius: 3px;
2579 border-radius: 3px;
2580}
2581.fade {
2582 opacity: 0;
2583 -webkit-transition: opacity 0.15s linear;
2584 -moz-transition: opacity 0.15s linear;
2585 -o-transition: opacity 0.15s linear;
2586 transition: opacity 0.15s linear;
2587}
2588.fade.in {
2589 opacity: 1;
2590}
2591.collapse {
2592 position: relative;
2593 height: 0;
2594 overflow: hidden; 1875 overflow: hidden;
2595 -webkit-transition: height 0.35s ease; 1876 width: 149px;
2596 -moz-transition: height 0.35s ease; 1877 border: 0;
2597 -o-transition: height 0.35s ease; 1878 -webkit-transition: left 0.15s ease-in-out;
2598 transition: height 0.35s ease; 1879 transition: left 0.15s ease-in-out;
1880 position: absolute;
1881 top: 0;
1882 left: -55px;
1883 -webkit-appearance: textarea;
1884 -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
2599} 1885}
2600.collapse.in { 1886/* line 577, ../scss/include/_skeleton.scss */
2601 height: auto; 1887#jqt .toggle input[type="checkbox"]:checked {
1888 left: 0px;
2602} 1889}
2603.close { 1890/* line 583, ../scss/include/_skeleton.scss */
2604 float: right; 1891#jqt .info {
2605 font-size: 20px; 1892 font-size: 12px;
1893 line-height: 16px;
1894 text-align: center;
1895 color: #444;
1896 padding: 15px;
2606 font-weight: bold; 1897 font-weight: bold;
2607 line-height: 20px;
2608 color: #000000;
2609 text-shadow: 0 1px 0 #ffffff;
2610 opacity: 0.2;
2611 filter: alpha(opacity=20);
2612} 1898}
2613.close:hover { 1899/* line 12, ../scss/jqtouch.scss */
2614 color: #000000; 1900#jqt {
2615 text-decoration: none; 1901 /* Lists */
2616 cursor: pointer; 1902
2617 opacity: 0.4;
2618 filter: alpha(opacity=40);
2619} 1903}
2620button.close { 1904/* line 13, ../scss/jqtouch.scss */
2621 padding: 0; 1905#jqt > * {
2622 cursor: pointer; 1906 background-image: url('data:image/png;base64,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'), -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #7b7c7f), color-stop(30%, #696a6d), color-stop(65%, #555658), color-stop(100%, #464748));
2623 background: transparent; 1907 background-image: url('data:image/png;base64,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'), -webkit-linear-gradient(top, #7b7c7f, #696a6d 30%, #555658 65%, #464748);
2624 border: 0; 1908 background-image: url('data:image/png;base64,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'), linear-gradient(top, #7b7c7f, #696a6d 30%, #555658 65%, #464748);
2625 -webkit-appearance: none; 1909}
1910/* line 20, ../scss/jqtouch.scss */
1911#jqt .toolbar {
1912 background-image: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 12.5, color-stop(12.5%, #181819), color-stop(12.5%, rgba(11, 11, 12, 0))), -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 12.5, color-stop(12.5%, #181819), color-stop(12.5%, rgba(11, 11, 12, 0))), -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 12.5, color-stop(12.5%, rgba(255, 255, 255, 0.1)), color-stop(12.5%, rgba(255, 255, 255, 0))), -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 12.5, color-stop(12.5%, rgba(255, 255, 255, 0.1)), color-stop(12.5%, rgba(255, 255, 255, 0)));
1913 background-image: -webkit-radial-gradient(#181819 12.5%, rgba(11, 11, 12, 0) 12.5%), -webkit-radial-gradient(#181819 12.5%, rgba(11, 11, 12, 0) 12.5%), -webkit-radial-gradient(rgba(255, 255, 255, 0.1) 12.5%, rgba(255, 255, 255, 0) 12.5%), -webkit-radial-gradient(rgba(255, 255, 255, 0.1) 12.5%, rgba(255, 255, 255, 0) 12.5%);
1914 background-image: radial-gradient(#181819 12.5%, rgba(11, 11, 12, 0) 12.5%), radial-gradient(#181819 12.5%, rgba(11, 11, 12, 0) 12.5%), radial-gradient(rgba(255, 255, 255, 0.1) 12.5%, rgba(255, 255, 255, 0) 12.5%), radial-gradient(rgba(255, 255, 255, 0.1) 12.5%, rgba(255, 255, 255, 0) 12.5%);
1915 background-repeat: repeat;
1916 background-position: 0 0, 8px 8px, 0 1px, 8px 9px;
1917 background-color: #2f3031;
1918 background-size: 16px 16px;
1919}
1920/* line 29, ../scss/jqtouch.scss */
1921#jqt ul li {
1922 border-top: 1px solid #48494b;
1923 background-image: none;
1924 background-color: rgba(85, 86, 88, 0.2);
1925 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(123, 124, 127, 0.2)), color-stop(3%, rgba(98, 99, 101, 0.2)), color-stop(100%, rgba(72, 73, 75, 0.2)));
1926 background-image: -webkit-linear-gradient(top, rgba(123, 124, 127, 0.2), rgba(98, 99, 101, 0.2) 3%, rgba(72, 73, 75, 0.2));
1927 background-image: linear-gradient(top, rgba(123, 124, 127, 0.2), rgba(98, 99, 101, 0.2) 3%, rgba(72, 73, 75, 0.2));
1928}
1929/* line 33, ../scss/jqtouch.scss */
1930#jqt ul li a {
1931 color: white;
1932 text-shadow: #3c3d3e 0 -1px 0;
1933}
1934/* line 37, ../scss/jqtouch.scss */
1935#jqt ul li .toggle input[type="checkbox"] {
1936 -webkit-border-radius: 5px;
1937 border-radius: 5px;
1938 background: #ffffff url(../img/jqt/on_off.png) 0 0 no-repeat;
2626} 1939}
2627.btn { 1940/* line 42, ../scss/jqtouch.scss */
2628 display: inline-block; 1941#jqt ul li input[type='submit'] {
2629 *display: inline;
2630 /* IE7 inline-block hack */
2631
2632 *zoom: 1;
2633 padding: 4px 12px;
2634 margin-bottom: 0;
2635 font-size: 14px;
2636 line-height: 20px;
2637 text-align: center;
2638 vertical-align: middle;
2639 cursor: pointer;
2640 color: #333333;
2641 text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
2642 background-color: #f5f5f5;
2643 background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
2644 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#e6e6e6));
2645 background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
2646 background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
2647 background-image: linear-gradient(to bottom, #ffffff, #e6e6e6);
2648 background-repeat: repeat-x;
2649 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0);
2650 border-color: #e6e6e6 #e6e6e6 #bfbfbf;
2651 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2652 *background-color: #e6e6e6;
2653 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2654
2655 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2656 border: 1px solid #bbbbbb;
2657 *border: 0;
2658 border-bottom-color: #a2a2a2;
2659 -webkit-border-radius: 4px;
2660 -moz-border-radius: 4px;
2661 border-radius: 4px;
2662 *margin-left: .3em;
2663 -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2664 -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2665 box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
2666}
2667.btn:hover,
2668.btn:active,
2669.btn.active,
2670.btn.disabled,
2671.btn[disabled] {
2672 color: #333333;
2673 background-color: #e6e6e6;
2674 *background-color: #d9d9d9;
2675}
2676.btn:active,
2677.btn.active {
2678 background-color: #cccccc \9;
2679}
2680.btn:first-child {
2681 *margin-left: 0;
2682}
2683.btn:hover {
2684 color: #333333;
2685 text-decoration: none;
2686 background-position: 0 -15px;
2687 -webkit-transition: background-position 0.1s linear;
2688 -moz-transition: background-position 0.1s linear;
2689 -o-transition: background-position 0.1s linear;
2690 transition: background-position 0.1s linear;
2691}
2692.btn:focus {
2693 outline: thin dotted #333;
2694 outline: 5px auto -webkit-focus-ring-color;
2695 outline-offset: -2px;
2696}
2697.btn.active,
2698.btn:active {
2699 background-image: none; 1942 background-image: none;
2700 outline: 0; 1943 background-color: white;
2701 -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); 1944 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(50%, #ffffff), color-stop(51%, #ffffff), color-stop(100%, #f2f2f2));
2702 -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); 1945 background-image: -webkit-linear-gradient(top, #ffffff, #ffffff 50%, #ffffff 51%, #f2f2f2);
2703 box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); 1946 background-image: linear-gradient(top, #ffffff, #ffffff 50%, #ffffff 51%, #f2f2f2);
2704} 1947 border: 1px outset black;
2705.btn.disabled, 1948}
2706.btn[disabled] { 1949/* line 47, ../scss/jqtouch.scss */
2707 cursor: default; 1950#jqt ul li small.counter {
1951 -webkit-box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0;
1952 box-shadow: rgba(255, 255, 255, 0.1) 0 1px 0;
1953}
1954/* line 54, ../scss/jqtouch.scss */
1955#jqt ul.metal li {
2708 background-image: none; 1956 background-image: none;
2709 opacity: 0.65; 1957 border-top: 1px solid #fff;
2710 filter: alpha(opacity=65); 1958 border-bottom: 1px solid #666;
2711 -webkit-box-shadow: none; 1959 background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#eeeeee), to(#9c9ea0));
2712 -moz-box-shadow: none;
2713 box-shadow: none;
2714}
2715.btn-large {
2716 padding: 11px 19px;
2717 font-size: 17.5px;
2718 -webkit-border-radius: 6px;
2719 -moz-border-radius: 6px;
2720 border-radius: 6px;
2721}
2722.btn-large [class^="icon-"],
2723.btn-large [class*=" icon-"] {
2724 margin-top: 4px;
2725}
2726.btn-small {
2727 padding: 2px 10px;
2728 font-size: 11.9px;
2729 -webkit-border-radius: 3px;
2730 -moz-border-radius: 3px;
2731 border-radius: 3px;
2732} 1960}
2733.btn-small [class^="icon-"], 1961/* line 60, ../scss/jqtouch.scss */
2734.btn-small [class*=" icon-"] { 1962#jqt ul.metal li a {
2735 margin-top: 0; 1963 text-shadow: #fff 0 1px 0;
2736} 1964}
2737.btn-mini [class^="icon-"], 1965/* line 62, ../scss/jqtouch.scss */
2738.btn-mini [class*=" icon-"] { 1966#jqt ul.metal li a.active {
2739 margin-top: -1px; 1967 color: #000;
2740} 1968}
2741.btn-mini { 1969/* line 65, ../scss/jqtouch.scss */
2742 padding: 0 6px; 1970#jqt ul.metal li em {
2743 font-size: 10.5px; 1971 color: #444;
2744 -webkit-border-radius: 3px;
2745 -moz-border-radius: 3px;
2746 border-radius: 3px;
2747} 1972}
2748.btn-block { 1973/* line 71, ../scss/jqtouch.scss */
2749 display: block; 1974#jqt ul.edgetoedge li {
2750 width: 100%;
2751 padding-left: 0;
2752 padding-right: 0;
2753 -webkit-box-sizing: border-box;
2754 -moz-box-sizing: border-box;
2755 box-sizing: border-box;
2756}
2757.btn-block + .btn-block {
2758 margin-top: 5px;
2759}
2760input[type="submit"].btn-block,
2761input[type="reset"].btn-block,
2762input[type="button"].btn-block {
2763 width: 100%;
2764}
2765.btn-primary.active,
2766.btn-warning.active,
2767.btn-danger.active,
2768.btn-success.active,
2769.btn-info.active,
2770.btn-inverse.active {
2771 color: rgba(255, 255, 255, 0.75);
2772}
2773.btn {
2774 border-color: #c5c5c5;
2775 border-color: rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);
2776}
2777.btn-primary {
2778 color: #ffffff;
2779 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2780 background-color: #006dcc;
2781 background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
2782 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
2783 background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
2784 background-image: -o-linear-gradient(top, #0088cc, #0044cc);
2785 background-image: linear-gradient(to bottom, #0088cc, #0044cc);
2786 background-repeat: repeat-x;
2787 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc', endColorstr='#ff0044cc', GradientType=0);
2788 border-color: #0044cc #0044cc #002a80;
2789 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2790 *background-color: #0044cc;
2791 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2792
2793 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2794}
2795.btn-primary:hover,
2796.btn-primary:active,
2797.btn-primary.active,
2798.btn-primary.disabled,
2799.btn-primary[disabled] {
2800 color: #ffffff;
2801 background-color: #0044cc;
2802 *background-color: #003bb3;
2803}
2804.btn-primary:active,
2805.btn-primary.active {
2806 background-color: #003399 \9;
2807}
2808.btn-warning {
2809 color: #ffffff;
2810 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2811 background-color: #faa732;
2812 background-image: -moz-linear-gradient(top, #fbb450, #f89406);
2813 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
2814 background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
2815 background-image: -o-linear-gradient(top, #fbb450, #f89406);
2816 background-image: linear-gradient(to bottom, #fbb450, #f89406);
2817 background-repeat: repeat-x;
2818 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
2819 border-color: #f89406 #f89406 #ad6704;
2820 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2821 *background-color: #f89406;
2822 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2823
2824 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2825}
2826.btn-warning:hover,
2827.btn-warning:active,
2828.btn-warning.active,
2829.btn-warning.disabled,
2830.btn-warning[disabled] {
2831 color: #ffffff;
2832 background-color: #f89406;
2833 *background-color: #df8505;
2834}
2835.btn-warning:active,
2836.btn-warning.active {
2837 background-color: #c67605 \9;
2838}
2839.btn-danger {
2840 color: #ffffff;
2841 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2842 background-color: #da4f49;
2843 background-image: -moz-linear-gradient(top, #ee5f5b, #bd362f);
2844 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#bd362f));
2845 background-image: -webkit-linear-gradient(top, #ee5f5b, #bd362f);
2846 background-image: -o-linear-gradient(top, #ee5f5b, #bd362f);
2847 background-image: linear-gradient(to bottom, #ee5f5b, #bd362f);
2848 background-repeat: repeat-x;
2849 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffbd362f', GradientType=0);
2850 border-color: #bd362f #bd362f #802420;
2851 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2852 *background-color: #bd362f;
2853 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2854
2855 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2856}
2857.btn-danger:hover,
2858.btn-danger:active,
2859.btn-danger.active,
2860.btn-danger.disabled,
2861.btn-danger[disabled] {
2862 color: #ffffff;
2863 background-color: #bd362f;
2864 *background-color: #a9302a;
2865}
2866.btn-danger:active,
2867.btn-danger.active {
2868 background-color: #942a25 \9;
2869}
2870.btn-success {
2871 color: #ffffff;
2872 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2873 background-color: #5bb75b;
2874 background-image: -moz-linear-gradient(top, #62c462, #51a351);
2875 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#51a351));
2876 background-image: -webkit-linear-gradient(top, #62c462, #51a351);
2877 background-image: -o-linear-gradient(top, #62c462, #51a351);
2878 background-image: linear-gradient(to bottom, #62c462, #51a351);
2879 background-repeat: repeat-x;
2880 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff51a351', GradientType=0);
2881 border-color: #51a351 #51a351 #387038;
2882 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2883 *background-color: #51a351;
2884 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2885
2886 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2887}
2888.btn-success:hover,
2889.btn-success:active,
2890.btn-success.active,
2891.btn-success.disabled,
2892.btn-success[disabled] {
2893 color: #ffffff;
2894 background-color: #51a351;
2895 *background-color: #499249;
2896}
2897.btn-success:active,
2898.btn-success.active {
2899 background-color: #408140 \9;
2900}
2901.btn-info {
2902 color: #ffffff;
2903 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2904 background-color: #49afcd;
2905 background-image: -moz-linear-gradient(top, #5bc0de, #2f96b4);
2906 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#2f96b4));
2907 background-image: -webkit-linear-gradient(top, #5bc0de, #2f96b4);
2908 background-image: -o-linear-gradient(top, #5bc0de, #2f96b4);
2909 background-image: linear-gradient(to bottom, #5bc0de, #2f96b4);
2910 background-repeat: repeat-x;
2911 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2f96b4', GradientType=0);
2912 border-color: #2f96b4 #2f96b4 #1f6377;
2913 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2914 *background-color: #2f96b4;
2915 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2916
2917 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2918}
2919.btn-info:hover,
2920.btn-info:active,
2921.btn-info.active,
2922.btn-info.disabled,
2923.btn-info[disabled] {
2924 color: #ffffff;
2925 background-color: #2f96b4;
2926 *background-color: #2a85a0;
2927}
2928.btn-info:active,
2929.btn-info.active {
2930 background-color: #24748c \9;
2931}
2932.btn-inverse {
2933 color: #ffffff;
2934 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
2935 background-color: #363636;
2936 background-image: -moz-linear-gradient(top, #444444, #222222);
2937 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#444444), to(#222222));
2938 background-image: -webkit-linear-gradient(top, #444444, #222222);
2939 background-image: -o-linear-gradient(top, #444444, #222222);
2940 background-image: linear-gradient(to bottom, #444444, #222222);
2941 background-repeat: repeat-x;
2942 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444', endColorstr='#ff222222', GradientType=0);
2943 border-color: #222222 #222222 #000000;
2944 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
2945 *background-color: #222222;
2946 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
2947
2948 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
2949}
2950.btn-inverse:hover,
2951.btn-inverse:active,
2952.btn-inverse.active,
2953.btn-inverse.disabled,
2954.btn-inverse[disabled] {
2955 color: #ffffff;
2956 background-color: #222222;
2957 *background-color: #151515;
2958}
2959.btn-inverse:active,
2960.btn-inverse.active {
2961 background-color: #080808 \9;
2962}
2963button.btn,
2964input[type="submit"].btn {
2965 *padding-top: 3px;
2966 *padding-bottom: 3px;
2967}
2968button.btn::-moz-focus-inner,
2969input[type="submit"].btn::-moz-focus-inner {
2970 padding: 0;
2971 border: 0;
2972}
2973button.btn.btn-large,
2974input[type="submit"].btn.btn-large {
2975 *padding-top: 7px;
2976 *padding-bottom: 7px;
2977}
2978button.btn.btn-small,
2979input[type="submit"].btn.btn-small {
2980 *padding-top: 3px;
2981 *padding-bottom: 3px;
2982}
2983button.btn.btn-mini,
2984input[type="submit"].btn.btn-mini {
2985 *padding-top: 1px;
2986 *padding-bottom: 1px;
2987}
2988.btn-link,
2989.btn-link:active,
2990.btn-link[disabled] {
2991 background-color: transparent;
2992 background-image: none; 1975 background-image: none;
2993 -webkit-box-shadow: none; 1976 background-color: #3c3d3e;
2994 -moz-box-shadow: none; 1977 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #282829), color-stop(100%, #2f3031));
2995 box-shadow: none; 1978 background-image: -webkit-linear-gradient(top, #282829, #2f3031);
2996} 1979 background-image: linear-gradient(top, #282829, #2f3031);
2997.btn-link { 1980 border-bottom: 1px solid #1e1e1f;
2998 border-color: transparent; 1981 border-top: 1px solid #343536;
2999 cursor: pointer; 1982}
3000 color: #0088cc; 1983/* line 76, ../scss/jqtouch.scss */
3001 -webkit-border-radius: 0; 1984#jqt ul.edgetoedge li.sep {
3002 -moz-border-radius: 0; 1985 background-image: none;
3003 border-radius: 0; 1986 background-color: rgba(0, 0, 0, 0.3);
3004} 1987 background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(38, 38, 38, 0.3)), color-stop(30%, rgba(20, 20, 20, 0.3)), color-stop(65%, rgba(0, 0, 0, 0.3)), color-stop(100%, rgba(0, 0, 0, 0.3)));
3005.btn-link:hover { 1988 background-image: -webkit-linear-gradient(top, rgba(38, 38, 38, 0.3), rgba(20, 20, 20, 0.3) 30%, rgba(0, 0, 0, 0.3) 65%, rgba(0, 0, 0, 0.3));
3006 color: #005580; 1989 background-image: linear-gradient(top, rgba(38, 38, 38, 0.3), rgba(20, 20, 20, 0.3) 30%, rgba(0, 0, 0, 0.3) 65%, rgba(0, 0, 0, 0.3));
3007 text-decoration: underline; 1990 color: #949698;
3008 background-color: transparent; 1991 text-shadow: #000000 0 -1px 0;
3009} 1992}
3010.btn-link[disabled]:hover { 1993/* line 83, ../scss/jqtouch.scss */
3011 color: #333333; 1994#jqt .info {
3012 text-decoration: none; 1995 background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#cccccc), to(#aaaaaa), color-stop(0.6, #cccccc));
1996 text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
1997 color: #444;
1998 border-top: 1px solid rgba(255, 255, 255, 0.2);
3013} 1999}
3014.btn-group { 2000div.spinner {
3015 position: relative; 2001 position: relative;
2002 width: 100px;
2003 height: 100px;
3016 display: inline-block; 2004 display: inline-block;
3017 *display: inline;
3018 /* IE7 inline-block hack */
3019
3020 *zoom: 1;
3021 font-size: 0;
3022 vertical-align: middle;
3023 white-space: nowrap;
3024 *margin-left: .3em;
3025} 2005}
3026.btn-group:first-child { 2006div.spinner div {
3027 *margin-left: 0; 2007 width: 12%;
2008 height: 26%;
2009 background: #000;
2010 position: absolute;
2011 left: 44.5%;
2012 top: 37%;
2013 opacity: 0;
2014 -webkit-animation: fade 1s linear infinite;
2015 -webkit-border-radius: 50px;
2016 -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
3028} 2017}
3029.btn-group + .btn-group { 2018div.spinner div.bar01 {
3030 margin-left: 5px; 2019 -webkit-transform: rotate(0deg) translate(0, -142%);
2020 -webkit-animation-delay: 0s;
3031} 2021}
3032.btn-toolbar { 2022div.spinner div.bar02 {
3033 font-size: 0; 2023 -webkit-transform: rotate(30deg) translate(0, -142%);
3034 margin-top: 10px; 2024 -webkit-animation-delay: -0.9167s;
3035 margin-bottom: 10px;
3036} 2025}
3037.btn-toolbar > .btn + .btn, 2026div.spinner div.bar03 {
3038.btn-toolbar > .btn-group + .btn, 2027 -webkit-transform: rotate(60deg) translate(0, -142%);
3039.btn-toolbar > .btn + .btn-group { 2028 -webkit-animation-delay: -0.833s;
3040 margin-left: 5px;
3041} 2029}
3042.btn-group > .btn { 2030div.spinner div.bar04 {
3043 position: relative; 2031 -webkit-transform: rotate(90deg) translate(0, -142%);
3044 -webkit-border-radius: 0; 2032 -webkit-animation-delay: -0.75s;
3045 -moz-border-radius: 0;
3046 border-radius: 0;
3047} 2033}
3048.btn-group > .btn + .btn { 2034div.spinner div.bar05 {
3049 margin-left: -1px; 2035 -webkit-transform: rotate(120deg) translate(0, -142%);
2036 -webkit-animation-delay: -0.667s;
3050} 2037}
3051.btn-group > .btn, 2038div.spinner div.bar06 {
3052.btn-group > .dropdown-menu, 2039 -webkit-transform: rotate(150deg) translate(0, -142%);
3053.btn-group > .popover { 2040 -webkit-animation-delay: -0.5833s;
3054 font-size: 14px;
3055} 2041}
3056.btn-group > .btn-mini { 2042div.spinner div.bar07 {
3057 font-size: 10.5px; 2043 -webkit-transform: rotate(180deg) translate(0, -142%);
3058} 2044 -webkit-animation-delay: -0.5s;
3059.btn-group > .btn-small {
3060 font-size: 11.9px;
3061}
3062.btn-group > .btn-large {
3063 font-size: 17.5px;
3064}
3065.btn-group > .btn:first-child {
3066 margin-left: 0;
3067 -webkit-border-top-left-radius: 4px;
3068 -moz-border-radius-topleft: 4px;
3069 border-top-left-radius: 4px;
3070 -webkit-border-bottom-left-radius: 4px;
3071 -moz-border-radius-bottomleft: 4px;
3072 border-bottom-left-radius: 4px;
3073}
3074.btn-group > .btn:last-child,
3075.btn-group > .dropdown-toggle {
3076 -webkit-border-top-right-radius: 4px;
3077 -moz-border-radius-topright: 4px;
3078 border-top-right-radius: 4px;
3079 -webkit-border-bottom-right-radius: 4px;
3080 -moz-border-radius-bottomright: 4px;
3081 border-bottom-right-radius: 4px;
3082}
3083.btn-group > .btn.large:first-child {
3084 margin-left: 0;
3085 -webkit-border-top-left-radius: 6px;
3086 -moz-border-radius-topleft: 6px;
3087 border-top-left-radius: 6px;
3088 -webkit-border-bottom-left-radius: 6px;
3089 -moz-border-radius-bottomleft: 6px;
3090 border-bottom-left-radius: 6px;
3091}
3092.btn-group > .btn.large:last-child,
3093.btn-group > .large.dropdown-toggle {
3094 -webkit-border-top-right-radius: 6px;
3095 -moz-border-radius-topright: 6px;
3096 border-top-right-radius: 6px;
3097 -webkit-border-bottom-right-radius: 6px;
3098 -moz-border-radius-bottomright: 6px;
3099 border-bottom-right-radius: 6px;
3100}
3101.btn-group > .btn:hover,
3102.btn-group > .btn:focus,
3103.btn-group > .btn:active,
3104.btn-group > .btn.active {
3105 z-index: 2;
3106}
3107.btn-group .dropdown-toggle:active,
3108.btn-group.open .dropdown-toggle {
3109 outline: 0;
3110}
3111.btn-group > .btn + .dropdown-toggle {
3112 padding-left: 8px;
3113 padding-right: 8px;
3114 -webkit-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
3115 -moz-box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
3116 box-shadow: inset 1px 0 0 rgba(255,255,255,.125), inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);
3117 *padding-top: 5px;
3118 *padding-bottom: 5px;
3119}
3120.btn-group > .btn-mini + .dropdown-toggle {
3121 padding-left: 5px;
3122 padding-right: 5px;
3123 *padding-top: 2px;
3124 *padding-bottom: 2px;
3125} 2045}
3126.btn-group > .btn-small + .dropdown-toggle { 2046div.spinner div.bar08 {
3127 *padding-top: 5px; 2047 -webkit-transform: rotate(210deg) translate(0, -142%);
3128 *padding-bottom: 4px; 2048 -webkit-animation-delay: -0.41667s;
3129} 2049}
3130.btn-group > .btn-large + .dropdown-toggle { 2050div.spinner div.bar09 {
3131 padding-left: 12px; 2051 -webkit-transform: rotate(240deg) translate(0, -142%);
3132 padding-right: 12px; 2052 -webkit-animation-delay: -0.333s;
3133 *padding-top: 7px;
3134 *padding-bottom: 7px;
3135} 2053}
3136.btn-group.open .dropdown-toggle { 2054div.spinner div.bar10 {
3137 background-image: none; 2055 -webkit-transform: rotate(270deg) translate(0, -142%);
3138 -webkit-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); 2056 -webkit-animation-delay: -0.25s;
3139 -moz-box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
3140 box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05);
3141} 2057}
3142.btn-group.open .btn.dropdown-toggle { 2058div.spinner div.bar11 {
3143 background-color: #e6e6e6; 2059 -webkit-transform: rotate(300deg) translate(0, -142%);
2060 -webkit-animation-delay: -0.1667s;
3144} 2061}
3145.btn-group.open .btn-primary.dropdown-toggle { 2062div.spinner div.bar12 {
3146 background-color: #0044cc; 2063 -webkit-transform: rotate(330deg) translate(0, -142%);
2064 -webkit-animation-delay: -0.0833s;
3147} 2065}
3148.btn-group.open .btn-warning.dropdown-toggle { 2066@-webkit-keyframes fade {
3149 background-color: #f89406; 2067 from {
2068 opacity: 1;
3150} 2069}
3151.btn-group.open .btn-danger.dropdown-toggle { 2070 to {
3152 background-color: #bd362f; 2071 opacity: 0.25;
3153} 2072}
3154.btn-group.open .btn-success.dropdown-toggle {
3155 background-color: #51a351;
3156} 2073}
3157.btn-group.open .btn-info.dropdown-toggle { 2074/*
3158 background-color: #2f96b4; 2075
2076Color list:
2077- login box:
2078 light#ff9955
2079 dark#ff6622
2080- login button:
2081 regular#dd5500
2082 hover#773311
2083- login translations:
2084 box: #cc6622;
2085 not-selected:
2086 color: #ddaa99
2087 background:#994422
2088 selected: #772211;
2089*/
2090html {
2091 height: 100%;
2092 -webkit-text-size-adjust: none;
2093 -ms-text-size-adjust: none;
3159} 2094}
3160.btn-group.open .btn-inverse.dropdown-toggle { 2095body {
3161 background-color: #222222; 2096 font-family: Helvetica-Neue, Helvetica, Arial, Geneva, sans-serif;
2097 margin: 0px;
3162} 2098}
3163.btn .caret { 2099.ellipsis {
3164 margin-top: 8px; 2100 text-overflow: ellipsis;
3165 margin-left: 0; 2101 overflow: hidden;
2102 white-space: nowrap;
3166} 2103}
3167.btn-mini .caret, 2104div#loginForm div.credentialsMessage.error h1 {
3168.btn-small .caret, 2105 color: red;
3169.btn-large .caret {
3170 margin-top: 6px;
3171} 2106}
3172.btn-large .caret { 2107div#loginForm div.validating div.loading {
3173 border-left-width: 5px; 2108 margin-top: 50px;
3174 border-right-width: 5px; 2109 margin-bottom: 50px;
3175 border-top-width: 5px; 2110 margin-left: auto;
2111 margin-right: auto;
2112 width: 100px;
3176} 2113}
3177.dropup .btn-large .caret { 2114/*
3178 border-bottom-width: 5px; 2115
2116Color list:
2117- login box:
2118 light#ff9955
2119 dark#ff6622
2120- login button:
2121 regular#dd5500
2122 hover#773311
2123- login translations:
2124 box: #cc6622;
2125 not-selected:
2126 color: #ddaa99
2127 background:#994422
2128 selected: #772211;
2129*/
2130html {
2131 height: 100%;
2132 -webkit-text-size-adjust: none;
2133 -ms-text-size-adjust: none;
3179} 2134}
3180.btn-primary .caret, 2135body {
3181.btn-warning .caret, 2136 font-family: Helvetica-Neue, Helvetica, Arial, Geneva, sans-serif;
3182.btn-danger .caret, 2137 margin: 0px;
3183.btn-info .caret,
3184.btn-success .caret,
3185.btn-inverse .caret {
3186 border-top-color: #ffffff;
3187 border-bottom-color: #ffffff;
3188} 2138}
3189.btn-group-vertical { 2139.ellipsis {
3190 display: inline-block; 2140 text-overflow: ellipsis;
3191 *display: inline; 2141 overflow: hidden;
3192 /* IE7 inline-block hack */ 2142 white-space: nowrap;
3193
3194 *zoom: 1;
3195} 2143}
3196.btn-group-vertical > .btn { 2144#jqt div.cardList ul li.cardListItem a small.favicon {
2145 background: white;
2146 -webkit-border-radius: 3px;
2147 border-radius: 3px;
3197 display: block; 2148 display: block;
3198 float: none; 2149 width: 26px;
3199 max-width: 100%; 2150 height: 26px;
3200 -webkit-border-radius: 0; 2151 padding: 0px;
3201 -moz-border-radius: 0;
3202 border-radius: 0;
3203} 2152}
3204.btn-group-vertical > .btn + .btn { 2153#jqt div.cardList ul li.cardListItem a small.favicon img.favicon {
3205 margin-left: 0; 2154 margin-right: 3px;
3206 margin-top: -1px; 2155 margin-top: 3px;
3207} 2156 width: 20px;
3208.btn-group-vertical > .btn:first-child { 2157 height: 20px;
3209 -webkit-border-radius: 4px 4px 0 0;
3210 -moz-border-radius: 4px 4px 0 0;
3211 border-radius: 4px 4px 0 0;
3212}
3213.btn-group-vertical > .btn:last-child {
3214 -webkit-border-radius: 0 0 4px 4px;
3215 -moz-border-radius: 0 0 4px 4px;
3216 border-radius: 0 0 4px 4px;
3217}
3218.btn-group-vertical > .btn-large:first-child {
3219 -webkit-border-radius: 6px 6px 0 0;
3220 -moz-border-radius: 6px 6px 0 0;
3221 border-radius: 6px 6px 0 0;
3222}
3223.btn-group-vertical > .btn-large:last-child {
3224 -webkit-border-radius: 0 0 6px 6px;
3225 -moz-border-radius: 0 0 6px 6px;
3226 border-radius: 0 0 6px 6px;
3227}
3228.alert {
3229 padding: 8px 35px 8px 14px;
3230 margin-bottom: 20px;
3231 text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
3232 background-color: #fcf8e3;
3233 border: 1px solid #fbeed5;
3234 -webkit-border-radius: 4px;
3235 -moz-border-radius: 4px;
3236 border-radius: 4px;
3237} 2158}
3238.alert, 2159#jqt div.cardDetail ul li a.password {
3239.alert h4 { 2160 color: gray;
3240 color: #c09853;
3241} 2161}
3242.alert h4 { 2162/* ---------------------------------------- */
2163/*
2164body {
3243 margin: 0; 2165 margin: 0;
2166 font-family: Helvetica;
2167 background: #FFFFFF;
2168 color: #000000;
2169 overflow-x: hidden;
2170 -webkit-user-select: none;
2171 -webkit-text-size-adjust: none;
3244} 2172}
3245.alert .close { 2173
3246 position: relative; 2174
3247 top: -2px; 2175div.toolbar {
3248 right: -21px; 2176 box-sizing: border-box;
3249 line-height: 20px; 2177 -moz-box-sizing: border-box;
3250} 2178 -webkit-box-sizing: border-box;
3251.alert-success { 2179 border-bottom: 1px solid #2d3642;
3252 background-color: #dff0d8; 2180 border-top: 1px solid #6d84a2;
3253 border-color: #d6e9c6; 2181 padding: 10px;
3254 color: #468847; 2182 height: 45px;
3255} 2183 //background: url(./images/old/iPhone/toolbar.png) #6d84a2 repeat-x;
3256.alert-success h4 { 2184 background: url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAArCAIAAAA2QHWOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAE1JREFUCNddjDEOgEAQAgn//5qltYWFnb1GB4vdSy4WBAYStKyb9+O0FJMYyjMyMWCC35lJM71r6vF1P07/lFSfPx6ZxNLcy1HtihzpA/RWcOj0zlDhAAAAAElFTkSuQmCCCg==) #6d84a2 repeat-x;
3257 color: #468847;
3258}
3259.alert-danger,
3260.alert-error {
3261 background-color: #f2dede;
3262 border-color: #eed3d7;
3263 color: #b94a48;
3264}
3265.alert-danger h4,
3266.alert-error h4 {
3267 color: #b94a48;
3268}
3269.alert-info {
3270 background-color: #d9edf7;
3271 border-color: #bce8f1;
3272 color: #3a87ad;
3273}
3274.alert-info h4 {
3275 color: #3a87ad;
3276}
3277.alert-block {
3278 padding-top: 14px;
3279 padding-bottom: 14px;
3280}
3281.alert-block > p,
3282.alert-block > ul {
3283 margin-bottom: 0;
3284}
3285.alert-block p + p {
3286 margin-top: 5px;
3287}
3288.nav {
3289 margin-left: 0;
3290 margin-bottom: 20px;
3291 list-style: none;
3292}
3293.nav > li > a {
3294 display: block;
3295}
3296.nav > li > a:hover {
3297 text-decoration: none;
3298 background-color: #eeeeee;
3299}
3300.nav > li > a > img {
3301 max-width: none;
3302}
3303.nav > .pull-right {
3304 float: right;
3305} 2185}
3306.nav-header { 2186
3307 display: block; 2187div.toolbar h1#pageTitle {
3308 padding: 3px 15px; 2188 overflow: hidden;
3309 font-size: 11px; 2189 margin-top: 1px;
2190 margin-bottom: 0px;
2191 margin-left: auto;
2192 margin-right: auto;
2193 width: 150px;
2194 height: 25px;
2195 font-size: 20px;
2196 width: 150px;
3310 font-weight: bold; 2197 font-weight: bold;
3311 line-height: 20px; 2198 text-shadow: rgba(0, 0, 0, 0.4) 0px -1px 0;
3312 color: #999999; 2199 text-align: center;
3313 text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); 2200 text-overflow: ellipsis;
3314 text-transform: uppercase; 2201 white-space: nowrap;
2202 color: #FFFFFF;
3315} 2203}
3316.nav li + .nav-header { 2204
3317 margin-top: 9px; 2205div.toolbar a.button {
3318} 2206 position: absolute;
3319.nav-list {
3320 padding-left: 15px;
3321 padding-right: 15px;
3322 margin-bottom: 0;
3323}
3324.nav-list > li > a,
3325.nav-list .nav-header {
3326 margin-left: -15px;
3327 margin-right: -15px;
3328 text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
3329}
3330.nav-list > li > a {
3331 padding: 3px 15px;
3332}
3333.nav-list > .active > a,
3334.nav-list > .active > a:hover {
3335 color: #ffffff;
3336 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
3337 background-color: #0088cc;
3338}
3339.nav-list [class^="icon-"],
3340.nav-list [class*=" icon-"] {
3341 margin-right: 2px;
3342}
3343.nav-list .divider {
3344 *width: 100%;
3345 height: 1px;
3346 margin: 9px 1px;
3347 *margin: -5px 0 5px;
3348 overflow: hidden; 2207 overflow: hidden;
3349 background-color: #e5e5e5; 2208 top: 8px;
3350 border-bottom: 1px solid #ffffff; 2209 right: 6px;
3351} 2210 margin: 0;
3352.nav-tabs, 2211 border-width: 0 5px;
3353.nav-pills { 2212 padding: 0 3px;
3354 *zoom: 1;
3355}
3356.nav-tabs:before,
3357.nav-pills:before,
3358.nav-tabs:after,
3359.nav-pills:after {
3360 display: table;
3361 content: "";
3362 line-height: 0;
3363}
3364.nav-tabs:after,
3365.nav-pills:after {
3366 clear: both;
3367}
3368.nav-tabs > li,
3369.nav-pills > li {
3370 float: left;
3371}
3372.nav-tabs > li > a,
3373.nav-pills > li > a {
3374 padding-right: 12px;
3375 padding-left: 12px;
3376 margin-right: 2px;
3377 line-height: 14px;
3378}
3379.nav-tabs {
3380 border-bottom: 1px solid #ddd;
3381}
3382.nav-tabs > li {
3383 margin-bottom: -1px;
3384}
3385.nav-tabs > li > a {
3386 padding-top: 8px;
3387 padding-bottom: 8px;
3388 line-height: 20px;
3389 border: 1px solid transparent;
3390 -webkit-border-radius: 4px 4px 0 0;
3391 -moz-border-radius: 4px 4px 0 0;
3392 border-radius: 4px 4px 0 0;
3393}
3394.nav-tabs > li > a:hover {
3395 border-color: #eeeeee #eeeeee #dddddd;
3396}
3397.nav-tabs > .active > a,
3398.nav-tabs > .active > a:hover {
3399 color: #555555;
3400 background-color: #ffffff;
3401 border: 1px solid #ddd;
3402 border-bottom-color: transparent;
3403 cursor: default;
3404}
3405.nav-pills > li > a {
3406 padding-top: 8px;
3407 padding-bottom: 8px;
3408 margin-top: 2px;
3409 margin-bottom: 2px;
3410 -webkit-border-radius: 5px;
3411 -moz-border-radius: 5px;
3412 border-radius: 5px;
3413}
3414.nav-pills > .active > a,
3415.nav-pills > .active > a:hover {
3416 color: #ffffff;
3417 background-color: #0088cc;
3418}
3419.nav-stacked > li {
3420 float: none;
3421}
3422.nav-stacked > li > a {
3423 margin-right: 0;
3424}
3425.nav-tabs.nav-stacked {
3426 border-bottom: 0;
3427}
3428.nav-tabs.nav-stacked > li > a {
3429 border: 1px solid #ddd;
3430 -webkit-border-radius: 0;
3431 -moz-border-radius: 0;
3432 border-radius: 0;
3433}
3434.nav-tabs.nav-stacked > li:first-child > a {
3435 -webkit-border-top-right-radius: 4px;
3436 -moz-border-radius-topright: 4px;
3437 border-top-right-radius: 4px;
3438 -webkit-border-top-left-radius: 4px;
3439 -moz-border-radius-topleft: 4px;
3440 border-top-left-radius: 4px;
3441}
3442.nav-tabs.nav-stacked > li:last-child > a {
3443 -webkit-border-bottom-right-radius: 4px;
3444 -moz-border-radius-bottomright: 4px;
3445 border-bottom-right-radius: 4px;
3446 -webkit-border-bottom-left-radius: 4px;
3447 -moz-border-radius-bottomleft: 4px;
3448 border-bottom-left-radius: 4px;
3449}
3450.nav-tabs.nav-stacked > li > a:hover {
3451 border-color: #ddd;
3452 z-index: 2;
3453}
3454.nav-pills.nav-stacked > li > a {
3455 margin-bottom: 3px;
3456}
3457.nav-pills.nav-stacked > li:last-child > a {
3458 margin-bottom: 1px;
3459}
3460.nav-tabs .dropdown-menu {
3461 -webkit-border-radius: 0 0 6px 6px;
3462 -moz-border-radius: 0 0 6px 6px;
3463 border-radius: 0 0 6px 6px;
3464}
3465.nav-pills .dropdown-menu {
3466 -webkit-border-radius: 6px;
3467 -moz-border-radius: 6px;
3468 border-radius: 6px;
3469}
3470.nav .dropdown-toggle .caret {
3471 border-top-color: #0088cc;
3472 border-bottom-color: #0088cc;
3473 margin-top: 6px;
3474}
3475.nav .dropdown-toggle:hover .caret {
3476 border-top-color: #005580;
3477 border-bottom-color: #005580;
3478}
3479/* move down carets for tabs */
3480.nav-tabs .dropdown-toggle .caret {
3481 margin-top: 8px;
3482}
3483.nav .active .dropdown-toggle .caret {
3484 border-top-color: #fff;
3485 border-bottom-color: #fff;
3486}
3487.nav-tabs .active .dropdown-toggle .caret {
3488 border-top-color: #555555;
3489 border-bottom-color: #555555;
3490}
3491.nav > .dropdown.active > a:hover {
3492 cursor: pointer;
3493}
3494.nav-tabs .open .dropdown-toggle,
3495.nav-pills .open .dropdown-toggle,
3496.nav > li.dropdown.open.active > a:hover {
3497 color: #ffffff;
3498 background-color: #999999;
3499 border-color: #999999;
3500}
3501.nav li.dropdown.open .caret,
3502.nav li.dropdown.open.active .caret,
3503.nav li.dropdown.open a:hover .caret {
3504 border-top-color: #ffffff;
3505 border-bottom-color: #ffffff;
3506 opacity: 1;
3507 filter: alpha(opacity=100);
3508}
3509.tabs-stacked .open > a:hover {
3510 border-color: #999999;
3511}
3512.tabbable {
3513 *zoom: 1;
3514}
3515.tabbable:before,
3516.tabbable:after {
3517 display: table;
3518 content: "";
3519 line-height: 0;
3520}
3521.tabbable:after {
3522 clear: both;
3523}
3524.tab-content {
3525 overflow: auto;
3526}
3527.tabs-below > .nav-tabs,
3528.tabs-right > .nav-tabs,
3529.tabs-left > .nav-tabs {
3530 border-bottom: 0;
3531}
3532.tab-content > .tab-pane,
3533.pill-content > .pill-pane {
3534 display: none;
3535}
3536.tab-content > .active,
3537.pill-content > .active {
3538 display: block;
3539}
3540.tabs-below > .nav-tabs {
3541 border-top: 1px solid #ddd;
3542}
3543.tabs-below > .nav-tabs > li {
3544 margin-top: -1px;
3545 margin-bottom: 0;
3546}
3547.tabs-below > .nav-tabs > li > a {
3548 -webkit-border-radius: 0 0 4px 4px;
3549 -moz-border-radius: 0 0 4px 4px;
3550 border-radius: 0 0 4px 4px;
3551}
3552.tabs-below > .nav-tabs > li > a:hover {
3553 border-bottom-color: transparent;
3554 border-top-color: #ddd;
3555}
3556.tabs-below > .nav-tabs > .active > a,
3557.tabs-below > .nav-tabs > .active > a:hover {
3558 border-color: transparent #ddd #ddd #ddd;
3559}
3560.tabs-left > .nav-tabs > li,
3561.tabs-right > .nav-tabs > li {
3562 float: none;
3563}
3564.tabs-left > .nav-tabs > li > a,
3565.tabs-right > .nav-tabs > li > a {
3566 min-width: 74px;
3567 margin-right: 0;
3568 margin-bottom: 3px;
3569}
3570.tabs-left > .nav-tabs {
3571 float: left;
3572 margin-right: 19px;
3573 border-right: 1px solid #ddd;
3574}
3575.tabs-left > .nav-tabs > li > a {
3576 margin-right: -1px;
3577 -webkit-border-radius: 4px 0 0 4px;
3578 -moz-border-radius: 4px 0 0 4px;
3579 border-radius: 4px 0 0 4px;
3580}
3581.tabs-left > .nav-tabs > li > a:hover {
3582 border-color: #eeeeee #dddddd #eeeeee #eeeeee;
3583}
3584.tabs-left > .nav-tabs .active > a,
3585.tabs-left > .nav-tabs .active > a:hover {
3586 border-color: #ddd transparent #ddd #ddd;
3587 *border-right-color: #ffffff;
3588}
3589.tabs-right > .nav-tabs {
3590 float: right;
3591 margin-left: 19px;
3592 border-left: 1px solid #ddd;
3593}
3594.tabs-right > .nav-tabs > li > a {
3595 margin-left: -1px;
3596 -webkit-border-radius: 0 4px 4px 0;
3597 -moz-border-radius: 0 4px 4px 0;
3598 border-radius: 0 4px 4px 0;
3599}
3600.tabs-right > .nav-tabs > li > a:hover {
3601 border-color: #eeeeee #eeeeee #eeeeee #dddddd;
3602}
3603.tabs-right > .nav-tabs .active > a,
3604.tabs-right > .nav-tabs .active > a:hover {
3605 border-color: #ddd #ddd #ddd transparent;
3606 *border-left-color: #ffffff;
3607}
3608.nav > .disabled > a {
3609 color: #999999;
3610}
3611.nav > .disabled > a:hover {
3612 text-decoration: none;
3613 background-color: transparent;
3614 cursor: default;
3615}
3616.navbar {
3617 overflow: visible;
3618 margin-bottom: 20px;
3619 *position: relative;
3620 *z-index: 2;
3621}
3622.navbar-inner {
3623 min-height: 40px;
3624 padding-left: 20px;
3625 padding-right: 20px;
3626 background-color: #fafafa;
3627 background-image: -moz-linear-gradient(top, #ffffff, #f2f2f2);
3628 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f2f2f2));
3629 background-image: -webkit-linear-gradient(top, #ffffff, #f2f2f2);
3630 background-image: -o-linear-gradient(top, #ffffff, #f2f2f2);
3631 background-image: linear-gradient(to bottom, #ffffff, #f2f2f2);
3632 background-repeat: repeat-x;
3633 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff2f2f2', GradientType=0);
3634 border: 1px solid #d4d4d4;
3635 -webkit-border-radius: 4px;
3636 -moz-border-radius: 4px;
3637 border-radius: 4px;
3638 -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
3639 -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
3640 box-shadow: 0 1px 4px rgba(0, 0, 0, 0.065);
3641 *zoom: 1;
3642}
3643.navbar-inner:before,
3644.navbar-inner:after {
3645 display: table;
3646 content: "";
3647 line-height: 0;
3648}
3649.navbar-inner:after {
3650 clear: both;
3651}
3652.navbar .container {
3653 width: auto; 2213 width: auto;
3654} 2214 height: 30px;
3655.nav-collapse.collapse { 2215 line-height: 30px;
3656 height: auto; 2216 font-family: inherit;
3657 overflow: visible; 2217 font-size: 12px;
3658} 2218 font-weight: bold;
3659.navbar .brand { 2219 color: #FFFFFF;
3660 float: left; 2220 text-shadow: rgba(0, 0, 0, 0.6) 0px -1px 0;
3661 display: block; 2221 text-overflow: ellipsis;
3662 padding: 10px 20px 10px;
3663 margin-left: -20px;
3664 font-size: 20px;
3665 font-weight: 200;
3666 color: #777777;
3667 text-shadow: 0 1px 0 #ffffff;
3668}
3669.navbar .brand:hover {
3670 text-decoration: none; 2222 text-decoration: none;
3671}
3672.navbar-text {
3673 margin-bottom: 0;
3674 line-height: 40px;
3675 color: #777777;
3676}
3677.navbar-link {
3678 color: #777777;
3679}
3680.navbar-link:hover {
3681 color: #333333;
3682}
3683.navbar .divider-vertical {
3684 height: 40px;
3685 margin: 0 9px;
3686 border-left: 1px solid #f2f2f2;
3687 border-right: 1px solid #ffffff;
3688}
3689.navbar .btn,
3690.navbar .btn-group {
3691 margin-top: 5px;
3692}
3693.navbar .btn-group .btn,
3694.navbar .input-prepend .btn,
3695.navbar .input-append .btn {
3696 margin-top: 0;
3697}
3698.navbar-form {
3699 margin-bottom: 0;
3700 *zoom: 1;
3701}
3702.navbar-form:before,
3703.navbar-form:after {
3704 display: table;
3705 content: "";
3706 line-height: 0;
3707}
3708.navbar-form:after {
3709 clear: both;
3710}
3711.navbar-form input,
3712.navbar-form select,
3713.navbar-form .radio,
3714.navbar-form .checkbox {
3715 margin-top: 5px;
3716}
3717.navbar-form input,
3718.navbar-form select,
3719.navbar-form .btn {
3720 display: inline-block;
3721 margin-bottom: 0;
3722}
3723.navbar-form input[type="image"],
3724.navbar-form input[type="checkbox"],
3725.navbar-form input[type="radio"] {
3726 margin-top: 3px;
3727}
3728.navbar-form .input-append,
3729.navbar-form .input-prepend {
3730 margin-top: 5px;
3731 white-space: nowrap; 2223 white-space: nowrap;
2224 background: none;
2225 //-webkit-border-image: url(./images/old/iPhone/toolButton.png) 0 5 0 5;
3732} 2226}
3733.navbar-form .input-append input,
3734.navbar-form .input-prepend input {
3735 margin-top: 0;
3736}
3737.navbar-search {
3738 position: relative;
3739 float: left;
3740 margin-top: 5px;
3741 margin-bottom: 0;
3742}
3743.navbar-search .search-query {
3744 margin-bottom: 0;
3745 padding: 4px 14px;
3746 font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
3747 font-size: 13px;
3748 font-weight: normal;
3749 line-height: 1;
3750 -webkit-border-radius: 15px;
3751 -moz-border-radius: 15px;
3752 border-radius: 15px;
3753}
3754.navbar-static-top {
3755 position: static;
3756 margin-bottom: 0;
3757}
3758.navbar-static-top .navbar-inner {
3759 -webkit-border-radius: 0;
3760 -moz-border-radius: 0;
3761 border-radius: 0;
3762}
3763.navbar-fixed-top,
3764.navbar-fixed-bottom {
3765 position: fixed;
3766 right: 0;
3767 left: 0;
3768 z-index: 1030;
3769 margin-bottom: 0;
3770}
3771.navbar-fixed-top .navbar-inner,
3772.navbar-static-top .navbar-inner {
3773 border-width: 0 0 1px;
3774}
3775.navbar-fixed-bottom .navbar-inner {
3776 border-width: 1px 0 0;
3777}
3778.navbar-fixed-top .navbar-inner,
3779.navbar-fixed-bottom .navbar-inner {
3780 padding-left: 0;
3781 padding-right: 0;
3782 -webkit-border-radius: 0;
3783 -moz-border-radius: 0;
3784 border-radius: 0;
3785}
3786.navbar-static-top .container,
3787.navbar-fixed-top .container,
3788.navbar-fixed-bottom .container {
3789 width: 940px;
3790}
3791.navbar-fixed-top {
3792 top: 0;
3793}
3794.navbar-fixed-top .navbar-inner,
3795.navbar-static-top .navbar-inner {
3796 -webkit-box-shadow: 0 1px 10px rgba(0,0,0,.1);
3797 -moz-box-shadow: 0 1px 10px rgba(0,0,0,.1);
3798 box-shadow: 0 1px 10px rgba(0,0,0,.1);
3799}
3800.navbar-fixed-bottom {
3801 bottom: 0;
3802}
3803.navbar-fixed-bottom .navbar-inner {
3804 -webkit-box-shadow: 0 -1px 10px rgba(0,0,0,.1);
3805 -moz-box-shadow: 0 -1px 10px rgba(0,0,0,.1);
3806 box-shadow: 0 -1px 10px rgba(0,0,0,.1);
3807}
3808.navbar .nav {
3809 position: relative;
3810 left: 0;
3811 display: block;
3812 float: left;
3813 margin: 0 10px 0 0;
3814}
3815.navbar .nav.pull-right {
3816 float: right;
3817 margin-right: 0;
3818}
3819.navbar .nav > li {
3820 float: left;
3821}
3822.navbar .nav > li > a {
3823 float: none;
3824 padding: 10px 15px 10px;
3825 color: #777777;
3826 text-decoration: none;
3827 text-shadow: 0 1px 0 #ffffff;
3828}
3829.navbar .nav .dropdown-toggle .caret {
3830 margin-top: 8px;
3831}
3832.navbar .nav > li > a:focus,
3833.navbar .nav > li > a:hover {
3834 background-color: transparent;
3835 color: #333333;
3836 text-decoration: none;
3837}
3838.navbar .nav > .active > a,
3839.navbar .nav > .active > a:hover,
3840.navbar .nav > .active > a:focus {
3841 color: #555555;
3842 text-decoration: none;
3843 background-color: #e5e5e5;
3844 -webkit-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
3845 -moz-box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
3846 box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
3847}
3848.navbar .btn-navbar {
3849 display: none;
3850 float: right;
3851 padding: 7px 10px;
3852 margin-left: 5px;
3853 margin-right: 5px;
3854 color: #ffffff;
3855 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
3856 background-color: #ededed;
3857 background-image: -moz-linear-gradient(top, #f2f2f2, #e5e5e5);
3858 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f2f2f2), to(#e5e5e5));
3859 background-image: -webkit-linear-gradient(top, #f2f2f2, #e5e5e5);
3860 background-image: -o-linear-gradient(top, #f2f2f2, #e5e5e5);
3861 background-image: linear-gradient(to bottom, #f2f2f2, #e5e5e5);
3862 background-repeat: repeat-x;
3863 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2', endColorstr='#ffe5e5e5', GradientType=0);
3864 border-color: #e5e5e5 #e5e5e5 #bfbfbf;
3865 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3866 *background-color: #e5e5e5;
3867 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
3868 2227
3869 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 2228div.toolbar a#backButton {
3870 -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); 2229 left: 6px;
3871 -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); 2230 right: auto;
3872 box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.075); 2231 padding: 0px;
3873} 2232 max-width: 55px;
3874.navbar .btn-navbar:hover, 2233 border-width: 0 8px 0 14px;
3875.navbar .btn-navbar:active, 2234 //-webkit-border-image: url(./images/old/iPhone/backButton.png) 0 8 0 14;
3876.navbar .btn-navbar.active, 2235 -webkit-border-image: url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAAAeCAIAAAA6iHCJAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtJJREFUeNrEV21P01AYbbtubNExBnXDbYjjZYI4BMdgEANDQoTElw/+Rw0mBs0UiSGaoJFEQEPwjRhFCW/JxrZ2Xdu1fe71bpAhCHzqupPnS5ObPOeec+5zb+lHLxao05HPiwvzr3/++J7N7FFGgaaDLe034+O+wCXyxSKET1u5+Wc98XTK39zeOzjudLmNIoAR2tlaf/Zkqm9gKNI/RBigE9dtb23MJKZj8fvuC16b3WGxsJRxOFfHeQOtH+ZnOI+XRfgEBoLAzz6fjo7ebfD4GYYhMiEdDGRAW6xOt6d7YGzl4xIL/7mgyPL044edkVt19T4EFAJEVQYud+MvOCkHc7MJ3+VrXGOzXrHeZS1s9trjOVj7tiqpONTWBRgD6BVmQFls9iMaSHnx/bu3ffEHgC2gVVqAIojKR3Iw9zLRcjVmtTnA0NydxQDg0IWvq59kYIOeZtWs9gQkagcMcgK/vLjYNXQHcEkas0AcYPdNIPr7Q/0M69B089ofavB5ZVm3OJ2cTwegzAUgxGbSe8tLS52xewjRZGabzAABZt+8mvGHBsiYNF+AAw1cXEBGNUiQqWpAlArM5MSYBXgEOl0NkLcCkxak28MRKbuDMa6KDAwAUnU8HO2Q+N0SJ3OLMCA7V1S9vt7d3tSg5LNV0ACXwOekcGfreVbVVYUqMjOvyPsH71cqkxsZ7NHFJIXBTCMONMAlEryoxAfDucyOmaOpmINyaTowrK23IyDxKbNzUIYoKU3+i37OXpCESvfGCOw11uMMcCkQke4rDlrS1coOSk2VOXftERfKtZsURmLXQUqBVqiUABgrQirc0Xp4Fv4t8kxN8dLkaJQupOVcGnTN0PuQHHlRSG1Eu9tUTLOnxZ5clclsfmK078va7/WN7axomCN2e42Xc/VEIoiiM0KePeM20DTY3M22BZtuhENW1rC/NrI3WVGTmZxSKEr7V4ABAJ+53J1I3nPjAAAAAElFTkSuQmCCCg==) 0 8 0 14;
3877.navbar .btn-navbar.disabled,
3878.navbar .btn-navbar[disabled] {
3879 color: #ffffff;
3880 background-color: #e5e5e5;
3881 *background-color: #d9d9d9;
3882}
3883.navbar .btn-navbar:active,
3884.navbar .btn-navbar.active {
3885 background-color: #cccccc \9;
3886}
3887.navbar .btn-navbar .icon-bar {
3888 display: block;
3889 width: 18px;
3890 height: 2px;
3891 background-color: #f5f5f5;
3892 -webkit-border-radius: 1px;
3893 -moz-border-radius: 1px;
3894 border-radius: 1px;
3895 -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
3896 -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
3897 box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25);
3898}
3899.btn-navbar .icon-bar + .icon-bar {
3900 margin-top: 3px;
3901}
3902.navbar .nav > li > .dropdown-menu:before {
3903 content: '';
3904 display: inline-block;
3905 border-left: 7px solid transparent;
3906 border-right: 7px solid transparent;
3907 border-bottom: 7px solid #ccc;
3908 border-bottom-color: rgba(0, 0, 0, 0.2);
3909 position: absolute;
3910 top: -7px;
3911 left: 9px;
3912}
3913.navbar .nav > li > .dropdown-menu:after {
3914 content: '';
3915 display: inline-block;
3916 border-left: 6px solid transparent;
3917 border-right: 6px solid transparent;
3918 border-bottom: 6px solid #ffffff;
3919 position: absolute;
3920 top: -6px;
3921 left: 10px;
3922}
3923.navbar-fixed-bottom .nav > li > .dropdown-menu:before {
3924 border-top: 7px solid #ccc;
3925 border-top-color: rgba(0, 0, 0, 0.2);
3926 border-bottom: 0;
3927 bottom: -7px;
3928 top: auto;
3929}
3930.navbar-fixed-bottom .nav > li > .dropdown-menu:after {
3931 border-top: 6px solid #ffffff;
3932 border-bottom: 0;
3933 bottom: -6px;
3934 top: auto;
3935}
3936.navbar .nav li.dropdown > a:hover .caret {
3937 border-top-color: #555555;
3938 border-bottom-color: #555555;
3939}
3940.navbar .nav li.dropdown.open > .dropdown-toggle,
3941.navbar .nav li.dropdown.active > .dropdown-toggle,
3942.navbar .nav li.dropdown.open.active > .dropdown-toggle {
3943 background-color: #e5e5e5;
3944 color: #555555;
3945}
3946.navbar .nav li.dropdown > .dropdown-toggle .caret {
3947 border-top-color: #777777;
3948 border-bottom-color: #777777;
3949}
3950.navbar .nav li.dropdown.open > .dropdown-toggle .caret,
3951.navbar .nav li.dropdown.active > .dropdown-toggle .caret,
3952.navbar .nav li.dropdown.open.active > .dropdown-toggle .caret {
3953 border-top-color: #555555;
3954 border-bottom-color: #555555;
3955}
3956.navbar .pull-right > li > .dropdown-menu,
3957.navbar .nav > li > .dropdown-menu.pull-right {
3958 left: auto;
3959 right: 0;
3960} 2236}
3961.navbar .pull-right > li > .dropdown-menu:before,
3962.navbar .nav > li > .dropdown-menu.pull-right:before {
3963 left: auto;
3964 right: 12px;
3965}
3966.navbar .pull-right > li > .dropdown-menu:after,
3967.navbar .nav > li > .dropdown-menu.pull-right:after {
3968 left: auto;
3969 right: 13px;
3970}
3971.navbar .pull-right > li > .dropdown-menu .dropdown-menu,
3972.navbar .nav > li > .dropdown-menu.pull-right .dropdown-menu {
3973 left: auto;
3974 right: 100%;
3975 margin-left: 0;
3976 margin-right: -1px;
3977 -webkit-border-radius: 6px 0 6px 6px;
3978 -moz-border-radius: 6px 0 6px 6px;
3979 border-radius: 6px 0 6px 6px;
3980}
3981.navbar-inverse .navbar-inner {
3982 background-color: #1b1b1b;
3983 background-image: -moz-linear-gradient(top, #222222, #111111);
3984 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#222222), to(#111111));
3985 background-image: -webkit-linear-gradient(top, #222222, #111111);
3986 background-image: -o-linear-gradient(top, #222222, #111111);
3987 background-image: linear-gradient(to bottom, #222222, #111111);
3988 background-repeat: repeat-x;
3989 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff111111', GradientType=0);
3990 border-color: #252525;
3991}
3992.navbar-inverse .brand,
3993.navbar-inverse .nav > li > a {
3994 color: #999999;
3995 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
3996}
3997.navbar-inverse .brand:hover,
3998.navbar-inverse .nav > li > a:hover {
3999 color: #ffffff;
4000}
4001.navbar-inverse .brand {
4002 color: #999999;
4003}
4004.navbar-inverse .navbar-text {
4005 color: #999999;
4006}
4007.navbar-inverse .nav > li > a:focus,
4008.navbar-inverse .nav > li > a:hover {
4009 background-color: transparent;
4010 color: #ffffff;
4011}
4012.navbar-inverse .nav .active > a,
4013.navbar-inverse .nav .active > a:hover,
4014.navbar-inverse .nav .active > a:focus {
4015 color: #ffffff;
4016 background-color: #111111;
4017}
4018.navbar-inverse .navbar-link {
4019 color: #999999;
4020}
4021.navbar-inverse .navbar-link:hover {
4022 color: #ffffff;
4023}
4024.navbar-inverse .divider-vertical {
4025 border-left-color: #111111;
4026 border-right-color: #222222;
4027}
4028.navbar-inverse .nav li.dropdown.open > .dropdown-toggle,
4029.navbar-inverse .nav li.dropdown.active > .dropdown-toggle,
4030.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle {
4031 background-color: #111111;
4032 color: #ffffff;
4033}
4034.navbar-inverse .nav li.dropdown > a:hover .caret {
4035 border-top-color: #ffffff;
4036 border-bottom-color: #ffffff;
4037}
4038.navbar-inverse .nav li.dropdown > .dropdown-toggle .caret {
4039 border-top-color: #999999;
4040 border-bottom-color: #999999;
4041}
4042.navbar-inverse .nav li.dropdown.open > .dropdown-toggle .caret,
4043.navbar-inverse .nav li.dropdown.active > .dropdown-toggle .caret,
4044.navbar-inverse .nav li.dropdown.open.active > .dropdown-toggle .caret {
4045 border-top-color: #ffffff;
4046 border-bottom-color: #ffffff;
4047}
4048.navbar-inverse .navbar-search .search-query {
4049 color: #ffffff;
4050 background-color: #515151;
4051 border-color: #111111;
4052 -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);
4053 -moz-box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);
4054 box-shadow: inset 0 1px 2px rgba(0,0,0,.1), 0 1px 0 rgba(255,255,255,.15);
4055 -webkit-transition: none;
4056 -moz-transition: none;
4057 -o-transition: none;
4058 transition: none;
4059}
4060.navbar-inverse .navbar-search .search-query:-moz-placeholder {
4061 color: #cccccc;
4062}
4063.navbar-inverse .navbar-search .search-query:-ms-input-placeholder {
4064 color: #cccccc;
4065}
4066.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder {
4067 color: #cccccc;
4068}
4069.navbar-inverse .navbar-search .search-query:focus,
4070.navbar-inverse .navbar-search .search-query.focused {
4071 padding: 5px 15px;
4072 color: #333333;
4073 text-shadow: 0 1px 0 #ffffff;
4074 background-color: #ffffff;
4075 border: 0;
4076 -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
4077 -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
4078 box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
4079 outline: 0;
4080}
4081.navbar-inverse .btn-navbar {
4082 color: #ffffff;
4083 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
4084 background-color: #0e0e0e;
4085 background-image: -moz-linear-gradient(top, #151515, #040404);
4086 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#151515), to(#040404));
4087 background-image: -webkit-linear-gradient(top, #151515, #040404);
4088 background-image: -o-linear-gradient(top, #151515, #040404);
4089 background-image: linear-gradient(to bottom, #151515, #040404);
4090 background-repeat: repeat-x;
4091 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515', endColorstr='#ff040404', GradientType=0);
4092 border-color: #040404 #040404 #000000;
4093 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
4094 *background-color: #040404;
4095 /* Darken IE7 buttons by default so they stand out more given they won't have borders */
4096 2237
4097 filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); 2238// -------------------------------------------
4098}
4099.navbar-inverse .btn-navbar:hover,
4100.navbar-inverse .btn-navbar:active,
4101.navbar-inverse .btn-navbar.active,
4102.navbar-inverse .btn-navbar.disabled,
4103.navbar-inverse .btn-navbar[disabled] {
4104 color: #ffffff;
4105 background-color: #040404;
4106 *background-color: #000000;
4107}
4108.navbar-inverse .btn-navbar:active,
4109.navbar-inverse .btn-navbar.active {
4110 background-color: #000000 \9;
4111}
4112.breadcrumb {
4113 padding: 8px 15px;
4114 margin: 0 0 20px;
4115 list-style: none;
4116 background-color: #f5f5f5;
4117 -webkit-border-radius: 4px;
4118 -moz-border-radius: 4px;
4119 border-radius: 4px;
4120}
4121.breadcrumb > li {
4122 display: inline-block;
4123 *display: inline;
4124 /* IE7 inline-block hack */
4125 2239
4126 *zoom: 1; 2240body.iPhone form.loginForm {
4127 text-shadow: 0 1px 0 #ffffff; 2241 min-height: 372px;
4128}
4129.breadcrumb > li > .divider {
4130 padding: 0 5px;
4131 color: #ccc;
4132}
4133.breadcrumb > .active {
4134 color: #999999;
4135}
4136.pagination {
4137 margin: 20px 0;
4138}
4139.pagination ul {
4140 display: inline-block;
4141 *display: inline;
4142 /* IE7 inline-block hack */
4143 2242
4144 *zoom: 1; 2243 box-sizing: border-box;
4145 margin-left: 0; 2244 -moz-box-sizing: border-box;
4146 margin-bottom: 0; 2245 -webkit-box-sizing: border-box;
4147 -webkit-border-radius: 4px; 2246 padding: 10px;
4148 -moz-border-radius: 4px; 2247 //background: #c8c8c8 url(./images/old/iPhone/pinstripes.png);
4149 border-radius: 4px; 2248 background: #c8c8c8 url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAABCAIAAACdaSOZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABdJREFUeNpiPHrmCgMC/GNjYwNSAAEGADdNA3dnzPlQAAAAAElFTkSuQmCCCg==);
4150 -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
4151 -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
4152 box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
4153}
4154.pagination ul > li {
4155 display: inline;
4156}
4157.pagination ul > li > a,
4158.pagination ul > li > span {
4159 float: left;
4160 padding: 4px 12px;
4161 line-height: 20px;
4162 text-decoration: none;
4163 background-color: #ffffff;
4164 border: 1px solid #dddddd;
4165 border-left-width: 0;
4166}
4167.pagination ul > li > a:hover,
4168.pagination ul > .active > a,
4169.pagination ul > .active > span {
4170 background-color: #f5f5f5;
4171}
4172.pagination ul > .active > a,
4173.pagination ul > .active > span {
4174 color: #999999;
4175 cursor: default;
4176}
4177.pagination ul > .disabled > span,
4178.pagination ul > .disabled > a,
4179.pagination ul > .disabled > a:hover {
4180 color: #999999;
4181 background-color: transparent;
4182 cursor: default;
4183}
4184.pagination ul > li:first-child > a,
4185.pagination ul > li:first-child > span {
4186 border-left-width: 1px;
4187 -webkit-border-top-left-radius: 4px;
4188 -moz-border-radius-topleft: 4px;
4189 border-top-left-radius: 4px;
4190 -webkit-border-bottom-left-radius: 4px;
4191 -moz-border-radius-bottomleft: 4px;
4192 border-bottom-left-radius: 4px;
4193}
4194.pagination ul > li:last-child > a,
4195.pagination ul > li:last-child > span {
4196 -webkit-border-top-right-radius: 4px;
4197 -moz-border-radius-topright: 4px;
4198 border-top-right-radius: 4px;
4199 -webkit-border-bottom-right-radius: 4px;
4200 -moz-border-radius-bottomright: 4px;
4201 border-bottom-right-radius: 4px;
4202}
4203.pagination-centered {
4204 text-align: center;
4205} 2249}
4206.pagination-right { 2250
2251fieldset {
2252 position: relative;
2253 margin: 0 0 20px 0;
2254 padding: 0;
2255 background: #FFFFFF;
2256 -webkit-border-radius: 10px;
2257 -moz-border-radius: 10px;
2258 border: 1px solid #999999;
4207 text-align: right; 2259 text-align: right;
2260 font-size: 16px;
4208} 2261}
4209.pagination-large ul > li > a,
4210.pagination-large ul > li > span {
4211 padding: 11px 19px;
4212 font-size: 17.5px;
4213}
4214.pagination-large ul > li:first-child > a,
4215.pagination-large ul > li:first-child > span {
4216 -webkit-border-top-left-radius: 6px;
4217 -moz-border-radius-topleft: 6px;
4218 border-top-left-radius: 6px;
4219 -webkit-border-bottom-left-radius: 6px;
4220 -moz-border-radius-bottomleft: 6px;
4221 border-bottom-left-radius: 6px;
4222}
4223.pagination-large ul > li:last-child > a,
4224.pagination-large ul > li:last-child > span {
4225 -webkit-border-top-right-radius: 6px;
4226 -moz-border-radius-topright: 6px;
4227 border-top-right-radius: 6px;
4228 -webkit-border-bottom-right-radius: 6px;
4229 -moz-border-radius-bottomright: 6px;
4230 border-bottom-right-radius: 6px;
4231}
4232.pagination-mini ul > li:first-child > a,
4233.pagination-small ul > li:first-child > a,
4234.pagination-mini ul > li:first-child > span,
4235.pagination-small ul > li:first-child > span {
4236 -webkit-border-top-left-radius: 3px;
4237 -moz-border-radius-topleft: 3px;
4238 border-top-left-radius: 3px;
4239 -webkit-border-bottom-left-radius: 3px;
4240 -moz-border-radius-bottomleft: 3px;
4241 border-bottom-left-radius: 3px;
4242}
4243.pagination-mini ul > li:last-child > a,
4244.pagination-small ul > li:last-child > a,
4245.pagination-mini ul > li:last-child > span,
4246.pagination-small ul > li:last-child > span {
4247 -webkit-border-top-right-radius: 3px;
4248 -moz-border-radius-topright: 3px;
4249 border-top-right-radius: 3px;
4250 -webkit-border-bottom-right-radius: 3px;
4251 -moz-border-radius-bottomright: 3px;
4252 border-bottom-right-radius: 3px;
4253}
4254.pagination-small ul > li > a,
4255.pagination-small ul > li > span {
4256 padding: 2px 10px;
4257 font-size: 11.9px;
4258}
4259.pagination-mini ul > li > a,
4260.pagination-mini ul > li > span {
4261 padding: 0 6px;
4262 font-size: 10.5px;
4263}
4264.pager {
4265 margin: 20px 0;
4266 list-style: none;
4267 text-align: center;
4268 *zoom: 1;
4269}
4270.pager:before,
4271.pager:after {
4272 display: table;
4273 content: "";
4274 line-height: 0;
4275}
4276.pager:after {
4277 clear: both;
4278}
4279.pager li {
4280 display: inline;
4281}
4282.pager li > a,
4283.pager li > span {
4284 display: inline-block;
4285 padding: 5px 14px;
4286 background-color: #fff;
4287 border: 1px solid #ddd;
4288 -webkit-border-radius: 15px;
4289 -moz-border-radius: 15px;
4290 border-radius: 15px;
4291}
4292.pager li > a:hover {
4293 text-decoration: none;
4294 background-color: #f5f5f5;
4295}
4296.pager .next > a,
4297.pager .next > span {
4298 float: right;
4299}
4300.pager .previous > a,
4301.pager .previous > span {
4302 float: left;
4303}
4304.pager .disabled > a,
4305.pager .disabled > a:hover,
4306.pager .disabled > span {
4307 color: #999999;
4308 background-color: #fff;
4309 cursor: default;
4310}
4311.modal-backdrop {
4312 position: fixed;
4313 top: 0;
4314 right: 0;
4315 bottom: 0;
4316 left: 0;
4317 z-index: 1040;
4318 background-color: #000000;
4319}
4320.modal-backdrop.fade {
4321 opacity: 0;
4322}
4323.modal-backdrop,
4324.modal-backdrop.fade.in {
4325 opacity: 0.8;
4326 filter: alpha(opacity=80);
4327}
4328.modal {
4329 position: fixed;
4330 top: 10%;
4331 left: 50%;
4332 z-index: 1050;
4333 width: 560px;
4334 margin-left: -280px;
4335 background-color: #ffffff;
4336 border: 1px solid #999;
4337 border: 1px solid rgba(0, 0, 0, 0.3);
4338 *border: 1px solid #999;
4339 /* IE6-7 */
4340 2262
4341 -webkit-border-radius: 6px; 2263.row {
4342 -moz-border-radius: 6px;
4343 border-radius: 6px;
4344 -webkit-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
4345 -moz-box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
4346 box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);
4347 -webkit-background-clip: padding-box;
4348 -moz-background-clip: padding-box;
4349 background-clip: padding-box;
4350 outline: none;
4351}
4352.modal.fade {
4353 -webkit-transition: opacity .3s linear, top .3s ease-out;
4354 -moz-transition: opacity .3s linear, top .3s ease-out;
4355 -o-transition: opacity .3s linear, top .3s ease-out;
4356 transition: opacity .3s linear, top .3s ease-out;
4357 top: -25%;
4358}
4359.modal.fade.in {
4360 top: 10%;
4361}
4362.modal-header {
4363 padding: 9px 15px;
4364 border-bottom: 1px solid #eee;
4365}
4366.modal-header .close {
4367 margin-top: 2px;
4368}
4369.modal-header h3 {
4370 margin: 0;
4371 line-height: 30px;
4372}
4373.modal-body {
4374 position: relative; 2264 position: relative;
4375 overflow-y: auto; 2265 min-height: 42px;
4376 max-height: 400px; 2266 border-bottom: 1px solid #999999;
4377 padding: 15px; 2267 -webkit-border-radius: 0;
4378}
4379.modal-form {
4380 margin-bottom: 0;
4381}
4382.modal-footer {
4383 padding: 14px 15px 15px;
4384 margin-bottom: 0;
4385 text-align: right; 2268 text-align: right;
4386 background-color: #f5f5f5;
4387 border-top: 1px solid #ddd;
4388 -webkit-border-radius: 0 0 6px 6px;
4389 -moz-border-radius: 0 0 6px 6px;
4390 border-radius: 0 0 6px 6px;
4391 -webkit-box-shadow: inset 0 1px 0 #ffffff;
4392 -moz-box-shadow: inset 0 1px 0 #ffffff;
4393 box-shadow: inset 0 1px 0 #ffffff;
4394 *zoom: 1;
4395}
4396.modal-footer:before,
4397.modal-footer:after {
4398 display: table;
4399 content: "";
4400 line-height: 0;
4401}
4402.modal-footer:after {
4403 clear: both;
4404}
4405.modal-footer .btn + .btn {
4406 margin-left: 5px;
4407 margin-bottom: 0;
4408}
4409.modal-footer .btn-group .btn + .btn {
4410 margin-left: -1px;
4411}
4412.modal-footer .btn-block + .btn-block {
4413 margin-left: 0;
4414} 2269}
4415.tooltip { 2270
4416 position: absolute; 2271fieldset > .row:last-child {
4417 z-index: 1030; 2272 border-bottom: none !important;
4418 display: block;
4419 visibility: visible;
4420 padding: 5px;
4421 font-size: 11px;
4422 opacity: 0;
4423 filter: alpha(opacity=0);
4424} 2273}
4425.tooltip.in { 2274
4426 opacity: 0.8; 2275
4427 filter: alpha(opacity=80); 2276.row > input:not(input[type|=radio]):not(input[type|=checkbox]),
2277.row > div.fieldValue {
2278 width: 100%;
2279 box-sizing: border-box;
2280 -moz-box-sizing: border-box;
2281 -webkit-box-sizing: border-box;
2282 margin: 0;
2283 border: none;
2284 padding: 0px 10px 0 112px;
2285 height: 42px;
2286 background: none;
2287 font-size: 16px;
2288 font-weight: normal;
2289
2290 color: #666a60;
2291 -webkit-user-select: text;
4428} 2292}
4429.tooltip.top { 2293
4430 margin-top: -3px; 2294.row > div.fieldValue p {
2295 margin: 0px;
2296 text-align: left;
2297 height: 40px;
2298 vertical-align: middle;
2299 line-height: 40px;
4431} 2300}
4432.tooltip.right { 2301
4433 margin-left: 3px; 2302body[orientation="landscape"] .row > div.fieldValue.password {
2303 padding-right: 120px;
2304 //background: url(./images/old/iPhone/password_background.png) no-repeat 105px;
2305 background: url(data:image/png;charset=utf-8;base64,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) no-repeat 105px;
4434} 2306}
4435.tooltip.bottom { 2307
4436 margin-top: 3px; 2308.row > div.fieldValue.password {
2309 color: rgba(255,255,255,0.5);
2310 //background: url(./images/old/iPhone/password_background.png) no-repeat 106px;
2311 background: url(data:image/png;charset=utf-8;base64,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) no-repeat 106px;
4437} 2312}
4438.tooltip.left { 2313
4439 margin-left: -3px; 2314.row > div.fieldValue.password.clear {
2315 color: #666a60;
2316 background: none;
4440} 2317}
4441.tooltip-inner { 2318
4442 max-width: 200px; 2319.row > input[type|=radio], .row > input[type|=checkbox] {
4443 padding: 3px 8px; 2320 margin: 7px 7px 0 0;
4444 color: #ffffff; 2321 height: 25px;
4445 text-align: center; 2322 width: 25px;
4446 text-decoration: none;
4447 background-color: #000000;
4448 -webkit-border-radius: 4px;
4449 -moz-border-radius: 4px;
4450 border-radius: 4px;
4451} 2323}
4452.tooltip-arrow { 2324
2325
2326.row > label {
4453 position: absolute; 2327 position: absolute;
4454 width: 0; 2328 margin: 0 0 0 14px;
4455 height: 0; 2329 line-height: 42px;
4456 border-color: transparent; 2330 font-weight: bold;
4457 border-style: solid; 2331 max-width: 92px;
4458} 2332 overflow: hidden;
4459.tooltip.top .tooltip-arrow { 2333 white-space: nowrap;
4460 bottom: 0;
4461 left: 50%;
4462 margin-left: -5px;
4463 border-width: 5px 5px 0;
4464 border-top-color: #000000;
4465}
4466.tooltip.right .tooltip-arrow {
4467 top: 50%;
4468 left: 0;
4469 margin-top: -5px;
4470 border-width: 5px 5px 5px 0;
4471 border-right-color: #000000;
4472} 2334}
4473.tooltip.left .tooltip-arrow { 2335
4474 top: 50%; 2336body[orientation="landscape"] .row > label {
4475 right: 0; 2337 max-width: 150px;
4476 margin-top: -5px;
4477 border-width: 5px 0 5px 5px;
4478 border-left-color: #000000;
4479} 2338}
4480.tooltip.bottom .tooltip-arrow { 2339
4481 top: 0; 2340body[orientation="landscape"] .row > input:not(input[type|=radio]):not(input[type|=checkbox]) {
4482 left: 50%; 2341 padding-left: 140px;
4483 margin-left: -5px;
4484 border-width: 0 5px 5px;
4485 border-bottom-color: #000000;
4486} 2342}
4487.popover { 2343
2344.row > img.favicon {
4488 position: absolute; 2345 position: absolute;
4489 top: 0; 2346 width: 20px;
4490 left: 0; 2347 height: 20px;
4491 z-index: 1010; 2348 top: 12px;
4492 display: none; 2349 left: 11px;
4493 width: 236px;
4494 padding: 1px;
4495 text-align: left;
4496 background-color: #ffffff;
4497 -webkit-background-clip: padding-box;
4498 -moz-background-clip: padding;
4499 background-clip: padding-box;
4500 border: 1px solid #ccc;
4501 border: 1px solid rgba(0, 0, 0, 0.2);
4502 -webkit-border-radius: 6px;
4503 -moz-border-radius: 6px;
4504 border-radius: 6px;
4505 -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4506 -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4507 box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
4508 white-space: normal;
4509}
4510.popover.top {
4511 margin-top: -10px;
4512}
4513.popover.right {
4514 margin-left: 10px;
4515}
4516.popover.bottom {
4517 margin-top: 10px;
4518}
4519.popover.left {
4520 margin-left: -10px;
4521} 2350}
4522.popover-title { 2351
4523 margin: 0; 2352.row > span {
4524 padding: 8px 14px; 2353 padding: 8px 13px;
4525 font-size: 14px; 2354 text-align: left;
4526 font-weight: normal;
4527 line-height: 18px;
4528 background-color: #f7f7f7;
4529 border-bottom: 1px solid #ebebeb;
4530 -webkit-border-radius: 5px 5px 0 0;
4531 -moz-border-radius: 5px 5px 0 0;
4532 border-radius: 5px 5px 0 0;
4533}
4534.popover-content {
4535 padding: 9px 14px;
4536}
4537.popover .arrow,
4538.popover .arrow:after {
4539 position: absolute;
4540 display: block; 2355 display: block;
4541 width: 0; 2356 color: #666a60;
4542 height: 0; 2357 font-size: 10pt;
4543 border-color: transparent;
4544 border-style: solid;
4545}
4546.popover .arrow {
4547 border-width: 11px;
4548}
4549.popover .arrow:after {
4550 border-width: 10px;
4551 content: "";
4552}
4553.popover.top .arrow {
4554 left: 50%;
4555 margin-left: -11px;
4556 border-bottom-width: 0;
4557 border-top-color: #999;
4558 border-top-color: rgba(0, 0, 0, 0.25);
4559 bottom: -11px;
4560}
4561.popover.top .arrow:after {
4562 bottom: 1px;
4563 margin-left: -10px;
4564 border-bottom-width: 0;
4565 border-top-color: #ffffff;
4566}
4567.popover.right .arrow {
4568 top: 50%;
4569 left: -11px;
4570 margin-top: -11px;
4571 border-left-width: 0;
4572 border-right-color: #999;
4573 border-right-color: rgba(0, 0, 0, 0.25);
4574} 2358}
4575.popover.right .arrow:after { 2359
4576 left: 1px; 2360.row.notes {
4577 bottom: -10px; 2361 -webkit-user-select: text;
4578 border-left-width: 0;
4579 border-right-color: #ffffff;
4580}
4581.popover.bottom .arrow {
4582 left: 50%;
4583 margin-left: -11px;
4584 border-top-width: 0;
4585 border-bottom-color: #999;
4586 border-bottom-color: rgba(0, 0, 0, 0.25);
4587 top: -11px;
4588}
4589.popover.bottom .arrow:after {
4590 top: 1px;
4591 margin-left: -10px;
4592 border-top-width: 0;
4593 border-bottom-color: #ffffff;
4594}
4595.popover.left .arrow {
4596 top: 50%;
4597 right: -11px;
4598 margin-top: -11px;
4599 border-right-width: 0;
4600 border-left-color: #999;
4601 border-left-color: rgba(0, 0, 0, 0.25);
4602}
4603.popover.left .arrow:after {
4604 right: 1px;
4605 border-right-width: 0;
4606 border-left-color: #ffffff;
4607 bottom: -10px;
4608}
4609.thumbnails {
4610 margin-left: -20px;
4611 list-style: none;
4612 *zoom: 1;
4613}
4614.thumbnails:before,
4615.thumbnails:after {
4616 display: table;
4617 content: "";
4618 line-height: 0;
4619}
4620.thumbnails:after {
4621 clear: both;
4622}
4623.row-fluid .thumbnails {
4624 margin-left: 0;
4625}
4626.thumbnails > li {
4627 float: left;
4628 margin-bottom: 20px;
4629 margin-left: 20px;
4630} 2362}
4631.thumbnail { 2363
4632 display: block; 2364// -------------------------------------------
4633 padding: 4px; 2365
4634 line-height: 20px; 2366.whiteButton {
4635 border: 1px solid #ddd;
4636 -webkit-border-radius: 4px;
4637 -moz-border-radius: 4px;
4638 border-radius: 4px;
4639 -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
4640 -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
4641 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.055);
4642 -webkit-transition: all 0.2s ease-in-out;
4643 -moz-transition: all 0.2s ease-in-out;
4644 -o-transition: all 0.2s ease-in-out;
4645 transition: all 0.2s ease-in-out;
4646}
4647a.thumbnail:hover {
4648 border-color: #0088cc;
4649 -webkit-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
4650 -moz-box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
4651 box-shadow: 0 1px 4px rgba(0, 105, 214, 0.25);
4652}
4653.thumbnail > img {
4654 display: block;
4655 max-width: 100%;
4656 margin-left: auto; 2367 margin-left: auto;
4657 margin-right: auto; 2368 margin-right: auto;
4658} 2369 width: 150px;
4659.thumbnail .caption {
4660 padding: 9px;
4661 color: #555555;
4662}
4663.media,
4664.media-body {
4665 overflow: hidden;
4666 *overflow: visible;
4667 zoom: 1;
4668}
4669.media,
4670.media .media {
4671 margin-top: 15px;
4672}
4673.media:first-child {
4674 margin-top: 0;
4675}
4676.media-object {
4677 display: block; 2370 display: block;
4678} 2371 border-width: 0 12px;
4679.media-heading { 2372 padding: 10px;
4680 margin: 0 0 5px; 2373 text-align: center;
4681} 2374 font-size: 20px;
4682.media .pull-left {
4683 margin-right: 10px;
4684}
4685.media .pull-right {
4686 margin-left: 10px;
4687}
4688.media-list {
4689 margin-left: 0;
4690 list-style: none;
4691}
4692.label,
4693.badge {
4694 display: inline-block;
4695 padding: 2px 4px;
4696 font-size: 11.844px;
4697 font-weight: bold; 2375 font-weight: bold;
4698 line-height: 14px; 2376 text-decoration: inherit;
4699 color: #ffffff; 2377 color: inherit;
4700 vertical-align: baseline; 2378
4701 white-space: nowrap; 2379 //-webkit-border-image: url(./images/old/iPhone/whiteButton.png) 0 12 0 12;
4702 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); 2380 -webkit-border-image: url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAB0AAAAuCAQAAAB+dNqHAAAACXBIWXMAAABIAAAASABGyWs+AAAACXZwQWcAAAAdAAAALgChnaVgAAAAAmJLR0QA/4ePzL8AAANhSURBVEjHnZZNaFxVFMd/5747mclMkpmxzYdJtFaJglgFpYSiBAVX7l0UUZGuSkEEu3PtSulCUXFdxYXL7kQQIWD9CsRIqdomGGOaSdJmZjKTeW/eu/e4mKRmrE3n5X83j/ve7/3POfe+d67QrTxP8QLDnMTenkv4kQ2+YZ6d/Y/Kvut+XuZVKtygzVbXC8v0cT+jXORLWneix/mAZZZwKIrSbSAIAcd5kDdZ6kaf4zzfEeLPnHrr+UeOWpMJ9rjYxe7a5ntff/YThhyneJ/Zf9Ep3uEXkhNjX50bHoiStoPE76HWiPQFfcGN+kufLKxheZJ3+aOD5vmIBaLXpz89HSVhzF2Uy2TtGxe/+JksJzjHjgCvMEHz6cnZt7dD5zlAgSlkZy7MrVDgbz43FJimhV46W2vFzutBI3aN8NJZlBbTFAKepZ/o/IszU1Gs95Tz2Uw1nFuiiTE8Rhs9fbIROt/LaISvTaO0mbIM0kTKeefoUSMDCI6SxRCT9d77XlFrCYgQi0PH72vH9CyNMSjO4tGM9do76hXB4y2KU+c8aaR41KJ4SIn6DgqgPq2rggWc+kMEjBUBVDUNKQBiOx+218Pl6tVr+jJhUZx4PYSr4XBSsAKaJH9tpirT7uIoTj3pAna43TJJWtSjYDpxp5bv5OpTb4mOq3IIX0W14ypeUq+rYBH5T9fqbRerWMClrbB4PBgUjZPUuXrUGBW51Yhc71y9LSJi1NgQxVWj3a7aw2gmONSGJtNAxC9v9+56vaoe6aubXEWy4meXe/+VXl42TvqzG4ZFCkRzv/+w3lu436/PX6NNnsUgCctjUUJwnWdGC/ZenpXw47loTRrldu3XwLkSrQmiHbkSP3FkwB4MXpjfWDE3JTfw29ZGAGHjgWJdcDW9XC/0PVS4W47fVj5cuLUmFWlOVlevei8ApVLp8bWclnWU4khpZvTRwaw5VggEINHlZuSv1mcr6zW2ZF22xqLqlWr19uYdGSkeWyn4IY5okX61GBHMrp1HJaYldW4G9Ylm7c/19a4jV6k0+fBmtjbkCwxoDovdQ0lIpEXTNIrbR6OVxWr1joNeJjM+Xhyu2+0+Z6Ocmt17Kj4bBvFgPJTUNlZX4/j/zohAJlMuF4vW5vP7Z3d2kqRW29qKuxr4P1RbNFwZtqq8AAAAAElFTkSuQmCCCg==) 0 12 0 12;
4703 background-color: #999999; 2381 text-shadow: rgba(255, 255, 255, 0.7) 0 1px 0;
4704}
4705.label {
4706 -webkit-border-radius: 3px;
4707 -moz-border-radius: 3px;
4708 border-radius: 3px;
4709}
4710.badge {
4711 padding-left: 9px;
4712 padding-right: 9px;
4713 -webkit-border-radius: 9px;
4714 -moz-border-radius: 9px;
4715 border-radius: 9px;
4716}
4717.label:empty,
4718.badge:empty {
4719 display: none;
4720}
4721a.label:hover,
4722a.badge:hover {
4723 color: #ffffff;
4724 text-decoration: none;
4725 cursor: pointer;
4726}
4727.label-important,
4728.badge-important {
4729 background-color: #b94a48;
4730}
4731.label-important[href],
4732.badge-important[href] {
4733 background-color: #953b39;
4734}
4735.label-warning,
4736.badge-warning {
4737 background-color: #f89406;
4738}
4739.label-warning[href],
4740.badge-warning[href] {
4741 background-color: #c67605;
4742}
4743.label-success,
4744.badge-success {
4745 background-color: #468847;
4746} 2382}
4747.label-success[href], 2383
4748.badge-success[href] { 2384// -------------------------------------------
4749 background-color: #356635; 2385
2386body.iPhone .loginProgressPanel {
2387 min-height: 372px;
2388
2389 box-sizing: border-box;
2390 -moz-box-sizing: border-box;
2391 -webkit-box-sizing: border-box;
2392 padding: 10px;
2393 //background: #c8c8c8 url(./images/old/iPhone/pinstripes.png);
2394 background: #c8c8c8 url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAABCAIAAACdaSOZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABdJREFUeNpiPHrmCgMC/GNjYwNSAAEGADdNA3dnzPlQAAAAAElFTkSuQmCCCg==);
4750} 2395}
4751.label-info, 2396
4752.badge-info { 2397body.iPhone .loadingBar {
4753 background-color: #3a87ad; 2398 margin-left: auto;
2399 margin-right: auto;
2400 margin-top: 60px;
4754} 2401}
4755.label-info[href], 2402
4756.badge-info[href] { 2403div.loadingBar {
4757 background-color: #2d6987; 2404 height: 22px;
2405 width: 214px;
2406 //background: url(./images/old/loading/loadingBar.gif) no-repeat center;
2407 background: url(data:image/gif;charset=utf-8;base64,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) no-repeat center;
4758} 2408}
4759.label-inverse, 2409
4760.badge-inverse { 2410div.loadingBar div.loadingBarProgress {
4761 background-color: #333333; 2411 height: 100%;
2412 width: 0%;
4762} 2413}
4763.label-inverse[href], 2414
4764.badge-inverse[href] { 2415div.loadingBar div.loadingBarProgress div.loadingBarProgress_left {
4765 background-color: #1a1a1a; 2416 height: 100%;
2417 max-width: 8px;
2418 //background: url(./images/old/loading/loadingBarProgress.png) no-repeat 0;
2419 background: url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAANYAAAAWCAYAAAC8C2KaAAAACXBIWXMAAAsSAAALEgHS3X78AAACIklEQVR4Ae3brU7DUBQH8HO6PQAazx4BRUKDwfChQTGFQ4wRFGEERdgQONRQoGEzGFISFI8w/DQSWHsP565r0xY2BiWY/ivW+530l52cdr0jwgEBCPy5AE9aUc7XV0kcl4jniGR20lj0QaAYAtzXWHgmNh7v3HTGXfOXgSWnKy6VqEZMCKZxcmiHgFCfAjrjva6XxfgUWNJc3tVBG9mBqEMAAmMFrrl+10r2pgJLTpYO9dZvNTkAZQhAYAoBNh3evz+KRsaBJccLevtXakYdOEMAAj8UCII6Hzx6dlY5nipBjXwTV1GAAAR+KiA1neHZWcOMJY35FS03bAMOCEAgl0CDG0/dMGP5by6xk2s1TIYABFRAjKufo8AyfoUkftyCDwQg8FsBloqdGmaswMf7qt9CYh4E0gLDWBrdCg7SXahBAAK5BEYZa9AnZmStXJSYDAEVENEtT/GtYNAjxl5AfDEgkFtAuGfXCDPW4N0jh9zci2IBCBRdwCTeY1kL2Z65RdYq+rcC159LQLjPFy9rdo0wY9nS+2uLSk5qI6FtxgEBCEwpEJg4flIvr2SrfEgOYxPulI4YBoFYwEiHL/2jqJ4KLNuowVXT4NqMBuAMAQh8I2DkSoPqLDnqU2DZTqmWF4mcXTxzJalQhkBGQJ+piEyL2/5DpifchJttjOpSLenmXMfVvboVBFmkgnOhBYbBJPqTuv41vx10C22Bi4fAfwt8AJe2flCLvH1PAAAAAElFTkSuQmCCCg==) no-repeat 0;
4766} 2420}
4767.btn .label, 2421
4768.btn .badge { 2422div.loadingBar div.loadingBarProgress div.loadingBarProgress_right {
4769 position: relative; 2423 position: relative;
4770 top: -1px;
4771}
4772.btn-mini .label,
4773.btn-mini .badge {
4774 top: 0;
4775}
4776@-webkit-keyframes progress-bar-stripes {
4777 from {
4778 background-position: 40px 0;
4779 }
4780 to {
4781 background-position: 0 0;
4782 }
4783}
4784@-moz-keyframes progress-bar-stripes {
4785 from {
4786 background-position: 40px 0;
4787 }
4788 to {
4789 background-position: 0 0;
4790 }
4791}
4792@-ms-keyframes progress-bar-stripes {
4793 from {
4794 background-position: 40px 0;
4795 }
4796 to {
4797 background-position: 0 0;
4798 }
4799}
4800@-o-keyframes progress-bar-stripes {
4801 from {
4802 background-position: 0 0;
4803 }
4804 to {
4805 background-position: 40px 0;
4806 }
4807}
4808@keyframes progress-bar-stripes {
4809 from {
4810 background-position: 40px 0;
4811 }
4812 to {
4813 background-position: 0 0;
4814 }
4815}
4816.progress {
4817 overflow: hidden;
4818 height: 20px;
4819 margin-bottom: 20px;
4820 background-color: #f7f7f7;
4821 background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9);
4822 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));
4823 background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9);
4824 background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9);
4825 background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9);
4826 background-repeat: repeat-x;
4827 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);
4828 -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
4829 -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
4830 box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
4831 -webkit-border-radius: 4px;
4832 -moz-border-radius: 4px;
4833 border-radius: 4px;
4834}
4835.progress .bar {
4836 width: 0%;
4837 height: 100%; 2424 height: 100%;
4838 color: #ffffff; 2425 margin-left: 8px;
4839 float: left; 2426 //background: url(./images/old/loading/loadingBarProgress.png) no-repeat right;
4840 font-size: 12px; 2427 background: url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAANYAAAAWCAYAAAC8C2KaAAAACXBIWXMAAAsSAAALEgHS3X78AAACIklEQVR4Ae3brU7DUBQH8HO6PQAazx4BRUKDwfChQTGFQ4wRFGEERdgQONRQoGEzGFISFI8w/DQSWHsP565r0xY2BiWY/ivW+530l52cdr0jwgEBCPy5AE9aUc7XV0kcl4jniGR20lj0QaAYAtzXWHgmNh7v3HTGXfOXgSWnKy6VqEZMCKZxcmiHgFCfAjrjva6XxfgUWNJc3tVBG9mBqEMAAmMFrrl+10r2pgJLTpYO9dZvNTkAZQhAYAoBNh3evz+KRsaBJccLevtXakYdOEMAAj8UCII6Hzx6dlY5nipBjXwTV1GAAAR+KiA1neHZWcOMJY35FS03bAMOCEAgl0CDG0/dMGP5by6xk2s1TIYABFRAjKufo8AyfoUkftyCDwQg8FsBloqdGmaswMf7qt9CYh4E0gLDWBrdCg7SXahBAAK5BEYZa9AnZmStXJSYDAEVENEtT/GtYNAjxl5AfDEgkFtAuGfXCDPW4N0jh9zci2IBCBRdwCTeY1kL2Z65RdYq+rcC159LQLjPFy9rdo0wY9nS+2uLSk5qI6FtxgEBCEwpEJg4flIvr2SrfEgOYxPulI4YBoFYwEiHL/2jqJ4KLNuowVXT4NqMBuAMAQh8I2DkSoPqLDnqU2DZTqmWF4mcXTxzJalQhkBGQJ+piEyL2/5DpifchJttjOpSLenmXMfVvboVBFmkgnOhBYbBJPqTuv41vx10C22Bi4fAfwt8AJe2flCLvH1PAAAAAElFTkSuQmCCCg==) no-repeat right;
4841 text-align: center; 2428 top: -22px;
4842 text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
4843 background-color: #0e90d2;
4844 background-image: -moz-linear-gradient(top, #149bdf, #0480be);
4845 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));
4846 background-image: -webkit-linear-gradient(top, #149bdf, #0480be);
4847 background-image: -o-linear-gradient(top, #149bdf, #0480be);
4848 background-image: linear-gradient(to bottom, #149bdf, #0480be);
4849 background-repeat: repeat-x;
4850 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);
4851 -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
4852 -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
4853 box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
4854 -webkit-box-sizing: border-box;
4855 -moz-box-sizing: border-box;
4856 box-sizing: border-box;
4857 -webkit-transition: width 0.6s ease;
4858 -moz-transition: width 0.6s ease;
4859 -o-transition: width 0.6s ease;
4860 transition: width 0.6s ease;
4861}
4862.progress .bar + .bar {
4863 -webkit-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
4864 -moz-box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
4865 box-shadow: inset 1px 0 0 rgba(0,0,0,.15), inset 0 -1px 0 rgba(0,0,0,.15);
4866}
4867.progress-striped .bar {
4868 background-color: #149bdf;
4869 background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4870 background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4871 background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4872 background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4873 background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4874 -webkit-background-size: 40px 40px;
4875 -moz-background-size: 40px 40px;
4876 -o-background-size: 40px 40px;
4877 background-size: 40px 40px;
4878}
4879.progress.active .bar {
4880 -webkit-animation: progress-bar-stripes 2s linear infinite;
4881 -moz-animation: progress-bar-stripes 2s linear infinite;
4882 -ms-animation: progress-bar-stripes 2s linear infinite;
4883 -o-animation: progress-bar-stripes 2s linear infinite;
4884 animation: progress-bar-stripes 2s linear infinite;
4885}
4886.progress-danger .bar,
4887.progress .bar-danger {
4888 background-color: #dd514c;
4889 background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
4890 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));
4891 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
4892 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
4893 background-image: linear-gradient(to bottom, #ee5f5b, #c43c35);
4894 background-repeat: repeat-x;
4895 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);
4896}
4897.progress-danger.progress-striped .bar,
4898.progress-striped .bar-danger {
4899 background-color: #ee5f5b;
4900 background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4901 background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4902 background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4903 background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4904 background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4905}
4906.progress-success .bar,
4907.progress .bar-success {
4908 background-color: #5eb95e;
4909 background-image: -moz-linear-gradient(top, #62c462, #57a957);
4910 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));
4911 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
4912 background-image: -o-linear-gradient(top, #62c462, #57a957);
4913 background-image: linear-gradient(to bottom, #62c462, #57a957);
4914 background-repeat: repeat-x;
4915 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);
4916}
4917.progress-success.progress-striped .bar,
4918.progress-striped .bar-success {
4919 background-color: #62c462;
4920 background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4921 background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4922 background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4923 background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4924 background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4925}
4926.progress-info .bar,
4927.progress .bar-info {
4928 background-color: #4bb1cf;
4929 background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
4930 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));
4931 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
4932 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
4933 background-image: linear-gradient(to bottom, #5bc0de, #339bb9);
4934 background-repeat: repeat-x;
4935 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);
4936}
4937.progress-info.progress-striped .bar,
4938.progress-striped .bar-info {
4939 background-color: #5bc0de;
4940 background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4941 background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4942 background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4943 background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4944 background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4945}
4946.progress-warning .bar,
4947.progress .bar-warning {
4948 background-color: #faa732;
4949 background-image: -moz-linear-gradient(top, #fbb450, #f89406);
4950 background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fbb450), to(#f89406));
4951 background-image: -webkit-linear-gradient(top, #fbb450, #f89406);
4952 background-image: -o-linear-gradient(top, #fbb450, #f89406);
4953 background-image: linear-gradient(to bottom, #fbb450, #f89406);
4954 background-repeat: repeat-x;
4955 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450', endColorstr='#fff89406', GradientType=0);
4956}
4957.progress-warning.progress-striped .bar,
4958.progress-striped .bar-warning {
4959 background-color: #fbb450;
4960 background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
4961 background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4962 background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4963 background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4964 background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
4965}
4966.accordion {
4967 margin-bottom: 20px;
4968}
4969.accordion-group {
4970 margin-bottom: 2px;
4971 border: 1px solid #e5e5e5;
4972 -webkit-border-radius: 4px;
4973 -moz-border-radius: 4px;
4974 border-radius: 4px;
4975} 2429}
4976.accordion-heading { 2430
4977 border-bottom: 0; 2431// -------------------------------------------
2432
2433body.iPhone .loginErrorPanel {
2434 position: absolute;
2435 min-height: 372px;
2436 box-sizing: border-box;
2437 -moz-box-sizing: border-box;
2438 -webkit-box-sizing: border-box;
2439 padding: 10px;
2440 //background: #c8c8c8 url(./images/old/iPhone/pinstripes.png);
2441 background: #c8c8c8 url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAABCAIAAACdaSOZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABdJREFUeNpiPHrmCgMC/GNjYwNSAAEGADdNA3dnzPlQAAAAAElFTkSuQmCCCg==);
4978} 2442}
4979.accordion-heading .accordion-toggle { 2443
4980 display: block; 2444body.iPhone .loginErrorPanel h2 {
4981 padding: 8px 15px; 2445 text-align: center;
2446 color: red;
2447 margin-top: 40px;
4982} 2448}
4983.accordion-toggle { 2449
4984 cursor: pointer; 2450// -------------------------------------------
2451
2452form.cardListSearchForm {
2453 box-sizing: border-box;
2454 -moz-box-sizing: border-box;
2455 -webkit-box-sizing: border-box;
2456 border-bottom: 1px solid #2d3642;
2457 border-top: 1px solid #6d84a2;
2458 padding: 6px;
2459 height: 45px;
2460 // background: url(./images/old/iPhone/toolbar.png) #6d84a2 repeat-x;
2461 background: url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAArCAIAAAA2QHWOAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAE1JREFUCNddjDEOgEAQAgn//5qltYWFnb1GB4vdSy4WBAYStKyb9+O0FJMYyjMyMWCC35lJM71r6vF1P07/lFSfPx6ZxNLcy1HtihzpA/RWcOj0zlDhAAAAAElFTkSuQmCCCg==) #6d84a2 repeat-x;
2462 margin: 0px;
4985} 2463}
4986.accordion-inner { 2464
4987 padding: 9px 15px; 2465form.cardListSearchForm input {
4988 border-top: 1px solid #e5e5e5; 2466 margin: 7px;
2467 -webkit-appearance: searchfield;
2468 width: 200px;
4989} 2469}
4990.carousel { 2470
4991 position: relative; 2471ul.cardListPanel {
4992 margin-bottom: 20px; 2472 margin: 0px;
4993 line-height: 1; 2473 padding: 0px;
2474 list-style-type: none;
2475 min-height: 372px;
4994} 2476}
4995.carousel-inner { 2477
4996 overflow: hidden; 2478li.cardListItem {
4997 width: 100%; 2479 height: 43px;
4998 position: relative; 2480 border-bottom: 1px solid #cccccc;
2481 //background: url(./images/old/iPhone/listArrow.png) no-repeat right center;
2482 background: url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAYAAAB4d5a9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKVJREFUeNpi/P//PwOtARMDHcDwsYQFRJSXl8P4dVC6CZvizs5O8i1BsqARid9Ei+BiQ2KDLKumhSU1QNyKxG+hlkXoEQ+yqAPNogpapK5KNIvaKbUIVxKeAsTvkPg5QCxETUukgfgAkqFPgdgBzVKKLIFZoIJmwR1qBRdNLEC2BJQpV9LCAmRL/gBxAtRwqlqAXqzcgRrOQE0LQIBxtNIiBQAEGAA7xCa2yF9zEgAAAABJRU5ErkJgggo=) no-repeat right center;
2483
4999} 2484}
5000.carousel-inner > .item { 2485
5001 display: none; 2486li.cardListItem a {
5002 position: relative; 2487 position: relative;
5003 -webkit-transition: 0.6s ease-in-out left; 2488 top: -22px;
5004 -moz-transition: 0.6s ease-in-out left; 2489 left: 40px;
5005 -o-transition: 0.6s ease-in-out left;
5006 transition: 0.6s ease-in-out left;
5007}
5008.carousel-inner > .item > img {
5009 display: block; 2490 display: block;
5010 line-height: 1; 2491 white-space: nowrap;
5011} 2492 overflow: hidden;
5012.carousel-inner > .active,
5013.carousel-inner > .next,
5014.carousel-inner > .prev {
5015 display: block;
5016}
5017.carousel-inner > .active {
5018 left: 0;
5019}
5020.carousel-inner > .next,
5021.carousel-inner > .prev {
5022 position: absolute;
5023 top: 0;
5024 width: 100%;
5025}
5026.carousel-inner > .next {
5027 left: 100%;
5028}
5029.carousel-inner > .prev {
5030 left: -100%;
5031} 2493}
5032.carousel-inner > .next.left, 2494
5033.carousel-inner > .prev.right { 2495body[orientation="portrait"] li.cardListItem a {
5034 left: 0; 2496 max-width: 250px;
5035} 2497}
5036.carousel-inner > .active.left { 2498
5037 left: -100%; 2499body[orientation="landscape"] li.cardListItem a {
2500 max-width: 400px;
5038} 2501}
5039.carousel-inner > .active.right { 2502
5040 left: 100%; 2503li.cardListItem img {
2504 height: 20px;
2505 width: 20px;
2506 padding: 12px 10px 0px 10px;
5041} 2507}
5042.carousel-control { 2508
5043 position: absolute; 2509li.cardListItem a {
5044 top: 40%;
5045 left: 15px;
5046 width: 40px;
5047 height: 40px;
5048 margin-top: -20px;
5049 font-size: 60px;
5050 font-weight: 100;
5051 line-height: 30px;
5052 color: #ffffff;
5053 text-align: center;
5054 background: #222222;
5055 border: 3px solid #ffffff;
5056 -webkit-border-radius: 23px;
5057 -moz-border-radius: 23px;
5058 border-radius: 23px;
5059 opacity: 0.5;
5060 filter: alpha(opacity=50);
5061}
5062.carousel-control.right {
5063 left: auto;
5064 right: 15px;
5065}
5066.carousel-control:hover {
5067 color: #ffffff;
5068 text-decoration: none; 2510 text-decoration: none;
5069 opacity: 0.9; 2511 color: black;
5070 filter: alpha(opacity=90); 2512 font-weight: bold;
2513 font-size: 14pt;
2514 vertical-align: 3px;
5071} 2515}
5072.carousel-caption { 2516
2517
2518div.cardDetailPanel {
5073 position: absolute; 2519 position: absolute;
5074 left: 0; 2520 top: 45px;
5075 right: 0; 2521 min-height: 372px;
5076 bottom: 0; 2522
5077 padding: 15px;
5078 background: #333333;
5079 background: rgba(0, 0, 0, 0.75);
5080}
5081.carousel-caption h4,
5082.carousel-caption p {
5083 color: #ffffff;
5084 line-height: 20px;
5085}
5086.carousel-caption h4 {
5087 margin: 0 0 5px;
5088}
5089.carousel-caption p {
5090 margin-bottom: 0;
5091}
5092.hero-unit {
5093 padding: 60px;
5094 margin-bottom: 30px;
5095 font-size: 18px;
5096 font-weight: 200;
5097 line-height: 30px;
5098 color: inherit;
5099 background-color: #eeeeee;
5100 -webkit-border-radius: 6px;
5101 -moz-border-radius: 6px;
5102 border-radius: 6px;
5103}
5104.hero-unit h1 {
5105 margin-bottom: 0;
5106 font-size: 60px;
5107 line-height: 1;
5108 color: inherit;
5109 letter-spacing: -1px;
5110}
5111.hero-unit li {
5112 line-height: 30px;
5113}
5114.pull-right {
5115 float: right;
5116}
5117.pull-left {
5118 float: left;
5119}
5120.hide {
5121 display: none;
5122}
5123.show {
5124 display: block;
5125}
5126.invisible {
5127 visibility: hidden;
5128}
5129.affix {
5130 position: fixed;
5131}
5132.hidden {
5133 display: none;
5134 visibility: hidden;
5135}
5136.visible-phone {
5137 display: none !important;
5138}
5139.visible-tablet {
5140 display: none !important;
5141}
5142.hidden-desktop {
5143 display: none !important;
5144}
5145.visible-desktop {
5146 display: inherit !important;
5147}
5148@media (min-width: 768px) and (max-width: 979px) {
5149 .hidden-desktop {
5150 display: inherit !important;
5151 }
5152 .visible-desktop {
5153 display: none !important ;
5154 }
5155 .visible-tablet {
5156 display: inherit !important;
5157 }
5158 .hidden-tablet {
5159 display: none !important;
5160 }
5161}
5162@media (max-width: 767px) {
5163 .hidden-desktop {
5164 display: inherit !important;
5165 }
5166 .visible-desktop {
5167 display: none !important;
5168 }
5169 .visible-phone {
5170 display: inherit !important;
5171 }
5172 .hidden-phone {
5173 display: none !important;
5174 }
5175}
5176@media (min-width: 1200px) {
5177 .row {
5178 margin-left: -30px;
5179 *zoom: 1;
5180 }
5181 .row:before,
5182 .row:after {
5183 display: table;
5184 content: "";
5185 line-height: 0;
5186 }
5187 .row:after {
5188 clear: both;
5189 }
5190 [class*="span"] {
5191 float: left;
5192 min-height: 1px;
5193 margin-left: 30px;
5194 }
5195 .container,
5196 .navbar-static-top .container,
5197 .navbar-fixed-top .container,
5198 .navbar-fixed-bottom .container {
5199 width: 1170px;
5200 }
5201 .span12 {
5202 width: 1170px;
5203 }
5204 .span11 {
5205 width: 1070px;
5206 }
5207 .span10 {
5208 width: 970px;
5209 }
5210 .span9 {
5211 width: 870px;
5212 }
5213 .span8 {
5214 width: 770px;
5215 }
5216 .span7 {
5217 width: 670px;
5218 }
5219 .span6 {
5220 width: 570px;
5221 }
5222 .span5 {
5223 width: 470px;
5224 }
5225 .span4 {
5226 width: 370px;
5227 }
5228 .span3 {
5229 width: 270px;
5230 }
5231 .span2 {
5232 width: 170px;
5233 }
5234 .span1 {
5235 width: 70px;
5236 }
5237 .offset12 {
5238 margin-left: 1230px;
5239 }
5240 .offset11 {
5241 margin-left: 1130px;
5242 }
5243 .offset10 {
5244 margin-left: 1030px;
5245 }
5246 .offset9 {
5247 margin-left: 930px;
5248 }
5249 .offset8 {
5250 margin-left: 830px;
5251 }
5252 .offset7 {
5253 margin-left: 730px;
5254 }
5255 .offset6 {
5256 margin-left: 630px;
5257 }
5258 .offset5 {
5259 margin-left: 530px;
5260 }
5261 .offset4 {
5262 margin-left: 430px;
5263 }
5264 .offset3 {
5265 margin-left: 330px;
5266 }
5267 .offset2 {
5268 margin-left: 230px;
5269 }
5270 .offset1 {
5271 margin-left: 130px;
5272 }
5273 .row-fluid {
5274 width: 100%;
5275 *zoom: 1;
5276 }
5277 .row-fluid:before,
5278 .row-fluid:after {
5279 display: table;
5280 content: "";
5281 line-height: 0;
5282 }
5283 .row-fluid:after {
5284 clear: both;
5285 }
5286 .row-fluid [class*="span"] {
5287 display: block;
5288 width: 100%;
5289 min-height: 30px;
5290 -webkit-box-sizing: border-box;
5291 -moz-box-sizing: border-box;
5292 box-sizing: border-box; 2523 box-sizing: border-box;
5293 float: left;
5294 margin-left: 2.564102564102564%;
5295 *margin-left: 2.5109110747408616%;
5296 }
5297 .row-fluid [class*="span"]:first-child {
5298 margin-left: 0;
5299 }
5300 .row-fluid .controls-row [class*="span"] + [class*="span"] {
5301 margin-left: 2.564102564102564%;
5302 }
5303 .row-fluid .span12 {
5304 width: 100%;
5305 *width: 99.94680851063829%;
5306 }
5307 .row-fluid .span11 {
5308 width: 91.45299145299145%;
5309 *width: 91.39979996362975%;
5310 }
5311 .row-fluid .span10 {
5312 width: 82.90598290598291%;
5313 *width: 82.8527914166212%;
5314 }
5315 .row-fluid .span9 {
5316 width: 74.35897435897436%;
5317 *width: 74.30578286961266%;
5318 }
5319 .row-fluid .span8 {
5320 width: 65.81196581196582%;
5321 *width: 65.75877432260411%;
5322 }
5323 .row-fluid .span7 {
5324 width: 57.26495726495726%;
5325 *width: 57.21176577559556%;
5326 }
5327 .row-fluid .span6 {
5328 width: 48.717948717948715%;
5329 *width: 48.664757228587014%;
5330 }
5331 .row-fluid .span5 {
5332 width: 40.17094017094017%;
5333 *width: 40.11774868157847%;
5334 }
5335 .row-fluid .span4 {
5336 width: 31.623931623931625%;
5337 *width: 31.570740134569924%;
5338 }
5339 .row-fluid .span3 {
5340 width: 23.076923076923077%;
5341 *width: 23.023731587561375%;
5342 }
5343 .row-fluid .span2 {
5344 width: 14.52991452991453%;
5345 *width: 14.476723040552828%;
5346 }
5347 .row-fluid .span1 {
5348 width: 5.982905982905983%;
5349 *width: 5.929714493544281%;
5350 }
5351 .row-fluid .offset12 {
5352 margin-left: 105.12820512820512%;
5353 *margin-left: 105.02182214948171%;
5354 }
5355 .row-fluid .offset12:first-child {
5356 margin-left: 102.56410256410257%;
5357 *margin-left: 102.45771958537915%;
5358 }
5359 .row-fluid .offset11 {
5360 margin-left: 96.58119658119658%;
5361 *margin-left: 96.47481360247316%;
5362 }
5363 .row-fluid .offset11:first-child {
5364 margin-left: 94.01709401709402%;
5365 *margin-left: 93.91071103837061%;
5366 }
5367 .row-fluid .offset10 {
5368 margin-left: 88.03418803418803%;
5369 *margin-left: 87.92780505546462%;
5370 }
5371 .row-fluid .offset10:first-child {
5372 margin-left: 85.47008547008548%;
5373 *margin-left: 85.36370249136206%;
5374 }
5375 .row-fluid .offset9 {
5376 margin-left: 79.48717948717949%;
5377 *margin-left: 79.38079650845607%;
5378 }
5379 .row-fluid .offset9:first-child {
5380 margin-left: 76.92307692307693%;
5381 *margin-left: 76.81669394435352%;
5382 }
5383 .row-fluid .offset8 {
5384 margin-left: 70.94017094017094%;
5385 *margin-left: 70.83378796144753%;
5386 }
5387 .row-fluid .offset8:first-child {
5388 margin-left: 68.37606837606839%;
5389 *margin-left: 68.26968539734497%;
5390 }
5391 .row-fluid .offset7 {
5392 margin-left: 62.393162393162385%;
5393 *margin-left: 62.28677941443899%;
5394 }
5395 .row-fluid .offset7:first-child {
5396 margin-left: 59.82905982905982%;
5397 *margin-left: 59.72267685033642%;
5398 }
5399 .row-fluid .offset6 {
5400 margin-left: 53.84615384615384%;
5401 *margin-left: 53.739770867430444%;
5402 }
5403 .row-fluid .offset6:first-child {
5404 margin-left: 51.28205128205128%;
5405 *margin-left: 51.175668303327875%;
5406 }
5407 .row-fluid .offset5 {
5408 margin-left: 45.299145299145295%;
5409 *margin-left: 45.1927623204219%;
5410 }
5411 .row-fluid .offset5:first-child {
5412 margin-left: 42.73504273504273%;
5413 *margin-left: 42.62865975631933%;
5414 }
5415 .row-fluid .offset4 {
5416 margin-left: 36.75213675213675%;
5417 *margin-left: 36.645753773413354%;
5418 }
5419 .row-fluid .offset4:first-child {
5420 margin-left: 34.18803418803419%;
5421 *margin-left: 34.081651209310785%;
5422 }
5423 .row-fluid .offset3 {
5424 margin-left: 28.205128205128204%;
5425 *margin-left: 28.0987452264048%;
5426 }
5427 .row-fluid .offset3:first-child {
5428 margin-left: 25.641025641025642%;
5429 *margin-left: 25.53464266230224%;
5430 }
5431 .row-fluid .offset2 {
5432 margin-left: 19.65811965811966%;
5433 *margin-left: 19.551736679396257%;
5434 }
5435 .row-fluid .offset2:first-child {
5436 margin-left: 17.094017094017094%;
5437 *margin-left: 16.98763411529369%;
5438 }
5439 .row-fluid .offset1 {
5440 margin-left: 11.11111111111111%;
5441 *margin-left: 11.004728132387708%;
5442 }
5443 .row-fluid .offset1:first-child {
5444 margin-left: 8.547008547008547%;
5445 *margin-left: 8.440625568285142%;
5446 }
5447 input,
5448 textarea,
5449 .uneditable-input {
5450 margin-left: 0;
5451 }
5452 .controls-row [class*="span"] + [class*="span"] {
5453 margin-left: 30px;
5454 }
5455 input.span12, textarea.span12, .uneditable-input.span12 {
5456 width: 1156px;
5457 }
5458 input.span11, textarea.span11, .uneditable-input.span11 {
5459 width: 1056px;
5460 }
5461 input.span10, textarea.span10, .uneditable-input.span10 {
5462 width: 956px;
5463 }
5464 input.span9, textarea.span9, .uneditable-input.span9 {
5465 width: 856px;
5466 }
5467 input.span8, textarea.span8, .uneditable-input.span8 {
5468 width: 756px;
5469 }
5470 input.span7, textarea.span7, .uneditable-input.span7 {
5471 width: 656px;
5472 }
5473 input.span6, textarea.span6, .uneditable-input.span6 {
5474 width: 556px;
5475 }
5476 input.span5, textarea.span5, .uneditable-input.span5 {
5477 width: 456px;
5478 }
5479 input.span4, textarea.span4, .uneditable-input.span4 {
5480 width: 356px;
5481 }
5482 input.span3, textarea.span3, .uneditable-input.span3 {
5483 width: 256px;
5484 }
5485 input.span2, textarea.span2, .uneditable-input.span2 {
5486 width: 156px;
5487 }
5488 input.span1, textarea.span1, .uneditable-input.span1 {
5489 width: 56px;
5490 }
5491 .thumbnails {
5492 margin-left: -30px;
5493 }
5494 .thumbnails > li {
5495 margin-left: 30px;
5496 }
5497 .row-fluid .thumbnails {
5498 margin-left: 0;
5499 }
5500}
5501@media (min-width: 768px) and (max-width: 979px) {
5502 .row {
5503 margin-left: -20px;
5504 *zoom: 1;
5505 }
5506 .row:before,
5507 .row:after {
5508 display: table;
5509 content: "";
5510 line-height: 0;
5511 }
5512 .row:after {
5513 clear: both;
5514 }
5515 [class*="span"] {
5516 float: left;
5517 min-height: 1px;
5518 margin-left: 20px;
5519 }
5520 .container,
5521 .navbar-static-top .container,
5522 .navbar-fixed-top .container,
5523 .navbar-fixed-bottom .container {
5524 width: 724px;
5525 }
5526 .span12 {
5527 width: 724px;
5528 }
5529 .span11 {
5530 width: 662px;
5531 }
5532 .span10 {
5533 width: 600px;
5534 }
5535 .span9 {
5536 width: 538px;
5537 }
5538 .span8 {
5539 width: 476px;
5540 }
5541 .span7 {
5542 width: 414px;
5543 }
5544 .span6 {
5545 width: 352px;
5546 }
5547 .span5 {
5548 width: 290px;
5549 }
5550 .span4 {
5551 width: 228px;
5552 }
5553 .span3 {
5554 width: 166px;
5555 }
5556 .span2 {
5557 width: 104px;
5558 }
5559 .span1 {
5560 width: 42px;
5561 }
5562 .offset12 {
5563 margin-left: 764px;
5564 }
5565 .offset11 {
5566 margin-left: 702px;
5567 }
5568 .offset10 {
5569 margin-left: 640px;
5570 }
5571 .offset9 {
5572 margin-left: 578px;
5573 }
5574 .offset8 {
5575 margin-left: 516px;
5576 }
5577 .offset7 {
5578 margin-left: 454px;
5579 }
5580 .offset6 {
5581 margin-left: 392px;
5582 }
5583 .offset5 {
5584 margin-left: 330px;
5585 }
5586 .offset4 {
5587 margin-left: 268px;
5588 }
5589 .offset3 {
5590 margin-left: 206px;
5591 }
5592 .offset2 {
5593 margin-left: 144px;
5594 }
5595 .offset1 {
5596 margin-left: 82px;
5597 }
5598 .row-fluid {
5599 width: 100%;
5600 *zoom: 1;
5601 }
5602 .row-fluid:before,
5603 .row-fluid:after {
5604 display: table;
5605 content: "";
5606 line-height: 0;
5607 }
5608 .row-fluid:after {
5609 clear: both;
5610 }
5611 .row-fluid [class*="span"] {
5612 display: block;
5613 width: 100%;
5614 min-height: 30px;
5615 -webkit-box-sizing: border-box;
5616 -moz-box-sizing: border-box; 2524 -moz-box-sizing: border-box;
5617 box-sizing: border-box;
5618 float: left;
5619 margin-left: 2.7624309392265194%;
5620 *margin-left: 2.709239449864817%;
5621 }
5622 .row-fluid [class*="span"]:first-child {
5623 margin-left: 0;
5624 }
5625 .row-fluid .controls-row [class*="span"] + [class*="span"] {
5626 margin-left: 2.7624309392265194%;
5627 }
5628 .row-fluid .span12 {
5629 width: 100%;
5630 *width: 99.94680851063829%;
5631 }
5632 .row-fluid .span11 {
5633 width: 91.43646408839778%;
5634 *width: 91.38327259903608%;
5635 }
5636 .row-fluid .span10 {
5637 width: 82.87292817679558%;
5638 *width: 82.81973668743387%;
5639 }
5640 .row-fluid .span9 {
5641 width: 74.30939226519337%;
5642 *width: 74.25620077583166%;
5643 }
5644 .row-fluid .span8 {
5645 width: 65.74585635359117%;
5646 *width: 65.69266486422946%;
5647 }
5648 .row-fluid .span7 {
5649 width: 57.18232044198895%;
5650 *width: 57.12912895262725%;
5651 }
5652 .row-fluid .span6 {
5653 width: 48.61878453038674%;
5654 *width: 48.56559304102504%;
5655 }
5656 .row-fluid .span5 {
5657 width: 40.05524861878453%;
5658 *width: 40.00205712942283%;
5659 }
5660 .row-fluid .span4 {
5661 width: 31.491712707182323%;
5662 *width: 31.43852121782062%;
5663 }
5664 .row-fluid .span3 {
5665 width: 22.92817679558011%;
5666 *width: 22.87498530621841%;
5667 }
5668 .row-fluid .span2 {
5669 width: 14.3646408839779%;
5670 *width: 14.311449394616199%;
5671 }
5672 .row-fluid .span1 {
5673 width: 5.801104972375691%;
5674 *width: 5.747913483013988%;
5675 }
5676 .row-fluid .offset12 {
5677 margin-left: 105.52486187845304%;
5678 *margin-left: 105.41847889972962%;
5679 }
5680 .row-fluid .offset12:first-child {
5681 margin-left: 102.76243093922652%;
5682 *margin-left: 102.6560479605031%;
5683 }
5684 .row-fluid .offset11 {
5685 margin-left: 96.96132596685082%;
5686 *margin-left: 96.8549429881274%;
5687 }
5688 .row-fluid .offset11:first-child {
5689 margin-left: 94.1988950276243%;
5690 *margin-left: 94.09251204890089%;
5691 }
5692 .row-fluid .offset10 {
5693 margin-left: 88.39779005524862%;
5694 *margin-left: 88.2914070765252%;
5695 }
5696 .row-fluid .offset10:first-child {
5697 margin-left: 85.6353591160221%;
5698 *margin-left: 85.52897613729868%;
5699 }
5700 .row-fluid .offset9 {
5701 margin-left: 79.8342541436464%;
5702 *margin-left: 79.72787116492299%;
5703 }
5704 .row-fluid .offset9:first-child {
5705 margin-left: 77.07182320441989%;
5706 *margin-left: 76.96544022569647%;
5707 }
5708 .row-fluid .offset8 {
5709 margin-left: 71.2707182320442%;
5710 *margin-left: 71.16433525332079%;
5711 }
5712 .row-fluid .offset8:first-child {
5713 margin-left: 68.50828729281768%;
5714 *margin-left: 68.40190431409427%;
5715 }
5716 .row-fluid .offset7 {
5717 margin-left: 62.70718232044199%;
5718 *margin-left: 62.600799341718584%;
5719 }
5720 .row-fluid .offset7:first-child {
5721 margin-left: 59.94475138121547%;
5722 *margin-left: 59.838368402492065%;
5723 }
5724 .row-fluid .offset6 {
5725 margin-left: 54.14364640883978%;
5726 *margin-left: 54.037263430116376%;
5727 }
5728 .row-fluid .offset6:first-child {
5729 margin-left: 51.38121546961326%;
5730 *margin-left: 51.27483249088986%;
5731 }
5732 .row-fluid .offset5 {
5733 margin-left: 45.58011049723757%;
5734 *margin-left: 45.47372751851417%;
5735 }
5736 .row-fluid .offset5:first-child {
5737 margin-left: 42.81767955801105%;
5738 *margin-left: 42.71129657928765%;
5739 }
5740 .row-fluid .offset4 {
5741 margin-left: 37.01657458563536%;
5742 *margin-left: 36.91019160691196%;
5743 }
5744 .row-fluid .offset4:first-child {
5745 margin-left: 34.25414364640884%;
5746 *margin-left: 34.14776066768544%;
5747 }
5748 .row-fluid .offset3 {
5749 margin-left: 28.45303867403315%;
5750 *margin-left: 28.346655695309746%;
5751 }
5752 .row-fluid .offset3:first-child {
5753 margin-left: 25.69060773480663%;
5754 *margin-left: 25.584224756083227%;
5755 }
5756 .row-fluid .offset2 {
5757 margin-left: 19.88950276243094%;
5758 *margin-left: 19.783119783707537%;
5759 }
5760 .row-fluid .offset2:first-child {
5761 margin-left: 17.12707182320442%;
5762 *margin-left: 17.02068884448102%;
5763 }
5764 .row-fluid .offset1 {
5765 margin-left: 11.32596685082873%;
5766 *margin-left: 11.219583872105325%;
5767 }
5768 .row-fluid .offset1:first-child {
5769 margin-left: 8.56353591160221%;
5770 *margin-left: 8.457152932878806%;
5771 }
5772 input,
5773 textarea,
5774 .uneditable-input {
5775 margin-left: 0;
5776 }
5777 .controls-row [class*="span"] + [class*="span"] {
5778 margin-left: 20px;
5779 }
5780 input.span12, textarea.span12, .uneditable-input.span12 {
5781 width: 710px;
5782 }
5783 input.span11, textarea.span11, .uneditable-input.span11 {
5784 width: 648px;
5785 }
5786 input.span10, textarea.span10, .uneditable-input.span10 {
5787 width: 586px;
5788 }
5789 input.span9, textarea.span9, .uneditable-input.span9 {
5790 width: 524px;
5791 }
5792 input.span8, textarea.span8, .uneditable-input.span8 {
5793 width: 462px;
5794 }
5795 input.span7, textarea.span7, .uneditable-input.span7 {
5796 width: 400px;
5797 }
5798 input.span6, textarea.span6, .uneditable-input.span6 {
5799 width: 338px;
5800 }
5801 input.span5, textarea.span5, .uneditable-input.span5 {
5802 width: 276px;
5803 }
5804 input.span4, textarea.span4, .uneditable-input.span4 {
5805 width: 214px;
5806 }
5807 input.span3, textarea.span3, .uneditable-input.span3 {
5808 width: 152px;
5809 }
5810 input.span2, textarea.span2, .uneditable-input.span2 {
5811 width: 90px;
5812 }
5813 input.span1, textarea.span1, .uneditable-input.span1 {
5814 width: 28px;
5815 }
5816}
5817@media (max-width: 767px) {
5818 body {
5819 padding-left: 20px;
5820 padding-right: 20px;
5821 }
5822 .navbar-fixed-top,
5823 .navbar-fixed-bottom,
5824 .navbar-static-top {
5825 margin-left: -20px;
5826 margin-right: -20px;
5827 }
5828 .container-fluid {
5829 padding: 0;
5830 }
5831 .dl-horizontal dt {
5832 float: none;
5833 clear: none;
5834 width: auto;
5835 text-align: left;
5836 }
5837 .dl-horizontal dd {
5838 margin-left: 0;
5839 }
5840 .container {
5841 width: auto;
5842 }
5843 .row-fluid {
5844 width: 100%;
5845 }
5846 .row,
5847 .thumbnails {
5848 margin-left: 0;
5849 }
5850 .thumbnails > li {
5851 float: none;
5852 margin-left: 0;
5853 }
5854 [class*="span"],
5855 .uneditable-input[class*="span"],
5856 .row-fluid [class*="span"] {
5857 float: none;
5858 display: block;
5859 width: 100%;
5860 margin-left: 0;
5861 -webkit-box-sizing: border-box; 2525 -webkit-box-sizing: border-box;
5862 -moz-box-sizing: border-box; 2526 padding: 10px;
5863 box-sizing: border-box; 2527 //background: #c8c8c8 url(./images/old/iPhone/pinstripes.png);
2528 background: #c8c8c8 url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAABCAIAAACdaSOZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABdJREFUeNpiPHrmCgMC/GNjYwNSAAEGADdNA3dnzPlQAAAAAElFTkSuQmCCCg==);
5864 } 2529 }
5865 .span12, 2530
5866 .row-fluid .span12 { 2531div.cardDetailPanel > fieldset > div.row > span.directLogin {
5867 width: 100%; 2532 width: 100%;
5868 -webkit-box-sizing: border-box;
5869 -moz-box-sizing: border-box;
5870 box-sizing: border-box; 2533 box-sizing: border-box;
5871 }
5872 .row-fluid [class*="offset"]:first-child {
5873 margin-left: 0;
5874 }
5875 .input-large,
5876 .input-xlarge,
5877 .input-xxlarge,
5878 input[class*="span"],
5879 select[class*="span"],
5880 textarea[class*="span"],
5881 .uneditable-input {
5882 display: block;
5883 width: 100%;
5884 min-height: 30px;
5885 -webkit-box-sizing: border-box;
5886 -moz-box-sizing: border-box; 2534 -moz-box-sizing: border-box;
5887 box-sizing: border-box; 2535 -webkit-box-sizing: border-box;
5888 }
5889 .input-prepend input,
5890 .input-append input,
5891 .input-prepend input[class*="span"],
5892 .input-append input[class*="span"] {
5893 display: inline-block;
5894 width: auto;
5895 }
5896 .controls-row [class*="span"] + [class*="span"] {
5897 margin-left: 0;
5898 }
5899 .modal {
5900 position: fixed;
5901 top: 20px;
5902 left: 20px;
5903 right: 20px;
5904 width: auto;
5905 margin: 0; 2536 margin: 0;
5906 }
5907 .modal.fade {
5908 top: -100px;
5909 }
5910 .modal.fade.in {
5911 top: 20px;
5912 }
5913}
5914@media (max-width: 480px) {
5915 .nav-collapse {
5916 -webkit-transform: translate3d(0, 0, 0);
5917 }
5918 .page-header h1 small {
5919 display: block;
5920 line-height: 20px;
5921 }
5922 input[type="checkbox"],
5923 input[type="radio"] {
5924 border: 1px solid #ccc;
5925 }
5926 .form-horizontal .control-label {
5927 float: none;
5928 width: auto;
5929 padding-top: 0;
5930 text-align: left;
5931 }
5932 .form-horizontal .controls {
5933 margin-left: 0;
5934 }
5935 .form-horizontal .control-list {
5936 padding-top: 0;
5937 }
5938 .form-horizontal .form-actions {
5939 padding-left: 10px;
5940 padding-right: 10px;
5941 }
5942 .media .pull-left,
5943 .media .pull-right {
5944 float: none;
5945 display: block;
5946 margin-bottom: 10px;
5947 }
5948 .media-object {
5949 margin-right: 0;
5950 margin-left: 0;
5951 }
5952 .modal {
5953 top: 10px;
5954 left: 10px;
5955 right: 10px;
5956 }
5957 .modal-header .close {
5958 padding: 10px;
5959 margin: -10px;
5960 }
5961 .carousel-caption {
5962 position: static;
5963 }
5964}
5965@media (max-width: 979px) {
5966 body {
5967 padding-top: 0;
5968 }
5969 .navbar-fixed-top,
5970 .navbar-fixed-bottom {
5971 position: static;
5972 }
5973 .navbar-fixed-top {
5974 margin-bottom: 20px;
5975 }
5976 .navbar-fixed-bottom {
5977 margin-top: 20px;
5978 }
5979 .navbar-fixed-top .navbar-inner,
5980 .navbar-fixed-bottom .navbar-inner {
5981 padding: 5px;
5982 }
5983 .navbar .container {
5984 width: auto;
5985 padding: 0;
5986 }
5987 .navbar .brand {
5988 padding-left: 10px;
5989 padding-right: 10px;
5990 margin: 0 0 0 -5px;
5991 }
5992 .nav-collapse {
5993 clear: both;
5994 }
5995 .nav-collapse .nav {
5996 float: none;
5997 margin: 0 0 10px;
5998 }
5999 .nav-collapse .nav > li {
6000 float: none;
6001 }
6002 .nav-collapse .nav > li > a {
6003 margin-bottom: 2px;
6004 }
6005 .nav-collapse .nav > .divider-vertical {
6006 display: none;
6007 }
6008 .nav-collapse .nav .nav-header {
6009 color: #777777;
6010 text-shadow: none;
6011 }
6012 .nav-collapse .nav > li > a,
6013 .nav-collapse .dropdown-menu a {
6014 padding: 9px 15px;
6015 font-weight: bold;
6016 color: #777777;
6017 -webkit-border-radius: 3px;
6018 -moz-border-radius: 3px;
6019 border-radius: 3px;
6020 }
6021 .nav-collapse .btn {
6022 padding: 4px 10px 4px;
6023 font-weight: normal;
6024 -webkit-border-radius: 4px;
6025 -moz-border-radius: 4px;
6026 border-radius: 4px;
6027 }
6028 .nav-collapse .dropdown-menu li + li a {
6029 margin-bottom: 2px;
6030 }
6031 .nav-collapse .nav > li > a:hover,
6032 .nav-collapse .dropdown-menu a:hover {
6033 background-color: #f2f2f2;
6034 }
6035 .navbar-inverse .nav-collapse .nav > li > a,
6036 .navbar-inverse .nav-collapse .dropdown-menu a {
6037 color: #999999;
6038 }
6039 .navbar-inverse .nav-collapse .nav > li > a:hover,
6040 .navbar-inverse .nav-collapse .dropdown-menu a:hover {
6041 background-color: #111111;
6042 }
6043 .nav-collapse.in .btn-group {
6044 margin-top: 5px;
6045 padding: 0;
6046 }
6047 .nav-collapse .dropdown-menu {
6048 position: static;
6049 top: auto;
6050 left: auto;
6051 float: none;
6052 display: none;
6053 max-width: none;
6054 margin: 0 15px;
6055 padding: 0;
6056 background-color: transparent;
6057 border: none; 2537 border: none;
6058 -webkit-border-radius: 0; 2538 padding: 12px 10px 0 110px;
6059 -moz-border-radius: 0; 2539 height: 42px;
6060 border-radius: 0; 2540 background: none;
6061 -webkit-box-shadow: none; 2541 font-size: 16px;
6062 -moz-box-shadow: none; 2542 font-weight: normal;
6063 box-shadow: none; 2543
6064 } 2544 padding-left: 40px;
6065 .nav-collapse .open > .dropdown-menu { 2545 color: black;
6066 display: block; 2546 //background: url(./images/old/iPhone/listArrow.png) no-repeat right center;
6067 } 2547 background: url(data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAUCAYAAAB4d5a9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAKVJREFUeNpi/P//PwOtARMDHcDwsYQFRJSXl8P4dVC6CZvizs5O8i1BsqARid9Ei+BiQ2KDLKumhSU1QNyKxG+hlkXoEQ+yqAPNogpapK5KNIvaKbUIVxKeAsTvkPg5QCxETUukgfgAkqFPgdgBzVKKLIFZoIJmwR1qBRdNLEC2BJQpV9LCAmRL/gBxAtRwqlqAXqzcgRrOQE0LQIBxtNIiBQAEGAA7xCa2yF9zEgAAAABJRU5ErkJgggo=) no-repeat right center;
6068 .nav-collapse .dropdown-menu:before,
6069 .nav-collapse .dropdown-menu:after {
6070 display: none;
6071 }
6072 .nav-collapse .dropdown-menu .divider {
6073 display: none;
6074 }
6075 .nav-collapse .nav > li > .dropdown-menu:before,
6076 .nav-collapse .nav > li > .dropdown-menu:after {
6077 display: none;
6078 }
6079 .nav-collapse .navbar-form,
6080 .nav-collapse .navbar-search {
6081 float: none;
6082 padding: 10px 15px;
6083 margin: 10px 0;
6084 border-top: 1px solid #f2f2f2;
6085 border-bottom: 1px solid #f2f2f2;
6086 -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
6087 -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
6088 box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);
6089 }
6090 .navbar-inverse .nav-collapse .navbar-form,
6091 .navbar-inverse .nav-collapse .navbar-search {
6092 border-top-color: #111111;
6093 border-bottom-color: #111111;
6094 }
6095 .navbar .nav-collapse .nav.pull-right {
6096 float: none;
6097 margin-left: 0;
6098 }
6099 .nav-collapse,
6100 .nav-collapse.collapse {
6101 overflow: hidden;
6102 height: 0;
6103 }
6104 .navbar .btn-navbar {
6105 display: block;
6106 }
6107 .navbar-static .navbar-inner {
6108 padding-left: 10px;
6109 padding-right: 10px;
6110 }
6111}
6112@media (min-width: 980px) {
6113 .nav-collapse.collapse {
6114 height: auto !important;
6115 overflow: visible !important;
6116 }
6117}
6118div.spinner {
6119 position: relative;
6120 width: 100px;
6121 height: 100px;
6122 display: inline-block;
6123}
6124div.spinner div {
6125 width: 12%;
6126 height: 26%;
6127 background: #000;
6128 position: absolute;
6129 left: 44.5%;
6130 top: 37%;
6131 opacity: 0;
6132 -webkit-animation: fade 1s linear infinite;
6133 -webkit-border-radius: 50px;
6134 -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.2);
6135}
6136div.spinner div.bar01 {
6137 -webkit-transform: rotate(0deg) translate(0, -142%);
6138 -webkit-animation-delay: 0s;
6139}
6140div.spinner div.bar02 {
6141 -webkit-transform: rotate(30deg) translate(0, -142%);
6142 -webkit-animation-delay: -0.9167s;
6143}
6144div.spinner div.bar03 {
6145 -webkit-transform: rotate(60deg) translate(0, -142%);
6146 -webkit-animation-delay: -0.833s;
6147}
6148div.spinner div.bar04 {
6149 -webkit-transform: rotate(90deg) translate(0, -142%);
6150 -webkit-animation-delay: -0.75s;
6151}
6152div.spinner div.bar05 {
6153 -webkit-transform: rotate(120deg) translate(0, -142%);
6154 -webkit-animation-delay: -0.667s;
6155}
6156div.spinner div.bar06 {
6157 -webkit-transform: rotate(150deg) translate(0, -142%);
6158 -webkit-animation-delay: -0.5833s;
6159}
6160div.spinner div.bar07 {
6161 -webkit-transform: rotate(180deg) translate(0, -142%);
6162 -webkit-animation-delay: -0.5s;
6163}
6164div.spinner div.bar08 {
6165 -webkit-transform: rotate(210deg) translate(0, -142%);
6166 -webkit-animation-delay: -0.41667s;
6167}
6168div.spinner div.bar09 {
6169 -webkit-transform: rotate(240deg) translate(0, -142%);
6170 -webkit-animation-delay: -0.333s;
6171}
6172div.spinner div.bar10 {
6173 -webkit-transform: rotate(270deg) translate(0, -142%);
6174 -webkit-animation-delay: -0.25s;
6175}
6176div.spinner div.bar11 {
6177 -webkit-transform: rotate(300deg) translate(0, -142%);
6178 -webkit-animation-delay: -0.1667s;
6179} 2548}
6180div.spinner div.bar12 { 2549
6181 -webkit-transform: rotate(330deg) translate(0, -142%); 2550body[orientation="landscape"] div.cardDetailPanel > fieldset > div.row > span.directLogin {
6182 -webkit-animation-delay: -0.0833s; 2551 padding-left: 50px;
6183} 2552}
6184@-webkit-keyframes fade { 2553
6185 from { 2554div.cardDetailPanel h2 {
6186 opacity: 1; 2555 margin: 0 0 8px 14px;
2556 font-size: inherit;
2557 font-weight: bold;
2558 color: #4d4d70;
2559 text-shadow: rgba(255, 255, 255, 0.75) 1px 1px 0;
6187 } 2560 }
6188 to { 2561
6189 opacity: 0.25; 2562body[orientation="portrait"] > * {
2563 width: 320px;
6190 } 2564 }
2565
2566body[orientation="landscape"] > * {
2567 width: 480px;
6191} 2568}
2569*/ \ No newline at end of file
diff --git a/frontend/gamma/html/mobile_template.html b/frontend/gamma/html/mobile_template.html
index 935fbe5..c2d19d3 100644
--- a/frontend/gamma/html/mobile_template.html
+++ b/frontend/gamma/html/mobile_template.html
@@ -1,67 +1,43 @@
1<!DOCTYPE html> 1<!DOCTYPE html>
2<!-- Conditional comment for mobile ie7 blogs.msdn.com/b/iemobile/ --> 2<html>
3<!--[if IEMobile 7 ]> <html class="no-js iem7" lang="en"> <![endif]-->
4<!--[if (gt IEMobile 7)|!(IEMobile)]><!--> <html class="no-js" lang="en" manifest="mobile.appcache"> <!--<![endif]-->
5<head> 3<head>
6 <title>@page.title@</title> 4 <title>@page.title@</title>
7 <meta charset="utf-8"> 5 <meta charset="utf-8">
8 6 <meta name="viewport" content="width=device-width, initial-scale=1">
9 <meta name="HandheldFriendly" content="True">
10 <meta name="MobileOptimized" content="320">
11 <!-- meta name="viewport" content="width=device-width" -->
12 <meta name="viewport" content="width=device-width, initial-scale=1.0">
13
14<!-- link rel="apple-touch-icon-precomposed" ... -->
15 <link rel="apple-touch-icon" sizes="114x114" href="data:image/png;charset=utf-8;base64,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">
16 <link rel="apple-touch-icon" sizes="72x72" href="data:image/png;charset=utf-8;base64,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">
17 <link rel="apple-touch-icon" href="data:image/png;charset=utf-8;base64,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">
18 <link rel="shortcut icon" href="data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAADkAAAA5CAIAAAADehTSAAAD8GlDQ1BJQ0MgUHJvZmlsZQAAKJGNVd1v21QUP4lvXKQWP6Cxjg4Vi69VU1u5GxqtxgZJk6XpQhq5zdgqpMl1bhpT1za2021Vn/YCbwz4A4CyBx6QeEIaDMT2su0BtElTQRXVJKQ9dNpAaJP2gqpwrq9Tu13GuJGvfznndz7v0TVAx1ea45hJGWDe8l01n5GPn5iWO1YhCc9BJ/RAp6Z7TrpcLgIuxoVH1sNfIcHeNwfa6/9zdVappwMknkJsVz19HvFpgJSpO64PIN5G+fAp30Hc8TziHS4miFhheJbjLMMzHB8POFPqKGKWi6TXtSriJcT9MzH5bAzzHIK1I08t6hq6zHpRdu2aYdJYuk9Q/881bzZa8Xrx6fLmJo/iu4/VXnfH1BB/rmu5ScQvI77m+BkmfxXxvcZcJY14L0DymZp7pML5yTcW61PvIN6JuGr4halQvmjNlCa4bXJ5zj6qhpxrujeKPYMXEd+q00KR5yNAlWZzrF+Ie+uNsdC/MO4tTOZafhbroyXuR3Df08bLiHsQf+ja6gTPWVimZl7l/oUrjl8OcxDWLbNU5D6JRL2gxkDu16fGuC054OMhclsyXTOOFEL+kmMGs4i5kfNuQ62EnBuam8tzP+Q+tSqhz9SuqpZlvR1EfBiOJTSgYMMM7jpYsAEyqJCHDL4dcFFTAwNMlFDUUpQYiadhDmXteeWAw3HEmA2s15k1RmnP4RHuhBybdBOF7MfnICmSQ2SYjIBM3iRvkcMki9IRcnDTthyLz2Ld2fTzPjTQK+Mdg8y5nkZfFO+se9LQr3/09xZr+5GcaSufeAfAww60mAPx+q8u/bAr8rFCLrx7s+vqEkw8qb+p26n11Aruq6m1iJH6PbWGv1VIY25mkNE8PkaQhxfLIF7DZXx80HD/A3l2jLclYs061xNpWCfoB6WHJTjbH0mV35Q/lRXlC+W8cndbl9t2SfhU+Fb4UfhO+F74GWThknBZ+Em4InwjXIyd1ePnY/Psg3pb1TJNu15TMKWMtFt6ScpKL0ivSMXIn9QtDUlj0h7U7N48t3i8eC0GnMC91dX2sTivgloDTgUVeEGHLTizbf5Da9JLhkhh29QOs1luMcScmBXTIIt7xRFxSBxnuJWfuAd1I7jntkyd/pgKaIwVr3MgmDo2q8x6IdB5QH162mcX7ajtnHGN2bov71OU1+U0fqqoXLD0wX5ZM005UHmySz3qLtDqILDvIL+iH6jB9y2x83ok898GOPQX3lk3Itl0A+BrD6D7tUjWh3fis58BXDigN9yF8M5PJH4B8Gr79/F/XRm8m241mw/wvur4BGDj42bzn+Vmc+NL9L8GcMn8F1kAcXjEKMJAAAAACXBIWXMAAAsTAAALEwEAmpwYAAABbmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNC40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iPgogICAgICAgICA8ZGM6c3ViamVjdD4KICAgICAgICAgICAgPHJkZjpCYWcvPgogICAgICAgICA8L2RjOnN1YmplY3Q+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgrlPw1BAAALFElEQVRoge2aeWxcxR3Hv/OOvbKHvWuv7V0fcQK5E+wEm1w1OZ0Ek1BCARUhWpUCalGl0pMeIKBIFBVVolWJkGhpGiBAoCE0FaQBnEKUg6QkzmUbO7bjIz7iY+9950z/2F1718eujd1KVflp9GTtzux83m9+v+/7zRsDX9qX9r9jZJrjTSaT1+vNOEsg4L927do055quVVVVhcPhUDAYCgYmauFwaNeuXdOfS5jmeFEULRYLpH6AgbHxO5mtRqNxmhNh+qyMMYBBk5NYk4kJwAAjm+g2pmLTZQUAMDAdjMYpR2MxMDr9xMAMsQJMA02wgoEBYAABAViMdQZshlipDqYjFg/ASBiwGKueGhhf0GYqBjTQGNCYqGUMVKN0Blw7U37VRvw64t2YMegqo9r0J5kJVqaD6aBaEmhykjFQFVSf/jwzoVm6CqrFWTGcScN5xqCrdCZYuXE/feihh3bsuM1kMk0GFroKpsUbVeNXmrgyFVRlk2N15+Y8+M17fvGjh8f9dhy/ulyup3/1VE6u6+yZs6/tfX3fvrfa2tomRAWjusrRGCtLqGxyhsXiNR0rx3GVK8ru3llza/W6OSUFPX1DL7+y72pPX2bWDRvW5+Q6ER0qW1Ja9uwTP/3B9/5+6IM9e179+JOjiqKMgWUs5leqgTGAxq/xkAVA07AW5Llrtqy/+/ZbKssX2mcZQDWq+l0O48abV+1540Bm1q/t/CqYChCoKqSwy8ru+/q2e+/YdvrspVffeHv/O3/r6OxMYqVUV/kUv9KRDIux0tE6wPP8qoryu3fWbNu4erYnm4cCGoEqgxM4jnBadEd1VWZWT0HBzWtXQY6OZAmliAQ5qlYu81aW/+TR7z9w8NCRV/a+fezESU3TNE1jusqoRtiwX2mKIDAKqlI9zur15G/fsuHO2zZXLJtrM1GoESjXQHgQHoSCUfACdLmibF5psbe1vSsda/WmDXl5LmgqGE1pABQZNFhgZw/cs/G+OzadPNO4e+9fg6GwpspiTLbiPUfhUqYpIs+trlx+713bt66rKMmzcHoQeg+iZIRyuIHxPHLsxuqbK1/csz+ZbXRJcWDfKzt2bIWOlIyOhePwH0wF1SAIIMY+n2YymWx6J2FanJKNZo0y24DssBlVh1mFEgDTQXiAAziQWOMTVx6EBydIkfCho5d2fvvnyQ+8FL+Wzi5ZXVkOHeBEEB5UBQOggepx1xIeHAElIIAqgwbcRqppANTRfk3CFamvwBDkmYoIAALCARSEgHBgMUQ91bvgiF62sGj+nML65vbxWbdVr8/JcUENINAI3wUEGhHpgNwPXQYA3gDBBmMOzB5YimD2QnSAiAKRErVLDFcfFbgCGGjSMhISJyYx1+pJuEIsDESBy57Fb6laMT4rx3E7ampY80ukcRekLgyLzKgwiekmBxjsmFWKrDJk3wBzAQgHqiTUIFHOji1qCQGLsZIEK5catTxACSfwUDevXfaHv7yravpo1gXz5t64uIjVPUrCXeABHhlMCUCuw0AdRAPsi+CugmMxiAAqJ1iTtDZlr5BgTYnX4SYAFIAosEWl7iXzis9cah3Nun1bdRa5SiId8X1HxkKeJPpQBYNnMXQW1jnI34ysJfEqMVkTRlaEgCERtSQBqiclFgUTQJnAw2bCrevKRrMSQsqXLdDMs0nFbtZ7hO//WIg0QddGgNJbrKwItaD5RWQtRcE2mPLBYsKX9BhLvtEUVi6W/oDONFVWqKIyVSNBmbjdbsIRRmP3lzCn07myYnnN1o1VK28sdpvFSBPp+yc/dEyMXAbVJwsNgAKiBflb4FwBpoMl14rDoCS+LnFKwigna1A0XtFFXwT1bYO1pxo/PHauvqlNVeThhRxtTqdz9U0rajavW1t5Q2GOUYw0kf6jou+kKLWC0klBx6icK5C/GYSPJ9xIJJD4VowQRoms87JmUJjZH+Xqr/hqT33+0fFzFxtbNHV07ZFuWpfLteam5bds+srqFUu8Tl6MNHEDxw3B06LckZDbtMQUsM2Bpwa8MYELEAYwSomsCbJuUmD1S2Jju6/29OcfHTt/obFVU+WJfm9S65qbm7OmsnzrhtUry+Z7sogQbuJ8n5ojdQalI8NICszywFMD3gSqM0ajqhDRTDpnD8jGxk7/kVNNHx4/f7GxdXih09jUtu3u3NzVlWV3bFvzleXzs/p2O/zvTyoeLF4UbAHHM13rCrp6Qta9hy/Unrx4oaFlMojDllFFUywciTQ0tawtv26l56pj4E1CJrGTJoAahOaHuZBAt/DhoMS/sLf21Lkmqk9tYzM1VgD337npkbuWZve8yLHoZMcQQB4CITDmcES2isqS+QtqT7f4gtJ/kLVy2dznfrgz37dbVLunFj4EkK7BmA3eJHIRu5n35hceOtGsalN4bzAF1lyn7YXHvrHI+LEl/NkXeT3FGFQ/THkANfIhd3YWL5g/qevMPHCqrDzHPfPIndULAnbfQZIBlFAIBGMcRgBNAsfDYCVMNZJQSYGnqz/a0D40w6z3377mO9tnu3yv8xizPUy1QbKwnyxxoG2c7wighWDMAnSel41cdG6R99OG/j7fpAJ3Uqw3LS155uENXukdA+1P31OB7QpZH0a+yHwWMjhOD6qDA0QDdMUgSiaBFeflfnimV1Iya0JmVrfT+rsf37bY8ukstSF9TwbSx6/5U23kRMPA0uvnWGinSMbIJwF0GQYDoIIpZjFkM5ntFsuRcwMZXydnYBV47unvVlfP92dLn2RMJx+bc6p3zs92HTle17ps0fW5DquDdI2jwUwHr4GLgoYJiZqFQK49Oxhlda3habF+a3v5g1vz3dL7PDK86JOo9YpW8fjuiw2tPZTq51t9VSvmmTjZJo5JHQYQBYISc63AR418qMjlvNQhdQ6kmyUd68rFnqfuX17Mao3wpwdl4K7qS187pv75YF3sE58/NBAVKhZ6zBg0CamREKvlhQQ3g8moCpBLXMLRejXN82FC1mK39TcPr1lkr7eztvSgIOhXPf/qKfzlHz+LSCNYTe39ue682bkGh+DjuVQJYwAHkEQVzmCzqERXPQ52tBHKBM4d/z0hgLmlhXm52QNyTlDPTqf8BBHV3Bkpev6dy/1DwVQg+vu3Lp7pntURsLGxP6EDNMFK0dWDQBAlhZ4cp3WiqSb0a1tX/6nmyLzrrjOYnLqqWIXguMAUXHu4eN9p8vJ7TWMPBWRFaerFqoUGMwI28+ibjDVVRWMbugeMJ7qLHnsj0t49Ybyli9eevsHDp686crwed25YglUMC1yqChL0hBxnel2P72mNRMev7voGgirvWlQg2Q2aUUxl5eHz41IL+iPZr551P7e/x+cPpOHJoAOSJB05feWabJtfmi/JTCSyWVSHJwtKwmW/49l3o+cvjyf7Catvj5QUed1Gv8vGOBIfy4D2bjR3kCsR77OHDQeOdlBdTfMjmVkBAKyhpedEs1Y622vkNUWR7CadcNApWgbJgXPmlw9dS38kxKh+oRMV1zstCDodAIGk4FILuodMx3qLntwfqm/tncyh0mTrgYGhwAdnhgyOAq9TDYQiVhN6/TjXY3/yTSkUyVzbhyNSV9ixvJDYBFlWceEy+mXnnnO5zx/sDgaDGYdPjRWAqionzve3h/PmFWVJIb8vKv72H5a6yxmkd9g6+0Imh6fYEuobRFvU++vDwnsnO6Z0ljTVfQFr7Rw62mwsLSmqv8q/dHhgKueX7GKHtHhe0WW//Yn9gab2/9a/ExiMZqt11hcYaLfbBHEGzue/tP9P+zclUOrCr+J20QAAAABJRU5ErkJgggo=">
19
20 <meta http-equiv="cleartype" content="on">
21 <meta name="apple-mobile-web-app-capable" content="yes">
22
23
24 <!-- link rel="apple-touch-startup-image" href="data:image/png;charset=utf-8;base64,iVBORw0K...ggo=" -->
25
26<!--
27@copyright@
28-->
29
30@css@ 7@css@
31 8
32 <link rel="shortcut icon" href="./clipperz.ico" />
33
34 <meta name="description" content="Login to your web accounts with just one click. Never type a password again! Use multiple complex passwords and forget them. A password manager that enhances your online security." />
35 <meta name="keywords" content="password manager,gestor de contraseñas,gerenciador de senhas,Kennwortmanager,passwords,security,privacy,cryptography" />
36<script> 9<script>
37 Clipperz_IEisBroken = false; 10 Clipperz_IEisBroken = false;
38 Clipperz_normalizedNewLine = '\n'; 11 Clipperz_normalizedNewLine = '\n';
39 Clipperz_dumpUrl = "/dump/"; 12 Clipperz_dumpUrl = "/../dump/";
40</script> 13</script>
41 14
42@js_LINKED@ 15@js_LINKED@
43 16
44</head> 17</head>
45<body> 18<body>
46<div id="mainDiv"> 19<div id="loadingPage" data-role="page">
47 <div id="loading"> 20 <div data-role="header">
48 <div>
49 <!-- a href="http://www.clipperz.com" target="_blank"><div id="logo"></div></a -->
50 <h1>clipperz</h1> 21 <h1>clipperz</h1>
51 <h3 class="clipperzPayoff">keep it to yourself!</h3> 22 </div>
52 <!-- h5>loading ...</h5 --> 23 <div data-role="content">
24 <div>
25 <h5>loading ...</h5>
26 </div>
53 </div> 27 </div>
54 </div> 28 </div>
55 29
56@js_EMBEDDED@ 30@js_EMBEDDED@
57 31
58</div>
59<!-- div id="applicationVersionType" class="@application.version.type@"></div -->
60
61<script> 32<script>
62 Clipperz.PM.Proxy.defaultProxy = new Clipperz.PM.Proxy.JSON({'url':'@request.path@', 'shouldPayTolls':@should.pay.toll@}); 33 Clipperz.PM.Proxy.defaultProxy = new Clipperz.PM.Proxy.JSON({'url':'@request.path@', 'shouldPayTolls':@should.pay.toll@});
63 /*offline_data_placeholder*/ 34 /*offline_data_placeholder*/
35
36 MochiKit.DOM.addLoadEvent(function () {
37 Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose();
38 });
39
64</script> 40</script>
65 41
66</body> 42</body>
67</html> 43</html>
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/BaseComponent.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/BaseComponent.js
new file mode 100644
index 0000000..1e7b69f
--- a/dev/null
+++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/BaseComponent.js
@@ -0,0 +1,249 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components');
25
26//#############################################################################
27
28var _Clipperz_PM_Components_base_id_ = 0;
29
30//#############################################################################
31
32Clipperz.PM.UI.Mobile.Components.BaseComponent = function(args) {
33 args = args || {};
34 Clipperz.PM.UI.Mobile.Components.BaseComponent.superclass.constructor.call(this, args);
35
36 this._element = args.element || null;
37 this._ids = {};
38
39 this._isFullyRendered = false;
40 //this._renderingWaitingQueue = [];
41
42 return this;
43}
44
45//=============================================================================
46
47//MochiKit.Base.update(Clipperz.PM.UI.Mobile.Components.BaseComponent, Object, {
48Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.BaseComponent, Object, {
49
50 'isClipperzPMComponent': true,
51
52 //-------------------------------------------------------------------------
53
54 'toString': function () {
55 return "Clipperz.PM.UI.Mobile.Components.BaseComponent component";
56 },
57
58 'componentId': function () {
59 return this.getId('_id_');
60 },
61
62 //-------------------------------------------------------------------------
63
64 'element': function() {
65 return MochiKit.DOM.getElement(this._element);
66 },
67
68 'setElement': function(aNode) {
69 this._element = aNode;
70 },
71
72 //-----------------------------------------------------
73
74 'displayElement': function() {
75 return this.element();
76 },
77
78 //-------------------------------------------------------------------------
79
80 'renderInNode': function(aDomNode) {
81 this.setElement(aDomNode);
82 this.render();
83 },
84
85 'render': function() {
86 this.clear();
87 this.renderSelf();
88 // this.renderComponents();
89 // if (this.shouldShowTranslationHints()) {
90 // this.renderTranslationHints();
91 // }
92 if (this.shouldShowElementWhileRendering()) {
93 MochiKit.Style.showElement(this.displayElement());
94 };
95
96 this._isFullyRendered = true;
97
98 // MochiKit.Iter.forEach(this.renderingWaitingQueue(), MochiKit.Base.methodcaller('callback'));
99 // this.resetRenderingWaitingQueue();
100 },
101
102 'renderSelf': function() {
103 throw Clipperz.Base.exception.AbstractMethod;
104 },
105
106 //'renderComponents': function() {
107 // varslotName;
108 //
109 // for (slotName in this.slotComponents()) {
110 // this.slotComponents()[slotName].renderInNode(this.elementForSlotNamed(slotName));
111 // }
112 //},
113
114 //.........................................................................
115
116 'shouldShowElementWhileRendering': function() {
117 return false;
118 },
119
120 //.........................................................................
121
122 'isFullyRendered': function () {
123 return this._isFullyRendered;
124 },
125
126 //.........................................................................
127/*
128 'renderingWaitingQueue': function () {
129 return this._renderingWaitingQueue;
130 },
131
132 'resetRenderingWaitingQueue': function () {
133 this._renderingWaitingQueue = [];
134 },
135
136 //.........................................................................
137
138 'waitUntilFullyRendered': function () {
139 var deferredResult;
140
141 if (this.isFullyRendered() == true) {
142 deferredResult = MochiKit.Async.succeed
143 } else {
144 deferredResult = new Clipperz.Async.Deferred("BaseComponent.waitUntilFullyRendered", {trace:false});
145 this.renderingWaitingQueue().push(deferredResult);
146 }
147
148 return deferredResult;
149 },
150*/
151 //-----------------------------------------------------
152/*
153 'update': function(args) {
154 throw Clipperz.Base.exception.AbstractMethod;
155 },
156
157 'updateSelf': function(args) {
158 throw Clipperz.Base.exception.AbstractMethod;
159 },
160
161 'updateComponents': function(args) {
162 throw Clipperz.Base.exception.AbstractMethod;
163 },
164*/
165 //-----------------------------------------------------
166/*
167 'refresh': function() {
168 throw Clipperz.Base.exception.AbstractMethod;
169 },
170
171 'refreshSelf': function() {
172 throw Clipperz.Base.exception.AbstractMethod;
173 },
174
175 'refreshComponents': function(args) {
176 throw Clipperz.Base.exception.AbstractMethod;
177 },
178*/
179 //-----------------------------------------------------
180
181 'clear': function() {
182 varslotName;
183 var componentId;
184
185 MochiKit.Signal.disconnectAllTo(this);
186
187 if (this.displayElement() != null) {
188 if (this.element() != this.displayElement()) {
189 MochiKit.DOM.removeElement(this.displayElement());
190 } else {
191 this.displayElement().innerHTML = "";
192 }
193 }
194 },
195
196 'remove': function() {
197 this.clear();
198 MochiKit.Signal.disconnectAll(this);
199 },
200
201 'append': function(aNode, aValue) {
202 return Clipperz.DOM.Helper.append(aNode, aValue);
203 },
204
205 'insertBefore': function (aNode, aValue) {
206 return Clipperz.DOM.Helper.insertBefore(aNode, aValue);
207 },
208
209 'insertAfter': function (aNode, aValue) {
210 return Clipperz.DOM.Helper.insertAfter(aNode, aValue);
211 },
212
213 //-------------------------------------------------------------------------
214
215 'getId': function(aValue) {
216 varresult;
217
218 if (typeof(aValue) != 'undefined') {
219 result = this._ids[aValue];
220
221 if (typeof(result) == 'undefined') {
222 _Clipperz_PM_Components_base_id_ ++;
223
224 result = "Clipperz_PM_Components_" + aValue + "_" + _Clipperz_PM_Components_base_id_;
225 this._ids[aValue] = result;
226 }
227 } else {
228 // result = Clipperz.PM.UI.Common.Components.BaseComponent.superclass.getId.call(this);
229 throw "call to BaseComponent.getId with an undefined value";
230 }
231
232 return result;
233 },
234
235 'getAnchor': function (aValue) {
236 return '#' + this.getId(aValue);
237 },
238
239 //-------------------------------------------------------------------------
240
241 'getElement': function(aValue) {
242 return Clipperz.DOM.get(this.getId(aValue));
243 },
244
245 //-------------------------------------------------------------------------
246
247 __syntaxFix__: "syntax fix"
248
249});
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardList.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardList.js
index a0e4879..dbab41b 100644
--- a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardList.js
+++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/CardList.js
@@ -8,121 +8,142 @@ refer to http://www.clipperz.com.
8 8
9* Clipperz is free software: you can redistribute it and/or modify it 9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published 10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or 11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version. 12 (at your option) any later version.
13 13
14* Clipperz is distributed in the hope that it will be useful, but 14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of 15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details. 17 See the GNU Affero General Public License for more details.
18 18
19* You should have received a copy of the GNU Affero General Public 19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/. 20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21 21
22*/ 22*/
23 23
24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components'); 24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components');
25 25
26Clipperz.PM.UI.Mobile.Components.CardList = function(args) { 26Clipperz.PM.UI.Mobile.Components.CardList = function(args) {
27 args = args || {}; 27 args = args || {};
28 28
29 Clipperz.PM.UI.Mobile.Components.CardList.superclass.constructor.apply(this, arguments); 29 Clipperz.PM.UI.Mobile.Components.CardList.superclass.constructor.apply(this, arguments);
30 30
31 this._cardDetail = null; 31 this._cardDetail = null;
32 this.render();
32 33
33 return this; 34 return this;
34} 35}
35 36
36//============================================================================= 37//=============================================================================
37 38
38Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.CardList, Clipperz.PM.UI.Common.Components.BaseComponent, { 39Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.CardList, Clipperz.PM.UI.Mobile.Components.BaseComponent, {
39 40
40 //------------------------------------------------------------------------- 41 //-------------------------------------------------------------------------
41 42
42 'toString': function () { 43 'toString': function () {
43 return "Clipperz.PM.UI.Mobile.Components.CardList component"; 44 return "Clipperz.PM.UI.Mobile.Components.CardList component";
44 }, 45 },
45 46
46 //------------------------------------------------------------------------- 47 //-------------------------------------------------------------------------
47 48
48 'renderSelf': function () { 49 'renderSelf': function () {
50 varheaderElement;
51
52 headerElement = MochiKit.Selector.findChildElements(this.element().parentNode, ['div[data-role=header]'])[0];
53 this.append(this.element(),
54 {tag:'div', /*cls:'scroll',*/ id:this.getId('listBox'), children:[
55 {tag:'ul', /*cls:'rounded',*/ id:this.getId('list'), children:[
56 {tag:'li', html:'loading'}
57 ]}
58 ]}
59 );
60
61 this.append(headerElement,
62 // {tag:'a', href:"#", 'data-icon':'gear', cls:'ui-btn-right', html:"Options" }
63 {tag:'a', href:"#", id:this.getId('preferences'), cls:'ui-btn-right', html:"options" }
64 );
65
66 MochiKit.Signal.connect(this.getElement('preferences'), 'onclick', MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'showPreferences'));
67
68/*
49 this.append(this.element(), {tag:'div', cls:'cardList', children:[ 69 this.append(this.element(), {tag:'div', cls:'cardList', children:[
50 {tag:'div', cls:'toolbar', children:[ 70 {tag:'div', cls:'toolbar', children:[
51 {tag:'h1', html:"clipperz"}, 71 {tag:'h1', html:"clipperz"},
52 // {tag:'input', name:'search', type:'search', autocomplete:'off', placeholder:"search", id:this.getId('search')}, 72 // {tag:'input', name:'search', type:'search', autocomplete:'off', placeholder:"search", id:this.getId('search')},
53 {tag:'a', href:'#', id:'settings', cls:'button', html:"*"} 73 {tag:'a', href:'#', id:'settings', cls:'button', html:"*"}
54 ]}, 74 ]},
55 {tag:'div', cls:'scroll', id:this.getId('listBox'), children:[ 75 {tag:'div', cls:'scroll', id:this.getId('listBox'), children:[
56 {tag:'ul', cls:'rounded', id:this.getId('list'), children:[ 76 {tag:'ul', cls:'rounded', id:this.getId('list'), children:[
57 {tag:'li', html:'loading'} 77 {tag:'li', html:'loading'}
58 ]} 78 ]}
59 ]} 79 ]}
60 ]}); 80 ]});
61 81
62 MochiKit.Signal.connect(this.getElement('list'), 'onclick', this, 'cardSelectionHandler'); 82 MochiKit.Signal.connect(this.getElement('list'), 'onclick', this, 'cardSelectionHandler');
63 MochiKit.Signal.connect(this.getElement('list'), 'ontouchstart',this, 'cardSelectionHandler'); 83 MochiKit.Signal.connect(this.getElement('list'), 'ontouchstart',this, 'cardSelectionHandler');
64 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onsubmit', this,'searchHandler'); 84 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onsubmit', this,'searchHandler');
65 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeydown', this,'searchHandler'); 85 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeydown', this,'searchHandler');
66 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeyup', this,'searchHandler'); 86 // MochiKit.Signal.connect(this.getElement('cardListSearchForm'), 'onkeyup', this,'searchHandler');
67 87
68 // MochiKit.Signal.connect(this.getElement('cardListPanel'), 'onclick', this,'cardListClickHandler'); 88 // MochiKit.Signal.connect(this.getElement('cardListPanel'), 'onclick', this,'cardListClickHandler');
69 // MochiKit.Signal.connect('backButton', 'onclick', this,'backButtonClickHandler'); 89 // MochiKit.Signal.connect('backButton', 'onclick', this,'backButtonClickHandler');
70 90
71 // MochiKit.Style.hideElement('backButton'); 91 // MochiKit.Style.hideElement('backButton');
72 // MochiKit.Style.hideElement(this.getElement('cardDetail')); 92 // MochiKit.Style.hideElement(this.getElement('cardDetail'));
93*/
73 }, 94 },
74 95
75 'showCards': function (someCards) { 96 'showCards': function (someCards) {
76 varcardListElement; 97 varcardListElement;
77 if (this.isFullyRendered() == false) { 98 if (this.isFullyRendered() == false) {
78 this.render(); 99 this.render();
79 }; 100 };
80 101
81 cardListElement = this.getElement('list') 102 cardListElement = this.getElement('list')
82 103
83 cardInfo = { 104 cardInfo = {
84 '_rowObject': MochiKit.Async.succeed, 105 '_rowObject': MochiKit.Async.succeed,
85 '_reference': MochiKit.Base.methodcaller('reference'), 106 '_reference': MochiKit.Base.methodcaller('reference'),
86 '_searchableContent':MochiKit.Base.methodcaller('searchableContent'), 107 '_searchableContent':MochiKit.Base.methodcaller('searchableContent'),
87 'label': MochiKit.Base.methodcaller('label'), 108 'label': MochiKit.Base.methodcaller('label'),
88 'favicon': MochiKit.Base.methodcaller('favicon') 109 'favicon': MochiKit.Base.methodcaller('favicon')
89 }; 110 };
90 111
91 deferredResult = new Clipperz.Async.Deferred("CardList.showCards", {trace:false}); 112 deferredResult = new Clipperz.Async.Deferred("CardList.showCards", {trace:false});
92 deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false})); 113 deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false}));
93 deferredResult.addCallback(Clipperz.Async.collectAll); 114 deferredResult.addCallback(Clipperz.Async.collectAll);
94 deferredResult.addCallback(MochiKit.Base.methodcaller('sort', Clipperz.Base.caseInsensitiveKeyComparator('label'))); 115 deferredResult.addCallback(MochiKit.Base.methodcaller('sort', Clipperz.Base.caseInsensitiveKeyComparator('label')));
95 deferredResult.addCallbackPass(MochiKit.DOM.replaceChildNodes, cardListElement); 116 deferredResult.addCallbackPass(MochiKit.DOM.replaceChildNodes, cardListElement);
96 // deferredResult.addCallbackPass(MochiKit.DOM.removeElementClass, cardListElement, 'loading'); 117 // deferredResult.addCallbackPass(MochiKit.DOM.removeElementClass, cardListElement, 'loading');
97 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'appendCardToList', cardListElement)); 118 deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'appendCardToList', cardListElement));
98 deferredResult.callback(someCards); 119 deferredResult.callback(someCards);
99 }, 120 },
100 121
101 'appendCardToList': function (aCardListElement, aCardInfo) { 122 'appendCardToList': function (aCardListElement, aCardInfo) {
102 this.append(aCardListElement, {tag:'li', cls:'cardListItem arrow', cardreference:aCardInfo['_reference'], children:[ 123 this.append(aCardListElement, {tag:'li', cls:'cardListItem arrow', cardreference:aCardInfo['_reference'], children:[
103 {tag:'a', href:'#', html:aCardInfo['label'], children:[ 124 {tag:'a', href:'#', html:aCardInfo['label'], children:[
104 {tag:'small', cls:'favicon', children:[{tag:'img', cls:'favicon', src:aCardInfo['favicon']}]} 125 // {tag:'small', cls:'favicon', children:[{tag:'img', cls:'favicon', src:aCardInfo['favicon']}]}
105 ]} 126 ]}
106 ]}); 127 ]});
107 }, 128 },
108 129
109 'cardSelectionHandler': function (anEvent) { 130 'cardSelectionHandler': function (anEvent) {
110 var listElement; 131 var listElement;
111 varcardReference; 132 varcardReference;
112 133
113 anEvent.preventDefault(); 134 anEvent.preventDefault();
114 135
115 listElement = anEvent.target(); 136 listElement = anEvent.target();
116 if (MochiKit.DOM.getNodeAttribute(listElement, 'cardreference') == null) { 137 if (MochiKit.DOM.getNodeAttribute(listElement, 'cardreference') == null) {
117 listElement = MochiKit.DOM.getFirstParentByTagAndClassName(anEvent.target(), tagName='li', className='cardListItem'); 138 listElement = MochiKit.DOM.getFirstParentByTagAndClassName(anEvent.target(), tagName='li', className='cardListItem');
118 } 139 }
119 cardReference = MochiKit.DOM.getNodeAttribute(listElement, 'cardreference'); 140 cardReference = MochiKit.DOM.getNodeAttribute(listElement, 'cardreference');
120 //TODO: Notify card with reference MochiKit.DOM.getNodeAttribute(listElement, 'cardreference') has been selected 141 //TODO: Notify card with reference MochiKit.DOM.getNodeAttribute(listElement, 'cardreference') has been selected
121 MochiKit.Signal.signal(this, 'selectedCard', cardReference); 142 MochiKit.Signal.signal(this, 'selectedCard', cardReference);
122 }, 143 },
123 144
124 //------------------------------------------------------------------------- 145 //-------------------------------------------------------------------------
125/* 146/*
126 'searchHandler': function (anEvent) { 147 'searchHandler': function (anEvent) {
127 if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ENTER')) { //RETURN 148 if ((typeof(anEvent.key()) != 'undefined') && (anEvent.key().string == 'KEY_ENTER')) { //RETURN
128 anEvent.preventDefault(); 149 anEvent.preventDefault();
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js
index 3aeac0c..da864eb 100644
--- a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js
+++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/LoginForm.js
@@ -23,49 +23,50 @@ refer to http://www.clipperz.com.
23 23
24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components'); 24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components');
25 25
26Clipperz.PM.UI.Mobile.Components.LoginForm = function(args) { 26Clipperz.PM.UI.Mobile.Components.LoginForm = function(args) {
27 args = args || {}; 27 args = args || {};
28 28
29 this._pin = ''; 29 this._pin = '';
30 30
31 this._message = null; 31 this._message = null;
32 this._steps = 0; 32 this._steps = 0;
33 this._actualSteps = 0; 33 this._actualSteps = 0;
34 34
35 this._callback = null; 35 this._callback = null;
36 this._errorCallback = null; 36 this._errorCallback = null;
37 37
38 this._mode = 'CREDENTIALS'; 38 this._mode = 'CREDENTIALS';
39 39
40 Clipperz.PM.UI.Mobile.Components.LoginForm.superclass.constructor.apply(this, arguments); 40 Clipperz.PM.UI.Mobile.Components.LoginForm.superclass.constructor.apply(this, arguments);
41 41
42 return this; 42 return this;
43} 43}
44 44
45//============================================================================= 45//=============================================================================
46 46
47Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.LoginForm, Clipperz.PM.UI.Common.Components.BaseComponent, { 47//Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.LoginForm, Clipperz.PM.UI.Common.Components.BaseComponent, {
48Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.LoginForm, Clipperz.PM.UI.Mobile.Components.BaseComponent, {
48 49
49 //------------------------------------------------------------------------- 50 //-------------------------------------------------------------------------
50 51
51 'toString': function () { 52 'toString': function () {
52 return "Clipperz.PM.UI.Mobile.Components.LoginForm component"; 53 return "Clipperz.PM.UI.Mobile.Components.LoginForm component";
53 }, 54 },
54 55
55 //------------------------------------------------------------------------- 56 //-------------------------------------------------------------------------
56 57
57 'callback': function () { 58 'callback': function () {
58 return this._callback; 59 return this._callback;
59 }, 60 },
60 61
61 'errorCallback': function () { 62 'errorCallback': function () {
62 return this._errorCallback; 63 return this._errorCallback;
63 }, 64 },
64 65
65 //------------------------------------------------------------------------- 66 //-------------------------------------------------------------------------
66 67
67 'mode': function () { 68 'mode': function () {
68 return this._mode; 69 return this._mode;
69 }, 70 },
70 71
71 'setMode': function (aValue) { 72 'setMode': function (aValue) {
@@ -90,257 +91,282 @@ Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.LoginForm, Clipperz.PM.UI.
90 91
91 'setUsername': function (aValue) { 92 'setUsername': function (aValue) {
92 this._username = aValue; 93 this._username = aValue;
93 }, 94 },
94 95
95 //.......................................................................... 96 //..........................................................................
96 97
97 'passphrase': function () { 98 'passphrase': function () {
98 return this._passphrase; 99 return this._passphrase;
99 }, 100 },
100 101
101 'setPassphrase': function (aValue) { 102 'setPassphrase': function (aValue) {
102 this._passphrase = aValue; 103 this._passphrase = aValue;
103 }, 104 },
104 105
105 //------------------------------------------------------------------------- 106 //-------------------------------------------------------------------------
106 107
107 'message': function () { 108 'message': function () {
108 return this._message; 109 return this._message;
109 }, 110 },
110 111
111 '_setMessage': function (aValue) { 112 '_setMessage': function (aValue) {
112 this._message = aValue; 113 this._message = aValue;
113 114
114 if (aValue == null) { 115 // if (aValue == null) {
115 MochiKit.Style.hideElement(this.getElement('credentialsMessage')); 116 // MochiKit.Style.hideElement(this.getElement('credentialsMessage'));
116 } else { 117 // } else {
117 this.getElement('message').innerHTML = aValue; 118 // this.getElement('message').innerHTML = aValue;
118 MochiKit.Style.showElement(this.getElement('credentialsMessage')); 119 // MochiKit.Style.showElement(this.getElement('credentialsMessage'));
119 } 120 // }
120 }, 121 },
121 122
122 'setMessage': function (aValue) { 123 'setMessage': function (aValue) {
123 this._setMessage(aValue); 124 this._setMessage(aValue);
124 MochiKit.DOM.removeElementClass(this.getElement('credentialsMessage'), 'error'); 125 // MochiKit.DOM.removeElementClass(this.getElement('credentialsMessage'), 'error');
125 }, 126 },
126 127
127 'setErrorMessage': function (aValue) { 128 'setErrorMessage': function (aValue) {
128 this._setMessage(aValue); 129 this._setMessage(aValue);
129 MochiKit.DOM.addElementClass(this.getElement('credentialsMessage'), 'error'); 130 // MochiKit.DOM.addElementClass(this.getElement('credentialsMessage'), 'error');
130 }, 131 },
131 132
132 //------------------------------------------------------------------------- 133 //-------------------------------------------------------------------------
133 134
134 'setCallbacks': function (args) { 135 'setCallbacks': function (args) {
135 this._callback = args['callback']; 136 this._callback = args['callback'];
136 this._errorCallback = args['errorCallback']; 137 this._errorCallback = args['errorCallback'];
137 }, 138 },
138 139
140 'show': function (args) {
141 this.updateWithArgs(args);
142
143 if (this.mode() == 'PIN') {
144 this.setPin('');
145 this.getElement('PIN').focus();
146 } else if (this.mode() == 'CREDENTIALS') {
147 if (this.getElement('usernameField').value.length == 0) {
148 this.getElement('usernameField').focus();
149 } else {
150 this.getElement('passphraseField').focus();
151 this.getElement('passphraseField').select();
152 }
153 }
154 },
155
139 'showErrors': function (args) { 156 'showErrors': function (args) {
140 if (args['previousFailedAttempt'] == 'LOGIN') { 157 if (args['previousFailedAttempt'] == 'LOGIN') {
158 $(this.getAnchor('credentialsSubmitButton')).button('enable');
141 this.setErrorMessage("Wrong credentials"); 159 this.setErrorMessage("Wrong credentials");
142 } else if (args['previousFailedAttempt'] == 'PIN') { 160 } else if (args['previousFailedAttempt'] == 'PIN') {
143 if (args['failedAttempts'] == -1) { 161 if (args['failedAttempts'] == -1) {
144 this.setErrorMessage("Wrong PIN - Resetted"); 162 this.setErrorMessage("Wrong PIN - Resetted");
145 } else { 163 } else {
146 this.setErrorMessage("Wrong PIN"); 164 this.setErrorMessage("Wrong PIN");
147 } 165 }
148 } else { 166 } else {
149 this.setMessage(null); 167 this.setMessage(null);
150 } 168 }
151 }, 169 },
152 170
153 'updateWithArgs': function (args) { 171 'updateWithArgs': function (args) {
154 this.renderIfNeeded(); 172 this.renderOnlyOnce();
155 this.setCallbacks(args); 173 this.setCallbacks(args);
156 this.showErrors(args); 174 this.showErrors(args);
157 this.updateRendering(); 175 // this.updateRendering();
158 },
159
160 'showPinLogin': function (args) {
161 this.setPin('');
162 this.setMode('PIN');
163 this.updateWithArgs(args);
164
165 // $(this.getAnchor('PIN')).focus();
166 this.getElement('PIN').focus();
167 },
168
169 'showCredentialsLogin': function (args) {
170 this.setMode('CREDENTIALS');
171 this.updateWithArgs(args);
172
173 if (this.getElement('usernameField').value.length == 0) {
174 // $(this.getAnchor('usernameField')).focus();
175 this.getElement('usernameField').focus();
176 } else {
177 // $(this.getAnchor('passphraseField')).focus();
178 this.getElement('passphraseField').focus();
179 this.getElement('passphraseField').select();
180 }
181 }, 176 },
182 177
183 //------------------------------------------------------------------------- 178 //-------------------------------------------------------------------------
184 179
185 'renderIfNeeded': function () { 180 'renderOnlyOnce': function () {
186 if (this.isFullyRendered() == false) { 181 if (this.isFullyRendered() == false) {
187 this.render(); 182 this.render();
188 }; 183 };
189 this.updateRendering(); 184 // this.updateRendering();
190 }, 185 },
191 186/*
192 'updateRendering': function () { 187 'updateRendering': function () {
193 MochiKit.Style.showElement(this.getElement('credentialsBody')); 188 MochiKit.Style.showElement(this.getElement('credentialsBody'));
194 MochiKit.Style.hideElement(this.getElement('validating')); 189 MochiKit.Style.hideElement(this.getElement('validating'));
195 190
196 // this.hideAllPanes(); 191 // this.hideAllPanes();
197 MochiKit.Base.map(function (aNode) { MochiKit.Style.hideElement(aNode); }, MochiKit.Selector.findDocElements('div.credentialsBody > div')); 192 MochiKit.Base.map(function (aNode) { MochiKit.Style.hideElement(aNode); }, MochiKit.Selector.findDocElements('div.credentialsBody > div'));
198 if (this.mode() == 'CREDENTIALS') { 193 if (this.mode() == 'CREDENTIALS') {
199 selectedPanel = this.getElement('credentials') 194 selectedPanel = this.getElement('credentials');
195 $(this.getAnchor('credentialsSubmitButton')).button('enable');
200 } else if (this.mode() == 'PIN') { 196 } else if (this.mode() == 'PIN') {
201 selectedPanel = this.getElement('pin') 197 selectedPanel = this.getElement('pin')
202 // this.updatePinDisplay(); 198 // this.updatePinDisplay();
203 } else { 199 } else {
204 throw 'Unhandled login form mode'; 200 throw 'Unhandled login form mode';
205 } 201 }
206 MochiKit.Style.showElement(selectedPanel);
207 202
203 MochiKit.Style.showElement(selectedPanel);
208 MochiKit.Style.hideElement(this.getElement('validating')); 204 MochiKit.Style.hideElement(this.getElement('validating'));
209 }, 205 },
210 206*/
211 'renderSelf': function() { 207/*
208 '_renderSelf': function() {
212 var selectedPanel; 209 var selectedPanel;
213 this.append(this.element(), {tag:'div', id:'login', children:[ 210 this.append(this.element(), {tag:'div', id:'login', children:[
214 {tag:'div', cls:'toolbar', children:[ 211 {tag:'div', cls:'toolbar text-center', children:[
215 {tag:'h1', html:"clipperz"} 212 {tag:'h1', cls:'clipperz', html:"clipperz"}
216 ]}, 213 ]},
217 {tag:'div', cls:'scroll', children:[ 214 {tag:'div', cls:'', children:[
218 //================================================================== 215 //==================================================================
219 {tag:'div', cls:'credentialsMessage', id:this.getId('credentialsMessage'), children:[ 216 {tag:'div', cls:'credentialsMessage', id:this.getId('credentialsMessage'), children:[
220 {tag:'h1', cls:'message', id:this.getId('message'), html:"Message"} 217 {tag:'h1', cls:'message', id:this.getId('message'), html:"Message"}
221 ]}, 218 ]},
222 //================================================================== 219 //==================================================================
223 {tag:'div', cls:'credentialsBody', id:this.getId('credentialsBody'), children:[ 220 {tag:'div', cls:'credentialsBody', id:this.getId('credentialsBody'), children:[
224 //-------------------------------------------------------------- 221 //--------------------------------------------------------------
225 {tag:'div', cls:'pin', id:this.getId('pin'), children:[ 222 {tag:'div', cls:'pin', id:this.getId('pin'), children:[
226 {tag:'form', cls:'scroll', id:this.getId('pinForm'), children:[ 223 {tag:'form', cls:'', id:this.getId('pinForm'), children:[
227 {tag:'ul', cls:'edit rounded', children:[ 224 {tag:'ul', cls:'edit rounded', children:[
228 {tag:'li', children:[{tag:'input', type:'number', name:'PIN', placeholder:"PIN", id:this.getId('PIN') }]}, 225 {tag:'li', children:[{tag:'input', type:'number', name:'PIN', placeholder:"PIN", id:this.getId('PIN') }]},
229 ]}, 226 ]},
230 {tag:'a', href:'#', cls:'greenButton', id:this.getId('pinSubmitButton'), html:"Login"} 227 {tag:'a', href:'#', cls:'greenButton', id:this.getId('pinSubmitButton'), html:"Login"}
231 ]} 228 ]}
232 ]}, 229 ]},
233 //-------------------------------------------------------------- 230 //--------------------------------------------------------------
234 {tag:'div', cls:'credentials', id:this.getId('credentials'), children:[ 231 {tag:'div', cls:'credentials', id:this.getId('credentials'), children:[
235 {tag:'form', cls:'scroll', id:this.getId('credentialsForm'), children:[ 232 {tag:'form', cls:'text-center', id:this.getId('credentialsForm'), children:[
236 {tag:'ul', cls:'edit rounded', children:[ 233 {tag:'fieldset', children:[
237 {tag:'li', children:[{tag:'input', type:'email', name:'name', /*value:'joe',*/ placeholder:"username", id:this.getId('usernameField') }]}, 234 // {tag:'legend', html:"Legend"},
238 {tag:'li', children:[{tag:'input', type:'password', name:'passphrase', /*value:'clipperz',*/placeholder:"passphrase", id:this.getId('passphraseField') }]} 235 {tag:'input', type:'email', name:'name', /*value:'joe',* / placeholder:"username", id:this.getId('usernameField') },
236 // {tag:'span', cls:'help-block', html:"Example of help text here"},
237 {tag:'input', type:'password', name:'passphrase', /*value:'clipperz',* /placeholder:"passphrase", id:this.getId('passphraseField') },
239 ]}, 238 ]},
240 {tag:'a', href:'#', cls:'greenButton', id:this.getId('credentialsSubmitButton'), html:"Login"}
241 // {tag:'input', type:'submit', cls:'greenButton', id:this.getId('credentialsSubmitButton'), value:"Login"}
242 239
240 {tag:'button', cls:'btn btn-primary btn-large', type:'submit', id:this.getId('credentialsSubmitButton'), html:"Login"}
243 ]} 241 ]}
244 ]}, 242 ]},
245 //-------------------------------------------------------------- 243 //--------------------------------------------------------------
246 ]}, 244 ]},
247 //================================================================== 245 //==================================================================
248 {tag:'div', cls:'validating', id:this.getId('validating'), children:[ 246 {tag:'div', cls:'validating', id:this.getId('validating'), children:[
249 {tag:'div', cls:'loading', children:[ 247 {tag:'div', cls:'loading', children:[
250 {tag:'div', cls:'spinner', children:[ 248 {tag:'div', cls:'spinner', children:[
251 {tag:'div', cls:'bar01'}, 249 {tag:'div', cls:'bar01'},
252 {tag:'div', cls:'bar02'}, 250 {tag:'div', cls:'bar02'},
253 {tag:'div', cls:'bar03'}, 251 {tag:'div', cls:'bar03'},
254 {tag:'div', cls:'bar04'}, 252 {tag:'div', cls:'bar04'},
255 {tag:'div', cls:'bar05'}, 253 {tag:'div', cls:'bar05'},
256 {tag:'div', cls:'bar06'}, 254 {tag:'div', cls:'bar06'},
257 {tag:'div', cls:'bar07'}, 255 {tag:'div', cls:'bar07'},
258 {tag:'div', cls:'bar08'}, 256 {tag:'div', cls:'bar08'},
259 {tag:'div', cls:'bar09'}, 257 {tag:'div', cls:'bar09'},
260 {tag:'div', cls:'bar10'}, 258 {tag:'div', cls:'bar10'},
261 {tag:'div', cls:'bar11'}, 259 {tag:'div', cls:'bar11'},
262 {tag:'div', cls:'bar12'} 260 {tag:'div', cls:'bar12'}
263 ]} 261 ]}
264 ]}, 262 ]},
265 {tag:'div', id:this.getId('loadingMessage')}, 263 {tag:'div', id:this.getId('loadingMessage')},
266 {tag:'a', href:'#', cls:'grayButton', id:this.getId('loginCancelButton'), html:"Cancel"} 264 {tag:'a', href:'#', cls:'grayButton', id:this.getId('loginCancelButton'), html:"Cancel"}
267 ]} 265 ]}
268 //================================================================== 266 //==================================================================
269 ]} 267 ]}
270 ]}); 268 ]});
271 269
272 MochiKit.Signal.connect(this.getElement('credentialsForm'), 'onsubmit', this, 'submitCredentialsHandler'); 270 MochiKit.Signal.connect(this.getElement('credentialsForm'), 'onsubmit', this, 'submitCredentialsHandler');
273 MochiKit.Signal.connect(this.getElement('credentialsSubmitButton'), 'onclick', this, 'submitCredentialsHandler'); 271 MochiKit.Signal.connect(this.getElement('credentialsSubmitButton'), 'onclick', this, 'submitCredentialsHandler');
274 272
275 MochiKit.Signal.connect(this.getElement('pinForm'), 'onsubmit', this, 'submitPinHandler'); 273 MochiKit.Signal.connect(this.getElement('pinForm'), 'onsubmit', this, 'submitPinHandler');
276 MochiKit.Signal.connect(this.getElement('pinSubmitButton'), 'onclick', this, 'submitPinHandler'); 274 MochiKit.Signal.connect(this.getElement('pinSubmitButton'), 'onclick', this, 'submitPinHandler');
277 275
278 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'initProgress', this, 'initProgressHandle'); 276 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'initProgress', this, 'initProgressHandle');
279 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'updateProgress',this, 'updateProgressHandle'); 277 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'updateProgress',this, 'updateProgressHandle');
280 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'advanceProgress',this, 'advanceProgressHandle'); 278 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'advanceProgress',this, 'advanceProgressHandle');
281 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'progressDone', this, 'progressDoneHandle'); 279 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'progressDone', this, 'progressDoneHandle');
282 }, 280 },
281*/
282 'renderSelf': function() {
283 if (this.isFullyRendered() == false) {
284 this.append(this.element(), //[
285 // {tag:'div', 'data-role':'header', children:[
286 // {tag:'h1', html:'clipperz'}
287 // ]},
288 // {tag:'div', 'data-role':'content', children:[
289 {tag:'form', id:this.getId('credentialsForm'), children:[
290 {tag:'div', 'data-role':'fieldcontain', cls:'ui-hide-label', children:[
291 {tag:'label', 'for':'name', cls:'ui-input-text', html:"username"},
292 {tag:'input', type:'email', name:'name', /*value:'joe',*/ placeholder:"username", id:this.getId('usernameField') },
293 {tag:'label', 'for':'passphrase', cls:'ui-input-text', html:"passphrase"},
294 {tag:'input', type:'password', name:'passphrase', /*value:'clipperz',*/placeholder:"passphrase", id:this.getId('passphraseField') }
295 ]},
296 {tag:'button', type:'submit', id:this.getId('credentialsSubmitButton'), html:"login"}
297 ]}
298 // ]}
299 // ]
300 );
301
302 MochiKit.Signal.connect(this.getElement('credentialsForm'), 'onsubmit', this, 'submitCredentialsHandler');
303 MochiKit.Signal.connect(this.getElement('credentialsSubmitButton'), 'onclick', this, 'submitCredentialsHandler');
304 }
305 },
283 306
284 //------------------------------------------------------------------------- 307 //-------------------------------------------------------------------------
285 308
286 'submitPinHandler': function (anEvent) { 309 'submitPinHandler': function (anEvent) {
287 varpin; 310 varpin;
288 311
289 this.setMessage(null); 312 this.setMessage(null);
290 pin = this.getElement('PIN').value; 313 pin = this.getElement('PIN').value;
291 // $(this.getAnchor('PIN')).blur(); 314 $(this.getAnchor('PIN')).blur();
292 this.getElement('PIN').blur(); 315 // this.getElement('PIN').blur();
293 316
294 credentials = Clipperz.PM.PIN.credentialsWithPIN(pin); 317 credentials = Clipperz.PM.PIN.credentialsWithPIN(pin);
295 this.loginWithCredentials(credentials); 318 this.loginWithCredentials(credentials);
296 }, 319 },
297 320
298 'submitCredentialsHandler': function (anEvent) { 321 'submitCredentialsHandler': function (anEvent) {
299 varcredentials; 322 varcredentials;
300 323
301 this.setMessage(null); 324 anEvent.preventDefault();
325
326 // this.setMessage(null);
327 $(this.getAnchor('usernameField')).blur();
328 $(this.getAnchor('passphraseField')).blur();
329 $(this.getAnchor('credentialsSubmitButton')).button('disable');
302 330
303 credentials = {}; 331 credentials = {};
304 credentials['username'] = this.getElement('usernameField').value; 332 credentials['username'] = this.getElement('usernameField').value;
305 credentials['passphrase'] = this.getElement('passphraseField').value; 333 credentials['passphrase'] = this.getElement('passphraseField').value;
306 // $(this.getAnchor('passphraseField')).blur();
307 this.getElement('passphraseField').blur();
308 334
309 this.loginWithCredentials(credentials); 335 this.loginWithCredentials(credentials);
310 }, 336 },
311 337
312 //------------------------------------------------------------------------- 338 //-------------------------------------------------------------------------
313 339
314 'loginWithCredentials': function (someCredentials) { 340 'loginWithCredentials': function (someCredentials) {
315 varargs; 341 varargs;
316 342
317 args = {}; 343 args = {};
318 args['credentials'] = someCredentials; 344 args['credentials'] = someCredentials;
319 args['errorCallback'] = this.errorCallback(); 345 args['errorCallback'] = this.errorCallback();
320 346
321 MochiKit.Style.hideElement(this.getElement('credentialsBody')); 347 // MochiKit.Style.hideElement(this.getElement('credentialsBody'));
322 MochiKit.Style.showElement(this.getElement('validating')); 348 // MochiKit.Style.showElement(this.getElement('validating'));
323 349
324 MochiKit.Async.callLater(0.1, this.callback(), args); 350 MochiKit.Async.callLater(0.1, this.callback(), args);
325 }, 351 },
326 352
327 //------------------------------------------------------------------------- 353 //-------------------------------------------------------------------------
328 354
329 'initProgressHandle': function (anEvent) { 355 'initProgressHandle': function (anEvent) {
330 this._steps = anEvent['steps']; 356 this._steps = anEvent['steps'];
331 this._actualSteps = 0; 357 this._actualSteps = 0;
332 }, 358 },
333 359
334 'updateProgressHandle': function (anEvent) { 360 'updateProgressHandle': function (anEvent) {
335 this._steps += anEvent['extraSteps']; 361 this._steps += anEvent['extraSteps'];
336 }, 362 },
337 363
338 'advanceProgressHandle': function (anEvent) { 364 'advanceProgressHandle': function (anEvent) {
339 this._actualSteps ++; 365 this._actualSteps ++;
340 }, 366 },
341 367
342 'progressDoneHandle': function (anEvent) { 368 'progressDoneHandle': function (anEvent) {
343 }, 369 },
344 370
345 //------------------------------------------------------------------------- 371 //-------------------------------------------------------------------------
346 __syntaxFix__: "syntax fix" 372 __syntaxFix__: "syntax fix"
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/Overlay.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/Overlay.js
new file mode 100644
index 0000000..da08d0f
--- a/dev/null
+++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/Overlay.js
@@ -0,0 +1,136 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components');
25
26Clipperz.PM.UI.Mobile.Components.Overlay = function(args) {
27 args = args || {};
28
29 this._defaultDelay = 2;
30
31 Clipperz.PM.UI.Mobile.Components.Overlay.superclass.constructor.apply(this, arguments);
32
33 this.render();
34 MochiKit.Style.hideElement(this.element());
35
36 return this;
37}
38
39//=============================================================================
40
41Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.Overlay, Clipperz.PM.UI.Mobile.Components.BaseComponent, {
42
43 //-------------------------------------------------------------------------
44
45 'toString': function () {
46 return "Clipperz.PM.UI.Mobile.Components.Overlay component";
47 },
48
49 //-------------------------------------------------------------------------
50
51 'show': function (aMessage) {
52 this.resetStatus();
53 this.setMessage(aMessage);
54 MochiKit.DOM.removeElementClass(this.element(), 'ios-overlay-hide');
55 MochiKit.DOM.addElementClass(this.element(), 'ios-overlay-show');
56 },
57
58 'done': function (aMessage, aDelayBeforeHiding) {
59 this.completed(this.showDoneIcon, aMessage, aDelayBeforeHiding);
60 },
61
62 'failed': function (aMessage, aDelayBeforeHiding) {
63 this.completed(this.showFailIcon, aMessage, aDelayBeforeHiding);
64 },
65
66 //-------------------------------------------------------------------------
67
68 'resetStatus': function () {
69 MochiKit.Style.showElement(this.element());
70 MochiKit.Style.showElement(this.getElement('spinner'));
71 MochiKit.Style.hideElement(this.getElement('done'));
72 MochiKit.Style.hideElement(this.getElement('failed'));
73 },
74
75 'setMessage': function (aMessage) {
76 if (typeof(aMessage) != 'undefined') {
77 this.getElement('title').innerHTML = aMessage;
78 }
79 },
80
81 'completed': function (aFunctionToShowResult, aMessage, aDelayBeforeHiding) {
82 var delay = aDelayBeforeHiding || this.defaultDelay();
83
84 this.hideSpinner();
85 MochiKit.Base.bind(aFunctionToShowResult, this)();
86 this.setMessage(aMessage);
87
88 MochiKit.Async.callLater(delay, MochiKit.Base.bind(this.hide, this))
89 },
90
91 'hide': function () {
92 MochiKit.DOM.removeElementClass(this.element(), 'ios-overlay-show');
93 MochiKit.DOM.addElementClass(this.element(), 'ios-overlay-hide');
94 MochiKit.Async.callLater(1, MochiKit.Style.hideElement, this.element());
95 },
96
97 'hideSpinner': function () {
98 MochiKit.Style.hideElement(this.getElement('spinner'));
99 },
100
101 'showDoneIcon': function () {
102 MochiKit.Style.showElement(this.getElement('done'));
103 },
104
105 'showFailIcon': function () {
106 MochiKit.Style.showElement(this.getElement('failed'));
107 },
108
109 //-------------------------------------------------------------------------
110
111 'defaultDelay': function () {
112 return this._defaultDelay;
113 },
114
115 //-------------------------------------------------------------------------
116
117 'renderSelf': function () {
118 this.setElement(Clipperz.DOM.Helper.append(MochiKit.DOM.currentDocument().body,
119 {tag:'div', id:'ui-ios-overlay', cls:'ui-ios-overlay', children:[
120 {tag:'div', cls:'spinner', id:this.getId('spinner'), children:[
121 {tag:'div', cls:'bar01'}, {tag:'div', cls:'bar02'}, {tag:'div', cls:'bar03'}, {tag:'div', cls:'bar04'}, {tag:'div', cls:'bar05'}, {tag:'div', cls:'bar06'}, {tag:'div', cls:'bar07'}, {tag:'div', cls:'bar08'}, {tag:'div', cls:'bar09'}, {tag:'div', cls:'bar10'}, {tag:'div', cls:'bar11'}, {tag:'div', cls:'bar12'}
122 ]},
123
124 // {tag:'span', cls:'icon', id:this.getId('done'), html:'&#xe000'},
125 {tag:'span', cls:'icon', id:this.getId('done'), html:'done'},
126 // {tag:'span', cls:'icon', id:this.getId('failed'), html:'&#xe001'},
127 {tag:'span', cls:'icon', id:this.getId('failed'), html:'failed'},
128
129 {tag:'span', cls:'title', id:this.getId('title'), html:""}
130 ]}
131 ));
132 },
133
134 //-------------------------------------------------------------------------
135 __syntaxFix__: "syntax fix"
136});
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/Preferences.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/Preferences.js
new file mode 100644
index 0000000..839069a
--- a/dev/null
+++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Components/Preferences.js
@@ -0,0 +1,77 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Components');
25
26Clipperz.PM.UI.Mobile.Components.Preferences = function(args) {
27 args = args || {};
28
29 Clipperz.PM.UI.Mobile.Components.Preferences.superclass.constructor.apply(this, arguments);
30
31 this.render();
32
33 return this;
34}
35
36//=============================================================================
37
38Clipperz.Base.extend(Clipperz.PM.UI.Mobile.Components.Preferences, Clipperz.PM.UI.Mobile.Components.BaseComponent, {
39
40 //-------------------------------------------------------------------------
41
42 'toString': function () {
43 return "Clipperz.PM.UI.Mobile.Components.Preferences component";
44 },
45
46 //-------------------------------------------------------------------------
47
48 'renderSelf': function () {
49 // varpageElement;
50 varheaderElement;
51 var titleElement;
52
53 // pageElement = this.element().parentNode;
54 // MochiKit.DOM.updateNodeAttributes(pageElement, {'data-add-back-btn': 'true'})
55 headerElement = MochiKit.Selector.findChildElements(this.element().parentNode, ['div[data-role=header]'])[0];
56 // headerElement.innerHTML = "Preferences";
57 titleElement = MochiKit.Selector.findChildElements(headerElement, ['h1'])[0];
58 titleElement.innerHTML = "Preferences";
59 this.append(this.element(),
60 {tag:'div', id:this.getId('listBox'), children:[
61 {tag:'h1', html:"Preferences"}
62 ]}
63 );
64
65 this.append(headerElement, [
66 //'data-direction':'reverse', 'data-rel':'back',
67 {tag:'a', href:"#", id:this.getId('back'), cls:'ui-btn-left', html:"back" },
68 {tag:'a', href:"#", id:this.getId('save'), cls:'ui-btn-right', html:"save" }
69 ]);
70
71 MochiKit.Signal.connect(this.getElement('back'), 'onclick', MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'back'));
72 MochiKit.Signal.connect(this.getElement('save'), 'onclick', MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'savePreferences'));
73 },
74
75 //=========================================================================
76 __syntaxFix__: "syntax fix"
77});
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js
index 9951f44..245874a 100644
--- a/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js
+++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/Controllers/MainController.js
@@ -6,253 +6,220 @@ This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please 6For further information about its features and functionalities please
7refer to http://www.clipperz.com. 7refer to http://www.clipperz.com.
8 8
9* Clipperz is free software: you can redistribute it and/or modify it 9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published 10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or 11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version. 12 (at your option) any later version.
13 13
14* Clipperz is distributed in the hope that it will be useful, but 14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of 15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details. 17 See the GNU Affero General Public License for more details.
18 18
19* You should have received a copy of the GNU Affero General Public 19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/. 20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21 21
22*/ 22*/
23 23
24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Controllers'); 24Clipperz.Base.module('Clipperz.PM.UI.Mobile.Controllers');
25 25
26Clipperz.PM.UI.Mobile.Controllers.MainController = function() { 26Clipperz.PM.UI.Mobile.Controllers.MainController = function() {
27 // this._jQTouch = null; 27 // this._jQTouch = null;
28 this._user = null; 28 this._user = null;
29 this._proxy = null; 29 this._proxy = null;
30 // this._overlay = null;
30 this._loginForm = null; 31 this._loginForm = null;
31 this._cardList = null; 32 this._cardList = null;
32 this._cardDetail= null; 33 this._cardDetail= null;
34 this._preferences= null;
33 35
34 return this; 36 return this;
35} 37}
36 38
37MochiKit.Base.update(Clipperz.PM.UI.Mobile.Controllers.MainController.prototype, { 39MochiKit.Base.update(Clipperz.PM.UI.Mobile.Controllers.MainController.prototype, {
38 40
39 'toString': function () { 41 'toString': function () {
40 return "Clipperz.PM.UI.Mobile.Controllers.MainController"; 42 return "Clipperz.PM.UI.Mobile.Controllers.MainController";
41 }, 43 },
42 44
43 //------------------------------------------------------------------------- 45 //-------------------------------------------------------------------------
44 46
45 'user': function () { 47 'user': function () {
46 return this._user; 48 return this._user;
47 }, 49 },
48 50
49 'setUser': function (aValue) { 51 'setUser': function (aValue) {
50 this._user = aValue; 52 this._user = aValue;
51 }, 53 },
52 54
53 //-------------------------------------------------------------------------
54/*
55 'jQTouch': function () {
56 return this._jQTouch;
57 },
58
59 'setJQTouch': function (aValue) {
60 this._jQTouch = aValue;
61 },
62*/
63 //========================================================================= 55 //=========================================================================
64 56
65 'run': function () { 57 'run': function () {
66 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'doLogin', MochiKit.Base.method(this, 'doLogin')); 58 vardefaultPageStructure;
67 Clipperz.DOM.Helper.overwrite(MochiKit.DOM.currentDocument().body, {tag:'div', id:'jqt', children:[
68 {tag:'div', id:'loginForm'},
69 {tag:'div', id:'cardList'},
70 {tag:'div', id:'cardDetail'},
71 {tag:'div', id:'preferences'}
72 ]});
73 59
60 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'doLogin', MochiKit.Base.method(this, 'doLogin'));
61 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'showPreferences',MochiKit.Base.method(this, 'showPreferences'));
62
63 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'savePreferences',MochiKit.Base.method(this, 'savePreferences'));
64 MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, 'back', MochiKit.Base.method(this, 'back'));
65
66 defaultPageStructure = [
67 {tag:'div', 'data-role':'header', 'data-position':'fixed', children:[
68 {tag:'h1', html:'clipperz'}
69 ]},
70 {tag:'div', 'data-role':'content'}
71 ];
72 Clipperz.DOM.Helper.insertAfter(MochiKit.DOM.getElement('loadingPage'), [
73 {tag:'div', 'data-role':'page', id:'loginPage', children:defaultPageStructure},
74 {tag:'div', 'data-role':'page', id:'cardListPage', children:defaultPageStructure},
75 {tag:'div', 'data-role':'page', id:'cardDetailPage',children:defaultPageStructure},
76 {tag:'div', 'data-role':'page', id:'preferencesPage',children:defaultPageStructure}
77 ])
78 // $.mobile.initializePage();
74 this.showLoginForm(); 79 this.showLoginForm();
75
76 // this.initjQTouch();
77
78
79 // this.showAddToHomeScreenBaloon();
80 // this.selectInitialProxy();
81 }, 80 },
82/*
83 'initjQTouch': function () {
84 var jqt;
85
86 jqt = new $.jQTouch({
87 icon: 'data:image/png;charset=utf-8;base64,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',
88 // icon4: 'jqtouch4.png',
89 // startupScreen: null, //Pass a string path to a 320px x 460px startup screen for full screen apps.
90 statusBar: 'black-translucent', //Styles the status bar when running as a fullscreen app. Other options are `default`, `black`, and `black-translucent`.
91 // addGlossToIcon: true, //Set to 'false' to prevent automatic glossy button effect on icon.
92 preloadImages: false, //Pass an array of image paths to load them before page loads. Ex: `['images/link_over.png', 'images/link_select.png']`
93 fixedViewport: true, //Removes the user's ability to scale the page. Ensures the site behaves more like an application.
94 // fullScreen: true, //The website will become a fullscreen application when saved to a user's home screen. Set to `false` to disable.
95 // fullScreenClass: 'fullscreen' //Adds a class to the `<body>` when running in full-screen mode, to allow for easy detection and styling. Set to `false` to disable.
96 // themeSelectionSelector: '#jqt #themes ul', //???
97
98 // useAnimations: true, //Set to `false` to disable all animations.
99 // useFastTouch: true, //Removes ~350ms onClick delay when tapping a link (use in conjunction with the .tap() event) **Experimental**
100 // useTouchScroll: true, //Adds support for iOS5 scrolling. Set to false to disable. **Experimental**
101
102 cacheGetRequests: false, //Automatically caches GET requests, so subsequent taps reference the pre-loaded views. (default: true)
103
104 // backSelector: '.back, .cancel, .goback', //A CSS selector for back links/buttons. When clicked, the page history goes back one, automatically reversing whichever entrance animation was used.
105
106 // cubeSelector: '.cube', //Link selector for a cube animation.
107 // dissolveSelector: '.dissolve', //Link selector for a dissolve animation.
108 // fadeSelector: '.fade', //Link selector for a fade animation.
109 // flipSelector: '.flip', //Link selector for a 3d flip animation.
110 formSelector: null, //Sets which forms are automatically submitted via Ajax. (default: 'form')
111 // popSelector: '.pop', //Link selector for a pop animation. (default: '.pop')
112 // slideSelector: 'body > * > ul li a', //Link selector for the default slide-left transition. By default applies to all links within an unordered list. Accepts any jQuery-capable selector `'li &gt; a, a:not(.dontslide)'`, etc. (default: 'body > * > ul li a')
113 // slideupSelector: '.slideup', //Link selector for a slide up animation. (default: '.slideup')
114 // submitSelector: '.submit', //Selector which, when clicked, will submit its parent form (and close keyboard if open). (default: '.submit')
115 // swapSelector: '.swap', //Link selector for 3d swap animation. (default: '.swap')
116 // touchSelector: 'a, .touch', //Selector for items which are automatically given expanded touch events. This makes ordinary links more responsive and provides trigger events like `swipe` (default: 'a, .touch')
117
118 debug: false
119 });
120 81
121 this.setJQTouch(jqt);
122 },
123*/
124 //========================================================================= 82 //=========================================================================
125 83
126 'showAddToHomeScreenBaloon': function () { 84 'showAddToHomeScreenBaloon': function () {
127 }, 85 },
128 86
129 //------------------------------------------------------------------------- 87 //-------------------------------------------------------------------------
130 88
131 'selectInitialProxy': function () { 89 'selectInitialProxy': function () {
132 if (this.isOnline()) { 90 if (this.isOnline()) {
133 this._proxy = Clipperz.PM.Proxy.defaultProxy; 91 this._proxy = Clipperz.PM.Proxy.defaultProxy;
134 } else { 92 } else {
135 if (this.hasLocalData()) { 93 if (this.hasLocalData()) {
136 this._proxy = new Clipperz.PM.Proxy.OfflineCache({'shouldPayTolls':false}); 94 this._proxy = new Clipperz.PM.Proxy.OfflineCache({'shouldPayTolls':false});
137 } else { 95 } else {
138 this.showOfflineError(); 96 this.showOfflineError();
139 } 97 }
140 } 98 }
141 }, 99 },
142 100
143 //------------------------------------------------------------------------- 101 //-------------------------------------------------------------------------
144 102
145 'showLoginForm': function (args) { 103 'showLoginForm': function (args) {
146 args = args || {}; 104 args = args || {};
147 105
148 args['callback'] = MochiKit.Base.method(this, 'doLogin'); 106 args['callback'] = MochiKit.Base.method(this, 'doLogin');
149 107
150 if (Clipperz.PM.PIN.isSet()) { 108 if (Clipperz.PM.PIN.isSet()) {
151 args['errorCallback'] = MochiKit.Base.method(this, 'handleFailedPinLogin'); 109 args['errorCallback'] = MochiKit.Base.method(this, 'handleFailedPinLogin');
152 this.loginForm().showPinLogin(args); 110 this.loginForm().setMode('PIN');
111 // this.loginForm().showPinLogin(args);
153 } else { 112 } else {
154 args['errorCallback'] = MochiKit.Base.method(this, 'handleFailedCredentialsLogin'); 113 args['errorCallback'] = MochiKit.Base.method(this, 'handleFailedCredentialsLogin');
155 this.loginForm().showCredentialsLogin(args); 114 this.loginForm().setMode('CREDENTIALS');
115 //this.loginForm().showCredentialsLogin(args);
156 } 116 }
117 this.loginForm().show(args);
118
119 // MochiKit.Async.callLater(0.1, $.mobile.changePage, $('#loginPage'), {changeHash:false, showLoadMsg:false, role:'page', fromPage:$('#loadingPage'), 'data-transition':'slide'});
120 MochiKit.Async.callLater(0.1, $.mobile.changePage, $('#loginPage'));
157 }, 121 },
158 122
159 //......................................................................... 123 //.........................................................................
160 124
161 'handleFailedCredentialsLogin': function () { 125 'handleFailedCredentialsLogin': function () {
126 this.overlay().failed("Failed login", 1);
162 this.showLoginForm({'previousFailedAttempt':'LOGIN'}); 127 this.showLoginForm({'previousFailedAttempt':'LOGIN'});
163 }, 128 },
164 129
165 //......................................................................... 130 //.........................................................................
166 131
167 'handleFailedPinLogin': function () { 132 'handleFailedPinLogin': function () {
168 varfailedAttempts; 133 varfailedAttempts;
169 varstatus; 134 varstatus;
170 135
136 this.overlay().failed("Failed login", 1);
171 failedAttempts = Clipperz.PM.PIN.recordFailedAttempt(); 137 failedAttempts = Clipperz.PM.PIN.recordFailedAttempt();
172 this.showLoginForm({'previousFailedAttempt':'PIN', 'failedAttempts': failedAttempts}); 138 this.showLoginForm({'previousFailedAttempt':'PIN', 'failedAttempts': failedAttempts});
173 }, 139 },
174 140
175 //------------------------------------------------------------------------- 141 //-------------------------------------------------------------------------
176 142
177 'doLogin': function (someArgs) { 143 'doLogin': function (someArgs) {
178 var deferredResult; 144 var deferredResult;
179 var credentials; 145 var credentials;
180 var errorCallback; 146 var errorCallback;
181 var user; 147 var user;
182 var getPassphraseDelegate; 148 var getPassphraseDelegate;
183 149
184 credentials = someArgs['credentials']; 150 credentials = someArgs['credentials'];
185 errorCallback = someArgs['errorCallback'] || MochiKit.Base.noop; 151 errorCallback = someArgs['errorCallback'] || MochiKit.Base.noop;
186 152
153 this.overlay().show("logging in");
187 getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase); 154 getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase);
188 user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate}); 155 user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate});
189 156
190 deferredResult = new Clipperz.Async.Deferred('MainController.doLogin', {trace:false}); 157 deferredResult = new Clipperz.Async.Deferred('MainController.doLogin', {trace:false});
191 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress', {'steps':4}); 158 deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'initProgress', {'steps':4});
192 deferredResult.addCallback(MochiKit.Async.wait, 0.1); 159 deferredResult.addCallback(MochiKit.Async.wait, 0.1);
193 deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection'); 160 deferredResult.addMethod(Clipperz.Crypto.PRNG.defaultRandomGenerator(), 'deferredEntropyCollection');
194 deferredResult.addMethod(user, 'login'); 161 deferredResult.addMethod(user, 'login');
195 deferredResult.addCallbacks( 162 deferredResult.addCallbacks(
196 MochiKit.Base.method(this, 'processSuccessfulLogin', user), 163 MochiKit.Base.method(this, 'processSuccessfulLogin', user),
197 errorCallback 164 errorCallback
198 ); 165 );
199 deferredResult.callback(); 166 deferredResult.callback();
200 167
201 return deferredResult; 168 return deferredResult;
202 }, 169 },
203 170
204 //.......................................................................... 171 //..........................................................................
205 172
206 'processSuccessfulLogin': function (aUser) { 173 'processSuccessfulLogin': function (aUser) {
207 var deferredResult; 174 var deferredResult;
208 175
209 deferredResult = new Clipperz.Async.Deferred('MainController.processSuccessfulLogin', {trace:false}); 176 deferredResult = new Clipperz.Async.Deferred('MainController.processSuccessfulLogin', {trace:false});
210 deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount'); 177 deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount');
178 deferredResult.addMethod(this.overlay(), 'done', "", 1);
211 // deferredResult.addMethod(this, 'removeLoginForm'); 179 // deferredResult.addMethod(this, 'removeLoginForm');
212 deferredResult.addMethod(this, 'setUser', aUser); 180 deferredResult.addMethod(this, 'setUser', aUser);
213 deferredResult.addMethod(this, 'setupApplication'); 181 deferredResult.addMethod(this, 'setupApplication');
214 deferredResult.addMethod(this, 'runApplication'); 182 deferredResult.addMethod(this, 'runApplication');
215 deferredResult.callback(); 183 deferredResult.callback();
216 184
217 return deferredResult; 185 return deferredResult;
218 }, 186 },
219 187
220 //------------------------------------------------------------------------- 188 //-------------------------------------------------------------------------
221 189
222 'setupApplication': function () { 190 'setupApplication': function () {
223 vardeferredResult; 191 vardeferredResult;
224 192
225 deferredResult = new Clipperz.Async.Deferred("MainController.setupApplication", {trace:false}); 193 deferredResult = new Clipperz.Async.Deferred("MainController.setupApplication", {trace:false});
226 deferredResult.addMethod(this, 'welcomeFirstTimeUser'); 194 deferredResult.addMethod(this, 'welcomeFirstTimeUser');
227 deferredResult.addMethod(this, 'showPaymentReminder'); 195 deferredResult.addMethod(this, 'showPaymentReminder');
228 deferredResult.addMethod(this, 'copyDataLocally'); 196 deferredResult.addMethod(this, 'copyDataLocally');
229 deferredResult.callback(arguments); 197 deferredResult.callback(arguments);
230 198
231 return deferredResult; 199 return deferredResult;
232 }, 200 },
233 201
234
235 //.......................................................................... 202 //..........................................................................
236 203
237 'isFirstTimeUser': function () { 204 'isFirstTimeUser': function () {
238 return false; 205 return false;
239 }, 206 },
240 207
241 'welcomeFirstTimeUser': function () { 208 'welcomeFirstTimeUser': function () {
242 vardeferredResult; 209 vardeferredResult;
243 210
244 deferredResult = new Clipperz.Async.Deferred('MainController.welcomeFirstTimeUser', {trace:false}); 211 deferredResult = new Clipperz.Async.Deferred('MainController.welcomeFirstTimeUser', {trace:false});
245 212
246 if (this.isFirstTimeUser()) { 213 if (this.isFirstTimeUser()) {
247 deferredResult.addCallback(function () { Clipperz.log("--> welcome"); }); 214 deferredResult.addCallback(function () { Clipperz.log("--> welcome"); });
248 } 215 }
249 deferredResult.callback(); 216 deferredResult.callback();
250 217
251 return deferredResult; 218 return deferredResult;
252 }, 219 },
253 220
254 //.......................................................................... 221 //..........................................................................
255 222
256 'shouldShowPaymentReminder': function () { 223 'shouldShowPaymentReminder': function () {
257 return true; 224 return true;
258 }, 225 },
@@ -274,108 +241,150 @@ MochiKit.Base.update(Clipperz.PM.UI.Mobile.Controllers.MainController.prototype,
274 241
275 'canCopyDataLocally': function () { 242 'canCopyDataLocally': function () {
276 return false; 243 return false;
277 }, 244 },
278 245
279 'copyDataLocally': function () { 246 'copyDataLocally': function () {
280 vardeferredResult; 247 vardeferredResult;
281 248
282 deferredResult = new Clipperz.Async.Deferred('MainController.copyDataLocally', {trace:false}); 249 deferredResult = new Clipperz.Async.Deferred('MainController.copyDataLocally', {trace:false});
283 250
284 if (this.canCopyDataLocally()) { 251 if (this.canCopyDataLocally()) {
285 deferredResult.addCallback(function () { Clipperz.log("--> copy data locally"); }); 252 deferredResult.addCallback(function () { Clipperz.log("--> copy data locally"); });
286 } 253 }
287 deferredResult.callback(); 254 deferredResult.callback();
288 255
289 return deferredResult; 256 return deferredResult;
290 257
291 }, 258 },
292 259
293 //------------------------------------------------------------------------- 260 //-------------------------------------------------------------------------
294 261
295 'runApplication': function () { 262 'runApplication': function () {
296 var deferredResult; 263 var deferredResult;
297 264
298 deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:true}); 265 deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false});
266 deferredResult.addMethod(this, 'showCardListPage');
267 deferredResult.addCallback(MochiKit.Async.wait, 0.5);
299 deferredResult.addMethod(this.user(), 'getRecords'); 268 deferredResult.addMethod(this.user(), 'getRecords');
300 deferredResult.addMethod(this, 'showCards'); 269 // deferredResult.addMethod(this, 'showCards');
270 deferredResult.addMethod(this.cardList(), 'showCards');
301 deferredResult.callback(); 271 deferredResult.callback();
302 272
303 return deferredResult; 273 return deferredResult;
304 }, 274 },
305 275
306 //========================================================================= 276 //=========================================================================
307 277
308 'showOfflineError': function (anException) { 278 'showOfflineError': function (anException) {
309 alert("Error: " + anException); 279 alert("Error: " + anException);
310 throw anException; 280 throw anException;
311 }, 281 },
312 282
313 //========================================================================= 283 //=========================================================================
314 284
315 'isOnline': function() { 285 'isOnline': function() {
316 return navigator.onLine; 286 return navigator.onLine;
317 }, 287 },
318 288
319 'hasLocalData': function() { 289 'hasLocalData': function() {
320 return false; 290 return false;
321 }, 291 },
322 292
323 //========================================================================= 293 //=========================================================================
324 294
295 'overlay': function () {
296 if (this._overlay == null) {
297 this._overlay = new Clipperz.PM.UI.Mobile.Components.Overlay();
298 }
299
300 return this._overlay;
301 },
302
303 //-------------------------------------------------------------------------
304
305 'contentElementForPage': function (aPageName) {
306 return MochiKit.Selector.findDocElements('#' + aPageName + ' div[data-role="content"]')[0];
307 },
308
325 'loginForm': function() { 309 'loginForm': function() {
326 if (this._loginForm == null) { 310 if (this._loginForm == null) {
327 this._loginForm = new Clipperz.PM.UI.Mobile.Components.LoginForm({element:MochiKit.DOM.getElement('loginForm')}); 311 this._loginForm = new Clipperz.PM.UI.Mobile.Components.LoginForm({element:this.contentElementForPage('loginPage')});
328 } 312 }
329 313
330 return this._loginForm; 314 return this._loginForm;
331 }, 315 },
332 316
333 'removeLoginForm': function () { 317 'removeLoginForm': function () {
334 if (this._loginForm != null) { 318 if (this._loginForm != null) {
335 this._loginForm.remove(); 319 this._loginForm.remove();
336 this._loginForm = null; 320 this._loginForm = null;
337 } 321 }
338 }, 322 },
339 323
340 //------------------------------------------------------------------------- 324 //-------------------------------------------------------------------------
341 325
342 'cardList': function () { 326 'cardList': function () {
343 if (this._cardList == null) { 327 if (this._cardList == null) {
344 this._cardList = new Clipperz.PM.UI.Mobile.Components.CardList({element:MochiKit.DOM.getElement('cardList')}); 328 this._cardList = new Clipperz.PM.UI.Mobile.Components.CardList({element:this.contentElementForPage('cardListPage')});
345 MochiKit.Signal.connect(this._cardList, 'selectedCard', this, 'selectCardHandler'); 329 MochiKit.Signal.connect(this._cardList, 'selectedCard', this, 'selectCardHandler');
346 } 330 }
347 331
348 return this._cardList; 332 return this._cardList;
349 }, 333 },
350 334
351 'showCards': function (someCards) { 335 'showCardListPage': function (someCards) {
352 this.cardList().showCards(someCards); 336 // this.cardList().render();
353 // this.jQTouch().goTo('#cardList', 'slideleft'); 337 $.mobile.changePage($('#cardListPage'), {'transition':'flow'}); //slide, flow, pop
354 }, 338 },
355 339
356 //------------------------------------------------------------------------- 340 //-------------------------------------------------------------------------
357 341
358 'cardDetail': function () { 342 'cardDetail': function () {
359 if (this._cardDetail == null) { 343 if (this._cardDetail == null) {
360 this._cardDetail = new Clipperz.PM.UI.Mobile.Components.CardDetail({element:MochiKit.DOM.getElement('cardDetail')}); 344 this._cardDetail = new Clipperz.PM.UI.Mobile.Components.CardDetail({element:MochiKit.DOM.getElement('cardDetail')});
361 } 345 }
362 346
363 return this._cardDetail; 347 return this._cardDetail;
364 }, 348 },
365 349
366 'selectCardHandler': function (aCardReference) { 350 'selectCardHandler': function (aCardReference) {
367 var deferredResult; 351 var deferredResult;
368 352
369 deferredResult = new Clipperz.Async.Deferred("MainController.selectCardHandler", {trace:true}); 353 deferredResult = new Clipperz.Async.Deferred("MainController.selectCardHandler", {trace:true});
370 deferredResult.addMethod(this.cardDetail(), 'render'); 354 deferredResult.addMethod(this.cardDetail(), 'render');
371 // deferredResult.addMethod(this.jQTouch(), 'goTo', '#cardDetail', 'slideleft');
372 deferredResult.addMethod(this.user(), 'getRecord', aCardReference); 355 deferredResult.addMethod(this.user(), 'getRecord', aCardReference);
373 deferredResult.addMethod(this.cardDetail(), 'showCard'); 356 deferredResult.addMethod(this.cardDetail(), 'showCard');
374 deferredResult.callback(); 357 deferredResult.callback();
375 358
376 return deferredResult; 359 return deferredResult;
377 }, 360 },
378 361
379 //========================================================================= 362 //=========================================================================
363
364 'preferences': function () {
365 if (this._preferences == null) {
366 this._preferences = new Clipperz.PM.UI.Mobile.Components.Preferences({element:this.contentElementForPage('preferencesPage')});
367 }
368
369 return this._preferences;
370 },
371
372 'showPreferences': function (anEvent) {
373//console.log("MainController.showPreferences", anEvent);
374 this.preferences();
375 // MochiKit.Async.callLater(0.1, $.mobile.changePage, $('#preferencesPage'), {transition:'flip'});
376 $.mobile.changePage($('#preferencesPage'), {transition:'flip'});
377 },
378
379 'savePreferences': function (anEvent) {
380console.log("MainController.savePreferences", anEvent);
381 },
382
383 'back': function (anEvent) {
384 // MochiKit.Async.callLater(0.1, $.mobile.changePage, $('#cardListPage'), {transition:'flip', reverse:true});
385 $.mobile.changePage($('#cardListPage'), {transition:'flip', reverse:true});
386 },
387
388 //=========================================================================
380 __syntaxFix__: "syntax fix" 389 __syntaxFix__: "syntax fix"
381}); 390});
diff --git a/frontend/gamma/js/Clipperz/PM/UI/Mobile/CustomizeJQueryMobile.js b/frontend/gamma/js/Clipperz/PM/UI/Mobile/CustomizeJQueryMobile.js
new file mode 100644
index 0000000..68d8a5b
--- a/dev/null
+++ b/frontend/gamma/js/Clipperz/PM/UI/Mobile/CustomizeJQueryMobile.js
@@ -0,0 +1,50 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24$(document).on("mobileinit", function() {
25 $.extend($.mobile, {
26 // activeBtnClass: 'ui-btn-active',
27 // activePageClass: 'ui-page-active',
28 ajaxEnabled: false,
29 // allowCrossDomainPages: false,
30 // autoInitializePage: true,
31 // buttonMarkup.hoverDelay: 200,
32 // defaultDialogTransition: 'pop',
33 // defaultPageTransition: 'fade,
34 // getMaxScrollForTransition: 3,
35 // gradeA: …,
36 // hashListeningEnabled: true,
37 ignoreContentEnabled: true,
38 // linkBindingEnabled: true,
39 // maxTransitionWidth: false,
40 // minScrollBack: 250,
41 // ns: '',
42 // pageLoadErrorMessage: "Error Loading Page",
43 // pageLoadErrorMessageTheme: 'e',
44 // phonegapNavigationEnabled: false,
45 // pushStateEnabled: true,
46 // subPageUrlKey: 'ui-page',
47 // transitionFallbacks.[transition]: 'fade',
48 __syntaxFix__: "syntax fix"
49 })
50});
diff --git a/frontend/gamma/js/JQuery/1.9.1/jquery.js b/frontend/gamma/js/JQuery/1.9.1/jquery.js
new file mode 100644
index 0000000..9c3bc21
--- a/dev/null
+++ b/frontend/gamma/js/JQuery/1.9.1/jquery.js
@@ -0,0 +1,9620 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/*!
25 * jQuery JavaScript Library v1.9.1
26 * http://jquery.com/
27 *
28 * Includes Sizzle.js
29 * http://sizzlejs.com/
30 *
31 * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
32 * Released under the MIT license
33 * http://jquery.org/license
34 *
35 * Date: 2013-2-4
36 */
37(function( window, undefined ) {
38
39// Can't do this because several apps including ASP.NET trace
40// the stack via arguments.caller.callee and Firefox dies if
41// you try to trace through "use strict" call chains. (#13335)
42// Support: Firefox 18+
43//"use strict";
44var
45 // The deferred used on DOM ready
46 readyList,
47
48 // A central reference to the root jQuery(document)
49 rootjQuery,
50
51 // Support: IE<9
52 // For `typeof node.method` instead of `node.method !== undefined`
53 core_strundefined = typeof undefined,
54
55 // Use the correct document accordingly with window argument (sandbox)
56 document = window.document,
57 location = window.location,
58
59 // Map over jQuery in case of overwrite
60 _jQuery = window.jQuery,
61
62 // Map over the $ in case of overwrite
63 _$ = window.$,
64
65 // [[Class]] -> type pairs
66 class2type = {},
67
68 // List of deleted data cache ids, so we can reuse them
69 core_deletedIds = [],
70
71 core_version = "1.9.1",
72
73 // Save a reference to some core methods
74 core_concat = core_deletedIds.concat,
75 core_push = core_deletedIds.push,
76 core_slice = core_deletedIds.slice,
77 core_indexOf = core_deletedIds.indexOf,
78 core_toString = class2type.toString,
79 core_hasOwn = class2type.hasOwnProperty,
80 core_trim = core_version.trim,
81
82 // Define a local copy of jQuery
83 jQuery = function( selector, context ) {
84 // The jQuery object is actually just the init constructor 'enhanced'
85 return new jQuery.fn.init( selector, context, rootjQuery );
86 },
87
88 // Used for matching numbers
89 core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
90
91 // Used for splitting on whitespace
92 core_rnotwhite = /\S+/g,
93
94 // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
95 rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
96
97 // A simple way to check for HTML strings
98 // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
99 // Strict HTML recognition (#11290: must start with <)
100 rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
101
102 // Match a standalone tag
103 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
104
105 // JSON RegExp
106 rvalidchars = /^[\],:{}\s]*$/,
107 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
108 rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
109 rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
110
111 // Matches dashed string for camelizing
112 rmsPrefix = /^-ms-/,
113 rdashAlpha = /-([\da-z])/gi,
114
115 // Used by jQuery.camelCase as callback to replace()
116 fcamelCase = function( all, letter ) {
117 return letter.toUpperCase();
118 },
119
120 // The ready event handler
121 completed = function( event ) {
122
123 // readyState === "complete" is good enough for us to call the dom ready in oldIE
124 if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
125 detach();
126 jQuery.ready();
127 }
128 },
129 // Clean-up method for dom ready events
130 detach = function() {
131 if ( document.addEventListener ) {
132 document.removeEventListener( "DOMContentLoaded", completed, false );
133 window.removeEventListener( "load", completed, false );
134
135 } else {
136 document.detachEvent( "onreadystatechange", completed );
137 window.detachEvent( "onload", completed );
138 }
139 };
140
141jQuery.fn = jQuery.prototype = {
142 // The current version of jQuery being used
143 jquery: core_version,
144
145 constructor: jQuery,
146 init: function( selector, context, rootjQuery ) {
147 var match, elem;
148
149 // HANDLE: $(""), $(null), $(undefined), $(false)
150 if ( !selector ) {
151 return this;
152 }
153
154 // Handle HTML strings
155 if ( typeof selector === "string" ) {
156 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
157 // Assume that strings that start and end with <> are HTML and skip the regex check
158 match = [ null, selector, null ];
159
160 } else {
161 match = rquickExpr.exec( selector );
162 }
163
164 // Match html or make sure no context is specified for #id
165 if ( match && (match[1] || !context) ) {
166
167 // HANDLE: $(html) -> $(array)
168 if ( match[1] ) {
169 context = context instanceof jQuery ? context[0] : context;
170
171 // scripts is true for back-compat
172 jQuery.merge( this, jQuery.parseHTML(
173 match[1],
174 context && context.nodeType ? context.ownerDocument || context : document,
175 true
176 ) );
177
178 // HANDLE: $(html, props)
179 if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
180 for ( match in context ) {
181 // Properties of context are called as methods if possible
182 if ( jQuery.isFunction( this[ match ] ) ) {
183 this[ match ]( context[ match ] );
184
185 // ...and otherwise set as attributes
186 } else {
187 this.attr( match, context[ match ] );
188 }
189 }
190 }
191
192 return this;
193
194 // HANDLE: $(#id)
195 } else {
196 elem = document.getElementById( match[2] );
197
198 // Check parentNode to catch when Blackberry 4.6 returns
199 // nodes that are no longer in the document #6963
200 if ( elem && elem.parentNode ) {
201 // Handle the case where IE and Opera return items
202 // by name instead of ID
203 if ( elem.id !== match[2] ) {
204 return rootjQuery.find( selector );
205 }
206
207 // Otherwise, we inject the element directly into the jQuery object
208 this.length = 1;
209 this[0] = elem;
210 }
211
212 this.context = document;
213 this.selector = selector;
214 return this;
215 }
216
217 // HANDLE: $(expr, $(...))
218 } else if ( !context || context.jquery ) {
219 return ( context || rootjQuery ).find( selector );
220
221 // HANDLE: $(expr, context)
222 // (which is just equivalent to: $(context).find(expr)
223 } else {
224 return this.constructor( context ).find( selector );
225 }
226
227 // HANDLE: $(DOMElement)
228 } else if ( selector.nodeType ) {
229 this.context = this[0] = selector;
230 this.length = 1;
231 return this;
232
233 // HANDLE: $(function)
234 // Shortcut for document ready
235 } else if ( jQuery.isFunction( selector ) ) {
236 return rootjQuery.ready( selector );
237 }
238
239 if ( selector.selector !== undefined ) {
240 this.selector = selector.selector;
241 this.context = selector.context;
242 }
243
244 return jQuery.makeArray( selector, this );
245 },
246
247 // Start with an empty selector
248 selector: "",
249
250 // The default length of a jQuery object is 0
251 length: 0,
252
253 // The number of elements contained in the matched element set
254 size: function() {
255 return this.length;
256 },
257
258 toArray: function() {
259 return core_slice.call( this );
260 },
261
262 // Get the Nth element in the matched element set OR
263 // Get the whole matched element set as a clean array
264 get: function( num ) {
265 return num == null ?
266
267 // Return a 'clean' array
268 this.toArray() :
269
270 // Return just the object
271 ( num < 0 ? this[ this.length + num ] : this[ num ] );
272 },
273
274 // Take an array of elements and push it onto the stack
275 // (returning the new matched element set)
276 pushStack: function( elems ) {
277
278 // Build a new jQuery matched element set
279 var ret = jQuery.merge( this.constructor(), elems );
280
281 // Add the old object onto the stack (as a reference)
282 ret.prevObject = this;
283 ret.context = this.context;
284
285 // Return the newly-formed element set
286 return ret;
287 },
288
289 // Execute a callback for every element in the matched set.
290 // (You can seed the arguments with an array of args, but this is
291 // only used internally.)
292 each: function( callback, args ) {
293 return jQuery.each( this, callback, args );
294 },
295
296 ready: function( fn ) {
297 // Add the callback
298 jQuery.ready.promise().done( fn );
299
300 return this;
301 },
302
303 slice: function() {
304 return this.pushStack( core_slice.apply( this, arguments ) );
305 },
306
307 first: function() {
308 return this.eq( 0 );
309 },
310
311 last: function() {
312 return this.eq( -1 );
313 },
314
315 eq: function( i ) {
316 var len = this.length,
317 j = +i + ( i < 0 ? len : 0 );
318 return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
319 },
320
321 map: function( callback ) {
322 return this.pushStack( jQuery.map(this, function( elem, i ) {
323 return callback.call( elem, i, elem );
324 }));
325 },
326
327 end: function() {
328 return this.prevObject || this.constructor(null);
329 },
330
331 // For internal use only.
332 // Behaves like an Array's method, not like a jQuery method.
333 push: core_push,
334 sort: [].sort,
335 splice: [].splice
336};
337
338// Give the init function the jQuery prototype for later instantiation
339jQuery.fn.init.prototype = jQuery.fn;
340
341jQuery.extend = jQuery.fn.extend = function() {
342 var src, copyIsArray, copy, name, options, clone,
343 target = arguments[0] || {},
344 i = 1,
345 length = arguments.length,
346 deep = false;
347
348 // Handle a deep copy situation
349 if ( typeof target === "boolean" ) {
350 deep = target;
351 target = arguments[1] || {};
352 // skip the boolean and the target
353 i = 2;
354 }
355
356 // Handle case when target is a string or something (possible in deep copy)
357 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
358 target = {};
359 }
360
361 // extend jQuery itself if only one argument is passed
362 if ( length === i ) {
363 target = this;
364 --i;
365 }
366
367 for ( ; i < length; i++ ) {
368 // Only deal with non-null/undefined values
369 if ( (options = arguments[ i ]) != null ) {
370 // Extend the base object
371 for ( name in options ) {
372 src = target[ name ];
373 copy = options[ name ];
374
375 // Prevent never-ending loop
376 if ( target === copy ) {
377 continue;
378 }
379
380 // Recurse if we're merging plain objects or arrays
381 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
382 if ( copyIsArray ) {
383 copyIsArray = false;
384 clone = src && jQuery.isArray(src) ? src : [];
385
386 } else {
387 clone = src && jQuery.isPlainObject(src) ? src : {};
388 }
389
390 // Never move original objects, clone them
391 target[ name ] = jQuery.extend( deep, clone, copy );
392
393 // Don't bring in undefined values
394 } else if ( copy !== undefined ) {
395 target[ name ] = copy;
396 }
397 }
398 }
399 }
400
401 // Return the modified object
402 return target;
403};
404
405jQuery.extend({
406 noConflict: function( deep ) {
407 if ( window.$ === jQuery ) {
408 window.$ = _$;
409 }
410
411 if ( deep && window.jQuery === jQuery ) {
412 window.jQuery = _jQuery;
413 }
414
415 return jQuery;
416 },
417
418 // Is the DOM ready to be used? Set to true once it occurs.
419 isReady: false,
420
421 // A counter to track how many items to wait for before
422 // the ready event fires. See #6781
423 readyWait: 1,
424
425 // Hold (or release) the ready event
426 holdReady: function( hold ) {
427 if ( hold ) {
428 jQuery.readyWait++;
429 } else {
430 jQuery.ready( true );
431 }
432 },
433
434 // Handle when the DOM is ready
435 ready: function( wait ) {
436
437 // Abort if there are pending holds or we're already ready
438 if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
439 return;
440 }
441
442 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
443 if ( !document.body ) {
444 return setTimeout( jQuery.ready );
445 }
446
447 // Remember that the DOM is ready
448 jQuery.isReady = true;
449
450 // If a normal DOM Ready event fired, decrement, and wait if need be
451 if ( wait !== true && --jQuery.readyWait > 0 ) {
452 return;
453 }
454
455 // If there are functions bound, to execute
456 readyList.resolveWith( document, [ jQuery ] );
457
458 // Trigger any bound ready events
459 if ( jQuery.fn.trigger ) {
460 jQuery( document ).trigger("ready").off("ready");
461 }
462 },
463
464 // See test/unit/core.js for details concerning isFunction.
465 // Since version 1.3, DOM methods and functions like alert
466 // aren't supported. They return false on IE (#2968).
467 isFunction: function( obj ) {
468 return jQuery.type(obj) === "function";
469 },
470
471 isArray: Array.isArray || function( obj ) {
472 return jQuery.type(obj) === "array";
473 },
474
475 isWindow: function( obj ) {
476 return obj != null && obj == obj.window;
477 },
478
479 isNumeric: function( obj ) {
480 return !isNaN( parseFloat(obj) ) && isFinite( obj );
481 },
482
483 type: function( obj ) {
484 if ( obj == null ) {
485 return String( obj );
486 }
487 return typeof obj === "object" || typeof obj === "function" ?
488 class2type[ core_toString.call(obj) ] || "object" :
489 typeof obj;
490 },
491
492 isPlainObject: function( obj ) {
493 // Must be an Object.
494 // Because of IE, we also have to check the presence of the constructor property.
495 // Make sure that DOM nodes and window objects don't pass through, as well
496 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
497 return false;
498 }
499
500 try {
501 // Not own constructor property must be Object
502 if ( obj.constructor &&
503 !core_hasOwn.call(obj, "constructor") &&
504 !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
505 return false;
506 }
507 } catch ( e ) {
508 // IE8,9 Will throw exceptions on certain host objects #9897
509 return false;
510 }
511
512 // Own properties are enumerated firstly, so to speed up,
513 // if last one is own, then all properties are own.
514
515 var key;
516 for ( key in obj ) {}
517
518 return key === undefined || core_hasOwn.call( obj, key );
519 },
520
521 isEmptyObject: function( obj ) {
522 var name;
523 for ( name in obj ) {
524 return false;
525 }
526 return true;
527 },
528
529 error: function( msg ) {
530 throw new Error( msg );
531 },
532
533 // data: string of html
534 // context (optional): If specified, the fragment will be created in this context, defaults to document
535 // keepScripts (optional): If true, will include scripts passed in the html string
536 parseHTML: function( data, context, keepScripts ) {
537 if ( !data || typeof data !== "string" ) {
538 return null;
539 }
540 if ( typeof context === "boolean" ) {
541 keepScripts = context;
542 context = false;
543 }
544 context = context || document;
545
546 var parsed = rsingleTag.exec( data ),
547 scripts = !keepScripts && [];
548
549 // Single tag
550 if ( parsed ) {
551 return [ context.createElement( parsed[1] ) ];
552 }
553
554 parsed = jQuery.buildFragment( [ data ], context, scripts );
555 if ( scripts ) {
556 jQuery( scripts ).remove();
557 }
558 return jQuery.merge( [], parsed.childNodes );
559 },
560
561 parseJSON: function( data ) {
562 // Attempt to parse using the native JSON parser first
563 if ( window.JSON && window.JSON.parse ) {
564 return window.JSON.parse( data );
565 }
566
567 if ( data === null ) {
568 return data;
569 }
570
571 if ( typeof data === "string" ) {
572
573 // Make sure leading/trailing whitespace is removed (IE can't handle it)
574 data = jQuery.trim( data );
575
576 if ( data ) {
577 // Make sure the incoming data is actual JSON
578 // Logic borrowed from http://json.org/json2.js
579 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
580 .replace( rvalidtokens, "]" )
581 .replace( rvalidbraces, "")) ) {
582
583 return ( new Function( "return " + data ) )();
584 }
585 }
586 }
587
588 jQuery.error( "Invalid JSON: " + data );
589 },
590
591 // Cross-browser xml parsing
592 parseXML: function( data ) {
593 var xml, tmp;
594 if ( !data || typeof data !== "string" ) {
595 return null;
596 }
597 try {
598 if ( window.DOMParser ) { // Standard
599 tmp = new DOMParser();
600 xml = tmp.parseFromString( data , "text/xml" );
601 } else { // IE
602 xml = new ActiveXObject( "Microsoft.XMLDOM" );
603 xml.async = "false";
604 xml.loadXML( data );
605 }
606 } catch( e ) {
607 xml = undefined;
608 }
609 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
610 jQuery.error( "Invalid XML: " + data );
611 }
612 return xml;
613 },
614
615 noop: function() {},
616
617 // Evaluates a script in a global context
618 // Workarounds based on findings by Jim Driscoll
619 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
620 globalEval: function( data ) {
621 if ( data && jQuery.trim( data ) ) {
622 // We use execScript on Internet Explorer
623 // We use an anonymous function so that context is window
624 // rather than jQuery in Firefox
625 ( window.execScript || function( data ) {
626 window[ "eval" ].call( window, data );
627 } )( data );
628 }
629 },
630
631 // Convert dashed to camelCase; used by the css and data modules
632 // Microsoft forgot to hump their vendor prefix (#9572)
633 camelCase: function( string ) {
634 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
635 },
636
637 nodeName: function( elem, name ) {
638 return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
639 },
640
641 // args is for internal usage only
642 each: function( obj, callback, args ) {
643 var value,
644 i = 0,
645 length = obj.length,
646 isArray = isArraylike( obj );
647
648 if ( args ) {
649 if ( isArray ) {
650 for ( ; i < length; i++ ) {
651 value = callback.apply( obj[ i ], args );
652
653 if ( value === false ) {
654 break;
655 }
656 }
657 } else {
658 for ( i in obj ) {
659 value = callback.apply( obj[ i ], args );
660
661 if ( value === false ) {
662 break;
663 }
664 }
665 }
666
667 // A special, fast, case for the most common use of each
668 } else {
669 if ( isArray ) {
670 for ( ; i < length; i++ ) {
671 value = callback.call( obj[ i ], i, obj[ i ] );
672
673 if ( value === false ) {
674 break;
675 }
676 }
677 } else {
678 for ( i in obj ) {
679 value = callback.call( obj[ i ], i, obj[ i ] );
680
681 if ( value === false ) {
682 break;
683 }
684 }
685 }
686 }
687
688 return obj;
689 },
690
691 // Use native String.trim function wherever possible
692 trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
693 function( text ) {
694 return text == null ?
695 "" :
696 core_trim.call( text );
697 } :
698
699 // Otherwise use our own trimming functionality
700 function( text ) {
701 return text == null ?
702 "" :
703 ( text + "" ).replace( rtrim, "" );
704 },
705
706 // results is for internal usage only
707 makeArray: function( arr, results ) {
708 var ret = results || [];
709
710 if ( arr != null ) {
711 if ( isArraylike( Object(arr) ) ) {
712 jQuery.merge( ret,
713 typeof arr === "string" ?
714 [ arr ] : arr
715 );
716 } else {
717 core_push.call( ret, arr );
718 }
719 }
720
721 return ret;
722 },
723
724 inArray: function( elem, arr, i ) {
725 var len;
726
727 if ( arr ) {
728 if ( core_indexOf ) {
729 return core_indexOf.call( arr, elem, i );
730 }
731
732 len = arr.length;
733 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
734
735 for ( ; i < len; i++ ) {
736 // Skip accessing in sparse arrays
737 if ( i in arr && arr[ i ] === elem ) {
738 return i;
739 }
740 }
741 }
742
743 return -1;
744 },
745
746 merge: function( first, second ) {
747 var l = second.length,
748 i = first.length,
749 j = 0;
750
751 if ( typeof l === "number" ) {
752 for ( ; j < l; j++ ) {
753 first[ i++ ] = second[ j ];
754 }
755 } else {
756 while ( second[j] !== undefined ) {
757 first[ i++ ] = second[ j++ ];
758 }
759 }
760
761 first.length = i;
762
763 return first;
764 },
765
766 grep: function( elems, callback, inv ) {
767 var retVal,
768 ret = [],
769 i = 0,
770 length = elems.length;
771 inv = !!inv;
772
773 // Go through the array, only saving the items
774 // that pass the validator function
775 for ( ; i < length; i++ ) {
776 retVal = !!callback( elems[ i ], i );
777 if ( inv !== retVal ) {
778 ret.push( elems[ i ] );
779 }
780 }
781
782 return ret;
783 },
784
785 // arg is for internal usage only
786 map: function( elems, callback, arg ) {
787 var value,
788 i = 0,
789 length = elems.length,
790 isArray = isArraylike( elems ),
791 ret = [];
792
793 // Go through the array, translating each of the items to their
794 if ( isArray ) {
795 for ( ; i < length; i++ ) {
796 value = callback( elems[ i ], i, arg );
797
798 if ( value != null ) {
799 ret[ ret.length ] = value;
800 }
801 }
802
803 // Go through every key on the object,
804 } else {
805 for ( i in elems ) {
806 value = callback( elems[ i ], i, arg );
807
808 if ( value != null ) {
809 ret[ ret.length ] = value;
810 }
811 }
812 }
813
814 // Flatten any nested arrays
815 return core_concat.apply( [], ret );
816 },
817
818 // A global GUID counter for objects
819 guid: 1,
820
821 // Bind a function to a context, optionally partially applying any
822 // arguments.
823 proxy: function( fn, context ) {
824 var args, proxy, tmp;
825
826 if ( typeof context === "string" ) {
827 tmp = fn[ context ];
828 context = fn;
829 fn = tmp;
830 }
831
832 // Quick check to determine if target is callable, in the spec
833 // this throws a TypeError, but we will just return undefined.
834 if ( !jQuery.isFunction( fn ) ) {
835 return undefined;
836 }
837
838 // Simulated bind
839 args = core_slice.call( arguments, 2 );
840 proxy = function() {
841 return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
842 };
843
844 // Set the guid of unique handler to the same of original handler, so it can be removed
845 proxy.guid = fn.guid = fn.guid || jQuery.guid++;
846
847 return proxy;
848 },
849
850 // Multifunctional method to get and set values of a collection
851 // The value/s can optionally be executed if it's a function
852 access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
853 var i = 0,
854 length = elems.length,
855 bulk = key == null;
856
857 // Sets many values
858 if ( jQuery.type( key ) === "object" ) {
859 chainable = true;
860 for ( i in key ) {
861 jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
862 }
863
864 // Sets one value
865 } else if ( value !== undefined ) {
866 chainable = true;
867
868 if ( !jQuery.isFunction( value ) ) {
869 raw = true;
870 }
871
872 if ( bulk ) {
873 // Bulk operations run against the entire set
874 if ( raw ) {
875 fn.call( elems, value );
876 fn = null;
877
878 // ...except when executing function values
879 } else {
880 bulk = fn;
881 fn = function( elem, key, value ) {
882 return bulk.call( jQuery( elem ), value );
883 };
884 }
885 }
886
887 if ( fn ) {
888 for ( ; i < length; i++ ) {
889 fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
890 }
891 }
892 }
893
894 return chainable ?
895 elems :
896
897 // Gets
898 bulk ?
899 fn.call( elems ) :
900 length ? fn( elems[0], key ) : emptyGet;
901 },
902
903 now: function() {
904 return ( new Date() ).getTime();
905 }
906});
907
908jQuery.ready.promise = function( obj ) {
909 if ( !readyList ) {
910
911 readyList = jQuery.Deferred();
912
913 // Catch cases where $(document).ready() is called after the browser event has already occurred.
914 // we once tried to use readyState "interactive" here, but it caused issues like the one
915 // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
916 if ( document.readyState === "complete" ) {
917 // Handle it asynchronously to allow scripts the opportunity to delay ready
918 setTimeout( jQuery.ready );
919
920 // Standards-based browsers support DOMContentLoaded
921 } else if ( document.addEventListener ) {
922 // Use the handy event callback
923 document.addEventListener( "DOMContentLoaded", completed, false );
924
925 // A fallback to window.onload, that will always work
926 window.addEventListener( "load", completed, false );
927
928 // If IE event model is used
929 } else {
930 // Ensure firing before onload, maybe late but safe also for iframes
931 document.attachEvent( "onreadystatechange", completed );
932
933 // A fallback to window.onload, that will always work
934 window.attachEvent( "onload", completed );
935
936 // If IE and not a frame
937 // continually check to see if the document is ready
938 var top = false;
939
940 try {
941 top = window.frameElement == null && document.documentElement;
942 } catch(e) {}
943
944 if ( top && top.doScroll ) {
945 (function doScrollCheck() {
946 if ( !jQuery.isReady ) {
947
948 try {
949 // Use the trick by Diego Perini
950 // http://javascript.nwbox.com/IEContentLoaded/
951 top.doScroll("left");
952 } catch(e) {
953 return setTimeout( doScrollCheck, 50 );
954 }
955
956 // detach all dom ready events
957 detach();
958
959 // and execute any waiting functions
960 jQuery.ready();
961 }
962 })();
963 }
964 }
965 }
966 return readyList.promise( obj );
967};
968
969// Populate the class2type map
970jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
971 class2type[ "[object " + name + "]" ] = name.toLowerCase();
972});
973
974function isArraylike( obj ) {
975 var length = obj.length,
976 type = jQuery.type( obj );
977
978 if ( jQuery.isWindow( obj ) ) {
979 return false;
980 }
981
982 if ( obj.nodeType === 1 && length ) {
983 return true;
984 }
985
986 return type === "array" || type !== "function" &&
987 ( length === 0 ||
988 typeof length === "number" && length > 0 && ( length - 1 ) in obj );
989}
990
991// All jQuery objects should point back to these
992rootjQuery = jQuery(document);
993// String to Object options format cache
994var optionsCache = {};
995
996// Convert String-formatted options into Object-formatted ones and store in cache
997function createOptions( options ) {
998 var object = optionsCache[ options ] = {};
999 jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
1000 object[ flag ] = true;
1001 });
1002 return object;
1003}
1004
1005/*
1006 * Create a callback list using the following parameters:
1007 *
1008 *options: an optional list of space-separated options that will change how
1009 * the callback list behaves or a more traditional option object
1010 *
1011 * By default a callback list will act like an event callback list and can be
1012 * "fired" multiple times.
1013 *
1014 * Possible options:
1015 *
1016 * once: will ensure the callback list can only be fired once (like a Deferred)
1017 *
1018 * memory: will keep track of previous values and will call any callback added
1019 * after the list has been fired right away with the latest "memorized"
1020 * values (like a Deferred)
1021 *
1022 * unique: will ensure a callback can only be added once (no duplicate in the list)
1023 *
1024 * stopOnFalse:interrupt callings when a callback returns false
1025 *
1026 */
1027jQuery.Callbacks = function( options ) {
1028
1029 // Convert options from String-formatted to Object-formatted if needed
1030 // (we check in cache first)
1031 options = typeof options === "string" ?
1032 ( optionsCache[ options ] || createOptions( options ) ) :
1033 jQuery.extend( {}, options );
1034
1035 var // Flag to know if list is currently firing
1036 firing,
1037 // Last fire value (for non-forgettable lists)
1038 memory,
1039 // Flag to know if list was already fired
1040 fired,
1041 // End of the loop when firing
1042 firingLength,
1043 // Index of currently firing callback (modified by remove if needed)
1044 firingIndex,
1045 // First callback to fire (used internally by add and fireWith)
1046 firingStart,
1047 // Actual callback list
1048 list = [],
1049 // Stack of fire calls for repeatable lists
1050 stack = !options.once && [],
1051 // Fire callbacks
1052 fire = function( data ) {
1053 memory = options.memory && data;
1054 fired = true;
1055 firingIndex = firingStart || 0;
1056 firingStart = 0;
1057 firingLength = list.length;
1058 firing = true;
1059 for ( ; list && firingIndex < firingLength; firingIndex++ ) {
1060 if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
1061 memory = false; // To prevent further calls using add
1062 break;
1063 }
1064 }
1065 firing = false;
1066 if ( list ) {
1067 if ( stack ) {
1068 if ( stack.length ) {
1069 fire( stack.shift() );
1070 }
1071 } else if ( memory ) {
1072 list = [];
1073 } else {
1074 self.disable();
1075 }
1076 }
1077 },
1078 // Actual Callbacks object
1079 self = {
1080 // Add a callback or a collection of callbacks to the list
1081 add: function() {
1082 if ( list ) {
1083 // First, we save the current length
1084 var start = list.length;
1085 (function add( args ) {
1086 jQuery.each( args, function( _, arg ) {
1087 var type = jQuery.type( arg );
1088 if ( type === "function" ) {
1089 if ( !options.unique || !self.has( arg ) ) {
1090 list.push( arg );
1091 }
1092 } else if ( arg && arg.length && type !== "string" ) {
1093 // Inspect recursively
1094 add( arg );
1095 }
1096 });
1097 })( arguments );
1098 // Do we need to add the callbacks to the
1099 // current firing batch?
1100 if ( firing ) {
1101 firingLength = list.length;
1102 // With memory, if we're not firing then
1103 // we should call right away
1104 } else if ( memory ) {
1105 firingStart = start;
1106 fire( memory );
1107 }
1108 }
1109 return this;
1110 },
1111 // Remove a callback from the list
1112 remove: function() {
1113 if ( list ) {
1114 jQuery.each( arguments, function( _, arg ) {
1115 var index;
1116 while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
1117 list.splice( index, 1 );
1118 // Handle firing indexes
1119 if ( firing ) {
1120 if ( index <= firingLength ) {
1121 firingLength--;
1122 }
1123 if ( index <= firingIndex ) {
1124 firingIndex--;
1125 }
1126 }
1127 }
1128 });
1129 }
1130 return this;
1131 },
1132 // Check if a given callback is in the list.
1133 // If no argument is given, return whether or not list has callbacks attached.
1134 has: function( fn ) {
1135 return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
1136 },
1137 // Remove all callbacks from the list
1138 empty: function() {
1139 list = [];
1140 return this;
1141 },
1142 // Have the list do nothing anymore
1143 disable: function() {
1144 list = stack = memory = undefined;
1145 return this;
1146 },
1147 // Is it disabled?
1148 disabled: function() {
1149 return !list;
1150 },
1151 // Lock the list in its current state
1152 lock: function() {
1153 stack = undefined;
1154 if ( !memory ) {
1155 self.disable();
1156 }
1157 return this;
1158 },
1159 // Is it locked?
1160 locked: function() {
1161 return !stack;
1162 },
1163 // Call all callbacks with the given context and arguments
1164 fireWith: function( context, args ) {
1165 args = args || [];
1166 args = [ context, args.slice ? args.slice() : args ];
1167 if ( list && ( !fired || stack ) ) {
1168 if ( firing ) {
1169 stack.push( args );
1170 } else {
1171 fire( args );
1172 }
1173 }
1174 return this;
1175 },
1176 // Call all the callbacks with the given arguments
1177 fire: function() {
1178 self.fireWith( this, arguments );
1179 return this;
1180 },
1181 // To know if the callbacks have already been called at least once
1182 fired: function() {
1183 return !!fired;
1184 }
1185 };
1186
1187 return self;
1188};
1189jQuery.extend({
1190
1191 Deferred: function( func ) {
1192 var tuples = [
1193 // action, add listener, listener list, final state
1194 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
1195 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
1196 [ "notify", "progress", jQuery.Callbacks("memory") ]
1197 ],
1198 state = "pending",
1199 promise = {
1200 state: function() {
1201 return state;
1202 },
1203 always: function() {
1204 deferred.done( arguments ).fail( arguments );
1205 return this;
1206 },
1207 then: function( /* fnDone, fnFail, fnProgress */ ) {
1208 var fns = arguments;
1209 return jQuery.Deferred(function( newDefer ) {
1210 jQuery.each( tuples, function( i, tuple ) {
1211 var action = tuple[ 0 ],
1212 fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
1213 // deferred[ done | fail | progress ] for forwarding actions to newDefer
1214 deferred[ tuple[1] ](function() {
1215 var returned = fn && fn.apply( this, arguments );
1216 if ( returned && jQuery.isFunction( returned.promise ) ) {
1217 returned.promise()
1218 .done( newDefer.resolve )
1219 .fail( newDefer.reject )
1220 .progress( newDefer.notify );
1221 } else {
1222 newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
1223 }
1224 });
1225 });
1226 fns = null;
1227 }).promise();
1228 },
1229 // Get a promise for this deferred
1230 // If obj is provided, the promise aspect is added to the object
1231 promise: function( obj ) {
1232 return obj != null ? jQuery.extend( obj, promise ) : promise;
1233 }
1234 },
1235 deferred = {};
1236
1237 // Keep pipe for back-compat
1238 promise.pipe = promise.then;
1239
1240 // Add list-specific methods
1241 jQuery.each( tuples, function( i, tuple ) {
1242 var list = tuple[ 2 ],
1243 stateString = tuple[ 3 ];
1244
1245 // promise[ done | fail | progress ] = list.add
1246 promise[ tuple[1] ] = list.add;
1247
1248 // Handle state
1249 if ( stateString ) {
1250 list.add(function() {
1251 // state = [ resolved | rejected ]
1252 state = stateString;
1253
1254 // [ reject_list | resolve_list ].disable; progress_list.lock
1255 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
1256 }
1257
1258 // deferred[ resolve | reject | notify ]
1259 deferred[ tuple[0] ] = function() {
1260 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
1261 return this;
1262 };
1263 deferred[ tuple[0] + "With" ] = list.fireWith;
1264 });
1265
1266 // Make the deferred a promise
1267 promise.promise( deferred );
1268
1269 // Call given func if any
1270 if ( func ) {
1271 func.call( deferred, deferred );
1272 }
1273
1274 // All done!
1275 return deferred;
1276 },
1277
1278 // Deferred helper
1279 when: function( subordinate /* , ..., subordinateN */ ) {
1280 var i = 0,
1281 resolveValues = core_slice.call( arguments ),
1282 length = resolveValues.length,
1283
1284 // the count of uncompleted subordinates
1285 remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
1286
1287 // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
1288 deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
1289
1290 // Update function for both resolve and progress values
1291 updateFunc = function( i, contexts, values ) {
1292 return function( value ) {
1293 contexts[ i ] = this;
1294 values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
1295 if( values === progressValues ) {
1296 deferred.notifyWith( contexts, values );
1297 } else if ( !( --remaining ) ) {
1298 deferred.resolveWith( contexts, values );
1299 }
1300 };
1301 },
1302
1303 progressValues, progressContexts, resolveContexts;
1304
1305 // add listeners to Deferred subordinates; treat others as resolved
1306 if ( length > 1 ) {
1307 progressValues = new Array( length );
1308 progressContexts = new Array( length );
1309 resolveContexts = new Array( length );
1310 for ( ; i < length; i++ ) {
1311 if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
1312 resolveValues[ i ].promise()
1313 .done( updateFunc( i, resolveContexts, resolveValues ) )
1314 .fail( deferred.reject )
1315 .progress( updateFunc( i, progressContexts, progressValues ) );
1316 } else {
1317 --remaining;
1318 }
1319 }
1320 }
1321
1322 // if we're not waiting on anything, resolve the master
1323 if ( !remaining ) {
1324 deferred.resolveWith( resolveContexts, resolveValues );
1325 }
1326
1327 return deferred.promise();
1328 }
1329});
1330jQuery.support = (function() {
1331
1332 var support, all, a,
1333 input, select, fragment,
1334 opt, eventName, isSupported, i,
1335 div = document.createElement("div");
1336
1337 // Setup
1338 div.setAttribute( "className", "t" );
1339 div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
1340
1341 // Support tests won't run in some limited or non-browser environments
1342 all = div.getElementsByTagName("*");
1343 a = div.getElementsByTagName("a")[ 0 ];
1344 if ( !all || !a || !all.length ) {
1345 return {};
1346 }
1347
1348 // First batch of tests
1349 select = document.createElement("select");
1350 opt = select.appendChild( document.createElement("option") );
1351 input = div.getElementsByTagName("input")[ 0 ];
1352
1353 a.style.cssText = "top:1px;float:left;opacity:.5";
1354 support = {
1355 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1356 getSetAttribute: div.className !== "t",
1357
1358 // IE strips leading whitespace when .innerHTML is used
1359 leadingWhitespace: div.firstChild.nodeType === 3,
1360
1361 // Make sure that tbody elements aren't automatically inserted
1362 // IE will insert them into empty tables
1363 tbody: !div.getElementsByTagName("tbody").length,
1364
1365 // Make sure that link elements get serialized correctly by innerHTML
1366 // This requires a wrapper element in IE
1367 htmlSerialize: !!div.getElementsByTagName("link").length,
1368
1369 // Get the style information from getAttribute
1370 // (IE uses .cssText instead)
1371 style: /top/.test( a.getAttribute("style") ),
1372
1373 // Make sure that URLs aren't manipulated
1374 // (IE normalizes it by default)
1375 hrefNormalized: a.getAttribute("href") === "/a",
1376
1377 // Make sure that element opacity exists
1378 // (IE uses filter instead)
1379 // Use a regex to work around a WebKit issue. See #5145
1380 opacity: /^0.5/.test( a.style.opacity ),
1381
1382 // Verify style float existence
1383 // (IE uses styleFloat instead of cssFloat)
1384 cssFloat: !!a.style.cssFloat,
1385
1386 // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
1387 checkOn: !!input.value,
1388
1389 // Make sure that a selected-by-default option has a working selected property.
1390 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1391 optSelected: opt.selected,
1392
1393 // Tests for enctype support on a form (#6743)
1394 enctype: !!document.createElement("form").enctype,
1395
1396 // Makes sure cloning an html5 element does not cause problems
1397 // Where outerHTML is undefined, this still works
1398 html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
1399
1400 // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
1401 boxModel: document.compatMode === "CSS1Compat",
1402
1403 // Will be defined later
1404 deleteExpando: true,
1405 noCloneEvent: true,
1406 inlineBlockNeedsLayout: false,
1407 shrinkWrapBlocks: false,
1408 reliableMarginRight: true,
1409 boxSizingReliable: true,
1410 pixelPosition: false
1411 };
1412
1413 // Make sure checked status is properly cloned
1414 input.checked = true;
1415 support.noCloneChecked = input.cloneNode( true ).checked;
1416
1417 // Make sure that the options inside disabled selects aren't marked as disabled
1418 // (WebKit marks them as disabled)
1419 select.disabled = true;
1420 support.optDisabled = !opt.disabled;
1421
1422 // Support: IE<9
1423 try {
1424 delete div.test;
1425 } catch( e ) {
1426 support.deleteExpando = false;
1427 }
1428
1429 // Check if we can trust getAttribute("value")
1430 input = document.createElement("input");
1431 input.setAttribute( "value", "" );
1432 support.input = input.getAttribute( "value" ) === "";
1433
1434 // Check if an input maintains its value after becoming a radio
1435 input.value = "t";
1436 input.setAttribute( "type", "radio" );
1437 support.radioValue = input.value === "t";
1438
1439 // #11217 - WebKit loses check when the name is after the checked attribute
1440 input.setAttribute( "checked", "t" );
1441 input.setAttribute( "name", "t" );
1442
1443 fragment = document.createDocumentFragment();
1444 fragment.appendChild( input );
1445
1446 // Check if a disconnected checkbox will retain its checked
1447 // value of true after appended to the DOM (IE6/7)
1448 support.appendChecked = input.checked;
1449
1450 // WebKit doesn't clone checked state correctly in fragments
1451 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1452
1453 // Support: IE<9
1454 // Opera does not clone events (and typeof div.attachEvent === undefined).
1455 // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
1456 if ( div.attachEvent ) {
1457 div.attachEvent( "onclick", function() {
1458 support.noCloneEvent = false;
1459 });
1460
1461 div.cloneNode( true ).click();
1462 }
1463
1464 // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
1465 // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
1466 for ( i in { submit: true, change: true, focusin: true }) {
1467 div.setAttribute( eventName = "on" + i, "t" );
1468
1469 support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
1470 }
1471
1472 div.style.backgroundClip = "content-box";
1473 div.cloneNode( true ).style.backgroundClip = "";
1474 support.clearCloneStyle = div.style.backgroundClip === "content-box";
1475
1476 // Run tests that need a body at doc ready
1477 jQuery(function() {
1478 var container, marginDiv, tds,
1479 divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
1480 body = document.getElementsByTagName("body")[0];
1481
1482 if ( !body ) {
1483 // Return for frameset docs that don't have a body
1484 return;
1485 }
1486
1487 container = document.createElement("div");
1488 container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
1489
1490 body.appendChild( container ).appendChild( div );
1491
1492 // Support: IE8
1493 // Check if table cells still have offsetWidth/Height when they are set
1494 // to display:none and there are still other visible table cells in a
1495 // table row; if so, offsetWidth/Height are not reliable for use when
1496 // determining if an element has been hidden directly using
1497 // display:none (it is still safe to use offsets if a parent element is
1498 // hidden; don safety goggles and see bug #4512 for more information).
1499 div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
1500 tds = div.getElementsByTagName("td");
1501 tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
1502 isSupported = ( tds[ 0 ].offsetHeight === 0 );
1503
1504 tds[ 0 ].style.display = "";
1505 tds[ 1 ].style.display = "none";
1506
1507 // Support: IE8
1508 // Check if empty table cells still have offsetWidth/Height
1509 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1510
1511 // Check box-sizing and margin behavior
1512 div.innerHTML = "";
1513 div.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%;";
1514 support.boxSizing = ( div.offsetWidth === 4 );
1515 support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
1516
1517 // Use window.getComputedStyle because jsdom on node.js will break without it.
1518 if ( window.getComputedStyle ) {
1519 support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
1520 support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
1521
1522 // Check if div with explicit width and no margin-right incorrectly
1523 // gets computed margin-right based on width of container. (#3333)
1524 // Fails in WebKit before Feb 2011 nightlies
1525 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1526 marginDiv = div.appendChild( document.createElement("div") );
1527 marginDiv.style.cssText = div.style.cssText = divReset;
1528 marginDiv.style.marginRight = marginDiv.style.width = "0";
1529 div.style.width = "1px";
1530
1531 support.reliableMarginRight =
1532 !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
1533 }
1534
1535 if ( typeof div.style.zoom !== core_strundefined ) {
1536 // Support: IE<8
1537 // Check if natively block-level elements act like inline-block
1538 // elements when setting their display to 'inline' and giving
1539 // them layout
1540 div.innerHTML = "";
1541 div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
1542 support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
1543
1544 // Support: IE6
1545 // Check if elements with layout shrink-wrap their children
1546 div.style.display = "block";
1547 div.innerHTML = "<div></div>";
1548 div.firstChild.style.width = "5px";
1549 support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
1550
1551 if ( support.inlineBlockNeedsLayout ) {
1552 // Prevent IE 6 from affecting layout for positioned elements #11048
1553 // Prevent IE from shrinking the body in IE 7 mode #12869
1554 // Support: IE<8
1555 body.style.zoom = 1;
1556 }
1557 }
1558
1559 body.removeChild( container );
1560
1561 // Null elements to avoid leaks in IE
1562 container = div = tds = marginDiv = null;
1563 });
1564
1565 // Null elements to avoid leaks in IE
1566 all = select = fragment = opt = a = input = null;
1567
1568 return support;
1569})();
1570
1571var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
1572 rmultiDash = /([A-Z])/g;
1573
1574function internalData( elem, name, data, pvt /* Internal Use Only */ ){
1575 if ( !jQuery.acceptData( elem ) ) {
1576 return;
1577 }
1578
1579 var thisCache, ret,
1580 internalKey = jQuery.expando,
1581 getByName = typeof name === "string",
1582
1583 // We have to handle DOM nodes and JS objects differently because IE6-7
1584 // can't GC object references properly across the DOM-JS boundary
1585 isNode = elem.nodeType,
1586
1587 // Only DOM nodes need the global jQuery cache; JS object data is
1588 // attached directly to the object so GC can occur automatically
1589 cache = isNode ? jQuery.cache : elem,
1590
1591 // Only defining an ID for JS objects if its cache already exists allows
1592 // the code to shortcut on the same path as a DOM node with no cache
1593 id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
1594
1595 // Avoid doing any more work than we need to when trying to get data on an
1596 // object that has no data at all
1597 if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
1598 return;
1599 }
1600
1601 if ( !id ) {
1602 // Only DOM nodes need a new unique ID for each element since their data
1603 // ends up in the global cache
1604 if ( isNode ) {
1605 elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
1606 } else {
1607 id = internalKey;
1608 }
1609 }
1610
1611 if ( !cache[ id ] ) {
1612 cache[ id ] = {};
1613
1614 // Avoids exposing jQuery metadata on plain JS objects when the object
1615 // is serialized using JSON.stringify
1616 if ( !isNode ) {
1617 cache[ id ].toJSON = jQuery.noop;
1618 }
1619 }
1620
1621 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1622 // shallow copied over onto the existing cache
1623 if ( typeof name === "object" || typeof name === "function" ) {
1624 if ( pvt ) {
1625 cache[ id ] = jQuery.extend( cache[ id ], name );
1626 } else {
1627 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
1628 }
1629 }
1630
1631 thisCache = cache[ id ];
1632
1633 // jQuery data() is stored in a separate object inside the object's internal data
1634 // cache in order to avoid key collisions between internal data and user-defined
1635 // data.
1636 if ( !pvt ) {
1637 if ( !thisCache.data ) {
1638 thisCache.data = {};
1639 }
1640
1641 thisCache = thisCache.data;
1642 }
1643
1644 if ( data !== undefined ) {
1645 thisCache[ jQuery.camelCase( name ) ] = data;
1646 }
1647
1648 // Check for both converted-to-camel and non-converted data property names
1649 // If a data property was specified
1650 if ( getByName ) {
1651
1652 // First Try to find as-is property data
1653 ret = thisCache[ name ];
1654
1655 // Test for null|undefined property data
1656 if ( ret == null ) {
1657
1658 // Try to find the camelCased property
1659 ret = thisCache[ jQuery.camelCase( name ) ];
1660 }
1661 } else {
1662 ret = thisCache;
1663 }
1664
1665 return ret;
1666}
1667
1668function internalRemoveData( elem, name, pvt ) {
1669 if ( !jQuery.acceptData( elem ) ) {
1670 return;
1671 }
1672
1673 var i, l, thisCache,
1674 isNode = elem.nodeType,
1675
1676 // See jQuery.data for more information
1677 cache = isNode ? jQuery.cache : elem,
1678 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1679
1680 // If there is already no cache entry for this object, there is no
1681 // purpose in continuing
1682 if ( !cache[ id ] ) {
1683 return;
1684 }
1685
1686 if ( name ) {
1687
1688 thisCache = pvt ? cache[ id ] : cache[ id ].data;
1689
1690 if ( thisCache ) {
1691
1692 // Support array or space separated string names for data keys
1693 if ( !jQuery.isArray( name ) ) {
1694
1695 // try the string as a key before any manipulation
1696 if ( name in thisCache ) {
1697 name = [ name ];
1698 } else {
1699
1700 // split the camel cased version by spaces unless a key with the spaces exists
1701 name = jQuery.camelCase( name );
1702 if ( name in thisCache ) {
1703 name = [ name ];
1704 } else {
1705 name = name.split(" ");
1706 }
1707 }
1708 } else {
1709 // If "name" is an array of keys...
1710 // When data is initially created, via ("key", "val") signature,
1711 // keys will be converted to camelCase.
1712 // Since there is no way to tell _how_ a key was added, remove
1713 // both plain key and camelCase key. #12786
1714 // This will only penalize the array argument path.
1715 name = name.concat( jQuery.map( name, jQuery.camelCase ) );
1716 }
1717
1718 for ( i = 0, l = name.length; i < l; i++ ) {
1719 delete thisCache[ name[i] ];
1720 }
1721
1722 // If there is no data left in the cache, we want to continue
1723 // and let the cache object itself get destroyed
1724 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
1725 return;
1726 }
1727 }
1728 }
1729
1730 // See jQuery.data for more information
1731 if ( !pvt ) {
1732 delete cache[ id ].data;
1733
1734 // Don't destroy the parent cache unless the internal data object
1735 // had been the only thing left in it
1736 if ( !isEmptyDataObject( cache[ id ] ) ) {
1737 return;
1738 }
1739 }
1740
1741 // Destroy the cache
1742 if ( isNode ) {
1743 jQuery.cleanData( [ elem ], true );
1744
1745 // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
1746 } else if ( jQuery.support.deleteExpando || cache != cache.window ) {
1747 delete cache[ id ];
1748
1749 // When all else fails, null
1750 } else {
1751 cache[ id ] = null;
1752 }
1753}
1754
1755jQuery.extend({
1756 cache: {},
1757
1758 // Unique for each copy of jQuery on the page
1759 // Non-digits removed to match rinlinejQuery
1760 expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
1761
1762 // The following elements throw uncatchable exceptions if you
1763 // attempt to add expando properties to them.
1764 noData: {
1765 "embed": true,
1766 // Ban all objects except for Flash (which handle expandos)
1767 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1768 "applet": true
1769 },
1770
1771 hasData: function( elem ) {
1772 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1773 return !!elem && !isEmptyDataObject( elem );
1774 },
1775
1776 data: function( elem, name, data ) {
1777 return internalData( elem, name, data );
1778 },
1779
1780 removeData: function( elem, name ) {
1781 return internalRemoveData( elem, name );
1782 },
1783
1784 // For internal use only.
1785 _data: function( elem, name, data ) {
1786 return internalData( elem, name, data, true );
1787 },
1788
1789 _removeData: function( elem, name ) {
1790 return internalRemoveData( elem, name, true );
1791 },
1792
1793 // A method for determining if a DOM node can handle the data expando
1794 acceptData: function( elem ) {
1795 // Do not set data on non-element because it will not be cleared (#8335).
1796 if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
1797 return false;
1798 }
1799
1800 var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
1801
1802 // nodes accept data unless otherwise specified; rejection can be conditional
1803 return !noData || noData !== true && elem.getAttribute("classid") === noData;
1804 }
1805});
1806
1807jQuery.fn.extend({
1808 data: function( key, value ) {
1809 var attrs, name,
1810 elem = this[0],
1811 i = 0,
1812 data = null;
1813
1814 // Gets all values
1815 if ( key === undefined ) {
1816 if ( this.length ) {
1817 data = jQuery.data( elem );
1818
1819 if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
1820 attrs = elem.attributes;
1821 for ( ; i < attrs.length; i++ ) {
1822 name = attrs[i].name;
1823
1824 if ( !name.indexOf( "data-" ) ) {
1825 name = jQuery.camelCase( name.slice(5) );
1826
1827 dataAttr( elem, name, data[ name ] );
1828 }
1829 }
1830 jQuery._data( elem, "parsedAttrs", true );
1831 }
1832 }
1833
1834 return data;
1835 }
1836
1837 // Sets multiple values
1838 if ( typeof key === "object" ) {
1839 return this.each(function() {
1840 jQuery.data( this, key );
1841 });
1842 }
1843
1844 return jQuery.access( this, function( value ) {
1845
1846 if ( value === undefined ) {
1847 // Try to fetch any internally stored data first
1848 return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
1849 }
1850
1851 this.each(function() {
1852 jQuery.data( this, key, value );
1853 });
1854 }, null, value, arguments.length > 1, null, true );
1855 },
1856
1857 removeData: function( key ) {
1858 return this.each(function() {
1859 jQuery.removeData( this, key );
1860 });
1861 }
1862});
1863
1864function dataAttr( elem, key, data ) {
1865 // If nothing was found internally, try to fetch any
1866 // data from the HTML5 data-* attribute
1867 if ( data === undefined && elem.nodeType === 1 ) {
1868
1869 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
1870
1871 data = elem.getAttribute( name );
1872
1873 if ( typeof data === "string" ) {
1874 try {
1875 data = data === "true" ? true :
1876 data === "false" ? false :
1877 data === "null" ? null :
1878 // Only convert to a number if it doesn't change the string
1879 +data + "" === data ? +data :
1880 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1881 data;
1882 } catch( e ) {}
1883
1884 // Make sure we set the data so it isn't changed later
1885 jQuery.data( elem, key, data );
1886
1887 } else {
1888 data = undefined;
1889 }
1890 }
1891
1892 return data;
1893}
1894
1895// checks a cache object for emptiness
1896function isEmptyDataObject( obj ) {
1897 var name;
1898 for ( name in obj ) {
1899
1900 // if the public data object is empty, the private is still empty
1901 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
1902 continue;
1903 }
1904 if ( name !== "toJSON" ) {
1905 return false;
1906 }
1907 }
1908
1909 return true;
1910}
1911jQuery.extend({
1912 queue: function( elem, type, data ) {
1913 var queue;
1914
1915 if ( elem ) {
1916 type = ( type || "fx" ) + "queue";
1917 queue = jQuery._data( elem, type );
1918
1919 // Speed up dequeue by getting out quickly if this is just a lookup
1920 if ( data ) {
1921 if ( !queue || jQuery.isArray(data) ) {
1922 queue = jQuery._data( elem, type, jQuery.makeArray(data) );
1923 } else {
1924 queue.push( data );
1925 }
1926 }
1927 return queue || [];
1928 }
1929 },
1930
1931 dequeue: function( elem, type ) {
1932 type = type || "fx";
1933
1934 var queue = jQuery.queue( elem, type ),
1935 startLength = queue.length,
1936 fn = queue.shift(),
1937 hooks = jQuery._queueHooks( elem, type ),
1938 next = function() {
1939 jQuery.dequeue( elem, type );
1940 };
1941
1942 // If the fx queue is dequeued, always remove the progress sentinel
1943 if ( fn === "inprogress" ) {
1944 fn = queue.shift();
1945 startLength--;
1946 }
1947
1948 hooks.cur = fn;
1949 if ( fn ) {
1950
1951 // Add a progress sentinel to prevent the fx queue from being
1952 // automatically dequeued
1953 if ( type === "fx" ) {
1954 queue.unshift( "inprogress" );
1955 }
1956
1957 // clear up the last queue stop function
1958 delete hooks.stop;
1959 fn.call( elem, next, hooks );
1960 }
1961
1962 if ( !startLength && hooks ) {
1963 hooks.empty.fire();
1964 }
1965 },
1966
1967 // not intended for public consumption - generates a queueHooks object, or returns the current one
1968 _queueHooks: function( elem, type ) {
1969 var key = type + "queueHooks";
1970 return jQuery._data( elem, key ) || jQuery._data( elem, key, {
1971 empty: jQuery.Callbacks("once memory").add(function() {
1972 jQuery._removeData( elem, type + "queue" );
1973 jQuery._removeData( elem, key );
1974 })
1975 });
1976 }
1977});
1978
1979jQuery.fn.extend({
1980 queue: function( type, data ) {
1981 var setter = 2;
1982
1983 if ( typeof type !== "string" ) {
1984 data = type;
1985 type = "fx";
1986 setter--;
1987 }
1988
1989 if ( arguments.length < setter ) {
1990 return jQuery.queue( this[0], type );
1991 }
1992
1993 return data === undefined ?
1994 this :
1995 this.each(function() {
1996 var queue = jQuery.queue( this, type, data );
1997
1998 // ensure a hooks for this queue
1999 jQuery._queueHooks( this, type );
2000
2001 if ( type === "fx" && queue[0] !== "inprogress" ) {
2002 jQuery.dequeue( this, type );
2003 }
2004 });
2005 },
2006 dequeue: function( type ) {
2007 return this.each(function() {
2008 jQuery.dequeue( this, type );
2009 });
2010 },
2011 // Based off of the plugin by Clint Helfers, with permission.
2012 // http://blindsignals.com/index.php/2009/07/jquery-delay/
2013 delay: function( time, type ) {
2014 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
2015 type = type || "fx";
2016
2017 return this.queue( type, function( next, hooks ) {
2018 var timeout = setTimeout( next, time );
2019 hooks.stop = function() {
2020 clearTimeout( timeout );
2021 };
2022 });
2023 },
2024 clearQueue: function( type ) {
2025 return this.queue( type || "fx", [] );
2026 },
2027 // Get a promise resolved when queues of a certain type
2028 // are emptied (fx is the type by default)
2029 promise: function( type, obj ) {
2030 var tmp,
2031 count = 1,
2032 defer = jQuery.Deferred(),
2033 elements = this,
2034 i = this.length,
2035 resolve = function() {
2036 if ( !( --count ) ) {
2037 defer.resolveWith( elements, [ elements ] );
2038 }
2039 };
2040
2041 if ( typeof type !== "string" ) {
2042 obj = type;
2043 type = undefined;
2044 }
2045 type = type || "fx";
2046
2047 while( i-- ) {
2048 tmp = jQuery._data( elements[ i ], type + "queueHooks" );
2049 if ( tmp && tmp.empty ) {
2050 count++;
2051 tmp.empty.add( resolve );
2052 }
2053 }
2054 resolve();
2055 return defer.promise( obj );
2056 }
2057});
2058var nodeHook, boolHook,
2059 rclass = /[\t\r\n]/g,
2060 rreturn = /\r/g,
2061 rfocusable = /^(?:input|select|textarea|button|object)$/i,
2062 rclickable = /^(?:a|area)$/i,
2063 rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
2064 ruseDefault = /^(?:checked|selected)$/i,
2065 getSetAttribute = jQuery.support.getSetAttribute,
2066 getSetInput = jQuery.support.input;
2067
2068jQuery.fn.extend({
2069 attr: function( name, value ) {
2070 return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
2071 },
2072
2073 removeAttr: function( name ) {
2074 return this.each(function() {
2075 jQuery.removeAttr( this, name );
2076 });
2077 },
2078
2079 prop: function( name, value ) {
2080 return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
2081 },
2082
2083 removeProp: function( name ) {
2084 name = jQuery.propFix[ name ] || name;
2085 return this.each(function() {
2086 // try/catch handles cases where IE balks (such as removing a property on window)
2087 try {
2088 this[ name ] = undefined;
2089 delete this[ name ];
2090 } catch( e ) {}
2091 });
2092 },
2093
2094 addClass: function( value ) {
2095 var classes, elem, cur, clazz, j,
2096 i = 0,
2097 len = this.length,
2098 proceed = typeof value === "string" && value;
2099
2100 if ( jQuery.isFunction( value ) ) {
2101 return this.each(function( j ) {
2102 jQuery( this ).addClass( value.call( this, j, this.className ) );
2103 });
2104 }
2105
2106 if ( proceed ) {
2107 // The disjunction here is for better compressibility (see removeClass)
2108 classes = ( value || "" ).match( core_rnotwhite ) || [];
2109
2110 for ( ; i < len; i++ ) {
2111 elem = this[ i ];
2112 cur = elem.nodeType === 1 && ( elem.className ?
2113 ( " " + elem.className + " " ).replace( rclass, " " ) :
2114 " "
2115 );
2116
2117 if ( cur ) {
2118 j = 0;
2119 while ( (clazz = classes[j++]) ) {
2120 if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
2121 cur += clazz + " ";
2122 }
2123 }
2124 elem.className = jQuery.trim( cur );
2125
2126 }
2127 }
2128 }
2129
2130 return this;
2131 },
2132
2133 removeClass: function( value ) {
2134 var classes, elem, cur, clazz, j,
2135 i = 0,
2136 len = this.length,
2137 proceed = arguments.length === 0 || typeof value === "string" && value;
2138
2139 if ( jQuery.isFunction( value ) ) {
2140 return this.each(function( j ) {
2141 jQuery( this ).removeClass( value.call( this, j, this.className ) );
2142 });
2143 }
2144 if ( proceed ) {
2145 classes = ( value || "" ).match( core_rnotwhite ) || [];
2146
2147 for ( ; i < len; i++ ) {
2148 elem = this[ i ];
2149 // This expression is here for better compressibility (see addClass)
2150 cur = elem.nodeType === 1 && ( elem.className ?
2151 ( " " + elem.className + " " ).replace( rclass, " " ) :
2152 ""
2153 );
2154
2155 if ( cur ) {
2156 j = 0;
2157 while ( (clazz = classes[j++]) ) {
2158 // Remove *all* instances
2159 while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
2160 cur = cur.replace( " " + clazz + " ", " " );
2161 }
2162 }
2163 elem.className = value ? jQuery.trim( cur ) : "";
2164 }
2165 }
2166 }
2167
2168 return this;
2169 },
2170
2171 toggleClass: function( value, stateVal ) {
2172 var type = typeof value,
2173 isBool = typeof stateVal === "boolean";
2174
2175 if ( jQuery.isFunction( value ) ) {
2176 return this.each(function( i ) {
2177 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2178 });
2179 }
2180
2181 return this.each(function() {
2182 if ( type === "string" ) {
2183 // toggle individual class names
2184 var className,
2185 i = 0,
2186 self = jQuery( this ),
2187 state = stateVal,
2188 classNames = value.match( core_rnotwhite ) || [];
2189
2190 while ( (className = classNames[ i++ ]) ) {
2191 // check each className given, space separated list
2192 state = isBool ? state : !self.hasClass( className );
2193 self[ state ? "addClass" : "removeClass" ]( className );
2194 }
2195
2196 // Toggle whole class name
2197 } else if ( type === core_strundefined || type === "boolean" ) {
2198 if ( this.className ) {
2199 // store className if set
2200 jQuery._data( this, "__className__", this.className );
2201 }
2202
2203 // If the element has a class name or if we're passed "false",
2204 // then remove the whole classname (if there was one, the above saved it).
2205 // Otherwise bring back whatever was previously saved (if anything),
2206 // falling back to the empty string if nothing was stored.
2207 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2208 }
2209 });
2210 },
2211
2212 hasClass: function( selector ) {
2213 var className = " " + selector + " ",
2214 i = 0,
2215 l = this.length;
2216 for ( ; i < l; i++ ) {
2217 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
2218 return true;
2219 }
2220 }
2221
2222 return false;
2223 },
2224
2225 val: function( value ) {
2226 var ret, hooks, isFunction,
2227 elem = this[0];
2228
2229 if ( !arguments.length ) {
2230 if ( elem ) {
2231 hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
2232
2233 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2234 return ret;
2235 }
2236
2237 ret = elem.value;
2238
2239 return typeof ret === "string" ?
2240 // handle most common string cases
2241 ret.replace(rreturn, "") :
2242 // handle cases where value is null/undef or number
2243 ret == null ? "" : ret;
2244 }
2245
2246 return;
2247 }
2248
2249 isFunction = jQuery.isFunction( value );
2250
2251 return this.each(function( i ) {
2252 var val,
2253 self = jQuery(this);
2254
2255 if ( this.nodeType !== 1 ) {
2256 return;
2257 }
2258
2259 if ( isFunction ) {
2260 val = value.call( this, i, self.val() );
2261 } else {
2262 val = value;
2263 }
2264
2265 // Treat null/undefined as ""; convert numbers to string
2266 if ( val == null ) {
2267 val = "";
2268 } else if ( typeof val === "number" ) {
2269 val += "";
2270 } else if ( jQuery.isArray( val ) ) {
2271 val = jQuery.map(val, function ( value ) {
2272 return value == null ? "" : value + "";
2273 });
2274 }
2275
2276 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
2277
2278 // If set returns undefined, fall back to normal setting
2279 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2280 this.value = val;
2281 }
2282 });
2283 }
2284});
2285
2286jQuery.extend({
2287 valHooks: {
2288 option: {
2289 get: function( elem ) {
2290 // attributes.value is undefined in Blackberry 4.7 but
2291 // uses .value. See #6932
2292 var val = elem.attributes.value;
2293 return !val || val.specified ? elem.value : elem.text;
2294 }
2295 },
2296 select: {
2297 get: function( elem ) {
2298 var value, option,
2299 options = elem.options,
2300 index = elem.selectedIndex,
2301 one = elem.type === "select-one" || index < 0,
2302 values = one ? null : [],
2303 max = one ? index + 1 : options.length,
2304 i = index < 0 ?
2305 max :
2306 one ? index : 0;
2307
2308 // Loop through all the selected options
2309 for ( ; i < max; i++ ) {
2310 option = options[ i ];
2311
2312 // oldIE doesn't update selected after form reset (#2551)
2313 if ( ( option.selected || i === index ) &&
2314 // Don't return options that are disabled or in a disabled optgroup
2315 ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
2316 ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
2317
2318 // Get the specific value for the option
2319 value = jQuery( option ).val();
2320
2321 // We don't need an array for one selects
2322 if ( one ) {
2323 return value;
2324 }
2325
2326 // Multi-Selects return an array
2327 values.push( value );
2328 }
2329 }
2330
2331 return values;
2332 },
2333
2334 set: function( elem, value ) {
2335 var values = jQuery.makeArray( value );
2336
2337 jQuery(elem).find("option").each(function() {
2338 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2339 });
2340
2341 if ( !values.length ) {
2342 elem.selectedIndex = -1;
2343 }
2344 return values;
2345 }
2346 }
2347 },
2348
2349 attr: function( elem, name, value ) {
2350 var hooks, notxml, ret,
2351 nType = elem.nodeType;
2352
2353 // don't get/set attributes on text, comment and attribute nodes
2354 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2355 return;
2356 }
2357
2358 // Fallback to prop when attributes are not supported
2359 if ( typeof elem.getAttribute === core_strundefined ) {
2360 return jQuery.prop( elem, name, value );
2361 }
2362
2363 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2364
2365 // All attributes are lowercase
2366 // Grab necessary hook if one is defined
2367 if ( notxml ) {
2368 name = name.toLowerCase();
2369 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
2370 }
2371
2372 if ( value !== undefined ) {
2373
2374 if ( value === null ) {
2375 jQuery.removeAttr( elem, name );
2376
2377 } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2378 return ret;
2379
2380 } else {
2381 elem.setAttribute( name, value + "" );
2382 return value;
2383 }
2384
2385 } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2386 return ret;
2387
2388 } else {
2389
2390 // In IE9+, Flash objects don't have .getAttribute (#12945)
2391 // Support: IE9+
2392 if ( typeof elem.getAttribute !== core_strundefined ) {
2393 ret = elem.getAttribute( name );
2394 }
2395
2396 // Non-existent attributes return null, we normalize to undefined
2397 return ret == null ?
2398 undefined :
2399 ret;
2400 }
2401 },
2402
2403 removeAttr: function( elem, value ) {
2404 var name, propName,
2405 i = 0,
2406 attrNames = value && value.match( core_rnotwhite );
2407
2408 if ( attrNames && elem.nodeType === 1 ) {
2409 while ( (name = attrNames[i++]) ) {
2410 propName = jQuery.propFix[ name ] || name;
2411
2412 // Boolean attributes get special treatment (#10870)
2413 if ( rboolean.test( name ) ) {
2414 // Set corresponding property to false for boolean attributes
2415 // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
2416 if ( !getSetAttribute && ruseDefault.test( name ) ) {
2417 elem[ jQuery.camelCase( "default-" + name ) ] =
2418 elem[ propName ] = false;
2419 } else {
2420 elem[ propName ] = false;
2421 }
2422
2423 // See #9699 for explanation of this approach (setting first, then removal)
2424 } else {
2425 jQuery.attr( elem, name, "" );
2426 }
2427
2428 elem.removeAttribute( getSetAttribute ? name : propName );
2429 }
2430 }
2431 },
2432
2433 attrHooks: {
2434 type: {
2435 set: function( elem, value ) {
2436 if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2437 // Setting the type on a radio button after the value resets the value in IE6-9
2438 // Reset value to default in case type is set after value during creation
2439 var val = elem.value;
2440 elem.setAttribute( "type", value );
2441 if ( val ) {
2442 elem.value = val;
2443 }
2444 return value;
2445 }
2446 }
2447 }
2448 },
2449
2450 propFix: {
2451 tabindex: "tabIndex",
2452 readonly: "readOnly",
2453 "for": "htmlFor",
2454 "class": "className",
2455 maxlength: "maxLength",
2456 cellspacing: "cellSpacing",
2457 cellpadding: "cellPadding",
2458 rowspan: "rowSpan",
2459 colspan: "colSpan",
2460 usemap: "useMap",
2461 frameborder: "frameBorder",
2462 contenteditable: "contentEditable"
2463 },
2464
2465 prop: function( elem, name, value ) {
2466 var ret, hooks, notxml,
2467 nType = elem.nodeType;
2468
2469 // don't get/set properties on text, comment and attribute nodes
2470 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2471 return;
2472 }
2473
2474 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2475
2476 if ( notxml ) {
2477 // Fix name and attach hooks
2478 name = jQuery.propFix[ name ] || name;
2479 hooks = jQuery.propHooks[ name ];
2480 }
2481
2482 if ( value !== undefined ) {
2483 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2484 return ret;
2485
2486 } else {
2487 return ( elem[ name ] = value );
2488 }
2489
2490 } else {
2491 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
2492 return ret;
2493
2494 } else {
2495 return elem[ name ];
2496 }
2497 }
2498 },
2499
2500 propHooks: {
2501 tabIndex: {
2502 get: function( elem ) {
2503 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2504 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2505 var attributeNode = elem.getAttributeNode("tabindex");
2506
2507 return attributeNode && attributeNode.specified ?
2508 parseInt( attributeNode.value, 10 ) :
2509 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2510 0 :
2511 undefined;
2512 }
2513 }
2514 }
2515});
2516
2517// Hook for boolean attributes
2518boolHook = {
2519 get: function( elem, name ) {
2520 var
2521 // Use .prop to determine if this attribute is understood as boolean
2522 prop = jQuery.prop( elem, name ),
2523
2524 // Fetch it accordingly
2525 attr = typeof prop === "boolean" && elem.getAttribute( name ),
2526 detail = typeof prop === "boolean" ?
2527
2528 getSetInput && getSetAttribute ?
2529 attr != null :
2530 // oldIE fabricates an empty string for missing boolean attributes
2531 // and conflates checked/selected into attroperties
2532 ruseDefault.test( name ) ?
2533 elem[ jQuery.camelCase( "default-" + name ) ] :
2534 !!attr :
2535
2536 // fetch an attribute node for properties not recognized as boolean
2537 elem.getAttributeNode( name );
2538
2539 return detail && detail.value !== false ?
2540 name.toLowerCase() :
2541 undefined;
2542 },
2543 set: function( elem, value, name ) {
2544 if ( value === false ) {
2545 // Remove boolean attributes when set to false
2546 jQuery.removeAttr( elem, name );
2547 } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
2548 // IE<8 needs the *property* name
2549 elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
2550
2551 // Use defaultChecked and defaultSelected for oldIE
2552 } else {
2553 elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
2554 }
2555
2556 return name;
2557 }
2558};
2559
2560// fix oldIE value attroperty
2561if ( !getSetInput || !getSetAttribute ) {
2562 jQuery.attrHooks.value = {
2563 get: function( elem, name ) {
2564 var ret = elem.getAttributeNode( name );
2565 return jQuery.nodeName( elem, "input" ) ?
2566
2567 // Ignore the value *property* by using defaultValue
2568 elem.defaultValue :
2569
2570 ret && ret.specified ? ret.value : undefined;
2571 },
2572 set: function( elem, value, name ) {
2573 if ( jQuery.nodeName( elem, "input" ) ) {
2574 // Does not return so that setAttribute is also used
2575 elem.defaultValue = value;
2576 } else {
2577 // Use nodeHook if defined (#1954); otherwise setAttribute is fine
2578 return nodeHook && nodeHook.set( elem, value, name );
2579 }
2580 }
2581 };
2582}
2583
2584// IE6/7 do not support getting/setting some attributes with get/setAttribute
2585if ( !getSetAttribute ) {
2586
2587 // Use this for any attribute in IE6/7
2588 // This fixes almost every IE6/7 issue
2589 nodeHook = jQuery.valHooks.button = {
2590 get: function( elem, name ) {
2591 var ret = elem.getAttributeNode( name );
2592 return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
2593 ret.value :
2594 undefined;
2595 },
2596 set: function( elem, value, name ) {
2597 // Set the existing or create a new attribute node
2598 var ret = elem.getAttributeNode( name );
2599 if ( !ret ) {
2600 elem.setAttributeNode(
2601 (ret = elem.ownerDocument.createAttribute( name ))
2602 );
2603 }
2604
2605 ret.value = value += "";
2606
2607 // Break association with cloned elements by also using setAttribute (#9646)
2608 return name === "value" || value === elem.getAttribute( name ) ?
2609 value :
2610 undefined;
2611 }
2612 };
2613
2614 // Set contenteditable to false on removals(#10429)
2615 // Setting to empty string throws an error as an invalid value
2616 jQuery.attrHooks.contenteditable = {
2617 get: nodeHook.get,
2618 set: function( elem, value, name ) {
2619 nodeHook.set( elem, value === "" ? false : value, name );
2620 }
2621 };
2622
2623 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2624 // This is for removals
2625 jQuery.each([ "width", "height" ], function( i, name ) {
2626 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2627 set: function( elem, value ) {
2628 if ( value === "" ) {
2629 elem.setAttribute( name, "auto" );
2630 return value;
2631 }
2632 }
2633 });
2634 });
2635}
2636
2637
2638// Some attributes require a special call on IE
2639// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
2640if ( !jQuery.support.hrefNormalized ) {
2641 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2642 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2643 get: function( elem ) {
2644 var ret = elem.getAttribute( name, 2 );
2645 return ret == null ? undefined : ret;
2646 }
2647 });
2648 });
2649
2650 // href/src property should get the full normalized URL (#10299/#12915)
2651 jQuery.each([ "href", "src" ], function( i, name ) {
2652 jQuery.propHooks[ name ] = {
2653 get: function( elem ) {
2654 return elem.getAttribute( name, 4 );
2655 }
2656 };
2657 });
2658}
2659
2660if ( !jQuery.support.style ) {
2661 jQuery.attrHooks.style = {
2662 get: function( elem ) {
2663 // Return undefined in the case of empty string
2664 // Note: IE uppercases css property names, but if we were to .toLowerCase()
2665 // .cssText, that would destroy case senstitivity in URL's, like in "background"
2666 return elem.style.cssText || undefined;
2667 },
2668 set: function( elem, value ) {
2669 return ( elem.style.cssText = value + "" );
2670 }
2671 };
2672}
2673
2674// Safari mis-reports the default selected property of an option
2675// Accessing the parent's selectedIndex property fixes it
2676if ( !jQuery.support.optSelected ) {
2677 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2678 get: function( elem ) {
2679 var parent = elem.parentNode;
2680
2681 if ( parent ) {
2682 parent.selectedIndex;
2683
2684 // Make sure that it also works with optgroups, see #5701
2685 if ( parent.parentNode ) {
2686 parent.parentNode.selectedIndex;
2687 }
2688 }
2689 return null;
2690 }
2691 });
2692}
2693
2694// IE6/7 call enctype encoding
2695if ( !jQuery.support.enctype ) {
2696 jQuery.propFix.enctype = "encoding";
2697}
2698
2699// Radios and checkboxes getter/setter
2700if ( !jQuery.support.checkOn ) {
2701 jQuery.each([ "radio", "checkbox" ], function() {
2702 jQuery.valHooks[ this ] = {
2703 get: function( elem ) {
2704 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2705 return elem.getAttribute("value") === null ? "on" : elem.value;
2706 }
2707 };
2708 });
2709}
2710jQuery.each([ "radio", "checkbox" ], function() {
2711 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2712 set: function( elem, value ) {
2713 if ( jQuery.isArray( value ) ) {
2714 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
2715 }
2716 }
2717 });
2718});
2719var rformElems = /^(?:input|select|textarea)$/i,
2720 rkeyEvent = /^key/,
2721 rmouseEvent = /^(?:mouse|contextmenu)|click/,
2722 rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
2723 rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
2724
2725function returnTrue() {
2726 return true;
2727}
2728
2729function returnFalse() {
2730 return false;
2731}
2732
2733/*
2734 * Helper functions for managing events -- not part of the public interface.
2735 * Props to Dean Edwards' addEvent library for many of the ideas.
2736 */
2737jQuery.event = {
2738
2739 global: {},
2740
2741 add: function( elem, types, handler, data, selector ) {
2742 var tmp, events, t, handleObjIn,
2743 special, eventHandle, handleObj,
2744 handlers, type, namespaces, origType,
2745 elemData = jQuery._data( elem );
2746
2747 // Don't attach events to noData or text/comment nodes (but allow plain objects)
2748 if ( !elemData ) {
2749 return;
2750 }
2751
2752 // Caller can pass in an object of custom data in lieu of the handler
2753 if ( handler.handler ) {
2754 handleObjIn = handler;
2755 handler = handleObjIn.handler;
2756 selector = handleObjIn.selector;
2757 }
2758
2759 // Make sure that the handler has a unique ID, used to find/remove it later
2760 if ( !handler.guid ) {
2761 handler.guid = jQuery.guid++;
2762 }
2763
2764 // Init the element's event structure and main handler, if this is the first
2765 if ( !(events = elemData.events) ) {
2766 events = elemData.events = {};
2767 }
2768 if ( !(eventHandle = elemData.handle) ) {
2769 eventHandle = elemData.handle = function( e ) {
2770 // Discard the second event of a jQuery.event.trigger() and
2771 // when an event is called after a page has unloaded
2772 return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
2773 jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
2774 undefined;
2775 };
2776 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
2777 eventHandle.elem = elem;
2778 }
2779
2780 // Handle multiple events separated by a space
2781 // jQuery(...).bind("mouseover mouseout", fn);
2782 types = ( types || "" ).match( core_rnotwhite ) || [""];
2783 t = types.length;
2784 while ( t-- ) {
2785 tmp = rtypenamespace.exec( types[t] ) || [];
2786 type = origType = tmp[1];
2787 namespaces = ( tmp[2] || "" ).split( "." ).sort();
2788
2789 // If event changes its type, use the special event handlers for the changed type
2790 special = jQuery.event.special[ type ] || {};
2791
2792 // If selector defined, determine special event api type, otherwise given type
2793 type = ( selector ? special.delegateType : special.bindType ) || type;
2794
2795 // Update special based on newly reset type
2796 special = jQuery.event.special[ type ] || {};
2797
2798 // handleObj is passed to all event handlers
2799 handleObj = jQuery.extend({
2800 type: type,
2801 origType: origType,
2802 data: data,
2803 handler: handler,
2804 guid: handler.guid,
2805 selector: selector,
2806 needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
2807 namespace: namespaces.join(".")
2808 }, handleObjIn );
2809
2810 // Init the event handler queue if we're the first
2811 if ( !(handlers = events[ type ]) ) {
2812 handlers = events[ type ] = [];
2813 handlers.delegateCount = 0;
2814
2815 // Only use addEventListener/attachEvent if the special events handler returns false
2816 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2817 // Bind the global event handler to the element
2818 if ( elem.addEventListener ) {
2819 elem.addEventListener( type, eventHandle, false );
2820
2821 } else if ( elem.attachEvent ) {
2822 elem.attachEvent( "on" + type, eventHandle );
2823 }
2824 }
2825 }
2826
2827 if ( special.add ) {
2828 special.add.call( elem, handleObj );
2829
2830 if ( !handleObj.handler.guid ) {
2831 handleObj.handler.guid = handler.guid;
2832 }
2833 }
2834
2835 // Add to the element's handler list, delegates in front
2836 if ( selector ) {
2837 handlers.splice( handlers.delegateCount++, 0, handleObj );
2838 } else {
2839 handlers.push( handleObj );
2840 }
2841
2842 // Keep track of which events have ever been used, for event optimization
2843 jQuery.event.global[ type ] = true;
2844 }
2845
2846 // Nullify elem to prevent memory leaks in IE
2847 elem = null;
2848 },
2849
2850 // Detach an event or set of events from an element
2851 remove: function( elem, types, handler, selector, mappedTypes ) {
2852 var j, handleObj, tmp,
2853 origCount, t, events,
2854 special, handlers, type,
2855 namespaces, origType,
2856 elemData = jQuery.hasData( elem ) && jQuery._data( elem );
2857
2858 if ( !elemData || !(events = elemData.events) ) {
2859 return;
2860 }
2861
2862 // Once for each type.namespace in types; type may be omitted
2863 types = ( types || "" ).match( core_rnotwhite ) || [""];
2864 t = types.length;
2865 while ( t-- ) {
2866 tmp = rtypenamespace.exec( types[t] ) || [];
2867 type = origType = tmp[1];
2868 namespaces = ( tmp[2] || "" ).split( "." ).sort();
2869
2870 // Unbind all events (on this namespace, if provided) for the element
2871 if ( !type ) {
2872 for ( type in events ) {
2873 jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
2874 }
2875 continue;
2876 }
2877
2878 special = jQuery.event.special[ type ] || {};
2879 type = ( selector ? special.delegateType : special.bindType ) || type;
2880 handlers = events[ type ] || [];
2881 tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
2882
2883 // Remove matching events
2884 origCount = j = handlers.length;
2885 while ( j-- ) {
2886 handleObj = handlers[ j ];
2887
2888 if ( ( mappedTypes || origType === handleObj.origType ) &&
2889 ( !handler || handler.guid === handleObj.guid ) &&
2890 ( !tmp || tmp.test( handleObj.namespace ) ) &&
2891 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
2892 handlers.splice( j, 1 );
2893
2894 if ( handleObj.selector ) {
2895 handlers.delegateCount--;
2896 }
2897 if ( special.remove ) {
2898 special.remove.call( elem, handleObj );
2899 }
2900 }
2901 }
2902
2903 // Remove generic event handler if we removed something and no more handlers exist
2904 // (avoids potential for endless recursion during removal of special event handlers)
2905 if ( origCount && !handlers.length ) {
2906 if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
2907 jQuery.removeEvent( elem, type, elemData.handle );
2908 }
2909
2910 delete events[ type ];
2911 }
2912 }
2913
2914 // Remove the expando if it's no longer used
2915 if ( jQuery.isEmptyObject( events ) ) {
2916 delete elemData.handle;
2917
2918 // removeData also checks for emptiness and clears the expando if empty
2919 // so use it instead of delete
2920 jQuery._removeData( elem, "events" );
2921 }
2922 },
2923
2924 trigger: function( event, data, elem, onlyHandlers ) {
2925 var handle, ontype, cur,
2926 bubbleType, special, tmp, i,
2927 eventPath = [ elem || document ],
2928 type = core_hasOwn.call( event, "type" ) ? event.type : event,
2929 namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
2930
2931 cur = tmp = elem = elem || document;
2932
2933 // Don't do events on text and comment nodes
2934 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2935 return;
2936 }
2937
2938 // focus/blur morphs to focusin/out; ensure we're not firing them right now
2939 if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
2940 return;
2941 }
2942
2943 if ( type.indexOf(".") >= 0 ) {
2944 // Namespaced trigger; create a regexp to match event type in handle()
2945 namespaces = type.split(".");
2946 type = namespaces.shift();
2947 namespaces.sort();
2948 }
2949 ontype = type.indexOf(":") < 0 && "on" + type;
2950
2951 // Caller can pass in a jQuery.Event object, Object, or just an event type string
2952 event = event[ jQuery.expando ] ?
2953 event :
2954 new jQuery.Event( type, typeof event === "object" && event );
2955
2956 event.isTrigger = true;
2957 event.namespace = namespaces.join(".");
2958 event.namespace_re = event.namespace ?
2959 new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
2960 null;
2961
2962 // Clean up the event in case it is being reused
2963 event.result = undefined;
2964 if ( !event.target ) {
2965 event.target = elem;
2966 }
2967
2968 // Clone any incoming data and prepend the event, creating the handler arg list
2969 data = data == null ?
2970 [ event ] :
2971 jQuery.makeArray( data, [ event ] );
2972
2973 // Allow special events to draw outside the lines
2974 special = jQuery.event.special[ type ] || {};
2975 if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
2976 return;
2977 }
2978
2979 // Determine event propagation path in advance, per W3C events spec (#9951)
2980 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
2981 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
2982
2983 bubbleType = special.delegateType || type;
2984 if ( !rfocusMorph.test( bubbleType + type ) ) {
2985 cur = cur.parentNode;
2986 }
2987 for ( ; cur; cur = cur.parentNode ) {
2988 eventPath.push( cur );
2989 tmp = cur;
2990 }
2991
2992 // Only add window if we got to document (e.g., not plain obj or detached DOM)
2993 if ( tmp === (elem.ownerDocument || document) ) {
2994 eventPath.push( tmp.defaultView || tmp.parentWindow || window );
2995 }
2996 }
2997
2998 // Fire handlers on the event path
2999 i = 0;
3000 while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
3001
3002 event.type = i > 1 ?
3003 bubbleType :
3004 special.bindType || type;
3005
3006 // jQuery handler
3007 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
3008 if ( handle ) {
3009 handle.apply( cur, data );
3010 }
3011
3012 // Native handler
3013 handle = ontype && cur[ ontype ];
3014 if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
3015 event.preventDefault();
3016 }
3017 }
3018 event.type = type;
3019
3020 // If nobody prevented the default action, do it now
3021 if ( !onlyHandlers && !event.isDefaultPrevented() ) {
3022
3023 if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
3024 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
3025
3026 // Call a native DOM method on the target with the same name name as the event.
3027 // Can't use an .isFunction() check here because IE6/7 fails that test.
3028 // Don't do default actions on window, that's where global variables be (#6170)
3029 if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
3030
3031 // Don't re-trigger an onFOO event when we call its FOO() method
3032 tmp = elem[ ontype ];
3033
3034 if ( tmp ) {
3035 elem[ ontype ] = null;
3036 }
3037
3038 // Prevent re-triggering of the same event, since we already bubbled it above
3039 jQuery.event.triggered = type;
3040 try {
3041 elem[ type ]();
3042 } catch ( e ) {
3043 // IE<9 dies on focus/blur to hidden element (#1486,#12518)
3044 // only reproducible on winXP IE8 native, not IE9 in IE8 mode
3045 }
3046 jQuery.event.triggered = undefined;
3047
3048 if ( tmp ) {
3049 elem[ ontype ] = tmp;
3050 }
3051 }
3052 }
3053 }
3054
3055 return event.result;
3056 },
3057
3058 dispatch: function( event ) {
3059
3060 // Make a writable jQuery.Event from the native event object
3061 event = jQuery.event.fix( event );
3062
3063 var i, ret, handleObj, matched, j,
3064 handlerQueue = [],
3065 args = core_slice.call( arguments ),
3066 handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
3067 special = jQuery.event.special[ event.type ] || {};
3068
3069 // Use the fix-ed jQuery.Event rather than the (read-only) native event
3070 args[0] = event;
3071 event.delegateTarget = this;
3072
3073 // Call the preDispatch hook for the mapped type, and let it bail if desired
3074 if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
3075 return;
3076 }
3077
3078 // Determine handlers
3079 handlerQueue = jQuery.event.handlers.call( this, event, handlers );
3080
3081 // Run delegates first; they may want to stop propagation beneath us
3082 i = 0;
3083 while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
3084 event.currentTarget = matched.elem;
3085
3086 j = 0;
3087 while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
3088
3089 // Triggered event must either 1) have no namespace, or
3090 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3091 if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
3092
3093 event.handleObj = handleObj;
3094 event.data = handleObj.data;
3095
3096 ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
3097 .apply( matched.elem, args );
3098
3099 if ( ret !== undefined ) {
3100 if ( (event.result = ret) === false ) {
3101 event.preventDefault();
3102 event.stopPropagation();
3103 }
3104 }
3105 }
3106 }
3107 }
3108
3109 // Call the postDispatch hook for the mapped type
3110 if ( special.postDispatch ) {
3111 special.postDispatch.call( this, event );
3112 }
3113
3114 return event.result;
3115 },
3116
3117 handlers: function( event, handlers ) {
3118 var sel, handleObj, matches, i,
3119 handlerQueue = [],
3120 delegateCount = handlers.delegateCount,
3121 cur = event.target;
3122
3123 // Find delegate handlers
3124 // Black-hole SVG <use> instance trees (#13180)
3125 // Avoid non-left-click bubbling in Firefox (#3861)
3126 if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
3127
3128 for ( ; cur != this; cur = cur.parentNode || this ) {
3129
3130 // Don't check non-elements (#13208)
3131 // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
3132 if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
3133 matches = [];
3134 for ( i = 0; i < delegateCount; i++ ) {
3135 handleObj = handlers[ i ];
3136
3137 // Don't conflict with Object.prototype properties (#13203)
3138 sel = handleObj.selector + " ";
3139
3140 if ( matches[ sel ] === undefined ) {
3141 matches[ sel ] = handleObj.needsContext ?
3142 jQuery( sel, this ).index( cur ) >= 0 :
3143 jQuery.find( sel, this, null, [ cur ] ).length;
3144 }
3145 if ( matches[ sel ] ) {
3146 matches.push( handleObj );
3147 }
3148 }
3149 if ( matches.length ) {
3150 handlerQueue.push({ elem: cur, handlers: matches });
3151 }
3152 }
3153 }
3154 }
3155
3156 // Add the remaining (directly-bound) handlers
3157 if ( delegateCount < handlers.length ) {
3158 handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
3159 }
3160
3161 return handlerQueue;
3162 },
3163
3164 fix: function( event ) {
3165 if ( event[ jQuery.expando ] ) {
3166 return event;
3167 }
3168
3169 // Create a writable copy of the event object and normalize some properties
3170 var i, prop, copy,
3171 type = event.type,
3172 originalEvent = event,
3173 fixHook = this.fixHooks[ type ];
3174
3175 if ( !fixHook ) {
3176 this.fixHooks[ type ] = fixHook =
3177 rmouseEvent.test( type ) ? this.mouseHooks :
3178 rkeyEvent.test( type ) ? this.keyHooks :
3179 {};
3180 }
3181 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
3182
3183 event = new jQuery.Event( originalEvent );
3184
3185 i = copy.length;
3186 while ( i-- ) {
3187 prop = copy[ i ];
3188 event[ prop ] = originalEvent[ prop ];
3189 }
3190
3191 // Support: IE<9
3192 // Fix target property (#1925)
3193 if ( !event.target ) {
3194 event.target = originalEvent.srcElement || document;
3195 }
3196
3197 // Support: Chrome 23+, Safari?
3198 // Target should not be a text node (#504, #13143)
3199 if ( event.target.nodeType === 3 ) {
3200 event.target = event.target.parentNode;
3201 }
3202
3203 // Support: IE<9
3204 // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
3205 event.metaKey = !!event.metaKey;
3206
3207 return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
3208 },
3209
3210 // Includes some event props shared by KeyEvent and MouseEvent
3211 props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3212
3213 fixHooks: {},
3214
3215 keyHooks: {
3216 props: "char charCode key keyCode".split(" "),
3217 filter: function( event, original ) {
3218
3219 // Add which for key events
3220 if ( event.which == null ) {
3221 event.which = original.charCode != null ? original.charCode : original.keyCode;
3222 }
3223
3224 return event;
3225 }
3226 },
3227
3228 mouseHooks: {
3229 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
3230 filter: function( event, original ) {
3231 var body, eventDoc, doc,
3232 button = original.button,
3233 fromElement = original.fromElement;
3234
3235 // Calculate pageX/Y if missing and clientX/Y available
3236 if ( event.pageX == null && original.clientX != null ) {
3237 eventDoc = event.target.ownerDocument || document;
3238 doc = eventDoc.documentElement;
3239 body = eventDoc.body;
3240
3241 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3242 event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
3243 }
3244
3245 // Add relatedTarget, if necessary
3246 if ( !event.relatedTarget && fromElement ) {
3247 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3248 }
3249
3250 // Add which for click: 1 === left; 2 === middle; 3 === right
3251 // Note: button is not normalized, so don't use it
3252 if ( !event.which && button !== undefined ) {
3253 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3254 }
3255
3256 return event;
3257 }
3258 },
3259
3260 special: {
3261 load: {
3262 // Prevent triggered image.load events from bubbling to window.load
3263 noBubble: true
3264 },
3265 click: {
3266 // For checkbox, fire native event so checked state will be right
3267 trigger: function() {
3268 if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
3269 this.click();
3270 return false;
3271 }
3272 }
3273 },
3274 focus: {
3275 // Fire native event if possible so blur/focus sequence is correct
3276 trigger: function() {
3277 if ( this !== document.activeElement && this.focus ) {
3278 try {
3279 this.focus();
3280 return false;
3281 } catch ( e ) {
3282 // Support: IE<9
3283 // If we error on focus to hidden element (#1486, #12518),
3284 // let .trigger() run the handlers
3285 }
3286 }
3287 },
3288 delegateType: "focusin"
3289 },
3290 blur: {
3291 trigger: function() {
3292 if ( this === document.activeElement && this.blur ) {
3293 this.blur();
3294 return false;
3295 }
3296 },
3297 delegateType: "focusout"
3298 },
3299
3300 beforeunload: {
3301 postDispatch: function( event ) {
3302
3303 // Even when returnValue equals to undefined Firefox will still show alert
3304 if ( event.result !== undefined ) {
3305 event.originalEvent.returnValue = event.result;
3306 }
3307 }
3308 }
3309 },
3310
3311 simulate: function( type, elem, event, bubble ) {
3312 // Piggyback on a donor event to simulate a different one.
3313 // Fake originalEvent to avoid donor's stopPropagation, but if the
3314 // simulated event prevents default then we do the same on the donor.
3315 var e = jQuery.extend(
3316 new jQuery.Event(),
3317 event,
3318 { type: type,
3319 isSimulated: true,
3320 originalEvent: {}
3321 }
3322 );
3323 if ( bubble ) {
3324 jQuery.event.trigger( e, null, elem );
3325 } else {
3326 jQuery.event.dispatch.call( elem, e );
3327 }
3328 if ( e.isDefaultPrevented() ) {
3329 event.preventDefault();
3330 }
3331 }
3332};
3333
3334jQuery.removeEvent = document.removeEventListener ?
3335 function( elem, type, handle ) {
3336 if ( elem.removeEventListener ) {
3337 elem.removeEventListener( type, handle, false );
3338 }
3339 } :
3340 function( elem, type, handle ) {
3341 var name = "on" + type;
3342
3343 if ( elem.detachEvent ) {
3344
3345 // #8545, #7054, preventing memory leaks for custom events in IE6-8
3346 // detachEvent needed property on element, by name of that event, to properly expose it to GC
3347 if ( typeof elem[ name ] === core_strundefined ) {
3348 elem[ name ] = null;
3349 }
3350
3351 elem.detachEvent( name, handle );
3352 }
3353 };
3354
3355jQuery.Event = function( src, props ) {
3356 // Allow instantiation without the 'new' keyword
3357 if ( !(this instanceof jQuery.Event) ) {
3358 return new jQuery.Event( src, props );
3359 }
3360
3361 // Event object
3362 if ( src && src.type ) {
3363 this.originalEvent = src;
3364 this.type = src.type;
3365
3366 // Events bubbling up the document may have been marked as prevented
3367 // by a handler lower down the tree; reflect the correct value.
3368 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
3369 src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
3370
3371 // Event type
3372 } else {
3373 this.type = src;
3374 }
3375
3376 // Put explicitly provided properties onto the event object
3377 if ( props ) {
3378 jQuery.extend( this, props );
3379 }
3380
3381 // Create a timestamp if incoming event doesn't have one
3382 this.timeStamp = src && src.timeStamp || jQuery.now();
3383
3384 // Mark it as fixed
3385 this[ jQuery.expando ] = true;
3386};
3387
3388// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3389// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3390jQuery.Event.prototype = {
3391 isDefaultPrevented: returnFalse,
3392 isPropagationStopped: returnFalse,
3393 isImmediatePropagationStopped: returnFalse,
3394
3395 preventDefault: function() {
3396 var e = this.originalEvent;
3397
3398 this.isDefaultPrevented = returnTrue;
3399 if ( !e ) {
3400 return;
3401 }
3402
3403 // If preventDefault exists, run it on the original event
3404 if ( e.preventDefault ) {
3405 e.preventDefault();
3406
3407 // Support: IE
3408 // Otherwise set the returnValue property of the original event to false
3409 } else {
3410 e.returnValue = false;
3411 }
3412 },
3413 stopPropagation: function() {
3414 var e = this.originalEvent;
3415
3416 this.isPropagationStopped = returnTrue;
3417 if ( !e ) {
3418 return;
3419 }
3420 // If stopPropagation exists, run it on the original event
3421 if ( e.stopPropagation ) {
3422 e.stopPropagation();
3423 }
3424
3425 // Support: IE
3426 // Set the cancelBubble property of the original event to true
3427 e.cancelBubble = true;
3428 },
3429 stopImmediatePropagation: function() {
3430 this.isImmediatePropagationStopped = returnTrue;
3431 this.stopPropagation();
3432 }
3433};
3434
3435// Create mouseenter/leave events using mouseover/out and event-time checks
3436jQuery.each({
3437 mouseenter: "mouseover",
3438 mouseleave: "mouseout"
3439}, function( orig, fix ) {
3440 jQuery.event.special[ orig ] = {
3441 delegateType: fix,
3442 bindType: fix,
3443
3444 handle: function( event ) {
3445 var ret,
3446 target = this,
3447 related = event.relatedTarget,
3448 handleObj = event.handleObj;
3449
3450 // For mousenter/leave call the handler if related is outside the target.
3451 // NB: No relatedTarget if the mouse left/entered the browser window
3452 if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
3453 event.type = handleObj.origType;
3454 ret = handleObj.handler.apply( this, arguments );
3455 event.type = fix;
3456 }
3457 return ret;
3458 }
3459 };
3460});
3461
3462// IE submit delegation
3463if ( !jQuery.support.submitBubbles ) {
3464
3465 jQuery.event.special.submit = {
3466 setup: function() {
3467 // Only need this for delegated form submit events
3468 if ( jQuery.nodeName( this, "form" ) ) {
3469 return false;
3470 }
3471
3472 // Lazy-add a submit handler when a descendant form may potentially be submitted
3473 jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
3474 // Node name check avoids a VML-related crash in IE (#9807)
3475 var elem = e.target,
3476 form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
3477 if ( form && !jQuery._data( form, "submitBubbles" ) ) {
3478 jQuery.event.add( form, "submit._submit", function( event ) {
3479 event._submit_bubble = true;
3480 });
3481 jQuery._data( form, "submitBubbles", true );
3482 }
3483 });
3484 // return undefined since we don't need an event listener
3485 },
3486
3487 postDispatch: function( event ) {
3488 // If form was submitted by the user, bubble the event up the tree
3489 if ( event._submit_bubble ) {
3490 delete event._submit_bubble;
3491 if ( this.parentNode && !event.isTrigger ) {
3492 jQuery.event.simulate( "submit", this.parentNode, event, true );
3493 }
3494 }
3495 },
3496
3497 teardown: function() {
3498 // Only need this for delegated form submit events
3499 if ( jQuery.nodeName( this, "form" ) ) {
3500 return false;
3501 }
3502
3503 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
3504 jQuery.event.remove( this, "._submit" );
3505 }
3506 };
3507}
3508
3509// IE change delegation and checkbox/radio fix
3510if ( !jQuery.support.changeBubbles ) {
3511
3512 jQuery.event.special.change = {
3513
3514 setup: function() {
3515
3516 if ( rformElems.test( this.nodeName ) ) {
3517 // IE doesn't fire change on a check/radio until blur; trigger it on click
3518 // after a propertychange. Eat the blur-change in special.change.handle.
3519 // This still fires onchange a second time for check/radio after blur.
3520 if ( this.type === "checkbox" || this.type === "radio" ) {
3521 jQuery.event.add( this, "propertychange._change", function( event ) {
3522 if ( event.originalEvent.propertyName === "checked" ) {
3523 this._just_changed = true;
3524 }
3525 });
3526 jQuery.event.add( this, "click._change", function( event ) {
3527 if ( this._just_changed && !event.isTrigger ) {
3528 this._just_changed = false;
3529 }
3530 // Allow triggered, simulated change events (#11500)
3531 jQuery.event.simulate( "change", this, event, true );
3532 });
3533 }
3534 return false;
3535 }
3536 // Delegated event; lazy-add a change handler on descendant inputs
3537 jQuery.event.add( this, "beforeactivate._change", function( e ) {
3538 var elem = e.target;
3539
3540 if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
3541 jQuery.event.add( elem, "change._change", function( event ) {
3542 if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
3543 jQuery.event.simulate( "change", this.parentNode, event, true );
3544 }
3545 });
3546 jQuery._data( elem, "changeBubbles", true );
3547 }
3548 });
3549 },
3550
3551 handle: function( event ) {
3552 var elem = event.target;
3553
3554 // Swallow native change events from checkbox/radio, we already triggered them above
3555 if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
3556 return event.handleObj.handler.apply( this, arguments );
3557 }
3558 },
3559
3560 teardown: function() {
3561 jQuery.event.remove( this, "._change" );
3562
3563 return !rformElems.test( this.nodeName );
3564 }
3565 };
3566}
3567
3568// Create "bubbling" focus and blur events
3569if ( !jQuery.support.focusinBubbles ) {
3570 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
3571
3572 // Attach a single capturing handler while someone wants focusin/focusout
3573 var attaches = 0,
3574 handler = function( event ) {
3575 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
3576 };
3577
3578 jQuery.event.special[ fix ] = {
3579 setup: function() {
3580 if ( attaches++ === 0 ) {
3581 document.addEventListener( orig, handler, true );
3582 }
3583 },
3584 teardown: function() {
3585 if ( --attaches === 0 ) {
3586 document.removeEventListener( orig, handler, true );
3587 }
3588 }
3589 };
3590 });
3591}
3592
3593jQuery.fn.extend({
3594
3595 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
3596 var type, origFn;
3597
3598 // Types can be a map of types/handlers
3599 if ( typeof types === "object" ) {
3600 // ( types-Object, selector, data )
3601 if ( typeof selector !== "string" ) {
3602 // ( types-Object, data )
3603 data = data || selector;
3604 selector = undefined;
3605 }
3606 for ( type in types ) {
3607 this.on( type, selector, data, types[ type ], one );
3608 }
3609 return this;
3610 }
3611
3612 if ( data == null && fn == null ) {
3613 // ( types, fn )
3614 fn = selector;
3615 data = selector = undefined;
3616 } else if ( fn == null ) {
3617 if ( typeof selector === "string" ) {
3618 // ( types, selector, fn )
3619 fn = data;
3620 data = undefined;
3621 } else {
3622 // ( types, data, fn )
3623 fn = data;
3624 data = selector;
3625 selector = undefined;
3626 }
3627 }
3628 if ( fn === false ) {
3629 fn = returnFalse;
3630 } else if ( !fn ) {
3631 return this;
3632 }
3633
3634 if ( one === 1 ) {
3635 origFn = fn;
3636 fn = function( event ) {
3637 // Can use an empty set, since event contains the info
3638 jQuery().off( event );
3639 return origFn.apply( this, arguments );
3640 };
3641 // Use same guid so caller can remove using origFn
3642 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
3643 }
3644 return this.each( function() {
3645 jQuery.event.add( this, types, fn, data, selector );
3646 });
3647 },
3648 one: function( types, selector, data, fn ) {
3649 return this.on( types, selector, data, fn, 1 );
3650 },
3651 off: function( types, selector, fn ) {
3652 var handleObj, type;
3653 if ( types && types.preventDefault && types.handleObj ) {
3654 // ( event ) dispatched jQuery.Event
3655 handleObj = types.handleObj;
3656 jQuery( types.delegateTarget ).off(
3657 handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
3658 handleObj.selector,
3659 handleObj.handler
3660 );
3661 return this;
3662 }
3663 if ( typeof types === "object" ) {
3664 // ( types-object [, selector] )
3665 for ( type in types ) {
3666 this.off( type, selector, types[ type ] );
3667 }
3668 return this;
3669 }
3670 if ( selector === false || typeof selector === "function" ) {
3671 // ( types [, fn] )
3672 fn = selector;
3673 selector = undefined;
3674 }
3675 if ( fn === false ) {
3676 fn = returnFalse;
3677 }
3678 return this.each(function() {
3679 jQuery.event.remove( this, types, fn, selector );
3680 });
3681 },
3682
3683 bind: function( types, data, fn ) {
3684 return this.on( types, null, data, fn );
3685 },
3686 unbind: function( types, fn ) {
3687 return this.off( types, null, fn );
3688 },
3689
3690 delegate: function( selector, types, data, fn ) {
3691 return this.on( types, selector, data, fn );
3692 },
3693 undelegate: function( selector, types, fn ) {
3694 // ( namespace ) or ( selector, types [, fn] )
3695 return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
3696 },
3697
3698 trigger: function( type, data ) {
3699 return this.each(function() {
3700 jQuery.event.trigger( type, data, this );
3701 });
3702 },
3703 triggerHandler: function( type, data ) {
3704 var elem = this[0];
3705 if ( elem ) {
3706 return jQuery.event.trigger( type, data, elem, true );
3707 }
3708 }
3709});
3710/*!
3711 * Sizzle CSS Selector Engine
3712 * Copyright 2012 jQuery Foundation and other contributors
3713 * Released under the MIT license
3714 * http://sizzlejs.com/
3715 */
3716(function( window, undefined ) {
3717
3718var i,
3719 cachedruns,
3720 Expr,
3721 getText,
3722 isXML,
3723 compile,
3724 hasDuplicate,
3725 outermostContext,
3726
3727 // Local document vars
3728 setDocument,
3729 document,
3730 docElem,
3731 documentIsXML,
3732 rbuggyQSA,
3733 rbuggyMatches,
3734 matches,
3735 contains,
3736 sortOrder,
3737
3738 // Instance-specific data
3739 expando = "sizzle" + -(new Date()),
3740 preferredDoc = window.document,
3741 support = {},
3742 dirruns = 0,
3743 done = 0,
3744 classCache = createCache(),
3745 tokenCache = createCache(),
3746 compilerCache = createCache(),
3747
3748 // General-purpose constants
3749 strundefined = typeof undefined,
3750 MAX_NEGATIVE = 1 << 31,
3751
3752 // Array methods
3753 arr = [],
3754 pop = arr.pop,
3755 push = arr.push,
3756 slice = arr.slice,
3757 // Use a stripped-down indexOf if we can't use a native one
3758 indexOf = arr.indexOf || function( elem ) {
3759 var i = 0,
3760 len = this.length;
3761 for ( ; i < len; i++ ) {
3762 if ( this[i] === elem ) {
3763 return i;
3764 }
3765 }
3766 return -1;
3767 },
3768
3769
3770 // Regular expressions
3771
3772 // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
3773 whitespace = "[\\x20\\t\\r\\n\\f]",
3774 // http://www.w3.org/TR/css3-syntax/#characters
3775 characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
3776
3777 // Loosely modeled on CSS identifier characters
3778 // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
3779 // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
3780 identifier = characterEncoding.replace( "w", "w#" ),
3781
3782 // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
3783 operators = "([*^$|!~]?=)",
3784 attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
3785 "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
3786
3787 // Prefer arguments quoted,
3788 // then not containing pseudos/brackets,
3789 // then attribute selectors/non-parenthetical expressions,
3790 // then anything else
3791 // These preferences are here to reduce the number of selectors
3792 // needing tokenize in the PSEUDO preFilter
3793 pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
3794
3795 // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
3796 rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
3797
3798 rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
3799 rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
3800 rpseudo = new RegExp( pseudos ),
3801 ridentifier = new RegExp( "^" + identifier + "$" ),
3802
3803 matchExpr = {
3804 "ID": new RegExp( "^#(" + characterEncoding + ")" ),
3805 "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
3806 "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
3807 "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
3808 "ATTR": new RegExp( "^" + attributes ),
3809 "PSEUDO": new RegExp( "^" + pseudos ),
3810 "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
3811 "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
3812 "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
3813 // For use in libraries implementing .is()
3814 // We use this for POS matching in `select`
3815 "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
3816 whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
3817 },
3818
3819 rsibling = /[\x20\t\r\n\f]*[+~]/,
3820
3821 rnative = /^[^{]+\{\s*\[native code/,
3822
3823 // Easily-parseable/retrievable ID or TAG or CLASS selectors
3824 rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
3825
3826 rinputs = /^(?:input|select|textarea|button)$/i,
3827 rheader = /^h\d$/i,
3828
3829 rescape = /'|\\/g,
3830 rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
3831
3832 // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
3833 runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
3834 funescape = function( _, escaped ) {
3835 var high = "0x" + escaped - 0x10000;
3836 // NaN means non-codepoint
3837 return high !== high ?
3838 escaped :
3839 // BMP codepoint
3840 high < 0 ?
3841 String.fromCharCode( high + 0x10000 ) :
3842 // Supplemental Plane codepoint (surrogate pair)
3843 String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
3844 };
3845
3846// Use a stripped-down slice if we can't use a native one
3847try {
3848 slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
3849} catch ( e ) {
3850 slice = function( i ) {
3851 var elem,
3852 results = [];
3853 while ( (elem = this[i++]) ) {
3854 results.push( elem );
3855 }
3856 return results;
3857 };
3858}
3859
3860/**
3861 * For feature detection
3862 * @param {Function} fn The function to test for native support
3863 */
3864function isNative( fn ) {
3865 return rnative.test( fn + "" );
3866}
3867
3868/**
3869 * Create key-value caches of limited size
3870 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
3871 *property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
3872 *deleting the oldest entry
3873 */
3874function createCache() {
3875 var cache,
3876 keys = [];
3877
3878 return (cache = function( key, value ) {
3879 // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
3880 if ( keys.push( key += " " ) > Expr.cacheLength ) {
3881 // Only keep the most recent entries
3882 delete cache[ keys.shift() ];
3883 }
3884 return (cache[ key ] = value);
3885 });
3886}
3887
3888/**
3889 * Mark a function for special use by Sizzle
3890 * @param {Function} fn The function to mark
3891 */
3892function markFunction( fn ) {
3893 fn[ expando ] = true;
3894 return fn;
3895}
3896
3897/**
3898 * Support testing using an element
3899 * @param {Function} fn Passed the created div and expects a boolean result
3900 */
3901function assert( fn ) {
3902 var div = document.createElement("div");
3903
3904 try {
3905 return fn( div );
3906 } catch (e) {
3907 return false;
3908 } finally {
3909 // release memory in IE
3910 div = null;
3911 }
3912}
3913
3914function Sizzle( selector, context, results, seed ) {
3915 var match, elem, m, nodeType,
3916 // QSA vars
3917 i, groups, old, nid, newContext, newSelector;
3918
3919 if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
3920 setDocument( context );
3921 }
3922
3923 context = context || document;
3924 results = results || [];
3925
3926 if ( !selector || typeof selector !== "string" ) {
3927 return results;
3928 }
3929
3930 if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
3931 return [];
3932 }
3933
3934 if ( !documentIsXML && !seed ) {
3935
3936 // Shortcuts
3937 if ( (match = rquickExpr.exec( selector )) ) {
3938 // Speed-up: Sizzle("#ID")
3939 if ( (m = match[1]) ) {
3940 if ( nodeType === 9 ) {
3941 elem = context.getElementById( m );
3942 // Check parentNode to catch when Blackberry 4.6 returns
3943 // nodes that are no longer in the document #6963
3944 if ( elem && elem.parentNode ) {
3945 // Handle the case where IE, Opera, and Webkit return items
3946 // by name instead of ID
3947 if ( elem.id === m ) {
3948 results.push( elem );
3949 return results;
3950 }
3951 } else {
3952 return results;
3953 }
3954 } else {
3955 // Context is not a document
3956 if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
3957 contains( context, elem ) && elem.id === m ) {
3958 results.push( elem );
3959 return results;
3960 }
3961 }
3962
3963 // Speed-up: Sizzle("TAG")
3964 } else if ( match[2] ) {
3965 push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
3966 return results;
3967
3968 // Speed-up: Sizzle(".CLASS")
3969 } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
3970 push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
3971 return results;
3972 }
3973 }
3974
3975 // QSA path
3976 if ( support.qsa && !rbuggyQSA.test(selector) ) {
3977 old = true;
3978 nid = expando;
3979 newContext = context;
3980 newSelector = nodeType === 9 && selector;
3981
3982 // qSA works strangely on Element-rooted queries
3983 // We can work around this by specifying an extra ID on the root
3984 // and working up from there (Thanks to Andrew Dupont for the technique)
3985 // IE 8 doesn't work on object elements
3986 if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
3987 groups = tokenize( selector );
3988
3989 if ( (old = context.getAttribute("id")) ) {
3990 nid = old.replace( rescape, "\\$&" );
3991 } else {
3992 context.setAttribute( "id", nid );
3993 }
3994 nid = "[id='" + nid + "'] ";
3995
3996 i = groups.length;
3997 while ( i-- ) {
3998 groups[i] = nid + toSelector( groups[i] );
3999 }
4000 newContext = rsibling.test( selector ) && context.parentNode || context;
4001 newSelector = groups.join(",");
4002 }
4003
4004 if ( newSelector ) {
4005 try {
4006 push.apply( results, slice.call( newContext.querySelectorAll(
4007 newSelector
4008 ), 0 ) );
4009 return results;
4010 } catch(qsaError) {
4011 } finally {
4012 if ( !old ) {
4013 context.removeAttribute("id");
4014 }
4015 }
4016 }
4017 }
4018 }
4019
4020 // All others
4021 return select( selector.replace( rtrim, "$1" ), context, results, seed );
4022}
4023
4024/**
4025 * Detect xml
4026 * @param {Element|Object} elem An element or a document
4027 */
4028isXML = Sizzle.isXML = function( elem ) {
4029 // documentElement is verified for cases where it doesn't yet exist
4030 // (such as loading iframes in IE - #4833)
4031 var documentElement = elem && (elem.ownerDocument || elem).documentElement;
4032 return documentElement ? documentElement.nodeName !== "HTML" : false;
4033};
4034
4035/**
4036 * Sets document-related variables once based on the current document
4037 * @param {Element|Object} [doc] An element or document object to use to set the document
4038 * @returns {Object} Returns the current document
4039 */
4040setDocument = Sizzle.setDocument = function( node ) {
4041 var doc = node ? node.ownerDocument || node : preferredDoc;
4042
4043 // If no document and documentElement is available, return
4044 if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
4045 return document;
4046 }
4047
4048 // Set our document
4049 document = doc;
4050 docElem = doc.documentElement;
4051
4052 // Support tests
4053 documentIsXML = isXML( doc );
4054
4055 // Check if getElementsByTagName("*") returns only elements
4056 support.tagNameNoComments = assert(function( div ) {
4057 div.appendChild( doc.createComment("") );
4058 return !div.getElementsByTagName("*").length;
4059 });
4060
4061 // Check if attributes should be retrieved by attribute nodes
4062 support.attributes = assert(function( div ) {
4063 div.innerHTML = "<select></select>";
4064 var type = typeof div.lastChild.getAttribute("multiple");
4065 // IE8 returns a string for some attributes even when not present
4066 return type !== "boolean" && type !== "string";
4067 });
4068
4069 // Check if getElementsByClassName can be trusted
4070 support.getByClassName = assert(function( div ) {
4071 // Opera can't find a second classname (in 9.6)
4072 div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
4073 if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
4074 return false;
4075 }
4076
4077 // Safari 3.2 caches class attributes and doesn't catch changes
4078 div.lastChild.className = "e";
4079 return div.getElementsByClassName("e").length === 2;
4080 });
4081
4082 // Check if getElementById returns elements by name
4083 // Check if getElementsByName privileges form controls or returns elements by ID
4084 support.getByName = assert(function( div ) {
4085 // Inject content
4086 div.id = expando + 0;
4087 div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
4088 docElem.insertBefore( div, docElem.firstChild );
4089
4090 // Test
4091 var pass = doc.getElementsByName &&
4092 // buggy browsers will return fewer than the correct 2
4093 doc.getElementsByName( expando ).length === 2 +
4094 // buggy browsers will return more than the correct 0
4095 doc.getElementsByName( expando + 0 ).length;
4096 support.getIdNotName = !doc.getElementById( expando );
4097
4098 // Cleanup
4099 docElem.removeChild( div );
4100
4101 return pass;
4102 });
4103
4104 // IE6/7 return modified attributes
4105 Expr.attrHandle = assert(function( div ) {
4106 div.innerHTML = "<a href='#'></a>";
4107 return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
4108 div.firstChild.getAttribute("href") === "#";
4109 }) ?
4110 {} :
4111 {
4112 "href": function( elem ) {
4113 return elem.getAttribute( "href", 2 );
4114 },
4115 "type": function( elem ) {
4116 return elem.getAttribute("type");
4117 }
4118 };
4119
4120 // ID find and filter
4121 if ( support.getIdNotName ) {
4122 Expr.find["ID"] = function( id, context ) {
4123 if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4124 var m = context.getElementById( id );
4125 // Check parentNode to catch when Blackberry 4.6 returns
4126 // nodes that are no longer in the document #6963
4127 return m && m.parentNode ? [m] : [];
4128 }
4129 };
4130 Expr.filter["ID"] = function( id ) {
4131 var attrId = id.replace( runescape, funescape );
4132 return function( elem ) {
4133 return elem.getAttribute("id") === attrId;
4134 };
4135 };
4136 } else {
4137 Expr.find["ID"] = function( id, context ) {
4138 if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
4139 var m = context.getElementById( id );
4140
4141 return m ?
4142 m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
4143 [m] :
4144 undefined :
4145 [];
4146 }
4147 };
4148 Expr.filter["ID"] = function( id ) {
4149 var attrId = id.replace( runescape, funescape );
4150 return function( elem ) {
4151 var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
4152 return node && node.value === attrId;
4153 };
4154 };
4155 }
4156
4157 // Tag
4158 Expr.find["TAG"] = support.tagNameNoComments ?
4159 function( tag, context ) {
4160 if ( typeof context.getElementsByTagName !== strundefined ) {
4161 return context.getElementsByTagName( tag );
4162 }
4163 } :
4164 function( tag, context ) {
4165 var elem,
4166 tmp = [],
4167 i = 0,
4168 results = context.getElementsByTagName( tag );
4169
4170 // Filter out possible comments
4171 if ( tag === "*" ) {
4172 while ( (elem = results[i++]) ) {
4173 if ( elem.nodeType === 1 ) {
4174 tmp.push( elem );
4175 }
4176 }
4177
4178 return tmp;
4179 }
4180 return results;
4181 };
4182
4183 // Name
4184 Expr.find["NAME"] = support.getByName && function( tag, context ) {
4185 if ( typeof context.getElementsByName !== strundefined ) {
4186 return context.getElementsByName( name );
4187 }
4188 };
4189
4190 // Class
4191 Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
4192 if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
4193 return context.getElementsByClassName( className );
4194 }
4195 };
4196
4197 // QSA and matchesSelector support
4198
4199 // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
4200 rbuggyMatches = [];
4201
4202 // qSa(:focus) reports false when true (Chrome 21),
4203 // no need to also add to buggyMatches since matches checks buggyQSA
4204 // A support test would require too much code (would include document ready)
4205 rbuggyQSA = [ ":focus" ];
4206
4207 if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
4208 // Build QSA regex
4209 // Regex strategy adopted from Diego Perini
4210 assert(function( div ) {
4211 // Select is set to empty string on purpose
4212 // This is to test IE's treatment of not explictly
4213 // setting a boolean content attribute,
4214 // since its presence should be enough
4215 // http://bugs.jquery.com/ticket/12359
4216 div.innerHTML = "<select><option selected=''></option></select>";
4217
4218 // IE8 - Some boolean attributes are not treated correctly
4219 if ( !div.querySelectorAll("[selected]").length ) {
4220 rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
4221 }
4222
4223 // Webkit/Opera - :checked should return selected option elements
4224 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4225 // IE8 throws error here and will not see later tests
4226 if ( !div.querySelectorAll(":checked").length ) {
4227 rbuggyQSA.push(":checked");
4228 }
4229 });
4230
4231 assert(function( div ) {
4232
4233 // Opera 10-12/IE8 - ^= $= *= and empty values
4234 // Should not select anything
4235 div.innerHTML = "<input type='hidden' i=''/>";
4236 if ( div.querySelectorAll("[i^='']").length ) {
4237 rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
4238 }
4239
4240 // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
4241 // IE8 throws error here and will not see later tests
4242 if ( !div.querySelectorAll(":enabled").length ) {
4243 rbuggyQSA.push( ":enabled", ":disabled" );
4244 }
4245
4246 // Opera 10-11 does not throw on post-comma invalid pseudos
4247 div.querySelectorAll("*,:x");
4248 rbuggyQSA.push(",.*:");
4249 });
4250 }
4251
4252 if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
4253 docElem.mozMatchesSelector ||
4254 docElem.webkitMatchesSelector ||
4255 docElem.oMatchesSelector ||
4256 docElem.msMatchesSelector) )) ) {
4257
4258 assert(function( div ) {
4259 // Check to see if it's possible to do matchesSelector
4260 // on a disconnected node (IE 9)
4261 support.disconnectedMatch = matches.call( div, "div" );
4262
4263 // This should fail with an exception
4264 // Gecko does not error, returns false instead
4265 matches.call( div, "[s!='']:x" );
4266 rbuggyMatches.push( "!=", pseudos );
4267 });
4268 }
4269
4270 rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
4271 rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
4272
4273 // Element contains another
4274 // Purposefully does not implement inclusive descendent
4275 // As in, an element does not contain itself
4276 contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
4277 function( a, b ) {
4278 var adown = a.nodeType === 9 ? a.documentElement : a,
4279 bup = b && b.parentNode;
4280 return a === bup || !!( bup && bup.nodeType === 1 && (
4281 adown.contains ?
4282 adown.contains( bup ) :
4283 a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
4284 ));
4285 } :
4286 function( a, b ) {
4287 if ( b ) {
4288 while ( (b = b.parentNode) ) {
4289 if ( b === a ) {
4290 return true;
4291 }
4292 }
4293 }
4294 return false;
4295 };
4296
4297 // Document order sorting
4298 sortOrder = docElem.compareDocumentPosition ?
4299 function( a, b ) {
4300 var compare;
4301
4302 if ( a === b ) {
4303 hasDuplicate = true;
4304 return 0;
4305 }
4306
4307 if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
4308 if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
4309 if ( a === doc || contains( preferredDoc, a ) ) {
4310 return -1;
4311 }
4312 if ( b === doc || contains( preferredDoc, b ) ) {
4313 return 1;
4314 }
4315 return 0;
4316 }
4317 return compare & 4 ? -1 : 1;
4318 }
4319
4320 return a.compareDocumentPosition ? -1 : 1;
4321 } :
4322 function( a, b ) {
4323 var cur,
4324 i = 0,
4325 aup = a.parentNode,
4326 bup = b.parentNode,
4327 ap = [ a ],
4328 bp = [ b ];
4329
4330 // Exit early if the nodes are identical
4331 if ( a === b ) {
4332 hasDuplicate = true;
4333 return 0;
4334
4335 // Parentless nodes are either documents or disconnected
4336 } else if ( !aup || !bup ) {
4337 return a === doc ? -1 :
4338 b === doc ? 1 :
4339 aup ? -1 :
4340 bup ? 1 :
4341 0;
4342
4343 // If the nodes are siblings, we can do a quick check
4344 } else if ( aup === bup ) {
4345 return siblingCheck( a, b );
4346 }
4347
4348 // Otherwise we need full lists of their ancestors for comparison
4349 cur = a;
4350 while ( (cur = cur.parentNode) ) {
4351 ap.unshift( cur );
4352 }
4353 cur = b;
4354 while ( (cur = cur.parentNode) ) {
4355 bp.unshift( cur );
4356 }
4357
4358 // Walk down the tree looking for a discrepancy
4359 while ( ap[i] === bp[i] ) {
4360 i++;
4361 }
4362
4363 return i ?
4364 // Do a sibling check if the nodes have a common ancestor
4365 siblingCheck( ap[i], bp[i] ) :
4366
4367 // Otherwise nodes in our document sort first
4368 ap[i] === preferredDoc ? -1 :
4369 bp[i] === preferredDoc ? 1 :
4370 0;
4371 };
4372
4373 // Always assume the presence of duplicates if sort doesn't
4374 // pass them to our comparison function (as in Google Chrome).
4375 hasDuplicate = false;
4376 [0, 0].sort( sortOrder );
4377 support.detectDuplicates = hasDuplicate;
4378
4379 return document;
4380};
4381
4382Sizzle.matches = function( expr, elements ) {
4383 return Sizzle( expr, null, null, elements );
4384};
4385
4386Sizzle.matchesSelector = function( elem, expr ) {
4387 // Set document vars if needed
4388 if ( ( elem.ownerDocument || elem ) !== document ) {
4389 setDocument( elem );
4390 }
4391
4392 // Make sure that attribute selectors are quoted
4393 expr = expr.replace( rattributeQuotes, "='$1']" );
4394
4395 // rbuggyQSA always contains :focus, so no need for an existence check
4396 if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
4397 try {
4398 var ret = matches.call( elem, expr );
4399
4400 // IE 9's matchesSelector returns false on disconnected nodes
4401 if ( ret || support.disconnectedMatch ||
4402 // As well, disconnected nodes are said to be in a document
4403 // fragment in IE 9
4404 elem.document && elem.document.nodeType !== 11 ) {
4405 return ret;
4406 }
4407 } catch(e) {}
4408 }
4409
4410 return Sizzle( expr, document, null, [elem] ).length > 0;
4411};
4412
4413Sizzle.contains = function( context, elem ) {
4414 // Set document vars if needed
4415 if ( ( context.ownerDocument || context ) !== document ) {
4416 setDocument( context );
4417 }
4418 return contains( context, elem );
4419};
4420
4421Sizzle.attr = function( elem, name ) {
4422 var val;
4423
4424 // Set document vars if needed
4425 if ( ( elem.ownerDocument || elem ) !== document ) {
4426 setDocument( elem );
4427 }
4428
4429 if ( !documentIsXML ) {
4430 name = name.toLowerCase();
4431 }
4432 if ( (val = Expr.attrHandle[ name ]) ) {
4433 return val( elem );
4434 }
4435 if ( documentIsXML || support.attributes ) {
4436 return elem.getAttribute( name );
4437 }
4438 return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
4439 name :
4440 val && val.specified ? val.value : null;
4441};
4442
4443Sizzle.error = function( msg ) {
4444 throw new Error( "Syntax error, unrecognized expression: " + msg );
4445};
4446
4447// Document sorting and removing duplicates
4448Sizzle.uniqueSort = function( results ) {
4449 var elem,
4450 duplicates = [],
4451 i = 1,
4452 j = 0;
4453
4454 // Unless we *know* we can detect duplicates, assume their presence
4455 hasDuplicate = !support.detectDuplicates;
4456 results.sort( sortOrder );
4457
4458 if ( hasDuplicate ) {
4459 for ( ; (elem = results[i]); i++ ) {
4460 if ( elem === results[ i - 1 ] ) {
4461 j = duplicates.push( i );
4462 }
4463 }
4464 while ( j-- ) {
4465 results.splice( duplicates[ j ], 1 );
4466 }
4467 }
4468
4469 return results;
4470};
4471
4472function siblingCheck( a, b ) {
4473 var cur = b && a,
4474 diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
4475
4476 // Use IE sourceIndex if available on both nodes
4477 if ( diff ) {
4478 return diff;
4479 }
4480
4481 // Check if b follows a
4482 if ( cur ) {
4483 while ( (cur = cur.nextSibling) ) {
4484 if ( cur === b ) {
4485 return -1;
4486 }
4487 }
4488 }
4489
4490 return a ? 1 : -1;
4491}
4492
4493// Returns a function to use in pseudos for input types
4494function createInputPseudo( type ) {
4495 return function( elem ) {
4496 var name = elem.nodeName.toLowerCase();
4497 return name === "input" && elem.type === type;
4498 };
4499}
4500
4501// Returns a function to use in pseudos for buttons
4502function createButtonPseudo( type ) {
4503 return function( elem ) {
4504 var name = elem.nodeName.toLowerCase();
4505 return (name === "input" || name === "button") && elem.type === type;
4506 };
4507}
4508
4509// Returns a function to use in pseudos for positionals
4510function createPositionalPseudo( fn ) {
4511 return markFunction(function( argument ) {
4512 argument = +argument;
4513 return markFunction(function( seed, matches ) {
4514 var j,
4515 matchIndexes = fn( [], seed.length, argument ),
4516 i = matchIndexes.length;
4517
4518 // Match elements found at the specified indexes
4519 while ( i-- ) {
4520 if ( seed[ (j = matchIndexes[i]) ] ) {
4521 seed[j] = !(matches[j] = seed[j]);
4522 }
4523 }
4524 });
4525 });
4526}
4527
4528/**
4529 * Utility function for retrieving the text value of an array of DOM nodes
4530 * @param {Array|Element} elem
4531 */
4532getText = Sizzle.getText = function( elem ) {
4533 var node,
4534 ret = "",
4535 i = 0,
4536 nodeType = elem.nodeType;
4537
4538 if ( !nodeType ) {
4539 // If no nodeType, this is expected to be an array
4540 for ( ; (node = elem[i]); i++ ) {
4541 // Do not traverse comment nodes
4542 ret += getText( node );
4543 }
4544 } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
4545 // Use textContent for elements
4546 // innerText usage removed for consistency of new lines (see #11153)
4547 if ( typeof elem.textContent === "string" ) {
4548 return elem.textContent;
4549 } else {
4550 // Traverse its children
4551 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4552 ret += getText( elem );
4553 }
4554 }
4555 } else if ( nodeType === 3 || nodeType === 4 ) {
4556 return elem.nodeValue;
4557 }
4558 // Do not include comment or processing instruction nodes
4559
4560 return ret;
4561};
4562
4563Expr = Sizzle.selectors = {
4564
4565 // Can be adjusted by the user
4566 cacheLength: 50,
4567
4568 createPseudo: markFunction,
4569
4570 match: matchExpr,
4571
4572 find: {},
4573
4574 relative: {
4575 ">": { dir: "parentNode", first: true },
4576 " ": { dir: "parentNode" },
4577 "+": { dir: "previousSibling", first: true },
4578 "~": { dir: "previousSibling" }
4579 },
4580
4581 preFilter: {
4582 "ATTR": function( match ) {
4583 match[1] = match[1].replace( runescape, funescape );
4584
4585 // Move the given value to match[3] whether quoted or unquoted
4586 match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
4587
4588 if ( match[2] === "~=" ) {
4589 match[3] = " " + match[3] + " ";
4590 }
4591
4592 return match.slice( 0, 4 );
4593 },
4594
4595 "CHILD": function( match ) {
4596 /* matches from matchExpr["CHILD"]
4597 1 type (only|nth|...)
4598 2 what (child|of-type)
4599 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
4600 4 xn-component of xn+y argument ([+-]?\d*n|)
4601 5 sign of xn-component
4602 6 x of xn-component
4603 7 sign of y-component
4604 8 y of y-component
4605 */
4606 match[1] = match[1].toLowerCase();
4607
4608 if ( match[1].slice( 0, 3 ) === "nth" ) {
4609 // nth-* requires argument
4610 if ( !match[3] ) {
4611 Sizzle.error( match[0] );
4612 }
4613
4614 // numeric x and y parameters for Expr.filter.CHILD
4615 // remember that false/true cast respectively to 0/1
4616 match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
4617 match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
4618
4619 // other types prohibit arguments
4620 } else if ( match[3] ) {
4621 Sizzle.error( match[0] );
4622 }
4623
4624 return match;
4625 },
4626
4627 "PSEUDO": function( match ) {
4628 var excess,
4629 unquoted = !match[5] && match[2];
4630
4631 if ( matchExpr["CHILD"].test( match[0] ) ) {
4632 return null;
4633 }
4634
4635 // Accept quoted arguments as-is
4636 if ( match[4] ) {
4637 match[2] = match[4];
4638
4639 // Strip excess characters from unquoted arguments
4640 } else if ( unquoted && rpseudo.test( unquoted ) &&
4641 // Get excess from tokenize (recursively)
4642 (excess = tokenize( unquoted, true )) &&
4643 // advance to the next closing parenthesis
4644 (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
4645
4646 // excess is a negative index
4647 match[0] = match[0].slice( 0, excess );
4648 match[2] = unquoted.slice( 0, excess );
4649 }
4650
4651 // Return only captures needed by the pseudo filter method (type and argument)
4652 return match.slice( 0, 3 );
4653 }
4654 },
4655
4656 filter: {
4657
4658 "TAG": function( nodeName ) {
4659 if ( nodeName === "*" ) {
4660 return function() { return true; };
4661 }
4662
4663 nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
4664 return function( elem ) {
4665 return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
4666 };
4667 },
4668
4669 "CLASS": function( className ) {
4670 var pattern = classCache[ className + " " ];
4671
4672 return pattern ||
4673 (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
4674 classCache( className, function( elem ) {
4675 return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
4676 });
4677 },
4678
4679 "ATTR": function( name, operator, check ) {
4680 return function( elem ) {
4681 var result = Sizzle.attr( elem, name );
4682
4683 if ( result == null ) {
4684 return operator === "!=";
4685 }
4686 if ( !operator ) {
4687 return true;
4688 }
4689
4690 result += "";
4691
4692 return operator === "=" ? result === check :
4693 operator === "!=" ? result !== check :
4694 operator === "^=" ? check && result.indexOf( check ) === 0 :
4695 operator === "*=" ? check && result.indexOf( check ) > -1 :
4696 operator === "$=" ? check && result.slice( -check.length ) === check :
4697 operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
4698 operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
4699 false;
4700 };
4701 },
4702
4703 "CHILD": function( type, what, argument, first, last ) {
4704 var simple = type.slice( 0, 3 ) !== "nth",
4705 forward = type.slice( -4 ) !== "last",
4706 ofType = what === "of-type";
4707
4708 return first === 1 && last === 0 ?
4709
4710 // Shortcut for :nth-*(n)
4711 function( elem ) {
4712 return !!elem.parentNode;
4713 } :
4714
4715 function( elem, context, xml ) {
4716 var cache, outerCache, node, diff, nodeIndex, start,
4717 dir = simple !== forward ? "nextSibling" : "previousSibling",
4718 parent = elem.parentNode,
4719 name = ofType && elem.nodeName.toLowerCase(),
4720 useCache = !xml && !ofType;
4721
4722 if ( parent ) {
4723
4724 // :(first|last|only)-(child|of-type)
4725 if ( simple ) {
4726 while ( dir ) {
4727 node = elem;
4728 while ( (node = node[ dir ]) ) {
4729 if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
4730 return false;
4731 }
4732 }
4733 // Reverse direction for :only-* (if we haven't yet done so)
4734 start = dir = type === "only" && !start && "nextSibling";
4735 }
4736 return true;
4737 }
4738
4739 start = [ forward ? parent.firstChild : parent.lastChild ];
4740
4741 // non-xml :nth-child(...) stores cache data on `parent`
4742 if ( forward && useCache ) {
4743 // Seek `elem` from a previously-cached index
4744 outerCache = parent[ expando ] || (parent[ expando ] = {});
4745 cache = outerCache[ type ] || [];
4746 nodeIndex = cache[0] === dirruns && cache[1];
4747 diff = cache[0] === dirruns && cache[2];
4748 node = nodeIndex && parent.childNodes[ nodeIndex ];
4749
4750 while ( (node = ++nodeIndex && node && node[ dir ] ||
4751
4752 // Fallback to seeking `elem` from the start
4753 (diff = nodeIndex = 0) || start.pop()) ) {
4754
4755 // When found, cache indexes on `parent` and break
4756 if ( node.nodeType === 1 && ++diff && node === elem ) {
4757 outerCache[ type ] = [ dirruns, nodeIndex, diff ];
4758 break;
4759 }
4760 }
4761
4762 // Use previously-cached element index if available
4763 } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
4764 diff = cache[1];
4765
4766 // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
4767 } else {
4768 // Use the same loop as above to seek `elem` from the start
4769 while ( (node = ++nodeIndex && node && node[ dir ] ||
4770 (diff = nodeIndex = 0) || start.pop()) ) {
4771
4772 if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
4773 // Cache the index of each encountered element
4774 if ( useCache ) {
4775 (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
4776 }
4777
4778 if ( node === elem ) {
4779 break;
4780 }
4781 }
4782 }
4783 }
4784
4785 // Incorporate the offset, then check against cycle size
4786 diff -= last;
4787 return diff === first || ( diff % first === 0 && diff / first >= 0 );
4788 }
4789 };
4790 },
4791
4792 "PSEUDO": function( pseudo, argument ) {
4793 // pseudo-class names are case-insensitive
4794 // http://www.w3.org/TR/selectors/#pseudo-classes
4795 // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
4796 // Remember that setFilters inherits from pseudos
4797 var args,
4798 fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
4799 Sizzle.error( "unsupported pseudo: " + pseudo );
4800
4801 // The user may use createPseudo to indicate that
4802 // arguments are needed to create the filter function
4803 // just as Sizzle does
4804 if ( fn[ expando ] ) {
4805 return fn( argument );
4806 }
4807
4808 // But maintain support for old signatures
4809 if ( fn.length > 1 ) {
4810 args = [ pseudo, pseudo, "", argument ];
4811 return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
4812 markFunction(function( seed, matches ) {
4813 var idx,
4814 matched = fn( seed, argument ),
4815 i = matched.length;
4816 while ( i-- ) {
4817 idx = indexOf.call( seed, matched[i] );
4818 seed[ idx ] = !( matches[ idx ] = matched[i] );
4819 }
4820 }) :
4821 function( elem ) {
4822 return fn( elem, 0, args );
4823 };
4824 }
4825
4826 return fn;
4827 }
4828 },
4829
4830 pseudos: {
4831 // Potentially complex pseudos
4832 "not": markFunction(function( selector ) {
4833 // Trim the selector passed to compile
4834 // to avoid treating leading and trailing
4835 // spaces as combinators
4836 var input = [],
4837 results = [],
4838 matcher = compile( selector.replace( rtrim, "$1" ) );
4839
4840 return matcher[ expando ] ?
4841 markFunction(function( seed, matches, context, xml ) {
4842 var elem,
4843 unmatched = matcher( seed, null, xml, [] ),
4844 i = seed.length;
4845
4846 // Match elements unmatched by `matcher`
4847 while ( i-- ) {
4848 if ( (elem = unmatched[i]) ) {
4849 seed[i] = !(matches[i] = elem);
4850 }
4851 }
4852 }) :
4853 function( elem, context, xml ) {
4854 input[0] = elem;
4855 matcher( input, null, xml, results );
4856 return !results.pop();
4857 };
4858 }),
4859
4860 "has": markFunction(function( selector ) {
4861 return function( elem ) {
4862 return Sizzle( selector, elem ).length > 0;
4863 };
4864 }),
4865
4866 "contains": markFunction(function( text ) {
4867 return function( elem ) {
4868 return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
4869 };
4870 }),
4871
4872 // "Whether an element is represented by a :lang() selector
4873 // is based solely on the element's language value
4874 // being equal to the identifier C,
4875 // or beginning with the identifier C immediately followed by "-".
4876 // The matching of C against the element's language value is performed case-insensitively.
4877 // The identifier C does not have to be a valid language name."
4878 // http://www.w3.org/TR/selectors/#lang-pseudo
4879 "lang": markFunction( function( lang ) {
4880 // lang value must be a valid identifider
4881 if ( !ridentifier.test(lang || "") ) {
4882 Sizzle.error( "unsupported lang: " + lang );
4883 }
4884 lang = lang.replace( runescape, funescape ).toLowerCase();
4885 return function( elem ) {
4886 var elemLang;
4887 do {
4888 if ( (elemLang = documentIsXML ?
4889 elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
4890 elem.lang) ) {
4891
4892 elemLang = elemLang.toLowerCase();
4893 return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
4894 }
4895 } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
4896 return false;
4897 };
4898 }),
4899
4900 // Miscellaneous
4901 "target": function( elem ) {
4902 var hash = window.location && window.location.hash;
4903 return hash && hash.slice( 1 ) === elem.id;
4904 },
4905
4906 "root": function( elem ) {
4907 return elem === docElem;
4908 },
4909
4910 "focus": function( elem ) {
4911 return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
4912 },
4913
4914 // Boolean properties
4915 "enabled": function( elem ) {
4916 return elem.disabled === false;
4917 },
4918
4919 "disabled": function( elem ) {
4920 return elem.disabled === true;
4921 },
4922
4923 "checked": function( elem ) {
4924 // In CSS3, :checked should return both checked and selected elements
4925 // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
4926 var nodeName = elem.nodeName.toLowerCase();
4927 return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
4928 },
4929
4930 "selected": function( elem ) {
4931 // Accessing this property makes selected-by-default
4932 // options in Safari work properly
4933 if ( elem.parentNode ) {
4934 elem.parentNode.selectedIndex;
4935 }
4936
4937 return elem.selected === true;
4938 },
4939
4940 // Contents
4941 "empty": function( elem ) {
4942 // http://www.w3.org/TR/selectors/#empty-pseudo
4943 // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
4944 // not comment, processing instructions, or others
4945 // Thanks to Diego Perini for the nodeName shortcut
4946 // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
4947 for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
4948 if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
4949 return false;
4950 }
4951 }
4952 return true;
4953 },
4954
4955 "parent": function( elem ) {
4956 return !Expr.pseudos["empty"]( elem );
4957 },
4958
4959 // Element/input types
4960 "header": function( elem ) {
4961 return rheader.test( elem.nodeName );
4962 },
4963
4964 "input": function( elem ) {
4965 return rinputs.test( elem.nodeName );
4966 },
4967
4968 "button": function( elem ) {
4969 var name = elem.nodeName.toLowerCase();
4970 return name === "input" && elem.type === "button" || name === "button";
4971 },
4972
4973 "text": function( elem ) {
4974 var attr;
4975 // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
4976 // use getAttribute instead to test this case
4977 return elem.nodeName.toLowerCase() === "input" &&
4978 elem.type === "text" &&
4979 ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
4980 },
4981
4982 // Position-in-collection
4983 "first": createPositionalPseudo(function() {
4984 return [ 0 ];
4985 }),
4986
4987 "last": createPositionalPseudo(function( matchIndexes, length ) {
4988 return [ length - 1 ];
4989 }),
4990
4991 "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
4992 return [ argument < 0 ? argument + length : argument ];
4993 }),
4994
4995 "even": createPositionalPseudo(function( matchIndexes, length ) {
4996 var i = 0;
4997 for ( ; i < length; i += 2 ) {
4998 matchIndexes.push( i );
4999 }
5000 return matchIndexes;
5001 }),
5002
5003 "odd": createPositionalPseudo(function( matchIndexes, length ) {
5004 var i = 1;
5005 for ( ; i < length; i += 2 ) {
5006 matchIndexes.push( i );
5007 }
5008 return matchIndexes;
5009 }),
5010
5011 "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5012 var i = argument < 0 ? argument + length : argument;
5013 for ( ; --i >= 0; ) {
5014 matchIndexes.push( i );
5015 }
5016 return matchIndexes;
5017 }),
5018
5019 "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
5020 var i = argument < 0 ? argument + length : argument;
5021 for ( ; ++i < length; ) {
5022 matchIndexes.push( i );
5023 }
5024 return matchIndexes;
5025 })
5026 }
5027};
5028
5029// Add button/input type pseudos
5030for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
5031 Expr.pseudos[ i ] = createInputPseudo( i );
5032}
5033for ( i in { submit: true, reset: true } ) {
5034 Expr.pseudos[ i ] = createButtonPseudo( i );
5035}
5036
5037function tokenize( selector, parseOnly ) {
5038 var matched, match, tokens, type,
5039 soFar, groups, preFilters,
5040 cached = tokenCache[ selector + " " ];
5041
5042 if ( cached ) {
5043 return parseOnly ? 0 : cached.slice( 0 );
5044 }
5045
5046 soFar = selector;
5047 groups = [];
5048 preFilters = Expr.preFilter;
5049
5050 while ( soFar ) {
5051
5052 // Comma and first run
5053 if ( !matched || (match = rcomma.exec( soFar )) ) {
5054 if ( match ) {
5055 // Don't consume trailing commas as valid
5056 soFar = soFar.slice( match[0].length ) || soFar;
5057 }
5058 groups.push( tokens = [] );
5059 }
5060
5061 matched = false;
5062
5063 // Combinators
5064 if ( (match = rcombinators.exec( soFar )) ) {
5065 matched = match.shift();
5066 tokens.push( {
5067 value: matched,
5068 // Cast descendant combinators to space
5069 type: match[0].replace( rtrim, " " )
5070 } );
5071 soFar = soFar.slice( matched.length );
5072 }
5073
5074 // Filters
5075 for ( type in Expr.filter ) {
5076 if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
5077 (match = preFilters[ type ]( match ))) ) {
5078 matched = match.shift();
5079 tokens.push( {
5080 value: matched,
5081 type: type,
5082 matches: match
5083 } );
5084 soFar = soFar.slice( matched.length );
5085 }
5086 }
5087
5088 if ( !matched ) {
5089 break;
5090 }
5091 }
5092
5093 // Return the length of the invalid excess
5094 // if we're just parsing
5095 // Otherwise, throw an error or return tokens
5096 return parseOnly ?
5097 soFar.length :
5098 soFar ?
5099 Sizzle.error( selector ) :
5100 // Cache the tokens
5101 tokenCache( selector, groups ).slice( 0 );
5102}
5103
5104function toSelector( tokens ) {
5105 var i = 0,
5106 len = tokens.length,
5107 selector = "";
5108 for ( ; i < len; i++ ) {
5109 selector += tokens[i].value;
5110 }
5111 return selector;
5112}
5113
5114function addCombinator( matcher, combinator, base ) {
5115 var dir = combinator.dir,
5116 checkNonElements = base && dir === "parentNode",
5117 doneName = done++;
5118
5119 return combinator.first ?
5120 // Check against closest ancestor/preceding element
5121 function( elem, context, xml ) {
5122 while ( (elem = elem[ dir ]) ) {
5123 if ( elem.nodeType === 1 || checkNonElements ) {
5124 return matcher( elem, context, xml );
5125 }
5126 }
5127 } :
5128
5129 // Check against all ancestor/preceding elements
5130 function( elem, context, xml ) {
5131 var data, cache, outerCache,
5132 dirkey = dirruns + " " + doneName;
5133
5134 // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
5135 if ( xml ) {
5136 while ( (elem = elem[ dir ]) ) {
5137 if ( elem.nodeType === 1 || checkNonElements ) {
5138 if ( matcher( elem, context, xml ) ) {
5139 return true;
5140 }
5141 }
5142 }
5143 } else {
5144 while ( (elem = elem[ dir ]) ) {
5145 if ( elem.nodeType === 1 || checkNonElements ) {
5146 outerCache = elem[ expando ] || (elem[ expando ] = {});
5147 if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
5148 if ( (data = cache[1]) === true || data === cachedruns ) {
5149 return data === true;
5150 }
5151 } else {
5152 cache = outerCache[ dir ] = [ dirkey ];
5153 cache[1] = matcher( elem, context, xml ) || cachedruns;
5154 if ( cache[1] === true ) {
5155 return true;
5156 }
5157 }
5158 }
5159 }
5160 }
5161 };
5162}
5163
5164function elementMatcher( matchers ) {
5165 return matchers.length > 1 ?
5166 function( elem, context, xml ) {
5167 var i = matchers.length;
5168 while ( i-- ) {
5169 if ( !matchers[i]( elem, context, xml ) ) {
5170 return false;
5171 }
5172 }
5173 return true;
5174 } :
5175 matchers[0];
5176}
5177
5178function condense( unmatched, map, filter, context, xml ) {
5179 var elem,
5180 newUnmatched = [],
5181 i = 0,
5182 len = unmatched.length,
5183 mapped = map != null;
5184
5185 for ( ; i < len; i++ ) {
5186 if ( (elem = unmatched[i]) ) {
5187 if ( !filter || filter( elem, context, xml ) ) {
5188 newUnmatched.push( elem );
5189 if ( mapped ) {
5190 map.push( i );
5191 }
5192 }
5193 }
5194 }
5195
5196 return newUnmatched;
5197}
5198
5199function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
5200 if ( postFilter && !postFilter[ expando ] ) {
5201 postFilter = setMatcher( postFilter );
5202 }
5203 if ( postFinder && !postFinder[ expando ] ) {
5204 postFinder = setMatcher( postFinder, postSelector );
5205 }
5206 return markFunction(function( seed, results, context, xml ) {
5207 var temp, i, elem,
5208 preMap = [],
5209 postMap = [],
5210 preexisting = results.length,
5211
5212 // Get initial elements from seed or context
5213 elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
5214
5215 // Prefilter to get matcher input, preserving a map for seed-results synchronization
5216 matcherIn = preFilter && ( seed || !selector ) ?
5217 condense( elems, preMap, preFilter, context, xml ) :
5218 elems,
5219
5220 matcherOut = matcher ?
5221 // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
5222 postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
5223
5224 // ...intermediate processing is necessary
5225 [] :
5226
5227 // ...otherwise use results directly
5228 results :
5229 matcherIn;
5230
5231 // Find primary matches
5232 if ( matcher ) {
5233 matcher( matcherIn, matcherOut, context, xml );
5234 }
5235
5236 // Apply postFilter
5237 if ( postFilter ) {
5238 temp = condense( matcherOut, postMap );
5239 postFilter( temp, [], context, xml );
5240
5241 // Un-match failing elements by moving them back to matcherIn
5242 i = temp.length;
5243 while ( i-- ) {
5244 if ( (elem = temp[i]) ) {
5245 matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
5246 }
5247 }
5248 }
5249
5250 if ( seed ) {
5251 if ( postFinder || preFilter ) {
5252 if ( postFinder ) {
5253 // Get the final matcherOut by condensing this intermediate into postFinder contexts
5254 temp = [];
5255 i = matcherOut.length;
5256 while ( i-- ) {
5257 if ( (elem = matcherOut[i]) ) {
5258 // Restore matcherIn since elem is not yet a final match
5259 temp.push( (matcherIn[i] = elem) );
5260 }
5261 }
5262 postFinder( null, (matcherOut = []), temp, xml );
5263 }
5264
5265 // Move matched elements from seed to results to keep them synchronized
5266 i = matcherOut.length;
5267 while ( i-- ) {
5268 if ( (elem = matcherOut[i]) &&
5269 (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
5270
5271 seed[temp] = !(results[temp] = elem);
5272 }
5273 }
5274 }
5275
5276 // Add elements to results, through postFinder if defined
5277 } else {
5278 matcherOut = condense(
5279 matcherOut === results ?
5280 matcherOut.splice( preexisting, matcherOut.length ) :
5281 matcherOut
5282 );
5283 if ( postFinder ) {
5284 postFinder( null, results, matcherOut, xml );
5285 } else {
5286 push.apply( results, matcherOut );
5287 }
5288 }
5289 });
5290}
5291
5292function matcherFromTokens( tokens ) {
5293 var checkContext, matcher, j,
5294 len = tokens.length,
5295 leadingRelative = Expr.relative[ tokens[0].type ],
5296 implicitRelative = leadingRelative || Expr.relative[" "],
5297 i = leadingRelative ? 1 : 0,
5298
5299 // The foundational matcher ensures that elements are reachable from top-level context(s)
5300 matchContext = addCombinator( function( elem ) {
5301 return elem === checkContext;
5302 }, implicitRelative, true ),
5303 matchAnyContext = addCombinator( function( elem ) {
5304 return indexOf.call( checkContext, elem ) > -1;
5305 }, implicitRelative, true ),
5306 matchers = [ function( elem, context, xml ) {
5307 return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
5308 (checkContext = context).nodeType ?
5309 matchContext( elem, context, xml ) :
5310 matchAnyContext( elem, context, xml ) );
5311 } ];
5312
5313 for ( ; i < len; i++ ) {
5314 if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
5315 matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
5316 } else {
5317 matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
5318
5319 // Return special upon seeing a positional matcher
5320 if ( matcher[ expando ] ) {
5321 // Find the next relative operator (if any) for proper handling
5322 j = ++i;
5323 for ( ; j < len; j++ ) {
5324 if ( Expr.relative[ tokens[j].type ] ) {
5325 break;
5326 }
5327 }
5328 return setMatcher(
5329 i > 1 && elementMatcher( matchers ),
5330 i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
5331 matcher,
5332 i < j && matcherFromTokens( tokens.slice( i, j ) ),
5333 j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
5334 j < len && toSelector( tokens )
5335 );
5336 }
5337 matchers.push( matcher );
5338 }
5339 }
5340
5341 return elementMatcher( matchers );
5342}
5343
5344function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
5345 // A counter to specify which element is currently being matched
5346 var matcherCachedRuns = 0,
5347 bySet = setMatchers.length > 0,
5348 byElement = elementMatchers.length > 0,
5349 superMatcher = function( seed, context, xml, results, expandContext ) {
5350 var elem, j, matcher,
5351 setMatched = [],
5352 matchedCount = 0,
5353 i = "0",
5354 unmatched = seed && [],
5355 outermost = expandContext != null,
5356 contextBackup = outermostContext,
5357 // We must always have either seed elements or context
5358 elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
5359 // Use integer dirruns iff this is the outermost matcher
5360 dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
5361
5362 if ( outermost ) {
5363 outermostContext = context !== document && context;
5364 cachedruns = matcherCachedRuns;
5365 }
5366
5367 // Add elements passing elementMatchers directly to results
5368 // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
5369 for ( ; (elem = elems[i]) != null; i++ ) {
5370 if ( byElement && elem ) {
5371 j = 0;
5372 while ( (matcher = elementMatchers[j++]) ) {
5373 if ( matcher( elem, context, xml ) ) {
5374 results.push( elem );
5375 break;
5376 }
5377 }
5378 if ( outermost ) {
5379 dirruns = dirrunsUnique;
5380 cachedruns = ++matcherCachedRuns;
5381 }
5382 }
5383
5384 // Track unmatched elements for set filters
5385 if ( bySet ) {
5386 // They will have gone through all possible matchers
5387 if ( (elem = !matcher && elem) ) {
5388 matchedCount--;
5389 }
5390
5391 // Lengthen the array for every element, matched or not
5392 if ( seed ) {
5393 unmatched.push( elem );
5394 }
5395 }
5396 }
5397
5398 // Apply set filters to unmatched elements
5399 matchedCount += i;
5400 if ( bySet && i !== matchedCount ) {
5401 j = 0;
5402 while ( (matcher = setMatchers[j++]) ) {
5403 matcher( unmatched, setMatched, context, xml );
5404 }
5405
5406 if ( seed ) {
5407 // Reintegrate element matches to eliminate the need for sorting
5408 if ( matchedCount > 0 ) {
5409 while ( i-- ) {
5410 if ( !(unmatched[i] || setMatched[i]) ) {
5411 setMatched[i] = pop.call( results );
5412 }
5413 }
5414 }
5415
5416 // Discard index placeholder values to get only actual matches
5417 setMatched = condense( setMatched );
5418 }
5419
5420 // Add matches to results
5421 push.apply( results, setMatched );
5422
5423 // Seedless set matches succeeding multiple successful matchers stipulate sorting
5424 if ( outermost && !seed && setMatched.length > 0 &&
5425 ( matchedCount + setMatchers.length ) > 1 ) {
5426
5427 Sizzle.uniqueSort( results );
5428 }
5429 }
5430
5431 // Override manipulation of globals by nested matchers
5432 if ( outermost ) {
5433 dirruns = dirrunsUnique;
5434 outermostContext = contextBackup;
5435 }
5436
5437 return unmatched;
5438 };
5439
5440 return bySet ?
5441 markFunction( superMatcher ) :
5442 superMatcher;
5443}
5444
5445compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
5446 var i,
5447 setMatchers = [],
5448 elementMatchers = [],
5449 cached = compilerCache[ selector + " " ];
5450
5451 if ( !cached ) {
5452 // Generate a function of recursive functions that can be used to check each element
5453 if ( !group ) {
5454 group = tokenize( selector );
5455 }
5456 i = group.length;
5457 while ( i-- ) {
5458 cached = matcherFromTokens( group[i] );
5459 if ( cached[ expando ] ) {
5460 setMatchers.push( cached );
5461 } else {
5462 elementMatchers.push( cached );
5463 }
5464 }
5465
5466 // Cache the compiled function
5467 cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
5468 }
5469 return cached;
5470};
5471
5472function multipleContexts( selector, contexts, results ) {
5473 var i = 0,
5474 len = contexts.length;
5475 for ( ; i < len; i++ ) {
5476 Sizzle( selector, contexts[i], results );
5477 }
5478 return results;
5479}
5480
5481function select( selector, context, results, seed ) {
5482 var i, tokens, token, type, find,
5483 match = tokenize( selector );
5484
5485 if ( !seed ) {
5486 // Try to minimize operations if there is only one group
5487 if ( match.length === 1 ) {
5488
5489 // Take a shortcut and set the context if the root selector is an ID
5490 tokens = match[0] = match[0].slice( 0 );
5491 if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
5492 context.nodeType === 9 && !documentIsXML &&
5493 Expr.relative[ tokens[1].type ] ) {
5494
5495 context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
5496 if ( !context ) {
5497 return results;
5498 }
5499
5500 selector = selector.slice( tokens.shift().value.length );
5501 }
5502
5503 // Fetch a seed set for right-to-left matching
5504 i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
5505 while ( i-- ) {
5506 token = tokens[i];
5507
5508 // Abort if we hit a combinator
5509 if ( Expr.relative[ (type = token.type) ] ) {
5510 break;
5511 }
5512 if ( (find = Expr.find[ type ]) ) {
5513 // Search, expanding context for leading sibling combinators
5514 if ( (seed = find(
5515 token.matches[0].replace( runescape, funescape ),
5516 rsibling.test( tokens[0].type ) && context.parentNode || context
5517 )) ) {
5518
5519 // If seed is empty or no tokens remain, we can return early
5520 tokens.splice( i, 1 );
5521 selector = seed.length && toSelector( tokens );
5522 if ( !selector ) {
5523 push.apply( results, slice.call( seed, 0 ) );
5524 return results;
5525 }
5526
5527 break;
5528 }
5529 }
5530 }
5531 }
5532 }
5533
5534 // Compile and execute a filtering function
5535 // Provide `match` to avoid retokenization if we modified the selector above
5536 compile( selector, match )(
5537 seed,
5538 context,
5539 documentIsXML,
5540 results,
5541 rsibling.test( selector )
5542 );
5543 return results;
5544}
5545
5546// Deprecated
5547Expr.pseudos["nth"] = Expr.pseudos["eq"];
5548
5549// Easy API for creating new setFilters
5550function setFilters() {}
5551Expr.filters = setFilters.prototype = Expr.pseudos;
5552Expr.setFilters = new setFilters();
5553
5554// Initialize with the default document
5555setDocument();
5556
5557// Override sizzle attribute retrieval
5558Sizzle.attr = jQuery.attr;
5559jQuery.find = Sizzle;
5560jQuery.expr = Sizzle.selectors;
5561jQuery.expr[":"] = jQuery.expr.pseudos;
5562jQuery.unique = Sizzle.uniqueSort;
5563jQuery.text = Sizzle.getText;
5564jQuery.isXMLDoc = Sizzle.isXML;
5565jQuery.contains = Sizzle.contains;
5566
5567
5568})( window );
5569var runtil = /Until$/,
5570 rparentsprev = /^(?:parents|prev(?:Until|All))/,
5571 isSimple = /^.[^:#\[\.,]*$/,
5572 rneedsContext = jQuery.expr.match.needsContext,
5573 // methods guaranteed to produce a unique set when starting from a unique set
5574 guaranteedUnique = {
5575 children: true,
5576 contents: true,
5577 next: true,
5578 prev: true
5579 };
5580
5581jQuery.fn.extend({
5582 find: function( selector ) {
5583 var i, ret, self,
5584 len = this.length;
5585
5586 if ( typeof selector !== "string" ) {
5587 self = this;
5588 return this.pushStack( jQuery( selector ).filter(function() {
5589 for ( i = 0; i < len; i++ ) {
5590 if ( jQuery.contains( self[ i ], this ) ) {
5591 return true;
5592 }
5593 }
5594 }) );
5595 }
5596
5597 ret = [];
5598 for ( i = 0; i < len; i++ ) {
5599 jQuery.find( selector, this[ i ], ret );
5600 }
5601
5602 // Needed because $( selector, context ) becomes $( context ).find( selector )
5603 ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
5604 ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
5605 return ret;
5606 },
5607
5608 has: function( target ) {
5609 var i,
5610 targets = jQuery( target, this ),
5611 len = targets.length;
5612
5613 return this.filter(function() {
5614 for ( i = 0; i < len; i++ ) {
5615 if ( jQuery.contains( this, targets[i] ) ) {
5616 return true;
5617 }
5618 }
5619 });
5620 },
5621
5622 not: function( selector ) {
5623 return this.pushStack( winnow(this, selector, false) );
5624 },
5625
5626 filter: function( selector ) {
5627 return this.pushStack( winnow(this, selector, true) );
5628 },
5629
5630 is: function( selector ) {
5631 return !!selector && (
5632 typeof selector === "string" ?
5633 // If this is a positional/relative selector, check membership in the returned set
5634 // so $("p:first").is("p:last") won't return true for a doc with two "p".
5635 rneedsContext.test( selector ) ?
5636 jQuery( selector, this.context ).index( this[0] ) >= 0 :
5637 jQuery.filter( selector, this ).length > 0 :
5638 this.filter( selector ).length > 0 );
5639 },
5640
5641 closest: function( selectors, context ) {
5642 var cur,
5643 i = 0,
5644 l = this.length,
5645 ret = [],
5646 pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
5647 jQuery( selectors, context || this.context ) :
5648 0;
5649
5650 for ( ; i < l; i++ ) {
5651 cur = this[i];
5652
5653 while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
5654 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5655 ret.push( cur );
5656 break;
5657 }
5658 cur = cur.parentNode;
5659 }
5660 }
5661
5662 return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
5663 },
5664
5665 // Determine the position of an element within
5666 // the matched set of elements
5667 index: function( elem ) {
5668
5669 // No argument, return index in parent
5670 if ( !elem ) {
5671 return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
5672 }
5673
5674 // index in selector
5675 if ( typeof elem === "string" ) {
5676 return jQuery.inArray( this[0], jQuery( elem ) );
5677 }
5678
5679 // Locate the position of the desired element
5680 return jQuery.inArray(
5681 // If it receives a jQuery object, the first element is used
5682 elem.jquery ? elem[0] : elem, this );
5683 },
5684
5685 add: function( selector, context ) {
5686 var set = typeof selector === "string" ?
5687 jQuery( selector, context ) :
5688 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5689 all = jQuery.merge( this.get(), set );
5690
5691 return this.pushStack( jQuery.unique(all) );
5692 },
5693
5694 addBack: function( selector ) {
5695 return this.add( selector == null ?
5696 this.prevObject : this.prevObject.filter(selector)
5697 );
5698 }
5699});
5700
5701jQuery.fn.andSelf = jQuery.fn.addBack;
5702
5703function sibling( cur, dir ) {
5704 do {
5705 cur = cur[ dir ];
5706 } while ( cur && cur.nodeType !== 1 );
5707
5708 return cur;
5709}
5710
5711jQuery.each({
5712 parent: function( elem ) {
5713 var parent = elem.parentNode;
5714 return parent && parent.nodeType !== 11 ? parent : null;
5715 },
5716 parents: function( elem ) {
5717 return jQuery.dir( elem, "parentNode" );
5718 },
5719 parentsUntil: function( elem, i, until ) {
5720 return jQuery.dir( elem, "parentNode", until );
5721 },
5722 next: function( elem ) {
5723 return sibling( elem, "nextSibling" );
5724 },
5725 prev: function( elem ) {
5726 return sibling( elem, "previousSibling" );
5727 },
5728 nextAll: function( elem ) {
5729 return jQuery.dir( elem, "nextSibling" );
5730 },
5731 prevAll: function( elem ) {
5732 return jQuery.dir( elem, "previousSibling" );
5733 },
5734 nextUntil: function( elem, i, until ) {
5735 return jQuery.dir( elem, "nextSibling", until );
5736 },
5737 prevUntil: function( elem, i, until ) {
5738 return jQuery.dir( elem, "previousSibling", until );
5739 },
5740 siblings: function( elem ) {
5741 return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
5742 },
5743 children: function( elem ) {
5744 return jQuery.sibling( elem.firstChild );
5745 },
5746 contents: function( elem ) {
5747 return jQuery.nodeName( elem, "iframe" ) ?
5748 elem.contentDocument || elem.contentWindow.document :
5749 jQuery.merge( [], elem.childNodes );
5750 }
5751}, function( name, fn ) {
5752 jQuery.fn[ name ] = function( until, selector ) {
5753 var ret = jQuery.map( this, fn, until );
5754
5755 if ( !runtil.test( name ) ) {
5756 selector = until;
5757 }
5758
5759 if ( selector && typeof selector === "string" ) {
5760 ret = jQuery.filter( selector, ret );
5761 }
5762
5763 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
5764
5765 if ( this.length > 1 && rparentsprev.test( name ) ) {
5766 ret = ret.reverse();
5767 }
5768
5769 return this.pushStack( ret );
5770 };
5771});
5772
5773jQuery.extend({
5774 filter: function( expr, elems, not ) {
5775 if ( not ) {
5776 expr = ":not(" + expr + ")";
5777 }
5778
5779 return elems.length === 1 ?
5780 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
5781 jQuery.find.matches(expr, elems);
5782 },
5783
5784 dir: function( elem, dir, until ) {
5785 var matched = [],
5786 cur = elem[ dir ];
5787
5788 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
5789 if ( cur.nodeType === 1 ) {
5790 matched.push( cur );
5791 }
5792 cur = cur[dir];
5793 }
5794 return matched;
5795 },
5796
5797 sibling: function( n, elem ) {
5798 var r = [];
5799
5800 for ( ; n; n = n.nextSibling ) {
5801 if ( n.nodeType === 1 && n !== elem ) {
5802 r.push( n );
5803 }
5804 }
5805
5806 return r;
5807 }
5808});
5809
5810// Implement the identical functionality for filter and not
5811function winnow( elements, qualifier, keep ) {
5812
5813 // Can't pass null or undefined to indexOf in Firefox 4
5814 // Set to 0 to skip string check
5815 qualifier = qualifier || 0;
5816
5817 if ( jQuery.isFunction( qualifier ) ) {
5818 return jQuery.grep(elements, function( elem, i ) {
5819 var retVal = !!qualifier.call( elem, i, elem );
5820 return retVal === keep;
5821 });
5822
5823 } else if ( qualifier.nodeType ) {
5824 return jQuery.grep(elements, function( elem ) {
5825 return ( elem === qualifier ) === keep;
5826 });
5827
5828 } else if ( typeof qualifier === "string" ) {
5829 var filtered = jQuery.grep(elements, function( elem ) {
5830 return elem.nodeType === 1;
5831 });
5832
5833 if ( isSimple.test( qualifier ) ) {
5834 return jQuery.filter(qualifier, filtered, !keep);
5835 } else {
5836 qualifier = jQuery.filter( qualifier, filtered );
5837 }
5838 }
5839
5840 return jQuery.grep(elements, function( elem ) {
5841 return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
5842 });
5843}
5844function createSafeFragment( document ) {
5845 var list = nodeNames.split( "|" ),
5846 safeFrag = document.createDocumentFragment();
5847
5848 if ( safeFrag.createElement ) {
5849 while ( list.length ) {
5850 safeFrag.createElement(
5851 list.pop()
5852 );
5853 }
5854 }
5855 return safeFrag;
5856}
5857
5858var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
5859 "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
5860 rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
5861 rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
5862 rleadingWhitespace = /^\s+/,
5863 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
5864 rtagName = /<([\w:]+)/,
5865 rtbody = /<tbody/i,
5866 rhtml = /<|&#?\w+;/,
5867 rnoInnerhtml = /<(?:script|style|link)/i,
5868 manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
5869 // checked="checked" or checked
5870 rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
5871 rscriptType = /^$|\/(?:java|ecma)script/i,
5872 rscriptTypeMasked = /^true\/(.*)/,
5873 rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
5874
5875 // We have to close these tags to support XHTML (#13200)
5876 wrapMap = {
5877 option: [ 1, "<select multiple='multiple'>", "</select>" ],
5878 legend: [ 1, "<fieldset>", "</fieldset>" ],
5879 area: [ 1, "<map>", "</map>" ],
5880 param: [ 1, "<object>", "</object>" ],
5881 thead: [ 1, "<table>", "</table>" ],
5882 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
5883 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
5884 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
5885
5886 // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
5887 // unless wrapped in a div with non-breaking characters in front of it.
5888 _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
5889 },
5890 safeFragment = createSafeFragment( document ),
5891 fragmentDiv = safeFragment.appendChild( document.createElement("div") );
5892
5893wrapMap.optgroup = wrapMap.option;
5894wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
5895wrapMap.th = wrapMap.td;
5896
5897jQuery.fn.extend({
5898 text: function( value ) {
5899 return jQuery.access( this, function( value ) {
5900 return value === undefined ?
5901 jQuery.text( this ) :
5902 this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
5903 }, null, value, arguments.length );
5904 },
5905
5906 wrapAll: function( html ) {
5907 if ( jQuery.isFunction( html ) ) {
5908 return this.each(function(i) {
5909 jQuery(this).wrapAll( html.call(this, i) );
5910 });
5911 }
5912
5913 if ( this[0] ) {
5914 // The elements to wrap the target around
5915 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
5916
5917 if ( this[0].parentNode ) {
5918 wrap.insertBefore( this[0] );
5919 }
5920
5921 wrap.map(function() {
5922 var elem = this;
5923
5924 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
5925 elem = elem.firstChild;
5926 }
5927
5928 return elem;
5929 }).append( this );
5930 }
5931
5932 return this;
5933 },
5934
5935 wrapInner: function( html ) {
5936 if ( jQuery.isFunction( html ) ) {
5937 return this.each(function(i) {
5938 jQuery(this).wrapInner( html.call(this, i) );
5939 });
5940 }
5941
5942 return this.each(function() {
5943 var self = jQuery( this ),
5944 contents = self.contents();
5945
5946 if ( contents.length ) {
5947 contents.wrapAll( html );
5948
5949 } else {
5950 self.append( html );
5951 }
5952 });
5953 },
5954
5955 wrap: function( html ) {
5956 var isFunction = jQuery.isFunction( html );
5957
5958 return this.each(function(i) {
5959 jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
5960 });
5961 },
5962
5963 unwrap: function() {
5964 return this.parent().each(function() {
5965 if ( !jQuery.nodeName( this, "body" ) ) {
5966 jQuery( this ).replaceWith( this.childNodes );
5967 }
5968 }).end();
5969 },
5970
5971 append: function() {
5972 return this.domManip(arguments, true, function( elem ) {
5973 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5974 this.appendChild( elem );
5975 }
5976 });
5977 },
5978
5979 prepend: function() {
5980 return this.domManip(arguments, true, function( elem ) {
5981 if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
5982 this.insertBefore( elem, this.firstChild );
5983 }
5984 });
5985 },
5986
5987 before: function() {
5988 return this.domManip( arguments, false, function( elem ) {
5989 if ( this.parentNode ) {
5990 this.parentNode.insertBefore( elem, this );
5991 }
5992 });
5993 },
5994
5995 after: function() {
5996 return this.domManip( arguments, false, function( elem ) {
5997 if ( this.parentNode ) {
5998 this.parentNode.insertBefore( elem, this.nextSibling );
5999 }
6000 });
6001 },
6002
6003 // keepData is for internal use only--do not document
6004 remove: function( selector, keepData ) {
6005 var elem,
6006 i = 0;
6007
6008 for ( ; (elem = this[i]) != null; i++ ) {
6009 if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
6010 if ( !keepData && elem.nodeType === 1 ) {
6011 jQuery.cleanData( getAll( elem ) );
6012 }
6013
6014 if ( elem.parentNode ) {
6015 if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
6016 setGlobalEval( getAll( elem, "script" ) );
6017 }
6018 elem.parentNode.removeChild( elem );
6019 }
6020 }
6021 }
6022
6023 return this;
6024 },
6025
6026 empty: function() {
6027 var elem,
6028 i = 0;
6029
6030 for ( ; (elem = this[i]) != null; i++ ) {
6031 // Remove element nodes and prevent memory leaks
6032 if ( elem.nodeType === 1 ) {
6033 jQuery.cleanData( getAll( elem, false ) );
6034 }
6035
6036 // Remove any remaining nodes
6037 while ( elem.firstChild ) {
6038 elem.removeChild( elem.firstChild );
6039 }
6040
6041 // If this is a select, ensure that it displays empty (#12336)
6042 // Support: IE<9
6043 if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
6044 elem.options.length = 0;
6045 }
6046 }
6047
6048 return this;
6049 },
6050
6051 clone: function( dataAndEvents, deepDataAndEvents ) {
6052 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6053 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6054
6055 return this.map( function () {
6056 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6057 });
6058 },
6059
6060 html: function( value ) {
6061 return jQuery.access( this, function( value ) {
6062 var elem = this[0] || {},
6063 i = 0,
6064 l = this.length;
6065
6066 if ( value === undefined ) {
6067 return elem.nodeType === 1 ?
6068 elem.innerHTML.replace( rinlinejQuery, "" ) :
6069 undefined;
6070 }
6071
6072 // See if we can take a shortcut and just use innerHTML
6073 if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6074 ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) &&
6075 ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
6076 !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
6077
6078 value = value.replace( rxhtmlTag, "<$1></$2>" );
6079
6080 try {
6081 for (; i < l; i++ ) {
6082 // Remove element nodes and prevent memory leaks
6083 elem = this[i] || {};
6084 if ( elem.nodeType === 1 ) {
6085 jQuery.cleanData( getAll( elem, false ) );
6086 elem.innerHTML = value;
6087 }
6088 }
6089
6090 elem = 0;
6091
6092 // If using innerHTML throws an exception, use the fallback method
6093 } catch(e) {}
6094 }
6095
6096 if ( elem ) {
6097 this.empty().append( value );
6098 }
6099 }, null, value, arguments.length );
6100 },
6101
6102 replaceWith: function( value ) {
6103 var isFunc = jQuery.isFunction( value );
6104
6105 // Make sure that the elements are removed from the DOM before they are inserted
6106 // this can help fix replacing a parent with child elements
6107 if ( !isFunc && typeof value !== "string" ) {
6108 value = jQuery( value ).not( this ).detach();
6109 }
6110
6111 return this.domManip( [ value ], true, function( elem ) {
6112 var next = this.nextSibling,
6113 parent = this.parentNode;
6114
6115 if ( parent ) {
6116 jQuery( this ).remove();
6117 parent.insertBefore( elem, next );
6118 }
6119 });
6120 },
6121
6122 detach: function( selector ) {
6123 return this.remove( selector, true );
6124 },
6125
6126 domManip: function( args, table, callback ) {
6127
6128 // Flatten any nested arrays
6129 args = core_concat.apply( [], args );
6130
6131 var first, node, hasScripts,
6132 scripts, doc, fragment,
6133 i = 0,
6134 l = this.length,
6135 set = this,
6136 iNoClone = l - 1,
6137 value = args[0],
6138 isFunction = jQuery.isFunction( value );
6139
6140 // We can't cloneNode fragments that contain checked, in WebKit
6141 if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
6142 return this.each(function( index ) {
6143 var self = set.eq( index );
6144 if ( isFunction ) {
6145 args[0] = value.call( this, index, table ? self.html() : undefined );
6146 }
6147 self.domManip( args, table, callback );
6148 });
6149 }
6150
6151 if ( l ) {
6152 fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
6153 first = fragment.firstChild;
6154
6155 if ( fragment.childNodes.length === 1 ) {
6156 fragment = first;
6157 }
6158
6159 if ( first ) {
6160 table = table && jQuery.nodeName( first, "tr" );
6161 scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
6162 hasScripts = scripts.length;
6163
6164 // Use the original fragment for the last item instead of the first because it can end up
6165 // being emptied incorrectly in certain situations (#8070).
6166 for ( ; i < l; i++ ) {
6167 node = fragment;
6168
6169 if ( i !== iNoClone ) {
6170 node = jQuery.clone( node, true, true );
6171
6172 // Keep references to cloned scripts for later restoration
6173 if ( hasScripts ) {
6174 jQuery.merge( scripts, getAll( node, "script" ) );
6175 }
6176 }
6177
6178 callback.call(
6179 table && jQuery.nodeName( this[i], "table" ) ?
6180 findOrAppend( this[i], "tbody" ) :
6181 this[i],
6182 node,
6183 i
6184 );
6185 }
6186
6187 if ( hasScripts ) {
6188 doc = scripts[ scripts.length - 1 ].ownerDocument;
6189
6190 // Reenable scripts
6191 jQuery.map( scripts, restoreScript );
6192
6193 // Evaluate executable scripts on first document insertion
6194 for ( i = 0; i < hasScripts; i++ ) {
6195 node = scripts[ i ];
6196 if ( rscriptType.test( node.type || "" ) &&
6197 !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
6198
6199 if ( node.src ) {
6200 // Hope ajax is available...
6201 jQuery.ajax({
6202 url: node.src,
6203 type: "GET",
6204 dataType: "script",
6205 async: false,
6206 global: false,
6207 "throws": true
6208 });
6209 } else {
6210 jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
6211 }
6212 }
6213 }
6214 }
6215
6216 // Fix #11809: Avoid leaking memory
6217 fragment = first = null;
6218 }
6219 }
6220
6221 return this;
6222 }
6223});
6224
6225function findOrAppend( elem, tag ) {
6226 return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
6227}
6228
6229// Replace/restore the type attribute of script elements for safe DOM manipulation
6230function disableScript( elem ) {
6231 var attr = elem.getAttributeNode("type");
6232 elem.type = ( attr && attr.specified ) + "/" + elem.type;
6233 return elem;
6234}
6235function restoreScript( elem ) {
6236 var match = rscriptTypeMasked.exec( elem.type );
6237 if ( match ) {
6238 elem.type = match[1];
6239 } else {
6240 elem.removeAttribute("type");
6241 }
6242 return elem;
6243}
6244
6245// Mark scripts as having already been evaluated
6246function setGlobalEval( elems, refElements ) {
6247 var elem,
6248 i = 0;
6249 for ( ; (elem = elems[i]) != null; i++ ) {
6250 jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
6251 }
6252}
6253
6254function cloneCopyEvent( src, dest ) {
6255
6256 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6257 return;
6258 }
6259
6260 var type, i, l,
6261 oldData = jQuery._data( src ),
6262 curData = jQuery._data( dest, oldData ),
6263 events = oldData.events;
6264
6265 if ( events ) {
6266 delete curData.handle;
6267 curData.events = {};
6268
6269 for ( type in events ) {
6270 for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6271 jQuery.event.add( dest, type, events[ type ][ i ] );
6272 }
6273 }
6274 }
6275
6276 // make the cloned public data object a copy from the original
6277 if ( curData.data ) {
6278 curData.data = jQuery.extend( {}, curData.data );
6279 }
6280}
6281
6282function fixCloneNodeIssues( src, dest ) {
6283 var nodeName, e, data;
6284
6285 // We do not need to do anything for non-Elements
6286 if ( dest.nodeType !== 1 ) {
6287 return;
6288 }
6289
6290 nodeName = dest.nodeName.toLowerCase();
6291
6292 // IE6-8 copies events bound via attachEvent when using cloneNode.
6293 if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
6294 data = jQuery._data( dest );
6295
6296 for ( e in data.events ) {
6297 jQuery.removeEvent( dest, e, data.handle );
6298 }
6299
6300 // Event data gets referenced instead of copied if the expando gets copied too
6301 dest.removeAttribute( jQuery.expando );
6302 }
6303
6304 // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
6305 if ( nodeName === "script" && dest.text !== src.text ) {
6306 disableScript( dest ).text = src.text;
6307 restoreScript( dest );
6308
6309 // IE6-10 improperly clones children of object elements using classid.
6310 // IE10 throws NoModificationAllowedError if parent is null, #12132.
6311 } else if ( nodeName === "object" ) {
6312 if ( dest.parentNode ) {
6313 dest.outerHTML = src.outerHTML;
6314 }
6315
6316 // This path appears unavoidable for IE9. When cloning an object
6317 // element in IE9, the outerHTML strategy above is not sufficient.
6318 // If the src has innerHTML and the destination does not,
6319 // copy the src.innerHTML into the dest.innerHTML. #10324
6320 if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
6321 dest.innerHTML = src.innerHTML;
6322 }
6323
6324 } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
6325 // IE6-8 fails to persist the checked state of a cloned checkbox
6326 // or radio button. Worse, IE6-7 fail to give the cloned element
6327 // a checked appearance if the defaultChecked value isn't also set
6328
6329 dest.defaultChecked = dest.checked = src.checked;
6330
6331 // IE6-7 get confused and end up setting the value of a cloned
6332 // checkbox/radio button to an empty string instead of "on"
6333 if ( dest.value !== src.value ) {
6334 dest.value = src.value;
6335 }
6336
6337 // IE6-8 fails to return the selected option to the default selected
6338 // state when cloning options
6339 } else if ( nodeName === "option" ) {
6340 dest.defaultSelected = dest.selected = src.defaultSelected;
6341
6342 // IE6-8 fails to set the defaultValue to the correct value when
6343 // cloning other types of input fields
6344 } else if ( nodeName === "input" || nodeName === "textarea" ) {
6345 dest.defaultValue = src.defaultValue;
6346 }
6347}
6348
6349jQuery.each({
6350 appendTo: "append",
6351 prependTo: "prepend",
6352 insertBefore: "before",
6353 insertAfter: "after",
6354 replaceAll: "replaceWith"
6355}, function( name, original ) {
6356 jQuery.fn[ name ] = function( selector ) {
6357 var elems,
6358 i = 0,
6359 ret = [],
6360 insert = jQuery( selector ),
6361 last = insert.length - 1;
6362
6363 for ( ; i <= last; i++ ) {
6364 elems = i === last ? this : this.clone(true);
6365 jQuery( insert[i] )[ original ]( elems );
6366
6367 // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
6368 core_push.apply( ret, elems.get() );
6369 }
6370
6371 return this.pushStack( ret );
6372 };
6373});
6374
6375function getAll( context, tag ) {
6376 var elems, elem,
6377 i = 0,
6378 found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
6379 typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
6380 undefined;
6381
6382 if ( !found ) {
6383 for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
6384 if ( !tag || jQuery.nodeName( elem, tag ) ) {
6385 found.push( elem );
6386 } else {
6387 jQuery.merge( found, getAll( elem, tag ) );
6388 }
6389 }
6390 }
6391
6392 return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
6393 jQuery.merge( [ context ], found ) :
6394 found;
6395}
6396
6397// Used in buildFragment, fixes the defaultChecked property
6398function fixDefaultChecked( elem ) {
6399 if ( manipulation_rcheckableType.test( elem.type ) ) {
6400 elem.defaultChecked = elem.checked;
6401 }
6402}
6403
6404jQuery.extend({
6405 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6406 var destElements, node, clone, i, srcElements,
6407 inPage = jQuery.contains( elem.ownerDocument, elem );
6408
6409 if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
6410 clone = elem.cloneNode( true );
6411
6412 // IE<=8 does not properly clone detached, unknown element nodes
6413 } else {
6414 fragmentDiv.innerHTML = elem.outerHTML;
6415 fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
6416 }
6417
6418 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6419 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6420
6421 // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
6422 destElements = getAll( clone );
6423 srcElements = getAll( elem );
6424
6425 // Fix all IE cloning issues
6426 for ( i = 0; (node = srcElements[i]) != null; ++i ) {
6427 // Ensure that the destination node is not null; Fixes #9587
6428 if ( destElements[i] ) {
6429 fixCloneNodeIssues( node, destElements[i] );
6430 }
6431 }
6432 }
6433
6434 // Copy the events from the original to the clone
6435 if ( dataAndEvents ) {
6436 if ( deepDataAndEvents ) {
6437 srcElements = srcElements || getAll( elem );
6438 destElements = destElements || getAll( clone );
6439
6440 for ( i = 0; (node = srcElements[i]) != null; i++ ) {
6441 cloneCopyEvent( node, destElements[i] );
6442 }
6443 } else {
6444 cloneCopyEvent( elem, clone );
6445 }
6446 }
6447
6448 // Preserve script evaluation history
6449 destElements = getAll( clone, "script" );
6450 if ( destElements.length > 0 ) {
6451 setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
6452 }
6453
6454 destElements = srcElements = node = null;
6455
6456 // Return the cloned set
6457 return clone;
6458 },
6459
6460 buildFragment: function( elems, context, scripts, selection ) {
6461 var j, elem, contains,
6462 tmp, tag, tbody, wrap,
6463 l = elems.length,
6464
6465 // Ensure a safe fragment
6466 safe = createSafeFragment( context ),
6467
6468 nodes = [],
6469 i = 0;
6470
6471 for ( ; i < l; i++ ) {
6472 elem = elems[ i ];
6473
6474 if ( elem || elem === 0 ) {
6475
6476 // Add nodes directly
6477 if ( jQuery.type( elem ) === "object" ) {
6478 jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
6479
6480 // Convert non-html into a text node
6481 } else if ( !rhtml.test( elem ) ) {
6482 nodes.push( context.createTextNode( elem ) );
6483
6484 // Convert html into DOM nodes
6485 } else {
6486 tmp = tmp || safe.appendChild( context.createElement("div") );
6487
6488 // Deserialize a standard representation
6489 tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
6490 wrap = wrapMap[ tag ] || wrapMap._default;
6491
6492 tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
6493
6494 // Descend through wrappers to the right content
6495 j = wrap[0];
6496 while ( j-- ) {
6497 tmp = tmp.lastChild;
6498 }
6499
6500 // Manually add leading whitespace removed by IE
6501 if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6502 nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
6503 }
6504
6505 // Remove IE's autoinserted <tbody> from table fragments
6506 if ( !jQuery.support.tbody ) {
6507
6508 // String was a <table>, *may* have spurious <tbody>
6509 elem = tag === "table" && !rtbody.test( elem ) ?
6510 tmp.firstChild :
6511
6512 // String was a bare <thead> or <tfoot>
6513 wrap[1] === "<table>" && !rtbody.test( elem ) ?
6514 tmp :
6515 0;
6516
6517 j = elem && elem.childNodes.length;
6518 while ( j-- ) {
6519 if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
6520 elem.removeChild( tbody );
6521 }
6522 }
6523 }
6524
6525 jQuery.merge( nodes, tmp.childNodes );
6526
6527 // Fix #12392 for WebKit and IE > 9
6528 tmp.textContent = "";
6529
6530 // Fix #12392 for oldIE
6531 while ( tmp.firstChild ) {
6532 tmp.removeChild( tmp.firstChild );
6533 }
6534
6535 // Remember the top-level container for proper cleanup
6536 tmp = safe.lastChild;
6537 }
6538 }
6539 }
6540
6541 // Fix #11356: Clear elements from fragment
6542 if ( tmp ) {
6543 safe.removeChild( tmp );
6544 }
6545
6546 // Reset defaultChecked for any radios and checkboxes
6547 // about to be appended to the DOM in IE 6/7 (#8060)
6548 if ( !jQuery.support.appendChecked ) {
6549 jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
6550 }
6551
6552 i = 0;
6553 while ( (elem = nodes[ i++ ]) ) {
6554
6555 // #4087 - If origin and destination elements are the same, and this is
6556 // that element, do not do anything
6557 if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
6558 continue;
6559 }
6560
6561 contains = jQuery.contains( elem.ownerDocument, elem );
6562
6563 // Append to fragment
6564 tmp = getAll( safe.appendChild( elem ), "script" );
6565
6566 // Preserve script evaluation history
6567 if ( contains ) {
6568 setGlobalEval( tmp );
6569 }
6570
6571 // Capture executables
6572 if ( scripts ) {
6573 j = 0;
6574 while ( (elem = tmp[ j++ ]) ) {
6575 if ( rscriptType.test( elem.type || "" ) ) {
6576 scripts.push( elem );
6577 }
6578 }
6579 }
6580 }
6581
6582 tmp = null;
6583
6584 return safe;
6585 },
6586
6587 cleanData: function( elems, /* internal */ acceptData ) {
6588 var elem, type, id, data,
6589 i = 0,
6590 internalKey = jQuery.expando,
6591 cache = jQuery.cache,
6592 deleteExpando = jQuery.support.deleteExpando,
6593 special = jQuery.event.special;
6594
6595 for ( ; (elem = elems[i]) != null; i++ ) {
6596
6597 if ( acceptData || jQuery.acceptData( elem ) ) {
6598
6599 id = elem[ internalKey ];
6600 data = id && cache[ id ];
6601
6602 if ( data ) {
6603 if ( data.events ) {
6604 for ( type in data.events ) {
6605 if ( special[ type ] ) {
6606 jQuery.event.remove( elem, type );
6607
6608 // This is a shortcut to avoid jQuery.event.remove's overhead
6609 } else {
6610 jQuery.removeEvent( elem, type, data.handle );
6611 }
6612 }
6613 }
6614
6615 // Remove cache only if it was not already removed by jQuery.event.remove
6616 if ( cache[ id ] ) {
6617
6618 delete cache[ id ];
6619
6620 // IE does not allow us to delete expando properties from nodes,
6621 // nor does it have a removeAttribute function on Document nodes;
6622 // we must handle all of these cases
6623 if ( deleteExpando ) {
6624 delete elem[ internalKey ];
6625
6626 } else if ( typeof elem.removeAttribute !== core_strundefined ) {
6627 elem.removeAttribute( internalKey );
6628
6629 } else {
6630 elem[ internalKey ] = null;
6631 }
6632
6633 core_deletedIds.push( id );
6634 }
6635 }
6636 }
6637 }
6638 }
6639});
6640var iframe, getStyles, curCSS,
6641 ralpha = /alpha\([^)]*\)/i,
6642 ropacity = /opacity\s*=\s*([^)]*)/,
6643 rposition = /^(top|right|bottom|left)$/,
6644 // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
6645 // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
6646 rdisplayswap = /^(none|table(?!-c[ea]).+)/,
6647 rmargin = /^margin/,
6648 rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
6649 rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
6650 rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
6651 elemdisplay = { BODY: "block" },
6652
6653 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6654 cssNormalTransform = {
6655 letterSpacing: 0,
6656 fontWeight: 400
6657 },
6658
6659 cssExpand = [ "Top", "Right", "Bottom", "Left" ],
6660 cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
6661
6662// return a css property mapped to a potentially vendor prefixed property
6663function vendorPropName( style, name ) {
6664
6665 // shortcut for names that are not vendor prefixed
6666 if ( name in style ) {
6667 return name;
6668 }
6669
6670 // check for vendor prefixed names
6671 var capName = name.charAt(0).toUpperCase() + name.slice(1),
6672 origName = name,
6673 i = cssPrefixes.length;
6674
6675 while ( i-- ) {
6676 name = cssPrefixes[ i ] + capName;
6677 if ( name in style ) {
6678 return name;
6679 }
6680 }
6681
6682 return origName;
6683}
6684
6685function isHidden( elem, el ) {
6686 // isHidden might be called from jQuery#filter function;
6687 // in that case, element will be second argument
6688 elem = el || elem;
6689 return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
6690}
6691
6692function showHide( elements, show ) {
6693 var display, elem, hidden,
6694 values = [],
6695 index = 0,
6696 length = elements.length;
6697
6698 for ( ; index < length; index++ ) {
6699 elem = elements[ index ];
6700 if ( !elem.style ) {
6701 continue;
6702 }
6703
6704 values[ index ] = jQuery._data( elem, "olddisplay" );
6705 display = elem.style.display;
6706 if ( show ) {
6707 // Reset the inline display of this element to learn if it is
6708 // being hidden by cascaded rules or not
6709 if ( !values[ index ] && display === "none" ) {
6710 elem.style.display = "";
6711 }
6712
6713 // Set elements which have been overridden with display: none
6714 // in a stylesheet to whatever the default browser style is
6715 // for such an element
6716 if ( elem.style.display === "" && isHidden( elem ) ) {
6717 values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
6718 }
6719 } else {
6720
6721 if ( !values[ index ] ) {
6722 hidden = isHidden( elem );
6723
6724 if ( display && display !== "none" || !hidden ) {
6725 jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
6726 }
6727 }
6728 }
6729 }
6730
6731 // Set the display of most of the elements in a second loop
6732 // to avoid the constant reflow
6733 for ( index = 0; index < length; index++ ) {
6734 elem = elements[ index ];
6735 if ( !elem.style ) {
6736 continue;
6737 }
6738 if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
6739 elem.style.display = show ? values[ index ] || "" : "none";
6740 }
6741 }
6742
6743 return elements;
6744}
6745
6746jQuery.fn.extend({
6747 css: function( name, value ) {
6748 return jQuery.access( this, function( elem, name, value ) {
6749 var len, styles,
6750 map = {},
6751 i = 0;
6752
6753 if ( jQuery.isArray( name ) ) {
6754 styles = getStyles( elem );
6755 len = name.length;
6756
6757 for ( ; i < len; i++ ) {
6758 map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
6759 }
6760
6761 return map;
6762 }
6763
6764 return value !== undefined ?
6765 jQuery.style( elem, name, value ) :
6766 jQuery.css( elem, name );
6767 }, name, value, arguments.length > 1 );
6768 },
6769 show: function() {
6770 return showHide( this, true );
6771 },
6772 hide: function() {
6773 return showHide( this );
6774 },
6775 toggle: function( state ) {
6776 var bool = typeof state === "boolean";
6777
6778 return this.each(function() {
6779 if ( bool ? state : isHidden( this ) ) {
6780 jQuery( this ).show();
6781 } else {
6782 jQuery( this ).hide();
6783 }
6784 });
6785 }
6786});
6787
6788jQuery.extend({
6789 // Add in style property hooks for overriding the default
6790 // behavior of getting and setting a style property
6791 cssHooks: {
6792 opacity: {
6793 get: function( elem, computed ) {
6794 if ( computed ) {
6795 // We should always get a number back from opacity
6796 var ret = curCSS( elem, "opacity" );
6797 return ret === "" ? "1" : ret;
6798 }
6799 }
6800 }
6801 },
6802
6803 // Exclude the following css properties to add px
6804 cssNumber: {
6805 "columnCount": true,
6806 "fillOpacity": true,
6807 "fontWeight": true,
6808 "lineHeight": true,
6809 "opacity": true,
6810 "orphans": true,
6811 "widows": true,
6812 "zIndex": true,
6813 "zoom": true
6814 },
6815
6816 // Add in properties whose names you wish to fix before
6817 // setting or getting the value
6818 cssProps: {
6819 // normalize float css property
6820 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6821 },
6822
6823 // Get and set the style property on a DOM Node
6824 style: function( elem, name, value, extra ) {
6825 // Don't set styles on text and comment nodes
6826 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6827 return;
6828 }
6829
6830 // Make sure that we're working with the right name
6831 var ret, type, hooks,
6832 origName = jQuery.camelCase( name ),
6833 style = elem.style;
6834
6835 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
6836
6837 // gets hook for the prefixed version
6838 // followed by the unprefixed version
6839 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6840
6841 // Check if we're setting a value
6842 if ( value !== undefined ) {
6843 type = typeof value;
6844
6845 // convert relative number strings (+= or -=) to relative numbers. #7345
6846 if ( type === "string" && (ret = rrelNum.exec( value )) ) {
6847 value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
6848 // Fixes bug #9237
6849 type = "number";
6850 }
6851
6852 // Make sure that NaN and null values aren't set. See: #7116
6853 if ( value == null || type === "number" && isNaN( value ) ) {
6854 return;
6855 }
6856
6857 // If a number was passed in, add 'px' to the (except for certain CSS properties)
6858 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6859 value += "px";
6860 }
6861
6862 // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
6863 // but it would mean to define eight (for every problematic property) identical functions
6864 if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
6865 style[ name ] = "inherit";
6866 }
6867
6868 // If a hook was provided, use that value, otherwise just set the specified value
6869 if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
6870
6871 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6872 // Fixes bug #5509
6873 try {
6874 style[ name ] = value;
6875 } catch(e) {}
6876 }
6877
6878 } else {
6879 // If a hook was provided get the non-computed value from there
6880 if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6881 return ret;
6882 }
6883
6884 // Otherwise just get the value from the style object
6885 return style[ name ];
6886 }
6887 },
6888
6889 css: function( elem, name, extra, styles ) {
6890 var num, val, hooks,
6891 origName = jQuery.camelCase( name );
6892
6893 // Make sure that we're working with the right name
6894 name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
6895
6896 // gets hook for the prefixed version
6897 // followed by the unprefixed version
6898 hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
6899
6900 // If a hook was provided get the computed value from there
6901 if ( hooks && "get" in hooks ) {
6902 val = hooks.get( elem, true, extra );
6903 }
6904
6905 // Otherwise, if a way to get the computed value exists, use that
6906 if ( val === undefined ) {
6907 val = curCSS( elem, name, styles );
6908 }
6909
6910 //convert "normal" to computed value
6911 if ( val === "normal" && name in cssNormalTransform ) {
6912 val = cssNormalTransform[ name ];
6913 }
6914
6915 // Return, converting to number if forced or a qualifier was provided and val looks numeric
6916 if ( extra === "" || extra ) {
6917 num = parseFloat( val );
6918 return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
6919 }
6920 return val;
6921 },
6922
6923 // A method for quickly swapping in/out CSS properties to get correct calculations
6924 swap: function( elem, options, callback, args ) {
6925 var ret, name,
6926 old = {};
6927
6928 // Remember the old values, and insert the new ones
6929 for ( name in options ) {
6930 old[ name ] = elem.style[ name ];
6931 elem.style[ name ] = options[ name ];
6932 }
6933
6934 ret = callback.apply( elem, args || [] );
6935
6936 // Revert the old values
6937 for ( name in options ) {
6938 elem.style[ name ] = old[ name ];
6939 }
6940
6941 return ret;
6942 }
6943});
6944
6945// NOTE: we've included the "window" in window.getComputedStyle
6946// because jsdom on node.js will break without it.
6947if ( window.getComputedStyle ) {
6948 getStyles = function( elem ) {
6949 return window.getComputedStyle( elem, null );
6950 };
6951
6952 curCSS = function( elem, name, _computed ) {
6953 var width, minWidth, maxWidth,
6954 computed = _computed || getStyles( elem ),
6955
6956 // getPropertyValue is only needed for .css('filter') in IE9, see #12537
6957 ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
6958 style = elem.style;
6959
6960 if ( computed ) {
6961
6962 if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
6963 ret = jQuery.style( elem, name );
6964 }
6965
6966 // A tribute to the "awesome hack by Dean Edwards"
6967 // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
6968 // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
6969 // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
6970 if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
6971
6972 // Remember the original values
6973 width = style.width;
6974 minWidth = style.minWidth;
6975 maxWidth = style.maxWidth;
6976
6977 // Put in the new values to get a computed value out
6978 style.minWidth = style.maxWidth = style.width = ret;
6979 ret = computed.width;
6980
6981 // Revert the changed values
6982 style.width = width;
6983 style.minWidth = minWidth;
6984 style.maxWidth = maxWidth;
6985 }
6986 }
6987
6988 return ret;
6989 };
6990} else if ( document.documentElement.currentStyle ) {
6991 getStyles = function( elem ) {
6992 return elem.currentStyle;
6993 };
6994
6995 curCSS = function( elem, name, _computed ) {
6996 var left, rs, rsLeft,
6997 computed = _computed || getStyles( elem ),
6998 ret = computed ? computed[ name ] : undefined,
6999 style = elem.style;
7000
7001 // Avoid setting ret to empty string here
7002 // so we don't default to auto
7003 if ( ret == null && style && style[ name ] ) {
7004 ret = style[ name ];
7005 }
7006
7007 // From the awesome hack by Dean Edwards
7008 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
7009
7010 // If we're not dealing with a regular pixel number
7011 // but a number that has a weird ending, we need to convert it to pixels
7012 // but not position css attributes, as those are proportional to the parent element instead
7013 // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
7014 if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
7015
7016 // Remember the original values
7017 left = style.left;
7018 rs = elem.runtimeStyle;
7019 rsLeft = rs && rs.left;
7020
7021 // Put in the new values to get a computed value out
7022 if ( rsLeft ) {
7023 rs.left = elem.currentStyle.left;
7024 }
7025 style.left = name === "fontSize" ? "1em" : ret;
7026 ret = style.pixelLeft + "px";
7027
7028 // Revert the changed values
7029 style.left = left;
7030 if ( rsLeft ) {
7031 rs.left = rsLeft;
7032 }
7033 }
7034
7035 return ret === "" ? "auto" : ret;
7036 };
7037}
7038
7039function setPositiveNumber( elem, value, subtract ) {
7040 var matches = rnumsplit.exec( value );
7041 return matches ?
7042 // Guard against undefined "subtract", e.g., when used as in cssHooks
7043 Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
7044 value;
7045}
7046
7047function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
7048 var i = extra === ( isBorderBox ? "border" : "content" ) ?
7049 // If we already have the right measurement, avoid augmentation
7050 4 :
7051 // Otherwise initialize for horizontal or vertical properties
7052 name === "width" ? 1 : 0,
7053
7054 val = 0;
7055
7056 for ( ; i < 4; i += 2 ) {
7057 // both box models exclude margin, so add it if we want it
7058 if ( extra === "margin" ) {
7059 val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
7060 }
7061
7062 if ( isBorderBox ) {
7063 // border-box includes padding, so remove it if we want content
7064 if ( extra === "content" ) {
7065 val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7066 }
7067
7068 // at this point, extra isn't border nor margin, so remove border
7069 if ( extra !== "margin" ) {
7070 val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7071 }
7072 } else {
7073 // at this point, extra isn't content, so add padding
7074 val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
7075
7076 // at this point, extra isn't content nor padding, so add border
7077 if ( extra !== "padding" ) {
7078 val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
7079 }
7080 }
7081 }
7082
7083 return val;
7084}
7085
7086function getWidthOrHeight( elem, name, extra ) {
7087
7088 // Start with offset property, which is equivalent to the border-box value
7089 var valueIsBorderBox = true,
7090 val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7091 styles = getStyles( elem ),
7092 isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
7093
7094 // some non-html elements return undefined for offsetWidth, so check for null/undefined
7095 // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
7096 // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
7097 if ( val <= 0 || val == null ) {
7098 // Fall back to computed then uncomputed css if necessary
7099 val = curCSS( elem, name, styles );
7100 if ( val < 0 || val == null ) {
7101 val = elem.style[ name ];
7102 }
7103
7104 // Computed unit is not pixels. Stop here and return.
7105 if ( rnumnonpx.test(val) ) {
7106 return val;
7107 }
7108
7109 // we need the check for style in case a browser which returns unreliable values
7110 // for getComputedStyle silently falls back to the reliable elem.style
7111 valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
7112
7113 // Normalize "", auto, and prepare for extra
7114 val = parseFloat( val ) || 0;
7115 }
7116
7117 // use the active box-sizing model to add/subtract irrelevant styles
7118 return ( val +
7119 augmentWidthOrHeight(
7120 elem,
7121 name,
7122 extra || ( isBorderBox ? "border" : "content" ),
7123 valueIsBorderBox,
7124 styles
7125 )
7126 ) + "px";
7127}
7128
7129// Try to determine the default display value of an element
7130function css_defaultDisplay( nodeName ) {
7131 var doc = document,
7132 display = elemdisplay[ nodeName ];
7133
7134 if ( !display ) {
7135 display = actualDisplay( nodeName, doc );
7136
7137 // If the simple way fails, read from inside an iframe
7138 if ( display === "none" || !display ) {
7139 // Use the already-created iframe if possible
7140 iframe = ( iframe ||
7141 jQuery("<iframe frameborder='0' width='0' height='0'/>")
7142 .css( "cssText", "display:block !important" )
7143 ).appendTo( doc.documentElement );
7144
7145 // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
7146 doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
7147 doc.write("<!doctype html><html><body>");
7148 doc.close();
7149
7150 display = actualDisplay( nodeName, doc );
7151 iframe.detach();
7152 }
7153
7154 // Store the correct default display
7155 elemdisplay[ nodeName ] = display;
7156 }
7157
7158 return display;
7159}
7160
7161// Called ONLY from within css_defaultDisplay
7162function actualDisplay( name, doc ) {
7163 var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
7164 display = jQuery.css( elem[0], "display" );
7165 elem.remove();
7166 return display;
7167}
7168
7169jQuery.each([ "height", "width" ], function( i, name ) {
7170 jQuery.cssHooks[ name ] = {
7171 get: function( elem, computed, extra ) {
7172 if ( computed ) {
7173 // certain elements can have dimension info if we invisibly show them
7174 // however, it must have a current display style that would benefit from this
7175 return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
7176 jQuery.swap( elem, cssShow, function() {
7177 return getWidthOrHeight( elem, name, extra );
7178 }) :
7179 getWidthOrHeight( elem, name, extra );
7180 }
7181 },
7182
7183 set: function( elem, value, extra ) {
7184 var styles = extra && getStyles( elem );
7185 return setPositiveNumber( elem, value, extra ?
7186 augmentWidthOrHeight(
7187 elem,
7188 name,
7189 extra,
7190 jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
7191 styles
7192 ) : 0
7193 );
7194 }
7195 };
7196});
7197
7198if ( !jQuery.support.opacity ) {
7199 jQuery.cssHooks.opacity = {
7200 get: function( elem, computed ) {
7201 // IE uses filters for opacity
7202 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7203 ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
7204 computed ? "1" : "";
7205 },
7206
7207 set: function( elem, value ) {
7208 var style = elem.style,
7209 currentStyle = elem.currentStyle,
7210 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7211 filter = currentStyle && currentStyle.filter || style.filter || "";
7212
7213 // IE has trouble with opacity if it does not have layout
7214 // Force it by setting the zoom level
7215 style.zoom = 1;
7216
7217 // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7218 // if value === "", then remove inline opacity #12685
7219 if ( ( value >= 1 || value === "" ) &&
7220 jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
7221 style.removeAttribute ) {
7222
7223 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7224 // if "filter:" is present at all, clearType is disabled, we want to avoid this
7225 // style.removeAttribute is IE Only, but so apparently is this code path...
7226 style.removeAttribute( "filter" );
7227
7228 // if there is no filter style applied in a css rule or unset inline opacity, we are done
7229 if ( value === "" || currentStyle && !currentStyle.filter ) {
7230 return;
7231 }
7232 }
7233
7234 // otherwise, set new filter values
7235 style.filter = ralpha.test( filter ) ?
7236 filter.replace( ralpha, opacity ) :
7237 filter + " " + opacity;
7238 }
7239 };
7240}
7241
7242// These hooks cannot be added until DOM ready because the support test
7243// for it is not run until after DOM ready
7244jQuery(function() {
7245 if ( !jQuery.support.reliableMarginRight ) {
7246 jQuery.cssHooks.marginRight = {
7247 get: function( elem, computed ) {
7248 if ( computed ) {
7249 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7250 // Work around by temporarily setting element display to inline-block
7251 return jQuery.swap( elem, { "display": "inline-block" },
7252 curCSS, [ elem, "marginRight" ] );
7253 }
7254 }
7255 };
7256 }
7257
7258 // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
7259 // getComputedStyle returns percent when specified for top/left/bottom/right
7260 // rather than make the css module depend on the offset module, we just check for it here
7261 if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
7262 jQuery.each( [ "top", "left" ], function( i, prop ) {
7263 jQuery.cssHooks[ prop ] = {
7264 get: function( elem, computed ) {
7265 if ( computed ) {
7266 computed = curCSS( elem, prop );
7267 // if curCSS returns percentage, fallback to offset
7268 return rnumnonpx.test( computed ) ?
7269 jQuery( elem ).position()[ prop ] + "px" :
7270 computed;
7271 }
7272 }
7273 };
7274 });
7275 }
7276
7277});
7278
7279if ( jQuery.expr && jQuery.expr.filters ) {
7280 jQuery.expr.filters.hidden = function( elem ) {
7281 // Support: Opera <= 12.12
7282 // Opera reports offsetWidths and offsetHeights less than zero on some elements
7283 return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
7284 (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7285 };
7286
7287 jQuery.expr.filters.visible = function( elem ) {
7288 return !jQuery.expr.filters.hidden( elem );
7289 };
7290}
7291
7292// These hooks are used by animate to expand properties
7293jQuery.each({
7294 margin: "",
7295 padding: "",
7296 border: "Width"
7297}, function( prefix, suffix ) {
7298 jQuery.cssHooks[ prefix + suffix ] = {
7299 expand: function( value ) {
7300 var i = 0,
7301 expanded = {},
7302
7303 // assumes a single number if not a string
7304 parts = typeof value === "string" ? value.split(" ") : [ value ];
7305
7306 for ( ; i < 4; i++ ) {
7307 expanded[ prefix + cssExpand[ i ] + suffix ] =
7308 parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
7309 }
7310
7311 return expanded;
7312 }
7313 };
7314
7315 if ( !rmargin.test( prefix ) ) {
7316 jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
7317 }
7318});
7319var r20 = /%20/g,
7320 rbracket = /\[\]$/,
7321 rCRLF = /\r?\n/g,
7322 rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
7323 rsubmittable = /^(?:input|select|textarea|keygen)/i;
7324
7325jQuery.fn.extend({
7326 serialize: function() {
7327 return jQuery.param( this.serializeArray() );
7328 },
7329 serializeArray: function() {
7330 return this.map(function(){
7331 // Can add propHook for "elements" to filter or add form elements
7332 var elements = jQuery.prop( this, "elements" );
7333 return elements ? jQuery.makeArray( elements ) : this;
7334 })
7335 .filter(function(){
7336 var type = this.type;
7337 // Use .is(":disabled") so that fieldset[disabled] works
7338 return this.name && !jQuery( this ).is( ":disabled" ) &&
7339 rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
7340 ( this.checked || !manipulation_rcheckableType.test( type ) );
7341 })
7342 .map(function( i, elem ){
7343 var val = jQuery( this ).val();
7344
7345 return val == null ?
7346 null :
7347 jQuery.isArray( val ) ?
7348 jQuery.map( val, function( val ){
7349 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7350 }) :
7351 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7352 }).get();
7353 }
7354});
7355
7356//Serialize an array of form elements or a set of
7357//key/values into a query string
7358jQuery.param = function( a, traditional ) {
7359 var prefix,
7360 s = [],
7361 add = function( key, value ) {
7362 // If value is a function, invoke it and return its value
7363 value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
7364 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7365 };
7366
7367 // Set traditional to true for jQuery <= 1.3.2 behavior.
7368 if ( traditional === undefined ) {
7369 traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
7370 }
7371
7372 // If an array was passed in, assume that it is an array of form elements.
7373 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7374 // Serialize the form elements
7375 jQuery.each( a, function() {
7376 add( this.name, this.value );
7377 });
7378
7379 } else {
7380 // If traditional, encode the "old" way (the way 1.3.2 or older
7381 // did it), otherwise encode params recursively.
7382 for ( prefix in a ) {
7383 buildParams( prefix, a[ prefix ], traditional, add );
7384 }
7385 }
7386
7387 // Return the resulting serialization
7388 return s.join( "&" ).replace( r20, "+" );
7389};
7390
7391function buildParams( prefix, obj, traditional, add ) {
7392 var name;
7393
7394 if ( jQuery.isArray( obj ) ) {
7395 // Serialize array item.
7396 jQuery.each( obj, function( i, v ) {
7397 if ( traditional || rbracket.test( prefix ) ) {
7398 // Treat each array item as a scalar.
7399 add( prefix, v );
7400
7401 } else {
7402 // Item is non-scalar (array or object), encode its numeric index.
7403 buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
7404 }
7405 });
7406
7407 } else if ( !traditional && jQuery.type( obj ) === "object" ) {
7408 // Serialize object item.
7409 for ( name in obj ) {
7410 buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
7411 }
7412
7413 } else {
7414 // Serialize scalar item.
7415 add( prefix, obj );
7416 }
7417}
7418jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
7419 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
7420 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
7421
7422 // Handle event binding
7423 jQuery.fn[ name ] = function( data, fn ) {
7424 return arguments.length > 0 ?
7425 this.on( name, null, data, fn ) :
7426 this.trigger( name );
7427 };
7428});
7429
7430jQuery.fn.hover = function( fnOver, fnOut ) {
7431 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
7432};
7433var
7434 // Document location
7435 ajaxLocParts,
7436 ajaxLocation,
7437 ajax_nonce = jQuery.now(),
7438
7439 ajax_rquery = /\?/,
7440 rhash = /#.*$/,
7441 rts = /([?&])_=[^&]*/,
7442 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7443 // #7653, #8125, #8152: local protocol detection
7444 rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
7445 rnoContent = /^(?:GET|HEAD)$/,
7446 rprotocol = /^\/\//,
7447 rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
7448
7449 // Keep a copy of the old load method
7450 _load = jQuery.fn.load,
7451
7452 /* Prefilters
7453 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7454 * 2) These are called:
7455 * - BEFORE asking for a transport
7456 * - AFTER param serialization (s.data is a string if s.processData is true)
7457 * 3) key is the dataType
7458 * 4) the catchall symbol "*" can be used
7459 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7460 */
7461 prefilters = {},
7462
7463 /* Transports bindings
7464 * 1) key is the dataType
7465 * 2) the catchall symbol "*" can be used
7466 * 3) selection will start with transport dataType and THEN go to "*" if needed
7467 */
7468 transports = {},
7469
7470 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7471 allTypes = "*/".concat("*");
7472
7473// #8138, IE may throw an exception when accessing
7474// a field from window.location if document.domain has been set
7475try {
7476 ajaxLocation = location.href;
7477} catch( e ) {
7478 // Use the href attribute of an A element
7479 // since IE will modify it given document.location
7480 ajaxLocation = document.createElement( "a" );
7481 ajaxLocation.href = "";
7482 ajaxLocation = ajaxLocation.href;
7483}
7484
7485// Segment location into parts
7486ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7487
7488// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7489function addToPrefiltersOrTransports( structure ) {
7490
7491 // dataTypeExpression is optional and defaults to "*"
7492 return function( dataTypeExpression, func ) {
7493
7494 if ( typeof dataTypeExpression !== "string" ) {
7495 func = dataTypeExpression;
7496 dataTypeExpression = "*";
7497 }
7498
7499 var dataType,
7500 i = 0,
7501 dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
7502
7503 if ( jQuery.isFunction( func ) ) {
7504 // For each dataType in the dataTypeExpression
7505 while ( (dataType = dataTypes[i++]) ) {
7506 // Prepend if requested
7507 if ( dataType[0] === "+" ) {
7508 dataType = dataType.slice( 1 ) || "*";
7509 (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
7510
7511 // Otherwise append
7512 } else {
7513 (structure[ dataType ] = structure[ dataType ] || []).push( func );
7514 }
7515 }
7516 }
7517 };
7518}
7519
7520// Base inspection function for prefilters and transports
7521function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
7522
7523 var inspected = {},
7524 seekingTransport = ( structure === transports );
7525
7526 function inspect( dataType ) {
7527 var selected;
7528 inspected[ dataType ] = true;
7529 jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
7530 var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
7531 if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
7532 options.dataTypes.unshift( dataTypeOrTransport );
7533 inspect( dataTypeOrTransport );
7534 return false;
7535 } else if ( seekingTransport ) {
7536 return !( selected = dataTypeOrTransport );
7537 }
7538 });
7539 return selected;
7540 }
7541
7542 return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
7543}
7544
7545// A special extend for ajax options
7546// that takes "flat" options (not to be deep extended)
7547// Fixes #9887
7548function ajaxExtend( target, src ) {
7549 var deep, key,
7550 flatOptions = jQuery.ajaxSettings.flatOptions || {};
7551
7552 for ( key in src ) {
7553 if ( src[ key ] !== undefined ) {
7554 ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
7555 }
7556 }
7557 if ( deep ) {
7558 jQuery.extend( true, target, deep );
7559 }
7560
7561 return target;
7562}
7563
7564jQuery.fn.load = function( url, params, callback ) {
7565 if ( typeof url !== "string" && _load ) {
7566 return _load.apply( this, arguments );
7567 }
7568
7569 var selector, response, type,
7570 self = this,
7571 off = url.indexOf(" ");
7572
7573 if ( off >= 0 ) {
7574 selector = url.slice( off, url.length );
7575 url = url.slice( 0, off );
7576 }
7577
7578 // If it's a function
7579 if ( jQuery.isFunction( params ) ) {
7580
7581 // We assume that it's the callback
7582 callback = params;
7583 params = undefined;
7584
7585 // Otherwise, build a param string
7586 } else if ( params && typeof params === "object" ) {
7587 type = "POST";
7588 }
7589
7590 // If we have elements to modify, make the request
7591 if ( self.length > 0 ) {
7592 jQuery.ajax({
7593 url: url,
7594
7595 // if "type" variable is undefined, then "GET" method will be used
7596 type: type,
7597 dataType: "html",
7598 data: params
7599 }).done(function( responseText ) {
7600
7601 // Save response for use in complete callback
7602 response = arguments;
7603
7604 self.html( selector ?
7605
7606 // If a selector was specified, locate the right elements in a dummy div
7607 // Exclude scripts to avoid IE 'Permission Denied' errors
7608 jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
7609
7610 // Otherwise use the full result
7611 responseText );
7612
7613 }).complete( callback && function( jqXHR, status ) {
7614 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
7615 });
7616 }
7617
7618 return this;
7619};
7620
7621// Attach a bunch of functions for handling common AJAX events
7622jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
7623 jQuery.fn[ type ] = function( fn ){
7624 return this.on( type, fn );
7625 };
7626});
7627
7628jQuery.each( [ "get", "post" ], function( i, method ) {
7629 jQuery[ method ] = function( url, data, callback, type ) {
7630 // shift arguments if data argument was omitted
7631 if ( jQuery.isFunction( data ) ) {
7632 type = type || callback;
7633 callback = data;
7634 data = undefined;
7635 }
7636
7637 return jQuery.ajax({
7638 url: url,
7639 type: method,
7640 dataType: type,
7641 data: data,
7642 success: callback
7643 });
7644 };
7645});
7646
7647jQuery.extend({
7648
7649 // Counter for holding the number of active queries
7650 active: 0,
7651
7652 // Last-Modified header cache for next request
7653 lastModified: {},
7654 etag: {},
7655
7656 ajaxSettings: {
7657 url: ajaxLocation,
7658 type: "GET",
7659 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7660 global: true,
7661 processData: true,
7662 async: true,
7663 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
7664 /*
7665 timeout: 0,
7666 data: null,
7667 dataType: null,
7668 username: null,
7669 password: null,
7670 cache: null,
7671 throws: false,
7672 traditional: false,
7673 headers: {},
7674 */
7675
7676 accepts: {
7677 "*": allTypes,
7678 text: "text/plain",
7679 html: "text/html",
7680 xml: "application/xml, text/xml",
7681 json: "application/json, text/javascript"
7682 },
7683
7684 contents: {
7685 xml: /xml/,
7686 html: /html/,
7687 json: /json/
7688 },
7689
7690 responseFields: {
7691 xml: "responseXML",
7692 text: "responseText"
7693 },
7694
7695 // Data converters
7696 // Keys separate source (or catchall "*") and destination types with a single space
7697 converters: {
7698
7699 // Convert anything to text
7700 "* text": window.String,
7701
7702 // Text to html (true = no transformation)
7703 "text html": true,
7704
7705 // Evaluate text as a json expression
7706 "text json": jQuery.parseJSON,
7707
7708 // Parse text as xml
7709 "text xml": jQuery.parseXML
7710 },
7711
7712 // For options that shouldn't be deep extended:
7713 // you can add your own custom options here if
7714 // and when you create one that shouldn't be
7715 // deep extended (see ajaxExtend)
7716 flatOptions: {
7717 url: true,
7718 context: true
7719 }
7720 },
7721
7722 // Creates a full fledged settings object into target
7723 // with both ajaxSettings and settings fields.
7724 // If target is omitted, writes into ajaxSettings.
7725 ajaxSetup: function( target, settings ) {
7726 return settings ?
7727
7728 // Building a settings object
7729 ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
7730
7731 // Extending ajaxSettings
7732 ajaxExtend( jQuery.ajaxSettings, target );
7733 },
7734
7735 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7736 ajaxTransport: addToPrefiltersOrTransports( transports ),
7737
7738 // Main method
7739 ajax: function( url, options ) {
7740
7741 // If url is an object, simulate pre-1.5 signature
7742 if ( typeof url === "object" ) {
7743 options = url;
7744 url = undefined;
7745 }
7746
7747 // Force options to be an object
7748 options = options || {};
7749
7750 var // Cross-domain detection vars
7751 parts,
7752 // Loop variable
7753 i,
7754 // URL without anti-cache param
7755 cacheURL,
7756 // Response headers as string
7757 responseHeadersString,
7758 // timeout handle
7759 timeoutTimer,
7760
7761 // To know if global events are to be dispatched
7762 fireGlobals,
7763
7764 transport,
7765 // Response headers
7766 responseHeaders,
7767 // Create the final options object
7768 s = jQuery.ajaxSetup( {}, options ),
7769 // Callbacks context
7770 callbackContext = s.context || s,
7771 // Context for global events is callbackContext if it is a DOM node or jQuery collection
7772 globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
7773 jQuery( callbackContext ) :
7774 jQuery.event,
7775 // Deferreds
7776 deferred = jQuery.Deferred(),
7777 completeDeferred = jQuery.Callbacks("once memory"),
7778 // Status-dependent callbacks
7779 statusCode = s.statusCode || {},
7780 // Headers (they are sent all at once)
7781 requestHeaders = {},
7782 requestHeadersNames = {},
7783 // The jqXHR state
7784 state = 0,
7785 // Default abort message
7786 strAbort = "canceled",
7787 // Fake xhr
7788 jqXHR = {
7789 readyState: 0,
7790
7791 // Builds headers hashtable if needed
7792 getResponseHeader: function( key ) {
7793 var match;
7794 if ( state === 2 ) {
7795 if ( !responseHeaders ) {
7796 responseHeaders = {};
7797 while ( (match = rheaders.exec( responseHeadersString )) ) {
7798 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7799 }
7800 }
7801 match = responseHeaders[ key.toLowerCase() ];
7802 }
7803 return match == null ? null : match;
7804 },
7805
7806 // Raw string
7807 getAllResponseHeaders: function() {
7808 return state === 2 ? responseHeadersString : null;
7809 },
7810
7811 // Caches the header
7812 setRequestHeader: function( name, value ) {
7813 var lname = name.toLowerCase();
7814 if ( !state ) {
7815 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7816 requestHeaders[ name ] = value;
7817 }
7818 return this;
7819 },
7820
7821 // Overrides response content-type header
7822 overrideMimeType: function( type ) {
7823 if ( !state ) {
7824 s.mimeType = type;
7825 }
7826 return this;
7827 },
7828
7829 // Status-dependent callbacks
7830 statusCode: function( map ) {
7831 var code;
7832 if ( map ) {
7833 if ( state < 2 ) {
7834 for ( code in map ) {
7835 // Lazy-add the new callback in a way that preserves old ones
7836 statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
7837 }
7838 } else {
7839 // Execute the appropriate callbacks
7840 jqXHR.always( map[ jqXHR.status ] );
7841 }
7842 }
7843 return this;
7844 },
7845
7846 // Cancel the request
7847 abort: function( statusText ) {
7848 var finalText = statusText || strAbort;
7849 if ( transport ) {
7850 transport.abort( finalText );
7851 }
7852 done( 0, finalText );
7853 return this;
7854 }
7855 };
7856
7857 // Attach deferreds
7858 deferred.promise( jqXHR ).complete = completeDeferred.add;
7859 jqXHR.success = jqXHR.done;
7860 jqXHR.error = jqXHR.fail;
7861
7862 // Remove hash character (#7531: and string promotion)
7863 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7864 // Handle falsy url in the settings object (#10093: consistency with old signature)
7865 // We also use the url parameter if available
7866 s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7867
7868 // Alias method option to type as per ticket #12004
7869 s.type = options.method || options.type || s.method || s.type;
7870
7871 // Extract dataTypes list
7872 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
7873
7874 // A cross-domain request is in order when we have a protocol:host:port mismatch
7875 if ( s.crossDomain == null ) {
7876 parts = rurl.exec( s.url.toLowerCase() );
7877 s.crossDomain = !!( parts &&
7878 ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
7879 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7880 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7881 );
7882 }
7883
7884 // Convert data if not already a string
7885 if ( s.data && s.processData && typeof s.data !== "string" ) {
7886 s.data = jQuery.param( s.data, s.traditional );
7887 }
7888
7889 // Apply prefilters
7890 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7891
7892 // If request was aborted inside a prefilter, stop there
7893 if ( state === 2 ) {
7894 return jqXHR;
7895 }
7896
7897 // We can fire global events as of now if asked to
7898 fireGlobals = s.global;
7899
7900 // Watch for a new set of requests
7901 if ( fireGlobals && jQuery.active++ === 0 ) {
7902 jQuery.event.trigger("ajaxStart");
7903 }
7904
7905 // Uppercase the type
7906 s.type = s.type.toUpperCase();
7907
7908 // Determine if request has content
7909 s.hasContent = !rnoContent.test( s.type );
7910
7911 // Save the URL in case we're toying with the If-Modified-Since
7912 // and/or If-None-Match header later on
7913 cacheURL = s.url;
7914
7915 // More options handling for requests with no content
7916 if ( !s.hasContent ) {
7917
7918 // If data is available, append data to url
7919 if ( s.data ) {
7920 cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
7921 // #9682: remove data so that it's not used in an eventual retry
7922 delete s.data;
7923 }
7924
7925 // Add anti-cache in url if needed
7926 if ( s.cache === false ) {
7927 s.url = rts.test( cacheURL ) ?
7928
7929 // If there is already a '_' parameter, set its value
7930 cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
7931
7932 // Otherwise add one to the end
7933 cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
7934 }
7935 }
7936
7937 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7938 if ( s.ifModified ) {
7939 if ( jQuery.lastModified[ cacheURL ] ) {
7940 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
7941 }
7942 if ( jQuery.etag[ cacheURL ] ) {
7943 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
7944 }
7945 }
7946
7947 // Set the correct header, if data is being sent
7948 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7949 jqXHR.setRequestHeader( "Content-Type", s.contentType );
7950 }
7951
7952 // Set the Accepts header for the server, depending on the dataType
7953 jqXHR.setRequestHeader(
7954 "Accept",
7955 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7956 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
7957 s.accepts[ "*" ]
7958 );
7959
7960 // Check for headers option
7961 for ( i in s.headers ) {
7962 jqXHR.setRequestHeader( i, s.headers[ i ] );
7963 }
7964
7965 // Allow custom headers/mimetypes and early abort
7966 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7967 // Abort if not done already and return
7968 return jqXHR.abort();
7969 }
7970
7971 // aborting is no longer a cancellation
7972 strAbort = "abort";
7973
7974 // Install callbacks on deferreds
7975 for ( i in { success: 1, error: 1, complete: 1 } ) {
7976 jqXHR[ i ]( s[ i ] );
7977 }
7978
7979 // Get transport
7980 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
7981
7982 // If no transport, we auto-abort
7983 if ( !transport ) {
7984 done( -1, "No Transport" );
7985 } else {
7986 jqXHR.readyState = 1;
7987
7988 // Send global event
7989 if ( fireGlobals ) {
7990 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
7991 }
7992 // Timeout
7993 if ( s.async && s.timeout > 0 ) {
7994 timeoutTimer = setTimeout(function() {
7995 jqXHR.abort("timeout");
7996 }, s.timeout );
7997 }
7998
7999 try {
8000 state = 1;
8001 transport.send( requestHeaders, done );
8002 } catch ( e ) {
8003 // Propagate exception as error if not done
8004 if ( state < 2 ) {
8005 done( -1, e );
8006 // Simply rethrow otherwise
8007 } else {
8008 throw e;
8009 }
8010 }
8011 }
8012
8013 // Callback for when everything is done
8014 function done( status, nativeStatusText, responses, headers ) {
8015 var isSuccess, success, error, response, modified,
8016 statusText = nativeStatusText;
8017
8018 // Called once
8019 if ( state === 2 ) {
8020 return;
8021 }
8022
8023 // State is "done" now
8024 state = 2;
8025
8026 // Clear timeout if it exists
8027 if ( timeoutTimer ) {
8028 clearTimeout( timeoutTimer );
8029 }
8030
8031 // Dereference transport for early garbage collection
8032 // (no matter how long the jqXHR object will be used)
8033 transport = undefined;
8034
8035 // Cache response headers
8036 responseHeadersString = headers || "";
8037
8038 // Set readyState
8039 jqXHR.readyState = status > 0 ? 4 : 0;
8040
8041 // Get response data
8042 if ( responses ) {
8043 response = ajaxHandleResponses( s, jqXHR, responses );
8044 }
8045
8046 // If successful, handle type chaining
8047 if ( status >= 200 && status < 300 || status === 304 ) {
8048
8049 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8050 if ( s.ifModified ) {
8051 modified = jqXHR.getResponseHeader("Last-Modified");
8052 if ( modified ) {
8053 jQuery.lastModified[ cacheURL ] = modified;
8054 }
8055 modified = jqXHR.getResponseHeader("etag");
8056 if ( modified ) {
8057 jQuery.etag[ cacheURL ] = modified;
8058 }
8059 }
8060
8061 // if no content
8062 if ( status === 204 ) {
8063 isSuccess = true;
8064 statusText = "nocontent";
8065
8066 // if not modified
8067 } else if ( status === 304 ) {
8068 isSuccess = true;
8069 statusText = "notmodified";
8070
8071 // If we have data, let's convert it
8072 } else {
8073 isSuccess = ajaxConvert( s, response );
8074 statusText = isSuccess.state;
8075 success = isSuccess.data;
8076 error = isSuccess.error;
8077 isSuccess = !error;
8078 }
8079 } else {
8080 // We extract error from statusText
8081 // then normalize statusText and status for non-aborts
8082 error = statusText;
8083 if ( status || !statusText ) {
8084 statusText = "error";
8085 if ( status < 0 ) {
8086 status = 0;
8087 }
8088 }
8089 }
8090
8091 // Set data for the fake xhr object
8092 jqXHR.status = status;
8093 jqXHR.statusText = ( nativeStatusText || statusText ) + "";
8094
8095 // Success/Error
8096 if ( isSuccess ) {
8097 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8098 } else {
8099 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8100 }
8101
8102 // Status-dependent callbacks
8103 jqXHR.statusCode( statusCode );
8104 statusCode = undefined;
8105
8106 if ( fireGlobals ) {
8107 globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
8108 [ jqXHR, s, isSuccess ? success : error ] );
8109 }
8110
8111 // Complete
8112 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8113
8114 if ( fireGlobals ) {
8115 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8116 // Handle the global AJAX counter
8117 if ( !( --jQuery.active ) ) {
8118 jQuery.event.trigger("ajaxStop");
8119 }
8120 }
8121 }
8122
8123 return jqXHR;
8124 },
8125
8126 getScript: function( url, callback ) {
8127 return jQuery.get( url, undefined, callback, "script" );
8128 },
8129
8130 getJSON: function( url, data, callback ) {
8131 return jQuery.get( url, data, callback, "json" );
8132 }
8133});
8134
8135/* Handles responses to an ajax request:
8136 * - sets all responseXXX fields accordingly
8137 * - finds the right dataType (mediates between content-type and expected dataType)
8138 * - returns the corresponding response
8139 */
8140function ajaxHandleResponses( s, jqXHR, responses ) {
8141 var firstDataType, ct, finalDataType, type,
8142 contents = s.contents,
8143 dataTypes = s.dataTypes,
8144 responseFields = s.responseFields;
8145
8146 // Fill responseXXX fields
8147 for ( type in responseFields ) {
8148 if ( type in responses ) {
8149 jqXHR[ responseFields[type] ] = responses[ type ];
8150 }
8151 }
8152
8153 // Remove auto dataType and get content-type in the process
8154 while( dataTypes[ 0 ] === "*" ) {
8155 dataTypes.shift();
8156 if ( ct === undefined ) {
8157 ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
8158 }
8159 }
8160
8161 // Check if we're dealing with a known content-type
8162 if ( ct ) {
8163 for ( type in contents ) {
8164 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8165 dataTypes.unshift( type );
8166 break;
8167 }
8168 }
8169 }
8170
8171 // Check to see if we have a response for the expected dataType
8172 if ( dataTypes[ 0 ] in responses ) {
8173 finalDataType = dataTypes[ 0 ];
8174 } else {
8175 // Try convertible dataTypes
8176 for ( type in responses ) {
8177 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8178 finalDataType = type;
8179 break;
8180 }
8181 if ( !firstDataType ) {
8182 firstDataType = type;
8183 }
8184 }
8185 // Or just use first one
8186 finalDataType = finalDataType || firstDataType;
8187 }
8188
8189 // If we found a dataType
8190 // We add the dataType to the list if needed
8191 // and return the corresponding response
8192 if ( finalDataType ) {
8193 if ( finalDataType !== dataTypes[ 0 ] ) {
8194 dataTypes.unshift( finalDataType );
8195 }
8196 return responses[ finalDataType ];
8197 }
8198}
8199
8200// Chain conversions given the request and the original response
8201function ajaxConvert( s, response ) {
8202 var conv2, current, conv, tmp,
8203 converters = {},
8204 i = 0,
8205 // Work with a copy of dataTypes in case we need to modify it for conversion
8206 dataTypes = s.dataTypes.slice(),
8207 prev = dataTypes[ 0 ];
8208
8209 // Apply the dataFilter if provided
8210 if ( s.dataFilter ) {
8211 response = s.dataFilter( response, s.dataType );
8212 }
8213
8214 // Create converters map with lowercased keys
8215 if ( dataTypes[ 1 ] ) {
8216 for ( conv in s.converters ) {
8217 converters[ conv.toLowerCase() ] = s.converters[ conv ];
8218 }
8219 }
8220
8221 // Convert to each sequential dataType, tolerating list modification
8222 for ( ; (current = dataTypes[++i]); ) {
8223
8224 // There's only work to do if current dataType is non-auto
8225 if ( current !== "*" ) {
8226
8227 // Convert response if prev dataType is non-auto and differs from current
8228 if ( prev !== "*" && prev !== current ) {
8229
8230 // Seek a direct converter
8231 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
8232
8233 // If none found, seek a pair
8234 if ( !conv ) {
8235 for ( conv2 in converters ) {
8236
8237 // If conv2 outputs current
8238 tmp = conv2.split(" ");
8239 if ( tmp[ 1 ] === current ) {
8240
8241 // If prev can be converted to accepted input
8242 conv = converters[ prev + " " + tmp[ 0 ] ] ||
8243 converters[ "* " + tmp[ 0 ] ];
8244 if ( conv ) {
8245 // Condense equivalence converters
8246 if ( conv === true ) {
8247 conv = converters[ conv2 ];
8248
8249 // Otherwise, insert the intermediate dataType
8250 } else if ( converters[ conv2 ] !== true ) {
8251 current = tmp[ 0 ];
8252 dataTypes.splice( i--, 0, current );
8253 }
8254
8255 break;
8256 }
8257 }
8258 }
8259 }
8260
8261 // Apply converter (if not an equivalence)
8262 if ( conv !== true ) {
8263
8264 // Unless errors are allowed to bubble, catch and return them
8265 if ( conv && s["throws"] ) {
8266 response = conv( response );
8267 } else {
8268 try {
8269 response = conv( response );
8270 } catch ( e ) {
8271 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
8272 }
8273 }
8274 }
8275 }
8276
8277 // Update prev for next iteration
8278 prev = current;
8279 }
8280 }
8281
8282 return { state: "success", data: response };
8283}
8284// Install script dataType
8285jQuery.ajaxSetup({
8286 accepts: {
8287 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8288 },
8289 contents: {
8290 script: /(?:java|ecma)script/
8291 },
8292 converters: {
8293 "text script": function( text ) {
8294 jQuery.globalEval( text );
8295 return text;
8296 }
8297 }
8298});
8299
8300// Handle cache's special case and global
8301jQuery.ajaxPrefilter( "script", function( s ) {
8302 if ( s.cache === undefined ) {
8303 s.cache = false;
8304 }
8305 if ( s.crossDomain ) {
8306 s.type = "GET";
8307 s.global = false;
8308 }
8309});
8310
8311// Bind script tag hack transport
8312jQuery.ajaxTransport( "script", function(s) {
8313
8314 // This transport only deals with cross domain requests
8315 if ( s.crossDomain ) {
8316
8317 var script,
8318 head = document.head || jQuery("head")[0] || document.documentElement;
8319
8320 return {
8321
8322 send: function( _, callback ) {
8323
8324 script = document.createElement("script");
8325
8326 script.async = true;
8327
8328 if ( s.scriptCharset ) {
8329 script.charset = s.scriptCharset;
8330 }
8331
8332 script.src = s.url;
8333
8334 // Attach handlers for all browsers
8335 script.onload = script.onreadystatechange = function( _, isAbort ) {
8336
8337 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8338
8339 // Handle memory leak in IE
8340 script.onload = script.onreadystatechange = null;
8341
8342 // Remove the script
8343 if ( script.parentNode ) {
8344 script.parentNode.removeChild( script );
8345 }
8346
8347 // Dereference the script
8348 script = null;
8349
8350 // Callback if not abort
8351 if ( !isAbort ) {
8352 callback( 200, "success" );
8353 }
8354 }
8355 };
8356
8357 // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
8358 // Use native DOM manipulation to avoid our domManip AJAX trickery
8359 head.insertBefore( script, head.firstChild );
8360 },
8361
8362 abort: function() {
8363 if ( script ) {
8364 script.onload( undefined, true );
8365 }
8366 }
8367 };
8368 }
8369});
8370var oldCallbacks = [],
8371 rjsonp = /(=)\?(?=&|$)|\?\?/;
8372
8373// Default jsonp settings
8374jQuery.ajaxSetup({
8375 jsonp: "callback",
8376 jsonpCallback: function() {
8377 var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
8378 this[ callback ] = true;
8379 return callback;
8380 }
8381});
8382
8383// Detect, normalize options and install callbacks for jsonp requests
8384jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8385
8386 var callbackName, overwritten, responseContainer,
8387 jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
8388 "url" :
8389 typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
8390 );
8391
8392 // Handle iff the expected data type is "jsonp" or we have a parameter to set
8393 if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
8394
8395 // Get callback name, remembering preexisting value associated with it
8396 callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
8397 s.jsonpCallback() :
8398 s.jsonpCallback;
8399
8400 // Insert callback into url or form data
8401 if ( jsonProp ) {
8402 s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
8403 } else if ( s.jsonp !== false ) {
8404 s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
8405 }
8406
8407 // Use data converter to retrieve json after script execution
8408 s.converters["script json"] = function() {
8409 if ( !responseContainer ) {
8410 jQuery.error( callbackName + " was not called" );
8411 }
8412 return responseContainer[ 0 ];
8413 };
8414
8415 // force json dataType
8416 s.dataTypes[ 0 ] = "json";
8417
8418 // Install callback
8419 overwritten = window[ callbackName ];
8420 window[ callbackName ] = function() {
8421 responseContainer = arguments;
8422 };
8423
8424 // Clean-up function (fires after converters)
8425 jqXHR.always(function() {
8426 // Restore preexisting value
8427 window[ callbackName ] = overwritten;
8428
8429 // Save back as free
8430 if ( s[ callbackName ] ) {
8431 // make sure that re-using the options doesn't screw things around
8432 s.jsonpCallback = originalSettings.jsonpCallback;
8433
8434 // save the callback name for future use
8435 oldCallbacks.push( callbackName );
8436 }
8437
8438 // Call if it was a function and we have a response
8439 if ( responseContainer && jQuery.isFunction( overwritten ) ) {
8440 overwritten( responseContainer[ 0 ] );
8441 }
8442
8443 responseContainer = overwritten = undefined;
8444 });
8445
8446 // Delegate to script
8447 return "script";
8448 }
8449});
8450var xhrCallbacks, xhrSupported,
8451 xhrId = 0,
8452 // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8453 xhrOnUnloadAbort = window.ActiveXObject && function() {
8454 // Abort all pending requests
8455 var key;
8456 for ( key in xhrCallbacks ) {
8457 xhrCallbacks[ key ]( undefined, true );
8458 }
8459 };
8460
8461// Functions to create xhrs
8462function createStandardXHR() {
8463 try {
8464 return new window.XMLHttpRequest();
8465 } catch( e ) {}
8466}
8467
8468function createActiveXHR() {
8469 try {
8470 return new window.ActiveXObject("Microsoft.XMLHTTP");
8471 } catch( e ) {}
8472}
8473
8474// Create the request object
8475// (This is still attached to ajaxSettings for backward compatibility)
8476jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8477 /* Microsoft failed to properly
8478 * implement the XMLHttpRequest in IE7 (can't request local files),
8479 * so we use the ActiveXObject when it is available
8480 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8481 * we need a fallback.
8482 */
8483 function() {
8484 return !this.isLocal && createStandardXHR() || createActiveXHR();
8485 } :
8486 // For all other browsers, use the standard XMLHttpRequest object
8487 createStandardXHR;
8488
8489// Determine support properties
8490xhrSupported = jQuery.ajaxSettings.xhr();
8491jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
8492xhrSupported = jQuery.support.ajax = !!xhrSupported;
8493
8494// Create transport if the browser can provide an xhr
8495if ( xhrSupported ) {
8496
8497 jQuery.ajaxTransport(function( s ) {
8498 // Cross domain only allowed if supported through XMLHttpRequest
8499 if ( !s.crossDomain || jQuery.support.cors ) {
8500
8501 var callback;
8502
8503 return {
8504 send: function( headers, complete ) {
8505
8506 // Get a new xhr
8507 var handle, i,
8508 xhr = s.xhr();
8509
8510 // Open the socket
8511 // Passing null username, generates a login popup on Opera (#2865)
8512 if ( s.username ) {
8513 xhr.open( s.type, s.url, s.async, s.username, s.password );
8514 } else {
8515 xhr.open( s.type, s.url, s.async );
8516 }
8517
8518 // Apply custom fields if provided
8519 if ( s.xhrFields ) {
8520 for ( i in s.xhrFields ) {
8521 xhr[ i ] = s.xhrFields[ i ];
8522 }
8523 }
8524
8525 // Override mime type if needed
8526 if ( s.mimeType && xhr.overrideMimeType ) {
8527 xhr.overrideMimeType( s.mimeType );
8528 }
8529
8530 // X-Requested-With header
8531 // For cross-domain requests, seeing as conditions for a preflight are
8532 // akin to a jigsaw puzzle, we simply never set it to be sure.
8533 // (it can always be set on a per-request basis or even using ajaxSetup)
8534 // For same-domain requests, won't change header if already provided.
8535 if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8536 headers["X-Requested-With"] = "XMLHttpRequest";
8537 }
8538
8539 // Need an extra try/catch for cross domain requests in Firefox 3
8540 try {
8541 for ( i in headers ) {
8542 xhr.setRequestHeader( i, headers[ i ] );
8543 }
8544 } catch( err ) {}
8545
8546 // Do send the request
8547 // This may raise an exception which is actually
8548 // handled in jQuery.ajax (so no try/catch here)
8549 xhr.send( ( s.hasContent && s.data ) || null );
8550
8551 // Listener
8552 callback = function( _, isAbort ) {
8553 var status, responseHeaders, statusText, responses;
8554
8555 // Firefox throws exceptions when accessing properties
8556 // of an xhr when a network error occurred
8557 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8558 try {
8559
8560 // Was never called and is aborted or complete
8561 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8562
8563 // Only called once
8564 callback = undefined;
8565
8566 // Do not keep as active anymore
8567 if ( handle ) {
8568 xhr.onreadystatechange = jQuery.noop;
8569 if ( xhrOnUnloadAbort ) {
8570 delete xhrCallbacks[ handle ];
8571 }
8572 }
8573
8574 // If it's an abort
8575 if ( isAbort ) {
8576 // Abort it manually if needed
8577 if ( xhr.readyState !== 4 ) {
8578 xhr.abort();
8579 }
8580 } else {
8581 responses = {};
8582 status = xhr.status;
8583 responseHeaders = xhr.getAllResponseHeaders();
8584
8585 // When requesting binary data, IE6-9 will throw an exception
8586 // on any attempt to access responseText (#11426)
8587 if ( typeof xhr.responseText === "string" ) {
8588 responses.text = xhr.responseText;
8589 }
8590
8591 // Firefox throws an exception when accessing
8592 // statusText for faulty cross-domain requests
8593 try {
8594 statusText = xhr.statusText;
8595 } catch( e ) {
8596 // We normalize with Webkit giving an empty statusText
8597 statusText = "";
8598 }
8599
8600 // Filter status for non standard behaviors
8601
8602 // If the request is local and we have data: assume a success
8603 // (success with no data won't get notified, that's the best we
8604 // can do given current implementations)
8605 if ( !status && s.isLocal && !s.crossDomain ) {
8606 status = responses.text ? 200 : 404;
8607 // IE - #1450: sometimes returns 1223 when it should be 204
8608 } else if ( status === 1223 ) {
8609 status = 204;
8610 }
8611 }
8612 }
8613 } catch( firefoxAccessException ) {
8614 if ( !isAbort ) {
8615 complete( -1, firefoxAccessException );
8616 }
8617 }
8618
8619 // Call complete if needed
8620 if ( responses ) {
8621 complete( status, statusText, responses, responseHeaders );
8622 }
8623 };
8624
8625 if ( !s.async ) {
8626 // if we're in sync mode we fire the callback
8627 callback();
8628 } else if ( xhr.readyState === 4 ) {
8629 // (IE6 & IE7) if it's in cache and has been
8630 // retrieved directly we need to fire the callback
8631 setTimeout( callback );
8632 } else {
8633 handle = ++xhrId;
8634 if ( xhrOnUnloadAbort ) {
8635 // Create the active xhrs callbacks list if needed
8636 // and attach the unload handler
8637 if ( !xhrCallbacks ) {
8638 xhrCallbacks = {};
8639 jQuery( window ).unload( xhrOnUnloadAbort );
8640 }
8641 // Add to list of active xhrs callbacks
8642 xhrCallbacks[ handle ] = callback;
8643 }
8644 xhr.onreadystatechange = callback;
8645 }
8646 },
8647
8648 abort: function() {
8649 if ( callback ) {
8650 callback( undefined, true );
8651 }
8652 }
8653 };
8654 }
8655 });
8656}
8657var fxNow, timerId,
8658 rfxtypes = /^(?:toggle|show|hide)$/,
8659 rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
8660 rrun = /queueHooks$/,
8661 animationPrefilters = [ defaultPrefilter ],
8662 tweeners = {
8663 "*": [function( prop, value ) {
8664 var end, unit,
8665 tween = this.createTween( prop, value ),
8666 parts = rfxnum.exec( value ),
8667 target = tween.cur(),
8668 start = +target || 0,
8669 scale = 1,
8670 maxIterations = 20;
8671
8672 if ( parts ) {
8673 end = +parts[2];
8674 unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
8675
8676 // We need to compute starting value
8677 if ( unit !== "px" && start ) {
8678 // Iteratively approximate from a nonzero starting point
8679 // Prefer the current property, because this process will be trivial if it uses the same units
8680 // Fallback to end or a simple constant
8681 start = jQuery.css( tween.elem, prop, true ) || end || 1;
8682
8683 do {
8684 // If previous iteration zeroed out, double until we get *something*
8685 // Use a string for doubling factor so we don't accidentally see scale as unchanged below
8686 scale = scale || ".5";
8687
8688 // Adjust and apply
8689 start = start / scale;
8690 jQuery.style( tween.elem, prop, start + unit );
8691
8692 // Update scale, tolerating zero or NaN from tween.cur()
8693 // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
8694 } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
8695 }
8696
8697 tween.unit = unit;
8698 tween.start = start;
8699 // If a +=/-= token was provided, we're doing a relative animation
8700 tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
8701 }
8702 return tween;
8703 }]
8704 };
8705
8706// Animations created synchronously will run synchronously
8707function createFxNow() {
8708 setTimeout(function() {
8709 fxNow = undefined;
8710 });
8711 return ( fxNow = jQuery.now() );
8712}
8713
8714function createTweens( animation, props ) {
8715 jQuery.each( props, function( prop, value ) {
8716 var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
8717 index = 0,
8718 length = collection.length;
8719 for ( ; index < length; index++ ) {
8720 if ( collection[ index ].call( animation, prop, value ) ) {
8721
8722 // we're done with this property
8723 return;
8724 }
8725 }
8726 });
8727}
8728
8729function Animation( elem, properties, options ) {
8730 var result,
8731 stopped,
8732 index = 0,
8733 length = animationPrefilters.length,
8734 deferred = jQuery.Deferred().always( function() {
8735 // don't match elem in the :animated selector
8736 delete tick.elem;
8737 }),
8738 tick = function() {
8739 if ( stopped ) {
8740 return false;
8741 }
8742 var currentTime = fxNow || createFxNow(),
8743 remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
8744 // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
8745 temp = remaining / animation.duration || 0,
8746 percent = 1 - temp,
8747 index = 0,
8748 length = animation.tweens.length;
8749
8750 for ( ; index < length ; index++ ) {
8751 animation.tweens[ index ].run( percent );
8752 }
8753
8754 deferred.notifyWith( elem, [ animation, percent, remaining ]);
8755
8756 if ( percent < 1 && length ) {
8757 return remaining;
8758 } else {
8759 deferred.resolveWith( elem, [ animation ] );
8760 return false;
8761 }
8762 },
8763 animation = deferred.promise({
8764 elem: elem,
8765 props: jQuery.extend( {}, properties ),
8766 opts: jQuery.extend( true, { specialEasing: {} }, options ),
8767 originalProperties: properties,
8768 originalOptions: options,
8769 startTime: fxNow || createFxNow(),
8770 duration: options.duration,
8771 tweens: [],
8772 createTween: function( prop, end ) {
8773 var tween = jQuery.Tween( elem, animation.opts, prop, end,
8774 animation.opts.specialEasing[ prop ] || animation.opts.easing );
8775 animation.tweens.push( tween );
8776 return tween;
8777 },
8778 stop: function( gotoEnd ) {
8779 var index = 0,
8780 // if we are going to the end, we want to run all the tweens
8781 // otherwise we skip this part
8782 length = gotoEnd ? animation.tweens.length : 0;
8783 if ( stopped ) {
8784 return this;
8785 }
8786 stopped = true;
8787 for ( ; index < length ; index++ ) {
8788 animation.tweens[ index ].run( 1 );
8789 }
8790
8791 // resolve when we played the last frame
8792 // otherwise, reject
8793 if ( gotoEnd ) {
8794 deferred.resolveWith( elem, [ animation, gotoEnd ] );
8795 } else {
8796 deferred.rejectWith( elem, [ animation, gotoEnd ] );
8797 }
8798 return this;
8799 }
8800 }),
8801 props = animation.props;
8802
8803 propFilter( props, animation.opts.specialEasing );
8804
8805 for ( ; index < length ; index++ ) {
8806 result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
8807 if ( result ) {
8808 return result;
8809 }
8810 }
8811
8812 createTweens( animation, props );
8813
8814 if ( jQuery.isFunction( animation.opts.start ) ) {
8815 animation.opts.start.call( elem, animation );
8816 }
8817
8818 jQuery.fx.timer(
8819 jQuery.extend( tick, {
8820 elem: elem,
8821 anim: animation,
8822 queue: animation.opts.queue
8823 })
8824 );
8825
8826 // attach callbacks from options
8827 return animation.progress( animation.opts.progress )
8828 .done( animation.opts.done, animation.opts.complete )
8829 .fail( animation.opts.fail )
8830 .always( animation.opts.always );
8831}
8832
8833function propFilter( props, specialEasing ) {
8834 var value, name, index, easing, hooks;
8835
8836 // camelCase, specialEasing and expand cssHook pass
8837 for ( index in props ) {
8838 name = jQuery.camelCase( index );
8839 easing = specialEasing[ name ];
8840 value = props[ index ];
8841 if ( jQuery.isArray( value ) ) {
8842 easing = value[ 1 ];
8843 value = props[ index ] = value[ 0 ];
8844 }
8845
8846 if ( index !== name ) {
8847 props[ name ] = value;
8848 delete props[ index ];
8849 }
8850
8851 hooks = jQuery.cssHooks[ name ];
8852 if ( hooks && "expand" in hooks ) {
8853 value = hooks.expand( value );
8854 delete props[ name ];
8855
8856 // not quite $.extend, this wont overwrite keys already present.
8857 // also - reusing 'index' from above because we have the correct "name"
8858 for ( index in value ) {
8859 if ( !( index in props ) ) {
8860 props[ index ] = value[ index ];
8861 specialEasing[ index ] = easing;
8862 }
8863 }
8864 } else {
8865 specialEasing[ name ] = easing;
8866 }
8867 }
8868}
8869
8870jQuery.Animation = jQuery.extend( Animation, {
8871
8872 tweener: function( props, callback ) {
8873 if ( jQuery.isFunction( props ) ) {
8874 callback = props;
8875 props = [ "*" ];
8876 } else {
8877 props = props.split(" ");
8878 }
8879
8880 var prop,
8881 index = 0,
8882 length = props.length;
8883
8884 for ( ; index < length ; index++ ) {
8885 prop = props[ index ];
8886 tweeners[ prop ] = tweeners[ prop ] || [];
8887 tweeners[ prop ].unshift( callback );
8888 }
8889 },
8890
8891 prefilter: function( callback, prepend ) {
8892 if ( prepend ) {
8893 animationPrefilters.unshift( callback );
8894 } else {
8895 animationPrefilters.push( callback );
8896 }
8897 }
8898});
8899
8900function defaultPrefilter( elem, props, opts ) {
8901 /*jshint validthis:true */
8902 var prop, index, length,
8903 value, dataShow, toggle,
8904 tween, hooks, oldfire,
8905 anim = this,
8906 style = elem.style,
8907 orig = {},
8908 handled = [],
8909 hidden = elem.nodeType && isHidden( elem );
8910
8911 // handle queue: false promises
8912 if ( !opts.queue ) {
8913 hooks = jQuery._queueHooks( elem, "fx" );
8914 if ( hooks.unqueued == null ) {
8915 hooks.unqueued = 0;
8916 oldfire = hooks.empty.fire;
8917 hooks.empty.fire = function() {
8918 if ( !hooks.unqueued ) {
8919 oldfire();
8920 }
8921 };
8922 }
8923 hooks.unqueued++;
8924
8925 anim.always(function() {
8926 // doing this makes sure that the complete handler will be called
8927 // before this completes
8928 anim.always(function() {
8929 hooks.unqueued--;
8930 if ( !jQuery.queue( elem, "fx" ).length ) {
8931 hooks.empty.fire();
8932 }
8933 });
8934 });
8935 }
8936
8937 // height/width overflow pass
8938 if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
8939 // Make sure that nothing sneaks out
8940 // Record all 3 overflow attributes because IE does not
8941 // change the overflow attribute when overflowX and
8942 // overflowY are set to the same value
8943 opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
8944
8945 // Set display property to inline-block for height/width
8946 // animations on inline elements that are having width/height animated
8947 if ( jQuery.css( elem, "display" ) === "inline" &&
8948 jQuery.css( elem, "float" ) === "none" ) {
8949
8950 // inline-level elements accept inline-block;
8951 // block-level elements need to be inline with layout
8952 if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
8953 style.display = "inline-block";
8954
8955 } else {
8956 style.zoom = 1;
8957 }
8958 }
8959 }
8960
8961 if ( opts.overflow ) {
8962 style.overflow = "hidden";
8963 if ( !jQuery.support.shrinkWrapBlocks ) {
8964 anim.always(function() {
8965 style.overflow = opts.overflow[ 0 ];
8966 style.overflowX = opts.overflow[ 1 ];
8967 style.overflowY = opts.overflow[ 2 ];
8968 });
8969 }
8970 }
8971
8972
8973 // show/hide pass
8974 for ( index in props ) {
8975 value = props[ index ];
8976 if ( rfxtypes.exec( value ) ) {
8977 delete props[ index ];
8978 toggle = toggle || value === "toggle";
8979 if ( value === ( hidden ? "hide" : "show" ) ) {
8980 continue;
8981 }
8982 handled.push( index );
8983 }
8984 }
8985
8986 length = handled.length;
8987 if ( length ) {
8988 dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
8989 if ( "hidden" in dataShow ) {
8990 hidden = dataShow.hidden;
8991 }
8992
8993 // store state if its toggle - enables .stop().toggle() to "reverse"
8994 if ( toggle ) {
8995 dataShow.hidden = !hidden;
8996 }
8997 if ( hidden ) {
8998 jQuery( elem ).show();
8999 } else {
9000 anim.done(function() {
9001 jQuery( elem ).hide();
9002 });
9003 }
9004 anim.done(function() {
9005 var prop;
9006 jQuery._removeData( elem, "fxshow" );
9007 for ( prop in orig ) {
9008 jQuery.style( elem, prop, orig[ prop ] );
9009 }
9010 });
9011 for ( index = 0 ; index < length ; index++ ) {
9012 prop = handled[ index ];
9013 tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
9014 orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
9015
9016 if ( !( prop in dataShow ) ) {
9017 dataShow[ prop ] = tween.start;
9018 if ( hidden ) {
9019 tween.end = tween.start;
9020 tween.start = prop === "width" || prop === "height" ? 1 : 0;
9021 }
9022 }
9023 }
9024 }
9025}
9026
9027function Tween( elem, options, prop, end, easing ) {
9028 return new Tween.prototype.init( elem, options, prop, end, easing );
9029}
9030jQuery.Tween = Tween;
9031
9032Tween.prototype = {
9033 constructor: Tween,
9034 init: function( elem, options, prop, end, easing, unit ) {
9035 this.elem = elem;
9036 this.prop = prop;
9037 this.easing = easing || "swing";
9038 this.options = options;
9039 this.start = this.now = this.cur();
9040 this.end = end;
9041 this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
9042 },
9043 cur: function() {
9044 var hooks = Tween.propHooks[ this.prop ];
9045
9046 return hooks && hooks.get ?
9047 hooks.get( this ) :
9048 Tween.propHooks._default.get( this );
9049 },
9050 run: function( percent ) {
9051 var eased,
9052 hooks = Tween.propHooks[ this.prop ];
9053
9054 if ( this.options.duration ) {
9055 this.pos = eased = jQuery.easing[ this.easing ](
9056 percent, this.options.duration * percent, 0, 1, this.options.duration
9057 );
9058 } else {
9059 this.pos = eased = percent;
9060 }
9061 this.now = ( this.end - this.start ) * eased + this.start;
9062
9063 if ( this.options.step ) {
9064 this.options.step.call( this.elem, this.now, this );
9065 }
9066
9067 if ( hooks && hooks.set ) {
9068 hooks.set( this );
9069 } else {
9070 Tween.propHooks._default.set( this );
9071 }
9072 return this;
9073 }
9074};
9075
9076Tween.prototype.init.prototype = Tween.prototype;
9077
9078Tween.propHooks = {
9079 _default: {
9080 get: function( tween ) {
9081 var result;
9082
9083 if ( tween.elem[ tween.prop ] != null &&
9084 (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
9085 return tween.elem[ tween.prop ];
9086 }
9087
9088 // passing an empty string as a 3rd parameter to .css will automatically
9089 // attempt a parseFloat and fallback to a string if the parse fails
9090 // so, simple values such as "10px" are parsed to Float.
9091 // complex values such as "rotate(1rad)" are returned as is.
9092 result = jQuery.css( tween.elem, tween.prop, "" );
9093 // Empty strings, null, undefined and "auto" are converted to 0.
9094 return !result || result === "auto" ? 0 : result;
9095 },
9096 set: function( tween ) {
9097 // use step hook for back compat - use cssHook if its there - use .style if its
9098 // available and use plain properties where available
9099 if ( jQuery.fx.step[ tween.prop ] ) {
9100 jQuery.fx.step[ tween.prop ]( tween );
9101 } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
9102 jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
9103 } else {
9104 tween.elem[ tween.prop ] = tween.now;
9105 }
9106 }
9107 }
9108};
9109
9110// Remove in 2.0 - this supports IE8's panic based approach
9111// to setting things on disconnected nodes
9112
9113Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
9114 set: function( tween ) {
9115 if ( tween.elem.nodeType && tween.elem.parentNode ) {
9116 tween.elem[ tween.prop ] = tween.now;
9117 }
9118 }
9119};
9120
9121jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
9122 var cssFn = jQuery.fn[ name ];
9123 jQuery.fn[ name ] = function( speed, easing, callback ) {
9124 return speed == null || typeof speed === "boolean" ?
9125 cssFn.apply( this, arguments ) :
9126 this.animate( genFx( name, true ), speed, easing, callback );
9127 };
9128});
9129
9130jQuery.fn.extend({
9131 fadeTo: function( speed, to, easing, callback ) {
9132
9133 // show any hidden elements after setting opacity to 0
9134 return this.filter( isHidden ).css( "opacity", 0 ).show()
9135
9136 // animate to the value specified
9137 .end().animate({ opacity: to }, speed, easing, callback );
9138 },
9139 animate: function( prop, speed, easing, callback ) {
9140 var empty = jQuery.isEmptyObject( prop ),
9141 optall = jQuery.speed( speed, easing, callback ),
9142 doAnimation = function() {
9143 // Operate on a copy of prop so per-property easing won't be lost
9144 var anim = Animation( this, jQuery.extend( {}, prop ), optall );
9145 doAnimation.finish = function() {
9146 anim.stop( true );
9147 };
9148 // Empty animations, or finishing resolves immediately
9149 if ( empty || jQuery._data( this, "finish" ) ) {
9150 anim.stop( true );
9151 }
9152 };
9153 doAnimation.finish = doAnimation;
9154
9155 return empty || optall.queue === false ?
9156 this.each( doAnimation ) :
9157 this.queue( optall.queue, doAnimation );
9158 },
9159 stop: function( type, clearQueue, gotoEnd ) {
9160 var stopQueue = function( hooks ) {
9161 var stop = hooks.stop;
9162 delete hooks.stop;
9163 stop( gotoEnd );
9164 };
9165
9166 if ( typeof type !== "string" ) {
9167 gotoEnd = clearQueue;
9168 clearQueue = type;
9169 type = undefined;
9170 }
9171 if ( clearQueue && type !== false ) {
9172 this.queue( type || "fx", [] );
9173 }
9174
9175 return this.each(function() {
9176 var dequeue = true,
9177 index = type != null && type + "queueHooks",
9178 timers = jQuery.timers,
9179 data = jQuery._data( this );
9180
9181 if ( index ) {
9182 if ( data[ index ] && data[ index ].stop ) {
9183 stopQueue( data[ index ] );
9184 }
9185 } else {
9186 for ( index in data ) {
9187 if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
9188 stopQueue( data[ index ] );
9189 }
9190 }
9191 }
9192
9193 for ( index = timers.length; index--; ) {
9194 if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
9195 timers[ index ].anim.stop( gotoEnd );
9196 dequeue = false;
9197 timers.splice( index, 1 );
9198 }
9199 }
9200
9201 // start the next in the queue if the last step wasn't forced
9202 // timers currently will call their complete callbacks, which will dequeue
9203 // but only if they were gotoEnd
9204 if ( dequeue || !gotoEnd ) {
9205 jQuery.dequeue( this, type );
9206 }
9207 });
9208 },
9209 finish: function( type ) {
9210 if ( type !== false ) {
9211 type = type || "fx";
9212 }
9213 return this.each(function() {
9214 var index,
9215 data = jQuery._data( this ),
9216 queue = data[ type + "queue" ],
9217 hooks = data[ type + "queueHooks" ],
9218 timers = jQuery.timers,
9219 length = queue ? queue.length : 0;
9220
9221 // enable finishing flag on private data
9222 data.finish = true;
9223
9224 // empty the queue first
9225 jQuery.queue( this, type, [] );
9226
9227 if ( hooks && hooks.cur && hooks.cur.finish ) {
9228 hooks.cur.finish.call( this );
9229 }
9230
9231 // look for any active animations, and finish them
9232 for ( index = timers.length; index--; ) {
9233 if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
9234 timers[ index ].anim.stop( true );
9235 timers.splice( index, 1 );
9236 }
9237 }
9238
9239 // look for any animations in the old queue and finish them
9240 for ( index = 0; index < length; index++ ) {
9241 if ( queue[ index ] && queue[ index ].finish ) {
9242 queue[ index ].finish.call( this );
9243 }
9244 }
9245
9246 // turn off finishing flag
9247 delete data.finish;
9248 });
9249 }
9250});
9251
9252// Generate parameters to create a standard animation
9253function genFx( type, includeWidth ) {
9254 var which,
9255 attrs = { height: type },
9256 i = 0;
9257
9258 // if we include width, step value is 1 to do all cssExpand values,
9259 // if we don't include width, step value is 2 to skip over Left and Right
9260 includeWidth = includeWidth? 1 : 0;
9261 for( ; i < 4 ; i += 2 - includeWidth ) {
9262 which = cssExpand[ i ];
9263 attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
9264 }
9265
9266 if ( includeWidth ) {
9267 attrs.opacity = attrs.width = type;
9268 }
9269
9270 return attrs;
9271}
9272
9273// Generate shortcuts for custom animations
9274jQuery.each({
9275 slideDown: genFx("show"),
9276 slideUp: genFx("hide"),
9277 slideToggle: genFx("toggle"),
9278 fadeIn: { opacity: "show" },
9279 fadeOut: { opacity: "hide" },
9280 fadeToggle: { opacity: "toggle" }
9281}, function( name, props ) {
9282 jQuery.fn[ name ] = function( speed, easing, callback ) {
9283 return this.animate( props, speed, easing, callback );
9284 };
9285});
9286
9287jQuery.speed = function( speed, easing, fn ) {
9288 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9289 complete: fn || !fn && easing ||
9290 jQuery.isFunction( speed ) && speed,
9291 duration: speed,
9292 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9293 };
9294
9295 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9296 opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9297
9298 // normalize opt.queue - true/undefined/null -> "fx"
9299 if ( opt.queue == null || opt.queue === true ) {
9300 opt.queue = "fx";
9301 }
9302
9303 // Queueing
9304 opt.old = opt.complete;
9305
9306 opt.complete = function() {
9307 if ( jQuery.isFunction( opt.old ) ) {
9308 opt.old.call( this );
9309 }
9310
9311 if ( opt.queue ) {
9312 jQuery.dequeue( this, opt.queue );
9313 }
9314 };
9315
9316 return opt;
9317};
9318
9319jQuery.easing = {
9320 linear: function( p ) {
9321 return p;
9322 },
9323 swing: function( p ) {
9324 return 0.5 - Math.cos( p*Math.PI ) / 2;
9325 }
9326};
9327
9328jQuery.timers = [];
9329jQuery.fx = Tween.prototype.init;
9330jQuery.fx.tick = function() {
9331 var timer,
9332 timers = jQuery.timers,
9333 i = 0;
9334
9335 fxNow = jQuery.now();
9336
9337 for ( ; i < timers.length; i++ ) {
9338 timer = timers[ i ];
9339 // Checks the timer has not already been removed
9340 if ( !timer() && timers[ i ] === timer ) {
9341 timers.splice( i--, 1 );
9342 }
9343 }
9344
9345 if ( !timers.length ) {
9346 jQuery.fx.stop();
9347 }
9348 fxNow = undefined;
9349};
9350
9351jQuery.fx.timer = function( timer ) {
9352 if ( timer() && jQuery.timers.push( timer ) ) {
9353 jQuery.fx.start();
9354 }
9355};
9356
9357jQuery.fx.interval = 13;
9358
9359jQuery.fx.start = function() {
9360 if ( !timerId ) {
9361 timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
9362 }
9363};
9364
9365jQuery.fx.stop = function() {
9366 clearInterval( timerId );
9367 timerId = null;
9368};
9369
9370jQuery.fx.speeds = {
9371 slow: 600,
9372 fast: 200,
9373 // Default speed
9374 _default: 400
9375};
9376
9377// Back Compat <1.8 extension point
9378jQuery.fx.step = {};
9379
9380if ( jQuery.expr && jQuery.expr.filters ) {
9381 jQuery.expr.filters.animated = function( elem ) {
9382 return jQuery.grep(jQuery.timers, function( fn ) {
9383 return elem === fn.elem;
9384 }).length;
9385 };
9386}
9387jQuery.fn.offset = function( options ) {
9388 if ( arguments.length ) {
9389 return options === undefined ?
9390 this :
9391 this.each(function( i ) {
9392 jQuery.offset.setOffset( this, options, i );
9393 });
9394 }
9395
9396 var docElem, win,
9397 box = { top: 0, left: 0 },
9398 elem = this[ 0 ],
9399 doc = elem && elem.ownerDocument;
9400
9401 if ( !doc ) {
9402 return;
9403 }
9404
9405 docElem = doc.documentElement;
9406
9407 // Make sure it's not a disconnected DOM node
9408 if ( !jQuery.contains( docElem, elem ) ) {
9409 return box;
9410 }
9411
9412 // If we don't have gBCR, just use 0,0 rather than error
9413 // BlackBerry 5, iOS 3 (original iPhone)
9414 if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
9415 box = elem.getBoundingClientRect();
9416 }
9417 win = getWindow( doc );
9418 return {
9419 top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
9420 left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
9421 };
9422};
9423
9424jQuery.offset = {
9425
9426 setOffset: function( elem, options, i ) {
9427 var position = jQuery.css( elem, "position" );
9428
9429 // set position first, in-case top/left are set even on static elem
9430 if ( position === "static" ) {
9431 elem.style.position = "relative";
9432 }
9433
9434 var curElem = jQuery( elem ),
9435 curOffset = curElem.offset(),
9436 curCSSTop = jQuery.css( elem, "top" ),
9437 curCSSLeft = jQuery.css( elem, "left" ),
9438 calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9439 props = {}, curPosition = {}, curTop, curLeft;
9440
9441 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9442 if ( calculatePosition ) {
9443 curPosition = curElem.position();
9444 curTop = curPosition.top;
9445 curLeft = curPosition.left;
9446 } else {
9447 curTop = parseFloat( curCSSTop ) || 0;
9448 curLeft = parseFloat( curCSSLeft ) || 0;
9449 }
9450
9451 if ( jQuery.isFunction( options ) ) {
9452 options = options.call( elem, i, curOffset );
9453 }
9454
9455 if ( options.top != null ) {
9456 props.top = ( options.top - curOffset.top ) + curTop;
9457 }
9458 if ( options.left != null ) {
9459 props.left = ( options.left - curOffset.left ) + curLeft;
9460 }
9461
9462 if ( "using" in options ) {
9463 options.using.call( elem, props );
9464 } else {
9465 curElem.css( props );
9466 }
9467 }
9468};
9469
9470
9471jQuery.fn.extend({
9472
9473 position: function() {
9474 if ( !this[ 0 ] ) {
9475 return;
9476 }
9477
9478 var offsetParent, offset,
9479 parentOffset = { top: 0, left: 0 },
9480 elem = this[ 0 ];
9481
9482 // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
9483 if ( jQuery.css( elem, "position" ) === "fixed" ) {
9484 // we assume that getBoundingClientRect is available when computed position is fixed
9485 offset = elem.getBoundingClientRect();
9486 } else {
9487 // Get *real* offsetParent
9488 offsetParent = this.offsetParent();
9489
9490 // Get correct offsets
9491 offset = this.offset();
9492 if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
9493 parentOffset = offsetParent.offset();
9494 }
9495
9496 // Add offsetParent borders
9497 parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
9498 parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
9499 }
9500
9501 // Subtract parent offsets and element margins
9502 // note: when an element has margin: auto the offsetLeft and marginLeft
9503 // are the same in Safari causing offset.left to incorrectly be 0
9504 return {
9505 top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
9506 left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
9507 };
9508 },
9509
9510 offsetParent: function() {
9511 return this.map(function() {
9512 var offsetParent = this.offsetParent || document.documentElement;
9513 while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
9514 offsetParent = offsetParent.offsetParent;
9515 }
9516 return offsetParent || document.documentElement;
9517 });
9518 }
9519});
9520
9521
9522// Create scrollLeft and scrollTop methods
9523jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
9524 var top = /Y/.test( prop );
9525
9526 jQuery.fn[ method ] = function( val ) {
9527 return jQuery.access( this, function( elem, method, val ) {
9528 var win = getWindow( elem );
9529
9530 if ( val === undefined ) {
9531 return win ? (prop in win) ? win[ prop ] :
9532 win.document.documentElement[ method ] :
9533 elem[ method ];
9534 }
9535
9536 if ( win ) {
9537 win.scrollTo(
9538 !top ? val : jQuery( win ).scrollLeft(),
9539 top ? val : jQuery( win ).scrollTop()
9540 );
9541
9542 } else {
9543 elem[ method ] = val;
9544 }
9545 }, method, val, arguments.length, null );
9546 };
9547});
9548
9549function getWindow( elem ) {
9550 return jQuery.isWindow( elem ) ?
9551 elem :
9552 elem.nodeType === 9 ?
9553 elem.defaultView || elem.parentWindow :
9554 false;
9555}
9556// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
9557jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
9558 jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
9559 // margin is only for outerHeight, outerWidth
9560 jQuery.fn[ funcName ] = function( margin, value ) {
9561 var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
9562 extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
9563
9564 return jQuery.access( this, function( elem, type, value ) {
9565 var doc;
9566
9567 if ( jQuery.isWindow( elem ) ) {
9568 // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
9569 // isn't a whole lot we can do. See pull request at this URL for discussion:
9570 // https://github.com/jquery/jquery/pull/764
9571 return elem.document.documentElement[ "client" + name ];
9572 }
9573
9574 // Get document width or height
9575 if ( elem.nodeType === 9 ) {
9576 doc = elem.documentElement;
9577
9578 // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
9579 // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
9580 return Math.max(
9581 elem.body[ "scroll" + name ], doc[ "scroll" + name ],
9582 elem.body[ "offset" + name ], doc[ "offset" + name ],
9583 doc[ "client" + name ]
9584 );
9585 }
9586
9587 return value === undefined ?
9588 // Get width or height on the element, requesting but not forcing parseFloat
9589 jQuery.css( elem, type, extra ) :
9590
9591 // Set width or height on the element
9592 jQuery.style( elem, type, value, extra );
9593 }, type, chainable ? margin : undefined, chainable, null );
9594 };
9595 });
9596});
9597// Limit scope pollution from any deprecated API
9598// (function() {
9599
9600// })();
9601// Expose jQuery to the global object
9602window.jQuery = window.$ = jQuery;
9603
9604// Expose jQuery as an AMD module, but only for AMD loaders that
9605// understand the issues with loading multiple versions of jQuery
9606// in a page that all might call define(). The loader will indicate
9607// they have special allowances for multiple jQuery versions by
9608// specifying define.amd.jQuery = true. Register as a named module,
9609// since jQuery can be concatenated with other files that may use define,
9610// but not use a proper concatenation script that understands anonymous
9611// AMD modules. A named AMD is safest and most robust way to register.
9612// Lowercase jquery is used because AMD module names are derived from
9613// file names, and jQuery is normally delivered in a lowercase file name.
9614// Do this after creating the global so that if an AMD module wants to call
9615// noConflict to hide this version of jQuery, it will work.
9616if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
9617 define( "jquery", [], function () { return jQuery; } );
9618}
9619
9620})( window );
diff --git a/frontend/gamma/js/JQuery/Mobile/1.3.0-rc.1/jquery.mobile.js b/frontend/gamma/js/JQuery/Mobile/1.3.0-rc.1/jquery.mobile.js
new file mode 100644
index 0000000..9ebe94b
--- a/dev/null
+++ b/frontend/gamma/js/JQuery/Mobile/1.3.0-rc.1/jquery.mobile.js
@@ -0,0 +1,11113 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/*
25* jQuery Mobile Git Build: SHA1: 56a6976b89feddf34e163c3fcc7196ae0a44c1a0 <> Date: Mon Feb 4 08:28:28 2013 -0800
26* http://jquerymobile.com
27*
28* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors
29* Released under the MIT license.
30* http://jquery.org/license
31*
32*/
33
34
35(function ( root, doc, factory ) {
36 if ( typeof define === "function" && define.amd ) {
37 // AMD. Register as an anonymous module.
38 define( [ "jquery" ], function ( $ ) {
39 factory( $, root, doc );
40 return $.mobile;
41 });
42 } else {
43 // Browser globals
44 factory( root.jQuery, root, doc );
45 }
46}( this, document, function ( jQuery, window, document, undefined ) {
47(function( $ ) {
48 $.mobile = {};
49}( jQuery ));
50(function( $, window, undefined ) {
51
52 var nsNormalizeDict = {};
53
54 // jQuery.mobile configurable options
55 $.mobile = $.extend($.mobile, {
56
57 // Version of the jQuery Mobile Framework
58 version: "1.3.0-rc.1",
59
60 // Namespace used framework-wide for data-attrs. Default is no namespace
61 ns: "",
62
63 // Define the url parameter used for referencing widget-generated sub-pages.
64 // Translates to to example.html&ui-page=subpageIdentifier
65 // hash segment before &ui-page= is used to make Ajax request
66 subPageUrlKey: "ui-page",
67
68 // Class assigned to page currently in view, and during transitions
69 activePageClass: "ui-page-active",
70
71 // Class used for "active" button state, from CSS framework
72 activeBtnClass: "ui-btn-active",
73
74 // Class used for "focus" form element state, from CSS framework
75 focusClass: "ui-focus",
76
77 // Automatically handle clicks and form submissions through Ajax, when same-domain
78 ajaxEnabled: true,
79
80 // Automatically load and show pages based on location.hash
81 hashListeningEnabled: true,
82
83 // disable to prevent jquery from bothering with links
84 linkBindingEnabled: true,
85
86 // Set default page transition - 'none' for no transitions
87 defaultPageTransition: "fade",
88
89 // Set maximum window width for transitions to apply - 'false' for no limit
90 maxTransitionWidth: false,
91
92 // Minimum scroll distance that will be remembered when returning to a page
93 minScrollBack: 250,
94
95 // DEPRECATED: the following property is no longer in use, but defined until 2.0 to prevent conflicts
96 touchOverflowEnabled: false,
97
98 // Set default dialog transition - 'none' for no transitions
99 defaultDialogTransition: "pop",
100
101 // Error response message - appears when an Ajax page request fails
102 pageLoadErrorMessage: "Error Loading Page",
103
104 // For error messages, which theme does the box uses?
105 pageLoadErrorMessageTheme: "e",
106
107 // replace calls to window.history.back with phonegaps navigation helper
108 // where it is provided on the window object
109 phonegapNavigationEnabled: false,
110
111 //automatically initialize the DOM when it's ready
112 autoInitializePage: true,
113
114 pushStateEnabled: true,
115
116 // allows users to opt in to ignoring content by marking a parent element as
117 // data-ignored
118 ignoreContentEnabled: false,
119
120 // turn of binding to the native orientationchange due to android orientation behavior
121 orientationChangeEnabled: true,
122
123 buttonMarkup: {
124 hoverDelay: 200
125 },
126
127 // define the window and the document objects
128 window: $( window ),
129 document: $( document ),
130
131 // TODO might be useful upstream in jquery itself ?
132 keyCode: {
133 ALT: 18,
134 BACKSPACE: 8,
135 CAPS_LOCK: 20,
136 COMMA: 188,
137 COMMAND: 91,
138 COMMAND_LEFT: 91, // COMMAND
139 COMMAND_RIGHT: 93,
140 CONTROL: 17,
141 DELETE: 46,
142 DOWN: 40,
143 END: 35,
144 ENTER: 13,
145 ESCAPE: 27,
146 HOME: 36,
147 INSERT: 45,
148 LEFT: 37,
149 MENU: 93, // COMMAND_RIGHT
150 NUMPAD_ADD: 107,
151 NUMPAD_DECIMAL: 110,
152 NUMPAD_DIVIDE: 111,
153 NUMPAD_ENTER: 108,
154 NUMPAD_MULTIPLY: 106,
155 NUMPAD_SUBTRACT: 109,
156 PAGE_DOWN: 34,
157 PAGE_UP: 33,
158 PERIOD: 190,
159 RIGHT: 39,
160 SHIFT: 16,
161 SPACE: 32,
162 TAB: 9,
163 UP: 38,
164 WINDOWS: 91 // COMMAND
165 },
166
167 // Place to store various widget extensions
168 behaviors: {},
169
170 // Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value
171 silentScroll: function( ypos ) {
172 if ( $.type( ypos ) !== "number" ) {
173 ypos = $.mobile.defaultHomeScroll;
174 }
175
176 // prevent scrollstart and scrollstop events
177 $.event.special.scrollstart.enabled = false;
178
179 setTimeout( function() {
180 window.scrollTo( 0, ypos );
181 $.mobile.document.trigger( "silentscroll", { x: 0, y: ypos });
182 }, 20 );
183
184 setTimeout( function() {
185 $.event.special.scrollstart.enabled = true;
186 }, 150 );
187 },
188
189 // Expose our cache for testing purposes.
190 nsNormalizeDict: nsNormalizeDict,
191
192 // Take a data attribute property, prepend the namespace
193 // and then camel case the attribute string. Add the result
194 // to our nsNormalizeDict so we don't have to do this again.
195 nsNormalize: function( prop ) {
196 if ( !prop ) {
197 return;
198 }
199
200 return nsNormalizeDict[ prop ] || ( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) );
201 },
202
203 // Find the closest parent with a theme class on it. Note that
204 // we are not using $.fn.closest() on purpose here because this
205 // method gets called quite a bit and we need it to be as fast
206 // as possible.
207 getInheritedTheme: function( el, defaultTheme ) {
208 var e = el[ 0 ],
209 ltr = "",
210 re = /ui-(bar|body|overlay)-([a-z])\b/,
211 c, m;
212
213 while ( e ) {
214 c = e.className || "";
215 if ( c && ( m = re.exec( c ) ) && ( ltr = m[ 2 ] ) ) {
216 // We found a parent with a theme class
217 // on it so bail from this loop.
218 break;
219 }
220
221 e = e.parentNode;
222 }
223
224 // Return the theme letter we found, if none, return the
225 // specified default.
226
227 return ltr || defaultTheme || "a";
228 },
229
230 // TODO the following $ and $.fn extensions can/probably should be moved into jquery.mobile.core.helpers
231 //
232 // Find the closest javascript page element to gather settings data jsperf test
233 // http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit
234 // possibly naive, but it shows that the parsing overhead for *just* the page selector vs
235 // the page and dialog selector is negligable. This could probably be speed up by
236 // doing a similar parent node traversal to the one found in the inherited theme code above
237 closestPageData: function( $target ) {
238 return $target
239 .closest( ':jqmData(role="page"), :jqmData(role="dialog")' )
240 .data( "mobile-page" );
241 },
242
243 enhanceable: function( $set ) {
244 return this.haveParents( $set, "enhance" );
245 },
246
247 hijackable: function( $set ) {
248 return this.haveParents( $set, "ajax" );
249 },
250
251 haveParents: function( $set, attr ) {
252 if ( !$.mobile.ignoreContentEnabled ) {
253 return $set;
254 }
255
256 var count = $set.length,
257 $newSet = $(),
258 e, $element, excluded;
259
260 for ( var i = 0; i < count; i++ ) {
261 $element = $set.eq( i );
262 excluded = false;
263 e = $set[ i ];
264
265 while ( e ) {
266 var c = e.getAttribute ? e.getAttribute( "data-" + $.mobile.ns + attr ) : "";
267
268 if ( c === "false" ) {
269 excluded = true;
270 break;
271 }
272
273 e = e.parentNode;
274 }
275
276 if ( !excluded ) {
277 $newSet = $newSet.add( $element );
278 }
279 }
280
281 return $newSet;
282 },
283
284 getScreenHeight: function() {
285 // Native innerHeight returns more accurate value for this across platforms,
286 // jQuery version is here as a normalized fallback for platforms like Symbian
287 return window.innerHeight || $.mobile.window.height();
288 }
289 }, $.mobile );
290
291 // Mobile version of data and removeData and hasData methods
292 // ensures all data is set and retrieved using jQuery Mobile's data namespace
293 $.fn.jqmData = function( prop, value ) {
294 var result;
295 if ( typeof prop !== "undefined" ) {
296 if ( prop ) {
297 prop = $.mobile.nsNormalize( prop );
298 }
299
300 // undefined is permitted as an explicit input for the second param
301 // in this case it returns the value and does not set it to undefined
302 if( arguments.length < 2 || value === undefined ){
303 result = this.data( prop );
304 } else {
305 result = this.data( prop, value );
306 }
307 }
308 return result;
309 };
310
311 $.jqmData = function( elem, prop, value ) {
312 var result;
313 if ( typeof prop !== "undefined" ) {
314 result = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value );
315 }
316 return result;
317 };
318
319 $.fn.jqmRemoveData = function( prop ) {
320 return this.removeData( $.mobile.nsNormalize( prop ) );
321 };
322
323 $.jqmRemoveData = function( elem, prop ) {
324 return $.removeData( elem, $.mobile.nsNormalize( prop ) );
325 };
326
327 $.fn.removeWithDependents = function() {
328 $.removeWithDependents( this );
329 };
330
331 $.removeWithDependents = function( elem ) {
332 var $elem = $( elem );
333
334 ( $elem.jqmData( 'dependents' ) || $() ).remove();
335 $elem.remove();
336 };
337
338 $.fn.addDependents = function( newDependents ) {
339 $.addDependents( $( this ), newDependents );
340 };
341
342 $.addDependents = function( elem, newDependents ) {
343 var dependents = $( elem ).jqmData( 'dependents' ) || $();
344
345 $( elem ).jqmData( 'dependents', $.merge( dependents, newDependents ) );
346 };
347
348 // note that this helper doesn't attempt to handle the callback
349 // or setting of an html elements text, its only purpose is
350 // to return the html encoded version of the text in all cases. (thus the name)
351 $.fn.getEncodedText = function() {
352 return $( "<div/>" ).text( $( this ).text() ).html();
353 };
354
355 // fluent helper function for the mobile namespaced equivalent
356 $.fn.jqmEnhanceable = function() {
357 return $.mobile.enhanceable( this );
358 };
359
360 $.fn.jqmHijackable = function() {
361 return $.mobile.hijackable( this );
362 };
363
364 // Monkey-patching Sizzle to filter the :jqmData selector
365 var oldFind = $.find,
366 jqmDataRE = /:jqmData\(([^)]*)\)/g;
367
368 $.find = function( selector, context, ret, extra ) {
369 selector = selector.replace( jqmDataRE, "[data-" + ( $.mobile.ns || "" ) + "$1]" );
370
371 return oldFind.call( this, selector, context, ret, extra );
372 };
373
374 $.extend( $.find, oldFind );
375
376 $.find.matches = function( expr, set ) {
377 return $.find( expr, null, null, set );
378 };
379
380 $.find.matchesSelector = function( node, expr ) {
381 return $.find( expr, null, null, [ node ] ).length > 0;
382 };
383})( jQuery, this );
384
385
386/*!
387 * jQuery UI Widget v1.10.0pre - 2012-11-13 (ff055a0c353c3c8ce6e5bfa07ad7cb03e8885bc5)
388 * http://jqueryui.com
389 *
390 * Copyright 2010, 2013 jQuery Foundation and other contributors
391 * Released under the MIT license.
392 * http://jquery.org/license
393 *
394 * http://api.jqueryui.com/jQuery.widget/
395 */
396(function( $, undefined ) {
397
398var uuid = 0,
399 slice = Array.prototype.slice,
400 _cleanData = $.cleanData;
401$.cleanData = function( elems ) {
402 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
403 try {
404 $( elem ).triggerHandler( "remove" );
405 // http://bugs.jquery.com/ticket/8235
406 } catch( e ) {}
407 }
408 _cleanData( elems );
409};
410
411$.widget = function( name, base, prototype ) {
412 var fullName, existingConstructor, constructor, basePrototype,
413 namespace = name.split( "." )[ 0 ];
414
415 name = name.split( "." )[ 1 ];
416 fullName = namespace + "-" + name;
417
418 if ( !prototype ) {
419 prototype = base;
420 base = $.Widget;
421 }
422
423 // create selector for plugin
424 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
425 return !!$.data( elem, fullName );
426 };
427
428 $[ namespace ] = $[ namespace ] || {};
429 existingConstructor = $[ namespace ][ name ];
430 constructor = $[ namespace ][ name ] = function( options, element ) {
431 // allow instantiation without "new" keyword
432 if ( !this._createWidget ) {
433 return new constructor( options, element );
434 }
435
436 // allow instantiation without initializing for simple inheritance
437 // must use "new" keyword (the code above always passes args)
438 if ( arguments.length ) {
439 this._createWidget( options, element );
440 }
441 };
442 // extend with the existing constructor to carry over any static properties
443 $.extend( constructor, existingConstructor, {
444 version: prototype.version,
445 // copy the object used to create the prototype in case we need to
446 // redefine the widget later
447 _proto: $.extend( {}, prototype ),
448 // track widgets that inherit from this widget in case this widget is
449 // redefined after a widget inherits from it
450 _childConstructors: []
451 });
452
453 basePrototype = new base();
454 // we need to make the options hash a property directly on the new instance
455 // otherwise we'll modify the options hash on the prototype that we're
456 // inheriting from
457 basePrototype.options = $.widget.extend( {}, basePrototype.options );
458 $.each( prototype, function( prop, value ) {
459 if ( $.isFunction( value ) ) {
460 prototype[ prop ] = (function() {
461 var _super = function() {
462 return base.prototype[ prop ].apply( this, arguments );
463 },
464 _superApply = function( args ) {
465 return base.prototype[ prop ].apply( this, args );
466 };
467 return function() {
468 var __super = this._super,
469 __superApply = this._superApply,
470 returnValue;
471
472 this._super = _super;
473 this._superApply = _superApply;
474
475 returnValue = value.apply( this, arguments );
476
477 this._super = __super;
478 this._superApply = __superApply;
479
480 return returnValue;
481 };
482 })();
483 }
484 });
485 constructor.prototype = $.widget.extend( basePrototype, {
486 // TODO: remove support for widgetEventPrefix
487 // always use the name + a colon as the prefix, e.g., draggable:start
488 // don't prefix for widgets that aren't DOM-based
489 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
490 }, prototype, {
491 constructor: constructor,
492 namespace: namespace,
493 widgetName: name,
494 widgetFullName: fullName
495 });
496
497 // If this widget is being redefined then we need to find all widgets that
498 // are inheriting from it and redefine all of them so that they inherit from
499 // the new version of this widget. We're essentially trying to replace one
500 // level in the prototype chain.
501 if ( existingConstructor ) {
502 $.each( existingConstructor._childConstructors, function( i, child ) {
503 var childPrototype = child.prototype;
504
505 // redefine the child widget using the same prototype that was
506 // originally used, but inherit from the new version of the base
507 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
508 });
509 // remove the list of existing child constructors from the old constructor
510 // so the old child constructors can be garbage collected
511 delete existingConstructor._childConstructors;
512 } else {
513 base._childConstructors.push( constructor );
514 }
515
516 $.widget.bridge( name, constructor );
517};
518
519$.widget.extend = function( target ) {
520 var input = slice.call( arguments, 1 ),
521 inputIndex = 0,
522 inputLength = input.length,
523 key,
524 value;
525 for ( ; inputIndex < inputLength; inputIndex++ ) {
526 for ( key in input[ inputIndex ] ) {
527 value = input[ inputIndex ][ key ];
528 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
529 // Clone objects
530 if ( $.isPlainObject( value ) ) {
531 target[ key ] = $.isPlainObject( target[ key ] ) ?
532 $.widget.extend( {}, target[ key ], value ) :
533 // Don't extend strings, arrays, etc. with objects
534 $.widget.extend( {}, value );
535 // Copy everything else by reference
536 } else {
537 target[ key ] = value;
538 }
539 }
540 }
541 }
542 return target;
543};
544
545$.widget.bridge = function( name, object ) {
546 var fullName = object.prototype.widgetFullName || name;
547 $.fn[ name ] = function( options ) {
548 var isMethodCall = typeof options === "string",
549 args = slice.call( arguments, 1 ),
550 returnValue = this;
551
552 // allow multiple hashes to be passed on init
553 options = !isMethodCall && args.length ?
554 $.widget.extend.apply( null, [ options ].concat(args) ) :
555 options;
556
557 if ( isMethodCall ) {
558 this.each(function() {
559 var methodValue,
560 instance = $.data( this, fullName );
561 if ( !instance ) {
562 return $.error( "cannot call methods on " + name + " prior to initialization; " +
563 "attempted to call method '" + options + "'" );
564 }
565 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
566 return $.error( "no such method '" + options + "' for " + name + " widget instance" );
567 }
568 methodValue = instance[ options ].apply( instance, args );
569 if ( methodValue !== instance && methodValue !== undefined ) {
570 returnValue = methodValue && methodValue.jquery ?
571 returnValue.pushStack( methodValue.get() ) :
572 methodValue;
573 return false;
574 }
575 });
576 } else {
577 this.each(function() {
578 var instance = $.data( this, fullName );
579 if ( instance ) {
580 instance.option( options || {} )._init();
581 } else {
582 $.data( this, fullName, new object( options, this ) );
583 }
584 });
585 }
586
587 return returnValue;
588 };
589};
590
591$.Widget = function( /* options, element */ ) {};
592$.Widget._childConstructors = [];
593
594$.Widget.prototype = {
595 widgetName: "widget",
596 widgetEventPrefix: "",
597 defaultElement: "<div>",
598 options: {
599 disabled: false,
600
601 // callbacks
602 create: null
603 },
604 _createWidget: function( options, element ) {
605 element = $( element || this.defaultElement || this )[ 0 ];
606 this.element = $( element );
607 this.uuid = uuid++;
608 this.eventNamespace = "." + this.widgetName + this.uuid;
609 this.options = $.widget.extend( {},
610 this.options,
611 this._getCreateOptions(),
612 options );
613
614 this.bindings = $();
615 this.hoverable = $();
616 this.focusable = $();
617
618 if ( element !== this ) {
619 $.data( element, this.widgetFullName, this );
620 this._on( true, this.element, {
621 remove: function( event ) {
622 if ( event.target === element ) {
623 this.destroy();
624 }
625 }
626 });
627 this.document = $( element.style ?
628 // element within the document
629 element.ownerDocument :
630 // element is window or document
631 element.document || element );
632 this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
633 }
634
635 this._create();
636 this._trigger( "create", null, this._getCreateEventData() );
637 this._init();
638 },
639 _getCreateOptions: $.noop,
640 _getCreateEventData: $.noop,
641 _create: $.noop,
642 _init: $.noop,
643
644 destroy: function() {
645 this._destroy();
646 // we can probably remove the unbind calls in 2.0
647 // all event bindings should go through this._on()
648 this.element
649 .unbind( this.eventNamespace )
650 // 1.9 BC for #7810
651 // TODO remove dual storage
652 .removeData( this.widgetName )
653 .removeData( this.widgetFullName )
654 // support: jquery <1.6.3
655 // http://bugs.jquery.com/ticket/9413
656 .removeData( $.camelCase( this.widgetFullName ) );
657 this.widget()
658 .unbind( this.eventNamespace )
659 .removeAttr( "aria-disabled" )
660 .removeClass(
661 this.widgetFullName + "-disabled " +
662 "ui-state-disabled" );
663
664 // clean up events and states
665 this.bindings.unbind( this.eventNamespace );
666 this.hoverable.removeClass( "ui-state-hover" );
667 this.focusable.removeClass( "ui-state-focus" );
668 },
669 _destroy: $.noop,
670
671 widget: function() {
672 return this.element;
673 },
674
675 option: function( key, value ) {
676 var options = key,
677 parts,
678 curOption,
679 i;
680
681 if ( arguments.length === 0 ) {
682 // don't return a reference to the internal hash
683 return $.widget.extend( {}, this.options );
684 }
685
686 if ( typeof key === "string" ) {
687 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
688 options = {};
689 parts = key.split( "." );
690 key = parts.shift();
691 if ( parts.length ) {
692 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
693 for ( i = 0; i < parts.length - 1; i++ ) {
694 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
695 curOption = curOption[ parts[ i ] ];
696 }
697 key = parts.pop();
698 if ( value === undefined ) {
699 return curOption[ key ] === undefined ? null : curOption[ key ];
700 }
701 curOption[ key ] = value;
702 } else {
703 if ( value === undefined ) {
704 return this.options[ key ] === undefined ? null : this.options[ key ];
705 }
706 options[ key ] = value;
707 }
708 }
709
710 this._setOptions( options );
711
712 return this;
713 },
714 _setOptions: function( options ) {
715 var key;
716
717 for ( key in options ) {
718 this._setOption( key, options[ key ] );
719 }
720
721 return this;
722 },
723 _setOption: function( key, value ) {
724 this.options[ key ] = value;
725
726 if ( key === "disabled" ) {
727 this.widget()
728 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
729 .attr( "aria-disabled", value );
730 this.hoverable.removeClass( "ui-state-hover" );
731 this.focusable.removeClass( "ui-state-focus" );
732 }
733
734 return this;
735 },
736
737 enable: function() {
738 return this._setOption( "disabled", false );
739 },
740 disable: function() {
741 return this._setOption( "disabled", true );
742 },
743
744 _on: function( suppressDisabledCheck, element, handlers ) {
745 var delegateElement,
746 instance = this;
747
748 // no suppressDisabledCheck flag, shuffle arguments
749 if ( typeof suppressDisabledCheck !== "boolean" ) {
750 handlers = element;
751 element = suppressDisabledCheck;
752 suppressDisabledCheck = false;
753 }
754
755 // no element argument, shuffle and use this.element
756 if ( !handlers ) {
757 handlers = element;
758 element = this.element;
759 delegateElement = this.widget();
760 } else {
761 // accept selectors, DOM elements
762 element = delegateElement = $( element );
763 this.bindings = this.bindings.add( element );
764 }
765
766 $.each( handlers, function( event, handler ) {
767 function handlerProxy() {
768 // allow widgets to customize the disabled handling
769 // - disabled as an array instead of boolean
770 // - disabled class as method for disabling individual parts
771 if ( !suppressDisabledCheck &&
772 ( instance.options.disabled === true ||
773 $( this ).hasClass( "ui-state-disabled" ) ) ) {
774 return;
775 }
776 return ( typeof handler === "string" ? instance[ handler ] : handler )
777 .apply( instance, arguments );
778 }
779
780 // copy the guid so direct unbinding works
781 if ( typeof handler !== "string" ) {
782 handlerProxy.guid = handler.guid =
783 handler.guid || handlerProxy.guid || $.guid++;
784 }
785
786 var match = event.match( /^(\w+)\s*(.*)$/ ),
787 eventName = match[1] + instance.eventNamespace,
788 selector = match[2];
789 if ( selector ) {
790 delegateElement.delegate( selector, eventName, handlerProxy );
791 } else {
792 element.bind( eventName, handlerProxy );
793 }
794 });
795 },
796
797 _off: function( element, eventName ) {
798 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
799 element.unbind( eventName ).undelegate( eventName );
800 },
801
802 _delay: function( handler, delay ) {
803 function handlerProxy() {
804 return ( typeof handler === "string" ? instance[ handler ] : handler )
805 .apply( instance, arguments );
806 }
807 var instance = this;
808 return setTimeout( handlerProxy, delay || 0 );
809 },
810
811 _hoverable: function( element ) {
812 this.hoverable = this.hoverable.add( element );
813 this._on( element, {
814 mouseenter: function( event ) {
815 $( event.currentTarget ).addClass( "ui-state-hover" );
816 },
817 mouseleave: function( event ) {
818 $( event.currentTarget ).removeClass( "ui-state-hover" );
819 }
820 });
821 },
822
823 _focusable: function( element ) {
824 this.focusable = this.focusable.add( element );
825 this._on( element, {
826 focusin: function( event ) {
827 $( event.currentTarget ).addClass( "ui-state-focus" );
828 },
829 focusout: function( event ) {
830 $( event.currentTarget ).removeClass( "ui-state-focus" );
831 }
832 });
833 },
834
835 _trigger: function( type, event, data ) {
836 var prop, orig,
837 callback = this.options[ type ];
838
839 data = data || {};
840 event = $.Event( event );
841 event.type = ( type === this.widgetEventPrefix ?
842 type :
843 this.widgetEventPrefix + type ).toLowerCase();
844 // the original event may come from any element
845 // so we need to reset the target on the new event
846 event.target = this.element[ 0 ];
847
848 // copy original event properties over to the new event
849 orig = event.originalEvent;
850 if ( orig ) {
851 for ( prop in orig ) {
852 if ( !( prop in event ) ) {
853 event[ prop ] = orig[ prop ];
854 }
855 }
856 }
857
858 this.element.trigger( event, data );
859 return !( $.isFunction( callback ) &&
860 callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
861 event.isDefaultPrevented() );
862 }
863};
864
865$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
866 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
867 if ( typeof options === "string" ) {
868 options = { effect: options };
869 }
870 var hasOptions,
871 effectName = !options ?
872 method :
873 options === true || typeof options === "number" ?
874 defaultEffect :
875 options.effect || defaultEffect;
876 options = options || {};
877 if ( typeof options === "number" ) {
878 options = { duration: options };
879 }
880 hasOptions = !$.isEmptyObject( options );
881 options.complete = callback;
882 if ( options.delay ) {
883 element.delay( options.delay );
884 }
885 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
886 element[ method ]( options );
887 } else if ( effectName !== method && element[ effectName ] ) {
888 element[ effectName ]( options.duration, options.easing, callback );
889 } else {
890 element.queue(function( next ) {
891 $( this )[ method ]();
892 if ( callback ) {
893 callback.call( element[ 0 ] );
894 }
895 next();
896 });
897 }
898 };
899});
900
901})( jQuery );
902
903(function( $, undefined ) {
904
905$.widget( "mobile.widget", {
906 // decorate the parent _createWidget to trigger `widgetinit` for users
907 // who wish to do post post `widgetcreate` alterations/additions
908 //
909 // TODO create a pull request for jquery ui to trigger this event
910 // in the original _createWidget
911 _createWidget: function() {
912 $.Widget.prototype._createWidget.apply( this, arguments );
913 this._trigger( 'init' );
914 },
915
916 _getCreateOptions: function() {
917
918 var elem = this.element,
919 options = {};
920
921 $.each( this.options, function( option ) {
922
923 var value = elem.jqmData( option.replace( /[A-Z]/g, function( c ) {
924 return "-" + c.toLowerCase();
925 })
926 );
927
928 if ( value !== undefined ) {
929 options[ option ] = value;
930 }
931 });
932
933 return options;
934 },
935
936 enhanceWithin: function( target, useKeepNative ) {
937 this.enhance( $( this.options.initSelector, $( target )), useKeepNative );
938 },
939
940 enhance: function( targets, useKeepNative ) {
941 var page, keepNative, $widgetElements = $( targets ), self = this;
942
943 // if ignoreContentEnabled is set to true the framework should
944 // only enhance the selected elements when they do NOT have a
945 // parent with the data-namespace-ignore attribute
946 $widgetElements = $.mobile.enhanceable( $widgetElements );
947
948 if ( useKeepNative && $widgetElements.length ) {
949 // TODO remove dependency on the page widget for the keepNative.
950 // Currently the keepNative value is defined on the page prototype so
951 // the method is as well
952 page = $.mobile.closestPageData( $widgetElements );
953 keepNative = ( page && page.keepNativeSelector()) || "";
954
955 $widgetElements = $widgetElements.not( keepNative );
956 }
957
958 $widgetElements[ this.widgetName ]();
959 },
960
961 raise: function( msg ) {
962 throw "Widget [" + this.widgetName + "]: " + msg;
963 }
964});
965
966})( jQuery );
967
968
969(function( $, window ) {
970 // DEPRECATED
971 // NOTE global mobile object settings
972 $.extend( $.mobile, {
973 // DEPRECATED Should the text be visble in the loading message?
974 loadingMessageTextVisible: undefined,
975
976 // DEPRECATED When the text is visible, what theme does the loading box use?
977 loadingMessageTheme: undefined,
978
979 // DEPRECATED default message setting
980 loadingMessage: undefined,
981
982 // DEPRECATED
983 // Turn on/off page loading message. Theme doubles as an object argument
984 // with the following shape: { theme: '', text: '', html: '', textVisible: '' }
985 // NOTE that the $.mobile.loading* settings and params past the first are deprecated
986 showPageLoadingMsg: function( theme, msgText, textonly ) {
987 $.mobile.loading( 'show', theme, msgText, textonly );
988 },
989
990 // DEPRECATED
991 hidePageLoadingMsg: function() {
992 $.mobile.loading( 'hide' );
993 },
994
995 loading: function() {
996 this.loaderWidget.loader.apply( this.loaderWidget, arguments );
997 }
998 });
999
1000 // TODO move loader class down into the widget settings
1001 var loaderClass = "ui-loader", $html = $( "html" ), $window = $.mobile.window;
1002
1003 $.widget( "mobile.loader", {
1004 // NOTE if the global config settings are defined they will override these
1005 // options
1006 options: {
1007 // the theme for the loading message
1008 theme: "a",
1009
1010 // whether the text in the loading message is shown
1011 textVisible: false,
1012
1013 // custom html for the inner content of the loading message
1014 html: "",
1015
1016 // the text to be displayed when the popup is shown
1017 text: "loading"
1018 },
1019
1020 defaultHtml: "<div class='" + loaderClass + "'>" +
1021 "<span class='ui-icon ui-icon-loading'></span>" +
1022 "<h1></h1>" +
1023 "</div>",
1024
1025 // For non-fixed supportin browsers. Position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top
1026 fakeFixLoader: function() {
1027 var activeBtn = $( "." + $.mobile.activeBtnClass ).first();
1028
1029 this.element
1030 .css({
1031 top: $.support.scrollTop && $window.scrollTop() + $window.height() / 2 ||
1032 activeBtn.length && activeBtn.offset().top || 100
1033 });
1034 },
1035
1036 // check position of loader to see if it appears to be "fixed" to center
1037 // if not, use abs positioning
1038 checkLoaderPosition: function() {
1039 var offset = this.element.offset(),
1040 scrollTop = $window.scrollTop(),
1041 screenHeight = $.mobile.getScreenHeight();
1042
1043 if ( offset.top < scrollTop || ( offset.top - scrollTop ) > screenHeight ) {
1044 this.element.addClass( "ui-loader-fakefix" );
1045 this.fakeFixLoader();
1046 $window
1047 .unbind( "scroll", this.checkLoaderPosition )
1048 .bind( "scroll", $.proxy( this.fakeFixLoader, this ) );
1049 }
1050 },
1051
1052 resetHtml: function() {
1053 this.element.html( $( this.defaultHtml ).html() );
1054 },
1055
1056 // Turn on/off page loading message. Theme doubles as an object argument
1057 // with the following shape: { theme: '', text: '', html: '', textVisible: '' }
1058 // NOTE that the $.mobile.loading* settings and params past the first are deprecated
1059 // TODO sweet jesus we need to break some of this out
1060 show: function( theme, msgText, textonly ) {
1061 var textVisible, message, $header, loadSettings;
1062
1063 this.resetHtml();
1064
1065 // use the prototype options so that people can set them globally at
1066 // mobile init. Consistency, it's what's for dinner
1067 if ( $.type(theme) === "object" ) {
1068 loadSettings = $.extend( {}, this.options, theme );
1069
1070 // prefer object property from the param then the old theme setting
1071 theme = loadSettings.theme || $.mobile.loadingMessageTheme;
1072 } else {
1073 loadSettings = this.options;
1074
1075 // here we prefer the them value passed as a string argument, then
1076 // we prefer the global option because we can't use undefined default
1077 // prototype options, then the prototype option
1078 theme = theme || $.mobile.loadingMessageTheme || loadSettings.theme;
1079 }
1080
1081 // set the message text, prefer the param, then the settings object
1082 // then loading message
1083 message = msgText || $.mobile.loadingMessage || loadSettings.text;
1084
1085 // prepare the dom
1086 $html.addClass( "ui-loading" );
1087
1088 if ( $.mobile.loadingMessage !== false || loadSettings.html ) {
1089 // boolean values require a bit more work :P, supports object properties
1090 // and old settings
1091 if ( $.mobile.loadingMessageTextVisible !== undefined ) {
1092 textVisible = $.mobile.loadingMessageTextVisible;
1093 } else {
1094 textVisible = loadSettings.textVisible;
1095 }
1096
1097 // add the proper css given the options (theme, text, etc)
1098 // Force text visibility if the second argument was supplied, or
1099 // if the text was explicitly set in the object args
1100 this.element.attr("class", loaderClass +
1101 " ui-corner-all ui-body-" + theme +
1102 " ui-loader-" + ( textVisible || msgText || theme.text ? "verbose" : "default" ) +
1103 ( loadSettings.textonly || textonly ? " ui-loader-textonly" : "" ) );
1104
1105 // TODO verify that jquery.fn.html is ok to use in both cases here
1106 // this might be overly defensive in preventing unknowing xss
1107 // if the html attribute is defined on the loading settings, use that
1108 // otherwise use the fallbacks from above
1109 if ( loadSettings.html ) {
1110 this.element.html( loadSettings.html );
1111 } else {
1112 this.element.find( "h1" ).text( message );
1113 }
1114
1115 // attach the loader to the DOM
1116 this.element.appendTo( $.mobile.pageContainer );
1117
1118 // check that the loader is visible
1119 this.checkLoaderPosition();
1120
1121 // on scroll check the loader position
1122 $window.bind( "scroll", $.proxy( this.checkLoaderPosition, this ) );
1123 }
1124 },
1125
1126 hide: function() {
1127 $html.removeClass( "ui-loading" );
1128
1129 if ( $.mobile.loadingMessage ) {
1130 this.element.removeClass( "ui-loader-fakefix" );
1131 }
1132
1133 $.mobile.window.unbind( "scroll", this.fakeFixLoader );
1134 $.mobile.window.unbind( "scroll", this.checkLoaderPosition );
1135 }
1136 });
1137
1138 $window.bind( 'pagecontainercreate', function() {
1139 $.mobile.loaderWidget = $.mobile.loaderWidget || $( $.mobile.loader.prototype.defaultHtml ).loader();
1140 });
1141})(jQuery, this);
1142
1143
1144(function( $, undefined ) {
1145
1146 /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
1147 window.matchMedia = window.matchMedia || (function( doc, undefined ) {
1148
1149
1150
1151 var bool,
1152 docElem = doc.documentElement,
1153 refNode = docElem.firstElementChild || docElem.firstChild,
1154 // fakeBody required for <FF4 when executed in <head>
1155 fakeBody = doc.createElement( "body" ),
1156 div = doc.createElement( "div" );
1157
1158 div.id = "mq-test-1";
1159 div.style.cssText = "position:absolute;top:-100em";
1160 fakeBody.style.background = "none";
1161 fakeBody.appendChild(div);
1162
1163 return function(q){
1164
1165 div.innerHTML = "&shy;<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>";
1166
1167 docElem.insertBefore( fakeBody, refNode );
1168 bool = div.offsetWidth === 42;
1169 docElem.removeChild( fakeBody );
1170
1171 return {
1172 matches: bool,
1173 media: q
1174 };
1175
1176 };
1177
1178 }( document ));
1179
1180 // $.mobile.media uses matchMedia to return a boolean.
1181 $.mobile.media = function( q ) {
1182 return window.matchMedia( q ).matches;
1183 };
1184
1185})(jQuery);
1186
1187 (function( $, undefined ) {
1188 var support = {
1189 touch: "ontouchend" in document
1190 };
1191
1192 $.mobile.support = $.mobile.support || {};
1193 $.extend( $.support, support );
1194 $.extend( $.mobile.support, support );
1195 }( jQuery ));
1196
1197 (function( $, undefined ) {
1198 $.extend( $.support, {
1199 orientation: "orientation" in window && "onorientationchange" in window
1200 });
1201 }( jQuery ));
1202
1203(function( $, undefined ) {
1204
1205// thx Modernizr
1206function propExists( prop ) {
1207 var uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),
1208 props = ( prop + " " + vendors.join( uc_prop + " " ) + uc_prop ).split( " " );
1209
1210 for ( var v in props ) {
1211 if ( fbCSS[ props[ v ] ] !== undefined ) {
1212 return true;
1213 }
1214 }
1215}
1216
1217var fakeBody = $( "<body>" ).prependTo( "html" ),
1218 fbCSS = fakeBody[ 0 ].style,
1219 vendors = [ "Webkit", "Moz", "O" ],
1220 webos = "palmGetResource" in window, //only used to rule out scrollTop
1221 opera = window.opera,
1222 operamini = window.operamini && ({}).toString.call( window.operamini ) === "[object OperaMini]",
1223 bb = window.blackberry && !propExists( "-webkit-transform" ); //only used to rule out box shadow, as it's filled opaque on BB 5 and lower
1224
1225
1226function validStyle( prop, value, check_vend ) {
1227 var div = document.createElement( 'div' ),
1228 uc = function( txt ) {
1229 return txt.charAt( 0 ).toUpperCase() + txt.substr( 1 );
1230 },
1231 vend_pref = function( vend ) {
1232 if( vend === "" ) {
1233 return "";
1234 } else {
1235 return "-" + vend.charAt( 0 ).toLowerCase() + vend.substr( 1 ) + "-";
1236 }
1237 },
1238 check_style = function( vend ) {
1239 var vend_prop = vend_pref( vend ) + prop + ": " + value + ";",
1240 uc_vend = uc( vend ),
1241 propStyle = uc_vend + ( uc_vend === "" ? prop : uc( prop ) );
1242
1243 div.setAttribute( "style", vend_prop );
1244
1245 if ( !!div.style[ propStyle ] ) {
1246 ret = true;
1247 }
1248 },
1249 check_vends = check_vend ? check_vend : vendors,
1250 ret;
1251
1252 for( var i = 0; i < check_vends.length; i++ ) {
1253 check_style( check_vends[i] );
1254 }
1255 return !!ret;
1256}
1257
1258function transform3dTest() {
1259 var mqProp = "transform-3d",
1260 // Because the `translate3d` test below throws false positives in Android:
1261 ret = $.mobile.media( "(-" + vendors.join( "-" + mqProp + "),(-" ) + "-" + mqProp + "),(" + mqProp + ")" );
1262
1263 if( ret ) {
1264 return !!ret;
1265 }
1266
1267 var el = document.createElement( "div" ),
1268 transforms = {
1269 // We’re omitting Opera for the time being; MS uses unprefixed.
1270 'MozTransform':'-moz-transform',
1271 'transform':'transform'
1272 };
1273
1274 fakeBody.append( el );
1275
1276 for ( var t in transforms ) {
1277 if( el.style[ t ] !== undefined ){
1278 el.style[ t ] = 'translate3d( 100px, 1px, 1px )';
1279 ret = window.getComputedStyle( el ).getPropertyValue( transforms[ t ] );
1280 }
1281 }
1282 return ( !!ret && ret !== "none" );
1283}
1284
1285// Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting )
1286function baseTagTest() {
1287 var fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/",
1288 base = $( "head base" ),
1289 fauxEle = null,
1290 href = "",
1291 link, rebase;
1292
1293 if ( !base.length ) {
1294 base = fauxEle = $( "<base>", { "href": fauxBase }).appendTo( "head" );
1295 } else {
1296 href = base.attr( "href" );
1297 }
1298
1299 link = $( "<a href='testurl' />" ).prependTo( fakeBody );
1300 rebase = link[ 0 ].href;
1301 base[ 0 ].href = href || location.pathname;
1302
1303 if ( fauxEle ) {
1304 fauxEle.remove();
1305 }
1306 return rebase.indexOf( fauxBase ) === 0;
1307}
1308
1309// Thanks Modernizr
1310function cssPointerEventsTest() {
1311 var element = document.createElement( 'x' ),
1312 documentElement = document.documentElement,
1313 getComputedStyle = window.getComputedStyle,
1314 supports;
1315
1316 if ( !( 'pointerEvents' in element.style ) ) {
1317 return false;
1318 }
1319
1320 element.style.pointerEvents = 'auto';
1321 element.style.pointerEvents = 'x';
1322 documentElement.appendChild( element );
1323 supports = getComputedStyle &&
1324 getComputedStyle( element, '' ).pointerEvents === 'auto';
1325 documentElement.removeChild( element );
1326 return !!supports;
1327}
1328
1329function boundingRect() {
1330 var div = document.createElement( "div" );
1331 return typeof div.getBoundingClientRect !== "undefined";
1332}
1333
1334// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683
1335// allows for inclusion of IE 6+, including Windows Mobile 7
1336$.extend( $.mobile, { browser: {} } );
1337$.mobile.browser.oldIE = (function() {
1338 var v = 3,
1339 div = document.createElement( "div" ),
1340 a = div.all || [];
1341
1342 do {
1343 div.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->";
1344 } while( a[0] );
1345
1346 return v > 4 ? v : !v;
1347})();
1348
1349function fixedPosition() {
1350 var w = window,
1351 ua = navigator.userAgent,
1352 platform = navigator.platform,
1353 // Rendering engine is Webkit, and capture major version
1354 wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ),
1355 wkversion = !!wkmatch && wkmatch[ 1 ],
1356 ffmatch = ua.match( /Fennec\/([0-9]+)/ ),
1357 ffversion = !!ffmatch && ffmatch[ 1 ],
1358 operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ ),
1359 omversion = !!operammobilematch && operammobilematch[ 1 ];
1360
1361 if(
1362 // iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
1363 ( ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1 || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534 ) ||
1364 // Opera Mini
1365 ( w.operamini && ({}).toString.call( w.operamini ) === "[object OperaMini]" ) ||
1366 ( operammobilematch && omversion < 7458 )||
1367 //Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
1368 ( ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533 ) ||
1369 // Firefox Mobile before 6.0 -
1370 ( ffversion && ffversion < 6 ) ||
1371 // WebOS less than 3
1372 ( "palmGetResource" in window && wkversion && wkversion < 534 )||
1373 // MeeGo
1374 ( ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1 ) ) {
1375 return false;
1376 }
1377
1378 return true;
1379}
1380
1381$.extend( $.support, {
1382 cssTransitions: "WebKitTransitionEvent" in window ||
1383 validStyle( 'transition', 'height 100ms linear', [ "Webkit", "Moz", "" ] ) &&
1384 !$.mobile.browser.oldIE && !opera,
1385
1386 // Note, Chrome for iOS has an extremely quirky implementation of popstate.
1387 // We've chosen to take the shortest path to a bug fix here for issue #5426
1388 // See the following link for information about the regex chosen
1389 // https://developers.google.com/chrome/mobile/docs/user-agent#chrome_for_ios_user-agent
1390 pushState: "pushState" in history &&
1391 "replaceState" in history &&
1392 ( window.navigator.userAgent.search(/CriOS/) === -1 ),
1393
1394 mediaquery: $.mobile.media( "only all" ),
1395 cssPseudoElement: !!propExists( "content" ),
1396 touchOverflow: !!propExists( "overflowScrolling" ),
1397 cssTransform3d: transform3dTest(),
1398 boxShadow: !!propExists( "boxShadow" ) && !bb,
1399 fixedPosition: fixedPosition(),
1400 scrollTop: ("pageXOffset" in window ||
1401 "scrollTop" in document.documentElement ||
1402 "scrollTop" in fakeBody[ 0 ]) && !webos && !operamini,
1403
1404 dynamicBaseTag: baseTagTest(),
1405 cssPointerEvents: cssPointerEventsTest(),
1406 boundingRect: boundingRect()
1407});
1408
1409fakeBody.remove();
1410
1411
1412// $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian)
1413// or that generally work better browsing in regular http for full page refreshes (Opera Mini)
1414// Note: This detection below is used as a last resort.
1415// We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible
1416var nokiaLTE7_3 = (function() {
1417
1418 var ua = window.navigator.userAgent;
1419
1420 //The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older
1421 return ua.indexOf( "Nokia" ) > -1 &&
1422 ( ua.indexOf( "Symbian/3" ) > -1 || ua.indexOf( "Series60/5" ) > -1 ) &&
1423 ua.indexOf( "AppleWebKit" ) > -1 &&
1424 ua.match( /(BrowserNG|NokiaBrowser)\/7\.[0-3]/ );
1425})();
1426
1427// Support conditions that must be met in order to proceed
1428// default enhanced qualifications are media query support OR IE 7+
1429
1430$.mobile.gradeA = function() {
1431 return ( $.support.mediaquery || $.mobile.browser.oldIE && $.mobile.browser.oldIE >= 7 ) && ( $.support.boundingRect || $.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/) !== null );
1432};
1433
1434$.mobile.ajaxBlacklist =
1435 // BlackBerry browsers, pre-webkit
1436 window.blackberry && !window.WebKitPoint ||
1437 // Opera Mini
1438 operamini ||
1439 // Symbian webkits pre 7.3
1440 nokiaLTE7_3;
1441
1442// Lastly, this workaround is the only way we've found so far to get pre 7.3 Symbian webkit devices
1443// to render the stylesheets when they're referenced before this script, as we'd recommend doing.
1444// This simply reappends the CSS in place, which for some reason makes it apply
1445if ( nokiaLTE7_3 ) {
1446 $(function() {
1447 $( "head link[rel='stylesheet']" ).attr( "rel", "alternate stylesheet" ).attr( "rel", "stylesheet" );
1448 });
1449}
1450
1451// For ruling out shadows via css
1452if ( !$.support.boxShadow ) {
1453 $( "html" ).addClass( "ui-mobile-nosupport-boxshadow" );
1454}
1455
1456})( jQuery );
1457
1458
1459(function( $, undefined ) {
1460 var $win = $.mobile.window, self, history;
1461
1462 $.event.special.navigate = self = {
1463 bound: false,
1464
1465 pushStateEnabled: true,
1466
1467 originalEventName: undefined,
1468
1469 // If pushstate support is present and push state support is defined to
1470 // be true on the mobile namespace.
1471 isPushStateEnabled: function() {
1472 return $.support.pushState &&
1473 $.mobile.pushStateEnabled === true &&
1474 this.isHashChangeEnabled();
1475 },
1476
1477 // !! assumes mobile namespace is present
1478 isHashChangeEnabled: function() {
1479 return $.mobile.hashListeningEnabled === true;
1480 },
1481
1482 // TODO a lot of duplication between popstate and hashchange
1483 popstate: function( event ) {
1484 var newEvent = new $.Event( "navigate" ),
1485 beforeNavigate = new $.Event( "beforenavigate" ),
1486 state = event.originalEvent.state || {},
1487 href = location.href;
1488
1489 $win.trigger( beforeNavigate );
1490
1491 if( beforeNavigate.isDefaultPrevented() ){
1492 return;
1493 }
1494
1495 if( event.historyState ){
1496 $.extend(state, event.historyState);
1497 }
1498
1499 // Make sure the original event is tracked for the end
1500 // user to inspect incase they want to do something special
1501 newEvent.originalEvent = event;
1502
1503 // NOTE we let the current stack unwind because any assignment to
1504 // location.hash will stop the world and run this event handler. By
1505 // doing this we create a similar behavior to hashchange on hash
1506 // assignment
1507 setTimeout(function() {
1508 $win.trigger( newEvent, {
1509 state: state
1510 });
1511 }, 0);
1512 },
1513
1514 hashchange: function( event, data ) {
1515 var newEvent = new $.Event( "navigate" ),
1516 beforeNavigate = new $.Event( "beforenavigate" );
1517
1518 $win.trigger( beforeNavigate );
1519
1520 if( beforeNavigate.isDefaultPrevented() ){
1521 return;
1522 }
1523
1524 // Make sure the original event is tracked for the end
1525 // user to inspect incase they want to do something special
1526 newEvent.originalEvent = event;
1527
1528 // Trigger the hashchange with state provided by the user
1529 // that altered the hash
1530 $win.trigger( newEvent, {
1531 // Users that want to fully normalize the two events
1532 // will need to do history management down the stack and
1533 // add the state to the event before this binding is fired
1534 // TODO consider allowing for the explicit addition of callbacks
1535 // to be fired before this value is set to avoid event timing issues
1536 state: event.hashchangeState || {}
1537 });
1538 },
1539
1540 // TODO We really only want to set this up once
1541 // but I'm not clear if there's a beter way to achieve
1542 // this with the jQuery special event structure
1543 setup: function( data, namespaces ) {
1544 if( self.bound ) {
1545 return;
1546 }
1547
1548 self.bound = true;
1549
1550 if( self.isPushStateEnabled() ) {
1551 self.originalEventName = "popstate";
1552 $win.bind( "popstate.navigate", self.popstate );
1553 } else if ( self.isHashChangeEnabled() ){
1554 self.originalEventName = "hashchange";
1555 $win.bind( "hashchange.navigate", self.hashchange );
1556 }
1557 }
1558 };
1559})( jQuery );
1560
1561
1562
1563(function( $, undefined ) {
1564 var path, documentBase, $base, dialogHashKey = "&ui-state=dialog";
1565
1566 $.mobile.path = path = {
1567 uiStateKey: "&ui-state",
1568
1569 // This scary looking regular expression parses an absolute URL or its relative
1570 // variants (protocol, site, document, query, and hash), into the various
1571 // components (protocol, host, path, query, fragment, etc that make up the
1572 // URL as well as some other commonly used sub-parts. When used with RegExp.exec()
1573 // or String.match, it parses the URL into a results array that looks like this:
1574 //
1575 // [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content
1576 // [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread
1577 // [2]: http://jblas:password@mycompany.com:8080/mail/inbox
1578 // [3]: http://jblas:password@mycompany.com:8080
1579 // [4]: http:
1580 // [5]: //
1581 // [6]: jblas:password@mycompany.com:8080
1582 // [7]: jblas:password
1583 // [8]: jblas
1584 // [9]: password
1585 // [10]: mycompany.com:8080
1586 // [11]: mycompany.com
1587 // [12]: 8080
1588 // [13]: /mail/inbox
1589 // [14]: /mail/
1590 // [15]: inbox
1591 // [16]: ?msg=1234&type=unread
1592 // [17]: #msg-content
1593 //
1594 urlParseRE: /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
1595
1596 // Abstraction to address xss (Issue #4787) by removing the authority in
1597 // browsers that autodecode it. All references to location.href should be
1598 // replaced with a call to this method so that it can be dealt with properly here
1599 getLocation: function( url ) {
1600 var uri = url ? this.parseUrl( url ) : location,
1601 hash = this.parseUrl( url || location.href ).hash;
1602
1603 // mimic the browser with an empty string when the hash is empty
1604 hash = hash === "#" ? "" : hash;
1605
1606 // Make sure to parse the url or the location object for the hash because using location.hash
1607 // is autodecoded in firefox, the rest of the url should be from the object (location unless
1608 // we're testing) to avoid the inclusion of the authority
1609 return uri.protocol + "//" + uri.host + uri.pathname + uri.search + hash;
1610 },
1611
1612 parseLocation: function() {
1613 return this.parseUrl( this.getLocation() );
1614 },
1615
1616 //Parse a URL into a structure that allows easy access to
1617 //all of the URL components by name.
1618 parseUrl: function( url ) {
1619 // If we're passed an object, we'll assume that it is
1620 // a parsed url object and just return it back to the caller.
1621 if ( $.type( url ) === "object" ) {
1622 return url;
1623 }
1624
1625 var matches = path.urlParseRE.exec( url || "" ) || [];
1626
1627 // Create an object that allows the caller to access the sub-matches
1628 // by name. Note that IE returns an empty string instead of undefined,
1629 // like all other browsers do, so we normalize everything so its consistent
1630 // no matter what browser we're running on.
1631 return {
1632 href: matches[ 0 ] || "",
1633 hrefNoHash: matches[ 1 ] || "",
1634 hrefNoSearch: matches[ 2 ] || "",
1635 domain: matches[ 3 ] || "",
1636 protocol: matches[ 4 ] || "",
1637 doubleSlash: matches[ 5 ] || "",
1638 authority: matches[ 6 ] || "",
1639 username: matches[ 8 ] || "",
1640 password: matches[ 9 ] || "",
1641 host: matches[ 10 ] || "",
1642 hostname: matches[ 11 ] || "",
1643 port: matches[ 12 ] || "",
1644 pathname: matches[ 13 ] || "",
1645 directory: matches[ 14 ] || "",
1646 filename: matches[ 15 ] || "",
1647 search: matches[ 16 ] || "",
1648 hash: matches[ 17 ] || ""
1649 };
1650 },
1651
1652 //Turn relPath into an asbolute path. absPath is
1653 //an optional absolute path which describes what
1654 //relPath is relative to.
1655 makePathAbsolute: function( relPath, absPath ) {
1656 if ( relPath && relPath.charAt( 0 ) === "/" ) {
1657 return relPath;
1658 }
1659
1660 relPath = relPath || "";
1661 absPath = absPath ? absPath.replace( /^\/|(\/[^\/]*|[^\/]+)$/g, "" ) : "";
1662
1663 var absStack = absPath ? absPath.split( "/" ) : [],
1664 relStack = relPath.split( "/" );
1665 for ( var i = 0; i < relStack.length; i++ ) {
1666 var d = relStack[ i ];
1667 switch ( d ) {
1668 case ".":
1669 break;
1670 case "..":
1671 if ( absStack.length ) {
1672 absStack.pop();
1673 }
1674 break;
1675 default:
1676 absStack.push( d );
1677 break;
1678 }
1679 }
1680 return "/" + absStack.join( "/" );
1681 },
1682
1683 //Returns true if both urls have the same domain.
1684 isSameDomain: function( absUrl1, absUrl2 ) {
1685 return path.parseUrl( absUrl1 ).domain === path.parseUrl( absUrl2 ).domain;
1686 },
1687
1688 //Returns true for any relative variant.
1689 isRelativeUrl: function( url ) {
1690 // All relative Url variants have one thing in common, no protocol.
1691 return path.parseUrl( url ).protocol === "";
1692 },
1693
1694 //Returns true for an absolute url.
1695 isAbsoluteUrl: function( url ) {
1696 return path.parseUrl( url ).protocol !== "";
1697 },
1698
1699 //Turn the specified realtive URL into an absolute one. This function
1700 //can handle all relative variants (protocol, site, document, query, fragment).
1701 makeUrlAbsolute: function( relUrl, absUrl ) {
1702 if ( !path.isRelativeUrl( relUrl ) ) {
1703 return relUrl;
1704 }
1705
1706 if ( absUrl === undefined ) {
1707 absUrl = this.documentBase;
1708 }
1709
1710 var relObj = path.parseUrl( relUrl ),
1711 absObj = path.parseUrl( absUrl ),
1712 protocol = relObj.protocol || absObj.protocol,
1713 doubleSlash = relObj.protocol ? relObj.doubleSlash : ( relObj.doubleSlash || absObj.doubleSlash ),
1714 authority = relObj.authority || absObj.authority,
1715 hasPath = relObj.pathname !== "",
1716 pathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ),
1717 search = relObj.search || ( !hasPath && absObj.search ) || "",
1718 hash = relObj.hash;
1719
1720 return protocol + doubleSlash + authority + pathname + search + hash;
1721 },
1722
1723 //Add search (aka query) params to the specified url.
1724 addSearchParams: function( url, params ) {
1725 var u = path.parseUrl( url ),
1726 p = ( typeof params === "object" ) ? $.param( params ) : params,
1727 s = u.search || "?";
1728 return u.hrefNoSearch + s + ( s.charAt( s.length - 1 ) !== "?" ? "&" : "" ) + p + ( u.hash || "" );
1729 },
1730
1731 convertUrlToDataUrl: function( absUrl ) {
1732 var u = path.parseUrl( absUrl );
1733 if ( path.isEmbeddedPage( u ) ) {
1734 // For embedded pages, remove the dialog hash key as in getFilePath(),
1735 // and remove otherwise the Data Url won't match the id of the embedded Page.
1736 return u.hash
1737 .split( dialogHashKey )[0]
1738 .replace( /^#/, "" )
1739 .replace( /\?.*$/, "" );
1740 } else if ( path.isSameDomain( u, this.documentBase ) ) {
1741 return u.hrefNoHash.replace( this.documentBase.domain, "" ).split( dialogHashKey )[0];
1742 }
1743
1744 return window.decodeURIComponent(absUrl);
1745 },
1746
1747 //get path from current hash, or from a file path
1748 get: function( newPath ) {
1749 if ( newPath === undefined ) {
1750 newPath = path.parseLocation().hash;
1751 }
1752 return path.stripHash( newPath ).replace( /[^\/]*\.[^\/*]+$/, '' );
1753 },
1754
1755 //set location hash to path
1756 set: function( path ) {
1757 location.hash = path;
1758 },
1759
1760 //test if a given url (string) is a path
1761 //NOTE might be exceptionally naive
1762 isPath: function( url ) {
1763 return ( /\// ).test( url );
1764 },
1765
1766 //return a url path with the window's location protocol/hostname/pathname removed
1767 clean: function( url ) {
1768 return url.replace( this.documentBase.domain, "" );
1769 },
1770
1771 //just return the url without an initial #
1772 stripHash: function( url ) {
1773 return url.replace( /^#/, "" );
1774 },
1775
1776 stripQueryParams: function( url ) {
1777 return url.replace( /\?.*$/, "" );
1778 },
1779
1780 //remove the preceding hash, any query params, and dialog notations
1781 cleanHash: function( hash ) {
1782 return path.stripHash( hash.replace( /\?.*$/, "" ).replace( dialogHashKey, "" ) );
1783 },
1784
1785 isHashValid: function( hash ) {
1786 return ( /^#[^#]+$/ ).test( hash );
1787 },
1788
1789 //check whether a url is referencing the same domain, or an external domain or different protocol
1790 //could be mailto, etc
1791 isExternal: function( url ) {
1792 var u = path.parseUrl( url );
1793 return u.protocol && u.domain !== this.documentUrl.domain ? true : false;
1794 },
1795
1796 hasProtocol: function( url ) {
1797 return ( /^(:?\w+:)/ ).test( url );
1798 },
1799
1800 isEmbeddedPage: function( url ) {
1801 var u = path.parseUrl( url );
1802
1803 //if the path is absolute, then we need to compare the url against
1804 //both the this.documentUrl and the documentBase. The main reason for this
1805 //is that links embedded within external documents will refer to the
1806 //application document, whereas links embedded within the application
1807 //document will be resolved against the document base.
1808 if ( u.protocol !== "" ) {
1809 return ( !this.isPath(u.hash) && u.hash && ( u.hrefNoHash === this.documentUrl.hrefNoHash || ( this.documentBaseDiffers && u.hrefNoHash === this.documentBase.hrefNoHash ) ) );
1810 }
1811 return ( /^#/ ).test( u.href );
1812 },
1813
1814 squash: function( url, resolutionUrl ) {
1815 var state, href, cleanedUrl, search, stateIndex,
1816 isPath = this.isPath( url ),
1817 uri = this.parseUrl( url ),
1818 preservedHash = uri.hash,
1819 uiState = "";
1820
1821 // produce a url against which we can resole the provided path
1822 resolutionUrl = resolutionUrl || (path.isPath(url) ? path.getLocation() : path.getDocumentUrl());
1823
1824 // If the url is anything but a simple string, remove any preceding hash
1825 // eg #foo/bar -> foo/bar
1826 // #foo -> #foo
1827 cleanedUrl = isPath ? path.stripHash( url ) : url;
1828
1829 // If the url is a full url with a hash check if the parsed hash is a path
1830 // if it is, strip the #, and use it otherwise continue without change
1831 cleanedUrl = path.isPath( uri.hash ) ? path.stripHash( uri.hash ) : cleanedUrl;
1832
1833 // Split the UI State keys off the href
1834 stateIndex = cleanedUrl.indexOf( this.uiStateKey );
1835
1836 // store the ui state keys for use
1837 if( stateIndex > -1 ){
1838 uiState = cleanedUrl.slice( stateIndex );
1839 cleanedUrl = cleanedUrl.slice( 0, stateIndex );
1840 }
1841
1842 // make the cleanedUrl absolute relative to the resolution url
1843 href = path.makeUrlAbsolute( cleanedUrl, resolutionUrl );
1844
1845 // grab the search from the resolved url since parsing from
1846 // the passed url may not yield the correct result
1847 search = this.parseUrl( href ).search;
1848
1849 // TODO all this crap is terrible, clean it up
1850 if ( isPath ) {
1851 // reject the hash if it's a path or it's just a dialog key
1852 if( path.isPath( preservedHash ) || preservedHash.replace("#", "").indexOf( this.uiStateKey ) === 0) {
1853 preservedHash = "";
1854 }
1855
1856 // Append the UI State keys where it exists and it's been removed
1857 // from the url
1858 if( uiState && preservedHash.indexOf( this.uiStateKey ) === -1){
1859 preservedHash += uiState;
1860 }
1861
1862 // make sure that pound is on the front of the hash
1863 if( preservedHash.indexOf( "#" ) === -1 && preservedHash !== "" ){
1864 preservedHash = "#" + preservedHash;
1865 }
1866
1867 // reconstruct each of the pieces with the new search string and hash
1868 href = path.parseUrl( href );
1869 href = href.protocol + "//" + href.host + href.pathname + search + preservedHash;
1870 } else {
1871 href += href.indexOf( "#" ) > -1 ? uiState : "#" + uiState;
1872 }
1873
1874 return href;
1875 },
1876
1877 isPreservableHash: function( hash ) {
1878 return hash.replace( "#", "" ).indexOf( this.uiStateKey ) === 0;
1879 }
1880 };
1881
1882 path.documentUrl = path.parseLocation();
1883
1884 $base = $( "head" ).find( "base" );
1885
1886 path.documentBase = $base.length ?
1887 path.parseUrl( path.makeUrlAbsolute( $base.attr( "href" ), path.documentUrl.href ) ) :
1888 path.documentUrl;
1889
1890 path.documentBaseDiffers = (path.documentUrl.hrefNoHash !== path.documentBase.hrefNoHash);
1891
1892 //return the original document url
1893 path.getDocumentUrl = function( asParsedObject ) {
1894 return asParsedObject ? $.extend( {}, path.documentUrl ) : path.documentUrl.href;
1895 };
1896
1897 //return the original document base url
1898 path.getDocumentBase = function( asParsedObject ) {
1899 return asParsedObject ? $.extend( {}, path.documentBase ) : path.documentBase.href;
1900 };
1901})( jQuery );
1902
1903
1904
1905(function( $, undefined ) {
1906 var path = $.mobile.path;
1907
1908 $.mobile.History = function( stack, index ) {
1909 this.stack = stack || [];
1910 this.activeIndex = index || 0;
1911 };
1912
1913 $.extend($.mobile.History.prototype, {
1914 getActive: function() {
1915 return this.stack[ this.activeIndex ];
1916 },
1917
1918 getLast: function() {
1919 return this.stack[ this.previousIndex ];
1920 },
1921
1922 getNext: function() {
1923 return this.stack[ this.activeIndex + 1 ];
1924 },
1925
1926 getPrev: function() {
1927 return this.stack[ this.activeIndex - 1 ];
1928 },
1929
1930 // addNew is used whenever a new page is added
1931 add: function( url, data ){
1932 data = data || {};
1933
1934 //if there's forward history, wipe it
1935 if ( this.getNext() ) {
1936 this.clearForward();
1937 }
1938
1939 // if the hash is included in the data make sure the shape
1940 // is consistent for comparison
1941 if( data.hash && data.hash.indexOf( "#" ) === -1) {
1942 data.hash = "#" + data.hash;
1943 }
1944
1945 data.url = url;
1946 this.stack.push( data );
1947 this.activeIndex = this.stack.length - 1;
1948 },
1949
1950 //wipe urls ahead of active index
1951 clearForward: function() {
1952 this.stack = this.stack.slice( 0, this.activeIndex + 1 );
1953 },
1954
1955 find: function( url, stack, earlyReturn ) {
1956 stack = stack || this.stack;
1957
1958 var entry, i, length = stack.length, index;
1959
1960 for ( i = 0; i < length; i++ ) {
1961 entry = stack[i];
1962
1963 if ( decodeURIComponent(url) === decodeURIComponent(entry.url) ||
1964 decodeURIComponent(url) === decodeURIComponent(entry.hash) ) {
1965 index = i;
1966
1967 if( earlyReturn ) {
1968 return index;
1969 }
1970 }
1971 }
1972
1973 return index;
1974 },
1975
1976 closest: function( url ) {
1977 var closest, a = this.activeIndex;
1978
1979 // First, take the slice of the history stack before the current index and search
1980 // for a url match. If one is found, we'll avoid avoid looking through forward history
1981 // NOTE the preference for backward history movement is driven by the fact that
1982 // most mobile browsers only have a dedicated back button, and users rarely use
1983 // the forward button in desktop browser anyhow
1984 closest = this.find( url, this.stack.slice(0, a) );
1985
1986 // If nothing was found in backward history check forward. The `true`
1987 // value passed as the third parameter causes the find method to break
1988 // on the first match in the forward history slice. The starting index
1989 // of the slice must then be added to the result to get the element index
1990 // in the original history stack :( :(
1991 //
1992 // TODO this is hyper confusing and should be cleaned up (ugh so bad)
1993 if( closest === undefined ) {
1994 closest = this.find( url, this.stack.slice(a), true );
1995 closest = closest === undefined ? closest : closest + a;
1996 }
1997
1998 return closest;
1999 },
2000
2001 direct: function( opts ) {
2002 var newActiveIndex = this.closest( opts.url ), a = this.activeIndex;
2003
2004 // save new page index, null check to prevent falsey 0 result
2005 // record the previous index for reference
2006 if( newActiveIndex !== undefined ) {
2007 this.activeIndex = newActiveIndex;
2008 this.previousIndex = a;
2009 }
2010
2011 // invoke callbacks where appropriate
2012 //
2013 // TODO this is also convoluted and confusing
2014 if ( newActiveIndex < a ) {
2015 ( opts.present || opts.back || $.noop )( this.getActive(), 'back' );
2016 } else if ( newActiveIndex > a ) {
2017 ( opts.present || opts.forward || $.noop )( this.getActive(), 'forward' );
2018 } else if ( newActiveIndex === undefined && opts.missing ){
2019 opts.missing( this.getActive() );
2020 }
2021 }
2022 });
2023})( jQuery );
2024
2025
2026(function( $, undefined ) {
2027 var path = $.mobile.path;
2028
2029 $.mobile.Navigator = function( history ) {
2030 this.history = history;
2031 this.ignoreInitialHashChange = true;
2032
2033 // This ensures that browsers which don't fire the initial popstate
2034 // like opera don't have further hash assignment popstates blocked
2035 setTimeout($.proxy(function() {
2036 this.ignoreInitialHashChange = false;
2037 }, this), 200);
2038
2039 $.mobile.window.bind({
2040 "popstate.history": $.proxy( this.popstate, this ),
2041 "hashchange.history": $.proxy( this.hashchange, this )
2042 });
2043 };
2044
2045 $.extend($.mobile.Navigator.prototype, {
2046 squash: function( url, data ) {
2047 var state, href, hash = path.isPath(url) ? path.stripHash(url) : url;
2048
2049 href = path.squash( url );
2050
2051 // make sure to provide this information when it isn't explicitly set in the
2052 // data object that was passed to the squash method
2053 state = $.extend({
2054 hash: hash,
2055 url: href
2056 }, data);
2057
2058 // replace the current url with the new href and store the state
2059 // Note that in some cases we might be replacing an url with the
2060 // same url. We do this anyways because we need to make sure that
2061 // all of our history entries have a state object associated with
2062 // them. This allows us to work around the case where $.mobile.back()
2063 // is called to transition from an external page to an embedded page.
2064 // In that particular case, a hashchange event is *NOT* generated by the browser.
2065 // Ensuring each history entry has a state object means that onPopState()
2066 // will always trigger our hashchange callback even when a hashchange event
2067 // is not fired.
2068 window.history.replaceState( state, state.title || document.title, href );
2069
2070 return state;
2071 },
2072
2073 hash: function( url, href ) {
2074 var parsed, loc, hash;
2075
2076 // Grab the hash for recording. If the passed url is a path
2077 // we used the parsed version of the squashed url to reconstruct,
2078 // otherwise we assume it's a hash and store it directly
2079 parsed = path.parseUrl( url );
2080 loc = path.parseLocation();
2081
2082 if( loc.pathname + loc.search === parsed.pathname + parsed.search ) {
2083 // If the pathname and search of the passed url is identical to the current loc
2084 // then we must use the hash. Otherwise there will be no event
2085 // eg, url = "/foo/bar?baz#bang", location.href = "http://example.com/foo/bar?baz"
2086 hash = parsed.hash ? parsed.hash : parsed.pathname + parsed.search;
2087 } else if ( path.isPath(url) ) {
2088 var resolved = path.parseUrl( href );
2089 // If the passed url is a path, make it domain relative and remove any trailing hash
2090 hash = resolved.pathname + resolved.search + (path.isPreservableHash( resolved.hash )? resolved.hash.replace( "#", "" ) : "");
2091 } else {
2092 hash = url;
2093 }
2094
2095 return hash;
2096 },
2097
2098 // TODO reconsider name
2099 go: function( url, data, noEvents ) {
2100 var state, href, hash, popstateEvent,
2101 isPopStateEvent = $.event.special.navigate.isPushStateEnabled();
2102
2103 // Get the url as it would look squashed on to the current resolution url
2104 href = path.squash( url );
2105
2106 // sort out what the hash sould be from the url
2107 hash = this.hash( url, href );
2108
2109 // Here we prevent the next hash change or popstate event from doing any
2110 // history management. In the case of hashchange we don't swallow it
2111 // if there will be no hashchange fired (since that won't reset the value)
2112 // and will swallow the following hashchange
2113 if( noEvents && hash !== path.stripHash(path.parseLocation().hash) ) {
2114 this.preventNextHashChange = noEvents;
2115 }
2116
2117 // IMPORTANT in the case where popstate is supported the event will be triggered
2118 // directly, stopping further execution - ie, interupting the flow of this
2119 // method call to fire bindings at this expression. Below the navigate method
2120 // there is a binding to catch this event and stop its propagation.
2121 //
2122 // We then trigger a new popstate event on the window with a null state
2123 // so that the navigate events can conclude their work properly
2124 //
2125 // if the url is a path we want to preserve the query params that are available on
2126 // the current url.
2127 this.preventHashAssignPopState = true;
2128 window.location.hash = hash;
2129
2130 // If popstate is enabled and the browser triggers `popstate` events when the hash
2131 // is set (this often happens immediately in browsers like Chrome), then the
2132 // this flag will be set to false already. If it's a browser that does not trigger
2133 // a `popstate` on hash assignement or `replaceState` then we need avoid the branch
2134 // that swallows the event created by the popstate generated by the hash assignment
2135 // At the time of this writing this happens with Opera 12 and some version of IE
2136 this.preventHashAssignPopState = false;
2137
2138 state = $.extend({
2139 url: href,
2140 hash: hash,
2141 title: document.title
2142 }, data);
2143
2144 if( isPopStateEvent ) {
2145 popstateEvent = new $.Event( "popstate" );
2146 popstateEvent.originalEvent = {
2147 type: "popstate",
2148 state: null
2149 };
2150
2151 this.squash( url, state );
2152
2153 // Trigger a new faux popstate event to replace the one that we
2154 // caught that was triggered by the hash setting above.
2155 if( !noEvents ) {
2156 this.ignorePopState = true;
2157 $.mobile.window.trigger( popstateEvent );
2158 }
2159 }
2160
2161 // record the history entry so that the information can be included
2162 // in hashchange event driven navigate events in a similar fashion to
2163 // the state that's provided by popstate
2164 this.history.add( state.url, state );
2165 },
2166
2167
2168 // This binding is intended to catch the popstate events that are fired
2169 // when execution of the `$.navigate` method stops at window.location.hash = url;
2170 // and completely prevent them from propagating. The popstate event will then be
2171 // retriggered after execution resumes
2172 //
2173 // TODO grab the original event here and use it for the synthetic event in the
2174 // second half of the navigate execution that will follow this binding
2175 popstate: function( event ) {
2176 var active, hash, state, closestIndex;
2177
2178 // Partly to support our test suite which manually alters the support
2179 // value to test hashchange. Partly to prevent all around weirdness
2180 if( !$.event.special.navigate.isPushStateEnabled() ){
2181 return;
2182 }
2183
2184 // If this is the popstate triggered by the actual alteration of the hash
2185 // prevent it completely. History is tracked manually
2186 if( this.preventHashAssignPopState ) {
2187 this.preventHashAssignPopState = false;
2188 event.stopImmediatePropagation();
2189 return;
2190 }
2191
2192 // if this is the popstate triggered after the `replaceState` call in the go
2193 // method, then simply ignore it. The history entry has already been captured
2194 if( this.ignorePopState ) {
2195 this.ignorePopState = false;
2196 return;
2197 }
2198
2199 // If there is no state, and the history stack length is one were
2200 // probably getting the page load popstate fired by browsers like chrome
2201 // avoid it and set the one time flag to false
2202 if( !event.originalEvent.state &&
2203 this.history.stack.length === 1 &&
2204 this.ignoreInitialHashChange ) {
2205 this.ignoreInitialHashChange = false;
2206
2207 return;
2208 }
2209
2210 // account for direct manipulation of the hash. That is, we will receive a popstate
2211 // when the hash is changed by assignment, and it won't have a state associated. We
2212 // then need to squash the hash. See below for handling of hash assignment that
2213 // matches an existing history entry
2214 // TODO it might be better to only add to the history stack
2215 // when the hash is adjacent to the active history entry
2216 hash = path.parseLocation().hash;
2217 if( !event.originalEvent.state && hash ) {
2218 // squash the hash that's been assigned on the URL with replaceState
2219 // also grab the resulting state object for storage
2220 state = this.squash( hash );
2221
2222 // record the new hash as an additional history entry
2223 // to match the browser's treatment of hash assignment
2224 this.history.add( state.url, state );
2225
2226 // pass the newly created state information
2227 // along with the event
2228 event.historyState = state;
2229
2230 // do not alter history, we've added a new history entry
2231 // so we know where we are
2232 return;
2233 }
2234
2235 // If all else fails this is a popstate that comes from the back or forward buttons
2236 // make sure to set the state of our history stack properly, and record the directionality
2237 this.history.direct({
2238 url: (event.originalEvent.state || {}).url || hash,
2239
2240 // When the url is either forward or backward in history include the entry
2241 // as data on the event object for merging as data in the navigate event
2242 present: function( historyEntry, direction ) {
2243 // make sure to create a new object to pass down as the navigate event data
2244 event.historyState = $.extend({}, historyEntry);
2245 event.historyState.direction = direction;
2246 }
2247 });
2248 },
2249
2250 // NOTE must bind before `navigate` special event hashchange binding otherwise the
2251 // navigation data won't be attached to the hashchange event in time for those
2252 // bindings to attach it to the `navigate` special event
2253 // TODO add a check here that `hashchange.navigate` is bound already otherwise it's
2254 // broken (exception?)
2255 hashchange: function( event ) {
2256 var history, hash;
2257
2258 // If hashchange listening is explicitly disabled or pushstate is supported
2259 // avoid making use of the hashchange handler.
2260 if(!$.event.special.navigate.isHashChangeEnabled() ||
2261 $.event.special.navigate.isPushStateEnabled() ) {
2262 return;
2263 }
2264
2265 // On occasion explicitly want to prevent the next hash from propogating because we only
2266 // with to alter the url to represent the new state do so here
2267 if( this.preventNextHashChange ){
2268 this.preventNextHashChange = false;
2269 event.stopImmediatePropagation();
2270 return;
2271 }
2272
2273 history = this.history;
2274 hash = path.parseLocation().hash;
2275
2276 // If this is a hashchange caused by the back or forward button
2277 // make sure to set the state of our history stack properly
2278 this.history.direct({
2279 url: hash,
2280
2281 // When the url is either forward or backward in history include the entry
2282 // as data on the event object for merging as data in the navigate event
2283 present: function( historyEntry, direction ) {
2284 // make sure to create a new object to pass down as the navigate event data
2285 event.hashchangeState = $.extend({}, historyEntry);
2286 event.hashchangeState.direction = direction;
2287 },
2288
2289 // When we don't find a hash in our history clearly we're aiming to go there
2290 // record the entry as new for future traversal
2291 //
2292 // NOTE it's not entirely clear that this is the right thing to do given that we
2293 // can't know the users intention. It might be better to explicitly _not_
2294 // support location.hash assignment in preference to $.navigate calls
2295 // TODO first arg to add should be the href, but it causes issues in identifying
2296 // embeded pages
2297 missing: function() {
2298 history.add( hash, {
2299 hash: hash,
2300 title: document.title
2301 });
2302 }
2303 });
2304 }
2305 });
2306})( jQuery );
2307
2308
2309
2310(function( $, undefined ) {
2311 // TODO consider queueing navigation activity until previous activities have completed
2312 // so that end users don't have to think about it. Punting for now
2313 // TODO !! move the event bindings into callbacks on the navigate event
2314 $.mobile.navigate = function( url, data, noEvents ) {
2315 $.mobile.navigate.navigator.go( url, data, noEvents );
2316 };
2317
2318 // expose the history on the navigate method in anticipation of full integration with
2319 // existing navigation functionalty that is tightly coupled to the history information
2320 $.mobile.navigate.history = new $.mobile.History();
2321
2322 // instantiate an instance of the navigator for use within the $.navigate method
2323 $.mobile.navigate.navigator = new $.mobile.Navigator( $.mobile.navigate.history );
2324
2325 var loc = $.mobile.path.parseLocation();
2326 $.mobile.navigate.history.add( loc.href, {hash: loc.hash} );
2327})( jQuery );
2328
2329
2330// This plugin is an experiment for abstracting away the touch and mouse
2331// events so that developers don't have to worry about which method of input
2332// the device their document is loaded on supports.
2333//
2334// The idea here is to allow the developer to register listeners for the
2335// basic mouse events, such as mousedown, mousemove, mouseup, and click,
2336// and the plugin will take care of registering the correct listeners
2337// behind the scenes to invoke the listener at the fastest possible time
2338// for that device, while still retaining the order of event firing in
2339// the traditional mouse environment, should multiple handlers be registered
2340// on the same element for different events.
2341//
2342// The current version exposes the following virtual events to jQuery bind methods:
2343// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel"
2344
2345(function( $, window, document, undefined ) {
2346
2347var dataPropertyName = "virtualMouseBindings",
2348 touchTargetPropertyName = "virtualTouchID",
2349 virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ),
2350 touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ),
2351 mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],
2352 mouseEventProps = $.event.props.concat( mouseHookProps ),
2353 activeDocHandlers = {},
2354 resetTimerID = 0,
2355 startX = 0,
2356 startY = 0,
2357 didScroll = false,
2358 clickBlockList = [],
2359 blockMouseTriggers = false,
2360 blockTouchTriggers = false,
2361 eventCaptureSupported = "addEventListener" in document,
2362 $document = $( document ),
2363 nextTouchID = 1,
2364 lastTouchID = 0, threshold;
2365
2366$.vmouse = {
2367 moveDistanceThreshold: 10,
2368 clickDistanceThreshold: 10,
2369 resetTimerDuration: 1500
2370};
2371
2372function getNativeEvent( event ) {
2373
2374 while ( event && typeof event.originalEvent !== "undefined" ) {
2375 event = event.originalEvent;
2376 }
2377 return event;
2378}
2379
2380function createVirtualEvent( event, eventType ) {
2381
2382 var t = event.type,
2383 oe, props, ne, prop, ct, touch, i, j, len;
2384
2385 event = $.Event( event );
2386 event.type = eventType;
2387
2388 oe = event.originalEvent;
2389 props = $.event.props;
2390
2391 // addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280
2392 // https://github.com/jquery/jquery-mobile/issues/3280
2393 if ( t.search( /^(mouse|click)/ ) > -1 ) {
2394 props = mouseEventProps;
2395 }
2396
2397 // copy original event properties over to the new event
2398 // this would happen if we could call $.event.fix instead of $.Event
2399 // but we don't have a way to force an event to be fixed multiple times
2400 if ( oe ) {
2401 for ( i = props.length, prop; i; ) {
2402 prop = props[ --i ];
2403 event[ prop ] = oe[ prop ];
2404 }
2405 }
2406
2407 // make sure that if the mouse and click virtual events are generated
2408 // without a .which one is defined
2409 if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) {
2410 event.which = 1;
2411 }
2412
2413 if ( t.search(/^touch/) !== -1 ) {
2414 ne = getNativeEvent( oe );
2415 t = ne.touches;
2416 ct = ne.changedTouches;
2417 touch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined );
2418
2419 if ( touch ) {
2420 for ( j = 0, len = touchEventProps.length; j < len; j++) {
2421 prop = touchEventProps[ j ];
2422 event[ prop ] = touch[ prop ];
2423 }
2424 }
2425 }
2426
2427 return event;
2428}
2429
2430function getVirtualBindingFlags( element ) {
2431
2432 var flags = {},
2433 b, k;
2434
2435 while ( element ) {
2436
2437 b = $.data( element, dataPropertyName );
2438
2439 for ( k in b ) {
2440 if ( b[ k ] ) {
2441 flags[ k ] = flags.hasVirtualBinding = true;
2442 }
2443 }
2444 element = element.parentNode;
2445 }
2446 return flags;
2447}
2448
2449function getClosestElementWithVirtualBinding( element, eventType ) {
2450 var b;
2451 while ( element ) {
2452
2453 b = $.data( element, dataPropertyName );
2454
2455 if ( b && ( !eventType || b[ eventType ] ) ) {
2456 return element;
2457 }
2458 element = element.parentNode;
2459 }
2460 return null;
2461}
2462
2463function enableTouchBindings() {
2464 blockTouchTriggers = false;
2465}
2466
2467function disableTouchBindings() {
2468 blockTouchTriggers = true;
2469}
2470
2471function enableMouseBindings() {
2472 lastTouchID = 0;
2473 clickBlockList.length = 0;
2474 blockMouseTriggers = false;
2475
2476 // When mouse bindings are enabled, our
2477 // touch bindings are disabled.
2478 disableTouchBindings();
2479}
2480
2481function disableMouseBindings() {
2482 // When mouse bindings are disabled, our
2483 // touch bindings are enabled.
2484 enableTouchBindings();
2485}
2486
2487function startResetTimer() {
2488 clearResetTimer();
2489 resetTimerID = setTimeout( function() {
2490 resetTimerID = 0;
2491 enableMouseBindings();
2492 }, $.vmouse.resetTimerDuration );
2493}
2494
2495function clearResetTimer() {
2496 if ( resetTimerID ) {
2497 clearTimeout( resetTimerID );
2498 resetTimerID = 0;
2499 }
2500}
2501
2502function triggerVirtualEvent( eventType, event, flags ) {
2503 var ve;
2504
2505 if ( ( flags && flags[ eventType ] ) ||
2506 ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
2507
2508 ve = createVirtualEvent( event, eventType );
2509
2510 $( event.target).trigger( ve );
2511 }
2512
2513 return ve;
2514}
2515
2516function mouseEventCallback( event ) {
2517 var touchID = $.data( event.target, touchTargetPropertyName );
2518
2519 if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) {
2520 var ve = triggerVirtualEvent( "v" + event.type, event );
2521 if ( ve ) {
2522 if ( ve.isDefaultPrevented() ) {
2523 event.preventDefault();
2524 }
2525 if ( ve.isPropagationStopped() ) {
2526 event.stopPropagation();
2527 }
2528 if ( ve.isImmediatePropagationStopped() ) {
2529 event.stopImmediatePropagation();
2530 }
2531 }
2532 }
2533}
2534
2535function handleTouchStart( event ) {
2536
2537 var touches = getNativeEvent( event ).touches,
2538 target, flags;
2539
2540 if ( touches && touches.length === 1 ) {
2541
2542 target = event.target;
2543 flags = getVirtualBindingFlags( target );
2544
2545 if ( flags.hasVirtualBinding ) {
2546
2547 lastTouchID = nextTouchID++;
2548 $.data( target, touchTargetPropertyName, lastTouchID );
2549
2550 clearResetTimer();
2551
2552 disableMouseBindings();
2553 didScroll = false;
2554
2555 var t = getNativeEvent( event ).touches[ 0 ];
2556 startX = t.pageX;
2557 startY = t.pageY;
2558
2559 triggerVirtualEvent( "vmouseover", event, flags );
2560 triggerVirtualEvent( "vmousedown", event, flags );
2561 }
2562 }
2563}
2564
2565function handleScroll( event ) {
2566 if ( blockTouchTriggers ) {
2567 return;
2568 }
2569
2570 if ( !didScroll ) {
2571 triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) );
2572 }
2573
2574 didScroll = true;
2575 startResetTimer();
2576}
2577
2578function handleTouchMove( event ) {
2579 if ( blockTouchTriggers ) {
2580 return;
2581 }
2582
2583 var t = getNativeEvent( event ).touches[ 0 ],
2584 didCancel = didScroll,
2585 moveThreshold = $.vmouse.moveDistanceThreshold,
2586 flags = getVirtualBindingFlags( event.target );
2587
2588 didScroll = didScroll ||
2589 ( Math.abs( t.pageX - startX ) > moveThreshold ||
2590 Math.abs( t.pageY - startY ) > moveThreshold );
2591
2592
2593 if ( didScroll && !didCancel ) {
2594 triggerVirtualEvent( "vmousecancel", event, flags );
2595 }
2596
2597 triggerVirtualEvent( "vmousemove", event, flags );
2598 startResetTimer();
2599}
2600
2601function handleTouchEnd( event ) {
2602 if ( blockTouchTriggers ) {
2603 return;
2604 }
2605
2606 disableTouchBindings();
2607
2608 var flags = getVirtualBindingFlags( event.target ),
2609 t;
2610 triggerVirtualEvent( "vmouseup", event, flags );
2611
2612 if ( !didScroll ) {
2613 var ve = triggerVirtualEvent( "vclick", event, flags );
2614 if ( ve && ve.isDefaultPrevented() ) {
2615 // The target of the mouse events that follow the touchend
2616 // event don't necessarily match the target used during the
2617 // touch. This means we need to rely on coordinates for blocking
2618 // any click that is generated.
2619 t = getNativeEvent( event ).changedTouches[ 0 ];
2620 clickBlockList.push({
2621 touchID: lastTouchID,
2622 x: t.clientX,
2623 y: t.clientY
2624 });
2625
2626 // Prevent any mouse events that follow from triggering
2627 // virtual event notifications.
2628 blockMouseTriggers = true;
2629 }
2630 }
2631 triggerVirtualEvent( "vmouseout", event, flags);
2632 didScroll = false;
2633
2634 startResetTimer();
2635}
2636
2637function hasVirtualBindings( ele ) {
2638 var bindings = $.data( ele, dataPropertyName ),
2639 k;
2640
2641 if ( bindings ) {
2642 for ( k in bindings ) {
2643 if ( bindings[ k ] ) {
2644 return true;
2645 }
2646 }
2647 }
2648 return false;
2649}
2650
2651function dummyMouseHandler() {}
2652
2653function getSpecialEventObject( eventType ) {
2654 var realType = eventType.substr( 1 );
2655
2656 return {
2657 setup: function( data, namespace ) {
2658 // If this is the first virtual mouse binding for this element,
2659 // add a bindings object to its data.
2660
2661 if ( !hasVirtualBindings( this ) ) {
2662 $.data( this, dataPropertyName, {} );
2663 }
2664
2665 // If setup is called, we know it is the first binding for this
2666 // eventType, so initialize the count for the eventType to zero.
2667 var bindings = $.data( this, dataPropertyName );
2668 bindings[ eventType ] = true;
2669
2670 // If this is the first virtual mouse event for this type,
2671 // register a global handler on the document.
2672
2673 activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;
2674
2675 if ( activeDocHandlers[ eventType ] === 1 ) {
2676 $document.bind( realType, mouseEventCallback );
2677 }
2678
2679 // Some browsers, like Opera Mini, won't dispatch mouse/click events
2680 // for elements unless they actually have handlers registered on them.
2681 // To get around this, we register dummy handlers on the elements.
2682
2683 $( this ).bind( realType, dummyMouseHandler );
2684
2685 // For now, if event capture is not supported, we rely on mouse handlers.
2686 if ( eventCaptureSupported ) {
2687 // If this is the first virtual mouse binding for the document,
2688 // register our touchstart handler on the document.
2689
2690 activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1;
2691
2692 if ( activeDocHandlers[ "touchstart" ] === 1 ) {
2693 $document.bind( "touchstart", handleTouchStart )
2694 .bind( "touchend", handleTouchEnd )
2695
2696 // On touch platforms, touching the screen and then dragging your finger
2697 // causes the window content to scroll after some distance threshold is
2698 // exceeded. On these platforms, a scroll prevents a click event from being
2699 // dispatched, and on some platforms, even the touchend is suppressed. To
2700 // mimic the suppression of the click event, we need to watch for a scroll
2701 // event. Unfortunately, some platforms like iOS don't dispatch scroll
2702 // events until *AFTER* the user lifts their finger (touchend). This means
2703 // we need to watch both scroll and touchmove events to figure out whether
2704 // or not a scroll happenens before the touchend event is fired.
2705
2706 .bind( "touchmove", handleTouchMove )
2707 .bind( "scroll", handleScroll );
2708 }
2709 }
2710 },
2711
2712 teardown: function( data, namespace ) {
2713 // If this is the last virtual binding for this eventType,
2714 // remove its global handler from the document.
2715
2716 --activeDocHandlers[ eventType ];
2717
2718 if ( !activeDocHandlers[ eventType ] ) {
2719 $document.unbind( realType, mouseEventCallback );
2720 }
2721
2722 if ( eventCaptureSupported ) {
2723 // If this is the last virtual mouse binding in existence,
2724 // remove our document touchstart listener.
2725
2726 --activeDocHandlers[ "touchstart" ];
2727
2728 if ( !activeDocHandlers[ "touchstart" ] ) {
2729 $document.unbind( "touchstart", handleTouchStart )
2730 .unbind( "touchmove", handleTouchMove )
2731 .unbind( "touchend", handleTouchEnd )
2732 .unbind( "scroll", handleScroll );
2733 }
2734 }
2735
2736 var $this = $( this ),
2737 bindings = $.data( this, dataPropertyName );
2738
2739 // teardown may be called when an element was
2740 // removed from the DOM. If this is the case,
2741 // jQuery core may have already stripped the element
2742 // of any data bindings so we need to check it before
2743 // using it.
2744 if ( bindings ) {
2745 bindings[ eventType ] = false;
2746 }
2747
2748 // Unregister the dummy event handler.
2749
2750 $this.unbind( realType, dummyMouseHandler );
2751
2752 // If this is the last virtual mouse binding on the
2753 // element, remove the binding data from the element.
2754
2755 if ( !hasVirtualBindings( this ) ) {
2756 $this.removeData( dataPropertyName );
2757 }
2758 }
2759 };
2760}
2761
2762// Expose our custom events to the jQuery bind/unbind mechanism.
2763
2764for ( var i = 0; i < virtualEventNames.length; i++ ) {
2765 $.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );
2766}
2767
2768// Add a capture click handler to block clicks.
2769// Note that we require event capture support for this so if the device
2770// doesn't support it, we punt for now and rely solely on mouse events.
2771if ( eventCaptureSupported ) {
2772 document.addEventListener( "click", function( e ) {
2773 var cnt = clickBlockList.length,
2774 target = e.target,
2775 x, y, ele, i, o, touchID;
2776
2777 if ( cnt ) {
2778 x = e.clientX;
2779 y = e.clientY;
2780 threshold = $.vmouse.clickDistanceThreshold;
2781
2782 // The idea here is to run through the clickBlockList to see if
2783 // the current click event is in the proximity of one of our
2784 // vclick events that had preventDefault() called on it. If we find
2785 // one, then we block the click.
2786 //
2787 // Why do we have to rely on proximity?
2788 //
2789 // Because the target of the touch event that triggered the vclick
2790 // can be different from the target of the click event synthesized
2791 // by the browser. The target of a mouse/click event that is syntehsized
2792 // from a touch event seems to be implementation specific. For example,
2793 // some browsers will fire mouse/click events for a link that is near
2794 // a touch event, even though the target of the touchstart/touchend event
2795 // says the user touched outside the link. Also, it seems that with most
2796 // browsers, the target of the mouse/click event is not calculated until the
2797 // time it is dispatched, so if you replace an element that you touched
2798 // with another element, the target of the mouse/click will be the new
2799 // element underneath that point.
2800 //
2801 // Aside from proximity, we also check to see if the target and any
2802 // of its ancestors were the ones that blocked a click. This is necessary
2803 // because of the strange mouse/click target calculation done in the
2804 // Android 2.1 browser, where if you click on an element, and there is a
2805 // mouse/click handler on one of its ancestors, the target will be the
2806 // innermost child of the touched element, even if that child is no where
2807 // near the point of touch.
2808
2809 ele = target;
2810
2811 while ( ele ) {
2812 for ( i = 0; i < cnt; i++ ) {
2813 o = clickBlockList[ i ];
2814 touchID = 0;
2815
2816 if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||
2817 $.data( ele, touchTargetPropertyName ) === o.touchID ) {
2818 // XXX: We may want to consider removing matches from the block list
2819 // instead of waiting for the reset timer to fire.
2820 e.preventDefault();
2821 e.stopPropagation();
2822 return;
2823 }
2824 }
2825 ele = ele.parentNode;
2826 }
2827 }
2828 }, true);
2829}
2830})( jQuery, window, document );
2831
2832
2833(function( $, window, undefined ) {
2834 var $document = $( document );
2835
2836 // add new event shortcuts
2837 $.each( ( "touchstart touchmove touchend " +
2838 "tap taphold " +
2839 "swipe swipeleft swiperight " +
2840 "scrollstart scrollstop" ).split( " " ), function( i, name ) {
2841
2842 $.fn[ name ] = function( fn ) {
2843 return fn ? this.bind( name, fn ) : this.trigger( name );
2844 };
2845
2846 // jQuery < 1.8
2847 if ( $.attrFn ) {
2848 $.attrFn[ name ] = true;
2849 }
2850 });
2851
2852 var supportTouch = $.mobile.support.touch,
2853 scrollEvent = "touchmove scroll",
2854 touchStartEvent = supportTouch ? "touchstart" : "mousedown",
2855 touchStopEvent = supportTouch ? "touchend" : "mouseup",
2856 touchMoveEvent = supportTouch ? "touchmove" : "mousemove";
2857
2858 function triggerCustomEvent( obj, eventType, event ) {
2859 var originalType = event.type;
2860 event.type = eventType;
2861 $.event.dispatch.call( obj, event );
2862 event.type = originalType;
2863 }
2864
2865 // also handles scrollstop
2866 $.event.special.scrollstart = {
2867
2868 enabled: true,
2869
2870 setup: function() {
2871
2872 var thisObject = this,
2873 $this = $( thisObject ),
2874 scrolling,
2875 timer;
2876
2877 function trigger( event, state ) {
2878 scrolling = state;
2879 triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );
2880 }
2881
2882 // iPhone triggers scroll after a small delay; use touchmove instead
2883 $this.bind( scrollEvent, function( event ) {
2884
2885 if ( !$.event.special.scrollstart.enabled ) {
2886 return;
2887 }
2888
2889 if ( !scrolling ) {
2890 trigger( event, true );
2891 }
2892
2893 clearTimeout( timer );
2894 timer = setTimeout( function() {
2895 trigger( event, false );
2896 }, 50 );
2897 });
2898 }
2899 };
2900
2901 // also handles taphold
2902 $.event.special.tap = {
2903 tapholdThreshold: 750,
2904
2905 setup: function() {
2906 var thisObject = this,
2907 $this = $( thisObject );
2908
2909 $this.bind( "vmousedown", function( event ) {
2910
2911 if ( event.which && event.which !== 1 ) {
2912 return false;
2913 }
2914
2915 var origTarget = event.target,
2916 origEvent = event.originalEvent,
2917 timer;
2918
2919 function clearTapTimer() {
2920 clearTimeout( timer );
2921 }
2922
2923 function clearTapHandlers() {
2924 clearTapTimer();
2925
2926 $this.unbind( "vclick", clickHandler )
2927 .unbind( "vmouseup", clearTapTimer );
2928 $document.unbind( "vmousecancel", clearTapHandlers );
2929 }
2930
2931 function clickHandler( event ) {
2932 clearTapHandlers();
2933
2934 // ONLY trigger a 'tap' event if the start target is
2935 // the same as the stop target.
2936 if ( origTarget === event.target ) {
2937 triggerCustomEvent( thisObject, "tap", event );
2938 }
2939 }
2940
2941 $this.bind( "vmouseup", clearTapTimer )
2942 .bind( "vclick", clickHandler );
2943 $document.bind( "vmousecancel", clearTapHandlers );
2944
2945 timer = setTimeout( function() {
2946 triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
2947 }, $.event.special.tap.tapholdThreshold );
2948 });
2949 }
2950 };
2951
2952 // also handles swipeleft, swiperight
2953 $.event.special.swipe = {
2954 scrollSupressionThreshold: 30, // More than this horizontal displacement, and we will suppress scrolling.
2955
2956 durationThreshold: 1000, // More time than this, and it isn't a swipe.
2957
2958 horizontalDistanceThreshold: 30, // Swipe horizontal displacement must be more than this.
2959
2960 verticalDistanceThreshold: 75, // Swipe vertical displacement must be less than this.
2961
2962 start: function( event ) {
2963 var data = event.originalEvent.touches ?
2964 event.originalEvent.touches[ 0 ] : event;
2965 return {
2966 time: ( new Date() ).getTime(),
2967 coords: [ data.pageX, data.pageY ],
2968 origin: $( event.target )
2969 };
2970 },
2971
2972 stop: function( event ) {
2973 var data = event.originalEvent.touches ?
2974 event.originalEvent.touches[ 0 ] : event;
2975 return {
2976 time: ( new Date() ).getTime(),
2977 coords: [ data.pageX, data.pageY ]
2978 };
2979 },
2980
2981 handleSwipe: function( start, stop ) {
2982 if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
2983 Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&
2984 Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {
2985
2986 start.origin.trigger( "swipe" )
2987 .trigger( start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight" );
2988 }
2989 },
2990
2991 setup: function() {
2992 var thisObject = this,
2993 $this = $( thisObject );
2994
2995 $this.bind( touchStartEvent, function( event ) {
2996 var start = $.event.special.swipe.start( event ),
2997 stop;
2998
2999 function moveHandler( event ) {
3000 if ( !start ) {
3001 return;
3002 }
3003
3004 stop = $.event.special.swipe.stop( event );
3005
3006 // prevent scrolling
3007 if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
3008 event.preventDefault();
3009 }
3010 }
3011
3012 $this.bind( touchMoveEvent, moveHandler )
3013 .one( touchStopEvent, function() {
3014 $this.unbind( touchMoveEvent, moveHandler );
3015
3016 if ( start && stop ) {
3017 $.event.special.swipe.handleSwipe( start, stop );
3018 }
3019 start = stop = undefined;
3020 });
3021 });
3022 }
3023 };
3024 $.each({
3025 scrollstop: "scrollstart",
3026 taphold: "tap",
3027 swipeleft: "swipe",
3028 swiperight: "swipe"
3029 }, function( event, sourceEvent ) {
3030
3031 $.event.special[ event ] = {
3032 setup: function() {
3033 $( this ).bind( sourceEvent, $.noop );
3034 }
3035 };
3036 });
3037
3038})( jQuery, this );
3039
3040
3041 // throttled resize event
3042 (function( $ ) {
3043 $.event.special.throttledresize = {
3044 setup: function() {
3045 $( this ).bind( "resize", handler );
3046 },
3047 teardown: function() {
3048 $( this ).unbind( "resize", handler );
3049 }
3050 };
3051
3052 var throttle = 250,
3053 handler = function() {
3054 curr = ( new Date() ).getTime();
3055 diff = curr - lastCall;
3056
3057 if ( diff >= throttle ) {
3058
3059 lastCall = curr;
3060 $( this ).trigger( "throttledresize" );
3061
3062 } else {
3063
3064 if ( heldCall ) {
3065 clearTimeout( heldCall );
3066 }
3067
3068 // Promise a held call will still execute
3069 heldCall = setTimeout( handler, throttle - diff );
3070 }
3071 },
3072 lastCall = 0,
3073 heldCall,
3074 curr,
3075 diff;
3076 })( jQuery );
3077
3078(function( $, window ) {
3079 var win = $( window ),
3080 event_name = "orientationchange",
3081 special_event,
3082 get_orientation,
3083 last_orientation,
3084 initial_orientation_is_landscape,
3085 initial_orientation_is_default,
3086 portrait_map = { "0": true, "180": true };
3087
3088 // It seems that some device/browser vendors use window.orientation values 0 and 180 to
3089 // denote the "default" orientation. For iOS devices, and most other smart-phones tested,
3090 // the default orientation is always "portrait", but in some Android and RIM based tablets,
3091 // the default orientation is "landscape". The following code attempts to use the window
3092 // dimensions to figure out what the current orientation is, and then makes adjustments
3093 // to the to the portrait_map if necessary, so that we can properly decode the
3094 // window.orientation value whenever get_orientation() is called.
3095 //
3096 // Note that we used to use a media query to figure out what the orientation the browser
3097 // thinks it is in:
3098 //
3099 // initial_orientation_is_landscape = $.mobile.media("all and (orientation: landscape)");
3100 //
3101 // but there was an iPhone/iPod Touch bug beginning with iOS 4.2, up through iOS 5.1,
3102 // where the browser *ALWAYS* applied the landscape media query. This bug does not
3103 // happen on iPad.
3104
3105 if ( $.support.orientation ) {
3106
3107 // Check the window width and height to figure out what the current orientation
3108 // of the device is at this moment. Note that we've initialized the portrait map
3109 // values to 0 and 180, *AND* we purposely check for landscape so that if we guess
3110 // wrong, , we default to the assumption that portrait is the default orientation.
3111 // We use a threshold check below because on some platforms like iOS, the iPhone
3112 // form-factor can report a larger width than height if the user turns on the
3113 // developer console. The actual threshold value is somewhat arbitrary, we just
3114 // need to make sure it is large enough to exclude the developer console case.
3115
3116 var ww = window.innerWidth || win.width(),
3117 wh = window.innerHeight || win.height(),
3118 landscape_threshold = 50;
3119
3120 initial_orientation_is_landscape = ww > wh && ( ww - wh ) > landscape_threshold;
3121
3122
3123 // Now check to see if the current window.orientation is 0 or 180.
3124 initial_orientation_is_default = portrait_map[ window.orientation ];
3125
3126 // If the initial orientation is landscape, but window.orientation reports 0 or 180, *OR*
3127 // if the initial orientation is portrait, but window.orientation reports 90 or -90, we
3128 // need to flip our portrait_map values because landscape is the default orientation for
3129 // this device/browser.
3130 if ( ( initial_orientation_is_landscape && initial_orientation_is_default ) || ( !initial_orientation_is_landscape && !initial_orientation_is_default ) ) {
3131 portrait_map = { "-90": true, "90": true };
3132 }
3133 }
3134
3135 $.event.special.orientationchange = $.extend( {}, $.event.special.orientationchange, {
3136 setup: function() {
3137 // If the event is supported natively, return false so that jQuery
3138 // will bind to the event using DOM methods.
3139 if ( $.support.orientation && !$.event.special.orientationchange.disabled ) {
3140 return false;
3141 }
3142
3143 // Get the current orientation to avoid initial double-triggering.
3144 last_orientation = get_orientation();
3145
3146 // Because the orientationchange event doesn't exist, simulate the
3147 // event by testing window dimensions on resize.
3148 win.bind( "throttledresize", handler );
3149 },
3150 teardown: function() {
3151 // If the event is not supported natively, return false so that
3152 // jQuery will unbind the event using DOM methods.
3153 if ( $.support.orientation && !$.event.special.orientationchange.disabled ) {
3154 return false;
3155 }
3156
3157 // Because the orientationchange event doesn't exist, unbind the
3158 // resize event handler.
3159 win.unbind( "throttledresize", handler );
3160 },
3161 add: function( handleObj ) {
3162 // Save a reference to the bound event handler.
3163 var old_handler = handleObj.handler;
3164
3165
3166 handleObj.handler = function( event ) {
3167 // Modify event object, adding the .orientation property.
3168 event.orientation = get_orientation();
3169
3170 // Call the originally-bound event handler and return its result.
3171 return old_handler.apply( this, arguments );
3172 };
3173 }
3174 });
3175
3176 // If the event is not supported natively, this handler will be bound to
3177 // the window resize event to simulate the orientationchange event.
3178 function handler() {
3179 // Get the current orientation.
3180 var orientation = get_orientation();
3181
3182 if ( orientation !== last_orientation ) {
3183 // The orientation has changed, so trigger the orientationchange event.
3184 last_orientation = orientation;
3185 win.trigger( event_name );
3186 }
3187 }
3188
3189 // Get the current page orientation. This method is exposed publicly, should it
3190 // be needed, as jQuery.event.special.orientationchange.orientation()
3191 $.event.special.orientationchange.orientation = get_orientation = function() {
3192 var isPortrait = true, elem = document.documentElement;
3193
3194 // prefer window orientation to the calculation based on screensize as
3195 // the actual screen resize takes place before or after the orientation change event
3196 // has been fired depending on implementation (eg android 2.3 is before, iphone after).
3197 // More testing is required to determine if a more reliable method of determining the new screensize
3198 // is possible when orientationchange is fired. (eg, use media queries + element + opacity)
3199 if ( $.support.orientation ) {
3200 // if the window orientation registers as 0 or 180 degrees report
3201 // portrait, otherwise landscape
3202 isPortrait = portrait_map[ window.orientation ];
3203 } else {
3204 isPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;
3205 }
3206
3207 return isPortrait ? "portrait" : "landscape";
3208 };
3209
3210 $.fn[ event_name ] = function( fn ) {
3211 return fn ? this.bind( event_name, fn ) : this.trigger( event_name );
3212 };
3213
3214 // jQuery < 1.8
3215 if ( $.attrFn ) {
3216 $.attrFn[ event_name ] = true;
3217 }
3218
3219}( jQuery, this ));
3220
3221
3222
3223(function( $, undefined ) {
3224
3225$.widget( "mobile.page", $.mobile.widget, {
3226 options: {
3227 theme: "c",
3228 domCache: false,
3229 keepNativeDefault: ":jqmData(role='none'), :jqmData(role='nojs')"
3230 },
3231
3232 _create: function() {
3233 // if false is returned by the callbacks do not create the page
3234 if ( this._trigger( "beforecreate" ) === false ) {
3235 return false;
3236 }
3237
3238 this.element
3239 .attr( "tabindex", "0" )
3240 .addClass( "ui-page ui-body-" + this.options.theme );
3241
3242 this._on( this.element, {
3243 pagebeforehide: "removeContainerBackground",
3244 pagebeforeshow: "_handlePageBeforeShow"
3245 });
3246 },
3247
3248 _handlePageBeforeShow: function( e ) {
3249 this.setContainerBackground();
3250 },
3251
3252 removeContainerBackground: function() {
3253 $.mobile.pageContainer.removeClass( "ui-overlay-" + $.mobile.getInheritedTheme( this.element.parent() ) );
3254 },
3255
3256 // set the page container background to the page theme
3257 setContainerBackground: function( theme ) {
3258 if ( this.options.theme ) {
3259 $.mobile.pageContainer.addClass( "ui-overlay-" + ( theme || this.options.theme ) );
3260 }
3261 },
3262
3263 keepNativeSelector: function() {
3264 var options = this.options,
3265 keepNativeDefined = options.keepNative && $.trim( options.keepNative );
3266
3267 if ( keepNativeDefined && options.keepNative !== options.keepNativeDefault ) {
3268 return [options.keepNative, options.keepNativeDefault].join( ", " );
3269 }
3270
3271 return options.keepNativeDefault;
3272 }
3273});
3274})( jQuery );
3275
3276// Script: jQuery hashchange event
3277//
3278// *Version: 1.3, Last updated: 7/21/2010*
3279//
3280// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/
3281// GitHub - http://github.com/cowboy/jquery-hashchange/
3282// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js
3283// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)
3284//
3285// About: License
3286//
3287// Copyright (c) 2010 "Cowboy" Ben Alman,
3288// Dual licensed under the MIT and GPL licenses.
3289// http://benalman.com/about/license/
3290//
3291// About: Examples
3292//
3293// These working examples, complete with fully commented code, illustrate a few
3294// ways in which this plugin can be used.
3295//
3296// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
3297// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/
3298//
3299// About: Support and Testing
3300//
3301// Information about what version or versions of jQuery this plugin has been
3302// tested with, what browsers it has been tested in, and where the unit tests
3303// reside (so you can test it yourself).
3304//
3305// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2
3306// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,
3307// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.
3308// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/
3309//
3310// About: Known issues
3311//
3312// While this jQuery hashchange event implementation is quite stable and
3313// robust, there are a few unfortunate browser bugs surrounding expected
3314// hashchange event-based behaviors, independent of any JavaScript
3315// window.onhashchange abstraction. See the following examples for more
3316// information:
3317//
3318// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/
3319// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/
3320// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/
3321// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/
3322//
3323// Also note that should a browser natively support the window.onhashchange
3324// event, but not report that it does, the fallback polling loop will be used.
3325//
3326// About: Release History
3327//
3328// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more
3329// "removable" for mobile-only development. Added IE6/7 document.title
3330// support. Attempted to make Iframe as hidden as possible by using
3331// techniques from http://www.paciellogroup.com/blog/?p=604. Added
3332// support for the "shortcut" format $(window).hashchange( fn ) and
3333// $(window).hashchange() like jQuery provides for built-in events.
3334// Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and
3335// lowered its default value to 50. Added <jQuery.fn.hashchange.domain>
3336// and <jQuery.fn.hashchange.src> properties plus document-domain.html
3337// file to address access denied issues when setting document.domain in
3338// IE6/7.
3339// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin
3340// from a page on another domain would cause an error in Safari 4. Also,
3341// IE6/7 Iframe is now inserted after the body (this actually works),
3342// which prevents the page from scrolling when the event is first bound.
3343// Event can also now be bound before DOM ready, but it won't be usable
3344// before then in IE6/7.
3345// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug
3346// where browser version is incorrectly reported as 8.0, despite
3347// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.
3348// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special
3349// window.onhashchange functionality into a separate plugin for users
3350// who want just the basic event & back button support, without all the
3351// extra awesomeness that BBQ provides. This plugin will be included as
3352// part of jQuery BBQ, but also be available separately.
3353
3354(function( $, window, undefined ) {
3355 // Reused string.
3356 var str_hashchange = 'hashchange',
3357
3358 // Method / object references.
3359 doc = document,
3360 fake_onhashchange,
3361 special = $.event.special,
3362
3363 // Does the browser support window.onhashchange? Note that IE8 running in
3364 // IE7 compatibility mode reports true for 'onhashchange' in window, even
3365 // though the event isn't supported, so also test document.documentMode.
3366 doc_mode = doc.documentMode,
3367 supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );
3368
3369 // Get location.hash (or what you'd expect location.hash to be) sans any
3370 // leading #. Thanks for making this necessary, Firefox!
3371 function get_fragment( url ) {
3372 url = url || location.href;
3373 return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );
3374 };
3375
3376 // Method: jQuery.fn.hashchange
3377 //
3378 // Bind a handler to the window.onhashchange event or trigger all bound
3379 // window.onhashchange event handlers. This behavior is consistent with
3380 // jQuery's built-in event handlers.
3381 //
3382 // Usage:
3383 //
3384 // > jQuery(window).hashchange( [ handler ] );
3385 //
3386 // Arguments:
3387 //
3388 // handler - (Function) Optional handler to be bound to the hashchange
3389 // event. This is a "shortcut" for the more verbose form:
3390 // jQuery(window).bind( 'hashchange', handler ). If handler is omitted,
3391 // all bound window.onhashchange event handlers will be triggered. This
3392 // is a shortcut for the more verbose
3393 // jQuery(window).trigger( 'hashchange' ). These forms are described in
3394 // the <hashchange event> section.
3395 //
3396 // Returns:
3397 //
3398 // (jQuery) The initial jQuery collection of elements.
3399
3400 // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and
3401 // $(elem).hashchange() for triggering, like jQuery does for built-in events.
3402 $.fn[ str_hashchange ] = function( fn ) {
3403 return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );
3404 };
3405
3406 // Property: jQuery.fn.hashchange.delay
3407 //
3408 // The numeric interval (in milliseconds) at which the <hashchange event>
3409 // polling loop executes. Defaults to 50.
3410
3411 // Property: jQuery.fn.hashchange.domain
3412 //
3413 // If you're setting document.domain in your JavaScript, and you want hash
3414 // history to work in IE6/7, not only must this property be set, but you must
3415 // also set document.domain BEFORE jQuery is loaded into the page. This
3416 // property is only applicable if you are supporting IE6/7 (or IE8 operating
3417 // in "IE7 compatibility" mode).
3418 //
3419 // In addition, the <jQuery.fn.hashchange.src> property must be set to the
3420 // path of the included "document-domain.html" file, which can be renamed or
3421 // modified if necessary (note that the document.domain specified must be the
3422 // same in both your main JavaScript as well as in this file).
3423 //
3424 // Usage:
3425 //
3426 // jQuery.fn.hashchange.domain = document.domain;
3427
3428 // Property: jQuery.fn.hashchange.src
3429 //
3430 // If, for some reason, you need to specify an Iframe src file (for example,
3431 // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can
3432 // do so using this property. Note that when using this property, history
3433 // won't be recorded in IE6/7 until the Iframe src file loads. This property
3434 // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7
3435 // compatibility" mode).
3436 //
3437 // Usage:
3438 //
3439 // jQuery.fn.hashchange.src = 'path/to/file.html';
3440
3441 $.fn[ str_hashchange ].delay = 50;
3442 /*
3443 $.fn[ str_hashchange ].domain = null;
3444 $.fn[ str_hashchange ].src = null;
3445 */
3446
3447 // Event: hashchange event
3448 //
3449 // Fired when location.hash changes. In browsers that support it, the native
3450 // HTML5 window.onhashchange event is used, otherwise a polling loop is
3451 // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to
3452 // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7
3453 // compatibility" mode), a hidden Iframe is created to allow the back button
3454 // and hash-based history to work.
3455 //
3456 // Usage as described in <jQuery.fn.hashchange>:
3457 //
3458 // > // Bind an event handler.
3459 // > jQuery(window).hashchange( function(e) {
3460 // > var hash = location.hash;
3461 // > ...
3462 // > });
3463 // >
3464 // > // Manually trigger the event handler.
3465 // > jQuery(window).hashchange();
3466 //
3467 // A more verbose usage that allows for event namespacing:
3468 //
3469 // > // Bind an event handler.
3470 // > jQuery(window).bind( 'hashchange', function(e) {
3471 // > var hash = location.hash;
3472 // > ...
3473 // > });
3474 // >
3475 // > // Manually trigger the event handler.
3476 // > jQuery(window).trigger( 'hashchange' );
3477 //
3478 // Additional Notes:
3479 //
3480 // * The polling loop and Iframe are not created until at least one handler
3481 // is actually bound to the 'hashchange' event.
3482 // * If you need the bound handler(s) to execute immediately, in cases where
3483 // a location.hash exists on page load, via bookmark or page refresh for
3484 // example, use jQuery(window).hashchange() or the more verbose
3485 // jQuery(window).trigger( 'hashchange' ).
3486 // * The event can be bound before DOM ready, but since it won't be usable
3487 // before then in IE6/7 (due to the necessary Iframe), recommended usage is
3488 // to bind it inside a DOM ready handler.
3489
3490 // Override existing $.event.special.hashchange methods (allowing this plugin
3491 // to be defined after jQuery BBQ in BBQ's source code).
3492 special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
3493
3494 // Called only when the first 'hashchange' event is bound to window.
3495 setup: function() {
3496 // If window.onhashchange is supported natively, there's nothing to do..
3497 if ( supports_onhashchange ) { return false; }
3498
3499 // Otherwise, we need to create our own. And we don't want to call this
3500 // until the user binds to the event, just in case they never do, since it
3501 // will create a polling loop and possibly even a hidden Iframe.
3502 $( fake_onhashchange.start );
3503 },
3504
3505 // Called only when the last 'hashchange' event is unbound from window.
3506 teardown: function() {
3507 // If window.onhashchange is supported natively, there's nothing to do..
3508 if ( supports_onhashchange ) { return false; }
3509
3510 // Otherwise, we need to stop ours (if possible).
3511 $( fake_onhashchange.stop );
3512 }
3513
3514 });
3515
3516 // fake_onhashchange does all the work of triggering the window.onhashchange
3517 // event for browsers that don't natively support it, including creating a
3518 // polling loop to watch for hash changes and in IE 6/7 creating a hidden
3519 // Iframe to enable back and forward.
3520 fake_onhashchange = (function() {
3521 var self = {},
3522 timeout_id,
3523
3524 // Remember the initial hash so it doesn't get triggered immediately.
3525 last_hash = get_fragment(),
3526
3527 fn_retval = function( val ) { return val; },
3528 history_set = fn_retval,
3529 history_get = fn_retval;
3530
3531 // Start the polling loop.
3532 self.start = function() {
3533 timeout_id || poll();
3534 };
3535
3536 // Stop the polling loop.
3537 self.stop = function() {
3538 timeout_id && clearTimeout( timeout_id );
3539 timeout_id = undefined;
3540 };
3541
3542 // This polling loop checks every $.fn.hashchange.delay milliseconds to see
3543 // if location.hash has changed, and triggers the 'hashchange' event on
3544 // window when necessary.
3545 function poll() {
3546 var hash = get_fragment(),
3547 history_hash = history_get( last_hash );
3548
3549 if ( hash !== last_hash ) {
3550 history_set( last_hash = hash, history_hash );
3551
3552 $(window).trigger( str_hashchange );
3553
3554 } else if ( history_hash !== last_hash ) {
3555 location.href = location.href.replace( /#.*/, '' ) + history_hash;
3556 }
3557
3558 timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );
3559 };
3560
3561 // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3562 // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv
3563 // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
3564 window.attachEvent && !window.addEventListener && !supports_onhashchange && (function() {
3565 // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8
3566 // when running in "IE7 compatibility" mode.
3567
3568 var iframe,
3569 iframe_src;
3570
3571 // When the event is bound and polling starts in IE 6/7, create a hidden
3572 // Iframe for history handling.
3573 self.start = function() {
3574 if ( !iframe ) {
3575 iframe_src = $.fn[ str_hashchange ].src;
3576 iframe_src = iframe_src && iframe_src + get_fragment();
3577
3578 // Create hidden Iframe. Attempt to make Iframe as hidden as possible
3579 // by using techniques from http://www.paciellogroup.com/blog/?p=604.
3580 iframe = $('<iframe tabindex="-1" title="empty"/>').hide()
3581
3582 // When Iframe has completely loaded, initialize the history and
3583 // start polling.
3584 .one( 'load', function() {
3585 iframe_src || history_set( get_fragment() );
3586 poll();
3587 })
3588
3589 // Load Iframe src if specified, otherwise nothing.
3590 .attr( 'src', iframe_src || 'javascript:0' )
3591
3592 // Append Iframe after the end of the body to prevent unnecessary
3593 // initial page scrolling (yes, this works).
3594 .insertAfter( 'body' )[0].contentWindow;
3595
3596 // Whenever `document.title` changes, update the Iframe's title to
3597 // prettify the back/next history menu entries. Since IE sometimes
3598 // errors with "Unspecified error" the very first time this is set
3599 // (yes, very useful) wrap this with a try/catch block.
3600 doc.onpropertychange = function() {
3601 try {
3602 if ( event.propertyName === 'title' ) {
3603 iframe.document.title = doc.title;
3604 }
3605 } catch(e) {}
3606 };
3607
3608 }
3609 };
3610
3611 // Override the "stop" method since an IE6/7 Iframe was created. Even
3612 // if there are no longer any bound event handlers, the polling loop
3613 // is still necessary for back/next to work at all!
3614 self.stop = fn_retval;
3615
3616 // Get history by looking at the hidden Iframe's location.hash.
3617 history_get = function() {
3618 return get_fragment( iframe.location.href );
3619 };
3620
3621 // Set a new history item by opening and then closing the Iframe
3622 // document, *then* setting its location.hash. If document.domain has
3623 // been set, update that as well.
3624 history_set = function( hash, history_hash ) {
3625 var iframe_doc = iframe.document,
3626 domain = $.fn[ str_hashchange ].domain;
3627
3628 if ( hash !== history_hash ) {
3629 // Update Iframe with any initial `document.title` that might be set.
3630 iframe_doc.title = doc.title;
3631
3632 // Opening the Iframe's document after it has been closed is what
3633 // actually adds a history entry.
3634 iframe_doc.open();
3635
3636 // Set document.domain for the Iframe document as well, if necessary.
3637 domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' );
3638
3639 iframe_doc.close();
3640
3641 // Update the Iframe's hash, for great justice.
3642 iframe.location.hash = hash;
3643 }
3644 };
3645
3646 })();
3647 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3648 // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^
3649 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3650
3651 return self;
3652 })();
3653
3654})(jQuery,this);
3655
3656(function( $, window, undefined ) {
3657
3658var createHandler = function( sequential ) {
3659
3660 // Default to sequential
3661 if ( sequential === undefined ) {
3662 sequential = true;
3663 }
3664
3665 return function( name, reverse, $to, $from ) {
3666
3667 var deferred = new $.Deferred(),
3668 reverseClass = reverse ? " reverse" : "",
3669 active= $.mobile.urlHistory.getActive(),
3670 toScroll = active.lastScroll || $.mobile.defaultHomeScroll,
3671 screenHeight = $.mobile.getScreenHeight(),
3672 maxTransitionOverride = $.mobile.maxTransitionWidth !== false && $.mobile.window.width() > $.mobile.maxTransitionWidth,
3673 none = !$.support.cssTransitions || maxTransitionOverride || !name || name === "none" || Math.max( $.mobile.window.scrollTop(), toScroll ) > $.mobile.getMaxScrollForTransition(),
3674 toPreClass = " ui-page-pre-in",
3675 toggleViewportClass = function() {
3676 $.mobile.pageContainer.toggleClass( "ui-mobile-viewport-transitioning viewport-" + name );
3677 },
3678 scrollPage = function() {
3679 // By using scrollTo instead of silentScroll, we can keep things better in order
3680 // Just to be precautios, disable scrollstart listening like silentScroll would
3681 $.event.special.scrollstart.enabled = false;
3682
3683 window.scrollTo( 0, toScroll );
3684
3685 // reenable scrollstart listening like silentScroll would
3686 setTimeout( function() {
3687 $.event.special.scrollstart.enabled = true;
3688 }, 150 );
3689 },
3690 cleanFrom = function() {
3691 $from
3692 .removeClass( $.mobile.activePageClass + " out in reverse " + name )
3693 .height( "" );
3694 },
3695 startOut = function() {
3696 // if it's not sequential, call the doneOut transition to start the TO page animating in simultaneously
3697 if ( !sequential ) {
3698 doneOut();
3699 }
3700 else {
3701 $from.animationComplete( doneOut );
3702 }
3703
3704 // Set the from page's height and start it transitioning out
3705 // Note: setting an explicit height helps eliminate tiling in the transitions
3706 $from
3707 .height( screenHeight + $.mobile.window.scrollTop() )
3708 .addClass( name + " out" + reverseClass );
3709 },
3710
3711 doneOut = function() {
3712
3713 if ( $from && sequential ) {
3714 cleanFrom();
3715 }
3716
3717 startIn();
3718 },
3719
3720 startIn = function() {
3721
3722 // Prevent flickering in phonegap container: see comments at #4024 regarding iOS
3723 $to.css( "z-index", -10 );
3724
3725 $to.addClass( $.mobile.activePageClass + toPreClass );
3726
3727 // Send focus to page as it is now display: block
3728 $.mobile.focusPage( $to );
3729
3730 // Set to page height
3731 $to.height( screenHeight + toScroll );
3732
3733 scrollPage();
3734
3735 // Restores visibility of the new page: added together with $to.css( "z-index", -10 );
3736 $to.css( "z-index", "" );
3737
3738 if ( !none ) {
3739 $to.animationComplete( doneIn );
3740 }
3741
3742 $to
3743 .removeClass( toPreClass )
3744 .addClass( name + " in" + reverseClass );
3745
3746 if ( none ) {
3747 doneIn();
3748 }
3749
3750 },
3751
3752 doneIn = function() {
3753
3754 if ( !sequential ) {
3755
3756 if ( $from ) {
3757 cleanFrom();
3758 }
3759 }
3760
3761 $to
3762 .removeClass( "out in reverse " + name )
3763 .height( "" );
3764
3765 toggleViewportClass();
3766
3767 // In some browsers (iOS5), 3D transitions block the ability to scroll to the desired location during transition
3768 // This ensures we jump to that spot after the fact, if we aren't there already.
3769 if ( $.mobile.window.scrollTop() !== toScroll ) {
3770 scrollPage();
3771 }
3772
3773 deferred.resolve( name, reverse, $to, $from, true );
3774 };
3775
3776 toggleViewportClass();
3777
3778 if ( $from && !none ) {
3779 startOut();
3780 }
3781 else {
3782 doneOut();
3783 }
3784
3785 return deferred.promise();
3786 };
3787};
3788
3789// generate the handlers from the above
3790var sequentialHandler = createHandler(),
3791 simultaneousHandler = createHandler( false ),
3792 defaultGetMaxScrollForTransition = function() {
3793 return $.mobile.getScreenHeight() * 3;
3794 };
3795
3796// Make our transition handler the public default.
3797$.mobile.defaultTransitionHandler = sequentialHandler;
3798
3799//transition handler dictionary for 3rd party transitions
3800$.mobile.transitionHandlers = {
3801 "default": $.mobile.defaultTransitionHandler,
3802 "sequential": sequentialHandler,
3803 "simultaneous": simultaneousHandler
3804};
3805
3806$.mobile.transitionFallbacks = {};
3807
3808// If transition is defined, check if css 3D transforms are supported, and if not, if a fallback is specified
3809$.mobile._maybeDegradeTransition = function( transition ) {
3810 if ( transition && !$.support.cssTransform3d && $.mobile.transitionFallbacks[ transition ] ) {
3811 transition = $.mobile.transitionFallbacks[ transition ];
3812 }
3813
3814 return transition;
3815};
3816
3817// Set the getMaxScrollForTransition to default if no implementation was set by user
3818$.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defaultGetMaxScrollForTransition;
3819})( jQuery, this );
3820
3821(function( $, undefined ) {
3822
3823 //define vars for interal use
3824 var $window = $.mobile.window,
3825 $html = $( 'html' ),
3826 $head = $( 'head' ),
3827
3828 // NOTE: path extensions dependent on core attributes. Moved here to remove deps from
3829 // $.mobile.path definition
3830 path = $.extend($.mobile.path, {
3831
3832 //return the substring of a filepath before the sub-page key, for making a server request
3833 getFilePath: function( path ) {
3834 var splitkey = '&' + $.mobile.subPageUrlKey;
3835 return path && path.split( splitkey )[0].split( dialogHashKey )[0];
3836 },
3837
3838 //check if the specified url refers to the first page in the main application document.
3839 isFirstPageUrl: function( url ) {
3840 // We only deal with absolute paths.
3841 var u = path.parseUrl( path.makeUrlAbsolute( url, this.documentBase ) ),
3842
3843 // Does the url have the same path as the document?
3844 samePath = u.hrefNoHash === this.documentUrl.hrefNoHash || ( this.documentBaseDiffers && u.hrefNoHash === this.documentBase.hrefNoHash ),
3845
3846 // Get the first page element.
3847 fp = $.mobile.firstPage,
3848
3849 // Get the id of the first page element if it has one.
3850 fpId = fp && fp[0] ? fp[0].id : undefined;
3851
3852 // The url refers to the first page if the path matches the document and
3853 // it either has no hash value, or the hash is exactly equal to the id of the
3854 // first page element.
3855 return samePath && ( !u.hash || u.hash === "#" || ( fpId && u.hash.replace( /^#/, "" ) === fpId ) );
3856 },
3857
3858 // Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
3859 // requests if the document doing the request was loaded via the file:// protocol.
3860 // This is usually to allow the application to "phone home" and fetch app specific
3861 // data. We normally let the browser handle external/cross-domain urls, but if the
3862 // allowCrossDomainPages option is true, we will allow cross-domain http/https
3863 // requests to go through our page loading logic.
3864 isPermittedCrossDomainRequest: function( docUrl, reqUrl ) {
3865 return $.mobile.allowCrossDomainPages &&
3866 docUrl.protocol === "file:" &&
3867 reqUrl.search( /^https?:/ ) !== -1;
3868 }
3869 }),
3870
3871 //will be defined when a link is clicked and given an active class
3872 $activeClickedLink = null,
3873
3874 // resolved on domready
3875 domreadyDeferred = $.Deferred(),
3876
3877 //urlHistory is purely here to make guesses at whether the back or forward button was clicked
3878 //and provide an appropriate transition
3879 urlHistory = $.mobile.navigate.history,
3880
3881 //define first selector to receive focus when a page is shown
3882 focusable = "[tabindex],a,button:visible,select:visible,input",
3883
3884 //queue to hold simultanious page transitions
3885 pageTransitionQueue = [],
3886
3887 //indicates whether or not page is in process of transitioning
3888 isPageTransitioning = false,
3889
3890 //nonsense hash change key for dialogs, so they create a history entry
3891 dialogHashKey = "&ui-state=dialog",
3892
3893 //existing base tag?
3894 $base = $head.children( "base" ),
3895
3896 //tuck away the original document URL minus any fragment.
3897 documentUrl = path.documentUrl,
3898
3899 //if the document has an embedded base tag, documentBase is set to its
3900 //initial value. If a base tag does not exist, then we default to the documentUrl.
3901 documentBase = path.documentBase,
3902
3903 //cache the comparison once.
3904 documentBaseDiffers = path.documentBaseDiffers,
3905
3906 getScreenHeight = $.mobile.getScreenHeight;
3907
3908 //base element management, defined depending on dynamic base tag support
3909 var base = $.support.dynamicBaseTag ? {
3910
3911 //define base element, for use in routing asset urls that are referenced in Ajax-requested markup
3912 element: ( $base.length ? $base : $( "<base>", { href: documentBase.hrefNoHash } ).prependTo( $head ) ),
3913
3914 //set the generated BASE element's href attribute to a new page's base path
3915 set: function( href ) {
3916 href = path.parseUrl(href).hrefNoHash;
3917 base.element.attr( "href", path.makeUrlAbsolute( href, documentBase ) );
3918 },
3919
3920 //set the generated BASE element's href attribute to a new page's base path
3921 reset: function() {
3922 base.element.attr( "href", documentBase.hrefNoSearch );
3923 }
3924
3925 } : undefined;
3926
3927
3928 //return the original document url
3929 $.mobile.getDocumentUrl = path.getDocumentUrl;
3930
3931 //return the original document base url
3932 $.mobile.getDocumentBase = path.getDocumentBase;
3933
3934 /* internal utility functions */
3935
3936 // NOTE Issue #4950 Android phonegap doesn't navigate back properly
3937 // when a full page refresh has taken place. It appears that hashchange
3938 // and replacestate history alterations work fine but we need to support
3939 // both forms of history traversal in our code that uses backward history
3940 // movement
3941 $.mobile.back = function() {
3942 var nav = window.navigator;
3943
3944 // if the setting is on and the navigator object is
3945 // available use the phonegap navigation capability
3946 if( this.phonegapNavigationEnabled &&
3947 nav &&
3948 nav.app &&
3949 nav.app.backHistory ){
3950 nav.app.backHistory();
3951 } else {
3952 window.history.back();
3953 }
3954 };
3955
3956 //direct focus to the page title, or otherwise first focusable element
3957 $.mobile.focusPage = function ( page ) {
3958 var autofocus = page.find( "[autofocus]" ),
3959 pageTitle = page.find( ".ui-title:eq(0)" );
3960
3961 if ( autofocus.length ) {
3962 autofocus.focus();
3963 return;
3964 }
3965
3966 if ( pageTitle.length ) {
3967 pageTitle.focus();
3968 } else{
3969 page.focus();
3970 }
3971 };
3972
3973 //remove active classes after page transition or error
3974 function removeActiveLinkClass( forceRemoval ) {
3975 if ( !!$activeClickedLink && ( !$activeClickedLink.closest( "." + $.mobile.activePageClass ).length || forceRemoval ) ) {
3976 $activeClickedLink.removeClass( $.mobile.activeBtnClass );
3977 }
3978 $activeClickedLink = null;
3979 }
3980
3981 function releasePageTransitionLock() {
3982 isPageTransitioning = false;
3983 if ( pageTransitionQueue.length > 0 ) {
3984 $.mobile.changePage.apply( null, pageTransitionQueue.pop() );
3985 }
3986 }
3987
3988 // Save the last scroll distance per page, before it is hidden
3989 var setLastScrollEnabled = true,
3990 setLastScroll, delayedSetLastScroll;
3991
3992 setLastScroll = function() {
3993 // this barrier prevents setting the scroll value based on the browser
3994 // scrolling the window based on a hashchange
3995 if ( !setLastScrollEnabled ) {
3996 return;
3997 }
3998
3999 var active = $.mobile.urlHistory.getActive();
4000
4001 if ( active ) {
4002 var lastScroll = $window.scrollTop();
4003
4004 // Set active page's lastScroll prop.
4005 // If the location we're scrolling to is less than minScrollBack, let it go.
4006 active.lastScroll = lastScroll < $.mobile.minScrollBack ? $.mobile.defaultHomeScroll : lastScroll;
4007 }
4008 };
4009
4010 // bind to scrollstop to gather scroll position. The delay allows for the hashchange
4011 // event to fire and disable scroll recording in the case where the browser scrolls
4012 // to the hash targets location (sometimes the top of the page). once pagechange fires
4013 // getLastScroll is again permitted to operate
4014 delayedSetLastScroll = function() {
4015 setTimeout( setLastScroll, 100 );
4016 };
4017
4018 // disable an scroll setting when a hashchange has been fired, this only works
4019 // because the recording of the scroll position is delayed for 100ms after
4020 // the browser might have changed the position because of the hashchange
4021 $window.bind( $.support.pushState ? "popstate" : "hashchange", function() {
4022 setLastScrollEnabled = false;
4023 });
4024
4025 // handle initial hashchange from chrome :(
4026 $window.one( $.support.pushState ? "popstate" : "hashchange", function() {
4027 setLastScrollEnabled = true;
4028 });
4029
4030 // wait until the mobile page container has been determined to bind to pagechange
4031 $window.one( "pagecontainercreate", function() {
4032 // once the page has changed, re-enable the scroll recording
4033 $.mobile.pageContainer.bind( "pagechange", function() {
4034
4035 setLastScrollEnabled = true;
4036
4037 // remove any binding that previously existed on the get scroll
4038 // which may or may not be different than the scroll element determined for
4039 // this page previously
4040 $window.unbind( "scrollstop", delayedSetLastScroll );
4041
4042 // determine and bind to the current scoll element which may be the window
4043 // or in the case of touch overflow the element with touch overflow
4044 $window.bind( "scrollstop", delayedSetLastScroll );
4045 });
4046 });
4047
4048 // bind to scrollstop for the first page as "pagechange" won't be fired in that case
4049 $window.bind( "scrollstop", delayedSetLastScroll );
4050
4051 // No-op implementation of transition degradation
4052 $.mobile._maybeDegradeTransition = $.mobile._maybeDegradeTransition || function( transition ) {
4053 return transition;
4054 };
4055
4056 //function for transitioning between two existing pages
4057 function transitionPages( toPage, fromPage, transition, reverse ) {
4058 if ( fromPage ) {
4059 //trigger before show/hide events
4060 fromPage.data( "mobile-page" )._trigger( "beforehide", null, { nextPage: toPage } );
4061 }
4062
4063 toPage.data( "mobile-page" )._trigger( "beforeshow", null, { prevPage: fromPage || $( "" ) } );
4064
4065 //clear page loader
4066 $.mobile.hidePageLoadingMsg();
4067
4068 transition = $.mobile._maybeDegradeTransition( transition );
4069
4070 //find the transition handler for the specified transition. If there
4071 //isn't one in our transitionHandlers dictionary, use the default one.
4072 //call the handler immediately to kick-off the transition.
4073 var th = $.mobile.transitionHandlers[ transition || "default" ] || $.mobile.defaultTransitionHandler,
4074 promise = th( transition, reverse, toPage, fromPage );
4075
4076 promise.done(function() {
4077 //trigger show/hide events
4078 if ( fromPage ) {
4079 fromPage.data( "mobile-page" )._trigger( "hide", null, { nextPage: toPage } );
4080 }
4081
4082 //trigger pageshow, define prevPage as either fromPage or empty jQuery obj
4083 toPage.data( "mobile-page" )._trigger( "show", null, { prevPage: fromPage || $( "" ) } );
4084 });
4085
4086 return promise;
4087 }
4088
4089 //simply set the active page's minimum height to screen height, depending on orientation
4090 $.mobile.resetActivePageHeight = function resetActivePageHeight( height ) {
4091 var aPage = $( "." + $.mobile.activePageClass ),
4092 aPagePadT = parseFloat( aPage.css( "padding-top" ) ),
4093 aPagePadB = parseFloat( aPage.css( "padding-bottom" ) ),
4094 aPageBorderT = parseFloat( aPage.css( "border-top-width" ) ),
4095 aPageBorderB = parseFloat( aPage.css( "border-bottom-width" ) );
4096
4097 height = ( typeof height === "number" )? height : getScreenHeight();
4098
4099 aPage.css( "min-height", height - aPagePadT - aPagePadB - aPageBorderT - aPageBorderB );
4100 };
4101
4102 //shared page enhancements
4103 function enhancePage( $page, role ) {
4104 // If a role was specified, make sure the data-role attribute
4105 // on the page element is in sync.
4106 if ( role ) {
4107 $page.attr( "data-" + $.mobile.ns + "role", role );
4108 }
4109
4110 //run page plugin
4111 $page.page();
4112 }
4113
4114 // determine the current base url
4115 function findBaseWithDefault() {
4116 var closestBase = ( $.mobile.activePage && getClosestBaseUrl( $.mobile.activePage ) );
4117 return closestBase || documentBase.hrefNoHash;
4118 }
4119
4120 /* exposed $.mobile methods */
4121
4122 //animation complete callback
4123 $.fn.animationComplete = function( callback ) {
4124 if ( $.support.cssTransitions ) {
4125 return $( this ).one( 'webkitAnimationEnd animationend', callback );
4126 }
4127 else{
4128 // defer execution for consistency between webkit/non webkit
4129 setTimeout( callback, 0 );
4130 return $( this );
4131 }
4132 };
4133
4134 //expose path object on $.mobile
4135 $.mobile.path = path;
4136
4137 //expose base object on $.mobile
4138 $.mobile.base = base;
4139
4140 //history stack
4141 $.mobile.urlHistory = urlHistory;
4142
4143 $.mobile.dialogHashKey = dialogHashKey;
4144
4145 //enable cross-domain page support
4146 $.mobile.allowCrossDomainPages = false;
4147
4148 $.mobile._bindPageRemove = function() {
4149 var page = $( this );
4150
4151 // when dom caching is not enabled or the page is embedded bind to remove the page on hide
4152 if ( !page.data( "mobile-page" ).options.domCache &&
4153 page.is( ":jqmData(external-page='true')" ) ) {
4154
4155 page.bind( 'pagehide.remove', function( e ) {
4156 var $this = $( this ),
4157 prEvent = new $.Event( "pageremove" );
4158
4159 $this.trigger( prEvent );
4160
4161 if ( !prEvent.isDefaultPrevented() ) {
4162 $this.removeWithDependents();
4163 }
4164 });
4165 }
4166 };
4167
4168 // Load a page into the DOM.
4169 $.mobile.loadPage = function( url, options ) {
4170 // This function uses deferred notifications to let callers
4171 // know when the page is done loading, or if an error has occurred.
4172 var deferred = $.Deferred(),
4173
4174 // The default loadPage options with overrides specified by
4175 // the caller.
4176 settings = $.extend( {}, $.mobile.loadPage.defaults, options ),
4177
4178 // The DOM element for the page after it has been loaded.
4179 page = null,
4180
4181 // If the reloadPage option is true, and the page is already
4182 // in the DOM, dupCachedPage will be set to the page element
4183 // so that it can be removed after the new version of the
4184 // page is loaded off the network.
4185 dupCachedPage = null,
4186
4187 // The absolute version of the URL passed into the function. This
4188 // version of the URL may contain dialog/subpage params in it.
4189 absUrl = path.makeUrlAbsolute( url, findBaseWithDefault() );
4190
4191 // If the caller provided data, and we're using "get" request,
4192 // append the data to the URL.
4193 if ( settings.data && settings.type === "get" ) {
4194 absUrl = path.addSearchParams( absUrl, settings.data );
4195 settings.data = undefined;
4196 }
4197
4198 // If the caller is using a "post" request, reloadPage must be true
4199 if ( settings.data && settings.type === "post" ) {
4200 settings.reloadPage = true;
4201 }
4202
4203 // The absolute version of the URL minus any dialog/subpage params.
4204 // In otherwords the real URL of the page to be loaded.
4205 var fileUrl = path.getFilePath( absUrl ),
4206
4207 // The version of the Url actually stored in the data-url attribute of
4208 // the page. For embedded pages, it is just the id of the page. For pages
4209 // within the same domain as the document base, it is the site relative
4210 // path. For cross-domain pages (Phone Gap only) the entire absolute Url
4211 // used to load the page.
4212 dataUrl = path.convertUrlToDataUrl( absUrl );
4213
4214 // Make sure we have a pageContainer to work with.
4215 settings.pageContainer = settings.pageContainer || $.mobile.pageContainer;
4216
4217 // Check to see if the page already exists in the DOM.
4218 // NOTE do _not_ use the :jqmData psuedo selector because parenthesis
4219 // are a valid url char and it breaks on the first occurence
4220 page = settings.pageContainer.children( "[data-" + $.mobile.ns +"url='" + dataUrl + "']" );
4221
4222 // If we failed to find the page, check to see if the url is a
4223 // reference to an embedded page. If so, it may have been dynamically
4224 // injected by a developer, in which case it would be lacking a data-url
4225 // attribute and in need of enhancement.
4226 if ( page.length === 0 && dataUrl && !path.isPath( dataUrl ) ) {
4227 page = settings.pageContainer.children( "#" + dataUrl )
4228 .attr( "data-" + $.mobile.ns + "url", dataUrl )
4229 .jqmData( "url", dataUrl );
4230 }
4231
4232 // If we failed to find a page in the DOM, check the URL to see if it
4233 // refers to the first page in the application. If it isn't a reference
4234 // to the first page and refers to non-existent embedded page, error out.
4235 if ( page.length === 0 ) {
4236 if ( $.mobile.firstPage && path.isFirstPageUrl( fileUrl ) ) {
4237 // Check to make sure our cached-first-page is actually
4238 // in the DOM. Some user deployed apps are pruning the first
4239 // page from the DOM for various reasons, we check for this
4240 // case here because we don't want a first-page with an id
4241 // falling through to the non-existent embedded page error
4242 // case. If the first-page is not in the DOM, then we let
4243 // things fall through to the ajax loading code below so
4244 // that it gets reloaded.
4245 if ( $.mobile.firstPage.parent().length ) {
4246 page = $( $.mobile.firstPage );
4247 }
4248 } else if ( path.isEmbeddedPage( fileUrl ) ) {
4249 deferred.reject( absUrl, options );
4250 return deferred.promise();
4251 }
4252 }
4253
4254 // If the page we are interested in is already in the DOM,
4255 // and the caller did not indicate that we should force a
4256 // reload of the file, we are done. Otherwise, track the
4257 // existing page as a duplicated.
4258 if ( page.length ) {
4259 if ( !settings.reloadPage ) {
4260 enhancePage( page, settings.role );
4261 deferred.resolve( absUrl, options, page );
4262 return deferred.promise();
4263 }
4264 dupCachedPage = page;
4265 }
4266
4267 var mpc = settings.pageContainer,
4268 pblEvent = new $.Event( "pagebeforeload" ),
4269 triggerData = { url: url, absUrl: absUrl, dataUrl: dataUrl, deferred: deferred, options: settings };
4270
4271 // Let listeners know we're about to load a page.
4272 mpc.trigger( pblEvent, triggerData );
4273
4274 // If the default behavior is prevented, stop here!
4275 if ( pblEvent.isDefaultPrevented() ) {
4276 return deferred.promise();
4277 }
4278
4279 if ( settings.showLoadMsg ) {
4280
4281 // This configurable timeout allows cached pages a brief delay to load without showing a message
4282 var loadMsgDelay = setTimeout(function() {
4283 $.mobile.showPageLoadingMsg();
4284 }, settings.loadMsgDelay ),
4285
4286 // Shared logic for clearing timeout and removing message.
4287 hideMsg = function() {
4288
4289 // Stop message show timer
4290 clearTimeout( loadMsgDelay );
4291
4292 // Hide loading message
4293 $.mobile.hidePageLoadingMsg();
4294 };
4295 }
4296
4297 // Reset base to the default document base.
4298 if ( base ) {
4299 base.reset();
4300 }
4301
4302 if ( !( $.mobile.allowCrossDomainPages || path.isSameDomain( documentUrl, absUrl ) ) ) {
4303 deferred.reject( absUrl, options );
4304 } else {
4305 // Load the new page.
4306 $.ajax({
4307 url: fileUrl,
4308 type: settings.type,
4309 data: settings.data,
4310 dataType: "html",
4311 success: function( html, textStatus, xhr ) {
4312 //pre-parse html to check for a data-url,
4313 //use it as the new fileUrl, base path, etc
4314 var all = $( "<div></div>" ),
4315
4316 //page title regexp
4317 newPageTitle = html.match( /<title[^>]*>([^<]*)/ ) && RegExp.$1,
4318
4319 // TODO handle dialogs again
4320 pageElemRegex = new RegExp( "(<[^>]+\\bdata-" + $.mobile.ns + "role=[\"']?page[\"']?[^>]*>)" ),
4321 dataUrlRegex = new RegExp( "\\bdata-" + $.mobile.ns + "url=[\"']?([^\"'>]*)[\"']?" );
4322
4323
4324 // data-url must be provided for the base tag so resource requests can be directed to the
4325 // correct url. loading into a temprorary element makes these requests immediately
4326 if ( pageElemRegex.test( html ) &&
4327 RegExp.$1 &&
4328 dataUrlRegex.test( RegExp.$1 ) &&
4329 RegExp.$1 ) {
4330 url = fileUrl = path.getFilePath( $( "<div>" + RegExp.$1 + "</div>" ).text() );
4331 }
4332
4333 if ( base ) {
4334 base.set( fileUrl );
4335 }
4336
4337 //workaround to allow scripts to execute when included in page divs
4338 all.get( 0 ).innerHTML = html;
4339 page = all.find( ":jqmData(role='page'), :jqmData(role='dialog')" ).first();
4340
4341 //if page elem couldn't be found, create one and insert the body element's contents
4342 if ( !page.length ) {
4343 page = $( "<div data-" + $.mobile.ns + "role='page'>" + ( html.split( /<\/?body[^>]*>/gmi )[1] || "" ) + "</div>" );
4344 }
4345
4346 if ( newPageTitle && !page.jqmData( "title" ) ) {
4347 if ( ~newPageTitle.indexOf( "&" ) ) {
4348 newPageTitle = $( "<div>" + newPageTitle + "</div>" ).text();
4349 }
4350 page.jqmData( "title", newPageTitle );
4351 }
4352
4353 //rewrite src and href attrs to use a base url
4354 if ( !$.support.dynamicBaseTag ) {
4355 var newPath = path.get( fileUrl );
4356 page.find( "[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]" ).each(function() {
4357 var thisAttr = $( this ).is( '[href]' ) ? 'href' :
4358 $( this ).is( '[src]' ) ? 'src' : 'action',
4359 thisUrl = $( this ).attr( thisAttr );
4360
4361 // XXX_jblas: We need to fix this so that it removes the document
4362 // base URL, and then prepends with the new page URL.
4363 //if full path exists and is same, chop it - helps IE out
4364 thisUrl = thisUrl.replace( location.protocol + '//' + location.host + location.pathname, '' );
4365
4366 if ( !/^(\w+:|#|\/)/.test( thisUrl ) ) {
4367 $( this ).attr( thisAttr, newPath + thisUrl );
4368 }
4369 });
4370 }
4371
4372 //append to page and enhance
4373 // TODO taging a page with external to make sure that embedded pages aren't removed
4374 // by the various page handling code is bad. Having page handling code in many
4375 // places is bad. Solutions post 1.0
4376 page
4377 .attr( "data-" + $.mobile.ns + "url", path.convertUrlToDataUrl( fileUrl ) )
4378 .attr( "data-" + $.mobile.ns + "external-page", true )
4379 .appendTo( settings.pageContainer );
4380
4381 // wait for page creation to leverage options defined on widget
4382 page.one( 'pagecreate', $.mobile._bindPageRemove );
4383
4384 enhancePage( page, settings.role );
4385
4386 // Enhancing the page may result in new dialogs/sub pages being inserted
4387 // into the DOM. If the original absUrl refers to a sub-page, that is the
4388 // real page we are interested in.
4389 if ( absUrl.indexOf( "&" + $.mobile.subPageUrlKey ) > -1 ) {
4390 page = settings.pageContainer.children( "[data-" + $.mobile.ns +"url='" + dataUrl + "']" );
4391 }
4392
4393 // Remove loading message.
4394 if ( settings.showLoadMsg ) {
4395 hideMsg();
4396 }
4397
4398 // Add the page reference and xhr to our triggerData.
4399 triggerData.xhr = xhr;
4400 triggerData.textStatus = textStatus;
4401 triggerData.page = page;
4402
4403 // Let listeners know the page loaded successfully.
4404 settings.pageContainer.trigger( "pageload", triggerData );
4405
4406 deferred.resolve( absUrl, options, page, dupCachedPage );
4407 },
4408 error: function( xhr, textStatus, errorThrown ) {
4409 //set base back to current path
4410 if ( base ) {
4411 base.set( path.get() );
4412 }
4413
4414 // Add error info to our triggerData.
4415 triggerData.xhr = xhr;
4416 triggerData.textStatus = textStatus;
4417 triggerData.errorThrown = errorThrown;
4418
4419 var plfEvent = new $.Event( "pageloadfailed" );
4420
4421 // Let listeners know the page load failed.
4422 settings.pageContainer.trigger( plfEvent, triggerData );
4423
4424 // If the default behavior is prevented, stop here!
4425 // Note that it is the responsibility of the listener/handler
4426 // that called preventDefault(), to resolve/reject the
4427 // deferred object within the triggerData.
4428 if ( plfEvent.isDefaultPrevented() ) {
4429 return;
4430 }
4431
4432 // Remove loading message.
4433 if ( settings.showLoadMsg ) {
4434
4435 // Remove loading message.
4436 hideMsg();
4437
4438 // show error message
4439 $.mobile.showPageLoadingMsg( $.mobile.pageLoadErrorMessageTheme, $.mobile.pageLoadErrorMessage, true );
4440
4441 // hide after delay
4442 setTimeout( $.mobile.hidePageLoadingMsg, 1500 );
4443 }
4444
4445 deferred.reject( absUrl, options );
4446 }
4447 });
4448 }
4449
4450 return deferred.promise();
4451 };
4452
4453 $.mobile.loadPage.defaults = {
4454 type: "get",
4455 data: undefined,
4456 reloadPage: false,
4457 role: undefined, // By default we rely on the role defined by the @data-role attribute.
4458 showLoadMsg: false,
4459 pageContainer: undefined,
4460 loadMsgDelay: 50 // This delay allows loads that pull from browser cache to occur without showing the loading message.
4461 };
4462
4463 // Show a specific page in the page container.
4464 $.mobile.changePage = function( toPage, options ) {
4465 // If we are in the midst of a transition, queue the current request.
4466 // We'll call changePage() once we're done with the current transition to
4467 // service the request.
4468 if ( isPageTransitioning ) {
4469 pageTransitionQueue.unshift( arguments );
4470 return;
4471 }
4472
4473 var settings = $.extend( {}, $.mobile.changePage.defaults, options ), isToPageString;
4474
4475 // Make sure we have a pageContainer to work with.
4476 settings.pageContainer = settings.pageContainer || $.mobile.pageContainer;
4477
4478 // Make sure we have a fromPage.
4479 settings.fromPage = settings.fromPage || $.mobile.activePage;
4480
4481 isToPageString = (typeof toPage === "string");
4482
4483 var mpc = settings.pageContainer,
4484 pbcEvent = new $.Event( "pagebeforechange" ),
4485 triggerData = { toPage: toPage, options: settings };
4486
4487 // NOTE: preserve the original target as the dataUrl value will be simplified
4488 // eg, removing ui-state, and removing query params from the hash
4489 // this is so that users who want to use query params have access to them
4490 // in the event bindings for the page life cycle See issue #5085
4491 if ( isToPageString ) {
4492 // if the toPage is a string simply convert it
4493 triggerData.absUrl = path.makeUrlAbsolute( toPage, findBaseWithDefault() );
4494 } else {
4495 // if the toPage is a jQuery object grab the absolute url stored
4496 // in the loadPage callback where it exists
4497 triggerData.absUrl = toPage.data( 'absUrl' );
4498 }
4499
4500 // Let listeners know we're about to change the current page.
4501 mpc.trigger( pbcEvent, triggerData );
4502
4503 // If the default behavior is prevented, stop here!
4504 if ( pbcEvent.isDefaultPrevented() ) {
4505 return;
4506 }
4507
4508 // We allow "pagebeforechange" observers to modify the toPage in the trigger
4509 // data to allow for redirects. Make sure our toPage is updated.
4510 //
4511 // We also need to re-evaluate whether it is a string, because an object can
4512 // also be replaced by a string
4513
4514 toPage = triggerData.toPage;
4515 isToPageString = (typeof toPage === "string");
4516
4517 // Set the isPageTransitioning flag to prevent any requests from
4518 // entering this method while we are in the midst of loading a page
4519 // or transitioning.
4520 isPageTransitioning = true;
4521
4522 // If the caller passed us a url, call loadPage()
4523 // to make sure it is loaded into the DOM. We'll listen
4524 // to the promise object it returns so we know when
4525 // it is done loading or if an error ocurred.
4526 if ( isToPageString ) {
4527 // preserve the original target as the dataUrl value will be simplified
4528 // eg, removing ui-state, and removing query params from the hash
4529 // this is so that users who want to use query params have access to them
4530 // in the event bindings for the page life cycle See issue #5085
4531 settings.target = toPage;
4532
4533 $.mobile.loadPage( toPage, settings )
4534 .done(function( url, options, newPage, dupCachedPage ) {
4535 isPageTransitioning = false;
4536 options.duplicateCachedPage = dupCachedPage;
4537
4538 // store the original absolute url so that it can be provided
4539 // to events in the triggerData of the subsequent changePage call
4540 newPage.data( 'absUrl', triggerData.absUrl );
4541 $.mobile.changePage( newPage, options );
4542 })
4543 .fail(function( url, options ) {
4544 isPageTransitioning = false;
4545
4546 //clear out the active button state
4547 removeActiveLinkClass( true );
4548
4549 //release transition lock so navigation is free again
4550 releasePageTransitionLock();
4551 settings.pageContainer.trigger( "pagechangefailed", triggerData );
4552 });
4553 return;
4554 }
4555
4556 // If we are going to the first-page of the application, we need to make
4557 // sure settings.dataUrl is set to the application document url. This allows
4558 // us to avoid generating a document url with an id hash in the case where the
4559 // first-page of the document has an id attribute specified.
4560 if ( toPage[ 0 ] === $.mobile.firstPage[ 0 ] && !settings.dataUrl ) {
4561 settings.dataUrl = documentUrl.hrefNoHash;
4562 }
4563
4564 // The caller passed us a real page DOM element. Update our
4565 // internal state and then trigger a transition to the page.
4566 var fromPage = settings.fromPage,
4567 url = ( settings.dataUrl && path.convertUrlToDataUrl( settings.dataUrl ) ) || toPage.jqmData( "url" ),
4568 // The pageUrl var is usually the same as url, except when url is obscured as a dialog url. pageUrl always contains the file path
4569 pageUrl = url,
4570 fileUrl = path.getFilePath( url ),
4571 active = urlHistory.getActive(),
4572 activeIsInitialPage = urlHistory.activeIndex === 0,
4573 historyDir = 0,
4574 pageTitle = document.title,
4575 isDialog = settings.role === "dialog" || toPage.jqmData( "role" ) === "dialog";
4576
4577
4578 // By default, we prevent changePage requests when the fromPage and toPage
4579 // are the same element, but folks that generate content manually/dynamically
4580 // and reuse pages want to be able to transition to the same page. To allow
4581 // this, they will need to change the default value of allowSamePageTransition
4582 // to true, *OR*, pass it in as an option when they manually call changePage().
4583 // It should be noted that our default transition animations assume that the
4584 // formPage and toPage are different elements, so they may behave unexpectedly.
4585 // It is up to the developer that turns on the allowSamePageTransitiona option
4586 // to either turn off transition animations, or make sure that an appropriate
4587 // animation transition is used.
4588 if ( fromPage && fromPage[0] === toPage[0] && !settings.allowSamePageTransition ) {
4589 isPageTransitioning = false;
4590 mpc.trigger( "pagechange", triggerData );
4591
4592 // Even if there is no page change to be done, we should keep the urlHistory in sync with the hash changes
4593 if ( settings.fromHashChange ) {
4594 urlHistory.direct({ url: url });
4595 }
4596
4597 return;
4598 }
4599
4600 // We need to make sure the page we are given has already been enhanced.
4601 enhancePage( toPage, settings.role );
4602
4603 // If the changePage request was sent from a hashChange event, check to see if the
4604 // page is already within the urlHistory stack. If so, we'll assume the user hit
4605 // the forward/back button and will try to match the transition accordingly.
4606 if ( settings.fromHashChange ) {
4607 historyDir = options.direction === "back" ? -1 : 1;
4608 }
4609
4610 // Kill the keyboard.
4611 // XXX_jblas: We need to stop crawling the entire document to kill focus. Instead,
4612 // we should be tracking focus with a delegate() handler so we already have
4613 // the element in hand at this point.
4614 // Wrap this in a try/catch block since IE9 throw "Unspecified error" if document.activeElement
4615 // is undefined when we are in an IFrame.
4616 try {
4617 if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== 'body' ) {
4618 $( document.activeElement ).blur();
4619 } else {
4620 $( "input:focus, textarea:focus, select:focus" ).blur();
4621 }
4622 } catch( e ) {}
4623
4624 // Record whether we are at a place in history where a dialog used to be - if so, do not add a new history entry and do not change the hash either
4625 var alreadyThere = false;
4626
4627 // If we're displaying the page as a dialog, we don't want the url
4628 // for the dialog content to be used in the hash. Instead, we want
4629 // to append the dialogHashKey to the url of the current page.
4630 if ( isDialog && active ) {
4631 // on the initial page load active.url is undefined and in that case should
4632 // be an empty string. Moving the undefined -> empty string back into
4633 // urlHistory.addNew seemed imprudent given undefined better represents
4634 // the url state
4635
4636 // If we are at a place in history that once belonged to a dialog, reuse
4637 // this state without adding to urlHistory and without modifying the hash.
4638 // However, if a dialog is already displayed at this point, and we're
4639 // about to display another dialog, then we must add another hash and
4640 // history entry on top so that one may navigate back to the original dialog
4641 if ( active.url &&
4642 active.url.indexOf( dialogHashKey ) > -1 &&
4643 $.mobile.activePage &&
4644 !$.mobile.activePage.is( ".ui-dialog" ) &&
4645 urlHistory.activeIndex > 0 ) {
4646 settings.changeHash = false;
4647 alreadyThere = true;
4648 }
4649
4650 // Normally, we tack on a dialog hash key, but if this is the location of a stale dialog,
4651 // we reuse the URL from the entry
4652 url = ( active.url || "" );
4653
4654 // account for absolute urls instead of just relative urls use as hashes
4655 if( !alreadyThere && url.indexOf("#") > -1 ) {
4656 url += dialogHashKey;
4657 } else {
4658 url += "#" + dialogHashKey;
4659 }
4660
4661 // tack on another dialogHashKey if this is the same as the initial hash
4662 // this makes sure that a history entry is created for this dialog
4663 if ( urlHistory.activeIndex === 0 && url === urlHistory.initialDst ) {
4664 url += dialogHashKey;
4665 }
4666 }
4667
4668 // if title element wasn't found, try the page div data attr too
4669 // If this is a deep-link or a reload ( active === undefined ) then just use pageTitle
4670 var newPageTitle = ( !active )? pageTitle : toPage.jqmData( "title" ) || toPage.children( ":jqmData(role='header')" ).find( ".ui-title" ).getEncodedText();
4671 if ( !!newPageTitle && pageTitle === document.title ) {
4672 pageTitle = newPageTitle;
4673 }
4674 if ( !toPage.jqmData( "title" ) ) {
4675 toPage.jqmData( "title", pageTitle );
4676 }
4677
4678 // Make sure we have a transition defined.
4679 settings.transition = settings.transition ||
4680 ( ( historyDir && !activeIsInitialPage ) ? active.transition : undefined ) ||
4681 ( isDialog ? $.mobile.defaultDialogTransition : $.mobile.defaultPageTransition );
4682
4683 //add page to history stack if it's not back or forward
4684 if ( !historyDir && alreadyThere ) {
4685 urlHistory.getActive().pageUrl = pageUrl;
4686 }
4687
4688 // Set the location hash.
4689 if ( url && !settings.fromHashChange ) {
4690 var params;
4691
4692 // rebuilding the hash here since we loose it earlier on
4693 // TODO preserve the originally passed in path
4694 if( !path.isPath( url ) && url.indexOf( "#" ) < 0 ) {
4695 url = "#" + url;
4696 }
4697
4698 // TODO the property names here are just silly
4699 params = {
4700 transition: settings.transition,
4701 title: pageTitle,
4702 pageUrl: pageUrl,
4703 role: settings.role
4704 };
4705
4706 if ( settings.changeHash !== false && $.mobile.hashListeningEnabled ) {
4707 $.mobile.navigate( url, params, true);
4708 } else if ( toPage[ 0 ] !== $.mobile.firstPage[ 0 ] ) {
4709 $.mobile.navigate.history.add( url, params );
4710 }
4711 }
4712
4713 //set page title
4714 document.title = pageTitle;
4715
4716 //set "toPage" as activePage
4717 $.mobile.activePage = toPage;
4718
4719 // If we're navigating back in the URL history, set reverse accordingly.
4720 settings.reverse = settings.reverse || historyDir < 0;
4721
4722 transitionPages( toPage, fromPage, settings.transition, settings.reverse )
4723 .done(function( name, reverse, $to, $from, alreadyFocused ) {
4724 removeActiveLinkClass();
4725
4726 //if there's a duplicateCachedPage, remove it from the DOM now that it's hidden
4727 if ( settings.duplicateCachedPage ) {
4728 settings.duplicateCachedPage.remove();
4729 }
4730
4731 // Send focus to the newly shown page. Moved from promise .done binding in transitionPages
4732 // itself to avoid ie bug that reports offsetWidth as > 0 (core check for visibility)
4733 // despite visibility: hidden addresses issue #2965
4734 // https://github.com/jquery/jquery-mobile/issues/2965
4735 if ( !alreadyFocused ) {
4736 $.mobile.focusPage( toPage );
4737 }
4738
4739 releasePageTransitionLock();
4740 mpc.trigger( "pagechange", triggerData );
4741 });
4742 };
4743
4744 $.mobile.changePage.defaults = {
4745 transition: undefined,
4746 reverse: false,
4747 changeHash: true,
4748 fromHashChange: false,
4749 role: undefined, // By default we rely on the role defined by the @data-role attribute.
4750 duplicateCachedPage: undefined,
4751 pageContainer: undefined,
4752 showLoadMsg: true, //loading message shows by default when pages are being fetched during changePage
4753 dataUrl: undefined,
4754 fromPage: undefined,
4755 allowSamePageTransition: false
4756 };
4757
4758/* Event Bindings - hashchange, submit, and click */
4759 function findClosestLink( ele )
4760 {
4761 while ( ele ) {
4762 // Look for the closest element with a nodeName of "a".
4763 // Note that we are checking if we have a valid nodeName
4764 // before attempting to access it. This is because the
4765 // node we get called with could have originated from within
4766 // an embedded SVG document where some symbol instance elements
4767 // don't have nodeName defined on them, or strings are of type
4768 // SVGAnimatedString.
4769 if ( ( typeof ele.nodeName === "string" ) && ele.nodeName.toLowerCase() === "a" ) {
4770 break;
4771 }
4772 ele = ele.parentNode;
4773 }
4774 return ele;
4775 }
4776
4777 // The base URL for any given element depends on the page it resides in.
4778 function getClosestBaseUrl( ele )
4779 {
4780 // Find the closest page and extract out its url.
4781 var url = $( ele ).closest( ".ui-page" ).jqmData( "url" ),
4782 base = documentBase.hrefNoHash;
4783
4784 if ( !url || !path.isPath( url ) ) {
4785 url = base;
4786 }
4787
4788 return path.makeUrlAbsolute( url, base);
4789 }
4790
4791 function maybeCreateHiddenInput( $el ) {
4792 var type = $el.attr( "type" ),
4793 name = $el.attr( "name" );
4794
4795 if ( type !== "button" && type !== "reset" && name ) {
4796 // Add hidden input so the value of the clicked button will be recorded
4797 // in the submitted form data, but remove the hidden input from the form
4798 // after the value has been recorded so as to avoid multiple copies of it
4799 // preceding the original button.
4800 $.mobile.document.one( "submit",
4801 $.proxy( function() { this.remove(); },
4802 $( "<input>", {
4803 type: "hidden",
4804 name: $el.attr( "name" ),
4805 value: $el.attr( "value" )
4806 }).insertBefore( $el ) ) );
4807 }
4808 }
4809
4810 //The following event bindings should be bound after mobileinit has been triggered
4811 //the following deferred is resolved in the init file
4812 $.mobile.navreadyDeferred = $.Deferred();
4813 $.mobile._registerInternalEvents = function() {
4814 var getAjaxFormData = function( $form, calculateOnly ) {
4815 var type, target, url, ret = true;
4816 if ( !$.mobile.ajaxEnabled ||
4817 // test that the form is, itself, ajax false
4818 $form.is( ":jqmData(ajax='false')" ) ||
4819 // test that $.mobile.ignoreContentEnabled is set and
4820 // the form or one of it's parents is ajax=false
4821 !$form.jqmHijackable().length ) {
4822 return false;
4823 }
4824
4825 target = $form.attr( "target" );
4826 url = $form.attr( "action" );
4827
4828 // If no action is specified, browsers default to using the
4829 // URL of the document containing the form. Since we dynamically
4830 // pull in pages from external documents, the form should submit
4831 // to the URL for the source document of the page containing
4832 // the form.
4833 if ( !url ) {
4834 // Get the @data-url for the page containing the form.
4835 url = getClosestBaseUrl( $form );
4836 if ( url === documentBase.hrefNoHash ) {
4837 // The url we got back matches the document base,
4838 // which means the page must be an internal/embedded page,
4839 // so default to using the actual document url as a browser
4840 // would.
4841 url = documentUrl.hrefNoSearch;
4842 }
4843 }
4844
4845 url = path.makeUrlAbsolute( url, getClosestBaseUrl( $form ) );
4846
4847 if ( ( path.isExternal( url ) && !path.isPermittedCrossDomainRequest( documentUrl, url ) ) || target ) {
4848 return false;
4849 }
4850
4851 if ( !calculateOnly ) {
4852 type = $form.attr( "method" );
4853 ret = {
4854 url: url,
4855 options: {
4856 type: type && type.length && type.toLowerCase() || "get",
4857 data: $form.serialize(),
4858 transition:$form.jqmData( "transition" ),
4859 reverse:$form.jqmData( "direction" ) === "reverse",
4860 reloadPage:true
4861 }
4862 };
4863 }
4864
4865 return ret;
4866 };
4867
4868 //bind to form submit events, handle with Ajax
4869 $.mobile.document.delegate( "form", "submit", function( event ) {
4870 var formData = getAjaxFormData( $( this ) );
4871
4872 if ( formData ) {
4873 $.mobile.changePage( formData.url, formData.options );
4874 event.preventDefault();
4875 }
4876 });
4877
4878 //add active state on vclick
4879 $.mobile.document.bind( "vclick", function( event ) {
4880 var $btn, btnEls, target = event.target, needClosest = false;
4881 // if this isn't a left click we don't care. Its important to note
4882 // that when the virtual event is generated it will create the which attr
4883 if ( event.which > 1 || !$.mobile.linkBindingEnabled ) {
4884 return;
4885 }
4886
4887 // If this is a vclick on a button, we must make sure its value will be
4888 // recorded in the resulting form data by adding a hidden input that
4889 // carries the button's value
4890 maybeCreateHiddenInput( $( target ) );
4891
4892 // Try to find a target element to which the active class will be applied
4893 if ( $.data( target, "mobile-button" ) ) {
4894 // If the form will not be submitted via AJAX, do not add active class
4895 if ( !getAjaxFormData( $( target ).closest( "form" ), true ) ) {
4896 return;
4897 }
4898 // We will apply the active state to this button widget - the parent
4899 // of the input that was clicked will have the associated data
4900 if ( target.parentNode ) {
4901 target = target.parentNode;
4902 }
4903 } else {
4904 target = findClosestLink( target );
4905 if ( !( target && path.parseUrl( target.getAttribute( "href" ) || "#" ).hash !== "#" ) ) {
4906 return;
4907 }
4908
4909 // TODO teach $.mobile.hijackable to operate on raw dom elements so the
4910 // link wrapping can be avoided
4911 if ( !$( target ).jqmHijackable().length ) {
4912 return;
4913 }
4914 }
4915
4916 // Avoid calling .closest by using the data set during .buttonMarkup()
4917 // List items have the button data in the parent of the element clicked
4918 if ( !!~target.className.indexOf( "ui-link-inherit" ) ) {
4919 if ( target.parentNode ) {
4920 btnEls = $.data( target.parentNode, "buttonElements" );
4921 }
4922 // Otherwise, look for the data on the target itself
4923 } else {
4924 btnEls = $.data( target, "buttonElements" );
4925 }
4926 // If found, grab the button's outer element
4927 if ( btnEls ) {
4928 target = btnEls.outer;
4929 } else {
4930 needClosest = true;
4931 }
4932
4933 $btn = $( target );
4934 // If the outer element wasn't found by the our heuristics, use .closest()
4935 if ( needClosest ) {
4936 $btn = $btn.closest( ".ui-btn" );
4937 }
4938
4939 if ( $btn.length > 0 && !$btn.hasClass( "ui-disabled" ) ) {
4940 removeActiveLinkClass( true );
4941 $activeClickedLink = $btn;
4942 $activeClickedLink.addClass( $.mobile.activeBtnClass );
4943 }
4944 });
4945
4946 // click routing - direct to HTTP or Ajax, accordingly
4947 $.mobile.document.bind( "click", function( event ) {
4948 if ( !$.mobile.linkBindingEnabled || event.isDefaultPrevented() ) {
4949 return;
4950 }
4951
4952 var link = findClosestLink( event.target ), $link = $( link ), httpCleanup;
4953
4954 // If there is no link associated with the click or its not a left
4955 // click we want to ignore the click
4956 // TODO teach $.mobile.hijackable to operate on raw dom elements so the link wrapping
4957 // can be avoided
4958 if ( !link || event.which > 1 || !$link.jqmHijackable().length ) {
4959 return;
4960 }
4961
4962 //remove active link class if external (then it won't be there if you come back)
4963 httpCleanup = function() {
4964 window.setTimeout(function() { removeActiveLinkClass( true ); }, 200 );
4965 };
4966
4967 //if there's a data-rel=back attr, go back in history
4968 if ( $link.is( ":jqmData(rel='back')" ) ) {
4969 $.mobile.back();
4970 return false;
4971 }
4972
4973 var baseUrl = getClosestBaseUrl( $link ),
4974
4975 //get href, if defined, otherwise default to empty hash
4976 href = path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );
4977
4978 //if ajax is disabled, exit early
4979 if ( !$.mobile.ajaxEnabled && !path.isEmbeddedPage( href ) ) {
4980 httpCleanup();
4981 //use default click handling
4982 return;
4983 }
4984
4985 // XXX_jblas: Ideally links to application pages should be specified as
4986 // an url to the application document with a hash that is either
4987 // the site relative path or id to the page. But some of the
4988 // internal code that dynamically generates sub-pages for nested
4989 // lists and select dialogs, just write a hash in the link they
4990 // create. This means the actual URL path is based on whatever
4991 // the current value of the base tag is at the time this code
4992 // is called. For now we are just assuming that any url with a
4993 // hash in it is an application page reference.
4994 if ( href.search( "#" ) !== -1 ) {
4995 href = href.replace( /[^#]*#/, "" );
4996 if ( !href ) {
4997 //link was an empty hash meant purely
4998 //for interaction, so we ignore it.
4999 event.preventDefault();
5000 return;
5001 } else if ( path.isPath( href ) ) {
5002 //we have apath so make it the href we want to load.
5003 href = path.makeUrlAbsolute( href, baseUrl );
5004 } else {
5005 //we have a simple id so use the documentUrl as its base.
5006 href = path.makeUrlAbsolute( "#" + href, documentUrl.hrefNoHash );
5007 }
5008 }
5009
5010 // Should we handle this link, or let the browser deal with it?
5011 var useDefaultUrlHandling = $link.is( "[rel='external']" ) || $link.is( ":jqmData(ajax='false')" ) || $link.is( "[target]" ),
5012
5013 // Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
5014 // requests if the document doing the request was loaded via the file:// protocol.
5015 // This is usually to allow the application to "phone home" and fetch app specific
5016 // data. We normally let the browser handle external/cross-domain urls, but if the
5017 // allowCrossDomainPages option is true, we will allow cross-domain http/https
5018 // requests to go through our page loading logic.
5019
5020 //check for protocol or rel and its not an embedded page
5021 //TODO overlap in logic from isExternal, rel=external check should be
5022 // moved into more comprehensive isExternalLink
5023 isExternal = useDefaultUrlHandling || ( path.isExternal( href ) && !path.isPermittedCrossDomainRequest( documentUrl, href ) );
5024
5025 if ( isExternal ) {
5026 httpCleanup();
5027 //use default click handling
5028 return;
5029 }
5030
5031 //use ajax
5032 var transition = $link.jqmData( "transition" ),
5033 reverse = $link.jqmData( "direction" ) === "reverse" ||
5034 // deprecated - remove by 1.0
5035 $link.jqmData( "back" ),
5036
5037 //this may need to be more specific as we use data-rel more
5038 role = $link.attr( "data-" + $.mobile.ns + "rel" ) || undefined;
5039
5040 $.mobile.changePage( href, { transition: transition, reverse: reverse, role: role, link: $link } );
5041 event.preventDefault();
5042 });
5043
5044 //prefetch pages when anchors with data-prefetch are encountered
5045 $.mobile.document.delegate( ".ui-page", "pageshow.prefetch", function() {
5046 var urls = [];
5047 $( this ).find( "a:jqmData(prefetch)" ).each(function() {
5048 var $link = $( this ),
5049 url = $link.attr( "href" );
5050
5051 if ( url && $.inArray( url, urls ) === -1 ) {
5052 urls.push( url );
5053
5054 $.mobile.loadPage( url, { role: $link.attr( "data-" + $.mobile.ns + "rel" ) } );
5055 }
5056 });
5057 });
5058
5059 $.mobile._handleHashChange = function( url, data ) {
5060 //find first page via hash
5061 var to = path.stripHash(url),
5062 //transition is false if it's the first page, undefined otherwise (and may be overridden by default)
5063 transition = $.mobile.urlHistory.stack.length === 0 ? "none" : undefined,
5064
5065 // default options for the changPage calls made after examining the current state
5066 // of the page and the hash, NOTE that the transition is derived from the previous
5067 // history entry
5068 changePageOptions = {
5069 changeHash: false,
5070 fromHashChange: true,
5071 reverse: data.direction === "back"
5072 };
5073
5074 $.extend( changePageOptions, data, {
5075 transition: (urlHistory.getLast() || {}).transition || transition
5076 });
5077
5078 // special case for dialogs
5079 if ( urlHistory.activeIndex > 0 && to.indexOf( dialogHashKey ) > -1 && urlHistory.initialDst !== to ) {
5080
5081 // If current active page is not a dialog skip the dialog and continue
5082 // in the same direction
5083 if ( $.mobile.activePage && !$.mobile.activePage.is( ".ui-dialog" ) ) {
5084 //determine if we're heading forward or backward and continue accordingly past
5085 //the current dialog
5086 if( data.direction === "back" ) {
5087 $.mobile.back();
5088 } else {
5089 window.history.forward();
5090 }
5091
5092 // prevent changePage call
5093 return;
5094 } else {
5095 // if the current active page is a dialog and we're navigating
5096 // to a dialog use the dialog objected saved in the stack
5097 to = data.pageUrl;
5098 var active = $.mobile.urlHistory.getActive();
5099
5100 // make sure to set the role, transition and reversal
5101 // as most of this is lost by the domCache cleaning
5102 $.extend( changePageOptions, {
5103 role: active.role,
5104 transition: active.transition,
5105 reverse: data.direction === "back"
5106 });
5107 }
5108 }
5109
5110 //if to is defined, load it
5111 if ( to ) {
5112 // At this point, 'to' can be one of 3 things, a cached page element from
5113 // a history stack entry, an id, or site-relative/absolute URL. If 'to' is
5114 // an id, we need to resolve it against the documentBase, not the location.href,
5115 // since the hashchange could've been the result of a forward/backward navigation
5116 // that crosses from an external page/dialog to an internal page/dialog.
5117 to = !path.isPath( to ) ? ( path.makeUrlAbsolute( '#' + to, documentBase ) ) : to;
5118
5119 // If we're about to go to an initial URL that contains a reference to a non-existent
5120 // internal page, go to the first page instead. We know that the initial hash refers to a
5121 // non-existent page, because the initial hash did not end up in the initial urlHistory entry
5122 if ( to === path.makeUrlAbsolute( '#' + urlHistory.initialDst, documentBase ) &&
5123 urlHistory.stack.length && urlHistory.stack[0].url !== urlHistory.initialDst.replace( dialogHashKey, "" ) ) {
5124 to = $.mobile.firstPage;
5125 }
5126
5127 $.mobile.changePage( to, changePageOptions );
5128 }else {
5129
5130 //there's no hash, go to the first page in the dom
5131 $.mobile.changePage( $.mobile.firstPage, changePageOptions );
5132 }
5133 };
5134
5135 // TODO roll the logic here into the handleHashChange method
5136 $window.bind( "navigate", function( e, data ) {
5137 var url = $.event.special.navigate.originalEventName.indexOf( "hashchange" ) > -1 ? data.state.hash : data.state.url;
5138
5139 if( !url ) {
5140 url = $.mobile.path.parseLocation().hash;
5141 }
5142
5143 if( !url || url === "#" || url.indexOf( "#" + $.mobile.path.uiStateKey ) === 0 ){
5144 url = location.href;
5145 }
5146
5147 $.mobile._handleHashChange( url, data.state );
5148 });
5149
5150 //set page min-heights to be device specific
5151 $.mobile.document.bind( "pageshow", $.mobile.resetActivePageHeight );
5152 $.mobile.window.bind( "throttledresize", $.mobile.resetActivePageHeight );
5153
5154 };//navreadyDeferred done callback
5155
5156 $( function() { domreadyDeferred.resolve(); } );
5157
5158 $.when( domreadyDeferred, $.mobile.navreadyDeferred ).done( function() { $.mobile._registerInternalEvents(); } );
5159})( jQuery );
5160
5161/*
5162* fallback transition for flip in non-3D supporting browsers (which tend to handle complex transitions poorly in general
5163*/
5164
5165(function( $, window, undefined ) {
5166
5167$.mobile.transitionFallbacks.flip = "fade";
5168
5169})( jQuery, this );
5170/*
5171* fallback transition for flow in non-3D supporting browsers (which tend to handle complex transitions poorly in general
5172*/
5173
5174(function( $, window, undefined ) {
5175
5176$.mobile.transitionFallbacks.flow = "fade";
5177
5178})( jQuery, this );
5179/*
5180* fallback transition for pop in non-3D supporting browsers (which tend to handle complex transitions poorly in general
5181*/
5182
5183(function( $, window, undefined ) {
5184
5185$.mobile.transitionFallbacks.pop = "fade";
5186
5187})( jQuery, this );
5188/*
5189* fallback transition for slide in non-3D supporting browsers (which tend to handle complex transitions poorly in general
5190*/
5191
5192(function( $, window, undefined ) {
5193
5194// Use the simultaneous transitions handler for slide transitions
5195$.mobile.transitionHandlers.slide = $.mobile.transitionHandlers.simultaneous;
5196
5197// Set the slide transitions's fallback to "fade"
5198$.mobile.transitionFallbacks.slide = "fade";
5199
5200})( jQuery, this );
5201/*
5202* fallback transition for slidedown in non-3D supporting browsers (which tend to handle complex transitions poorly in general
5203*/
5204
5205(function( $, window, undefined ) {
5206
5207$.mobile.transitionFallbacks.slidedown = "fade";
5208
5209})( jQuery, this );
5210/*
5211* fallback transition for slidefade in non-3D supporting browsers (which tend to handle complex transitions poorly in general
5212*/
5213
5214(function( $, window, undefined ) {
5215
5216// Set the slide transitions's fallback to "fade"
5217$.mobile.transitionFallbacks.slidefade = "fade";
5218
5219})( jQuery, this );
5220/*
5221* fallback transition for slideup in non-3D supporting browsers (which tend to handle complex transitions poorly in general
5222*/
5223
5224(function( $, window, undefined ) {
5225
5226$.mobile.transitionFallbacks.slideup = "fade";
5227
5228})( jQuery, this );
5229/*
5230* fallback transition for turn in non-3D supporting browsers (which tend to handle complex transitions poorly in general
5231*/
5232
5233(function( $, window, undefined ) {
5234
5235$.mobile.transitionFallbacks.turn = "fade";
5236
5237})( jQuery, this );
5238
5239(function( $, undefined ) {
5240
5241$.mobile.page.prototype.options.degradeInputs = {
5242 color: false,
5243 date: false,
5244 datetime: false,
5245 "datetime-local": false,
5246 email: false,
5247 month: false,
5248 number: false,
5249 range: "number",
5250 search: "text",
5251 tel: false,
5252 time: false,
5253 url: false,
5254 week: false
5255};
5256
5257
5258//auto self-init widgets
5259$.mobile.document.bind( "pagecreate create", function( e ) {
5260
5261 var page = $.mobile.closestPageData( $( e.target ) ), options;
5262
5263 if ( !page ) {
5264 return;
5265 }
5266
5267 options = page.options;
5268
5269 // degrade inputs to avoid poorly implemented native functionality
5270 $( e.target ).find( "input" ).not( page.keepNativeSelector() ).each(function() {
5271 var $this = $( this ),
5272 type = this.getAttribute( "type" ),
5273 optType = options.degradeInputs[ type ] || "text";
5274
5275 if ( options.degradeInputs[ type ] ) {
5276 var html = $( "<div>" ).html( $this.clone() ).html(),
5277 // In IE browsers, the type sometimes doesn't exist in the cloned markup, so we replace the closing tag instead
5278 hasType = html.indexOf( " type=" ) > -1,
5279 findstr = hasType ? /\s+type=["']?\w+['"]?/ : /\/?>/,
5280 repstr = " type=\"" + optType + "\" data-" + $.mobile.ns + "type=\"" + type + "\"" + ( hasType ? "" : ">" );
5281
5282 $this.replaceWith( html.replace( findstr, repstr ) );
5283 }
5284 });
5285
5286});
5287
5288})( jQuery );
5289
5290(function( $, window, undefined ) {
5291
5292$.widget( "mobile.dialog", $.mobile.widget, {
5293 options: {
5294 closeBtn: "left",
5295 closeBtnText: "Close",
5296 overlayTheme: "a",
5297 corners: true,
5298 initSelector: ":jqmData(role='dialog')"
5299 },
5300
5301 // Override the theme set by the page plugin on pageshow
5302 _handlePageBeforeShow: function() {
5303 this._isCloseable = true;
5304 if ( this.options.overlayTheme ) {
5305 this.element
5306 .page( "removeContainerBackground" )
5307 .page( "setContainerBackground", this.options.overlayTheme );
5308 }
5309 },
5310
5311 _create: function() {
5312 var self = this,
5313 $el = this.element,
5314 cornerClass = !!this.options.corners ? " ui-corner-all" : "",
5315 dialogWrap = $( "<div/>", {
5316 "role" : "dialog",
5317 "class" : "ui-dialog-contain ui-overlay-shadow" + cornerClass
5318 });
5319
5320 $el.addClass( "ui-dialog ui-overlay-" + this.options.overlayTheme );
5321
5322 // Class the markup for dialog styling
5323 // Set aria role
5324 $el.wrapInner( dialogWrap );
5325
5326 /* bind events
5327 - clicks and submits should use the closing transition that the dialog opened with
5328 unless a data-transition is specified on the link/form
5329 - if the click was on the close button, or the link has a data-rel="back" it'll go back in history naturally
5330 */
5331 $el.bind( "vclick submit", function( event ) {
5332 var $target = $( event.target ).closest( event.type === "vclick" ? "a" : "form" ),
5333 active;
5334
5335 if ( $target.length && !$target.jqmData( "transition" ) ) {
5336
5337 active = $.mobile.urlHistory.getActive() || {};
5338
5339 $target.attr( "data-" + $.mobile.ns + "transition", ( active.transition || $.mobile.defaultDialogTransition ) )
5340 .attr( "data-" + $.mobile.ns + "direction", "reverse" );
5341 }
5342 });
5343
5344 this._on( $el, {
5345 pagebeforeshow: "_handlePageBeforeShow"
5346 });
5347
5348 $.extend( this, {
5349 _createComplete: false
5350 });
5351
5352 this._setCloseBtn( this.options.closeBtn );
5353 },
5354
5355 _setCloseBtn: function( value ) {
5356 var self = this, btn, location;
5357
5358 if ( this._headerCloseButton ) {
5359 this._headerCloseButton.remove();
5360 this._headerCloseButton = null;
5361 }
5362 if ( value !== "none" ) {
5363 // Sanitize value
5364 location = ( value === "left" ? "left" : "right" );
5365 btn = $( "<a href='#' class='ui-btn-" + location + "' data-" + $.mobile.ns + "icon='delete' data-" + $.mobile.ns + "iconpos='notext'>"+ this.options.closeBtnText + "</a>" );
5366 this.element.children().find( ":jqmData(role='header')" ).first().prepend( btn );
5367 if ( this._createComplete && $.fn.buttonMarkup ) {
5368 btn.buttonMarkup();
5369 }
5370 this._createComplete = true;
5371
5372 // this must be an anonymous function so that select menu dialogs can replace
5373 // the close method. This is a change from previously just defining data-rel=back
5374 // on the button and letting nav handle it
5375 //
5376 // Use click rather than vclick in order to prevent the possibility of unintentionally
5377 // reopening the dialog if the dialog opening item was directly under the close button.
5378 btn.bind( "click", function() {
5379 self.close();
5380 });
5381
5382 this._headerCloseButton = btn;
5383 }
5384 },
5385
5386 _setOption: function( key, value ) {
5387 if ( key === "closeBtn" ) {
5388 this._setCloseBtn( value );
5389 this._super( key, value );
5390 this.element.attr( "data-" + ( $.mobile.ns || "" ) + "close-btn", value );
5391 }
5392 },
5393
5394 // Close method goes back in history
5395 close: function() {
5396 var idx, dst, hist = $.mobile.navigate.history;
5397
5398 if ( this._isCloseable ) {
5399 this._isCloseable = false;
5400 // If the hash listening is enabled and there is at least one preceding history
5401 // entry it's ok to go back. Initial pages with the dialog hash state are an example
5402 // where the stack check is necessary
5403 if ( $.mobile.hashListeningEnabled && hist.activeIndex > 0 ) {
5404 $.mobile.back();
5405 } else {
5406 idx = Math.max( 0, hist.activeIndex - 1 );
5407 dst = hist.stack[ idx ].pageUrl || hist.stack[ idx ].url;
5408 hist.previousIndex = hist.activeIndex;
5409 hist.activeIndex = idx;
5410 if ( !$.mobile.path.isPath( dst ) ) {
5411 dst = $.mobile.path.makeUrlAbsolute( "#" + dst );
5412 }
5413
5414 $.mobile.changePage( dst, { direction: "back", changeHash: false, fromHashChange: true } );
5415 }
5416 }
5417 }
5418});
5419
5420//auto self-init widgets
5421$.mobile.document.delegate( $.mobile.dialog.prototype.options.initSelector, "pagecreate", function() {
5422 $.mobile.dialog.prototype.enhance( this );
5423});
5424
5425})( jQuery, this );
5426
5427(function( $, undefined ) {
5428
5429$.mobile.page.prototype.options.backBtnText = "Back";
5430$.mobile.page.prototype.options.addBackBtn = false;
5431$.mobile.page.prototype.options.backBtnTheme = null;
5432$.mobile.page.prototype.options.headerTheme = "a";
5433$.mobile.page.prototype.options.footerTheme = "a";
5434$.mobile.page.prototype.options.contentTheme = null;
5435
5436// NOTE bind used to force this binding to run before the buttonMarkup binding
5437// which expects .ui-footer top be applied in its gigantic selector
5438// TODO remove the buttonMarkup giant selector and move it to the various modules
5439// on which it depends
5440$.mobile.document.bind( "pagecreate", function( e ) {
5441 var $page = $( e.target ),
5442 o = $page.data( "mobile-page" ).options,
5443 pageRole = $page.jqmData( "role" ),
5444 pageTheme = o.theme;
5445
5446 $( ":jqmData(role='header'), :jqmData(role='footer'), :jqmData(role='content')", $page )
5447 .jqmEnhanceable()
5448 .each(function() {
5449
5450 var $this = $( this ),
5451 role = $this.jqmData( "role" ),
5452 theme = $this.jqmData( "theme" ),
5453 contentTheme = theme || o.contentTheme || ( pageRole === "dialog" && pageTheme ),
5454 $headeranchors,
5455 leftbtn,
5456 rightbtn,
5457 backBtn;
5458
5459 $this.addClass( "ui-" + role );
5460
5461 //apply theming and markup modifications to page,header,content,footer
5462 if ( role === "header" || role === "footer" ) {
5463
5464 var thisTheme = theme || ( role === "header" ? o.headerTheme : o.footerTheme ) || pageTheme;
5465
5466 $this
5467 //add theme class
5468 .addClass( "ui-bar-" + thisTheme )
5469 // Add ARIA role
5470 .attr( "role", role === "header" ? "banner" : "contentinfo" );
5471
5472 if ( role === "header") {
5473 // Right,left buttons
5474 $headeranchors= $this.children( "a, button" );
5475 leftbtn= $headeranchors.hasClass( "ui-btn-left" );
5476 rightbtn = $headeranchors.hasClass( "ui-btn-right" );
5477
5478 leftbtn = leftbtn || $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
5479
5480 rightbtn = rightbtn || $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
5481 }
5482
5483 // Auto-add back btn on pages beyond first view
5484 if ( o.addBackBtn &&
5485 role === "header" &&
5486 $( ".ui-page" ).length > 1 &&
5487 $page.jqmData( "url" ) !== $.mobile.path.stripHash( location.hash ) &&
5488 !leftbtn ) {
5489
5490 backBtn = $( "<a href='javascript:void(0);' class='ui-btn-left' data-"+ $.mobile.ns +"rel='back' data-"+ $.mobile.ns +"icon='arrow-l'>"+ o.backBtnText +"</a>" )
5491 // If theme is provided, override default inheritance
5492 .attr( "data-"+ $.mobile.ns +"theme", o.backBtnTheme || thisTheme )
5493 .prependTo( $this );
5494 }
5495
5496 // Page title
5497 $this.children( "h1, h2, h3, h4, h5, h6" )
5498 .addClass( "ui-title" )
5499 // Regardless of h element number in src, it becomes h1 for the enhanced page
5500 .attr({
5501 "role": "heading",
5502 "aria-level": "1"
5503 });
5504
5505 } else if ( role === "content" ) {
5506 if ( contentTheme ) {
5507 $this.addClass( "ui-body-" + ( contentTheme ) );
5508 }
5509
5510 // Add ARIA role
5511 $this.attr( "role", "main" );
5512 }
5513 });
5514});
5515
5516})( jQuery );
5517
5518(function( $, undefined ) {
5519
5520$.mobile.behaviors.addFirstLastClasses = {
5521 _getVisibles: function( $els, create ) {
5522 var visibles;
5523
5524 if ( create ) {
5525 visibles = $els.not( ".ui-screen-hidden" );
5526 } else {
5527 visibles = $els.filter( ":visible" );
5528 if ( visibles.length === 0 ) {
5529 visibles = $els.not( ".ui-screen-hidden" );
5530 }
5531 }
5532
5533 return visibles;
5534 },
5535
5536 _addFirstLastClasses: function( $els, $visibles, create ) {
5537 $els.removeClass( "ui-first-child ui-last-child" );
5538 $visibles.eq( 0 ).addClass( "ui-first-child" ).end().last().addClass( "ui-last-child" );
5539 if ( !create ) {
5540 this.element.trigger( "updatelayout" );
5541 }
5542 }
5543};
5544
5545})( jQuery );
5546
5547(function( $, undefined ) {
5548
5549// filter function removes whitespace between label and form element so we can use inline-block (nodeType 3 = text)
5550$.fn.fieldcontain = function( options ) {
5551 return this
5552 .addClass( "ui-field-contain ui-body ui-br" )
5553 .contents().filter( function() {
5554 return ( this.nodeType === 3 && !/\S/.test( this.nodeValue ) );
5555 }).remove();
5556};
5557
5558//auto self-init widgets
5559$( document ).bind( "pagecreate create", function( e ) {
5560 $( ":jqmData(role='fieldcontain')", e.target ).jqmEnhanceable().fieldcontain();
5561});
5562
5563})( jQuery );
5564
5565(function( $, undefined ) {
5566
5567$.fn.grid = function( options ) {
5568 return this.each(function() {
5569
5570 var $this = $( this ),
5571 o = $.extend({
5572 grid: null
5573 }, options ),
5574 $kids = $this.children(),
5575 gridCols = { solo:1, a:2, b:3, c:4, d:5 },
5576 grid = o.grid,
5577 iterator;
5578
5579 if ( !grid ) {
5580 if ( $kids.length <= 5 ) {
5581 for ( var letter in gridCols ) {
5582 if ( gridCols[ letter ] === $kids.length ) {
5583 grid = letter;
5584 }
5585 }
5586 } else {
5587 grid = "a";
5588 $this.addClass( "ui-grid-duo" );
5589 }
5590 }
5591 iterator = gridCols[grid];
5592
5593 $this.addClass( "ui-grid-" + grid );
5594
5595 $kids.filter( ":nth-child(" + iterator + "n+1)" ).addClass( "ui-block-a" );
5596
5597 if ( iterator > 1 ) {
5598 $kids.filter( ":nth-child(" + iterator + "n+2)" ).addClass( "ui-block-b" );
5599 }
5600 if ( iterator > 2 ) {
5601 $kids.filter( ":nth-child(" + iterator + "n+3)" ).addClass( "ui-block-c" );
5602 }
5603 if ( iterator > 3 ) {
5604 $kids.filter( ":nth-child(" + iterator + "n+4)" ).addClass( "ui-block-d" );
5605 }
5606 if ( iterator > 4 ) {
5607 $kids.filter( ":nth-child(" + iterator + "n+5)" ).addClass( "ui-block-e" );
5608 }
5609 });
5610};
5611})( jQuery );
5612
5613(function( $, undefined ) {
5614
5615$( document ).bind( "pagecreate create", function( e ) {
5616 $( ":jqmData(role='nojs')", e.target ).addClass( "ui-nojs" );
5617
5618});
5619
5620})( jQuery );
5621
5622(function( $, undefined ) {
5623
5624$.mobile.behaviors.formReset = {
5625 _handleFormReset: function() {
5626 this._on( this.element.closest( "form" ), {
5627 reset: function() {
5628 this._delay( "_reset" );
5629 }
5630 });
5631 }
5632};
5633
5634})( jQuery );
5635
5636(function( $, undefined ) {
5637
5638// This function calls getAttribute, which should be safe for data-* attributes
5639var getAttrFixed = function( e, key ) {
5640 var value = e.getAttribute( key );
5641
5642 return value === "true" ? true :
5643 value === "false" ? false :
5644 value === null ? undefined : value;
5645};
5646
5647$.fn.buttonMarkup = function( options ) {
5648 var $workingSet = this,
5649 nsKey = "data-" + $.mobile.ns,
5650 key;
5651
5652 // Enforce options to be of type string
5653 options = ( options && ( $.type( options ) === "object" ) )? options : {};
5654 for ( var i = 0; i < $workingSet.length; i++ ) {
5655 var el = $workingSet.eq( i ),
5656 e = el[ 0 ],
5657 o = $.extend( {}, $.fn.buttonMarkup.defaults, {
5658 icon: options.icon !== undefined ? options.icon : getAttrFixed( e, nsKey + "icon" ),
5659 iconpos: options.iconpos !== undefined ? options.iconpos : getAttrFixed( e, nsKey + "iconpos" ),
5660 theme: options.theme !== undefined ? options.theme : getAttrFixed( e, nsKey + "theme" ) || $.mobile.getInheritedTheme( el, "c" ),
5661 inline: options.inline !== undefined ? options.inline : getAttrFixed( e, nsKey + "inline" ),
5662 shadow: options.shadow !== undefined ? options.shadow : getAttrFixed( e, nsKey + "shadow" ),
5663 corners: options.corners !== undefined ? options.corners : getAttrFixed( e, nsKey + "corners" ),
5664 iconshadow: options.iconshadow !== undefined ? options.iconshadow : getAttrFixed( e, nsKey + "iconshadow" ),
5665 mini: options.mini !== undefined ? options.mini : getAttrFixed( e, nsKey + "mini" )
5666 }, options ),
5667
5668 // Classes Defined
5669 innerClass = "ui-btn-inner",
5670 textClass = "ui-btn-text",
5671 buttonClass, iconClass,
5672 hover = false,
5673 state = "up",
5674 // Button inner markup
5675 buttonInner,
5676 buttonText,
5677 buttonIcon,
5678 buttonElements;
5679
5680 for ( key in o ) {
5681 e.setAttribute( nsKey + key, o[ key ] );
5682 }
5683
5684 if ( getAttrFixed( e, nsKey + "rel" ) === "popup" && el.attr( "href" ) ) {
5685 e.setAttribute( "aria-haspopup", true );
5686 e.setAttribute( "aria-owns", el.attr( "href" ) );
5687 }
5688
5689 // Check if this element is already enhanced
5690 buttonElements = $.data( ( ( e.tagName === "INPUT" || e.tagName === "BUTTON" ) ? e.parentNode : e ), "buttonElements" );
5691
5692 if ( buttonElements ) {
5693 e = buttonElements.outer;
5694 el = $( e );
5695 buttonInner = buttonElements.inner;
5696 buttonText = buttonElements.text;
5697 // We will recreate this icon below
5698 $( buttonElements.icon ).remove();
5699 buttonElements.icon = null;
5700 hover = buttonElements.hover;
5701 state = buttonElements.state;
5702 }
5703 else {
5704 buttonInner = document.createElement( o.wrapperEls );
5705 buttonText = document.createElement( o.wrapperEls );
5706 }
5707 buttonIcon = o.icon ? document.createElement( "span" ) : null;
5708
5709 if ( attachEvents && !buttonElements ) {
5710 attachEvents();
5711 }
5712
5713 // if not, try to find closest theme container
5714 if ( !o.theme ) {
5715 o.theme = $.mobile.getInheritedTheme( el, "c" );
5716 }
5717
5718 buttonClass = "ui-btn ";
5719 buttonClass += ( hover ? "ui-btn-hover-" + o.theme : "" );
5720 buttonClass += ( state ? " ui-btn-" + state + "-" + o.theme : "" );
5721 buttonClass += o.shadow ? " ui-shadow" : "";
5722 buttonClass += o.corners ? " ui-btn-corner-all" : "";
5723
5724 if ( o.mini !== undefined ) {
5725 // Used to control styling in headers/footers, where buttons default to `mini` style.
5726 buttonClass += o.mini === true ? " ui-mini" : " ui-fullsize";
5727 }
5728
5729 if ( o.inline !== undefined ) {
5730 // Used to control styling in headers/footers, where buttons default to `inline` style.
5731 buttonClass += o.inline === true ? " ui-btn-inline" : " ui-btn-block";
5732 }
5733
5734 if ( o.icon ) {
5735 o.icon = "ui-icon-" + o.icon;
5736 o.iconpos = o.iconpos || "left";
5737
5738 iconClass = "ui-icon " + o.icon;
5739
5740 if ( o.iconshadow ) {
5741 iconClass += " ui-icon-shadow";
5742 }
5743 }
5744
5745 if ( o.iconpos ) {
5746 buttonClass += " ui-btn-icon-" + o.iconpos;
5747
5748 if ( o.iconpos === "notext" && !el.attr( "title" ) ) {
5749 el.attr( "title", el.getEncodedText() );
5750 }
5751 }
5752
5753 if ( o.iconpos && o.iconpos === "notext" && !el.attr( "title" ) ) {
5754 el.attr( "title", el.getEncodedText() );
5755 }
5756
5757 if ( buttonElements ) {
5758 el.removeClass( buttonElements.bcls || "" );
5759 }
5760 el.removeClass( "ui-link" ).addClass( buttonClass );
5761
5762 buttonInner.className = innerClass;
5763 buttonText.className = textClass;
5764 if ( !buttonElements ) {
5765 buttonInner.appendChild( buttonText );
5766 }
5767 if ( buttonIcon ) {
5768 buttonIcon.className = iconClass;
5769 if ( !( buttonElements && buttonElements.icon ) ) {
5770 buttonIcon.innerHTML = "&#160;";
5771 buttonInner.appendChild( buttonIcon );
5772 }
5773 }
5774
5775 while ( e.firstChild && !buttonElements ) {
5776 buttonText.appendChild( e.firstChild );
5777 }
5778
5779 if ( !buttonElements ) {
5780 e.appendChild( buttonInner );
5781 }
5782
5783 // Assign a structure containing the elements of this button to the elements of this button. This
5784 // will allow us to recognize this as an already-enhanced button in future calls to buttonMarkup().
5785 buttonElements = {
5786 hover : hover,
5787 state : state,
5788 bcls : buttonClass,
5789 outer : e,
5790 inner : buttonInner,
5791 text : buttonText,
5792 icon : buttonIcon
5793 };
5794
5795 $.data( e, 'buttonElements', buttonElements );
5796 $.data( buttonInner, 'buttonElements', buttonElements );
5797 $.data( buttonText, 'buttonElements', buttonElements );
5798 if ( buttonIcon ) {
5799 $.data( buttonIcon, 'buttonElements', buttonElements );
5800 }
5801 }
5802
5803 return this;
5804};
5805
5806$.fn.buttonMarkup.defaults = {
5807 corners: true,
5808 shadow: true,
5809 iconshadow: true,
5810 wrapperEls: "span"
5811};
5812
5813function closestEnabledButton( element ) {
5814 var cname;
5815
5816 while ( element ) {
5817 // Note that we check for typeof className below because the element we
5818 // handed could be in an SVG DOM where className on SVG elements is defined to
5819 // be of a different type (SVGAnimatedString). We only operate on HTML DOM
5820 // elements, so we look for plain "string".
5821 cname = ( typeof element.className === 'string' ) && ( element.className + ' ' );
5822 if ( cname && cname.indexOf( "ui-btn " ) > -1 && cname.indexOf( "ui-disabled " ) < 0 ) {
5823 break;
5824 }
5825
5826 element = element.parentNode;
5827 }
5828
5829 return element;
5830}
5831
5832function updateButtonClass( $btn, classToRemove, classToAdd, hover, state ) {
5833 var buttonElements = $.data( $btn[ 0 ], "buttonElements" );
5834 $btn.removeClass( classToRemove ).addClass( classToAdd );
5835 if ( buttonElements ) {
5836 buttonElements.bcls = $( document.createElement( "div" ) )
5837 .addClass( buttonElements.bcls + " " + classToAdd )
5838 .removeClass( classToRemove )
5839 .attr( "class" );
5840 if ( hover !== undefined ) {
5841 buttonElements.hover = hover;
5842 }
5843 buttonElements.state = state;
5844 }
5845}
5846
5847var attachEvents = function() {
5848 var hoverDelay = $.mobile.buttonMarkup.hoverDelay, hov, foc;
5849
5850 $.mobile.document.bind( {
5851 "vmousedown vmousecancel vmouseup vmouseover vmouseout focus blur scrollstart": function( event ) {
5852 var theme,
5853 $btn = $( closestEnabledButton( event.target ) ),
5854 isTouchEvent = event.originalEvent && /^touch/.test( event.originalEvent.type ),
5855 evt = event.type;
5856
5857 if ( $btn.length ) {
5858 theme = $btn.attr( "data-" + $.mobile.ns + "theme" );
5859
5860 if ( evt === "vmousedown" ) {
5861 if ( isTouchEvent ) {
5862 // Use a short delay to determine if the user is scrolling before highlighting
5863 hov = setTimeout( function() {
5864 updateButtonClass( $btn, "ui-btn-up-" + theme, "ui-btn-down-" + theme, undefined, "down" );
5865 }, hoverDelay );
5866 } else {
5867 updateButtonClass( $btn, "ui-btn-up-" + theme, "ui-btn-down-" + theme, undefined, "down" );
5868 }
5869 } else if ( evt === "vmousecancel" || evt === "vmouseup" ) {
5870 updateButtonClass( $btn, "ui-btn-down-" + theme, "ui-btn-up-" + theme, undefined, "up" );
5871 } else if ( evt === "vmouseover" || evt === "focus" ) {
5872 if ( isTouchEvent ) {
5873 // Use a short delay to determine if the user is scrolling before highlighting
5874 foc = setTimeout( function() {
5875 updateButtonClass( $btn, "ui-btn-up-" + theme, "ui-btn-hover-" + theme, true, "" );
5876 }, hoverDelay );
5877 } else {
5878 updateButtonClass( $btn, "ui-btn-up-" + theme, "ui-btn-hover-" + theme, true, "" );
5879 }
5880 } else if ( evt === "vmouseout" || evt === "blur" || evt === "scrollstart" ) {
5881 updateButtonClass( $btn, "ui-btn-hover-" + theme + " ui-btn-down-" + theme, "ui-btn-up-" + theme, false, "up" );
5882 if ( hov ) {
5883 clearTimeout( hov );
5884 }
5885 if ( foc ) {
5886 clearTimeout( foc );
5887 }
5888 }
5889 }
5890 },
5891 "focusin focus": function( event ) {
5892 $( closestEnabledButton( event.target ) ).addClass( $.mobile.focusClass );
5893 },
5894 "focusout blur": function( event ) {
5895 $( closestEnabledButton( event.target ) ).removeClass( $.mobile.focusClass );
5896 }
5897 });
5898
5899 attachEvents = null;
5900};
5901
5902//links in bars, or those with data-role become buttons
5903//auto self-init widgets
5904$.mobile.document.bind( "pagecreate create", function( e ) {
5905
5906 $( ":jqmData(role='button'), .ui-bar > a, .ui-header > a, .ui-footer > a, .ui-bar > :jqmData(role='controlgroup') > a", e.target )
5907 .jqmEnhanceable()
5908 .not( "button, input, .ui-btn, :jqmData(role='none'), :jqmData(role='nojs')" )
5909 .buttonMarkup();
5910});
5911
5912})( jQuery );
5913
5914
5915(function( $, undefined ) {
5916
5917$.widget( "mobile.collapsible", $.mobile.widget, {
5918 options: {
5919 expandCueText: " click to expand contents",
5920 collapseCueText: " click to collapse contents",
5921 collapsed: true,
5922 heading: "h1,h2,h3,h4,h5,h6,legend",
5923 collapsedIcon: "plus",
5924 expandedIcon: "minus",
5925 iconpos: "left",
5926 theme: null,
5927 contentTheme: null,
5928 inset: true,
5929 corners: true,
5930 mini: false,
5931 initSelector: ":jqmData(role='collapsible')"
5932 },
5933 _create: function() {
5934
5935 var $el = this.element,
5936 o = this.options,
5937 collapsible = $el.addClass( "ui-collapsible" ),
5938 collapsibleHeading = $el.children( o.heading ).first(),
5939 collapsibleContent = collapsible.wrapInner( "<div class='ui-collapsible-content'></div>" ).children( ".ui-collapsible-content" ),
5940 collapsibleSet = $el.closest( ":jqmData(role='collapsible-set')" ).addClass( "ui-collapsible-set" ),
5941 collapsibleClasses = "";
5942
5943 // Replace collapsibleHeading if it's a legend
5944 if ( collapsibleHeading.is( "legend" ) ) {
5945 collapsibleHeading = $( "<div role='heading'>"+ collapsibleHeading.html() +"</div>" ).insertBefore( collapsibleHeading );
5946 collapsibleHeading.next().remove();
5947 }
5948
5949 // If we are in a collapsible set
5950 if ( collapsibleSet.length ) {
5951 // Inherit the theme from collapsible-set
5952 if ( !o.theme ) {
5953 o.theme = collapsibleSet.jqmData( "theme" ) || $.mobile.getInheritedTheme( collapsibleSet, "c" );
5954 }
5955 // Inherit the content-theme from collapsible-set
5956 if ( !o.contentTheme ) {
5957 o.contentTheme = collapsibleSet.jqmData( "content-theme" );
5958 }
5959
5960 // Get the preference for collapsed icon in the set, but override with data- attribute on the individual collapsible
5961 o.collapsedIcon = $el.jqmData( "collapsed-icon" ) || collapsibleSet.jqmData( "collapsed-icon" ) || o.collapsedIcon;
5962
5963 // Get the preference for expanded icon in the set, but override with data- attribute on the individual collapsible
5964 o.expandedIcon = $el.jqmData( "expanded-icon" ) || collapsibleSet.jqmData( "expanded-icon" ) || o.expandedIcon;
5965
5966 // Gets the preference icon position in the set, but override with data- attribute on the individual collapsible
5967 o.iconpos = $el.jqmData( "iconpos" ) || collapsibleSet.jqmData( "iconpos" ) || o.iconpos;
5968
5969 // Inherit the preference for inset from collapsible-set or set the default value to ensure equalty within a set
5970 if ( collapsibleSet.jqmData( "inset" ) !== undefined ) {
5971 o.inset = collapsibleSet.jqmData( "inset" );
5972 } else {
5973 o.inset = true;
5974 }
5975 // Set corners for individual collapsibles to false when in a collapsible-set
5976 o.corners = false;
5977 // Gets the preference for mini in the set
5978 if ( !o.mini ) {
5979 o.mini = collapsibleSet.jqmData( "mini" );
5980 }
5981 } else {
5982 // get inherited theme if not a set and no theme has been set
5983 if ( !o.theme ) {
5984 o.theme = $.mobile.getInheritedTheme( $el, "c" );
5985 }
5986 }
5987
5988 if ( !!o.inset ) {
5989 collapsibleClasses += " ui-collapsible-inset";
5990 if ( !!o.corners ) {
5991 collapsibleClasses += " ui-corner-all" ;
5992 }
5993 }
5994 if ( o.contentTheme ) {
5995 collapsibleClasses += " ui-collapsible-themed-content";
5996 collapsibleContent.addClass( "ui-body-" + o.contentTheme );
5997 }
5998 if ( collapsibleClasses !== "" ) {
5999 collapsible.addClass( collapsibleClasses );
6000 }
6001
6002 collapsibleHeading
6003 //drop heading in before content
6004 .insertBefore( collapsibleContent )
6005 //modify markup & attributes
6006 .addClass( "ui-collapsible-heading" )
6007 .append( "<span class='ui-collapsible-heading-status'></span>" )
6008 .wrapInner( "<a href='#' class='ui-collapsible-heading-toggle'></a>" )
6009 .find( "a" )
6010 .first()
6011 .buttonMarkup({
6012 shadow: false,
6013 corners: false,
6014 iconpos: o.iconpos,
6015 icon: o.collapsedIcon,
6016 mini: o.mini,
6017 theme: o.theme
6018 });
6019
6020 //events
6021 collapsible
6022 .bind( "expand collapse", function( event ) {
6023 if ( !event.isDefaultPrevented() ) {
6024 var $this = $( this ),
6025 isCollapse = ( event.type === "collapse" );
6026
6027 event.preventDefault();
6028
6029 collapsibleHeading
6030 .toggleClass( "ui-collapsible-heading-collapsed", isCollapse )
6031 .find( ".ui-collapsible-heading-status" )
6032 .text( isCollapse ? o.expandCueText : o.collapseCueText )
6033 .end()
6034 .find( ".ui-icon" )
6035 .toggleClass( "ui-icon-" + o.expandedIcon, !isCollapse )
6036 // logic or cause same icon for expanded/collapsed state would remove the ui-icon-class
6037 .toggleClass( "ui-icon-" + o.collapsedIcon, ( isCollapse || o.expandedIcon === o.collapsedIcon ) )
6038 .end()
6039 .find( "a" ).first().removeClass( $.mobile.activeBtnClass );
6040
6041 $this.toggleClass( "ui-collapsible-collapsed", isCollapse );
6042 collapsibleContent.toggleClass( "ui-collapsible-content-collapsed", isCollapse ).attr( "aria-hidden", isCollapse );
6043
6044 collapsibleContent.trigger( "updatelayout" );
6045 }
6046 })
6047 .trigger( o.collapsed ? "collapse" : "expand" );
6048
6049 collapsibleHeading
6050 .bind( "tap", function( event ) {
6051 collapsibleHeading.find( "a" ).first().addClass( $.mobile.activeBtnClass );
6052 })
6053 .bind( "click", function( event ) {
6054
6055 var type = collapsibleHeading.is( ".ui-collapsible-heading-collapsed" ) ? "expand" : "collapse";
6056
6057 collapsible.trigger( type );
6058
6059 event.preventDefault();
6060 event.stopPropagation();
6061 });
6062 }
6063});
6064
6065//auto self-init widgets
6066$.mobile.document.bind( "pagecreate create", function( e ) {
6067 $.mobile.collapsible.prototype.enhanceWithin( e.target );
6068});
6069
6070})( jQuery );
6071
6072(function( $, undefined ) {
6073
6074$.widget( "mobile.collapsibleset", $.mobile.widget, {
6075 options: {
6076 initSelector: ":jqmData(role='collapsible-set')"
6077 },
6078 _create: function() {
6079 var $el = this.element.addClass( "ui-collapsible-set" ),
6080 o = this.options;
6081
6082 // Inherit the theme from collapsible-set
6083 if ( !o.theme ) {
6084 o.theme = $.mobile.getInheritedTheme( $el, "c" );
6085 }
6086 // Inherit the content-theme from collapsible-set
6087 if ( !o.contentTheme ) {
6088 o.contentTheme = $el.jqmData( "content-theme" );
6089 }
6090 // Inherit the corner styling from collapsible-set
6091 if ( !o.corners ) {
6092 o.corners = $el.jqmData( "corners" );
6093 }
6094
6095 if ( $el.jqmData( "inset" ) !== undefined ) {
6096 o.inset = $el.jqmData( "inset" );
6097 }
6098 o.inset = o.inset !== undefined ? o.inset : true;
6099 o.corners = o.corners !== undefined ? o.corners : true;
6100
6101 if ( !!o.corners && !!o.inset ) {
6102 $el.addClass( "ui-corner-all" );
6103 }
6104
6105 // Initialize the collapsible set if it's not already initialized
6106 if ( !$el.jqmData( "collapsiblebound" ) ) {
6107 $el
6108 .jqmData( "collapsiblebound", true )
6109 .bind( "expand", function( event ) {
6110 var closestCollapsible = $( event.target )
6111 .closest( ".ui-collapsible" );
6112 if ( closestCollapsible.parent().is( ":jqmData(role='collapsible-set')" ) ) {
6113 closestCollapsible
6114 .siblings( ".ui-collapsible" )
6115 .trigger( "collapse" );
6116 }
6117 });
6118 }
6119 },
6120
6121 _init: function() {
6122 var $el = this.element,
6123 collapsiblesInSet = $el.children( ":jqmData(role='collapsible')" ),
6124 expanded = collapsiblesInSet.filter( ":jqmData(collapsed='false')" );
6125 this._refresh( "true" );
6126
6127 // Because the corners are handled by the collapsible itself and the default state is collapsed
6128 // That was causing https://github.com/jquery/jquery-mobile/issues/4116
6129 expanded.trigger( "expand" );
6130 },
6131
6132 _refresh: function( create ) {
6133 var collapsiblesInSet = this.element.children( ":jqmData(role='collapsible')" );
6134
6135 $.mobile.collapsible.prototype.enhance( collapsiblesInSet.not( ".ui-collapsible" ) );
6136
6137 this._addFirstLastClasses( collapsiblesInSet, this._getVisibles( collapsiblesInSet, create ), create );
6138 },
6139
6140 refresh: function() {
6141 this._refresh( false );
6142 }
6143});
6144
6145$.widget( "mobile.collapsibleset", $.mobile.collapsibleset, $.mobile.behaviors.addFirstLastClasses );
6146
6147//auto self-init widgets
6148$.mobile.document.bind( "pagecreate create", function( e ) {
6149 $.mobile.collapsibleset.prototype.enhanceWithin( e.target );
6150});
6151
6152})( jQuery );
6153
6154(function( $, undefined ) {
6155
6156$.widget( "mobile.navbar", $.mobile.widget, {
6157 options: {
6158 iconpos: "top",
6159 grid: null,
6160 initSelector: ":jqmData(role='navbar')"
6161 },
6162
6163 _create: function() {
6164
6165 var $navbar = this.element,
6166 $navbtns = $navbar.find( "a" ),
6167 iconpos = $navbtns.filter( ":jqmData(icon)" ).length ?
6168 this.options.iconpos : undefined;
6169
6170 $navbar.addClass( "ui-navbar ui-mini" )
6171 .attr( "role", "navigation" )
6172 .find( "ul" )
6173 .jqmEnhanceable()
6174 .grid({ grid: this.options.grid });
6175
6176 $navbtns.buttonMarkup({
6177 corners:false,
6178 shadow: false,
6179 inline: true,
6180 iconpos:iconpos
6181 });
6182
6183 $navbar.delegate( "a", "vclick", function( event ) {
6184 if ( !$(event.target).hasClass( "ui-disabled" ) ) {
6185 $navbtns.removeClass( $.mobile.activeBtnClass );
6186 $( this ).addClass( $.mobile.activeBtnClass );
6187 // The code below is a workaround to fix #1181. We have to see why removeActiveLinkClass() doesn't take care of it.
6188 var activeNavbtn = $( this );
6189 $( document ).one( "pagechange", function( event ) {
6190 activeNavbtn.removeClass( $.mobile.activeBtnClass );
6191 });
6192 }
6193 });
6194
6195 // Buttons in the navbar with ui-state-persist class should regain their active state before page show
6196 $navbar.closest( ".ui-page" ).bind( "pagebeforeshow", function() {
6197 $navbtns.filter( ".ui-state-persist" ).addClass( $.mobile.activeBtnClass );
6198 });
6199 }
6200});
6201
6202//auto self-init widgets
6203$.mobile.document.bind( "pagecreate create", function( e ) {
6204 $.mobile.navbar.prototype.enhanceWithin( e.target );
6205});
6206
6207})( jQuery );
6208
6209(function( $, undefined ) {
6210
6211//Keeps track of the number of lists per page UID
6212//This allows support for multiple nested list in the same page
6213//https://github.com/jquery/jquery-mobile/issues/1617
6214var listCountPerPage = {};
6215
6216$.widget( "mobile.listview", $.mobile.widget, {
6217
6218 options: {
6219 theme: null,
6220 countTheme: "c",
6221 headerTheme: "b",
6222 dividerTheme: "b",
6223 icon: "arrow-r",
6224 splitIcon: "arrow-r",
6225 splitTheme: "b",
6226 corners: true,
6227 shadow: true,
6228 inset: false,
6229 initSelector: ":jqmData(role='listview')"
6230 },
6231
6232 _create: function() {
6233 var t = this,
6234 listviewClasses = "";
6235
6236 listviewClasses += t.options.inset ? " ui-listview-inset" : "";
6237
6238 if ( !!t.options.inset ) {
6239 listviewClasses += t.options.corners ? " ui-corner-all" : "";
6240 listviewClasses += t.options.shadow ? " ui-shadow" : "";
6241 }
6242
6243 // create listview markup
6244 t.element.addClass(function( i, orig ) {
6245 return orig + " ui-listview" + listviewClasses;
6246 });
6247
6248 t.refresh( true );
6249 },
6250
6251 // This is a generic utility method for finding the first
6252 // node with a given nodeName. It uses basic DOM traversal
6253 // to be fast and is meant to be a substitute for simple
6254 // $.fn.closest() and $.fn.children() calls on a single
6255 // element. Note that callers must pass both the lowerCase
6256 // and upperCase version of the nodeName they are looking for.
6257 // The main reason for this is that this function will be
6258 // called many times and we want to avoid having to lowercase
6259 // the nodeName from the element every time to ensure we have
6260 // a match. Note that this function lives here for now, but may
6261 // be moved into $.mobile if other components need a similar method.
6262 _findFirstElementByTagName: function( ele, nextProp, lcName, ucName ) {
6263 var dict = {};
6264 dict[ lcName ] = dict[ ucName ] = true;
6265 while ( ele ) {
6266 if ( dict[ ele.nodeName ] ) {
6267 return ele;
6268 }
6269 ele = ele[ nextProp ];
6270 }
6271 return null;
6272 },
6273 _getChildrenByTagName: function( ele, lcName, ucName ) {
6274 var results = [],
6275 dict = {};
6276 dict[ lcName ] = dict[ ucName ] = true;
6277 ele = ele.firstChild;
6278 while ( ele ) {
6279 if ( dict[ ele.nodeName ] ) {
6280 results.push( ele );
6281 }
6282 ele = ele.nextSibling;
6283 }
6284 return $( results );
6285 },
6286
6287 _addThumbClasses: function( containers ) {
6288 var i, img, len = containers.length;
6289 for ( i = 0; i < len; i++ ) {
6290 img = $( this._findFirstElementByTagName( containers[ i ].firstChild, "nextSibling", "img", "IMG" ) );
6291 if ( img.length ) {
6292 img.addClass( "ui-li-thumb" );
6293 $( this._findFirstElementByTagName( img[ 0 ].parentNode, "parentNode", "li", "LI" ) ).addClass( img.is( ".ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
6294 }
6295 }
6296 },
6297
6298 refresh: function( create ) {
6299 this.parentPage = this.element.closest( ".ui-page" );
6300 this._createSubPages();
6301
6302 var o = this.options,
6303 $list = this.element,
6304 self = this,
6305 dividertheme = $list.jqmData( "dividertheme" ) || o.dividerTheme,
6306 listsplittheme = $list.jqmData( "splittheme" ),
6307 listspliticon = $list.jqmData( "spliticon" ),
6308 listicon = $list.jqmData( "icon" ),
6309 li = this._getChildrenByTagName( $list[ 0 ], "li", "LI" ),
6310 ol = !!$.nodeName( $list[ 0 ], "ol" ),
6311 jsCount = !$.support.cssPseudoElement,
6312 start = $list.attr( "start" ),
6313 itemClassDict = {},
6314 item, itemClass, itemTheme,
6315 a, last, splittheme, counter, startCount, newStartCount, countParent, icon, imgParents, img, linkIcon;
6316
6317 if ( ol && jsCount ) {
6318 $list.find( ".ui-li-dec" ).remove();
6319 }
6320
6321 if ( ol ) {
6322 // Check if a start attribute has been set while taking a value of 0 into account
6323 if ( start || start === 0 ) {
6324 if ( !jsCount ) {
6325 startCount = parseInt( start , 10 ) - 1;
6326 $list.css( "counter-reset", "listnumbering " + startCount );
6327 } else {
6328 counter = parseInt( start , 10 );
6329 }
6330 } else if ( jsCount ) {
6331 counter = 1;
6332 }
6333 }
6334
6335 if ( !o.theme ) {
6336 o.theme = $.mobile.getInheritedTheme( this.element, "c" );
6337 }
6338
6339 for ( var pos = 0, numli = li.length; pos < numli; pos++ ) {
6340 item = li.eq( pos );
6341 itemClass = "ui-li";
6342
6343 // If we're creating the element, we update it regardless
6344 if ( create || !item.hasClass( "ui-li" ) ) {
6345 itemTheme = item.jqmData( "theme" ) || o.theme;
6346 a = this._getChildrenByTagName( item[ 0 ], "a", "A" );
6347 var isDivider = ( item.jqmData( "role" ) === "list-divider" );
6348
6349 if ( a.length && !isDivider ) {
6350 icon = item.jqmData( "icon" );
6351
6352 item.buttonMarkup({
6353 wrapperEls: "div",
6354 shadow: false,
6355 corners: false,
6356 iconpos: "right",
6357 icon: a.length > 1 || icon === false ? false : icon || listicon || o.icon,
6358 theme: itemTheme
6359 });
6360
6361 if ( ( icon !== false ) && ( a.length === 1 ) ) {
6362 item.addClass( "ui-li-has-arrow" );
6363 }
6364
6365 a.first().removeClass( "ui-link" ).addClass( "ui-link-inherit" );
6366
6367 if ( a.length > 1 ) {
6368 itemClass += " ui-li-has-alt";
6369
6370 last = a.last();
6371 splittheme = listsplittheme || last.jqmData( "theme" ) || o.splitTheme;
6372 linkIcon = last.jqmData( "icon" );
6373
6374 last.appendTo( item )
6375 .attr( "title", $.trim(last.getEncodedText()) )
6376 .addClass( "ui-li-link-alt" )
6377 .empty()
6378 .buttonMarkup({
6379 shadow: false,
6380 corners: false,
6381 theme: itemTheme,
6382 icon: false,
6383 iconpos: "notext"
6384 })
6385 .find( ".ui-btn-inner" )
6386 .append(
6387 $( document.createElement( "span" ) ).buttonMarkup({
6388 shadow: true,
6389 corners: true,
6390 theme: splittheme,
6391 iconpos: "notext",
6392 // link icon overrides list item icon overrides ul element overrides options
6393 icon: linkIcon || icon || listspliticon || o.splitIcon
6394 })
6395 );
6396 }
6397 } else if ( isDivider ) {
6398
6399 itemClass += " ui-li-divider ui-bar-" + ( item.jqmData( "theme" ) || dividertheme );
6400 item.attr( "role", "heading" );
6401
6402 if ( ol ) {
6403 //reset counter when a divider heading is encountered
6404 if ( start || start === 0 ) {
6405 if ( !jsCount ) {
6406 newStartCount = parseInt( start , 10 ) - 1;
6407 item.css( "counter-reset", "listnumbering " + newStartCount );
6408 } else {
6409 counter = parseInt( start , 10 );
6410 }
6411 } else if ( jsCount ) {
6412 counter = 1;
6413 }
6414 }
6415
6416 } else {
6417 itemClass += " ui-li-static ui-btn-up-" + itemTheme;
6418 }
6419 }
6420
6421 if ( ol && jsCount && itemClass.indexOf( "ui-li-divider" ) < 0 ) {
6422 countParent = itemClass.indexOf( "ui-li-static" ) > 0 ? item : item.find( ".ui-link-inherit" );
6423
6424 countParent.addClass( "ui-li-jsnumbering" )
6425 .prepend( "<span class='ui-li-dec'>" + ( counter++ ) + ". </span>" );
6426 }
6427
6428 // Instead of setting item class directly on the list item and its
6429 // btn-inner at this point in time, push the item into a dictionary
6430 // that tells us what class to set on it so we can do this after this
6431 // processing loop is finished.
6432
6433 if ( !itemClassDict[ itemClass ] ) {
6434 itemClassDict[ itemClass ] = [];
6435 }
6436
6437 itemClassDict[ itemClass ].push( item[ 0 ] );
6438 }
6439
6440 // Set the appropriate listview item classes on each list item
6441 // and their btn-inner elements. The main reason we didn't do this
6442 // in the for-loop above is because we can eliminate per-item function overhead
6443 // by calling addClass() and children() once or twice afterwards. This
6444 // can give us a significant boost on platforms like WP7.5.
6445
6446 for ( itemClass in itemClassDict ) {
6447 $( itemClassDict[ itemClass ] ).addClass( itemClass ).children( ".ui-btn-inner" ).addClass( itemClass );
6448 }
6449
6450 $list.find( "h1, h2, h3, h4, h5, h6" ).addClass( "ui-li-heading" )
6451 .end()
6452
6453 .find( "p, dl" ).addClass( "ui-li-desc" )
6454 .end()
6455
6456 .find( ".ui-li-aside" ).each(function() {
6457 var $this = $( this );
6458 $this.prependTo( $this.parent() ); //shift aside to front for css float
6459 })
6460 .end()
6461
6462 .find( ".ui-li-count" ).each(function() {
6463 $( this ).closest( "li" ).addClass( "ui-li-has-count" );
6464 }).addClass( "ui-btn-up-" + ( $list.jqmData( "counttheme" ) || this.options.countTheme) + " ui-btn-corner-all" );
6465
6466 // The idea here is to look at the first image in the list item
6467 // itself, and any .ui-link-inherit element it may contain, so we
6468 // can place the appropriate classes on the image and list item.
6469 // Note that we used to use something like:
6470 //
6471 // li.find(">img:eq(0), .ui-link-inherit>img:eq(0)").each( ... );
6472 //
6473 // But executing a find() like that on Windows Phone 7.5 took a
6474 // really long time. Walking things manually with the code below
6475 // allows the 400 listview item page to load in about 3 seconds as
6476 // opposed to 30 seconds.
6477
6478 this._addThumbClasses( li );
6479 this._addThumbClasses( $list.find( ".ui-link-inherit" ) );
6480
6481 this._addFirstLastClasses( li, this._getVisibles( li, create ), create );
6482 // autodividers binds to this to redraw dividers after the listview refresh
6483 this._trigger( "afterrefresh" );
6484 },
6485
6486 //create a string for ID/subpage url creation
6487 _idStringEscape: function( str ) {
6488 return str.replace(/[^a-zA-Z0-9]/g, '-');
6489 },
6490
6491 _createSubPages: function() {
6492 var parentList = this.element,
6493 parentPage = parentList.closest( ".ui-page" ),
6494 parentUrl = parentPage.jqmData( "url" ),
6495 parentId = parentUrl || parentPage[ 0 ][ $.expando ],
6496 parentListId = parentList.attr( "id" ),
6497 o = this.options,
6498 dns = "data-" + $.mobile.ns,
6499 self = this,
6500 persistentFooterID = parentPage.find( ":jqmData(role='footer')" ).jqmData( "id" ),
6501 hasSubPages;
6502
6503 if ( typeof listCountPerPage[ parentId ] === "undefined" ) {
6504 listCountPerPage[ parentId ] = -1;
6505 }
6506
6507 parentListId = parentListId || ++listCountPerPage[ parentId ];
6508
6509 $( parentList.find( "li>ul, li>ol" ).toArray().reverse() ).each(function( i ) {
6510 var self = this,
6511 list = $( this ),
6512 listId = list.attr( "id" ) || parentListId + "-" + i,
6513 parent = list.parent(),
6514 nodeElsFull = $( list.prevAll().toArray().reverse() ),
6515 nodeEls = nodeElsFull.length ? nodeElsFull : $( "<span>" + $.trim(parent.contents()[ 0 ].nodeValue) + "</span>" ),
6516 title = nodeEls.first().getEncodedText(),//url limits to first 30 chars of text
6517 id = ( parentUrl || "" ) + "&" + $.mobile.subPageUrlKey + "=" + listId,
6518 theme = list.jqmData( "theme" ) || o.theme,
6519 countTheme = list.jqmData( "counttheme" ) || parentList.jqmData( "counttheme" ) || o.countTheme,
6520 newPage, anchor;
6521
6522 //define hasSubPages for use in later removal
6523 hasSubPages = true;
6524
6525 newPage = list.detach()
6526 .wrap( "<div " + dns + "role='page' " + dns + "url='" + id + "' " + dns + "theme='" + theme + "' " + dns + "count-theme='" + countTheme + "'><div " + dns + "role='content'></div></div>" )
6527 .parent()
6528 .before( "<div " + dns + "role='header' " + dns + "theme='" + o.headerTheme + "'><div class='ui-title'>" + title + "</div></div>" )
6529 .after( persistentFooterID ? $( "<div " + dns + "role='footer' " + dns + "id='"+ persistentFooterID +"'>" ) : "" )
6530 .parent()
6531 .appendTo( $.mobile.pageContainer );
6532
6533 newPage.page();
6534
6535 anchor = parent.find( 'a:first' );
6536
6537 if ( !anchor.length ) {
6538 anchor = $( "<a/>" ).html( nodeEls || title ).prependTo( parent.empty() );
6539 }
6540
6541 anchor.attr( "href", "#" + id );
6542
6543 }).listview();
6544
6545 // on pagehide, remove any nested pages along with the parent page, as long as they aren't active
6546 // and aren't embedded
6547 if ( hasSubPages &&
6548 parentPage.is( ":jqmData(external-page='true')" ) &&
6549 parentPage.data( "mobile-page" ).options.domCache === false ) {
6550
6551 var newRemove = function( e, ui ) {
6552 var nextPage = ui.nextPage, npURL,
6553 prEvent = new $.Event( "pageremove" );
6554
6555 if ( ui.nextPage ) {
6556 npURL = nextPage.jqmData( "url" );
6557 if ( npURL.indexOf( parentUrl + "&" + $.mobile.subPageUrlKey ) !== 0 ) {
6558 self.childPages().remove();
6559 parentPage.trigger( prEvent );
6560 if ( !prEvent.isDefaultPrevented() ) {
6561 parentPage.removeWithDependents();
6562 }
6563 }
6564 }
6565 };
6566
6567 // unbind the original page remove and replace with our specialized version
6568 parentPage
6569 .unbind( "pagehide.remove" )
6570 .bind( "pagehide.remove", newRemove);
6571 }
6572 },
6573
6574 // TODO sort out a better way to track sub pages of the listview this is brittle
6575 childPages: function() {
6576 var parentUrl = this.parentPage.jqmData( "url" );
6577
6578 return $( ":jqmData(url^='"+ parentUrl + "&" + $.mobile.subPageUrlKey + "')" );
6579 }
6580});
6581
6582$.widget( "mobile.listview", $.mobile.listview, $.mobile.behaviors.addFirstLastClasses );
6583
6584//auto self-init widgets
6585$.mobile.document.bind( "pagecreate create", function( e ) {
6586 $.mobile.listview.prototype.enhanceWithin( e.target );
6587});
6588
6589})( jQuery );
6590
6591(function( $, undefined ) {
6592
6593$.mobile.listview.prototype.options.autodividers = false;
6594$.mobile.listview.prototype.options.autodividersSelector = function( elt ) {
6595 // look for the text in the given element
6596 var text = $.trim( elt.text() ) || null;
6597
6598 if ( !text ) {
6599 return null;
6600 }
6601
6602 // create the text for the divider (first uppercased letter)
6603 text = text.slice( 0, 1 ).toUpperCase();
6604
6605 return text;
6606};
6607
6608$.mobile.document.delegate( "ul,ol", "listviewcreate", function() {
6609
6610 var list = $( this ),
6611 listview = list.data( "mobile-listview" );
6612
6613 if ( !listview || !listview.options.autodividers ) {
6614 return;
6615 }
6616
6617 var replaceDividers = function () {
6618 list.find( "li:jqmData(role='list-divider')" ).remove();
6619
6620 var lis = list.find( 'li' ),
6621 lastDividerText = null, li, dividerText;
6622
6623 for ( var i = 0; i < lis.length ; i++ ) {
6624 li = lis[i];
6625 dividerText = listview.options.autodividersSelector( $( li ) );
6626
6627 if ( dividerText && lastDividerText !== dividerText ) {
6628 var divider = document.createElement( 'li' );
6629 divider.appendChild( document.createTextNode( dividerText ) );
6630 divider.setAttribute( 'data-' + $.mobile.ns + 'role', 'list-divider' );
6631 li.parentNode.insertBefore( divider, li );
6632 }
6633
6634 lastDividerText = dividerText;
6635 }
6636 };
6637
6638 var afterListviewRefresh = function () {
6639 list.unbind( 'listviewafterrefresh', afterListviewRefresh );
6640 replaceDividers();
6641 listview.refresh();
6642 list.bind( 'listviewafterrefresh', afterListviewRefresh );
6643 };
6644
6645 afterListviewRefresh();
6646});
6647
6648})( jQuery );
6649
6650/*
6651* "checkboxradio" plugin
6652*/
6653
6654(function( $, undefined ) {
6655
6656$.widget( "mobile.checkboxradio", $.mobile.widget, {
6657 options: {
6658 theme: null,
6659 mini: false,
6660 initSelector: "input[type='checkbox'],input[type='radio']"
6661 },
6662 _create: function() {
6663 var self = this,
6664 input = this.element,
6665 o = this.options,
6666 inheritAttr = function( input, dataAttr ) {
6667 return input.jqmData( dataAttr ) || input.closest( "form, fieldset" ).jqmData( dataAttr );
6668 },
6669 // NOTE: Windows Phone could not find the label through a selector
6670 // filter works though.
6671 parentLabel = $( input ).closest( "label" ),
6672 label = parentLabel.length ? parentLabel : $( input ).closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" ).find( "label" ).filter( "[for='" + input[0].id + "']" ).first(),
6673 inputtype = input[0].type,
6674 mini = inheritAttr( input, "mini" ) || o.mini,
6675 checkedState = inputtype + "-on",
6676 uncheckedState = inputtype + "-off",
6677 iconpos = inheritAttr( input, "iconpos" ),
6678 checkedClass = "ui-" + checkedState,
6679 uncheckedClass = "ui-" + uncheckedState;
6680
6681 if ( inputtype !== "checkbox" && inputtype !== "radio" ) {
6682 return;
6683 }
6684
6685 // Expose for other methods
6686 $.extend( this, {
6687 label: label,
6688 inputtype: inputtype,
6689 checkedClass: checkedClass,
6690 uncheckedClass: uncheckedClass,
6691 checkedicon: checkedState,
6692 uncheckedicon: uncheckedState
6693 });
6694
6695 // If there's no selected theme check the data attr
6696 if ( !o.theme ) {
6697 o.theme = $.mobile.getInheritedTheme( this.element, "c" );
6698 }
6699
6700 label.buttonMarkup({
6701 theme: o.theme,
6702 icon: uncheckedState,
6703 shadow: false,
6704 mini: mini,
6705 iconpos: iconpos
6706 });
6707
6708 // Wrap the input + label in a div
6709 var wrapper = document.createElement('div');
6710 wrapper.className = 'ui-' + inputtype;
6711
6712 input.add( label ).wrapAll( wrapper );
6713
6714 label.bind({
6715 vmouseover: function( event ) {
6716 if ( $( this ).parent().is( ".ui-disabled" ) ) {
6717 event.stopPropagation();
6718 }
6719 },
6720
6721 vclick: function( event ) {
6722 if ( input.is( ":disabled" ) ) {
6723 event.preventDefault();
6724 return;
6725 }
6726
6727 self._cacheVals();
6728
6729 input.prop( "checked", inputtype === "radio" && true || !input.prop( "checked" ) );
6730
6731 // trigger click handler's bound directly to the input as a substitute for
6732 // how label clicks behave normally in the browsers
6733 // TODO: it would be nice to let the browser's handle the clicks and pass them
6734 // through to the associate input. we can swallow that click at the parent
6735 // wrapper element level
6736 input.triggerHandler( 'click' );
6737
6738 // Input set for common radio buttons will contain all the radio
6739 // buttons, but will not for checkboxes. clearing the checked status
6740 // of other radios ensures the active button state is applied properly
6741 self._getInputSet().not( input ).prop( "checked", false );
6742
6743 self._updateAll();
6744 return false;
6745 }
6746 });
6747
6748 input
6749 .bind({
6750 vmousedown: function() {
6751 self._cacheVals();
6752 },
6753
6754 vclick: function() {
6755 var $this = $( this );
6756
6757 // Adds checked attribute to checked input when keyboard is used
6758 if ( $this.is( ":checked" ) ) {
6759
6760 $this.prop( "checked", true);
6761 self._getInputSet().not( $this ).prop( "checked", false );
6762 } else {
6763
6764 $this.prop( "checked", false );
6765 }
6766
6767 self._updateAll();
6768 },
6769
6770 focus: function() {
6771 label.addClass( $.mobile.focusClass );
6772 },
6773
6774 blur: function() {
6775 label.removeClass( $.mobile.focusClass );
6776 }
6777 });
6778
6779 if ( this._handleFormReset ) {
6780 this._handleFormReset();
6781 }
6782 this.refresh();
6783 },
6784
6785 _cacheVals: function() {
6786 this._getInputSet().each(function() {
6787 $( this ).jqmData( "cacheVal", this.checked );
6788 });
6789 },
6790
6791 //returns either a set of radios with the same name attribute, or a single checkbox
6792 _getInputSet: function() {
6793 if ( this.inputtype === "checkbox" ) {
6794 return this.element;
6795 }
6796
6797 return this.element.closest( "form, :jqmData(role='page'), :jqmData(role='dialog')" )
6798 .find( "input[name='" + this.element[0].name + "'][type='" + this.inputtype + "']" );
6799 },
6800
6801 _updateAll: function() {
6802 var self = this;
6803
6804 this._getInputSet().each(function() {
6805 var $this = $( this );
6806
6807 if ( this.checked || self.inputtype === "checkbox" ) {
6808 $this.trigger( "change" );
6809 }
6810 })
6811 .checkboxradio( "refresh" );
6812 },
6813
6814 _reset: function() {
6815 this.refresh();
6816 },
6817
6818 refresh: function() {
6819 var input = this.element[ 0 ],
6820 active = " " + $.mobile.activeBtnClass,
6821 checkedClass = this.checkedClass + ( this.element.parents( ".ui-controlgroup-horizontal" ).length ? active : "" ),
6822 label = this.label;
6823
6824 if ( input.checked ) {
6825 label.removeClass( this.uncheckedClass + active ).addClass( checkedClass ).buttonMarkup( { icon: this.checkedicon } );
6826 } else {
6827 label.removeClass( checkedClass ).addClass( this.uncheckedClass ).buttonMarkup( { icon: this.uncheckedicon } );
6828 }
6829
6830 if ( input.disabled ) {
6831 this.disable();
6832 } else {
6833 this.enable();
6834 }
6835 },
6836
6837 disable: function() {
6838 this.element.prop( "disabled", true ).parent().addClass( "ui-disabled" );
6839 },
6840
6841 enable: function() {
6842 this.element.prop( "disabled", false ).parent().removeClass( "ui-disabled" );
6843 }
6844});
6845
6846$.widget( "mobile.checkboxradio", $.mobile.checkboxradio, $.mobile.behaviors.formReset );
6847
6848//auto self-init widgets
6849$.mobile.document.bind( "pagecreate create", function( e ) {
6850 $.mobile.checkboxradio.prototype.enhanceWithin( e.target, true );
6851});
6852
6853})( jQuery );
6854
6855(function( $, undefined ) {
6856
6857$.widget( "mobile.button", $.mobile.widget, {
6858 options: {
6859 theme: null,
6860 icon: null,
6861 iconpos: null,
6862 corners: true,
6863 shadow: true,
6864 iconshadow: true,
6865 inline: null,
6866 mini: null,
6867 initSelector: "button, [type='button'], [type='submit'], [type='reset']"
6868 },
6869 _create: function() {
6870 var $el = this.element,
6871 $button,
6872 // create a copy of this.options we can pass to buttonMarkup
6873 o = ( function( tdo ) {
6874 var key, ret = {};
6875
6876 for ( key in tdo ) {
6877 if ( tdo[ key ] !== null && key !== "initSelector" ) {
6878 ret[ key ] = tdo[ key ];
6879 }
6880 }
6881
6882 return ret;
6883 } )( this.options ),
6884 classes = "",
6885 $buttonPlaceholder;
6886
6887 // if this is a link, check if it's been enhanced and, if not, use the right function
6888 if ( $el[ 0 ].tagName === "A" ) {
6889 if ( !$el.hasClass( "ui-btn" ) ) {
6890 $el.buttonMarkup();
6891 }
6892 return;
6893 }
6894
6895 // get the inherited theme
6896 // TODO centralize for all widgets
6897 if ( !this.options.theme ) {
6898 this.options.theme = $.mobile.getInheritedTheme( this.element, "c" );
6899 }
6900
6901 // TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577
6902 /* if ( $el[0].className.length ) {
6903 classes = $el[0].className;
6904 } */
6905 if ( !!~$el[0].className.indexOf( "ui-btn-left" ) ) {
6906 classes = "ui-btn-left";
6907 }
6908
6909 if ( !!~$el[0].className.indexOf( "ui-btn-right" ) ) {
6910 classes = "ui-btn-right";
6911 }
6912
6913 if ( $el.attr( "type" ) === "submit" || $el.attr( "type" ) === "reset" ) {
6914 classes ? classes += " ui-submit" : classes = "ui-submit";
6915 }
6916 $( "label[for='" + $el.attr( "id" ) + "']" ).addClass( "ui-submit" );
6917
6918 // Add ARIA role
6919 this.button = $( "<div></div>" )
6920 [ $el.html() ? "html" : "text" ]( $el.html() || $el.val() )
6921 .insertBefore( $el )
6922 .buttonMarkup( o )
6923 .addClass( classes )
6924 .append( $el.addClass( "ui-btn-hidden" ) );
6925
6926 $button = this.button;
6927
6928 $el.bind({
6929 focus: function() {
6930 $button.addClass( $.mobile.focusClass );
6931 },
6932
6933 blur: function() {
6934 $button.removeClass( $.mobile.focusClass );
6935 }
6936 });
6937
6938 this.refresh();
6939 },
6940
6941 _setOption: function( key, value ) {
6942 var op = {};
6943
6944 op[ key ] = value;
6945 if ( key !== "initSelector" ) {
6946 this.button.buttonMarkup( op );
6947 // Record the option change in the options and in the DOM data-* attributes
6948 this.element.attr( "data-" + ( $.mobile.ns || "" ) + ( key.replace( /([A-Z])/, "-$1" ).toLowerCase() ), value );
6949 }
6950 this._super( "_setOption", key, value );
6951 },
6952
6953 enable: function() {
6954 this.element.attr( "disabled", false );
6955 this.button.removeClass( "ui-disabled" ).attr( "aria-disabled", false );
6956 return this._setOption( "disabled", false );
6957 },
6958
6959 disable: function() {
6960 this.element.attr( "disabled", true );
6961 this.button.addClass( "ui-disabled" ).attr( "aria-disabled", true );
6962 return this._setOption( "disabled", true );
6963 },
6964
6965 refresh: function() {
6966 var $el = this.element;
6967
6968 if ( $el.prop("disabled") ) {
6969 this.disable();
6970 } else {
6971 this.enable();
6972 }
6973
6974 // Grab the button's text element from its implementation-independent data item
6975 $( this.button.data( 'buttonElements' ).text )[ $el.html() ? "html" : "text" ]( $el.html() || $el.val() );
6976 }
6977});
6978
6979//auto self-init widgets
6980$.mobile.document.bind( "pagecreate create", function( e ) {
6981 $.mobile.button.prototype.enhanceWithin( e.target, true );
6982});
6983
6984})( jQuery );
6985
6986(function( $, undefined ) {
6987
6988 $.widget( "mobile.controlgroup", $.mobile.widget, {
6989 options: {
6990 shadow: false,
6991 corners: true,
6992 excludeInvisible: true,
6993 type: "vertical",
6994 mini: false,
6995 initSelector: ":jqmData(role='controlgroup')"
6996 },
6997
6998 _create: function() {
6999 var $el = this.element,
7000 ui = {
7001 inner: $( "<div class='ui-controlgroup-controls'></div>" ),
7002 legend: $( "<div role='heading' class='ui-controlgroup-label'></div>" )
7003 },
7004 grouplegend = $el.children( "legend" ),
7005 self = this;
7006
7007 // Apply the proto
7008 $el.wrapInner( ui.inner );
7009 if ( grouplegend.length ) {
7010 ui.legend.append( grouplegend ).insertBefore( $el.children( 0 ) );
7011 }
7012 $el.addClass( "ui-corner-all ui-controlgroup" );
7013
7014 $.extend( this, {
7015 _initialRefresh: true
7016 });
7017
7018 $.each( this.options, function( key, value ) {
7019 // Cause initial options to be applied by their handler by temporarily setting the option to undefined
7020 // - the handler then sets it to the initial value
7021 self.options[ key ] = undefined;
7022 self._setOption( key, value, true );
7023 });
7024 },
7025
7026 _init: function() {
7027 this.refresh();
7028 },
7029
7030 _setOption: function( key, value ) {
7031 var setter = "_set" + key.charAt( 0 ).toUpperCase() + key.slice( 1 );
7032
7033 if ( this[ setter ] !== undefined ) {
7034 this[ setter ]( value );
7035 }
7036
7037 this._super( key, value );
7038 this.element.attr( "data-" + ( $.mobile.ns || "" ) + ( key.replace( /([A-Z])/, "-$1" ).toLowerCase() ), value );
7039 },
7040
7041 _setType: function( value ) {
7042 this.element
7043 .removeClass( "ui-controlgroup-horizontal ui-controlgroup-vertical" )
7044 .addClass( "ui-controlgroup-" + value );
7045 this.refresh();
7046 },
7047
7048 _setCorners: function( value ) {
7049 this.element.toggleClass( "ui-corner-all", value );
7050 },
7051
7052 _setShadow: function( value ) {
7053 this.element.toggleClass( "ui-shadow", value );
7054 },
7055
7056 _setMini: function( value ) {
7057 this.element.toggleClass( "ui-mini", value );
7058 },
7059
7060 container: function() {
7061 return this.element.children( ".ui-controlgroup-controls" );
7062 },
7063
7064 refresh: function() {
7065 var els = this.element.find( ".ui-btn" ).not( ".ui-slider-handle" ),
7066 create = this._initialRefresh;
7067 if ( $.mobile.checkboxradio ) {
7068 this.element.find( ":mobile-checkboxradio" ).checkboxradio( "refresh" );
7069 }
7070 this._addFirstLastClasses( els, this.options.excludeInvisible ? this._getVisibles( els, create ) : els, create );
7071 this._initialRefresh = false;
7072 }
7073 });
7074
7075 $.widget( "mobile.controlgroup", $.mobile.controlgroup, $.mobile.behaviors.addFirstLastClasses );
7076
7077 // TODO: Implement a mechanism to allow widgets to become enhanced in the
7078 // correct order when their correct enhancement depends on other widgets in
7079 // the page being correctly enhanced already.
7080 //
7081 // For now, we wait until dom-ready to attach the controlgroup's enhancement
7082 // hook, because by that time, all the other widgets' enhancement hooks should
7083 // already be in place, ensuring that all widgets that need to be grouped will
7084 // already have been enhanced by the time the controlgroup is created.
7085 $( function() {
7086 $.mobile.document.bind( "pagecreate create", function( e ) {
7087 $.mobile.controlgroup.prototype.enhanceWithin( e.target, true );
7088 });
7089 });
7090})(jQuery);
7091
7092(function( $, undefined ) {
7093
7094$( document ).bind( "pagecreate create", function( e ) {
7095
7096 //links within content areas, tests included with page
7097 $( e.target )
7098 .find( "a" )
7099 .jqmEnhanceable()
7100 .not( ".ui-btn, .ui-link-inherit, :jqmData(role='none'), :jqmData(role='nojs')" )
7101 .addClass( "ui-link" );
7102
7103});
7104
7105})( jQuery );
7106
7107
7108(function( $, undefined ) {
7109
7110 function fitSegmentInsideSegment( winSize, segSize, offset, desired ) {
7111 var ret = desired;
7112
7113 if ( winSize < segSize ) {
7114 // Center segment if it's bigger than the window
7115 ret = offset + ( winSize - segSize ) / 2;
7116 } else {
7117 // Otherwise center it at the desired coordinate while keeping it completely inside the window
7118 ret = Math.min( Math.max( offset, desired - segSize / 2 ), offset + winSize - segSize );
7119 }
7120
7121 return ret;
7122 }
7123
7124 function windowCoords() {
7125 var $win = $.mobile.window;
7126
7127 return {
7128 x: $win.scrollLeft(),
7129 y: $win.scrollTop(),
7130 cx: ( window.innerWidth || $win.width() ),
7131 cy: ( window.innerHeight || $win.height() )
7132 };
7133 }
7134
7135 $.widget( "mobile.popup", $.mobile.widget, {
7136 options: {
7137 theme: null,
7138 overlayTheme: null,
7139 shadow: true,
7140 corners: true,
7141 transition: "none",
7142 positionTo: "origin",
7143 tolerance: null,
7144 initSelector: ":jqmData(role='popup')",
7145 closeLinkSelector: "a:jqmData(rel='back')",
7146 closeLinkEvents: "click.popup",
7147 navigateEvents: "navigate.popup",
7148 closeEvents: "navigate.popup pagebeforechange.popup",
7149 dismissible: true,
7150
7151 // NOTE Windows Phone 7 has a scroll position caching issue that
7152 // requires us to disable popup history management by default
7153 // https://github.com/jquery/jquery-mobile/issues/4784
7154 //
7155 // NOTE this option is modified in _create!
7156 history: !$.mobile.browser.oldIE
7157 },
7158
7159 _eatEventAndClose: function( e ) {
7160 e.preventDefault();
7161 e.stopImmediatePropagation();
7162 if ( this.options.dismissible ) {
7163 this.close();
7164 }
7165 return false;
7166 },
7167
7168 // Make sure the screen size is increased beyond the page height if the popup's causes the document to increase in height
7169 _resizeScreen: function() {
7170 var popupHeight = this._ui.container.outerHeight( true );
7171
7172 this._ui.screen.removeAttr( "style" );
7173 if ( popupHeight > this._ui.screen.height() ) {
7174 this._ui.screen.height( popupHeight );
7175 }
7176 },
7177
7178 _handleWindowKeyUp: function( e ) {
7179 if ( this._isOpen && e.keyCode === $.mobile.keyCode.ESCAPE ) {
7180 return this._eatEventAndClose( e );
7181 }
7182 },
7183
7184 _expectResizeEvent: function() {
7185 var winCoords = windowCoords();
7186
7187 if ( this._resizeData ) {
7188 if ( winCoords.x === this._resizeData.winCoords.x &&
7189 winCoords.y === this._resizeData.winCoords.y &&
7190 winCoords.cx === this._resizeData.winCoords.cx &&
7191 winCoords.cy === this._resizeData.winCoords.cy ) {
7192 // timeout not refreshed
7193 return false;
7194 } else {
7195 // clear existing timeout - it will be refreshed below
7196 clearTimeout( this._resizeData.timeoutId );
7197 }
7198 }
7199
7200 this._resizeData = {
7201 timeoutId: setTimeout( $.proxy( this, "_resizeTimeout" ), 200 ),
7202 winCoords: winCoords
7203 };
7204
7205 return true;
7206 },
7207
7208 _resizeTimeout: function() {
7209 if ( this._isOpen ) {
7210 if ( !this._expectResizeEvent() ) {
7211 if ( this._ui.container.hasClass( "ui-popup-hidden" ) ) {
7212 // effectively rapid-open the popup while leaving the screen intact
7213 this._ui.container.removeClass( "ui-popup-hidden" );
7214 this.reposition( { positionTo: "window" } );
7215 this._ignoreResizeEvents();
7216 }
7217
7218 this._resizeScreen();
7219 this._resizeData = null;
7220 this._orientationchangeInProgress = false;
7221 }
7222 } else {
7223 this._resizeData = null;
7224 this._orientationchangeInProgress = false;
7225 }
7226 },
7227
7228 _ignoreResizeEvents: function() {
7229 var self = this;
7230
7231 if ( this._ignoreResizeTo ) {
7232 clearTimeout( this._ignoreResizeTo );
7233 }
7234 this._ignoreResizeTo = setTimeout( function() { self._ignoreResizeTo = 0; }, 1000 );
7235 },
7236
7237 _handleWindowResize: function( e ) {
7238 if ( this._isOpen && this._ignoreResizeTo === 0 ) {
7239 if ( ( this._expectResizeEvent() || this._orientationchangeInProgress ) &&
7240 !this._ui.container.hasClass( "ui-popup-hidden" ) ) {
7241 // effectively rapid-close the popup while leaving the screen intact
7242 this._ui.container
7243 .addClass( "ui-popup-hidden" )
7244 .removeAttr( "style" );
7245 }
7246 }
7247 },
7248
7249 _handleWindowOrientationchange: function( e ) {
7250 if ( !this._orientationchangeInProgress && this._isOpen && this._ignoreResizeTo === 0 ) {
7251 this._expectResizeEvent();
7252 this._orientationchangeInProgress = true;
7253 }
7254 },
7255
7256 // When the popup is open, attempting to focus on an element that is not a
7257 // child of the popup will redirect focus to the popup
7258 _handleDocumentFocusIn: function( e ) {
7259 var tgt = e.target, $tgt, ui = this._ui;
7260
7261 if ( !this._isOpen ) {
7262 return;
7263 }
7264
7265 if ( tgt !== ui.container[ 0 ] ) {
7266 $tgt = $( e.target );
7267 if ( 0 === $tgt.parents().filter( ui.container[ 0 ] ).length ) {
7268 $( document.activeElement ).one( "focus", function( e ) {
7269 $tgt.blur();
7270 });
7271 ui.focusElement.focus();
7272 e.preventDefault();
7273 e.stopImmediatePropagation();
7274 return false;
7275 } else if ( ui.focusElement[ 0 ] === ui.container[ 0 ] ) {
7276 ui.focusElement = $tgt;
7277 }
7278 } else if ( ui.focusElement && ui.focusElement[ 0 ] !== ui.container[ 0 ] ) {
7279 ui.container.blur();
7280 ui.focusElement.focus();
7281 }
7282
7283 this._ignoreResizeEvents();
7284 },
7285
7286 _create: function() {
7287 var ui = {
7288 screen: $( "<div class='ui-screen-hidden ui-popup-screen'></div>" ),
7289 placeholder: $( "<div style='display: none;'><!-- placeholder --></div>" ),
7290 container: $( "<div class='ui-popup-container ui-popup-hidden'></div>" )
7291 },
7292 thisPage = this.element.closest( ".ui-page" ),
7293 myId = this.element.attr( "id" ),
7294 self = this;
7295
7296 // We need to adjust the history option to be false if there's no AJAX nav.
7297 // We can't do it in the option declarations because those are run before
7298 // it is determined whether there shall be AJAX nav.
7299 this.options.history = this.options.history && $.mobile.ajaxEnabled && $.mobile.hashListeningEnabled;
7300
7301 if ( thisPage.length === 0 ) {
7302 thisPage = $( "body" );
7303 }
7304
7305 // define the container for navigation event bindings
7306 // TODO this would be nice at the the mobile widget level
7307 this.options.container = this.options.container || $.mobile.pageContainer;
7308
7309 // Apply the proto
7310 thisPage.append( ui.screen );
7311 ui.container.insertAfter( ui.screen );
7312 // Leave a placeholder where the element used to be
7313 ui.placeholder.insertAfter( this.element );
7314 if ( myId ) {
7315 ui.screen.attr( "id", myId + "-screen" );
7316 ui.container.attr( "id", myId + "-popup" );
7317 ui.placeholder.html( "<!-- placeholder for " + myId + " -->" );
7318 }
7319 ui.container.append( this.element );
7320 ui.focusElement = ui.container;
7321
7322 // Add class to popup element
7323 this.element.addClass( "ui-popup" );
7324
7325 // Define instance variables
7326 $.extend( this, {
7327 _scrollTop: 0,
7328 _page: thisPage,
7329 _ui: ui,
7330 _fallbackTransition: "",
7331 _currentTransition: false,
7332 _prereqs: null,
7333 _isOpen: false,
7334 _tolerance: null,
7335 _resizeData: null,
7336 _ignoreResizeTo: 0,
7337 _orientationchangeInProgress: false
7338 });
7339
7340 $.each( this.options, function( key, value ) {
7341 // Cause initial options to be applied by their handler by temporarily setting the option to undefined
7342 // - the handler then sets it to the initial value
7343 self.options[ key ] = undefined;
7344 self._setOption( key, value, true );
7345 });
7346
7347 ui.screen.bind( "vclick", $.proxy( this, "_eatEventAndClose" ) );
7348
7349 this._on( $.mobile.window, {
7350 orientationchange: $.proxy( this, "_handleWindowOrientationchange" ),
7351 resize: $.proxy( this, "_handleWindowResize" ),
7352 keyup: $.proxy( this, "_handleWindowKeyUp" )
7353 });
7354 this._on( $.mobile.document, {
7355 focusin: $.proxy( this, "_handleDocumentFocusIn" )
7356 });
7357 },
7358
7359 _applyTheme: function( dst, theme, prefix ) {
7360 var classes = ( dst.attr( "class" ) || "").split( " " ),
7361 alreadyAdded = true,
7362 currentTheme = null,
7363 matches,
7364 themeStr = String( theme );
7365
7366 while ( classes.length > 0 ) {
7367 currentTheme = classes.pop();
7368 matches = ( new RegExp( "^ui-" + prefix + "-([a-z])$" ) ).exec( currentTheme );
7369 if ( matches && matches.length > 1 ) {
7370 currentTheme = matches[ 1 ];
7371 break;
7372 } else {
7373 currentTheme = null;
7374 }
7375 }
7376
7377 if ( theme !== currentTheme ) {
7378 dst.removeClass( "ui-" + prefix + "-" + currentTheme );
7379 if ( ! ( theme === null || theme === "none" ) ) {
7380 dst.addClass( "ui-" + prefix + "-" + themeStr );
7381 }
7382 }
7383 },
7384
7385 _setTheme: function( value ) {
7386 this._applyTheme( this.element, value, "body" );
7387 },
7388
7389 _setOverlayTheme: function( value ) {
7390 this._applyTheme( this._ui.screen, value, "overlay" );
7391
7392 if ( this._isOpen ) {
7393 this._ui.screen.addClass( "in" );
7394 }
7395 },
7396
7397 _setShadow: function( value ) {
7398 this.element.toggleClass( "ui-overlay-shadow", value );
7399 },
7400
7401 _setCorners: function( value ) {
7402 this.element.toggleClass( "ui-corner-all", value );
7403 },
7404
7405 _applyTransition: function( value ) {
7406 this._ui.container.removeClass( this._fallbackTransition );
7407 if ( value && value !== "none" ) {
7408 this._fallbackTransition = $.mobile._maybeDegradeTransition( value );
7409 if ( this._fallbackTransition === "none" ) {
7410 this._fallbackTransition = "";
7411 }
7412 this._ui.container.addClass( this._fallbackTransition );
7413 }
7414 },
7415
7416 _setTransition: function( value ) {
7417 if ( !this._currentTransition ) {
7418 this._applyTransition( value );
7419 }
7420 },
7421
7422 _setTolerance: function( value ) {
7423 var tol = { t: 30, r: 15, b: 30, l: 15 };
7424
7425 if ( value !== undefined ) {
7426 var ar = String( value ).split( "," );
7427
7428 $.each( ar, function( idx, val ) { ar[ idx ] = parseInt( val, 10 ); } );
7429
7430 switch( ar.length ) {
7431 // All values are to be the same
7432 case 1:
7433 if ( !isNaN( ar[ 0 ] ) ) {
7434 tol.t = tol.r = tol.b = tol.l = ar[ 0 ];
7435 }
7436 break;
7437
7438 // The first value denotes top/bottom tolerance, and the second value denotes left/right tolerance
7439 case 2:
7440 if ( !isNaN( ar[ 0 ] ) ) {
7441 tol.t = tol.b = ar[ 0 ];
7442 }
7443 if ( !isNaN( ar[ 1 ] ) ) {
7444 tol.l = tol.r = ar[ 1 ];
7445 }
7446 break;
7447
7448 // The array contains values in the order top, right, bottom, left
7449 case 4:
7450 if ( !isNaN( ar[ 0 ] ) ) {
7451 tol.t = ar[ 0 ];
7452 }
7453 if ( !isNaN( ar[ 1 ] ) ) {
7454 tol.r = ar[ 1 ];
7455 }
7456 if ( !isNaN( ar[ 2 ] ) ) {
7457 tol.b = ar[ 2 ];
7458 }
7459 if ( !isNaN( ar[ 3 ] ) ) {
7460 tol.l = ar[ 3 ];
7461 }
7462 break;
7463
7464 default:
7465 break;
7466 }
7467 }
7468
7469 this._tolerance = tol;
7470 },
7471
7472 _setOption: function( key, value ) {
7473 var exclusions, setter = "_set" + key.charAt( 0 ).toUpperCase() + key.slice( 1 );
7474
7475 if ( this[ setter ] !== undefined ) {
7476 this[ setter ]( value );
7477 }
7478
7479 // TODO REMOVE FOR 1.2.1 by moving them out to a default options object
7480 exclusions = [
7481 "initSelector",
7482 "closeLinkSelector",
7483 "closeLinkEvents",
7484 "navigateEvents",
7485 "closeEvents",
7486 "history",
7487 "container"
7488 ];
7489
7490 $.mobile.widget.prototype._setOption.apply( this, arguments );
7491 if ( $.inArray( key, exclusions ) === -1 ) {
7492 // Record the option change in the options and in the DOM data-* attributes
7493 this.element.attr( "data-" + ( $.mobile.ns || "" ) + ( key.replace( /([A-Z])/, "-$1" ).toLowerCase() ), value );
7494 }
7495 },
7496
7497 // Try and center the overlay over the given coordinates
7498 _placementCoords: function( desired ) {
7499 // rectangle within which the popup must fit
7500 var
7501 winCoords = windowCoords(),
7502 rc = {
7503 x: this._tolerance.l,
7504 y: winCoords.y + this._tolerance.t,
7505 cx: winCoords.cx - this._tolerance.l - this._tolerance.r,
7506 cy: winCoords.cy - this._tolerance.t - this._tolerance.b
7507 },
7508 menuSize, ret;
7509
7510 // Clamp the width of the menu before grabbing its size
7511 this._ui.container.css( "max-width", rc.cx );
7512 menuSize = {
7513 cx: this._ui.container.outerWidth( true ),
7514 cy: this._ui.container.outerHeight( true )
7515 };
7516
7517 // Center the menu over the desired coordinates, while not going outside
7518 // the window tolerances. This will center wrt. the window if the popup is too large.
7519 ret = {
7520 x: fitSegmentInsideSegment( rc.cx, menuSize.cx, rc.x, desired.x ),
7521 y: fitSegmentInsideSegment( rc.cy, menuSize.cy, rc.y, desired.y )
7522 };
7523
7524 // Make sure the top of the menu is visible
7525 ret.y = Math.max( 0, ret.y );
7526
7527 // If the height of the menu is smaller than the height of the document
7528 // align the bottom with the bottom of the document
7529
7530 // fix for $.mobile.document.height() bug in core 1.7.2.
7531 var docEl = document.documentElement, docBody = document.body,
7532 docHeight = Math.max( docEl.clientHeight, docBody.scrollHeight, docBody.offsetHeight, docEl.scrollHeight, docEl.offsetHeight );
7533
7534 ret.y -= Math.min( ret.y, Math.max( 0, ret.y + menuSize.cy - docHeight ) );
7535
7536 return { left: ret.x, top: ret.y };
7537 },
7538
7539 _createPrereqs: function( screenPrereq, containerPrereq, whenDone ) {
7540 var self = this, prereqs;
7541
7542 // It is important to maintain both the local variable prereqs and self._prereqs. The local variable remains in
7543 // the closure of the functions which call the callbacks passed in. The comparison between the local variable and
7544 // self._prereqs is necessary, because once a function has been passed to .animationComplete() it will be called
7545 // next time an animation completes, even if that's not the animation whose end the function was supposed to catch
7546 // (for example, if an abort happens during the opening animation, the .animationComplete handler is not called for
7547 // that animation anymore, but the handler remains attached, so it is called the next time the popup is opened
7548 // - making it stale. Comparing the local variable prereqs to the widget-level variable self._prereqs ensures that
7549 // callbacks triggered by a stale .animationComplete will be ignored.
7550
7551 prereqs = {
7552 screen: $.Deferred(),
7553 container: $.Deferred()
7554 };
7555
7556 prereqs.screen.then( function() {
7557 if ( prereqs === self._prereqs ) {
7558 screenPrereq();
7559 }
7560 });
7561
7562 prereqs.container.then( function() {
7563 if ( prereqs === self._prereqs ) {
7564 containerPrereq();
7565 }
7566 });
7567
7568 $.when( prereqs.screen, prereqs.container ).done( function() {
7569 if ( prereqs === self._prereqs ) {
7570 self._prereqs = null;
7571 whenDone();
7572 }
7573 });
7574
7575 self._prereqs = prereqs;
7576 },
7577
7578 _animate: function( args ) {
7579 // NOTE before removing the default animation of the screen
7580 // this had an animate callback that would resolve the deferred
7581 // now the deferred is resolved immediately
7582 // TODO remove the dependency on the screen deferred
7583 this._ui.screen
7584 .removeClass( args.classToRemove )
7585 .addClass( args.screenClassToAdd );
7586
7587 args.prereqs.screen.resolve();
7588
7589 if ( args.transition && args.transition !== "none" ) {
7590 if ( args.applyTransition ) {
7591 this._applyTransition( args.transition );
7592 }
7593 if ( this._fallbackTransition ) {
7594 this._ui.container
7595 .animationComplete( $.proxy( args.prereqs.container, "resolve" ) )
7596 .addClass( args.containerClassToAdd )
7597 .removeClass( args.classToRemove );
7598 return;
7599 }
7600 }
7601 this._ui.container.removeClass( args.classToRemove );
7602 args.prereqs.container.resolve();
7603 },
7604
7605 // The desired coordinates passed in will be returned untouched if no reference element can be identified via
7606 // desiredPosition.positionTo. Nevertheless, this function ensures that its return value always contains valid
7607 // x and y coordinates by specifying the center middle of the window if the coordinates are absent.
7608 // options: { x: coordinate, y: coordinate, positionTo: string: "origin", "window", or jQuery selector
7609 _desiredCoords: function( o ) {
7610 var dst = null, offset, winCoords = windowCoords(), x = o.x, y = o.y, pTo = o.positionTo;
7611
7612 // Establish which element will serve as the reference
7613 if ( pTo && pTo !== "origin" ) {
7614 if ( pTo === "window" ) {
7615 x = winCoords.cx / 2 + winCoords.x;
7616 y = winCoords.cy / 2 + winCoords.y;
7617 } else {
7618 try {
7619 dst = $( pTo );
7620 } catch( e ) {
7621 dst = null;
7622 }
7623 if ( dst ) {
7624 dst.filter( ":visible" );
7625 if ( dst.length === 0 ) {
7626 dst = null;
7627 }
7628 }
7629 }
7630 }
7631
7632 // If an element was found, center over it
7633 if ( dst ) {
7634 offset = dst.offset();
7635 x = offset.left + dst.outerWidth() / 2;
7636 y = offset.top + dst.outerHeight() / 2;
7637 }
7638
7639 // Make sure x and y are valid numbers - center over the window
7640 if ( $.type( x ) !== "number" || isNaN( x ) ) {
7641 x = winCoords.cx / 2 + winCoords.x;
7642 }
7643 if ( $.type( y ) !== "number" || isNaN( y ) ) {
7644 y = winCoords.cy / 2 + winCoords.y;
7645 }
7646
7647 return { x: x, y: y };
7648 },
7649
7650 _reposition: function( o ) {
7651 // We only care about position-related parameters for repositioning
7652 o = { x: o.x, y: o.y, positionTo: o.positionTo };
7653 this._trigger( "beforeposition", o );
7654 this._ui.container.offset( this._placementCoords( this._desiredCoords( o ) ) );
7655 },
7656
7657 reposition: function( o ) {
7658 if ( this._isOpen ) {
7659 this._reposition( o );
7660 }
7661 },
7662
7663 _openPrereqsComplete: function() {
7664 this._ui.container.addClass( "ui-popup-active" );
7665 this._isOpen = true;
7666 this._resizeScreen();
7667 this._ui.container.attr( "tabindex", "0" ).focus();
7668 this._ignoreResizeEvents();
7669 this._trigger( "afteropen" );
7670 },
7671
7672 _open: function( options ) {
7673 var o = $.extend( {}, this.options, options ),
7674 // TODO move blacklist to private method
7675 androidBlacklist = ( function() {
7676 var w = window,
7677 ua = navigator.userAgent,
7678 // Rendering engine is Webkit, and capture major version
7679 wkmatch = ua.match( /AppleWebKit\/([0-9\.]+)/ ),
7680 wkversion = !!wkmatch && wkmatch[ 1 ],
7681 androidmatch = ua.match( /Android (\d+(?:\.\d+))/ ),
7682 andversion = !!androidmatch && androidmatch[ 1 ],
7683 chromematch = ua.indexOf( "Chrome" ) > -1;
7684
7685 // Platform is Android, WebKit version is greater than 534.13 ( Android 3.2.1 ) and not Chrome.
7686 if( androidmatch !== null && andversion === "4.0" && wkversion && wkversion > 534.13 && !chromematch ) {
7687 return true;
7688 }
7689 return false;
7690 }());
7691
7692 // Count down to triggering "popupafteropen" - we have two prerequisites:
7693 // 1. The popup window animation completes (container())
7694 // 2. The screen opacity animation completes (screen())
7695 this._createPrereqs(
7696 $.noop,
7697 $.noop,
7698 $.proxy( this, "_openPrereqsComplete" ) );
7699
7700 this._currentTransition = o.transition;
7701 this._applyTransition( o.transition );
7702
7703 if ( !this.options.theme ) {
7704 this._setTheme( this._page.jqmData( "theme" ) || $.mobile.getInheritedTheme( this._page, "c" ) );
7705 }
7706
7707 this._ui.screen.removeClass( "ui-screen-hidden" );
7708 this._ui.container.removeClass( "ui-popup-hidden" );
7709
7710 // Give applications a chance to modify the contents of the container before it appears
7711 this._reposition( o );
7712
7713 if ( this.options.overlayTheme && androidBlacklist ) {
7714 /* TODO:
7715 The native browser on Android 4.0.X ("Ice Cream Sandwich") suffers from an issue where the popup overlay appears to be z-indexed
7716 above the popup itself when certain other styles exist on the same page -- namely, any element set to `position: fixed` and certain
7717 types of input. These issues are reminiscent of previously uncovered bugs in older versions of Android's native browser:
7718 https://github.com/scottjehl/Device-Bugs/issues/3
7719
7720 This fix closes the following bugs ( I use "closes" with reluctance, and stress that this issue should be revisited as soon as possible ):
7721
7722 https://github.com/jquery/jquery-mobile/issues/4816
7723 https://github.com/jquery/jquery-mobile/issues/4844
7724 https://github.com/jquery/jquery-mobile/issues/4874
7725 */
7726
7727 // TODO sort out why this._page isn't working
7728 this.element.closest( ".ui-page" ).addClass( "ui-popup-open" );
7729 }
7730 this._animate({
7731 additionalCondition: true,
7732 transition: o.transition,
7733 classToRemove: "",
7734 screenClassToAdd: "in",
7735 containerClassToAdd: "in",
7736 applyTransition: false,
7737 prereqs: this._prereqs
7738 });
7739 },
7740
7741 _closePrereqScreen: function() {
7742 this._ui.screen
7743 .removeClass( "out" )
7744 .addClass( "ui-screen-hidden" );
7745 },
7746
7747 _closePrereqContainer: function() {
7748 this._ui.container
7749 .removeClass( "reverse out" )
7750 .addClass( "ui-popup-hidden" )
7751 .removeAttr( "style" );
7752 },
7753
7754 _closePrereqsDone: function() {
7755 var opts = this.options;
7756
7757 this._ui.container.removeAttr( "tabindex" );
7758
7759 // remove the global mutex for popups
7760 $.mobile.popup.active = undefined;
7761
7762 // alert users that the popup is closed
7763 this._trigger( "afterclose" );
7764 },
7765
7766 _close: function( immediate ) {
7767 this._ui.container.removeClass( "ui-popup-active" );
7768 this._page.removeClass( "ui-popup-open" );
7769
7770 this._isOpen = false;
7771
7772 // Count down to triggering "popupafterclose" - we have two prerequisites:
7773 // 1. The popup window reverse animation completes (container())
7774 // 2. The screen opacity animation completes (screen())
7775 this._createPrereqs(
7776 $.proxy( this, "_closePrereqScreen" ),
7777 $.proxy( this, "_closePrereqContainer" ),
7778 $.proxy( this, "_closePrereqsDone" ) );
7779
7780 this._animate( {
7781 additionalCondition: this._ui.screen.hasClass( "in" ),
7782 transition: ( immediate ? "none" : ( this._currentTransition ) ),
7783 classToRemove: "in",
7784 screenClassToAdd: "out",
7785 containerClassToAdd: "reverse out",
7786 applyTransition: true,
7787 prereqs: this._prereqs
7788 });
7789 },
7790
7791 _unenhance: function() {
7792 // Put the element back to where the placeholder was and remove the "ui-popup" class
7793 this._setTheme( "none" );
7794 this.element
7795 // Cannot directly insertAfter() - we need to detach() first, because
7796 // insertAfter() will do nothing if the payload div was not attached
7797 // to the DOM at the time the widget was created, and so the payload
7798 // will remain inside the container even after we call insertAfter().
7799 // If that happens and we remove the container a few lines below, we
7800 // will cause an infinite recursion - #5244
7801 .detach()
7802 .insertAfter( this._ui.placeholder )
7803 .removeClass( "ui-popup ui-overlay-shadow ui-corner-all" );
7804 this._ui.screen.remove();
7805 this._ui.container.remove();
7806 this._ui.placeholder.remove();
7807 },
7808
7809 _destroy: function() {
7810 if ( $.mobile.popup.active === this ) {
7811 this.element.one( "popupafterclose", $.proxy( this, "_unenhance" ) );
7812 this.close();
7813 } else {
7814 this._unenhance();
7815 }
7816 },
7817
7818 _closePopup: function( e, data ) {
7819 var parsedDst, toUrl, o = this.options, immediate = false;
7820
7821 // restore location on screen
7822 window.scrollTo( 0, this._scrollTop );
7823
7824 if ( e && e.type === "pagebeforechange" && data ) {
7825 // Determine whether we need to rapid-close the popup, or whether we can
7826 // take the time to run the closing transition
7827 if ( typeof data.toPage === "string" ) {
7828 parsedDst = data.toPage;
7829 } else {
7830 parsedDst = data.toPage.jqmData( "url" );
7831 }
7832 parsedDst = $.mobile.path.parseUrl( parsedDst );
7833 toUrl = parsedDst.pathname + parsedDst.search + parsedDst.hash;
7834
7835 if ( this._myUrl !== $.mobile.path.makeUrlAbsolute( toUrl ) ) {
7836 // Going to a different page - close immediately
7837 immediate = true;
7838 } else {
7839 e.preventDefault();
7840 }
7841 }
7842
7843 // remove nav bindings
7844 o.container.unbind( o.closeEvents );
7845 // unbind click handlers added when history is disabled
7846 this.element.undelegate( o.closeLinkSelector, o.closeLinkEvents );
7847
7848 this._close( immediate );
7849 },
7850
7851 // any navigation event after a popup is opened should close the popup
7852 // NOTE the pagebeforechange is bound to catch navigation events that don't
7853 // alter the url (eg, dialogs from popups)
7854 _bindContainerClose: function() {
7855 this.options.container
7856 .one( this.options.closeEvents, $.proxy( this, "_closePopup" ) );
7857 },
7858
7859 // TODO no clear deliniation of what should be here and
7860 // what should be in _open. Seems to be "visual" vs "history" for now
7861 open: function( options ) {
7862 var self = this, opts = this.options, url, hashkey, activePage, currentIsDialog, hasHash, urlHistory;
7863
7864 // make sure open is idempotent
7865 if( $.mobile.popup.active ) {
7866 return;
7867 }
7868
7869 // set the global popup mutex
7870 $.mobile.popup.active = this;
7871 this._scrollTop = $.mobile.window.scrollTop();
7872
7873 // if history alteration is disabled close on navigate events
7874 // and leave the url as is
7875 if( !( opts.history ) ) {
7876 self._open( options );
7877 self._bindContainerClose();
7878
7879 // When histoy is disabled we have to grab the data-rel
7880 // back link clicks so we can close the popup instead of
7881 // relying on history to do it for us
7882 self.element
7883 .delegate( opts.closeLinkSelector, opts.closeLinkEvents, function( e ) {
7884 self.close();
7885 e.preventDefault();
7886 });
7887
7888 return;
7889 }
7890
7891 // cache some values for min/readability
7892 urlHistory = $.mobile.urlHistory;
7893 hashkey = $.mobile.dialogHashKey;
7894 activePage = $.mobile.activePage;
7895 currentIsDialog = activePage.is( ".ui-dialog" );
7896 this._myUrl = url = urlHistory.getActive().url;
7897 hasHash = ( url.indexOf( hashkey ) > -1 ) && !currentIsDialog && ( urlHistory.activeIndex > 0 );
7898
7899 if ( hasHash ) {
7900 self._open( options );
7901 self._bindContainerClose();
7902 return;
7903 }
7904
7905 // if the current url has no dialog hash key proceed as normal
7906 // otherwise, if the page is a dialog simply tack on the hash key
7907 if ( url.indexOf( hashkey ) === -1 && !currentIsDialog ){
7908 url = url + (url.indexOf( "#" ) > -1 ? hashkey : "#" + hashkey);
7909 } else {
7910 url = $.mobile.path.parseLocation().hash + hashkey;
7911 }
7912
7913 // Tack on an extra hashkey if this is the first page and we've just reconstructed the initial hash
7914 if ( urlHistory.activeIndex === 0 && url === urlHistory.initialDst ) {
7915 url += hashkey;
7916 }
7917
7918 // swallow the the initial navigation event, and bind for the next
7919 $(window).one( "beforenavigate", function( e ) {
7920 e.preventDefault();
7921 self._open( options );
7922 self._bindContainerClose();
7923 });
7924
7925 this.urlAltered = true;
7926 $.mobile.navigate( url, {role: "dialog"} );
7927 },
7928
7929 close: function() {
7930 // make sure close is idempotent
7931 if( $.mobile.popup.active !== this ) {
7932 return;
7933 }
7934
7935 this._scrollTop = $.mobile.window.scrollTop();
7936
7937 if( this.options.history && this.urlAltered ) {
7938 $.mobile.back();
7939 this.urlAltered = false;
7940 } else {
7941 // simulate the nav bindings having fired
7942 this._closePopup();
7943 }
7944 }
7945 });
7946
7947
7948 // TODO this can be moved inside the widget
7949 $.mobile.popup.handleLink = function( $link ) {
7950 var closestPage = $link.closest( ":jqmData(role='page')" ),
7951 scope = ( ( closestPage.length === 0 ) ? $( "body" ) : closestPage ),
7952 // NOTE make sure to get only the hash, ie7 (wp7) return the absolute href
7953 // in this case ruining the element selection
7954 popup = $( $.mobile.path.parseUrl($link.attr( "href" )).hash, scope[0] ),
7955 offset;
7956
7957 if ( popup.data( "mobile-popup" ) ) {
7958 offset = $link.offset();
7959 popup.popup( "open", {
7960 x: offset.left + $link.outerWidth() / 2,
7961 y: offset.top + $link.outerHeight() / 2,
7962 transition: $link.jqmData( "transition" ),
7963 positionTo: $link.jqmData( "position-to" )
7964 });
7965 }
7966
7967 //remove after delay
7968 setTimeout( function() {
7969 // Check if we are in a listview
7970 var $parent = $link.parent().parent();
7971 if ($parent.hasClass("ui-li")) {
7972 $link = $parent.parent();
7973 }
7974 $link.removeClass( $.mobile.activeBtnClass );
7975 }, 300 );
7976 };
7977
7978 // TODO move inside _create
7979 $.mobile.document.bind( "pagebeforechange", function( e, data ) {
7980 if ( data.options.role === "popup" ) {
7981 $.mobile.popup.handleLink( data.options.link );
7982 e.preventDefault();
7983 }
7984 });
7985
7986 $.mobile.document.bind( "pagecreate create", function( e ) {
7987 $.mobile.popup.prototype.enhanceWithin( e.target, true );
7988 });
7989
7990})( jQuery );
7991
7992(function( $, undefined ) {
7993
7994$.widget( "mobile.panel", $.mobile.widget, {
7995 options: {
7996 classes: {
7997 panel: "ui-panel",
7998 panelOpen: "ui-panel-open",
7999 panelClosed: "ui-panel-closed",
8000 panelFixed: "ui-panel-fixed",
8001 panelInner: "ui-panel-inner",
8002 modal: "ui-panel-dismiss",
8003 modalOpen: "ui-panel-dismiss-open",
8004 pagePanel: "ui-page-panel",
8005 pagePanelOpen: "ui-page-panel-open",
8006 contentWrap: "ui-panel-content-wrap",
8007 contentWrapOpen: "ui-panel-content-wrap-open",
8008 contentWrapClosed: "ui-panel-content-wrap-closed",
8009 contentFixedToolbar: "ui-panel-content-fixed-toolbar",
8010 contentFixedToolbarOpen: "ui-panel-content-fixed-toolbar-open",
8011 contentFixedToolbarClosed: "ui-panel-content-fixed-toolbar-closed",
8012 animate: "ui-panel-animate"
8013 },
8014 animate: true,
8015 theme: "c",
8016 position: "left",
8017 dismissible: true,
8018 display: "reveal", //accepts reveal, push, overlay
8019 initSelector: ":jqmData(role='panel')",
8020 swipeClose: true,
8021 positionFixed: false
8022 },
8023
8024 _panelID: null,
8025 _closeLink: null,
8026 _page: null,
8027 _modal: null,
8028 _pannelInner: null,
8029 _wrapper: null,
8030 _fixedToolbar: null,
8031
8032 _create: function() {
8033 var self = this,
8034 $el = self.element,
8035 page = $el.closest( ":jqmData(role='page')" ),
8036 _getPageTheme = function() {
8037 var $theme = $.data( page[0], "mobilePage" ).options.theme,
8038 $pageThemeClass = "ui-body-" + $theme;
8039 return $pageThemeClass;
8040 },
8041 _getPanelInner = function() {
8042 var $pannelInner = $el.find( "." + self.options.classes.panelInner );
8043 if ( $pannelInner.length === 0 ) {
8044 $pannelInner = $el.children().wrapAll( '<div class="' + self.options.classes.panelInner + '" />' ).parent();
8045 }
8046 return $pannelInner;
8047 },
8048 _getWrapper = function() {
8049 var $wrapper = page.find( "." + self.options.classes.contentWrap );
8050 if ( $wrapper.length === 0 ) {
8051 $wrapper = page.children( ".ui-header:not(:jqmData(position='fixed')), .ui-content:not(:jqmData(role='popup')), .ui-footer:not(:jqmData(position='fixed'))" ).wrapAll( '<div class="' + self.options.classes.contentWrap + ' ' + _getPageTheme() + '" />' ).parent();
8052 if ( $.support.cssTransform3d && !!self.options.animate ) {
8053 $wrapper.addClass( self.options.classes.animate );
8054 }
8055 }
8056 return $wrapper;
8057 },
8058 _getFixedToolbar = function() {
8059 var $fixedToolbar = page.find( "." + self.options.classes.contentFixedToolbar );
8060 if ( $fixedToolbar.length === 0 ) {
8061 $fixedToolbar = page.find( ".ui-header:jqmData(position='fixed'), .ui-footer:jqmData(position='fixed')" ).addClass( self.options.classes.contentFixedToolbar );
8062 if ( $.support.cssTransform3d && !!self.options.animate ) {
8063 $fixedToolbar.addClass( self.options.classes.animate );
8064 }
8065 }
8066 return $fixedToolbar;
8067 };
8068
8069 // expose some private props to other methods
8070 $.extend( this, {
8071 _panelID: $el.attr( "id" ),
8072 _closeLink: $el.find( ":jqmData(rel='close')" ),
8073 _page: $el.closest( ":jqmData(role='page')" ),
8074 _pageTheme: _getPageTheme(),
8075 _pannelInner: _getPanelInner(),
8076 _wrapper: _getWrapper(),
8077 _fixedToolbar: _getFixedToolbar()
8078 });
8079
8080 self._addPanelClasses();
8081 self._wrapper.addClass( this.options.classes.contentWrapClosed );
8082 self._fixedToolbar.addClass( this.options.classes.contentFixedToolbarClosed );
8083 // add class to page so we can set "overflow-x: hidden;" for it to fix Android zoom issue
8084 self._page.addClass( self.options.classes.pagePanel );
8085
8086 // if animating, add the class to do so
8087 if ( $.support.cssTransform3d && !!self.options.animate ) {
8088 this.element.addClass( self.options.classes.animate );
8089 }
8090
8091 self._bindUpdateLayout();
8092 self._bindCloseEvents();
8093 self._bindLinkListeners();
8094 self._bindPageEvents();
8095
8096 if ( !!self.options.dismissible ) {
8097 self._createModal();
8098 }
8099
8100 self._bindSwipeEvents();
8101 },
8102
8103 _createModal: function( options ) {
8104 var self = this;
8105
8106 self._modal = $( "<div class='" + self.options.classes.modal + "' data-panelid='" + self._panelID + "'></div>" )
8107 .on( "mousedown", function() {
8108 self.close();
8109 })
8110 .appendTo( this._page );
8111 },
8112
8113 _getPosDisplayClasses: function( prefix ) {
8114 return prefix + "-position-" + this.options.position + " " + prefix + "-display-" + this.options.display;
8115 },
8116
8117 _getPanelClasses: function() {
8118 var panelClasses = this.options.classes.panel +
8119 " " + this._getPosDisplayClasses( this.options.classes.panel ) +
8120 " " + this.options.classes.panelClosed;
8121
8122 if ( this.options.theme ) {
8123 panelClasses += " ui-body-" + this.options.theme;
8124 }
8125 if ( !!this.options.positionFixed ) {
8126 panelClasses += " " + this.options.classes.panelFixed;
8127 }
8128 return panelClasses;
8129 },
8130
8131 _addPanelClasses: function() {
8132 this.element.addClass( this._getPanelClasses() );
8133 },
8134
8135 _bindCloseEvents: function() {
8136 var self = this;
8137
8138 self._closeLink.on( "click.panel" , function( e ) {
8139 e.preventDefault();
8140 self.close();
8141 return false;
8142 });
8143 self.element.on( "click.panel" , "a:jqmData(ajax='false')", function( e ) {
8144 self.close();
8145 });
8146 },
8147
8148 _positionPanel: function() {
8149 var self = this,
8150 pannelInnerHeight = self._pannelInner.outerHeight(),
8151 expand = pannelInnerHeight > $.mobile.getScreenHeight();
8152
8153 if ( expand || !self.options.positionFixed ) {
8154 if ( expand ) {
8155 self._unfixPanel();
8156 $.mobile.resetActivePageHeight( pannelInnerHeight );
8157 }
8158 self._scrollIntoView( pannelInnerHeight );
8159 } else {
8160 self._fixPanel();
8161 }
8162 },
8163
8164 _scrollIntoView: function( pannelInnerHeight ) {
8165 if ( pannelInnerHeight < $( window ).scrollTop() ) {
8166 window.scrollTo( 0, 0 );
8167 }
8168 },
8169
8170 _bindFixListener: function() {
8171 this._on( $( window ), { "throttledresize": "_positionPanel" });
8172 },
8173
8174 _unbindFixListener: function() {
8175 this._off( $( window ), "throttledresize" );
8176 },
8177
8178 _unfixPanel: function() {
8179 if ( !!this.options.positionFixed && $.support.fixedPosition ) {
8180 this.element.removeClass( this.options.classes.panelFixed );
8181 }
8182 },
8183
8184 _fixPanel: function() {
8185 if ( !!this.options.positionFixed && $.support.fixedPosition ) {
8186 this.element.addClass( this.options.classes.panelFixed );
8187 }
8188 },
8189
8190 _bindUpdateLayout: function() {
8191 var self = this;
8192
8193 self.element.on( "updatelayout", function( e ) {
8194 if ( self._open ) {
8195 self._positionPanel();
8196 }
8197 });
8198 },
8199
8200 _bindLinkListeners: function() {
8201 var self = this;
8202
8203 self._page.on( "click.panel" , "a", function( e ) {
8204 if ( this.href.split( "#" )[ 1 ] === self._panelID && self._panelID !== undefined ) {
8205 e.preventDefault();
8206 var $link = $( this );
8207 if ( $link.is( ":jqmData(role='button')" ) ) {
8208 $link.addClass( $.mobile.activeBtnClass );
8209 self.element.one( "panelopen panelclose", function() {
8210 $link.removeClass( $.mobile.activeBtnClass );
8211 });
8212 }
8213 self.toggle();
8214 return false;
8215 }
8216 });
8217 },
8218
8219 _bindSwipeEvents: function() {
8220 var self = this,
8221 area = self._modal ? self.element.add( self._modal ) : self.element;
8222
8223 // on swipe, close the panel
8224 if( !!self.options.swipeClose ) {
8225 if ( self.options.position === "left" ) {
8226 area.on( "swipeleft.panel", function( e ) {
8227 self.close();
8228 });
8229 } else {
8230 area.on( "swiperight.panel", function( e ) {
8231 self.close();
8232 });
8233 }
8234 }
8235 },
8236
8237 _bindPageEvents: function() {
8238 var self = this;
8239
8240 self._page
8241 // Close the panel if another panel on the page opens
8242 .on( "panelbeforeopen", function( e ) {
8243 if ( self._open && e.target !== self.element[ 0 ] ) {
8244 self.close();
8245 }
8246 })
8247 // clean up open panels after page hide
8248 .on( "pagehide", function( e ) {
8249 if ( self._open ) {
8250 self.close( true );
8251 }
8252 })
8253 // on escape, close? might need to have a target check too...
8254 .on( "keyup.panel", function( e ) {
8255 if ( e.keyCode === 27 && self._open ) {
8256 self.close();
8257 }
8258 });
8259 },
8260
8261 // state storage of open or closed
8262 _open: false,
8263
8264 _contentWrapOpenClasses: null,
8265 _fixedToolbarOpenClasses: null,
8266 _modalOpenClasses: null,
8267
8268 open: function( immediate ) {
8269 if ( !this._open ) {
8270 var self = this,
8271 o = self.options,
8272 _openPanel = function() {
8273 self._page.off( "panelclose" );
8274 self._page.jqmData( "panel", "open" );
8275
8276 if ( !immediate && $.support.cssTransform3d && !!o.animate ) {
8277 self.element.add( self._wrapper ).on( self._transitionEndEvents, complete );
8278 } else {
8279 setTimeout( complete, 0 );
8280 }
8281
8282 if ( self.options.theme && self.options.display !== "overlay" ) {
8283 self._page
8284 .removeClass( self._pageTheme )
8285 .addClass( "ui-body-" + self.options.theme );
8286 }
8287
8288 self.element.removeClass( o.classes.panelClosed ).addClass( o.classes.panelOpen );
8289
8290 self._contentWrapOpenClasses = self._getPosDisplayClasses( o.classes.contentWrap );
8291 self._wrapper
8292 .removeClass( o.classes.contentWrapClosed )
8293 .addClass( self._contentWrapOpenClasses + " " + o.classes.contentWrapOpen );
8294
8295 self._fixedToolbarOpenClasses = self._getPosDisplayClasses( o.classes.contentFixedToolbar );
8296 self._fixedToolbar
8297 .removeClass( o.classes.contentFixedToolbarClosed )
8298 .addClass( self._fixedToolbarOpenClasses + " " + o.classes.contentFixedToolbarOpen );
8299
8300 self._modalOpenClasses = self._getPosDisplayClasses( o.classes.modal ) + " " + o.classes.modalOpen;
8301 if ( self._modal ) {
8302 self._modal.addClass( self._modalOpenClasses );
8303 }
8304 },
8305 complete = function() {
8306 self.element.add( self._wrapper ).off( self._transitionEndEvents, complete );
8307
8308 self._page.addClass( o.classes.pagePanelOpen );
8309
8310 self._positionPanel();
8311 self._bindFixListener();
8312
8313 self._trigger( "open" );
8314 };
8315
8316 if ( this.element.closest( ".ui-page-active" ).length < 0 ) {
8317 immediate = true;
8318 }
8319
8320 self._trigger( "beforeopen" );
8321
8322 if ( self._page.jqmData('panel') === "open" ) {
8323 self._page.on( "panelclose", function() {
8324 _openPanel();
8325 });
8326 } else {
8327 _openPanel();
8328 }
8329
8330 self._open = true;
8331 }
8332 },
8333
8334 close: function( immediate ) {
8335 if ( this._open ) {
8336 var o = this.options,
8337 self = this,
8338 _closePanel = function() {
8339 if ( !immediate && $.support.cssTransform3d && !!o.animate ) {
8340 self.element.add( self._wrapper ).on( self._transitionEndEvents, complete );
8341 } else {
8342 setTimeout( complete, 0 );
8343 }
8344
8345 self._page.removeClass( o.classes.pagePanelOpen );
8346 self.element.removeClass( o.classes.panelOpen );
8347 self._wrapper.removeClass( o.classes.contentWrapOpen );
8348 self._fixedToolbar.removeClass( o.classes.contentFixedToolbarOpen );
8349
8350 if ( self._modal ) {
8351 self._modal.removeClass( self._modalOpenClasses );
8352 }
8353 },
8354 complete = function() {
8355 if ( self.options.theme && self.options.display !== "overlay" ) {
8356 self._page.removeClass( "ui-body-" + self.options.theme ).addClass( self._pageTheme );
8357 }
8358 self.element.add( self._wrapper ).off( self._transitionEndEvents, complete );
8359 self.element.addClass( o.classes.panelClosed );
8360
8361 self._wrapper
8362 .removeClass( self._contentWrapOpenClasses )
8363 .addClass( o.classes.contentWrapClosed );
8364
8365 self._fixedToolbar
8366 .removeClass( self._fixedToolbarOpenClasses )
8367 .addClass( o.classes.contentFixedToolbarClosed );
8368
8369 self._fixPanel();
8370 self._unbindFixListener();
8371 $.mobile.resetActivePageHeight();
8372
8373 self._page.jqmRemoveData( "panel" );
8374 self._trigger( "close" );
8375 };
8376
8377 if ( this.element.closest( ".ui-page-active" ).length < 0 ) {
8378 immediate = true;
8379 }
8380 self._trigger( "beforeclose" );
8381
8382 _closePanel();
8383
8384 self._open = false;
8385 }
8386 },
8387
8388 toggle: function( options ) {
8389 this[ this._open ? "close" : "open" ]();
8390 },
8391
8392 _transitionEndEvents: "webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd",
8393
8394 _destroy: function() {
8395 var classes = this.options.classes,
8396 theme = this.options.theme,
8397 hasOtherSiblingPanels = this.element.siblings( "." + classes.panel ).length;
8398
8399 // create
8400 if ( !hasOtherSiblingPanels ) {
8401 this._wrapper.children().unwrap();
8402 this._page.find( "a" ).unbind( "panelopen panelclose" );
8403 this._page.removeClass( classes.pagePanel );
8404 if ( this._open ) {
8405 this._page.jqmRemoveData( "panel" );
8406 this._page.removeClass( classes.pagePanelOpen );
8407 if ( theme ) {
8408 this._page.removeClass( "ui-body-" + theme ).addClass( this._pageTheme );
8409 }
8410 $.mobile.resetActivePageHeight();
8411 }
8412 } else if ( this._open ) {
8413 this._wrapper.removeClass( classes.contentWrapOpen );
8414 this._fixedToolbar.removeClass( classes.contentFixedToolbarOpen );
8415 this._page.jqmRemoveData( "panel" );
8416 this._page.removeClass( classes.pagePanelOpen );
8417 if ( theme ) {
8418 this._page.removeClass( "ui-body-" + theme ).addClass( this._pageTheme );
8419 }
8420 }
8421
8422 this._pannelInner.children().unwrap();
8423
8424 this.element.removeClass( [ this._getPanelClasses(), classes.panelAnimate ].join( " " ) )
8425 .off( "swipeleft.panel swiperight.panel" )
8426 .off( "panelbeforeopen" )
8427 .off( "panelhide" )
8428 .off( "keyup.panel" )
8429 .off( "updatelayout" );
8430
8431 this._closeLink.off( "click.panel" );
8432
8433 if ( this._modal ) {
8434 this._modal.remove();
8435 }
8436
8437 // open and close
8438 this.element.off( this._transitionEndEvents )
8439 .removeClass( [ classes.panelUnfixed, classes.panelClosed, classes.panelOpen ].join( " " ) );
8440 }
8441});
8442
8443//auto self-init widgets
8444$( document ).bind( "pagecreate create", function( e ) {
8445 $.mobile.panel.prototype.enhanceWithin( e.target );
8446});
8447
8448})( jQuery );
8449
8450(function( $, undefined ) {
8451
8452$.widget( "mobile.table", $.mobile.widget, {
8453
8454 options: {
8455 classes: {
8456 table: "ui-table"
8457 },
8458 initSelector: ":jqmData(role='table')"
8459 },
8460
8461 _create: function() {
8462
8463 var self = this,
8464 trs = this.element.find( "thead tr" );
8465
8466 this.element.addClass( this.options.classes.table );
8467
8468 // Expose headers and allHeaders properties on the widget
8469 // headers references the THs within the first TR in the table
8470 self.headers = this.element.find( "tr:eq(0)" ).children();
8471
8472 // allHeaders references headers, plus all THs in the thead, which may include several rows, or not
8473 self.allHeaders = self.headers.add( trs.children() );
8474
8475 trs.each(function(){
8476
8477 var coltally = 0;
8478
8479 $( this ).children().each(function( i ){
8480
8481 var span = parseInt( $( this ).attr( "colspan" ), 10 ),
8482 sel = ":nth-child(" + ( coltally + 1 ) + ")";
8483
8484 $( this )
8485 .jqmData( "colstart", coltally + 1 );
8486
8487 if( span ){
8488 for( var j = 0; j < span - 1; j++ ){
8489 coltally++;
8490 sel += ", :nth-child(" + ( coltally + 1 ) + ")";
8491 }
8492 }
8493
8494 // Store "cells" data on header as a reference to all cells in the same column as this TH
8495 $( this )
8496 .jqmData( "cells", self.element.find( "tr" ).not( trs.eq(0) ).not( this ).children( sel ) );
8497
8498 coltally++;
8499
8500 });
8501
8502 });
8503
8504 }
8505
8506});
8507
8508//auto self-init widgets
8509$.mobile.document.bind( "pagecreate create", function( e ) {
8510 $.mobile.table.prototype.enhanceWithin( e.target );
8511});
8512
8513})( jQuery );
8514
8515
8516(function( $, undefined ) {
8517
8518$.mobile.table.prototype.options.mode = "columntoggle";
8519
8520$.mobile.table.prototype.options.columnBtnTheme = null;
8521
8522$.mobile.table.prototype.options.columnPopupTheme = null;
8523
8524$.mobile.table.prototype.options.columnBtnText = "Columns...";
8525
8526$.mobile.table.prototype.options.classes = $.extend(
8527 $.mobile.table.prototype.options.classes,
8528 {
8529 popup: "ui-table-columntoggle-popup",
8530 columnBtn: "ui-table-columntoggle-btn",
8531 priorityPrefix: "ui-table-priority-",
8532 columnToggleTable: "ui-table-columntoggle"
8533 }
8534);
8535
8536$.mobile.document.delegate( ":jqmData(role='table')", "tablecreate", function() {
8537
8538 var $table = $( this ),
8539 self = $table.data( "mobile-table" ),
8540 o = self.options,
8541 ns = $.mobile.ns;
8542
8543 if( o.mode !== "columntoggle" ){
8544 return;
8545 }
8546
8547 self.element.addClass( o.classes.columnToggleTable );
8548
8549 var id = ( $table.attr( "id" ) || o.classes.popup ) + "-popup", //TODO BETTER FALLBACK ID HERE
8550 $menuButton = $( "<a href='#" + id + "' class='" + o.classes.columnBtn + "' data-" + ns + "rel='popup' data-" + ns + "mini='true'>" + o.columnBtnText + "</a>" ),
8551 $popup = $( "<div data-" + ns + "role='popup' data-" + ns + "role='fieldcontain' class='" + o.classes.popup + "' id='" + id + "'></div>"),
8552 $menu = $("<fieldset data-" + ns + "role='controlgroup'></fieldset>");
8553
8554 // create the hide/show toggles
8555 self.headers.not( "td" ).each(function(){
8556
8557 var priority = $( this ).jqmData( "priority" ),
8558 $cells = $( this ).add( $( this ).jqmData( "cells" ) );
8559
8560 if( priority ){
8561
8562 $cells.addClass( o.classes.priorityPrefix + priority );
8563
8564 $("<label><input type='checkbox' checked />" + $( this ).text() + "</label>" )
8565 .appendTo( $menu )
8566 .children( 0 )
8567 .jqmData( "cells", $cells )
8568 .checkboxradio({
8569 theme: o.columnPopupTheme
8570 });
8571 }
8572 });
8573 $menu.appendTo( $popup );
8574
8575 // bind change event listeners to inputs - TODO: move to a private method?
8576 $menu.on( "change", "input", function( e ){
8577 if( this.checked ){
8578 $( this ).jqmData( "cells" ).removeClass( "ui-table-cell-hidden" ).addClass( "ui-table-cell-visible" );
8579 }
8580 else {
8581 $( this ).jqmData( "cells" ).removeClass( "ui-table-cell-visible" ).addClass( "ui-table-cell-hidden" );
8582 }
8583 });
8584
8585 $menuButton
8586 .insertBefore( $table )
8587 .buttonMarkup({
8588 theme: o.columnBtnTheme
8589 });
8590
8591 $popup
8592 .insertBefore( $table )
8593 .popup();
8594
8595 // refresh method
8596 self.refresh = function(){
8597 $menu.find( "input" ).each( function(){
8598 this.checked = $( this ).jqmData( "cells" ).eq(0).css( "display" ) === "table-cell";
8599 $( this ).checkboxradio( "refresh" );
8600 });
8601 };
8602
8603 $.mobile.window.on( "throttledresize", self.refresh );
8604
8605 self.refresh();
8606
8607});
8608
8609})( jQuery );
8610
8611(function( $, undefined ) {
8612
8613$.mobile.table.prototype.options.mode = "reflow";
8614
8615$.mobile.table.prototype.options.classes = $.extend(
8616 $.mobile.table.prototype.options.classes,
8617 {
8618 reflowTable: "ui-table-reflow",
8619 cellLabels: "ui-table-cell-label"
8620 }
8621);
8622
8623$.mobile.document.delegate( ":jqmData(role='table')", "tablecreate", function() {
8624
8625 var $table = $( this ),
8626 self = $table.data( "mobile-table" ),
8627 o = self.options;
8628
8629 // If it's not reflow mode, return here.
8630 if( o.mode !== "reflow" ){
8631 return;
8632 }
8633
8634 self.element.addClass( o.classes.reflowTable );
8635
8636 // get headers in reverse order so that top-level headers are appended last
8637 var reverseHeaders = $( self.allHeaders.get().reverse() );
8638
8639 // create the hide/show toggles
8640 reverseHeaders.each(function(i){
8641 var $cells = $( this ).jqmData( "cells" ),
8642 colstart = $( this ).jqmData( "colstart" ),
8643 hierarchyClass = $cells.not( this ).filter( "thead th" ).length && " ui-table-cell-label-top",
8644 text = $(this).text();
8645
8646 if( text !== "" ){
8647
8648 if( hierarchyClass ){
8649 var iteration = parseInt( $( this ).attr( "colspan" ), 10 ),
8650 filter = "";
8651
8652 if( iteration ){
8653 filter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";
8654 }
8655 $cells.filter( filter ).prepend( "<b class='" + o.classes.cellLabels + hierarchyClass + "'>" + text + "</b>" );
8656 }
8657 else {
8658 $cells.prepend( "<b class='" + o.classes.cellLabels + "'>" + text + "</b>" );
8659 }
8660
8661 }
8662 });
8663
8664});
8665
8666})( jQuery );
8667
8668(function( $ ) {
8669 varmeta = $( "meta[name=viewport]" ),
8670 initialContent = meta.attr( "content" ),
8671 disabledZoom = initialContent + ",maximum-scale=1, user-scalable=no",
8672 enabledZoom = initialContent + ",maximum-scale=10, user-scalable=yes",
8673 disabledInitially = /(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test( initialContent );
8674
8675 $.mobile.zoom = $.extend( {}, {
8676 enabled: !disabledInitially,
8677 locked: false,
8678 disable: function( lock ) {
8679 if ( !disabledInitially && !$.mobile.zoom.locked ) {
8680 meta.attr( "content", disabledZoom );
8681 $.mobile.zoom.enabled = false;
8682 $.mobile.zoom.locked = lock || false;
8683 }
8684 },
8685 enable: function( unlock ) {
8686 if ( !disabledInitially && ( !$.mobile.zoom.locked || unlock === true ) ) {
8687 meta.attr( "content", enabledZoom );
8688 $.mobile.zoom.enabled = true;
8689 $.mobile.zoom.locked = false;
8690 }
8691 },
8692 restore: function() {
8693 if ( !disabledInitially ) {
8694 meta.attr( "content", initialContent );
8695 $.mobile.zoom.enabled = true;
8696 }
8697 }
8698 });
8699
8700}( jQuery ));
8701
8702(function( $, undefined ) {
8703
8704$.widget( "mobile.textinput", $.mobile.widget, {
8705 options: {
8706 theme: null,
8707 mini: false,
8708 // This option defaults to true on iOS devices.
8709 preventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1,
8710 initSelector: "input[type='text'], input[type='search'], :jqmData(type='search'), input[type='number'], :jqmData(type='number'), input[type='password'], input[type='email'], input[type='url'], input[type='tel'], textarea, input[type='time'], input[type='date'], input[type='month'], input[type='week'], input[type='datetime'], input[type='datetime-local'], input[type='color'], input:not([type]), input[type='file']",
8711 clearBtn: false,
8712 clearSearchButtonText: null, //deprecating for 1.3...
8713 clearBtnText: "clear text",
8714 disabled: false
8715 },
8716
8717 _create: function() {
8718
8719 var self = this,
8720 input = this.element,
8721 o = this.options,
8722 theme = o.theme || $.mobile.getInheritedTheme( this.element, "c" ),
8723 themeclass = " ui-body-" + theme,
8724 miniclass = o.mini ? " ui-mini" : "",
8725 isSearch = input.is( "[type='search'], :jqmData(type='search')" ),
8726 focusedEl,
8727 clearbtn,
8728 clearBtnText = o.clearSearchButtonText || o.clearBtnText,
8729 clearBtnBlacklist = input.is( "textarea, :jqmData(type='range')" ),
8730 inputNeedsClearBtn = !!o.clearBtn && !clearBtnBlacklist,
8731 inputNeedsWrap = input.is( "input" ) && !input.is( ":jqmData(type='range')" );
8732
8733 function toggleClear() {
8734 setTimeout( function() {
8735 clearbtn.toggleClass( "ui-input-clear-hidden", !input.val() );
8736 }, 0 );
8737 }
8738
8739 $( "label[for='" + input.attr( "id" ) + "']" ).addClass( "ui-input-text" );
8740
8741 focusedEl = input.addClass( "ui-input-text ui-body-"+ theme );
8742
8743 // XXX: Temporary workaround for issue 785 (Apple bug 8910589).
8744 // Turn off autocorrect and autocomplete on non-iOS 5 devices
8745 // since the popup they use can't be dismissed by the user. Note
8746 // that we test for the presence of the feature by looking for
8747 // the autocorrect property on the input element. We currently
8748 // have no test for iOS 5 or newer so we're temporarily using
8749 // the touchOverflow support flag for jQM 1.0. Yes, I feel dirty. - jblas
8750 if ( typeof input[0].autocorrect !== "undefined" && !$.support.touchOverflow ) {
8751 // Set the attribute instead of the property just in case there
8752 // is code that attempts to make modifications via HTML.
8753 input[0].setAttribute( "autocorrect", "off" );
8754 input[0].setAttribute( "autocomplete", "off" );
8755 }
8756
8757 //"search" and "text" input widgets
8758 if ( isSearch ) {
8759 focusedEl = input.wrap( "<div class='ui-input-search ui-shadow-inset ui-btn-corner-all ui-btn-shadow ui-icon-searchfield" + themeclass + miniclass + "'></div>" ).parent();
8760 } else if ( inputNeedsWrap ) {
8761 focusedEl = input.wrap( "<div class='ui-input-text ui-shadow-inset ui-corner-all ui-btn-shadow" + themeclass + miniclass + "'></div>" ).parent();
8762 }
8763
8764 if( inputNeedsClearBtn || isSearch ) {
8765 clearbtn = $( "<a href='#' class='ui-input-clear' title='" + clearBtnText + "'>" + clearBtnText + "</a>" )
8766 .bind( "click", function( event ) {
8767 input
8768 .val( "" )
8769 .focus()
8770 .trigger( "change" );
8771 clearbtn.addClass( "ui-input-clear-hidden" );
8772 event.preventDefault();
8773 })
8774 .appendTo( focusedEl )
8775 .buttonMarkup({
8776 icon: "delete",
8777 iconpos: "notext",
8778 corners: true,
8779 shadow: true,
8780 mini: o.mini
8781 });
8782
8783 if ( !isSearch ) {
8784 focusedEl.addClass( "ui-input-has-clear" );
8785 }
8786
8787 toggleClear();
8788
8789 input.bind( "paste cut keyup input focus change blur", toggleClear );
8790 }
8791 else if ( !inputNeedsWrap && !isSearch ) {
8792 input.addClass( "ui-corner-all ui-shadow-inset" + themeclass + miniclass );
8793 }
8794
8795 input.focus(function() {
8796 // In many situations, iOS will zoom into the input upon tap, this prevents that from happening
8797 if ( o.preventFocusZoom ) {
8798 $.mobile.zoom.disable( true );
8799 }
8800 focusedEl.addClass( $.mobile.focusClass );
8801 })
8802 .blur(function() {
8803 focusedEl.removeClass( $.mobile.focusClass );
8804 if ( o.preventFocusZoom ) {
8805 $.mobile.zoom.enable( true );
8806 }
8807 })
8808
8809 // Autogrow
8810 if ( input.is( "textarea" ) ) {
8811 var extraLineHeight = 15,
8812 keyupTimeoutBuffer = 100,
8813 keyupTimeout;
8814
8815 this._keyup = function() {
8816 var scrollHeight = input[ 0 ].scrollHeight,
8817 clientHeight = input[ 0 ].clientHeight;
8818
8819 if ( clientHeight < scrollHeight ) {
8820 input.height( scrollHeight + extraLineHeight );
8821 }
8822 };
8823
8824 input.on( "keyup change input paste", function() {
8825 clearTimeout( keyupTimeout );
8826 keyupTimeout = setTimeout( self._keyup, keyupTimeoutBuffer );
8827 });
8828
8829 // binding to pagechange here ensures that for pages loaded via
8830 // ajax the height is recalculated without user input
8831 this._on( $.mobile.document, { "pagechange": "_keyup" });
8832
8833 // Issue 509: the browser is not providing scrollHeight properly until the styles load
8834 if ( $.trim( input.val() ) ) {
8835 // bind to the window load to make sure the height is calculated based on BOTH
8836 // the DOM and CSS
8837 this._on( $.mobile.window, {"load": "_keyup"});
8838 }
8839 }
8840 if ( input.attr( "disabled" ) ) {
8841 this.disable();
8842 }
8843 },
8844
8845 disable: function() {
8846 var $el,
8847 isSearch = this.element.is( "[type='search'], :jqmData(type='search')" ),
8848 inputNeedsWrap = this.element.is( "input" ) && !this.element.is( ":jqmData(type='range')" ),
8849 parentNeedsDisabled = this.element.attr( "disabled", true )&& ( inputNeedsWrap || isSearch );
8850
8851 if ( parentNeedsDisabled ) {
8852 $el = this.element.parent();
8853 } else {
8854 $el = this.element;
8855 }
8856 $el.addClass( "ui-disabled" );
8857 return this._setOption( "disabled", true );
8858 },
8859
8860 enable: function() {
8861 var $el,
8862 isSearch = this.element.is( "[type='search'], :jqmData(type='search')" ),
8863 inputNeedsWrap = this.element.is( "input" ) && !this.element.is( ":jqmData(type='range')" ),
8864 parentNeedsEnabled = this.element.attr( "disabled", false )&& ( inputNeedsWrap || isSearch );
8865
8866 if ( parentNeedsEnabled ) {
8867 $el = this.element.parent();
8868 } else {
8869 $el = this.element;
8870 }
8871 $el.removeClass( "ui-disabled" );
8872 return this._setOption( "disabled", false );
8873 }
8874});
8875
8876//auto self-init widgets
8877$.mobile.document.bind( "pagecreate create", function( e ) {
8878 $.mobile.textinput.prototype.enhanceWithin( e.target, true );
8879});
8880
8881})( jQuery );
8882
8883(function( $, undefined ) {
8884
8885$.mobile.listview.prototype.options.filter = false;
8886$.mobile.listview.prototype.options.filterPlaceholder = "Filter items...";
8887$.mobile.listview.prototype.options.filterTheme = "c";
8888$.mobile.listview.prototype.options.filterReveal = false;
8889// TODO rename callback/deprecate and default to the item itself as the first argument
8890var defaultFilterCallback = function( text, searchValue, item ) {
8891 return text.toString().toLowerCase().indexOf( searchValue ) === -1;
8892 };
8893
8894$.mobile.listview.prototype.options.filterCallback = defaultFilterCallback;
8895
8896$.mobile.document.delegate( "ul, ol", "listviewcreate", function() {
8897
8898 var list = $( this ),
8899 listview = list.data( "mobile-listview" );
8900
8901 if ( !listview.options.filter ) {
8902 return;
8903 }
8904
8905 if ( listview.options.filterReveal ) {
8906 list.children().addClass( "ui-screen-hidden" );
8907 }
8908
8909 var wrapper = $( "<form>", {
8910 "class": "ui-listview-filter ui-bar-" + listview.options.filterTheme,
8911 "role": "search"
8912 }).submit( function( e ) {
8913 e.preventDefault();
8914 search.blur();
8915 }),
8916 onKeyUp = function( e ) {
8917 var $this = $( this ),
8918 val = this.value.toLowerCase(),
8919 listItems = null,
8920 li = list.children(),
8921 lastval = $this.jqmData( "lastval" ) + "",
8922 childItems = false,
8923 itemtext = "",
8924 item,
8925 // Check if a custom filter callback applies
8926 isCustomFilterCallback = listview.options.filterCallback !== defaultFilterCallback;
8927
8928 if ( lastval && lastval === val ) {
8929 // Execute the handler only once per value change
8930 return;
8931 }
8932
8933 listview._trigger( "beforefilter", "beforefilter", { input: this } );
8934
8935 // Change val as lastval for next execution
8936 $this.jqmData( "lastval" , val );
8937 if ( isCustomFilterCallback || val.length < lastval.length || val.indexOf( lastval ) !== 0 ) {
8938
8939 // Custom filter callback applies or removed chars or pasted something totally different, check all items
8940 listItems = list.children();
8941 } else {
8942
8943 // Only chars added, not removed, only use visible subset
8944 listItems = list.children( ":not(.ui-screen-hidden)" );
8945
8946 if ( !listItems.length && listview.options.filterReveal ) {
8947 listItems = list.children( ".ui-screen-hidden" );
8948 }
8949 }
8950
8951 if ( val ) {
8952
8953 // This handles hiding regular rows without the text we search for
8954 // and any list dividers without regular rows shown under it
8955
8956 for ( var i = listItems.length - 1; i >= 0; i-- ) {
8957 item = $( listItems[ i ] );
8958 itemtext = item.jqmData( "filtertext" ) || item.text();
8959
8960 if ( item.is( "li:jqmData(role=list-divider)" ) ) {
8961
8962 item.toggleClass( "ui-filter-hidequeue" , !childItems );
8963
8964 // New bucket!
8965 childItems = false;
8966
8967 } else if ( listview.options.filterCallback( itemtext, val, item ) ) {
8968
8969 //mark to be hidden
8970 item.toggleClass( "ui-filter-hidequeue" , true );
8971 } else {
8972
8973 // There's a shown item in the bucket
8974 childItems = true;
8975 }
8976 }
8977
8978 // Show items, not marked to be hidden
8979 listItems
8980 .filter( ":not(.ui-filter-hidequeue)" )
8981 .toggleClass( "ui-screen-hidden", false );
8982
8983 // Hide items, marked to be hidden
8984 listItems
8985 .filter( ".ui-filter-hidequeue" )
8986 .toggleClass( "ui-screen-hidden", true )
8987 .toggleClass( "ui-filter-hidequeue", false );
8988
8989 } else {
8990
8991 //filtervalue is empty => show all
8992 listItems.toggleClass( "ui-screen-hidden", !!listview.options.filterReveal );
8993 }
8994 listview._addFirstLastClasses( li, listview._getVisibles( li, false ), false );
8995 },
8996 search = $( "<input>", {
8997 placeholder: listview.options.filterPlaceholder
8998 })
8999 .attr( "data-" + $.mobile.ns + "type", "search" )
9000 .jqmData( "lastval", "" )
9001 .bind( "keyup change input", onKeyUp )
9002 .appendTo( wrapper )
9003 .textinput();
9004
9005 if ( listview.options.inset ) {
9006 wrapper.addClass( "ui-listview-filter-inset" );
9007 }
9008
9009 wrapper.bind( "submit", function() {
9010 return false;
9011 })
9012 .insertBefore( list );
9013});
9014
9015})( jQuery );
9016
9017(function( $, undefined ) {
9018
9019$.widget( "mobile.slider", $.mobile.widget, {
9020 widgetEventPrefix: "slide",
9021
9022 options: {
9023 theme: null,
9024 trackTheme: null,
9025 disabled: false,
9026 initSelector: "input[type='range'], :jqmData(type='range'), :jqmData(role='slider')",
9027 mini: false,
9028 highlight: false
9029 },
9030
9031 _create: function() {
9032
9033 // TODO: Each of these should have comments explain what they're for
9034 var self = this,
9035 control = this.element,
9036 parentTheme = $.mobile.getInheritedTheme( control, "c" ),
9037 theme = this.options.theme || parentTheme,
9038 trackTheme = this.options.trackTheme || parentTheme,
9039 cType = control[ 0 ].nodeName.toLowerCase(),
9040 isSelect = this.isToggleSwitch = cType === "select",
9041 isRangeslider = control.parent().is( ":jqmData(role='rangeslider')" ),
9042 selectClass = ( this.isToggleSwitch ) ? "ui-slider-switch" : "",
9043 controlID = control.attr( "id" ),
9044 $label = $( "[for='" + controlID + "']" ),
9045 labelID = $label.attr( "id" ) || controlID + "-label",
9046 label = $label.attr( "id", labelID ),
9047 min = !this.isToggleSwitch ? parseFloat( control.attr( "min" ) ) : 0,
9048 max = !this.isToggleSwitch ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length-1,
9049 step = window.parseFloat( control.attr( "step" ) || 1 ),
9050 miniClass = ( this.options.mini || control.jqmData( "mini" ) ) ? " ui-mini" : "",
9051 domHandle = document.createElement( "a" ),
9052 handle = $( domHandle ),
9053 domSlider = document.createElement( "div" ),
9054 slider = $( domSlider ),
9055 valuebg = this.options.highlight && !this.isToggleSwitch ? (function() {
9056 var bg = document.createElement( "div" );
9057 bg.className = "ui-slider-bg " + $.mobile.activeBtnClass + " ui-btn-corner-all";
9058 return $( bg ).prependTo( slider );
9059 })() : false,
9060 options;
9061
9062 domHandle.setAttribute( "href", "#" );
9063 domSlider.setAttribute( "role", "application" );
9064 domSlider.className = [this.isToggleSwitch ? "ui-slider " : "ui-slider-track ",selectClass," ui-btn-down-",trackTheme," ui-btn-corner-all", miniClass].join( "" );
9065 domHandle.className = "ui-slider-handle";
9066 domSlider.appendChild( domHandle );
9067
9068 handle.buttonMarkup({ corners: true, theme: theme, shadow: true })
9069 .attr({
9070 "role": "slider",
9071 "aria-valuemin": min,
9072 "aria-valuemax": max,
9073 "aria-valuenow": this._value(),
9074 "aria-valuetext": this._value(),
9075 "title": this._value(),
9076 "aria-labelledby": labelID
9077 });
9078
9079 $.extend( this, {
9080 slider: slider,
9081 handle: handle,
9082 type: cType,
9083 step: step,
9084 max: max,
9085 min: min,
9086 valuebg: valuebg,
9087 isRangeslider: isRangeslider,
9088 dragging: false,
9089 beforeStart: null,
9090 userModified: false,
9091 mouseMoved: false
9092 });
9093
9094 if ( this.isToggleSwitch ) {
9095 var wrapper = document.createElement( "div" );
9096 wrapper.className = "ui-slider-inneroffset";
9097
9098 for ( var j = 0, length = domSlider.childNodes.length; j < length; j++ ) {
9099 wrapper.appendChild( domSlider.childNodes[j] );
9100 }
9101
9102 domSlider.appendChild( wrapper );
9103
9104 // slider.wrapInner( "<div class='ui-slider-inneroffset'></div>" );
9105
9106 // make the handle move with a smooth transition
9107 handle.addClass( "ui-slider-handle-snapping" );
9108
9109 options = control.find( "option" );
9110
9111 for ( var i = 0, optionsCount = options.length; i < optionsCount; i++ ) {
9112 var side = !i ? "b" : "a",
9113 sliderTheme = !i ? " ui-btn-down-" + trackTheme : ( " " + $.mobile.activeBtnClass ),
9114 sliderLabel = document.createElement( "div" ),
9115 sliderImg = document.createElement( "span" );
9116
9117 sliderImg.className = ["ui-slider-label ui-slider-label-", side, sliderTheme, " ui-btn-corner-all"].join( "" );
9118 sliderImg.setAttribute( "role", "img" );
9119 sliderImg.appendChild( document.createTextNode( options[i].innerHTML ) );
9120 $( sliderImg ).prependTo( slider );
9121 }
9122
9123 self._labels = $( ".ui-slider-label", slider );
9124
9125 }
9126
9127 label.addClass( "ui-slider" );
9128
9129 // monitor the input for updated values
9130 control.addClass( this.isToggleSwitch ? "ui-slider-switch" : "ui-slider-input" );
9131
9132 this._on( control, {
9133 "change": "_controlChange",
9134 "keyup": "_controlKeyup",
9135 "blur": "_controlBlur",
9136 "vmouseup": "_controlVMouseUp"
9137 });
9138
9139 slider.bind( "vmousedown", $.proxy( this._sliderVMouseDown, this ) )
9140 .bind( "vclick", false );
9141
9142 // We have to instantiate a new function object for the unbind to work properly
9143 // since the method itself is defined in the prototype (causing it to unbind everything)
9144 this._on( document, { "vmousemove": "_preventDocumentDrag" });
9145 this._on( slider.add( document ), { "vmouseup": "_sliderVMouseUp" });
9146
9147 slider.insertAfter( control );
9148
9149 // wrap in a div for styling purposes
9150 if ( !this.isToggleSwitch && !isRangeslider ) {
9151 var wrapper = this.options.mini ? "<div class='ui-slider ui-mini'>" : "<div class='ui-slider'>";
9152
9153 control.add( slider ).wrapAll( wrapper );
9154 }
9155
9156 // Only add focus class to toggle switch, sliders get it automatically from ui-btn
9157 if ( this.isToggleSwitch ) {
9158 this.handle.bind({
9159 focus: function() {
9160 slider.addClass( $.mobile.focusClass );
9161 },
9162
9163 blur: function() {
9164 slider.removeClass( $.mobile.focusClass );
9165 }
9166 });
9167 }
9168
9169 // bind the handle event callbacks and set the context to the widget instance
9170 this._on( this.handle, {
9171 "vmousedown": "_handleVMouseDown",
9172 "keydown": "_handleKeydown",
9173 "keyup": "_handleKeyup"
9174 });
9175
9176 this.handle.bind( "vclick", false );
9177
9178 if ( this._handleFormReset ) {
9179 this._handleFormReset();
9180 }
9181
9182 this.refresh( undefined, undefined, true );
9183 },
9184
9185 _controlChange: function( event ) {
9186 // if the user dragged the handle, the "change" event was triggered from inside refresh(); don't call refresh() again
9187 if ( this._trigger( "controlchange", event ) === false ) {
9188 return false;
9189 }
9190 if ( !this.mouseMoved ) {
9191 this.refresh( this._value(), true );
9192 }
9193 },
9194
9195 _controlKeyup: function( event ) { // necessary?
9196 this.refresh( this._value(), true, true );
9197 },
9198
9199 _controlBlur: function( event ) {
9200 this.refresh( this._value(), true );
9201 },
9202
9203 // it appears the clicking the up and down buttons in chrome on
9204 // range/number inputs doesn't trigger a change until the field is
9205 // blurred. Here we check thif the value has changed and refresh
9206 _controlVMouseUp: function( event ) {
9207 this._checkedRefresh();
9208 },
9209
9210 // NOTE force focus on handle
9211 _handleVMouseDown: function( event ) {
9212 this.handle.focus();
9213 },
9214
9215 _handleKeydown: function( event ) {
9216 var index = this._value();
9217 if ( this.options.disabled ) {
9218 return;
9219 }
9220
9221 // In all cases prevent the default and mark the handle as active
9222 switch ( event.keyCode ) {
9223 case $.mobile.keyCode.HOME:
9224 case $.mobile.keyCode.END:
9225 case $.mobile.keyCode.PAGE_UP:
9226 case $.mobile.keyCode.PAGE_DOWN:
9227 case $.mobile.keyCode.UP:
9228 case $.mobile.keyCode.RIGHT:
9229 case $.mobile.keyCode.DOWN:
9230 case $.mobile.keyCode.LEFT:
9231 event.preventDefault();
9232
9233 if ( !this._keySliding ) {
9234 this._keySliding = true;
9235 this.handle.addClass( "ui-state-active" );
9236 }
9237
9238 break;
9239 }
9240
9241 // move the slider according to the keypress
9242 switch ( event.keyCode ) {
9243 case $.mobile.keyCode.HOME:
9244 this.refresh( this.min );
9245 break;
9246 case $.mobile.keyCode.END:
9247 this.refresh( this.max );
9248 break;
9249 case $.mobile.keyCode.PAGE_UP:
9250 case $.mobile.keyCode.UP:
9251 case $.mobile.keyCode.RIGHT:
9252 this.refresh( index + this.step );
9253 break;
9254 case $.mobile.keyCode.PAGE_DOWN:
9255 case $.mobile.keyCode.DOWN:
9256 case $.mobile.keyCode.LEFT:
9257 this.refresh( index - this.step );
9258 break;
9259 }
9260 }, // remove active mark
9261
9262 _handleKeyup: function( event ) {
9263 if ( this._keySliding ) {
9264 this._keySliding = false;
9265 this.handle.removeClass( "ui-state-active" );
9266 }
9267 },
9268
9269 _sliderVMouseDown: function( event ) {
9270 // NOTE: we don't do this in refresh because we still want to
9271 // support programmatic alteration of disabled inputs
9272 if ( this.options.disabled ) {
9273 return false;
9274 }
9275 if ( this._trigger( "beforestart", event ) === false ) {
9276 return false;
9277 }
9278 this.dragging = true;
9279 this.userModified = false;
9280 this.mouseMoved = false;
9281
9282 if ( this.isToggleSwitch ) {
9283 this.beforeStart = this.element[0].selectedIndex;
9284 }
9285
9286
9287 this.refresh( event );
9288 this._trigger( "start" );
9289 return false;
9290 },
9291
9292 _sliderVMouseUp: function() {
9293 if ( this.dragging ) {
9294 this.dragging = false;
9295
9296 if ( this.isToggleSwitch ) {
9297 // make the handle move with a smooth transition
9298 this.handle.addClass( "ui-slider-handle-snapping" );
9299
9300 if ( this.mouseMoved ) {
9301 // this is a drag, change the value only if user dragged enough
9302 if ( this.userModified ) {
9303 this.refresh( this.beforeStart === 0 ? 1 : 0 );
9304 } else {
9305 this.refresh( this.beforeStart );
9306 }
9307 } else {
9308 // this is just a click, change the value
9309 this.refresh( this.beforeStart === 0 ? 1 : 0 );
9310 }
9311 }
9312
9313 this.mouseMoved = false;
9314 this._trigger( "stop" );
9315 return false;
9316 }
9317 },
9318
9319 _preventDocumentDrag: function( event ) {
9320 // NOTE: we don't do this in refresh because we still want to
9321 // support programmatic alteration of disabled inputs
9322 if ( this._trigger( "drag", event ) === false) {
9323 return false;
9324 }
9325 if ( this.dragging && !this.options.disabled ) {
9326
9327 // this.mouseMoved must be updated before refresh() because it will be used in the control "change" event
9328 this.mouseMoved = true;
9329
9330 if ( this.isToggleSwitch ) {
9331 // make the handle move in sync with the mouse
9332 this.handle.removeClass( "ui-slider-handle-snapping" );
9333 }
9334
9335 this.refresh( event );
9336
9337 // only after refresh() you can calculate this.userModified
9338 this.userModified = this.beforeStart !== this.element[0].selectedIndex;
9339 return false;
9340 }
9341 },
9342
9343 _checkedRefresh: function() {
9344 if ( this.value != this._value() ) {
9345 this.refresh( this._value() );
9346 }
9347 },
9348
9349 _value: function() {
9350 return this.isToggleSwitch ? this.element[0].selectedIndex : parseFloat( this.element.val() ) ;
9351 },
9352
9353
9354 _reset: function() {
9355 this.refresh( undefined, false, true );
9356 },
9357
9358 refresh: function( val, isfromControl, preventInputUpdate ) {
9359 // NOTE: we don't return here because we want to support programmatic
9360 // alteration of the input value, which should still update the slider
9361
9362 var self = this,
9363 parentTheme = $.mobile.getInheritedTheme( this.element, "c" ),
9364 theme = this.options.theme || parentTheme,
9365 trackTheme = this.options.trackTheme || parentTheme;
9366
9367 self.slider[0].className = [ this.isToggleSwitch ? "ui-slider ui-slider-switch" : "ui-slider-track"," ui-btn-down-" + trackTheme,' ui-btn-corner-all', ( this.options.mini ) ? " ui-mini":""].join( "" );
9368 if ( this.options.disabled || this.element.attr( "disabled" ) ) {
9369 this.disable();
9370 }
9371
9372 // set the stored value for comparison later
9373 this.value = this._value();
9374 if ( this.options.highlight && !this.isToggleSwitch && this.slider.find( ".ui-slider-bg" ).length === 0 ) {
9375 this.valuebg = (function() {
9376 var bg = document.createElement( "div" );
9377 bg.className = "ui-slider-bg " + $.mobile.activeBtnClass + " ui-btn-corner-all";
9378 return $( bg ).prependTo( self.slider );
9379 })();
9380 }
9381 this.handle.buttonMarkup({ corners: true, theme: theme, shadow: true });
9382
9383 var pxStep, percent,
9384 control = this.element,
9385 isInput = !this.isToggleSwitch,
9386 optionElements = isInput ? [] : control.find( "option" ),
9387 min = isInput ? parseFloat( control.attr( "min" ) ) : 0,
9388 max = isInput ? parseFloat( control.attr( "max" ) ) : optionElements.length - 1,
9389 step = ( isInput && parseFloat( control.attr( "step" ) ) > 0 ) ? parseFloat( control.attr( "step" ) ) : 1;
9390
9391 if ( typeof val === "object" ) {
9392 var left, width, data = val,
9393 // a slight tolerance helped get to the ends of the slider
9394 tol = 8;
9395
9396 left = this.slider.offset().left;
9397 width = this.slider.width();
9398 pxStep = width/((max-min)/step);
9399 if ( !this.dragging ||
9400 data.pageX < left - tol ||
9401 data.pageX > left + width + tol ) {
9402 return;
9403 }
9404 if ( pxStep > 1 ) {
9405 percent = ( ( data.pageX - left ) / width ) * 100;
9406 } else {
9407 percent = Math.round( ( ( data.pageX - left ) / width ) * 100 );
9408 }
9409 } else {
9410 if ( val == null ) {
9411 val = isInput ? parseFloat( control.val() || 0 ) : control[0].selectedIndex;
9412 }
9413 percent = ( parseFloat( val ) - min ) / ( max - min ) * 100;
9414 }
9415
9416 if ( isNaN( percent ) ) {
9417 return;
9418 }
9419
9420 var newval = ( percent / 100 ) * ( max - min ) + min;
9421
9422 //from jQuery UI slider, the following source will round to the nearest step
9423 var valModStep = ( newval - min ) % step;
9424 var alignValue = newval - valModStep;
9425
9426 if ( Math.abs( valModStep ) * 2 >= step ) {
9427 alignValue += ( valModStep > 0 ) ? step : ( -step );
9428 }
9429
9430 var percentPerStep = 100/((max-min)/step);
9431 // Since JavaScript has problems with large floats, round
9432 // the final value to 5 digits after the decimal point (see jQueryUI: #4124)
9433 newval = parseFloat( alignValue.toFixed(5) );
9434
9435 if ( typeof pxStep === "undefined" ) {
9436 pxStep = width / ( (max-min) / step );
9437 }
9438 if ( pxStep > 1 && isInput ) {
9439 percent = ( newval - min ) * percentPerStep * ( 1 / step );
9440 }
9441 if ( percent < 0 ) {
9442 percent = 0;
9443 }
9444
9445 if ( percent > 100 ) {
9446 percent = 100;
9447 }
9448
9449 if ( newval < min ) {
9450 newval = min;
9451 }
9452
9453 if ( newval > max ) {
9454 newval = max;
9455 }
9456
9457 this.handle.css( "left", percent + "%" );
9458
9459 this.handle[0].setAttribute( "aria-valuenow", isInput ? newval : optionElements.eq( newval ).attr( "value" ) );
9460
9461 this.handle[0].setAttribute( "aria-valuetext", isInput ? newval : optionElements.eq( newval ).getEncodedText() );
9462
9463 this.handle[0].setAttribute( "title", isInput ? newval : optionElements.eq( newval ).getEncodedText() );
9464
9465 if ( this.valuebg ) {
9466 this.valuebg.css( "width", percent + "%" );
9467 }
9468
9469 // drag the label widths
9470 if ( this._labels ) {
9471 var handlePercent = this.handle.width() / this.slider.width() * 100,
9472 aPercent = percent && handlePercent + ( 100 - handlePercent ) * percent / 100,
9473 bPercent = percent === 100 ? 0 : Math.min( handlePercent + 100 - aPercent, 100 );
9474
9475 this._labels.each(function() {
9476 var ab = $( this ).is( ".ui-slider-label-a" );
9477 $( this ).width( ( ab ? aPercent : bPercent ) + "%" );
9478 });
9479 }
9480
9481 if ( !preventInputUpdate ) {
9482 var valueChanged = false;
9483
9484 // update control"s value
9485 if ( isInput ) {
9486 valueChanged = control.val() !== newval;
9487 control.val( newval );
9488 } else {
9489 valueChanged = control[ 0 ].selectedIndex !== newval;
9490 control[ 0 ].selectedIndex = newval;
9491 }
9492 if ( this._trigger( "beforechange", val ) === false) {
9493 return false;
9494 }
9495 if ( !isfromControl && valueChanged ) {
9496 control.trigger( "change" );
9497 }
9498 }
9499 },
9500
9501 enable: function() {
9502 this.element.attr( "disabled", false );
9503 this.slider.removeClass( "ui-disabled" ).attr( "aria-disabled", false );
9504 return this._setOption( "disabled", false );
9505 },
9506
9507 disable: function() {
9508 this.element.attr( "disabled", true );
9509 this.slider.addClass( "ui-disabled" ).attr( "aria-disabled", true );
9510 return this._setOption( "disabled", true );
9511 }
9512
9513});
9514
9515$.widget( "mobile.slider", $.mobile.slider, $.mobile.behaviors.formReset );
9516
9517//auto self-init widgets
9518$.mobile.document.bind( "pagecreate create", function( e ) {
9519 $.mobile.slider.prototype.enhanceWithin( e.target, true );
9520});
9521
9522})( jQuery );
9523
9524(function( $, undefined ) {
9525 $.widget( "mobile.rangeslider", $.mobile.widget, {
9526
9527 options: {
9528 theme: null,
9529 trackTheme: null,
9530 disabled: false,
9531 initSelector: ":jqmData(role='rangeslider')",
9532 mini: false,
9533 highlight: true
9534 },
9535
9536 _create: function() {
9537 var secondLabel,
9538 $el = this.element,
9539 elClass = this.options.mini ? "ui-rangeslider ui-mini" : "ui-rangeslider",
9540 _inputFirst = $el.find( "input" ).first(),
9541 _inputLast = $el.find( "input" ).last(),
9542 label = $el.find( "label" ).first(),
9543 _sliderFirst = $.data( _inputFirst.get(0), "mobileSlider" ).slider,
9544 _sliderLast = $.data( _inputLast.get(0), "mobileSlider" ).slider,
9545 firstHandle = $.data( _inputFirst.get(0), "mobileSlider" ).handle,
9546 _sliders = $( "<div class=\"ui-rangeslider-sliders\" />" ).appendTo( $el );
9547
9548 if ( $el.find( "label" ).length > 1 ) {
9549 secondLabel = $el.find( "label" ).last().hide();
9550 }
9551
9552 _inputFirst.addClass( "ui-rangeslider-first" );
9553 _inputLast.addClass( "ui-rangeslider-last" );
9554 $el.addClass( elClass );
9555
9556 _sliderFirst.appendTo( _sliders );
9557 _sliderLast.appendTo( _sliders );
9558 label.prependTo( $el );
9559 firstHandle.prependTo( _sliderLast );
9560
9561 $.extend( this, {
9562 _inputFirst: _inputFirst,
9563 _inputLast: _inputLast,
9564 _sliderFirst: _sliderFirst,
9565 _sliderLast: _sliderLast,
9566 _targetVal: null,
9567 _sliderTarget: false,
9568 _sliders: _sliders,
9569 _proxy: false
9570 });
9571
9572 this.refresh();
9573 this._on( this.element.find( "input.ui-slider-input" ), {
9574 "slidebeforestart": "_slidebeforestart",
9575 "slidestop": "_slidestop",
9576 "slidedrag": "_slidedrag",
9577 "slidebeforechange": "_change",
9578 "blur": "_change",
9579 "keyup": "_change"
9580 });
9581 this._on( firstHandle, {
9582 "vmousedown": "_dragFirstHandle"
9583 });
9584 },
9585
9586 _dragFirstHandle: function( event ) {
9587 //if the first handle is dragged send the event to the first slider
9588 $.data( this._inputFirst.get(0), "mobileSlider" ).dragging = true;
9589 $.data( this._inputFirst.get(0), "mobileSlider" ).refresh( event );
9590 return false;
9591 },
9592
9593 _slidedrag: function( event ) {
9594 var first = $( event.target ).is( this._inputFirst ),
9595 otherSlider = ( first ) ? this._inputLast : this._inputFirst;
9596
9597 this._sliderTarget = false;
9598 //if the drag was initaed on an extream and the other handle is focused send the events to
9599 //the closest handle
9600 if ( ( this._proxy === "first" && first ) || ( this._proxy === "last" && !first ) ) {
9601 $.data( otherSlider.get(0), "mobileSlider" ).dragging = true;
9602 $.data( otherSlider.get(0), "mobileSlider" ).refresh( event );
9603 return false;
9604 }
9605 },
9606
9607 _slidestop: function( event ) {
9608 var first = $( event.target ).is( this._inputFirst );
9609
9610 this._proxy = false;
9611 //this stops dragging of the handle and brings the active track to the front
9612 //this makes clicks on the track go the the last handle used
9613 this.element.find( "input" ).trigger( "vmouseup" );
9614 this._sliderFirst.css( "z-index", first ? 1 : "" );
9615 },
9616
9617 _slidebeforestart: function( event ) {
9618 this._sliderTarget = false;
9619 //if the track is the target remember this and the original value
9620 if ( $( event.originalEvent.target ).hasClass( "ui-slider-track" ) ) {
9621 this._sliderTarget = true;
9622 this._targetVal = $( event.target ).val();
9623 }
9624 },
9625
9626 _setOption: function( options ) {
9627 this._superApply( options );
9628 this.refresh();
9629 },
9630
9631 refresh: function() {
9632 var $el = this.element,
9633 o = this.options;
9634
9635 $el.find( "input" ).slider({
9636 theme: o.theme,
9637 trackTheme: o.trackTheme,
9638 disabled: o.disabled,
9639 mini: o.mini,
9640 highlight: o.highlight
9641 }).slider( "refresh" );
9642 this._updateHighlight();
9643 },
9644
9645 _change: function( event ) {
9646 if ( event.type == "keyup" ) {
9647 this._updateHighlight();
9648 return false;
9649 }
9650
9651 var min = parseFloat( this._inputFirst.val(), 10 ),
9652 max = parseFloat( this._inputLast.val(), 10 ),
9653 first = $( event.target ).hasClass( "ui-rangeslider-first" ),
9654 thisSlider = first ? this._inputFirst : this._inputLast,
9655 otherSlider = first ? this._inputLast : this._inputFirst;
9656
9657 if ( min > max && !this._sliderTarget ) {
9658 //this prevents min from being greater then max
9659 thisSlider.val( first ? max: min ).slider( "refresh" );
9660 this._trigger( "normalize" );
9661 } else if ( min > max ) {
9662 //this makes it so clicks on the target on either extream go to the closest handle
9663 thisSlider.val( this._targetVal ).slider( "refresh" );
9664
9665 var self = this;
9666 //You must wait for the stack to unwind so first slider is updated before updating second
9667 setTimeout( function() {
9668 otherSlider.val( first ? min: max ).slider( "refresh" );
9669 $.data( otherSlider.get(0), "mobileSlider" ).handle.focus();
9670 self._sliderFirst.css( "z-index", first ? "" : 1 );
9671 self._trigger( "normalize" );
9672 }, 0 );
9673 this._proxy = ( first ) ? "first" : "last";
9674 }
9675 //fixes issue where when both _sliders are at min they cannot be adjusted
9676 if ( min === max ) {
9677 $.data( thisSlider.get(0), "mobileSlider" ).handle.css( "z-index", 1 );
9678 $.data( otherSlider.get(0), "mobileSlider" ).handle.css( "z-index", 0 );
9679 } else {
9680 $.data( otherSlider.get(0), "mobileSlider" ).handle.css( "z-index", "" );
9681 $.data( thisSlider.get(0), "mobileSlider" ).handle.css( "z-index", "" );
9682 }
9683
9684 this._updateHighlight();
9685
9686 if ( min >= max ) {
9687 return false;
9688 }
9689 },
9690
9691 _updateHighlight: function() {
9692 var min = parseInt( $.data( this._inputFirst.get(0), "mobileSlider" ).handle.get(0).style.left, 10 ),
9693 max = parseInt( $.data( this._inputLast.get(0), "mobileSlider" ).handle.get(0).style.left, 10 ),
9694 width = (max - min);
9695
9696 this.element.find( ".ui-slider-bg" ).css({
9697 "margin-left": min + "%",
9698 "width": width + "%"
9699 });
9700 },
9701
9702 _destroy: function() {
9703 this.element.removeClass( "ui-rangeslider ui-mini" ).find( "label" ).show();
9704 this._inputFirst.after( this._sliderFirst );
9705 this._inputLast.after( this._sliderLast );
9706 this._sliders.remove();
9707 this.element.find( "input" ).removeClass( "ui-rangeslider-first ui-rangeslider-last" ).slider( "destroy" );
9708 }
9709
9710 });
9711
9712$.widget( "mobile.rangeslider", $.mobile.rangeslider, $.mobile.behaviors.formReset );
9713
9714//auto self-init widgets
9715$( document ).bind( "pagecreate create", function( e ) {
9716 $.mobile.rangeslider.prototype.enhanceWithin( e.target, true );
9717});
9718
9719})( jQuery );
9720(function( $, undefined ) {
9721
9722$.widget( "mobile.selectmenu", $.mobile.widget, {
9723 options: {
9724 theme: null,
9725 disabled: false,
9726 icon: "arrow-d",
9727 iconpos: "right",
9728 inline: false,
9729 corners: true,
9730 shadow: true,
9731 iconshadow: true,
9732 overlayTheme: "a",
9733 dividerTheme: "b",
9734 hidePlaceholderMenuItems: true,
9735 closeText: "Close",
9736 nativeMenu: true,
9737 // This option defaults to true on iOS devices.
9738 preventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1,
9739 initSelector: "select:not( :jqmData(role='slider') )",
9740 mini: false
9741 },
9742
9743 _button: function() {
9744 return $( "<div/>" );
9745 },
9746
9747 _setDisabled: function( value ) {
9748 this.element.attr( "disabled", value );
9749 this.button.attr( "aria-disabled", value );
9750 return this._setOption( "disabled", value );
9751 },
9752
9753 _focusButton : function() {
9754 var self = this;
9755
9756 setTimeout( function() {
9757 self.button.focus();
9758 }, 40);
9759 },
9760
9761 _selectOptions: function() {
9762 return this.select.find( "option" );
9763 },
9764
9765 // setup items that are generally necessary for select menu extension
9766 _preExtension: function() {
9767 var classes = "";
9768 // TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577
9769 /* if ( $el[0].className.length ) {
9770 classes = $el[0].className;
9771 } */
9772 if ( !!~this.element[0].className.indexOf( "ui-btn-left" ) ) {
9773 classes = " ui-btn-left";
9774 }
9775
9776 if ( !!~this.element[0].className.indexOf( "ui-btn-right" ) ) {
9777 classes = " ui-btn-right";
9778 }
9779
9780 this.select = this.element.removeClass( "ui-btn-left ui-btn-right" ).wrap( "<div class='ui-select" + classes + "'>" );
9781 this.selectID = this.select.attr( "id" );
9782 this.label = $( "label[for='"+ this.selectID +"']" ).addClass( "ui-select" );
9783 this.isMultiple = this.select[ 0 ].multiple;
9784 if ( !this.options.theme ) {
9785 this.options.theme = $.mobile.getInheritedTheme( this.select, "c" );
9786 }
9787 },
9788
9789 _destroy: function() {
9790 var wrapper = this.element.parents( ".ui-select" );
9791 if ( wrapper.length > 0 ) {
9792 if ( wrapper.is( ".ui-btn-left, .ui-btn-right" ) ) {
9793 this.element.addClass( wrapper.is( ".ui-btn-left" ) ? "ui-btn-left" : "ui-btn-right" );
9794 }
9795 this.element.insertAfter( wrapper );
9796 wrapper.remove();
9797 }
9798 },
9799
9800 _create: function() {
9801 this._preExtension();
9802
9803 // Allows for extension of the native select for custom selects and other plugins
9804 // see select.custom for example extension
9805 // TODO explore plugin registration
9806 this._trigger( "beforeCreate" );
9807
9808 this.button = this._button();
9809
9810 var self = this,
9811
9812 options = this.options,
9813
9814 inline = options.inline || this.select.jqmData( "inline" ),
9815 mini = options.mini || this.select.jqmData( "mini" ),
9816 iconpos = options.icon ? ( options.iconpos || this.select.jqmData( "iconpos" ) ) : false,
9817
9818 // IE throws an exception at options.item() function when
9819 // there is no selected item
9820 // select first in this case
9821 selectedIndex = this.select[ 0 ].selectedIndex === -1 ? 0 : this.select[ 0 ].selectedIndex,
9822
9823 // TODO values buttonId and menuId are undefined here
9824 button = this.button
9825 .insertBefore( this.select )
9826 .buttonMarkup( {
9827 theme: options.theme,
9828 icon: options.icon,
9829 iconpos: iconpos,
9830 inline: inline,
9831 corners: options.corners,
9832 shadow: options.shadow,
9833 iconshadow: options.iconshadow,
9834 mini: mini
9835 });
9836
9837 this.setButtonText();
9838
9839 // Opera does not properly support opacity on select elements
9840 // In Mini, it hides the element, but not its text
9841 // On the desktop,it seems to do the opposite
9842 // for these reasons, using the nativeMenu option results in a full native select in Opera
9843 if ( options.nativeMenu && window.opera && window.opera.version ) {
9844 button.addClass( "ui-select-nativeonly" );
9845 }
9846
9847 // Add counter for multi selects
9848 if ( this.isMultiple ) {
9849 this.buttonCount = $( "<span>" )
9850 .addClass( "ui-li-count ui-btn-up-c ui-btn-corner-all" )
9851 .hide()
9852 .appendTo( button.addClass('ui-li-has-count') );
9853 }
9854
9855 // Disable if specified
9856 if ( options.disabled || this.element.attr('disabled')) {
9857 this.disable();
9858 }
9859
9860 // Events on native select
9861 this.select.change(function() {
9862 self.refresh();
9863 });
9864
9865 if ( this._handleFormReset ) {
9866 this._handleFormReset();
9867 }
9868 this.build();
9869 },
9870
9871 build: function() {
9872 var self = this;
9873
9874 this.select
9875 .appendTo( self.button )
9876 .bind( "vmousedown", function() {
9877 // Add active class to button
9878 self.button.addClass( $.mobile.activeBtnClass );
9879 })
9880 .bind( "focus", function() {
9881 self.button.addClass( $.mobile.focusClass );
9882 })
9883 .bind( "blur", function() {
9884 self.button.removeClass( $.mobile.focusClass );
9885 })
9886 .bind( "focus vmouseover", function() {
9887 self.button.trigger( "vmouseover" );
9888 })
9889 .bind( "vmousemove", function() {
9890 // Remove active class on scroll/touchmove
9891 self.button.removeClass( $.mobile.activeBtnClass );
9892 })
9893 .bind( "change blur vmouseout", function() {
9894 self.button.trigger( "vmouseout" )
9895 .removeClass( $.mobile.activeBtnClass );
9896 })
9897 .bind( "change blur", function() {
9898 self.button.removeClass( "ui-btn-down-" + self.options.theme );
9899 });
9900
9901 // In many situations, iOS will zoom into the select upon tap, this prevents that from happening
9902 self.button.bind( "vmousedown", function() {
9903 if ( self.options.preventFocusZoom ) {
9904 $.mobile.zoom.disable( true );
9905 }
9906 });
9907 self.label.bind( "click focus", function() {
9908 if ( self.options.preventFocusZoom ) {
9909 $.mobile.zoom.disable( true );
9910 }
9911 });
9912 self.select.bind( "focus", function() {
9913 if ( self.options.preventFocusZoom ) {
9914 $.mobile.zoom.disable( true );
9915 }
9916 });
9917 self.button.bind( "mouseup", function() {
9918 if ( self.options.preventFocusZoom ) {
9919 setTimeout(function() {
9920 $.mobile.zoom.enable( true );
9921 }, 0 );
9922 }
9923 });
9924 self.select.bind( "blur", function() {
9925 if ( self.options.preventFocusZoom ) {
9926 $.mobile.zoom.enable( true );
9927 }
9928 });
9929
9930 },
9931
9932 selected: function() {
9933 return this._selectOptions().filter( ":selected" );
9934 },
9935
9936 selectedIndices: function() {
9937 var self = this;
9938
9939 return this.selected().map(function() {
9940 return self._selectOptions().index( this );
9941 }).get();
9942 },
9943
9944 setButtonText: function() {
9945 var self = this,
9946 selected = this.selected(),
9947 text = this.placeholder,
9948 span = $( document.createElement( "span" ) );
9949
9950 this.button.find( ".ui-btn-text" ).html(function() {
9951 if ( selected.length ) {
9952 text = selected.map(function() {
9953 return $( this ).text();
9954 }).get().join( ", " );
9955 } else {
9956 text = self.placeholder;
9957 }
9958
9959 // TODO possibly aggregate multiple select option classes
9960 return span.text( text )
9961 .addClass( self.select.attr( "class" ) )
9962 .addClass( selected.attr( "class" ) );
9963 });
9964 },
9965
9966 setButtonCount: function() {
9967 var selected = this.selected();
9968
9969 // multiple count inside button
9970 if ( this.isMultiple ) {
9971 this.buttonCount[ selected.length > 1 ? "show" : "hide" ]().text( selected.length );
9972 }
9973 },
9974
9975 _reset: function() {
9976 this.refresh();
9977 },
9978
9979 refresh: function() {
9980 this.setButtonText();
9981 this.setButtonCount();
9982 },
9983
9984 // open and close preserved in native selects
9985 // to simplify users code when looping over selects
9986 open: $.noop,
9987 close: $.noop,
9988
9989 disable: function() {
9990 this._setDisabled( true );
9991 this.button.addClass( "ui-disabled" );
9992 },
9993
9994 enable: function() {
9995 this._setDisabled( false );
9996 this.button.removeClass( "ui-disabled" );
9997 }
9998});
9999
10000$.widget( "mobile.selectmenu", $.mobile.selectmenu, $.mobile.behaviors.formReset );
10001
10002//auto self-init widgets
10003$.mobile.document.bind( "pagecreate create", function( e ) {
10004 $.mobile.selectmenu.prototype.enhanceWithin( e.target, true );
10005});
10006})( jQuery );
10007
10008/*
10009* custom "selectmenu" plugin
10010*/
10011
10012(function( $, undefined ) {
10013 var extendSelect = function( widget ) {
10014
10015 var select = widget.select,
10016 origDestroy = widget._destroy,
10017 selectID = widget.selectID,
10018 prefix = ( selectID ? selectID : ( ( $.mobile.ns || "" ) + "uuid-" + widget.uuid ) ),
10019 popupID = prefix + "-listbox",
10020 dialogID = prefix + "-dialog",
10021 label = widget.label,
10022 thisPage = widget.select.closest( ".ui-page" ),
10023 selectOptions = widget._selectOptions(),
10024 isMultiple = widget.isMultiple = widget.select[ 0 ].multiple,
10025 buttonId = selectID + "-button",
10026 menuId = selectID + "-menu",
10027 menuPage = $( "<div data-" + $.mobile.ns + "role='dialog' id='" + dialogID + "' data-" +$.mobile.ns + "theme='"+ widget.options.theme +"' data-" +$.mobile.ns + "overlay-theme='"+ widget.options.overlayTheme +"'>" +
10028 "<div data-" + $.mobile.ns + "role='header'>" +
10029 "<div class='ui-title'>" + label.getEncodedText() + "</div>"+
10030 "</div>"+
10031 "<div data-" + $.mobile.ns + "role='content'></div>"+
10032 "</div>" ),
10033
10034 listbox = $( "<div id='" + popupID + "' class='ui-selectmenu'>" ).insertAfter( widget.select ).popup( { theme: widget.options.overlayTheme } ),
10035
10036 list = $( "<ul>", {
10037 "class": "ui-selectmenu-list",
10038 "id": menuId,
10039 "role": "listbox",
10040 "aria-labelledby": buttonId
10041 }).attr( "data-" + $.mobile.ns + "theme", widget.options.theme )
10042 .attr( "data-" + $.mobile.ns + "divider-theme", widget.options.dividerTheme )
10043 .appendTo( listbox ),
10044
10045
10046 header = $( "<div>", {
10047 "class": "ui-header ui-bar-" + widget.options.theme
10048 }).prependTo( listbox ),
10049
10050 headerTitle = $( "<h1>", {
10051 "class": "ui-title"
10052 }).appendTo( header ),
10053
10054 menuPageContent,
10055 menuPageClose,
10056 headerClose;
10057
10058 if ( widget.isMultiple ) {
10059 headerClose = $( "<a>", {
10060 "text": widget.options.closeText,
10061 "href": "#",
10062 "class": "ui-btn-left"
10063 }).attr( "data-" + $.mobile.ns + "iconpos", "notext" ).attr( "data-" + $.mobile.ns + "icon", "delete" ).appendTo( header ).buttonMarkup();
10064 }
10065
10066 $.extend( widget, {
10067 select: widget.select,
10068 selectID: selectID,
10069 buttonId: buttonId,
10070 menuId: menuId,
10071 popupID: popupID,
10072 dialogID: dialogID,
10073 thisPage: thisPage,
10074 menuPage: menuPage,
10075 label: label,
10076 selectOptions: selectOptions,
10077 isMultiple: isMultiple,
10078 theme: widget.options.theme,
10079 listbox: listbox,
10080 list: list,
10081 header: header,
10082 headerTitle: headerTitle,
10083 headerClose: headerClose,
10084 menuPageContent: menuPageContent,
10085 menuPageClose: menuPageClose,
10086 placeholder: "",
10087
10088 build: function() {
10089 var self = this;
10090
10091 // Create list from select, update state
10092 self.refresh();
10093
10094 if ( self._origTabIndex === undefined ) {
10095 // Map undefined to false, because self._origTabIndex === undefined
10096 // indicates that we have not yet checked whether the select has
10097 // originally had a tabindex attribute, whereas false indicates that
10098 // we have checked the select for such an attribute, and have found
10099 // none present.
10100 self._origTabIndex = ( self.select[ 0 ].getAttribute( "tabindex" ) === null ) ? false : self.select.attr( "tabindex" );
10101 }
10102 self.select.attr( "tabindex", "-1" ).focus(function() {
10103 $( this ).blur();
10104 self.button.focus();
10105 });
10106
10107 // Button events
10108 self.button.bind( "vclick keydown" , function( event ) {
10109 if ( self.options.disabled || self.isOpen ) {
10110 return;
10111 }
10112
10113 if (event.type === "vclick" ||
10114 event.keyCode && (event.keyCode === $.mobile.keyCode.ENTER ||
10115 event.keyCode === $.mobile.keyCode.SPACE)) {
10116
10117 self._decideFormat();
10118 if ( self.menuType === "overlay" ) {
10119 self.button.attr( "href", "#" + self.popupID ).attr( "data-" + ( $.mobile.ns || "" ) + "rel", "popup" );
10120 } else {
10121 self.button.attr( "href", "#" + self.dialogID ).attr( "data-" + ( $.mobile.ns || "" ) + "rel", "dialog" );
10122 }
10123 self.isOpen = true;
10124 // Do not prevent default, so the navigation may have a chance to actually open the chosen format
10125 }
10126 });
10127
10128 // Events for list items
10129 self.list.attr( "role", "listbox" )
10130 .bind( "focusin", function( e ) {
10131 $( e.target )
10132 .attr( "tabindex", "0" )
10133 .trigger( "vmouseover" );
10134
10135 })
10136 .bind( "focusout", function( e ) {
10137 $( e.target )
10138 .attr( "tabindex", "-1" )
10139 .trigger( "vmouseout" );
10140 })
10141 .delegate( "li:not(.ui-disabled, .ui-li-divider)", "click", function( event ) {
10142
10143 // index of option tag to be selected
10144 var oldIndex = self.select[ 0 ].selectedIndex,
10145 newIndex = self.list.find( "li:not(.ui-li-divider)" ).index( this ),
10146 option = self._selectOptions().eq( newIndex )[ 0 ];
10147
10148 // toggle selected status on the tag for multi selects
10149 option.selected = self.isMultiple ? !option.selected : true;
10150
10151 // toggle checkbox class for multiple selects
10152 if ( self.isMultiple ) {
10153 $( this ).find( ".ui-icon" )
10154 .toggleClass( "ui-icon-checkbox-on", option.selected )
10155 .toggleClass( "ui-icon-checkbox-off", !option.selected );
10156 }
10157
10158 // trigger change if value changed
10159 if ( self.isMultiple || oldIndex !== newIndex ) {
10160 self.select.trigger( "change" );
10161 }
10162
10163 // hide custom select for single selects only - otherwise focus clicked item
10164 // We need to grab the clicked item the hard way, because the list may have been rebuilt
10165 if ( self.isMultiple ) {
10166 self.list.find( "li:not(.ui-li-divider)" ).eq( newIndex )
10167 .addClass( "ui-btn-down-" + widget.options.theme ).find( "a" ).first().focus();
10168 }
10169 else {
10170 self.close();
10171 }
10172
10173 event.preventDefault();
10174 })
10175 .keydown(function( event ) { //keyboard events for menu items
10176 var target = $( event.target ),
10177 li = target.closest( "li" ),
10178 prev, next;
10179
10180 // switch logic based on which key was pressed
10181 switch ( event.keyCode ) {
10182 // up or left arrow keys
10183 case 38:
10184 prev = li.prev().not( ".ui-selectmenu-placeholder" );
10185
10186 if ( prev.is( ".ui-li-divider" ) ) {
10187 prev = prev.prev();
10188 }
10189
10190 // if there's a previous option, focus it
10191 if ( prev.length ) {
10192 target
10193 .blur()
10194 .attr( "tabindex", "-1" );
10195
10196 prev.addClass( "ui-btn-down-" + widget.options.theme ).find( "a" ).first().focus();
10197 }
10198
10199 return false;
10200 // down or right arrow keys
10201 case 40:
10202 next = li.next();
10203
10204 if ( next.is( ".ui-li-divider" ) ) {
10205 next = next.next();
10206 }
10207
10208 // if there's a next option, focus it
10209 if ( next.length ) {
10210 target
10211 .blur()
10212 .attr( "tabindex", "-1" );
10213
10214 next.addClass( "ui-btn-down-" + widget.options.theme ).find( "a" ).first().focus();
10215 }
10216
10217 return false;
10218 // If enter or space is pressed, trigger click
10219 case 13:
10220 case 32:
10221 target.trigger( "click" );
10222
10223 return false;
10224 }
10225 });
10226
10227 // button refocus ensures proper height calculation
10228 // by removing the inline style and ensuring page inclusion
10229 self.menuPage.bind( "pagehide", function() {
10230 // TODO centralize page removal binding / handling in the page plugin.
10231 // Suggestion from @jblas to do refcounting
10232 //
10233 // TODO extremely confusing dependency on the open method where the pagehide.remove
10234 // bindings are stripped to prevent the parent page from disappearing. The way
10235 // we're keeping pages in the DOM right now sucks
10236 //
10237 // rebind the page remove that was unbound in the open function
10238 // to allow for the parent page removal from actions other than the use
10239 // of a dialog sized custom select
10240 //
10241 // doing this here provides for the back button on the custom select dialog
10242 $.mobile._bindPageRemove.call( self.thisPage );
10243 });
10244
10245 // Events on the popup
10246 self.listbox.bind( "popupafterclose", function( event ) {
10247 self.close();
10248 });
10249
10250 // Close button on small overlays
10251 if ( self.isMultiple ) {
10252 self.headerClose.click(function() {
10253 if ( self.menuType === "overlay" ) {
10254 self.close();
10255 return false;
10256 }
10257 });
10258 }
10259
10260 // track this dependency so that when the parent page
10261 // is removed on pagehide it will also remove the menupage
10262 self.thisPage.addDependents( this.menuPage );
10263 },
10264
10265 _isRebuildRequired: function() {
10266 var list = this.list.find( "li" ),
10267 options = this._selectOptions();
10268
10269 // TODO exceedingly naive method to determine difference
10270 // ignores value changes etc in favor of a forcedRebuild
10271 // from the user in the refresh method
10272 return options.text() !== list.text();
10273 },
10274
10275 selected: function() {
10276 return this._selectOptions().filter( ":selected:not( :jqmData(placeholder='true') )" );
10277 },
10278
10279 refresh: function( forceRebuild , foo ) {
10280 var self = this,
10281 select = this.element,
10282 isMultiple = this.isMultiple,
10283 indicies;
10284
10285 if ( forceRebuild || this._isRebuildRequired() ) {
10286 self._buildList();
10287 }
10288
10289 indicies = this.selectedIndices();
10290
10291 self.setButtonText();
10292 self.setButtonCount();
10293
10294 self.list.find( "li:not(.ui-li-divider)" )
10295 .removeClass( $.mobile.activeBtnClass )
10296 .attr( "aria-selected", false )
10297 .each(function( i ) {
10298
10299 if ( $.inArray( i, indicies ) > -1 ) {
10300 var item = $( this );
10301
10302 // Aria selected attr
10303 item.attr( "aria-selected", true );
10304
10305 // Multiple selects: add the "on" checkbox state to the icon
10306 if ( self.isMultiple ) {
10307 item.find( ".ui-icon" ).removeClass( "ui-icon-checkbox-off" ).addClass( "ui-icon-checkbox-on" );
10308 } else {
10309 if ( item.is( ".ui-selectmenu-placeholder" ) ) {
10310 item.next().addClass( $.mobile.activeBtnClass );
10311 } else {
10312 item.addClass( $.mobile.activeBtnClass );
10313 }
10314 }
10315 }
10316 });
10317 },
10318
10319 close: function() {
10320 if ( this.options.disabled || !this.isOpen ) {
10321 return;
10322 }
10323
10324 var self = this;
10325
10326 if ( self.menuType === "page" ) {
10327 self.menuPage.dialog( "close" );
10328 self.list.appendTo( self.listbox );
10329 } else {
10330 self.listbox.popup( "close" );
10331 }
10332
10333 self._focusButton();
10334 // allow the dialog to be closed again
10335 self.isOpen = false;
10336 },
10337
10338 open: function() {
10339 this.button.click();
10340 },
10341
10342 _decideFormat: function() {
10343 var self = this,
10344 $window = $.mobile.window,
10345 selfListParent = self.list.parent(),
10346 menuHeight = selfListParent.outerHeight(),
10347 menuWidth = selfListParent.outerWidth(),
10348 activePage = $( "." + $.mobile.activePageClass ),
10349 scrollTop = $window.scrollTop(),
10350 btnOffset = self.button.offset().top,
10351 screenHeight = $window.height(),
10352 screenWidth = $window.width();
10353
10354 function focusMenuItem() {
10355 var selector = self.list.find( "." + $.mobile.activeBtnClass + " a" );
10356 if ( selector.length === 0 ) {
10357 selector = self.list.find( "li.ui-btn:not( :jqmData(placeholder='true') ) a" );
10358 }
10359 selector.first().focus().closest( "li" ).addClass( "ui-btn-down-" + widget.options.theme );
10360 }
10361
10362 if ( menuHeight > screenHeight - 80 || !$.support.scrollTop ) {
10363
10364 self.menuPage.appendTo( $.mobile.pageContainer ).page();
10365 self.menuPageContent = menuPage.find( ".ui-content" );
10366 self.menuPageClose = menuPage.find( ".ui-header a" );
10367
10368 // prevent the parent page from being removed from the DOM,
10369 // otherwise the results of selecting a list item in the dialog
10370 // fall into a black hole
10371 self.thisPage.unbind( "pagehide.remove" );
10372
10373 //for WebOS/Opera Mini (set lastscroll using button offset)
10374 if ( scrollTop === 0 && btnOffset > screenHeight ) {
10375 self.thisPage.one( "pagehide", function() {
10376 $( this ).jqmData( "lastScroll", btnOffset );
10377 });
10378 }
10379
10380 self.menuPage
10381 .one( "pageshow", function() {
10382 focusMenuItem();
10383 })
10384 .one( "pagehide", function() {
10385 self.close();
10386 });
10387
10388 self.menuType = "page";
10389 self.menuPageContent.append( self.list );
10390 self.menuPage.find("div .ui-title").text(self.label.text());
10391 } else {
10392 self.menuType = "overlay";
10393
10394 self.listbox.one( "popupafteropen", focusMenuItem );
10395 }
10396 },
10397
10398 _buildList: function() {
10399 var self = this,
10400 o = this.options,
10401 placeholder = this.placeholder,
10402 needPlaceholder = true,
10403 optgroups = [],
10404 lis = [],
10405 dataIcon = self.isMultiple ? "checkbox-off" : "false";
10406
10407 self.list.empty().filter( ".ui-listview" ).listview( "destroy" );
10408
10409 var $options = self.select.find( "option" ),
10410 numOptions = $options.length,
10411 select = this.select[ 0 ],
10412 dataPrefix = 'data-' + $.mobile.ns,
10413 dataIndexAttr = dataPrefix + 'option-index',
10414 dataIconAttr = dataPrefix + 'icon',
10415 dataRoleAttr = dataPrefix + 'role',
10416 dataPlaceholderAttr = dataPrefix + 'placeholder',
10417 fragment = document.createDocumentFragment(),
10418 isPlaceholderItem = false,
10419 optGroup;
10420
10421 for (var i = 0; i < numOptions;i++, isPlaceholderItem = false) {
10422 var option = $options[i],
10423 $option = $( option ),
10424 parent = option.parentNode,
10425 text = $option.text(),
10426 anchor = document.createElement( 'a' ),
10427 classes = [];
10428
10429 anchor.setAttribute( 'href', '#' );
10430 anchor.appendChild( document.createTextNode( text ) );
10431
10432 // Are we inside an optgroup?
10433 if ( parent !== select && parent.nodeName.toLowerCase() === "optgroup" ) {
10434 var optLabel = parent.getAttribute( 'label' );
10435 if ( optLabel !== optGroup ) {
10436 var divider = document.createElement( 'li' );
10437 divider.setAttribute( dataRoleAttr, 'list-divider' );
10438 divider.setAttribute( 'role', 'option' );
10439 divider.setAttribute( 'tabindex', '-1' );
10440 divider.appendChild( document.createTextNode( optLabel ) );
10441 fragment.appendChild( divider );
10442 optGroup = optLabel;
10443 }
10444 }
10445
10446 if ( needPlaceholder && ( !option.getAttribute( "value" ) || text.length === 0 || $option.jqmData( "placeholder" ) ) ) {
10447 needPlaceholder = false;
10448 isPlaceholderItem = true;
10449
10450 // If we have identified a placeholder, record the fact that it was
10451 // us who have added the placeholder to the option and mark it
10452 // retroactively in the select as well
10453 if ( null === option.getAttribute( dataPlaceholderAttr ) ) {
10454 this._removePlaceholderAttr = true;
10455 }
10456 option.setAttribute( dataPlaceholderAttr, true );
10457 if ( o.hidePlaceholderMenuItems ) {
10458 classes.push( "ui-selectmenu-placeholder" );
10459 }
10460 if ( placeholder !== text ) {
10461 placeholder = self.placeholder = text;
10462 }
10463 }
10464
10465 var item = document.createElement('li');
10466 if ( option.disabled ) {
10467 classes.push( "ui-disabled" );
10468 item.setAttribute('aria-disabled',true);
10469 }
10470 item.setAttribute( dataIndexAttr,i );
10471 item.setAttribute( dataIconAttr, dataIcon );
10472 if ( isPlaceholderItem ) {
10473 item.setAttribute( dataPlaceholderAttr, true );
10474 }
10475 item.className = classes.join( " " );
10476 item.setAttribute( 'role', 'option' );
10477 anchor.setAttribute( 'tabindex', '-1' );
10478 item.appendChild( anchor );
10479 fragment.appendChild( item );
10480 }
10481
10482 self.list[0].appendChild( fragment );
10483
10484 // Hide header if it's not a multiselect and there's no placeholder
10485 if ( !this.isMultiple && !placeholder.length ) {
10486 this.header.hide();
10487 } else {
10488 this.headerTitle.text( this.placeholder );
10489 }
10490
10491 // Now populated, create listview
10492 self.list.listview();
10493 },
10494
10495 _button: function() {
10496 return $( "<a>", {
10497 "href": "#",
10498 "role": "button",
10499 // TODO value is undefined at creation
10500 "id": this.buttonId,
10501 "aria-haspopup": "true",
10502
10503 // TODO value is undefined at creation
10504 "aria-owns": this.menuId
10505 });
10506 },
10507
10508 _destroy: function() {
10509 this.close();
10510
10511 // Restore the tabindex attribute to its original value
10512 if ( this._origTabIndex !== undefined ) {
10513 if ( this._origTabIndex !== false ) {
10514 this.select.attr( "tabindex", this._origTabIndex );
10515 } else {
10516 this.select.removeAttr( "tabindex" );
10517 }
10518 }
10519
10520 // Remove the placeholder attribute if we were the ones to add it
10521 if ( this._removePlaceholderAttr ) {
10522 this._selectOptions().removeAttr( "data-" + $.mobile.ns + "placeholder" );
10523 }
10524
10525 // Remove the popup
10526 this.listbox.remove();
10527
10528 // Chain up
10529 origDestroy.apply( this, arguments );
10530 }
10531 });
10532 };
10533
10534 // issue #3894 - core doesn't trigger events on disabled delegates
10535 $.mobile.document.bind( "selectmenubeforecreate", function( event ) {
10536 var selectmenuWidget = $( event.target ).data( "mobile-selectmenu" );
10537
10538 if ( !selectmenuWidget.options.nativeMenu &&
10539 selectmenuWidget.element.parents( ":jqmData(role='popup')" ).length === 0 ) {
10540 extendSelect( selectmenuWidget );
10541 }
10542 });
10543})( jQuery );
10544
10545(function( $, undefined ) {
10546
10547
10548 $.widget( "mobile.fixedtoolbar", $.mobile.widget, {
10549 options: {
10550 visibleOnPageShow: true,
10551 disablePageZoom: true,
10552 transition: "slide", //can be none, fade, slide (slide maps to slideup or slidedown)
10553 fullscreen: false,
10554 tapToggle: true,
10555 tapToggleBlacklist: "a, button, input, select, textarea, .ui-header-fixed, .ui-footer-fixed, .ui-popup, .ui-panel, .ui-panel-dismiss-open",
10556 hideDuringFocus: "input, textarea, select",
10557 updatePagePadding: true,
10558 trackPersistentToolbars: true,
10559
10560 // Browser detection! Weeee, here we go...
10561 // Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.
10562 // Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.
10563 // Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window
10564 // The following function serves to rule out some popular browsers with known fixed-positioning issues
10565 // This is a plugin option like any other, so feel free to improve or overwrite it
10566 supportBlacklist: function() {
10567 return !$.support.fixedPosition;
10568 },
10569 initSelector: ":jqmData(position='fixed')"
10570 },
10571
10572 _create: function() {
10573
10574 var self = this,
10575 o = self.options,
10576 $el = self.element,
10577 tbtype = $el.is( ":jqmData(role='header')" ) ? "header" : "footer",
10578 $page = $el.closest( ".ui-page" );
10579
10580 // Feature detecting support for
10581 if ( o.supportBlacklist() ) {
10582 self.destroy();
10583 return;
10584 }
10585
10586 $el.addClass( "ui-"+ tbtype +"-fixed" );
10587
10588 // "fullscreen" overlay positioning
10589 if ( o.fullscreen ) {
10590 $el.addClass( "ui-"+ tbtype +"-fullscreen" );
10591 $page.addClass( "ui-page-" + tbtype + "-fullscreen" );
10592 }
10593 // If not fullscreen, add class to page to set top or bottom padding
10594 else{
10595 $page.addClass( "ui-page-" + tbtype + "-fixed" );
10596 }
10597
10598 $.extend( this, {
10599 _thisPage: null
10600 });
10601
10602 self._addTransitionClass();
10603 self._bindPageEvents();
10604 self._bindToggleHandlers();
10605 },
10606
10607 _addTransitionClass: function() {
10608 var tclass = this.options.transition;
10609
10610 if ( tclass && tclass !== "none" ) {
10611 // use appropriate slide for header or footer
10612 if ( tclass === "slide" ) {
10613 tclass = this.element.is( ".ui-header" ) ? "slidedown" : "slideup";
10614 }
10615
10616 this.element.addClass( tclass );
10617 }
10618 },
10619
10620 _bindPageEvents: function() {
10621 this._thisPage = this.element.closest( ".ui-page" );
10622 //page event bindings
10623 // Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up
10624 // This method is meant to disable zoom while a fixed-positioned toolbar page is visible
10625 this._on( this._thisPage, {
10626 "pagebeforeshow": "_handlePageBeforeShow",
10627 "webkitAnimationStart":"_handleAnimationStart",
10628 "animationstart":"_handleAnimationStart",
10629 "updatelayout": "_handleAnimationStart",
10630 "pageshow": "_handlePageShow",
10631 "pagebeforehide": "_handlePageBeforeHide"
10632 });
10633 },
10634
10635 _handlePageBeforeShow: function() {
10636 var o = this.options;
10637 if ( o.disablePageZoom ) {
10638 $.mobile.zoom.disable( true );
10639 }
10640 if ( !o.visibleOnPageShow ) {
10641 this.hide( true );
10642 }
10643 },
10644
10645 _handleAnimationStart: function() {
10646 if ( this.options.updatePagePadding ) {
10647 this.updatePagePadding( this._thisPage );
10648 }
10649 },
10650
10651 _handlePageShow: function() {
10652 this.updatePagePadding( this._thisPage );
10653 if ( this.options.updatePagePadding ) {
10654 this._on( $.mobile.window, { "throttledresize": "updatePagePadding" } );
10655 }
10656 },
10657
10658 _handlePageBeforeHide: function( e, ui ) {
10659 var o = this.options;
10660
10661 if ( o.disablePageZoom ) {
10662 $.mobile.zoom.enable( true );
10663 }
10664 if ( o.updatePagePadding ) {
10665 this._off( $.mobile.window, "throttledresize" );
10666 }
10667
10668 if ( o.trackPersistentToolbars ) {
10669 var thisFooter = $( ".ui-footer-fixed:jqmData(id)", this._thisPage ),
10670 thisHeader = $( ".ui-header-fixed:jqmData(id)", this._thisPage ),
10671 nextFooter = thisFooter.length && ui.nextPage && $( ".ui-footer-fixed:jqmData(id='" + thisFooter.jqmData( "id" ) + "')", ui.nextPage ) || $(),
10672 nextHeader = thisHeader.length && ui.nextPage && $( ".ui-header-fixed:jqmData(id='" + thisHeader.jqmData( "id" ) + "')", ui.nextPage ) || $();
10673
10674 if ( nextFooter.length || nextHeader.length ) {
10675
10676 nextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );
10677
10678 ui.nextPage.one( "pageshow", function() {
10679 nextHeader.prependTo( this );
10680 nextFooter.appendTo( this );
10681 });
10682 }
10683 }
10684 },
10685
10686 _visible: true,
10687
10688 // This will set the content element's top or bottom padding equal to the toolbar's height
10689 updatePagePadding: function( tbPage ) {
10690 var $el = this.element,
10691 header = $el.is( ".ui-header" ),
10692 pos = parseFloat( $el.css( header ? "top" : "bottom" ) );
10693
10694 // This behavior only applies to "fixed", not "fullscreen"
10695 if ( this.options.fullscreen ) { return; }
10696
10697 tbPage = tbPage || this._thisPage || $el.closest( ".ui-page" );
10698 $( tbPage ).css( "padding-" + ( header ? "top" : "bottom" ), $el.outerHeight() + pos );
10699 },
10700
10701 _useTransition: function( notransition ) {
10702 var $win = $.mobile.window,
10703 $el = this.element,
10704 scroll = $win.scrollTop(),
10705 elHeight = $el.height(),
10706 pHeight = $el.closest( ".ui-page" ).height(),
10707 viewportHeight = $.mobile.getScreenHeight(),
10708 tbtype = $el.is( ":jqmData(role='header')" ) ? "header" : "footer";
10709
10710 return !notransition &&
10711 ( this.options.transition && this.options.transition !== "none" &&
10712 (
10713 ( tbtype === "header" && !this.options.fullscreen && scroll > elHeight ) ||
10714 ( tbtype === "footer" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )
10715 ) || this.options.fullscreen
10716 );
10717 },
10718
10719 show: function( notransition ) {
10720 var hideClass = "ui-fixed-hidden",
10721 $el = this.element;
10722
10723 if ( this._useTransition( notransition ) ) {
10724 $el
10725 .removeClass( "out " + hideClass )
10726 .addClass( "in" )
10727 .animationComplete(function () {
10728 $el.removeClass('in');
10729 });
10730 }
10731 else {
10732 $el.removeClass( hideClass );
10733 }
10734 this._visible = true;
10735 },
10736
10737 hide: function( notransition ) {
10738 var hideClass = "ui-fixed-hidden",
10739 $el = this.element,
10740 // if it's a slide transition, our new transitions need the reverse class as well to slide outward
10741 outclass = "out" + ( this.options.transition === "slide" ? " reverse" : "" );
10742
10743 if( this._useTransition( notransition ) ) {
10744 $el
10745 .addClass( outclass )
10746 .removeClass( "in" )
10747 .animationComplete(function() {
10748 $el.addClass( hideClass ).removeClass( outclass );
10749 });
10750 }
10751 else {
10752 $el.addClass( hideClass ).removeClass( outclass );
10753 }
10754 this._visible = false;
10755 },
10756
10757 toggle: function() {
10758 this[ this._visible ? "hide" : "show" ]();
10759 },
10760
10761 _bindToggleHandlers: function() {
10762 var self = this, delay,
10763 o = self.options,
10764 $el = self.element;
10765
10766 // tap toggle
10767 $el.closest( ".ui-page" )
10768 .bind( "vclick", function( e ) {
10769 if ( o.tapToggle && !$( e.target ).closest( o.tapToggleBlacklist ).length ) {
10770 self.toggle();
10771 }
10772 })
10773 .bind( "focusin focusout", function( e ) {
10774 //this hides the toolbars on a keyboard pop to give more screen room and prevent ios bug which
10775 //positions fixed toolbars in the middle of the screen on pop if the input is near the top or
10776 //bottom of the screen addresses issues #4410 Footer navbar moves up when clicking on a textbox in an Android environment
10777 //and issue #4113 Header and footer change their position after keyboard popup - iOS
10778 //and issue #4410 Footer navbar moves up when clicking on a textbox in an Android environment
10779 if ( screen.width < 1025 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( ".ui-header-fixed, .ui-footer-fixed" ).length ) {
10780 //Fix for issue #4724 Moving through form in Mobile Safari with "Next" and "Previous" system
10781 //controls causes fixed position, tap-toggle false Header to reveal itself
10782 if ( e.type === "focusout" && !self._visible ) {
10783 //wait for the stack to unwind and see if we have jumped to another input
10784 delay = setTimeout( function() {
10785 self.show();
10786 }, 0 );
10787 } else if ( e.type === "focusin" && self._visible ) {
10788 //if we have jumped to another input clear the time out to cancel the show.
10789 clearTimeout( delay );
10790 self.hide();
10791 }
10792 }
10793 });
10794 },
10795
10796 _destroy: function() {
10797 var $el = this.element,
10798 header = $el.is( ".ui-header" );
10799
10800 $el.closest( ".ui-page" ).css( "padding-" + ( header ? "top" : "bottom" ), "" );
10801 $el.removeClass( "ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden" );
10802 $el.closest( ".ui-page" ).removeClass( "ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen" );
10803 }
10804
10805 });
10806
10807 //auto self-init widgets
10808 $.mobile.document
10809 .bind( "pagecreate create", function( e ) {
10810
10811 // DEPRECATED in 1.1: support for data-fullscreen=true|false on the page element.
10812 // This line ensures it still works, but we recommend moving the attribute to the toolbars themselves.
10813 if ( $( e.target ).jqmData( "fullscreen" ) ) {
10814 $( $.mobile.fixedtoolbar.prototype.options.initSelector, e.target ).not( ":jqmData(fullscreen)" ).jqmData( "fullscreen", true );
10815 }
10816
10817 $.mobile.fixedtoolbar.prototype.enhanceWithin( e.target );
10818 });
10819
10820})( jQuery );
10821
10822(function( $, undefined ) {
10823 $.widget( "mobile.fixedtoolbar", $.mobile.fixedtoolbar, {
10824
10825 _create: function() {
10826 this._super();
10827 this._workarounds();
10828 },
10829
10830 //check the browser and version and run needed workarounds
10831 _workarounds: function() {
10832 var ua = navigator.userAgent,
10833 platform = navigator.platform,
10834 // Rendering engine is Webkit, and capture major version
10835 wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ),
10836 wkversion = !!wkmatch && wkmatch[ 1 ],
10837 os = null,
10838 self = this;
10839 //set the os we are working in if it dosent match one with workarounds return
10840 if( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1 || platform.indexOf( "iPod" ) > -1 ){
10841 os = "ios";
10842 } else if( ua.indexOf( "Android" ) > -1 ){
10843 os = "android";
10844 } else {
10845 return;
10846 }
10847 //check os version if it dosent match one with workarounds return
10848 if( os === "ios" ) {
10849 //iOS workarounds
10850 self._bindScrollWorkaround();
10851 } else if( os === "android" && wkversion && wkversion < 534 ) {
10852 //Android 2.3 run all Android 2.3 workaround
10853 self._bindScrollWorkaround();
10854 self._bindListThumbWorkaround();
10855 } else {
10856 return;
10857 }
10858 },
10859
10860 //Utility class for checking header and footer positions relative to viewport
10861 _viewportOffset: function() {
10862 var $el = this.element,
10863 header = $el.is( ".ui-header" ),
10864 offset = Math.abs($el.offset().top - $.mobile.window.scrollTop());
10865 if( !header ) {
10866 offset = Math.round(offset - $.mobile.window.height() + $el.outerHeight())-60;
10867 }
10868 return offset;
10869 },
10870
10871 //bind events for _triggerRedraw() function
10872 _bindScrollWorkaround: function() {
10873 var self = this;
10874 //bind to scrollstop and check if the toolbars are correctly positioned
10875 this._on( $.mobile.window, { scrollstop: function() {
10876 var viewportOffset = self._viewportOffset();
10877 //check if the header is visible and if its in the right place
10878 if( viewportOffset > 2 && self._visible) {
10879 self._triggerRedraw();
10880 }
10881 }});
10882 },
10883
10884 //this addresses issue #4250 Persistent footer instability in v1.1 with long select lists in Android 2.3.3
10885 //and issue #3748 Android 2.x: Page transitions broken when fixed toolbars used
10886 //the absolutely positioned thumbnail in a list view causes problems with fixed position buttons above in a nav bar
10887 //setting the li's to -webkit-transform:translate3d(0,0,0); solves this problem to avoide potential issues in other
10888 //platforms we scope this with the class ui-android-2x-fix
10889 _bindListThumbWorkaround: function() {
10890 this.element.closest(".ui-page").addClass( "ui-android-2x-fixed" );
10891 },
10892 //this addresses issues #4337 Fixed header problem after scrolling content on iOS and Android
10893 //and device bugs project issue #1 Form elements can lose click hit area in position: fixed containers.
10894 //this also addresses not on fixed toolbars page in docs
10895 //adding 1px of padding to the bottom then removing it causes a "redraw"
10896 //which positions the toolbars correctly (they will always be visually correct)
10897 _triggerRedraw: function() {
10898 var paddingBottom = parseFloat( $( ".ui-page-active" ).css( "padding-bottom" ) );
10899 //trigger page redraw to fix incorrectly positioned fixed elements
10900 $( ".ui-page-active" ).css( "padding-bottom", ( paddingBottom + 1 ) +"px" );
10901 //if the padding is reset with out a timeout the reposition will not occure.
10902 //this is independant of JQM the browser seems to need the time to react.
10903 setTimeout( function() {
10904 $( ".ui-page-active" ).css( "padding-bottom", paddingBottom + "px" );
10905 }, 0 );
10906 },
10907
10908 destroy: function() {
10909 this._super();
10910 //Remove the class we added to the page previously in android 2.x
10911 this.element.closest(".ui-page-active").removeClass( "ui-android-2x-fix" );
10912 }
10913 });
10914
10915 })( jQuery );
10916
10917(function( $, window ) {
10918
10919 $.mobile.iosorientationfixEnabled = true;
10920
10921 // This fix addresses an iOS bug, so return early if the UA claims it's something else.
10922 var ua = navigator.userAgent;
10923 if( !( /iPhone|iPad|iPod/.test( navigator.platform ) && /OS [1-5]_[0-9_]* like Mac OS X/i.test( ua ) && ua.indexOf( "AppleWebKit" ) > -1 ) ){
10924 $.mobile.iosorientationfixEnabled = false;
10925 return;
10926 }
10927
10928 var zoom = $.mobile.zoom,
10929 evt, x, y, z, aig;
10930
10931 function checkTilt( e ) {
10932 evt = e.originalEvent;
10933 aig = evt.accelerationIncludingGravity;
10934
10935 x = Math.abs( aig.x );
10936 y = Math.abs( aig.y );
10937 z = Math.abs( aig.z );
10938
10939 // If portrait orientation and in one of the danger zones
10940 if ( !window.orientation && ( x > 7 || ( ( z > 6 && y < 8 || z < 8 && y > 6 ) && x > 5 ) ) ) {
10941 if ( zoom.enabled ) {
10942 zoom.disable();
10943 }
10944 }else if ( !zoom.enabled ) {
10945 zoom.enable();
10946 }
10947 }
10948
10949 $.mobile.document.on( "mobileinit", function(){
10950 if( $.mobile.iosorientationfixEnabled ){
10951 $.mobile.window
10952 .bind( "orientationchange.iosorientationfix", zoom.enable )
10953 .bind( "devicemotion.iosorientationfix", checkTilt );
10954 }
10955 });
10956
10957}( jQuery, this ));
10958
10959(function( $, window, undefined ) {
10960 var$html = $( "html" ),
10961 $head = $( "head" ),
10962 $window = $.mobile.window;
10963
10964 //remove initial build class (only present on first pageshow)
10965 function hideRenderingClass() {
10966 $html.removeClass( "ui-mobile-rendering" );
10967 }
10968
10969 // trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
10970 $( window.document ).trigger( "mobileinit" );
10971
10972 // support conditions
10973 // if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
10974 // otherwise, proceed with the enhancements
10975 if ( !$.mobile.gradeA() ) {
10976 return;
10977 }
10978
10979 // override ajaxEnabled on platforms that have known conflicts with hash history updates
10980 // or generally work better browsing in regular http for full page refreshes (BB5, Opera Mini)
10981 if ( $.mobile.ajaxBlacklist ) {
10982 $.mobile.ajaxEnabled = false;
10983 }
10984
10985 // Add mobile, initial load "rendering" classes to docEl
10986 $html.addClass( "ui-mobile ui-mobile-rendering" );
10987
10988 // This is a fallback. If anything goes wrong (JS errors, etc), or events don't fire,
10989 // this ensures the rendering class is removed after 5 seconds, so content is visible and accessible
10990 setTimeout( hideRenderingClass, 5000 );
10991
10992 $.extend( $.mobile, {
10993 // find and enhance the pages in the dom and transition to the first page.
10994 initializePage: function() {
10995 // find present pages
10996 var path = $.mobile.path,
10997 $pages = $( ":jqmData(role='page'), :jqmData(role='dialog')" ),
10998 hash = path.stripHash( path.stripQueryParams(path.parseLocation().hash) ),
10999 hashPage = document.getElementById( hash );
11000
11001 // if no pages are found, create one with body's inner html
11002 if ( !$pages.length ) {
11003 $pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 );
11004 }
11005
11006 // add dialogs, set data-url attrs
11007 $pages.each(function() {
11008 var $this = $( this );
11009
11010 // unless the data url is already set set it to the pathname
11011 if ( !$this.jqmData( "url" ) ) {
11012 $this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) || location.pathname + location.search );
11013 }
11014 });
11015
11016 // define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
11017 $.mobile.firstPage = $pages.first();
11018
11019 // define page container
11020 $.mobile.pageContainer = $.mobile.firstPage.parent().addClass( "ui-mobile-viewport" );
11021
11022 // alert listeners that the pagecontainer has been determined for binding
11023 // to events triggered on it
11024 $window.trigger( "pagecontainercreate" );
11025
11026 // cue page loading message
11027 $.mobile.showPageLoadingMsg();
11028
11029 //remove initial build class (only present on first pageshow)
11030 hideRenderingClass();
11031
11032 // if hashchange listening is disabled, there's no hash deeplink,
11033 // the hash is not valid (contains more than one # or does not start with #)
11034 // or there is no page with that hash, change to the first page in the DOM
11035 // Remember, however, that the hash can also be a path!
11036 if ( ! ( $.mobile.hashListeningEnabled &&
11037 $.mobile.path.isHashValid( location.hash ) &&
11038 ( $( hashPage ).is( ':jqmData(role="page")' ) ||
11039 $.mobile.path.isPath( hash ) ||
11040 hash === $.mobile.dialogHashKey ) ) ) {
11041
11042 // Store the initial destination
11043 if ( $.mobile.path.isHashValid( location.hash ) ) {
11044 $.mobile.urlHistory.initialDst = hash.replace( "#", "" );
11045 }
11046
11047 // make sure to set initial popstate state if it exists
11048 // so that navigation back to the initial page works properly
11049 if( $.event.special.navigate.isPushStateEnabled() ) {
11050 $.mobile.navigate.navigator.squash( path.parseLocation().href );
11051 }
11052
11053 $.mobile.changePage( $.mobile.firstPage, {
11054 transition: "none",
11055 reverse: true,
11056 changeHash: false,
11057 fromHashChange: true
11058 });
11059 } else {
11060 // trigger hashchange or navigate to squash and record the correct
11061 // history entry for an initial hash path
11062 if( !$.event.special.navigate.isPushStateEnabled() ) {
11063 $window.trigger( "hashchange", [true] );
11064 } else {
11065 // TODO figure out how to simplify this interaction with the initial history entry
11066 // at the bottom js/navigate/navigate.js
11067 $.mobile.navigate.history.stack = [];
11068 $.mobile.navigate( $.mobile.path.isPath( location.hash ) ? location.hash : location.href );
11069 }
11070 }
11071 }
11072 });
11073
11074 // initialize events now, after mobileinit has occurred
11075 $.mobile.navreadyDeferred.resolve();
11076
11077 // check which scrollTop value should be used by scrolling to 1 immediately at domready
11078 // then check what the scroll top is. Android will report 0... others 1
11079 // note that this initial scroll won't hide the address bar. It's just for the check.
11080 $(function() {
11081 window.scrollTo( 0, 1 );
11082
11083 // if defaultHomeScroll hasn't been set yet, see if scrollTop is 1
11084 // it should be 1 in most browsers, but android treats 1 as 0 (for hiding addr bar)
11085 // so if it's 1, use 0 from now on
11086 $.mobile.defaultHomeScroll = ( !$.support.scrollTop || $.mobile.window.scrollTop() === 1 ) ? 0 : 1;
11087
11088 //dom-ready inits
11089 if ( $.mobile.autoInitializePage ) {
11090 $.mobile.initializePage();
11091 }
11092
11093 // window load event
11094 // hide iOS browser chrome on load
11095 $window.load( $.mobile.silentScroll );
11096
11097 if ( !$.support.cssPointerEvents ) {
11098 // IE and Opera don't support CSS pointer-events: none that we use to disable link-based buttons
11099 // by adding the 'ui-disabled' class to them. Using a JavaScript workaround for those browser.
11100 // https://github.com/jquery/jquery-mobile/issues/3558
11101
11102 $.mobile.document.delegate( ".ui-disabled", "vclick",
11103 function( e ) {
11104 e.preventDefault();
11105 e.stopImmediatePropagation();
11106 }
11107 );
11108 }
11109 });
11110}( jQuery, this ));
11111
11112
11113}));
diff --git a/frontend/gamma/js/main.mobile.js b/frontend/gamma/js/main.mobile.js
index 2fdd920..363d9ed 100644
--- a/frontend/gamma/js/main.mobile.js
+++ b/frontend/gamma/js/main.mobile.js
@@ -19,44 +19,63 @@ refer to http://www.clipperz.com.
19* You should have received a copy of the GNU Affero General Public 19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/. 20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21 21
22*/ 22*/
23 23
24function _pm_logEvent(anEvent) { 24function _pm_logEvent(anEvent) {
25 //console.log("####", anEvent); 25 //console.log("####", anEvent);
26 26
27 anEvent.preventDefault(); 27 anEvent.preventDefault();
28} 28}
29 29
30function handleGenericDeferredError(anError) { 30function handleGenericDeferredError(anError) {
31 var result; 31 var result;
32 32
33 if (anError instanceof MochiKit.Async.CancelledError) { 33 if (anError instanceof MochiKit.Async.CancelledError) {
34 result = anError; 34 result = anError;
35 } else { 35 } else {
36MochiKit.Logging.logError("## MainController - GENERIC ERROR" + "\n" + "==>> " + anError + " <<==\n" + anError.stack); 36MochiKit.Logging.logError("## MainController - GENERIC ERROR" + "\n" + "==>> " + anError + " <<==\n" + anError.stack);
37 result = new MochiKit.Async.CancelledError(anError); 37 result = new MochiKit.Async.CancelledError(anError);
38 } 38 }
39 39
40 return result; 40 return result;
41} 41}
42 42
43
44Clipperz.PM.RunTime = {}; 43Clipperz.PM.RunTime = {};
45 44
45//==============================================================================
46
47function registerJQMLogEvents () {
48 var interestingEvents = [
49 'pagebeforeload', 'pageload', 'pageloadfailed',
50 'pagebeforechange', 'pagechange','pagechangefailed',
51 'pagebeforeshow','pagebeforehide',
52 'pageshow', 'pagehide',
53 'pagebeforecreate','pagecreate',
54 'pageinit',
55 'pageremove'
56 ]
57
58 interestingEvents.map(function (anEvent) {
59 $(document).on(anEvent,MochiKit.Base.partial(logJQMEvent, anEvent));
60 })
61}
62
63function logJQMEvent (anEventName, anEvent, someData) {
64 //console.log(anEventName);
65 console.log(anEventName, someData);
66 //console.log(anEventName, anEvent, someData);
67}
68
69//==============================================================================
46 70
47function run() { 71function run() {
48 Clipperz.PM.Strings.Languages.initSetup(); 72 Clipperz.PM.Strings.Languages.initSetup();
49 73
50 Clipperz.PM.RunTime.mainController = new Clipperz.PM.UI.Mobile.Controllers.MainController(); 74 Clipperz.PM.RunTime.mainController = new Clipperz.PM.UI.Mobile.Controllers.MainController();
51 Clipperz.PM.RunTime.mainController.run(); 75 Clipperz.PM.RunTime.mainController.run();
52} 76}
53 77
54// if (navigator.standalone == false) { 78//==============================================================================
55 // window.localStorage.setItem('PIN', '1234');
56 // alert("Saved PIN");
57// } else {
58 // alert (window.localStorage.getItem('PIN'));
59// }
60
61 79
80//registerJQMLogEvents();
62MochiKit.DOM.addLoadEvent(run); 81MochiKit.DOM.addLoadEvent(run);