]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libxo/doc/libxo-manual.html
Import libxo-0.9.0:
[FreeBSD/FreeBSD.git] / contrib / libxo / doc / libxo-manual.html
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
2 <html lang="en">
3 <head profile="http://www.w3.org/2006/03/hcard">
4 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5 <title>libxo: The Easy Way to Generate text, XML, JSON, and HTML output</title>
6 <style type="text/css">/*
7  * $Id$
8  *
9  * Copyright (c) 2006-2011, Juniper Networks, Inc.
10  * All rights reserved.
11  * This SOFTWARE is licensed under the LICENSE provided in the
12  * ../Copyright file. By downloading, installing, copying, or otherwise
13  * using the SOFTWARE, you agree to be bound by the terms of that
14  * LICENSE.
15  */
16
17 #media-inspector {
18     display:none
19 }
20 @media screen {
21     #media-inspector { z-index: 1 }
22 }
23 @media print {
24     #media-inspector { z-index: 2 }
25 }
26
27 pre {
28     font-family: Consolas, Menlo, Monaco,Lucida Console, Liberation Mono,
29                  DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New,
30                  monospace, serif;
31     margin-bottom: 10px;
32 }
33
34 @media screen {
35     hr.noprint {
36         display: none;
37     }
38
39     h1, h2, h3, h4, h5 {
40         font-size: 14pt;
41         color: black;
42         margin: 0;
43         padding: 0;
44     }
45     h1 a, h2 a, h3 a, h4 a, h5 a {
46         font-size: 12pt;
47         color: black;
48     }
49
50     div#top {
51         display: table;
52     }
53
54     div#top-left {
55         display: table-cell;
56         width: 400px;
57         border: 1px solid black;
58         border-right: 0px;
59     }
60
61     div#top-right {
62         display: table-cell;
63         width: 100%;
64         border: 1px solid black;
65     }
66
67     div.section-number {
68         display: none;
69     }
70
71     div.fake-content {
72         display: block;
73         background-color: #d0d0f0;
74     }
75
76     div.fake-active {
77         display: block;
78         background-color: #f0d0d0;
79     }
80
81     div#nav-bar {
82         display: inline-block;
83         float: right;
84     }
85
86     div#nav-bar button#nav-next {
87         margin-right: 1em;
88     }
89
90     div#nav-bar button {
91         border-radius: 4px;
92     }
93
94     div.content {
95         display: none;
96     }
97
98     div.active {
99         display: block;
100     }
101
102     a.toc-active {
103         background-color: #dddddd;
104     }
105
106     div.self-section-number {
107         display: none;
108     }
109
110     div#debug-log {
111         white-space: pre-wrap;
112     }
113
114     h1, h2, h3, h4, h5 {
115         margin: 0;
116     }
117
118     div#toc {
119         overflow-y: scroll;
120     }
121
122     div#toc > ul.toc {
123         margin-left: 2px;
124     }
125
126     table.header {
127         display: none;
128     }
129
130     p#title span.filename {
131         display: none;
132     }
133
134     p#title {
135         margin-top: 20px;
136     }
137
138     ul.top-toc {
139         display: none;
140     }
141
142     ul.top-toc-open {
143         display: block;
144     }
145
146     div.padding {
147         width: 300px;
148     }
149
150 }
151
152 @media print {
153     div.self-section-number, div.section-number {
154         display: block-inline;
155     }
156
157     button {
158         display: none;
159     }
160
161     h1 {
162         font-size: 14pt;
163         /*  line-height: 21pt;*/
164         page-break-after: avoid;
165     }
166     h1.np {
167         page-break-before: always;
168     }
169     h1 a {
170         color: #333333;
171     }
172     h2 {
173         font-size: 12pt;
174         /*  line-height: 15pt; */
175         page-break-after: avoid;
176     }
177     h2 a {
178         color: black;
179     }
180     h3 {
181         font-size: 10pt;
182         page-break-after: avoid;
183     }
184     h3 a {
185         color: black;
186     }
187     h4 {
188         font-size: 10pt;
189         page-break-after: avoid;
190     }
191     h4 a {
192         color: black;
193     }
194     h5 {
195         font-size: 10pt;
196         page-break-after: avoid;
197     }
198     h5 a {
199         color: black;
200     }
201 }
202
203 p.section-contents, p.section-contents + ul {
204     background-color: #f8f8ff;
205     padding: 1em 0px 1em 3em;
206     border: 1px dotted #0000c0;
207 }
208
209 p.section-contents + ul {
210     margin: 0px 1em 0px 3em;
211     border-top: 0px;
212 }
213
214 p.section-contents {
215     margin: 3em 1em 0px 3em;
216     font-weight: bold;
217     border-bottom: 0px;
218     padding-bottom: 0px;
219 }
220 </style>
221 <style type="text/css" title="Xml2Rfc (sans serif)">
222 a {
223   text-decoration: none;
224 }
225 a.smpl {
226   color: black;
227 }
228 a:hover {
229   text-decoration: underline;
230 }
231 a:active {
232   text-decoration: underline;
233 }
234 address {
235   margin-top: 1em;
236   margin-left: 2em;
237   font-style: normal;
238 }
239 body {
240   color: black;
241   font-family: verdana, helvetica, arial, sans-serif;
242   font-size: 10pt;
243 }
244 cite {
245   font-style: normal;
246 }
247 dd {
248   margin-right: 2em;
249 }
250 dl {
251   margin-left: 2em;
252 }
253
254 dl.empty dd {
255   margin-top: .5em;
256 }
257 dl p {
258   margin-left: 0em;
259 }
260 dt {
261   margin-top: .5em;
262 }
263 img {
264   margin-left: 3em;
265 }
266 li {
267   margin-left: 2em;
268   margin-right: 2em;
269 }
270 ol {
271   margin-left: 2em;
272   margin-right: 2em;
273 }
274 ol p {
275   margin-left: 0em;
276 }
277 p {
278   margin-left: 2em;
279   margin-right: 2em;
280 }
281 pre {
282   margin-left: 3em;
283   background-color: lightyellow;
284   padding: .25em;
285   padding-top: 12px;
286   margin-right: 1em;
287   -moz-box-shadow:    0 0 4px #000000;
288   -webkit-box-shadow: 0 0 4px #000000;
289   box-shadow:         0 0 4px #000000;
290 }
291 pre.text2 {
292   border-style: dotted;
293   border-width: 1px;
294   background-color: #f0f0f0;
295   width: 69em;
296 }
297 pre.inline {
298   background-color: white;
299   padding: 0em;
300 }
301 pre.text {
302   border-style: dotted;
303   border-width: 1px;
304   background-color: #f8f8f8;
305   width: 69em;
306 }
307 pre.drawing {
308   border-style: solid;
309   border-width: 1px;
310   background-color: #f8f8f8;
311   padding: 2em;
312 }
313 table {
314   margin-left: 2em;
315 }
316 table.tt {
317   vertical-align: top;
318 }
319 table.full {
320   border-style: outset;
321   border-width: 1px;
322   margin-left: 3em;
323   background-color: lightyellow;
324   padding: .25em;
325   -moz-box-shadow:    0 0 4px #000000;
326   -webkit-box-shadow: 0 0 4px #000000;
327   box-shadow:         0 0 4px #000000;
328 }
329 table.headers {
330   border-style: outset;
331   border-width: 1px;
332 }
333 table.tt td {
334   vertical-align: top;
335 }
336 table.full td {
337   border-style: inset;
338   border-width: 1px;
339 }
340 table.tt th {
341   vertical-align: top;
342 }
343 table.full th {
344   border-style: inset;
345   border-width: 1px;
346 }
347 table.headers th {
348   border-style: none none inset none;
349   border-width: 1px;
350 }
351 table.header {
352   width: 95%;
353   font-size: 10pt;
354   color: white;
355 }
356 td.top {
357   vertical-align: top;
358 }
359 td.topnowrap {
360   vertical-align: top;
361   white-space: nowrap; 
362 }
363 td.header {
364   background-color: gray;
365   width: 50%;
366 }
367 td.header a {
368   color: white;
369 }
370 td.reference {
371   vertical-align: top;
372   white-space: nowrap;
373   padding-right: 1em;
374 }
375 thead {
376   display:table-header-group;
377 }
378 ul.toc {
379   list-style: none;
380   margin-left: 1.5em;
381   margin-right: 0em;
382   padding-left: 0em;
383 }
384 li.tocline0 {
385   line-height: 150%;
386   font-weight: bold;
387   font-size: 10pt;
388   margin-left: 0em;
389   margin-right: 0em;
390 }
391 li.tocline1 {
392   line-height: normal;
393   font-weight: normal;
394   font-size: 9pt;
395   margin-left: 0em;
396   margin-right: 0em;
397 }
398 li.tocline2 {
399   font-size: 0pt;
400 }
401 ul p {
402   margin-left: 0em;
403 }
404 ul.ind {
405   list-style: none;
406   margin-left: 1.5em;
407   margin-right: 0em;
408   padding-left: 0em;
409 }
410 li.indline0 {
411   font-weight: bold;
412   line-height: 200%;
413   margin-left: 0em;
414   margin-right: 0em;
415 }
416 li.indline1 {
417   font-weight: normal;
418   line-height: 150%;
419   margin-left: 0em;
420   margin-right: 0em;
421 }
422
423 .comment {
424   background-color: yellow;
425 }
426 .center {
427   text-align: center;
428 }
429 .error {
430   color: red;
431   font-style: italic;
432   font-weight: bold;
433 }
434 .figure {
435   font-weight: bold;
436   text-align: center;
437   font-size: 9pt;
438 }
439 .filename {
440   color: #333333;
441   font-weight: bold;
442   font-size: 12pt;
443   line-height: 21pt;
444   text-align: center;
445 }
446 .fn {
447   font-weight: bold;
448 }
449 .hidden {
450   display: none;
451 }
452 .left {
453   text-align: left;
454 }
455 .right {
456   text-align: right;
457 }
458 .title {
459   color: #990000;
460   font-size: 18pt;
461   line-height: 18pt;
462   font-weight: bold;
463   text-align: center;
464   margin-top: 36pt;
465 }
466 .vcardline {
467   display: block;
468 }
469 .warning {
470   font-size: 14pt;
471   background-color: yellow;
472 }
473
474
475 @media print {
476   .noprint {
477     display: none;
478   }
479   
480   a {
481     color: black;
482     text-decoration: none;
483   }
484
485   table.header {
486     width: 90%;
487   }
488
489   td.header {
490     width: 50%;
491     color: black;
492     background-color: white;
493     vertical-align: top;
494     font-size: 12pt;
495   }
496
497   ul.toc a::after {
498     content: leader('.') target-counter(attr(href), page);
499   }
500   
501   a.iref {
502     content: target-counter(attr(href), page);
503   }
504   
505   .print2col {
506     column-count: 2;
507     -moz-column-count: 2;
508     column-fill: auto;
509   }
510 }
511
512 @page {
513   @top-left {
514        content: "";
515  
516   } 
517   @top-right {
518        content: "May 2018";
519  
520   } 
521   @top-center {
522        content: "LIBXO-MANUAL";
523  
524   } 
525   @bottom-left {
526        content: "Shafer";
527  
528   } 
529   @bottom-center {
530        content: "";
531  
532   } 
533   @bottom-right {
534        content: "[Page " counter(page) "]";
535  
536   } 
537 }
538
539 @page:first { 
540     @top-left {
541       content: normal;
542     }
543     @top-right {
544       content: normal;
545     }
546     @top-center {
547       content: normal;
548     }
549 }
550
551 div.tooltip {
552   border: solid 1px #666666;
553   padding: 0px;
554   position: absolute;
555   z-index: 100;
556   display: none;
557   color: #333333;
558   top: 20px;
559   left: 90px;
560   background-color: #ffffcc;
561   layer-background-color: #ffffcc;
562 }
563
564 div.fancy-tooltip-empty-header {
565   text-align: left;
566   font-weight: bold;
567   margin: 2px;
568 }
569
570 div.fancy-tooltip-header {
571   text-align: left;
572   font-weight: bold;
573   margin: 2px 2px 0px 2px;
574   border-bottom: 1px solid black;
575 }
576
577 div.fancy-tooltip-body {
578   font-weight: normal;
579   margin: 4px;
580 }
581
582 div.fancy-tooltip-body ul, div.fancy-tooltip-body li  {
583   padding: 1px 4px 1px 4px;
584   margin: 1px 2px 1px 8px;
585 }
586
587 span.digress {
588   background-color: #778899;
589   font: courier new, courier, monospace;
590   color: black;
591   font-weight: bold;
592   font-size: 10px;
593   border: 1px solid #aaaaaa;
594 }
595
596 span.digress-anchor {
597   margin: 10pt 20pt 10pt 50pt;
598 }
599
600 a.digress-anchor:link, a.digress-anchor:visited, 
601         a.digress-anchor-hover, a.digress-anchor,active {
602   text-decoration: none;
603   color: black;
604 }
605
606 </style>
607 <script type="text/javascript">/*!
608  * jQuery JavaScript Library v1.7
609  * http://jquery.com/
610  *
611  * Copyright 2011, John Resig
612  * Dual licensed under the MIT or GPL Version 2 licenses.
613  * http://jquery.org/license
614  *
615  * Includes Sizzle.js
616  * http://sizzlejs.com/
617  * Copyright 2011, The Dojo Foundation
618  * Released under the MIT, BSD, and GPL Licenses.
619  *
620  * Date: Thu Nov 3 16:18:21 2011 -0400
621  */
622 (function( window, undefined ) {
623
624 // Use the correct document accordingly with window argument (sandbox)
625 var document = window.document,
626         navigator = window.navigator,
627         location = window.location;
628 var jQuery = (function() {
629
630 // Define a local copy of jQuery
631 var jQuery = function( selector, context ) {
632                 // The jQuery object is actually just the init constructor 'enhanced'
633                 return new jQuery.fn.init( selector, context, rootjQuery );
634         },
635
636         // Map over jQuery in case of overwrite
637         _jQuery = window.jQuery,
638
639         // Map over the $ in case of overwrite
640         _$ = window.$,
641
642         // A central reference to the root jQuery(document)
643         rootjQuery,
644
645         // A simple way to check for HTML strings or ID strings
646         // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
647         quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
648
649         // Check if a string has a non-whitespace character in it
650         rnotwhite = /\S/,
651
652         // Used for trimming whitespace
653         trimLeft = /^\s+/,
654         trimRight = /\s+$/,
655
656         // Check for digits
657         rdigit = /\d/,
658
659         // Match a standalone tag
660         rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
661
662         // JSON RegExp
663         rvalidchars = /^[\],:{}\s]*$/,
664         rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
665         rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
666         rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
667
668         // Useragent RegExp
669         rwebkit = /(webkit)[ \/]([\w.]+)/,
670         ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
671         rmsie = /(msie) ([\w.]+)/,
672         rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
673
674         // Matches dashed string for camelizing
675         rdashAlpha = /-([a-z]|[0-9])/ig,
676         rmsPrefix = /^-ms-/,
677
678         // Used by jQuery.camelCase as callback to replace()
679         fcamelCase = function( all, letter ) {
680                 return ( letter + "" ).toUpperCase();
681         },
682
683         // Keep a UserAgent string for use with jQuery.browser
684         userAgent = navigator.userAgent,
685
686         // For matching the engine and version of the browser
687         browserMatch,
688
689         // The deferred used on DOM ready
690         readyList,
691
692         // The ready event handler
693         DOMContentLoaded,
694
695         // Save a reference to some core methods
696         toString = Object.prototype.toString,
697         hasOwn = Object.prototype.hasOwnProperty,
698         push = Array.prototype.push,
699         slice = Array.prototype.slice,
700         trim = String.prototype.trim,
701         indexOf = Array.prototype.indexOf,
702
703         // [[Class]] -> type pairs
704         class2type = {};
705
706 jQuery.fn = jQuery.prototype = {
707         constructor: jQuery,
708         init: function( selector, context, rootjQuery ) {
709                 var match, elem, ret, doc;
710
711                 // Handle $(""), $(null), or $(undefined)
712                 if ( !selector ) {
713                         return this;
714                 }
715
716                 // Handle $(DOMElement)
717                 if ( selector.nodeType ) {
718                         this.context = this[0] = selector;
719                         this.length = 1;
720                         return this;
721                 }
722
723                 // The body element only exists once, optimize finding it
724                 if ( selector === "body" && !context && document.body ) {
725                         this.context = document;
726                         this[0] = document.body;
727                         this.selector = selector;
728                         this.length = 1;
729                         return this;
730                 }
731
732                 // Handle HTML strings
733                 if ( typeof selector === "string" ) {
734                         // Are we dealing with HTML string or an ID?
735                         if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
736                                 // Assume that strings that start and end with <> are HTML and skip the regex check
737                                 match = [ null, selector, null ];
738
739                         } else {
740                                 match = quickExpr.exec( selector );
741                         }
742
743                         // Verify a match, and that no context was specified for #id
744                         if ( match && (match[1] || !context) ) {
745
746                                 // HANDLE: $(html) -> $(array)
747                                 if ( match[1] ) {
748                                         context = context instanceof jQuery ? context[0] : context;
749                                         doc = ( context ? context.ownerDocument || context : document );
750
751                                         // If a single string is passed in and it's a single tag
752                                         // just do a createElement and skip the rest
753                                         ret = rsingleTag.exec( selector );
754
755                                         if ( ret ) {
756                                                 if ( jQuery.isPlainObject( context ) ) {
757                                                         selector = [ document.createElement( ret[1] ) ];
758                                                         jQuery.fn.attr.call( selector, context, true );
759
760                                                 } else {
761                                                         selector = [ doc.createElement( ret[1] ) ];
762                                                 }
763
764                                         } else {
765                                                 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
766                                                 selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
767                                         }
768
769                                         return jQuery.merge( this, selector );
770
771                                 // HANDLE: $("#id")
772                                 } else {
773                                         elem = document.getElementById( match[2] );
774
775                                         // Check parentNode to catch when Blackberry 4.6 returns
776                                         // nodes that are no longer in the document #6963
777                                         if ( elem && elem.parentNode ) {
778                                                 // Handle the case where IE and Opera return items
779                                                 // by name instead of ID
780                                                 if ( elem.id !== match[2] ) {
781                                                         return rootjQuery.find( selector );
782                                                 }
783
784                                                 // Otherwise, we inject the element directly into the jQuery object
785                                                 this.length = 1;
786                                                 this[0] = elem;
787                                         }
788
789                                         this.context = document;
790                                         this.selector = selector;
791                                         return this;
792                                 }
793
794                         // HANDLE: $(expr, $(...))
795                         } else if ( !context || context.jquery ) {
796                                 return ( context || rootjQuery ).find( selector );
797
798                         // HANDLE: $(expr, context)
799                         // (which is just equivalent to: $(context).find(expr)
800                         } else {
801                                 return this.constructor( context ).find( selector );
802                         }
803
804                 // HANDLE: $(function)
805                 // Shortcut for document ready
806                 } else if ( jQuery.isFunction( selector ) ) {
807                         return rootjQuery.ready( selector );
808                 }
809
810                 if ( selector.selector !== undefined ) {
811                         this.selector = selector.selector;
812                         this.context = selector.context;
813                 }
814
815                 return jQuery.makeArray( selector, this );
816         },
817
818         // Start with an empty selector
819         selector: "",
820
821         // The current version of jQuery being used
822         jquery: "1.7",
823
824         // The default length of a jQuery object is 0
825         length: 0,
826
827         // The number of elements contained in the matched element set
828         size: function() {
829                 return this.length;
830         },
831
832         toArray: function() {
833                 return slice.call( this, 0 );
834         },
835
836         // Get the Nth element in the matched element set OR
837         // Get the whole matched element set as a clean array
838         get: function( num ) {
839                 return num == null ?
840
841                         // Return a 'clean' array
842                         this.toArray() :
843
844                         // Return just the object
845                         ( num < 0 ? this[ this.length + num ] : this[ num ] );
846         },
847
848         // Take an array of elements and push it onto the stack
849         // (returning the new matched element set)
850         pushStack: function( elems, name, selector ) {
851                 // Build a new jQuery matched element set
852                 var ret = this.constructor();
853
854                 if ( jQuery.isArray( elems ) ) {
855                         push.apply( ret, elems );
856
857                 } else {
858                         jQuery.merge( ret, elems );
859                 }
860
861                 // Add the old object onto the stack (as a reference)
862                 ret.prevObject = this;
863
864                 ret.context = this.context;
865
866                 if ( name === "find" ) {
867                         ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
868                 } else if ( name ) {
869                         ret.selector = this.selector + "." + name + "(" + selector + ")";
870                 }
871
872                 // Return the newly-formed element set
873                 return ret;
874         },
875
876         // Execute a callback for every element in the matched set.
877         // (You can seed the arguments with an array of args, but this is
878         // only used internally.)
879         each: function( callback, args ) {
880                 return jQuery.each( this, callback, args );
881         },
882
883         ready: function( fn ) {
884                 // Attach the listeners
885                 jQuery.bindReady();
886
887                 // Add the callback
888                 readyList.add( fn );
889
890                 return this;
891         },
892
893         eq: function( i ) {
894                 return i === -1 ?
895                         this.slice( i ) :
896                         this.slice( i, +i + 1 );
897         },
898
899         first: function() {
900                 return this.eq( 0 );
901         },
902
903         last: function() {
904                 return this.eq( -1 );
905         },
906
907         slice: function() {
908                 return this.pushStack( slice.apply( this, arguments ),
909                         "slice", slice.call(arguments).join(",") );
910         },
911
912         map: function( callback ) {
913                 return this.pushStack( jQuery.map(this, function( elem, i ) {
914                         return callback.call( elem, i, elem );
915                 }));
916         },
917
918         end: function() {
919                 return this.prevObject || this.constructor(null);
920         },
921
922         // For internal use only.
923         // Behaves like an Array's method, not like a jQuery method.
924         push: push,
925         sort: [].sort,
926         splice: [].splice
927 };
928
929 // Give the init function the jQuery prototype for later instantiation
930 jQuery.fn.init.prototype = jQuery.fn;
931
932 jQuery.extend = jQuery.fn.extend = function() {
933         var options, name, src, copy, copyIsArray, clone,
934                 target = arguments[0] || {},
935                 i = 1,
936                 length = arguments.length,
937                 deep = false;
938
939         // Handle a deep copy situation
940         if ( typeof target === "boolean" ) {
941                 deep = target;
942                 target = arguments[1] || {};
943                 // skip the boolean and the target
944                 i = 2;
945         }
946
947         // Handle case when target is a string or something (possible in deep copy)
948         if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
949                 target = {};
950         }
951
952         // extend jQuery itself if only one argument is passed
953         if ( length === i ) {
954                 target = this;
955                 --i;
956         }
957
958         for ( ; i < length; i++ ) {
959                 // Only deal with non-null/undefined values
960                 if ( (options = arguments[ i ]) != null ) {
961                         // Extend the base object
962                         for ( name in options ) {
963                                 src = target[ name ];
964                                 copy = options[ name ];
965
966                                 // Prevent never-ending loop
967                                 if ( target === copy ) {
968                                         continue;
969                                 }
970
971                                 // Recurse if we're merging plain objects or arrays
972                                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
973                                         if ( copyIsArray ) {
974                                                 copyIsArray = false;
975                                                 clone = src && jQuery.isArray(src) ? src : [];
976
977                                         } else {
978                                                 clone = src && jQuery.isPlainObject(src) ? src : {};
979                                         }
980
981                                         // Never move original objects, clone them
982                                         target[ name ] = jQuery.extend( deep, clone, copy );
983
984                                 // Don't bring in undefined values
985                                 } else if ( copy !== undefined ) {
986                                         target[ name ] = copy;
987                                 }
988                         }
989                 }
990         }
991
992         // Return the modified object
993         return target;
994 };
995
996 jQuery.extend({
997         noConflict: function( deep ) {
998                 if ( window.$ === jQuery ) {
999                         window.$ = _$;
1000                 }
1001
1002                 if ( deep && window.jQuery === jQuery ) {
1003                         window.jQuery = _jQuery;
1004                 }
1005
1006                 return jQuery;
1007         },
1008
1009         // Is the DOM ready to be used? Set to true once it occurs.
1010         isReady: false,
1011
1012         // A counter to track how many items to wait for before
1013         // the ready event fires. See #6781
1014         readyWait: 1,
1015
1016         // Hold (or release) the ready event
1017         holdReady: function( hold ) {
1018                 if ( hold ) {
1019                         jQuery.readyWait++;
1020                 } else {
1021                         jQuery.ready( true );
1022                 }
1023         },
1024
1025         // Handle when the DOM is ready
1026         ready: function( wait ) {
1027                 // Either a released hold or an DOMready/load event and not yet ready
1028                 if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
1029                         // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
1030                         if ( !document.body ) {
1031                                 return setTimeout( jQuery.ready, 1 );
1032                         }
1033
1034                         // Remember that the DOM is ready
1035                         jQuery.isReady = true;
1036
1037                         // If a normal DOM Ready event fired, decrement, and wait if need be
1038                         if ( wait !== true && --jQuery.readyWait > 0 ) {
1039                                 return;
1040                         }
1041
1042                         // If there are functions bound, to execute
1043                         readyList.fireWith( document, [ jQuery ] );
1044
1045                         // Trigger any bound ready events
1046                         if ( jQuery.fn.trigger ) {
1047                                 jQuery( document ).trigger( "ready" ).unbind( "ready" );
1048                         }
1049                 }
1050         },
1051
1052         bindReady: function() {
1053                 if ( readyList ) {
1054                         return;
1055                 }
1056
1057                 readyList = jQuery.Callbacks( "once memory" );
1058
1059                 // Catch cases where $(document).ready() is called after the
1060                 // browser event has already occurred.
1061                 if ( document.readyState === "complete" ) {
1062                         // Handle it asynchronously to allow scripts the opportunity to delay ready
1063                         return setTimeout( jQuery.ready, 1 );
1064                 }
1065
1066                 // Mozilla, Opera and webkit nightlies currently support this event
1067                 if ( document.addEventListener ) {
1068                         // Use the handy event callback
1069                         document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
1070
1071                         // A fallback to window.onload, that will always work
1072                         window.addEventListener( "load", jQuery.ready, false );
1073
1074                 // If IE event model is used
1075                 } else if ( document.attachEvent ) {
1076                         // ensure firing before onload,
1077                         // maybe late but safe also for iframes
1078                         document.attachEvent( "onreadystatechange", DOMContentLoaded );
1079
1080                         // A fallback to window.onload, that will always work
1081                         window.attachEvent( "onload", jQuery.ready );
1082
1083                         // If IE and not a frame
1084                         // continually check to see if the document is ready
1085                         var toplevel = false;
1086
1087                         try {
1088                                 toplevel = window.frameElement == null;
1089                         } catch(e) {}
1090
1091                         if ( document.documentElement.doScroll && toplevel ) {
1092                                 doScrollCheck();
1093                         }
1094                 }
1095         },
1096
1097         // See test/unit/core.js for details concerning isFunction.
1098         // Since version 1.3, DOM methods and functions like alert
1099         // aren't supported. They return false on IE (#2968).
1100         isFunction: function( obj ) {
1101                 return jQuery.type(obj) === "function";
1102         },
1103
1104         isArray: Array.isArray || function( obj ) {
1105                 return jQuery.type(obj) === "array";
1106         },
1107
1108         // A crude way of determining if an object is a window
1109         isWindow: function( obj ) {
1110                 return obj && typeof obj === "object" && "setInterval" in obj;
1111         },
1112
1113         isNumeric: function( obj ) {
1114                 return obj != null && rdigit.test( obj ) && !isNaN( obj );
1115         },
1116
1117         type: function( obj ) {
1118                 return obj == null ?
1119                         String( obj ) :
1120                         class2type[ toString.call(obj) ] || "object";
1121         },
1122
1123         isPlainObject: function( obj ) {
1124                 // Must be an Object.
1125                 // Because of IE, we also have to check the presence of the constructor property.
1126                 // Make sure that DOM nodes and window objects don't pass through, as well
1127                 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
1128                         return false;
1129                 }
1130
1131                 try {
1132                         // Not own constructor property must be Object
1133                         if ( obj.constructor &&
1134                                 !hasOwn.call(obj, "constructor") &&
1135                                 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
1136                                 return false;
1137                         }
1138                 } catch ( e ) {
1139                         // IE8,9 Will throw exceptions on certain host objects #9897
1140                         return false;
1141                 }
1142
1143                 // Own properties are enumerated firstly, so to speed up,
1144                 // if last one is own, then all properties are own.
1145
1146                 var key;
1147                 for ( key in obj ) {}
1148
1149                 return key === undefined || hasOwn.call( obj, key );
1150         },
1151
1152         isEmptyObject: function( obj ) {
1153                 for ( var name in obj ) {
1154                         return false;
1155                 }
1156                 return true;
1157         },
1158
1159         error: function( msg ) {
1160                 throw msg;
1161         },
1162
1163         parseJSON: function( data ) {
1164                 if ( typeof data !== "string" || !data ) {
1165                         return null;
1166                 }
1167
1168                 // Make sure leading/trailing whitespace is removed (IE can't handle it)
1169                 data = jQuery.trim( data );
1170
1171                 // Attempt to parse using the native JSON parser first
1172                 if ( window.JSON && window.JSON.parse ) {
1173                         return window.JSON.parse( data );
1174                 }
1175
1176                 // Make sure the incoming data is actual JSON
1177                 // Logic borrowed from http://json.org/json2.js
1178                 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
1179                         .replace( rvalidtokens, "]" )
1180                         .replace( rvalidbraces, "")) ) {
1181
1182                         return ( new Function( "return " + data ) )();
1183
1184                 }
1185                 jQuery.error( "Invalid JSON: " + data );
1186         },
1187
1188         // Cross-browser xml parsing
1189         parseXML: function( data ) {
1190                 var xml, tmp;
1191                 try {
1192                         if ( window.DOMParser ) { // Standard
1193                                 tmp = new DOMParser();
1194                                 xml = tmp.parseFromString( data , "text/xml" );
1195                         } else { // IE
1196                                 xml = new ActiveXObject( "Microsoft.XMLDOM" );
1197                                 xml.async = "false";
1198                                 xml.loadXML( data );
1199                         }
1200                 } catch( e ) {
1201                         xml = undefined;
1202                 }
1203                 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
1204                         jQuery.error( "Invalid XML: " + data );
1205                 }
1206                 return xml;
1207         },
1208
1209         noop: function() {},
1210
1211         // Evaluates a script in a global context
1212         // Workarounds based on findings by Jim Driscoll
1213         // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
1214         globalEval: function( data ) {
1215                 if ( data && rnotwhite.test( data ) ) {
1216                         // We use execScript on Internet Explorer
1217                         // We use an anonymous function so that context is window
1218                         // rather than jQuery in Firefox
1219                         ( window.execScript || function( data ) {
1220                                 window[ "eval" ].call( window, data );
1221                         } )( data );
1222                 }
1223         },
1224
1225         // Convert dashed to camelCase; used by the css and data modules
1226         // Microsoft forgot to hump their vendor prefix (#9572)
1227         camelCase: function( string ) {
1228                 return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
1229         },
1230
1231         nodeName: function( elem, name ) {
1232                 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
1233         },
1234
1235         // args is for internal usage only
1236         each: function( object, callback, args ) {
1237                 var name, i = 0,
1238                         length = object.length,
1239                         isObj = length === undefined || jQuery.isFunction( object );
1240
1241                 if ( args ) {
1242                         if ( isObj ) {
1243                                 for ( name in object ) {
1244                                         if ( callback.apply( object[ name ], args ) === false ) {
1245                                                 break;
1246                                         }
1247                                 }
1248                         } else {
1249                                 for ( ; i < length; ) {
1250                                         if ( callback.apply( object[ i++ ], args ) === false ) {
1251                                                 break;
1252                                         }
1253                                 }
1254                         }
1255
1256                 // A special, fast, case for the most common use of each
1257                 } else {
1258                         if ( isObj ) {
1259                                 for ( name in object ) {
1260                                         if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
1261                                                 break;
1262                                         }
1263                                 }
1264                         } else {
1265                                 for ( ; i < length; ) {
1266                                         if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
1267                                                 break;
1268                                         }
1269                                 }
1270                         }
1271                 }
1272
1273                 return object;
1274         },
1275
1276         // Use native String.trim function wherever possible
1277         trim: trim ?
1278                 function( text ) {
1279                         return text == null ?
1280                                 "" :
1281                                 trim.call( text );
1282                 } :
1283
1284                 // Otherwise use our own trimming functionality
1285                 function( text ) {
1286                         return text == null ?
1287                                 "" :
1288                                 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
1289                 },
1290
1291         // results is for internal usage only
1292         makeArray: function( array, results ) {
1293                 var ret = results || [];
1294
1295                 if ( array != null ) {
1296                         // The window, strings (and functions) also have 'length'
1297                         // The extra typeof function check is to prevent crashes
1298                         // in Safari 2 (See: #3039)
1299                         // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
1300                         var type = jQuery.type( array );
1301
1302                         if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
1303                                 push.call( ret, array );
1304                         } else {
1305                                 jQuery.merge( ret, array );
1306                         }
1307                 }
1308
1309                 return ret;
1310         },
1311
1312         inArray: function( elem, array, i ) {
1313                 var len;
1314
1315                 if ( array ) {
1316                         if ( indexOf ) {
1317                                 return indexOf.call( array, elem, i );
1318                         }
1319
1320                         len = array.length;
1321                         i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
1322
1323                         for ( ; i < len; i++ ) {
1324                                 // Skip accessing in sparse arrays
1325                                 if ( i in array && array[ i ] === elem ) {
1326                                         return i;
1327                                 }
1328                         }
1329                 }
1330
1331                 return -1;
1332         },
1333
1334         merge: function( first, second ) {
1335                 var i = first.length,
1336                         j = 0;
1337
1338                 if ( typeof second.length === "number" ) {
1339                         for ( var l = second.length; j < l; j++ ) {
1340                                 first[ i++ ] = second[ j ];
1341                         }
1342
1343                 } else {
1344                         while ( second[j] !== undefined ) {
1345                                 first[ i++ ] = second[ j++ ];
1346                         }
1347                 }
1348
1349                 first.length = i;
1350
1351                 return first;
1352         },
1353
1354         grep: function( elems, callback, inv ) {
1355                 var ret = [], retVal;
1356                 inv = !!inv;
1357
1358                 // Go through the array, only saving the items
1359                 // that pass the validator function
1360                 for ( var i = 0, length = elems.length; i < length; i++ ) {
1361                         retVal = !!callback( elems[ i ], i );
1362                         if ( inv !== retVal ) {
1363                                 ret.push( elems[ i ] );
1364                         }
1365                 }
1366
1367                 return ret;
1368         },
1369
1370         // arg is for internal usage only
1371         map: function( elems, callback, arg ) {
1372                 var value, key, ret = [],
1373                         i = 0,
1374                         length = elems.length,
1375                         // jquery objects are treated as arrays
1376                         isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
1377
1378                 // Go through the array, translating each of the items to their
1379                 if ( isArray ) {
1380                         for ( ; i < length; i++ ) {
1381                                 value = callback( elems[ i ], i, arg );
1382
1383                                 if ( value != null ) {
1384                                         ret[ ret.length ] = value;
1385                                 }
1386                         }
1387
1388                 // Go through every key on the object,
1389                 } else {
1390                         for ( key in elems ) {
1391                                 value = callback( elems[ key ], key, arg );
1392
1393                                 if ( value != null ) {
1394                                         ret[ ret.length ] = value;
1395                                 }
1396                         }
1397                 }
1398
1399                 // Flatten any nested arrays
1400                 return ret.concat.apply( [], ret );
1401         },
1402
1403         // A global GUID counter for objects
1404         guid: 1,
1405
1406         // Bind a function to a context, optionally partially applying any
1407         // arguments.
1408         proxy: function( fn, context ) {
1409                 if ( typeof context === "string" ) {
1410                         var tmp = fn[ context ];
1411                         context = fn;
1412                         fn = tmp;
1413                 }
1414
1415                 // Quick check to determine if target is callable, in the spec
1416                 // this throws a TypeError, but we will just return undefined.
1417                 if ( !jQuery.isFunction( fn ) ) {
1418                         return undefined;
1419                 }
1420
1421                 // Simulated bind
1422                 var args = slice.call( arguments, 2 ),
1423                         proxy = function() {
1424                                 return fn.apply( context, args.concat( slice.call( arguments ) ) );
1425                         };
1426
1427                 // Set the guid of unique handler to the same of original handler, so it can be removed
1428                 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
1429
1430                 return proxy;
1431         },
1432
1433         // Mutifunctional method to get and set values to a collection
1434         // The value/s can optionally be executed if it's a function
1435         access: function( elems, key, value, exec, fn, pass ) {
1436                 var length = elems.length;
1437
1438                 // Setting many attributes
1439                 if ( typeof key === "object" ) {
1440                         for ( var k in key ) {
1441                                 jQuery.access( elems, k, key[k], exec, fn, value );
1442                         }
1443                         return elems;
1444                 }
1445
1446                 // Setting one attribute
1447                 if ( value !== undefined ) {
1448                         // Optionally, function values get executed if exec is true
1449                         exec = !pass && exec && jQuery.isFunction(value);
1450
1451                         for ( var i = 0; i < length; i++ ) {
1452                                 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
1453                         }
1454
1455                         return elems;
1456                 }
1457
1458                 // Getting an attribute
1459                 return length ? fn( elems[0], key ) : undefined;
1460         },
1461
1462         now: function() {
1463                 return ( new Date() ).getTime();
1464         },
1465
1466         // Use of jQuery.browser is frowned upon.
1467         // More details: http://docs.jquery.com/Utilities/jQuery.browser
1468         uaMatch: function( ua ) {
1469                 ua = ua.toLowerCase();
1470
1471                 var match = rwebkit.exec( ua ) ||
1472                         ropera.exec( ua ) ||
1473                         rmsie.exec( ua ) ||
1474                         ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
1475                         [];
1476
1477                 return { browser: match[1] || "", version: match[2] || "0" };
1478         },
1479
1480         sub: function() {
1481                 function jQuerySub( selector, context ) {
1482                         return new jQuerySub.fn.init( selector, context );
1483                 }
1484                 jQuery.extend( true, jQuerySub, this );
1485                 jQuerySub.superclass = this;
1486                 jQuerySub.fn = jQuerySub.prototype = this();
1487                 jQuerySub.fn.constructor = jQuerySub;
1488                 jQuerySub.sub = this.sub;
1489                 jQuerySub.fn.init = function init( selector, context ) {
1490                         if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
1491                                 context = jQuerySub( context );
1492                         }
1493
1494                         return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
1495                 };
1496                 jQuerySub.fn.init.prototype = jQuerySub.fn;
1497                 var rootjQuerySub = jQuerySub(document);
1498                 return jQuerySub;
1499         },
1500
1501         browser: {}
1502 });
1503
1504 // Populate the class2type map
1505 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
1506         class2type[ "[object " + name + "]" ] = name.toLowerCase();
1507 });
1508
1509 browserMatch = jQuery.uaMatch( userAgent );
1510 if ( browserMatch.browser ) {
1511         jQuery.browser[ browserMatch.browser ] = true;
1512         jQuery.browser.version = browserMatch.version;
1513 }
1514
1515 // Deprecated, use jQuery.browser.webkit instead
1516 if ( jQuery.browser.webkit ) {
1517         jQuery.browser.safari = true;
1518 }
1519
1520 // IE doesn't match non-breaking spaces with \s
1521 if ( rnotwhite.test( "\xA0" ) ) {
1522         trimLeft = /^[\s\xA0]+/;
1523         trimRight = /[\s\xA0]+$/;
1524 }
1525
1526 // All jQuery objects should point back to these
1527 rootjQuery = jQuery(document);
1528
1529 // Cleanup functions for the document ready method
1530 if ( document.addEventListener ) {
1531         DOMContentLoaded = function() {
1532                 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
1533                 jQuery.ready();
1534         };
1535
1536 } else if ( document.attachEvent ) {
1537         DOMContentLoaded = function() {
1538                 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
1539                 if ( document.readyState === "complete" ) {
1540                         document.detachEvent( "onreadystatechange", DOMContentLoaded );
1541                         jQuery.ready();
1542                 }
1543         };
1544 }
1545
1546 // The DOM ready check for Internet Explorer
1547 function doScrollCheck() {
1548         if ( jQuery.isReady ) {
1549                 return;
1550         }
1551
1552         try {
1553                 // If IE is used, use the trick by Diego Perini
1554                 // http://javascript.nwbox.com/IEContentLoaded/
1555                 document.documentElement.doScroll("left");
1556         } catch(e) {
1557                 setTimeout( doScrollCheck, 1 );
1558                 return;
1559         }
1560
1561         // and execute any waiting functions
1562         jQuery.ready();
1563 }
1564
1565 // Expose jQuery as an AMD module, but only for AMD loaders that
1566 // understand the issues with loading multiple versions of jQuery
1567 // in a page that all might call define(). The loader will indicate
1568 // they have special allowances for multiple jQuery versions by
1569 // specifying define.amd.jQuery = true. Register as a named module,
1570 // since jQuery can be concatenated with other files that may use define,
1571 // but not use a proper concatenation script that understands anonymous
1572 // AMD modules. A named AMD is safest and most robust way to register.
1573 // Lowercase jquery is used because AMD module names are derived from
1574 // file names, and jQuery is normally delivered in a lowercase file name.
1575 if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
1576         define( "jquery", [], function () { return jQuery; } );
1577 }
1578
1579 return jQuery;
1580
1581 })();
1582
1583
1584 // String to Object flags format cache
1585 var flagsCache = {};
1586
1587 // Convert String-formatted flags into Object-formatted ones and store in cache
1588 function createFlags( flags ) {
1589         var object = flagsCache[ flags ] = {},
1590                 i, length;
1591         flags = flags.split( /\s+/ );
1592         for ( i = 0, length = flags.length; i < length; i++ ) {
1593                 object[ flags[i] ] = true;
1594         }
1595         return object;
1596 }
1597
1598 /*
1599  * Create a callback list using the following parameters:
1600  *
1601  *      flags:  an optional list of space-separated flags that will change how
1602  *                      the callback list behaves
1603  *
1604  * By default a callback list will act like an event callback list and can be
1605  * "fired" multiple times.
1606  *
1607  * Possible flags:
1608  *
1609  *      once:                   will ensure the callback list can only be fired once (like a Deferred)
1610  *
1611  *      memory:                 will keep track of previous values and will call any callback added
1612  *                                      after the list has been fired right away with the latest "memorized"
1613  *                                      values (like a Deferred)
1614  *
1615  *      unique:                 will ensure a callback can only be added once (no duplicate in the list)
1616  *
1617  *      stopOnFalse:    interrupt callings when a callback returns false
1618  *
1619  */
1620 jQuery.Callbacks = function( flags ) {
1621
1622         // Convert flags from String-formatted to Object-formatted
1623         // (we check in cache first)
1624         flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
1625
1626         var // Actual callback list
1627                 list = [],
1628                 // Stack of fire calls for repeatable lists
1629                 stack = [],
1630                 // Last fire value (for non-forgettable lists)
1631                 memory,
1632                 // Flag to know if list is currently firing
1633                 firing,
1634                 // First callback to fire (used internally by add and fireWith)
1635                 firingStart,
1636                 // End of the loop when firing
1637                 firingLength,
1638                 // Index of currently firing callback (modified by remove if needed)
1639                 firingIndex,
1640                 // Add one or several callbacks to the list
1641                 add = function( args ) {
1642                         var i,
1643                                 length,
1644                                 elem,
1645                                 type,
1646                                 actual;
1647                         for ( i = 0, length = args.length; i < length; i++ ) {
1648                                 elem = args[ i ];
1649                                 type = jQuery.type( elem );
1650                                 if ( type === "array" ) {
1651                                         // Inspect recursively
1652                                         add( elem );
1653                                 } else if ( type === "function" ) {
1654                                         // Add if not in unique mode and callback is not in
1655                                         if ( !flags.unique || !self.has( elem ) ) {
1656                                                 list.push( elem );
1657                                         }
1658                                 }
1659                         }
1660                 },
1661                 // Fire callbacks
1662                 fire = function( context, args ) {
1663                         args = args || [];
1664                         memory = !flags.memory || [ context, args ];
1665                         firing = true;
1666                         firingIndex = firingStart || 0;
1667                         firingStart = 0;
1668                         firingLength = list.length;
1669                         for ( ; list && firingIndex < firingLength; firingIndex++ ) {
1670                                 if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
1671                                         memory = true; // Mark as halted
1672                                         break;
1673                                 }
1674                         }
1675                         firing = false;
1676                         if ( list ) {
1677                                 if ( !flags.once ) {
1678                                         if ( stack && stack.length ) {
1679                                                 memory = stack.shift();
1680                                                 self.fireWith( memory[ 0 ], memory[ 1 ] );
1681                                         }
1682                                 } else if ( memory === true ) {
1683                                         self.disable();
1684                                 } else {
1685                                         list = [];
1686                                 }
1687                         }
1688                 },
1689                 // Actual Callbacks object
1690                 self = {
1691                         // Add a callback or a collection of callbacks to the list
1692                         add: function() {
1693                                 if ( list ) {
1694                                         var length = list.length;
1695                                         add( arguments );
1696                                         // Do we need to add the callbacks to the
1697                                         // current firing batch?
1698                                         if ( firing ) {
1699                                                 firingLength = list.length;
1700                                         // With memory, if we're not firing then
1701                                         // we should call right away, unless previous
1702                                         // firing was halted (stopOnFalse)
1703                                         } else if ( memory && memory !== true ) {
1704                                                 firingStart = length;
1705                                                 fire( memory[ 0 ], memory[ 1 ] );
1706                                         }
1707                                 }
1708                                 return this;
1709                         },
1710                         // Remove a callback from the list
1711                         remove: function() {
1712                                 if ( list ) {
1713                                         var args = arguments,
1714                                                 argIndex = 0,
1715                                                 argLength = args.length;
1716                                         for ( ; argIndex < argLength ; argIndex++ ) {
1717                                                 for ( var i = 0; i < list.length; i++ ) {
1718                                                         if ( args[ argIndex ] === list[ i ] ) {
1719                                                                 // Handle firingIndex and firingLength
1720                                                                 if ( firing ) {
1721                                                                         if ( i <= firingLength ) {
1722                                                                                 firingLength--;
1723                                                                                 if ( i <= firingIndex ) {
1724                                                                                         firingIndex--;
1725                                                                                 }
1726                                                                         }
1727                                                                 }
1728                                                                 // Remove the element
1729                                                                 list.splice( i--, 1 );
1730                                                                 // If we have some unicity property then
1731                                                                 // we only need to do this once
1732                                                                 if ( flags.unique ) {
1733                                                                         break;
1734                                                                 }
1735                                                         }
1736                                                 }
1737                                         }
1738                                 }
1739                                 return this;
1740                         },
1741                         // Control if a given callback is in the list
1742                         has: function( fn ) {
1743                                 if ( list ) {
1744                                         var i = 0,
1745                                                 length = list.length;
1746                                         for ( ; i < length; i++ ) {
1747                                                 if ( fn === list[ i ] ) {
1748                                                         return true;
1749                                                 }
1750                                         }
1751                                 }
1752                                 return false;
1753                         },
1754                         // Remove all callbacks from the list
1755                         empty: function() {
1756                                 list = [];
1757                                 return this;
1758                         },
1759                         // Have the list do nothing anymore
1760                         disable: function() {
1761                                 list = stack = memory = undefined;
1762                                 return this;
1763                         },
1764                         // Is it disabled?
1765                         disabled: function() {
1766                                 return !list;
1767                         },
1768                         // Lock the list in its current state
1769                         lock: function() {
1770                                 stack = undefined;
1771                                 if ( !memory || memory === true ) {
1772                                         self.disable();
1773                                 }
1774                                 return this;
1775                         },
1776                         // Is it locked?
1777                         locked: function() {
1778                                 return !stack;
1779                         },
1780                         // Call all callbacks with the given context and arguments
1781                         fireWith: function( context, args ) {
1782                                 if ( stack ) {
1783                                         if ( firing ) {
1784                                                 if ( !flags.once ) {
1785                                                         stack.push( [ context, args ] );
1786                                                 }
1787                                         } else if ( !( flags.once && memory ) ) {
1788                                                 fire( context, args );
1789                                         }
1790                                 }
1791                                 return this;
1792                         },
1793                         // Call all the callbacks with the given arguments
1794                         fire: function() {
1795                                 self.fireWith( this, arguments );
1796                                 return this;
1797                         },
1798                         // To know if the callbacks have already been called at least once
1799                         fired: function() {
1800                                 return !!memory;
1801                         }
1802                 };
1803
1804         return self;
1805 };
1806
1807
1808
1809
1810 var // Static reference to slice
1811         sliceDeferred = [].slice;
1812
1813 jQuery.extend({
1814
1815         Deferred: function( func ) {
1816                 var doneList = jQuery.Callbacks( "once memory" ),
1817                         failList = jQuery.Callbacks( "once memory" ),
1818                         progressList = jQuery.Callbacks( "memory" ),
1819                         state = "pending",
1820                         lists = {
1821                                 resolve: doneList,
1822                                 reject: failList,
1823                                 notify: progressList
1824                         },
1825                         promise = {
1826                                 done: doneList.add,
1827                                 fail: failList.add,
1828                                 progress: progressList.add,
1829
1830                                 state: function() {
1831                                         return state;
1832                                 },
1833
1834                                 // Deprecated
1835                                 isResolved: doneList.fired,
1836                                 isRejected: failList.fired,
1837
1838                                 then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
1839                                         deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
1840                                         return this;
1841                                 },
1842                                 always: function() {
1843                                         return deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
1844                                 },
1845                                 pipe: function( fnDone, fnFail, fnProgress ) {
1846                                         return jQuery.Deferred(function( newDefer ) {
1847                                                 jQuery.each( {
1848                                                         done: [ fnDone, "resolve" ],
1849                                                         fail: [ fnFail, "reject" ],
1850                                                         progress: [ fnProgress, "notify" ]
1851                                                 }, function( handler, data ) {
1852                                                         var fn = data[ 0 ],
1853                                                                 action = data[ 1 ],
1854                                                                 returned;
1855                                                         if ( jQuery.isFunction( fn ) ) {
1856                                                                 deferred[ handler ](function() {
1857                                                                         returned = fn.apply( this, arguments );
1858                                                                         if ( returned && jQuery.isFunction( returned.promise ) ) {
1859                                                                                 returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
1860                                                                         } else {
1861                                                                                 newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
1862                                                                         }
1863                                                                 });
1864                                                         } else {
1865                                                                 deferred[ handler ]( newDefer[ action ] );
1866                                                         }
1867                                                 });
1868                                         }).promise();
1869                                 },
1870                                 // Get a promise for this deferred
1871                                 // If obj is provided, the promise aspect is added to the object
1872                                 promise: function( obj ) {
1873                                         if ( obj == null ) {
1874                                                 obj = promise;
1875                                         } else {
1876                                                 for ( var key in promise ) {
1877                                                         obj[ key ] = promise[ key ];
1878                                                 }
1879                                         }
1880                                         return obj;
1881                                 }
1882                         },
1883                         deferred = promise.promise({}),
1884                         key;
1885
1886                 for ( key in lists ) {
1887                         deferred[ key ] = lists[ key ].fire;
1888                         deferred[ key + "With" ] = lists[ key ].fireWith;
1889                 }
1890
1891                 // Handle state
1892                 deferred.done( function() {
1893                         state = "resolved";
1894                 }, failList.disable, progressList.lock ).fail( function() {
1895                         state = "rejected";
1896                 }, doneList.disable, progressList.lock );
1897
1898                 // Call given func if any
1899                 if ( func ) {
1900                         func.call( deferred, deferred );
1901                 }
1902
1903                 // All done!
1904                 return deferred;
1905         },
1906
1907         // Deferred helper
1908         when: function( firstParam ) {
1909                 var args = sliceDeferred.call( arguments, 0 ),
1910                         i = 0,
1911                         length = args.length,
1912                         pValues = new Array( length ),
1913                         count = length,
1914                         pCount = length,
1915                         deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
1916                                 firstParam :
1917                                 jQuery.Deferred(),
1918                         promise = deferred.promise();
1919                 function resolveFunc( i ) {
1920                         return function( value ) {
1921                                 args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
1922                                 if ( !( --count ) ) {
1923                                         deferred.resolveWith( deferred, args );
1924                                 }
1925                         };
1926                 }
1927                 function progressFunc( i ) {
1928                         return function( value ) {
1929                                 pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
1930                                 deferred.notifyWith( promise, pValues );
1931                         };
1932                 }
1933                 if ( length > 1 ) {
1934                         for ( ; i < length; i++ ) {
1935                                 if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
1936                                         args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
1937                                 } else {
1938                                         --count;
1939                                 }
1940                         }
1941                         if ( !count ) {
1942                                 deferred.resolveWith( deferred, args );
1943                         }
1944                 } else if ( deferred !== firstParam ) {
1945                         deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
1946                 }
1947                 return promise;
1948         }
1949 });
1950
1951
1952
1953
1954 jQuery.support = (function() {
1955
1956         var div = document.createElement( "div" ),
1957                 documentElement = document.documentElement,
1958                 all,
1959                 a,
1960                 select,
1961                 opt,
1962                 input,
1963                 marginDiv,
1964                 support,
1965                 fragment,
1966                 body,
1967                 testElementParent,
1968                 testElement,
1969                 testElementStyle,
1970                 tds,
1971                 events,
1972                 eventName,
1973                 i,
1974                 isSupported;
1975
1976         // Preliminary tests
1977         div.setAttribute("className", "t");
1978         div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/><nav></nav>";
1979
1980
1981         all = div.getElementsByTagName( "*" );
1982         a = div.getElementsByTagName( "a" )[ 0 ];
1983
1984         // Can't get basic test support
1985         if ( !all || !all.length || !a ) {
1986                 return {};
1987         }
1988
1989         // First batch of supports tests
1990         select = document.createElement( "select" );
1991         opt = select.appendChild( document.createElement("option") );
1992         input = div.getElementsByTagName( "input" )[ 0 ];
1993
1994         support = {
1995                 // IE strips leading whitespace when .innerHTML is used
1996                 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1997
1998                 // Make sure that tbody elements aren't automatically inserted
1999                 // IE will insert them into empty tables
2000                 tbody: !div.getElementsByTagName( "tbody" ).length,
2001
2002                 // Make sure that link elements get serialized correctly by innerHTML
2003                 // This requires a wrapper element in IE
2004                 htmlSerialize: !!div.getElementsByTagName( "link" ).length,
2005
2006                 // Get the style information from getAttribute
2007                 // (IE uses .cssText instead)
2008                 style: /top/.test( a.getAttribute("style") ),
2009
2010                 // Make sure that URLs aren't manipulated
2011                 // (IE normalizes it by default)
2012                 hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
2013
2014                 // Make sure that element opacity exists
2015                 // (IE uses filter instead)
2016                 // Use a regex to work around a WebKit issue. See #5145
2017                 opacity: /^0.55/.test( a.style.opacity ),
2018
2019                 // Verify style float existence
2020                 // (IE uses styleFloat instead of cssFloat)
2021                 cssFloat: !!a.style.cssFloat,
2022
2023                 // Make sure unknown elements (like HTML5 elems) are handled appropriately
2024                 unknownElems: !!div.getElementsByTagName( "nav" ).length,
2025
2026                 // Make sure that if no value is specified for a checkbox
2027                 // that it defaults to "on".
2028                 // (WebKit defaults to "" instead)
2029                 checkOn: ( input.value === "on" ),
2030
2031                 // Make sure that a selected-by-default option has a working selected property.
2032                 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
2033                 optSelected: opt.selected,
2034
2035                 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
2036                 getSetAttribute: div.className !== "t",
2037
2038                 // Tests for enctype support on a form(#6743)
2039                 enctype: !!document.createElement("form").enctype,
2040
2041                 // Will be defined later
2042                 submitBubbles: true,
2043                 changeBubbles: true,
2044                 focusinBubbles: false,
2045                 deleteExpando: true,
2046                 noCloneEvent: true,
2047                 inlineBlockNeedsLayout: false,
2048                 shrinkWrapBlocks: false,
2049                 reliableMarginRight: true
2050         };
2051
2052         // Make sure checked status is properly cloned
2053         input.checked = true;
2054         support.noCloneChecked = input.cloneNode( true ).checked;
2055
2056         // Make sure that the options inside disabled selects aren't marked as disabled
2057         // (WebKit marks them as disabled)
2058         select.disabled = true;
2059         support.optDisabled = !opt.disabled;
2060
2061         // Test to see if it's possible to delete an expando from an element
2062         // Fails in Internet Explorer
2063         try {
2064                 delete div.test;
2065         } catch( e ) {
2066                 support.deleteExpando = false;
2067         }
2068
2069         if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
2070                 div.attachEvent( "onclick", function() {
2071                         // Cloning a node shouldn't copy over any
2072                         // bound event handlers (IE does this)
2073                         support.noCloneEvent = false;
2074                 });
2075                 div.cloneNode( true ).fireEvent( "onclick" );
2076         }
2077
2078         // Check if a radio maintains its value
2079         // after being appended to the DOM
2080         input = document.createElement("input");
2081         input.value = "t";
2082         input.setAttribute("type", "radio");
2083         support.radioValue = input.value === "t";
2084
2085         input.setAttribute("checked", "checked");
2086         div.appendChild( input );
2087         fragment = document.createDocumentFragment();
2088         fragment.appendChild( div.lastChild );
2089
2090         // WebKit doesn't clone checked state correctly in fragments
2091         support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
2092
2093         div.innerHTML = "";
2094
2095         // Figure out if the W3C box model works as expected
2096         div.style.width = div.style.paddingLeft = "1px";
2097
2098         // We don't want to do body-related feature tests on frameset
2099         // documents, which lack a body. So we use
2100         // document.getElementsByTagName("body")[0], which is undefined in
2101         // frameset documents, while document.body isn&#8217;t. (7398)
2102         body = document.getElementsByTagName("body")[ 0 ];
2103         // We use our own, invisible, body unless the body is already present
2104         // in which case we use a div (#9239)
2105         testElement = document.createElement( body ? "div" : "body" );
2106         testElementStyle = {
2107                 visibility: "hidden",
2108                 width: 0,
2109                 height: 0,
2110                 border: 0,
2111                 margin: 0,
2112                 background: "none"
2113         };
2114         if ( body ) {
2115                 jQuery.extend( testElementStyle, {
2116                         position: "absolute",
2117                         left: "-999px",
2118                         top: "-999px"
2119                 });
2120         }
2121         for ( i in testElementStyle ) {
2122                 testElement.style[ i ] = testElementStyle[ i ];
2123         }
2124         testElement.appendChild( div );
2125         testElementParent = body || documentElement;
2126         testElementParent.insertBefore( testElement, testElementParent.firstChild );
2127
2128         // Check if a disconnected checkbox will retain its checked
2129         // value of true after appended to the DOM (IE6/7)
2130         support.appendChecked = input.checked;
2131
2132         support.boxModel = div.offsetWidth === 2;
2133
2134         if ( "zoom" in div.style ) {
2135                 // Check if natively block-level elements act like inline-block
2136                 // elements when setting their display to 'inline' and giving
2137                 // them layout
2138                 // (IE < 8 does this)
2139                 div.style.display = "inline";
2140                 div.style.zoom = 1;
2141                 support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
2142
2143                 // Check if elements with layout shrink-wrap their children
2144                 // (IE 6 does this)
2145                 div.style.display = "";
2146                 div.innerHTML = "<div style='width:4px;'></div>";
2147                 support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
2148         }
2149
2150         div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
2151         tds = div.getElementsByTagName( "td" );
2152
2153         // Check if table cells still have offsetWidth/Height when they are set
2154         // to display:none and there are still other visible table cells in a
2155         // table row; if so, offsetWidth/Height are not reliable for use when
2156         // determining if an element has been hidden directly using
2157         // display:none (it is still safe to use offsets if a parent element is
2158         // hidden; don safety goggles and see bug #4512 for more information).
2159         // (only IE 8 fails this test)
2160         isSupported = ( tds[ 0 ].offsetHeight === 0 );
2161
2162         tds[ 0 ].style.display = "";
2163         tds[ 1 ].style.display = "none";
2164
2165         // Check if empty table cells still have offsetWidth/Height
2166         // (IE < 8 fail this test)
2167         support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
2168         div.innerHTML = "";
2169
2170         // Check if div with explicit width and no margin-right incorrectly
2171         // gets computed margin-right based on width of container. For more
2172         // info see bug #3333
2173         // Fails in WebKit before Feb 2011 nightlies
2174         // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
2175         if ( document.defaultView && document.defaultView.getComputedStyle ) {
2176                 marginDiv = document.createElement( "div" );
2177                 marginDiv.style.width = "0";
2178                 marginDiv.style.marginRight = "0";
2179                 div.appendChild( marginDiv );
2180                 support.reliableMarginRight =
2181                         ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
2182         }
2183
2184         // Technique from Juriy Zaytsev
2185         // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
2186         // We only care about the case where non-standard event systems
2187         // are used, namely in IE. Short-circuiting here helps us to
2188         // avoid an eval call (in setAttribute) which can cause CSP
2189         // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
2190         if ( div.attachEvent ) {
2191                 for( i in {
2192                         submit: 1,
2193                         change: 1,
2194                         focusin: 1
2195                 } ) {
2196                         eventName = "on" + i;
2197                         isSupported = ( eventName in div );
2198                         if ( !isSupported ) {
2199                                 div.setAttribute( eventName, "return;" );
2200                                 isSupported = ( typeof div[ eventName ] === "function" );
2201                         }
2202                         support[ i + "Bubbles" ] = isSupported;
2203                 }
2204         }
2205
2206         // Run fixed position tests at doc ready to avoid a crash
2207         // related to the invisible body in IE8
2208         jQuery(function() {
2209                 var container, outer, inner, table, td, offsetSupport,
2210                         conMarginTop = 1,
2211                         ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",
2212                         vb = "visibility:hidden;border:0;",
2213                         style = "style='" + ptlm + "border:5px solid #000;padding:0;'",
2214                         html = "<div " + style + "><div></div></div>" +
2215                                                         "<table " + style + " cellpadding='0' cellspacing='0'>" +
2216                                                         "<tr><td></td></tr></table>";
2217
2218                 // Reconstruct a container
2219                 body = document.getElementsByTagName("body")[0];
2220                 if ( !body ) {
2221                         // Return for frameset docs that don't have a body
2222                         // These tests cannot be done
2223                         return;
2224                 }
2225
2226                 container = document.createElement("div");
2227                 container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
2228                 body.insertBefore( container, body.firstChild );
2229
2230                 // Construct a test element
2231                 testElement = document.createElement("div");
2232                 testElement.style.cssText = ptlm + vb;
2233
2234                 testElement.innerHTML = html;
2235                 container.appendChild( testElement );
2236                 outer = testElement.firstChild;
2237                 inner = outer.firstChild;
2238                 td = outer.nextSibling.firstChild.firstChild;
2239
2240                 offsetSupport = {
2241                         doesNotAddBorder: ( inner.offsetTop !== 5 ),
2242                         doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
2243                 };
2244
2245                 inner.style.position = "fixed";
2246                 inner.style.top = "20px";
2247
2248                 // safari subtracts parent border width here which is 5px
2249                 offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
2250                 inner.style.position = inner.style.top = "";
2251
2252                 outer.style.overflow = "hidden";
2253                 outer.style.position = "relative";
2254
2255                 offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
2256                 offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
2257
2258                 body.removeChild( container );
2259                 testElement = container = null;
2260
2261                 jQuery.extend( support, offsetSupport );
2262         });
2263
2264         testElement.innerHTML = "";
2265         testElementParent.removeChild( testElement );
2266
2267         // Null connected elements to avoid leaks in IE
2268         testElement = fragment = select = opt = body = marginDiv = div = input = null;
2269
2270         return support;
2271 })();
2272
2273 // Keep track of boxModel
2274 jQuery.boxModel = jQuery.support.boxModel;
2275
2276
2277
2278
2279 var rbrace = /^(?:\{.*\}|\[.*\])$/,
2280         rmultiDash = /([A-Z])/g;
2281
2282 jQuery.extend({
2283         cache: {},
2284
2285         // Please use with caution
2286         uuid: 0,
2287
2288         // Unique for each copy of jQuery on the page
2289         // Non-digits removed to match rinlinejQuery
2290         expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
2291
2292         // The following elements throw uncatchable exceptions if you
2293         // attempt to add expando properties to them.
2294         noData: {
2295                 "embed": true,
2296                 // Ban all objects except for Flash (which handle expandos)
2297                 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
2298                 "applet": true
2299         },
2300
2301         hasData: function( elem ) {
2302                 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
2303                 return !!elem && !isEmptyDataObject( elem );
2304         },
2305
2306         data: function( elem, name, data, pvt /* Internal Use Only */ ) {
2307                 if ( !jQuery.acceptData( elem ) ) {
2308                         return;
2309                 }
2310
2311                 var privateCache, thisCache, ret,
2312                         internalKey = jQuery.expando,
2313                         getByName = typeof name === "string",
2314
2315                         // We have to handle DOM nodes and JS objects differently because IE6-7
2316                         // can't GC object references properly across the DOM-JS boundary
2317                         isNode = elem.nodeType,
2318
2319                         // Only DOM nodes need the global jQuery cache; JS object data is
2320                         // attached directly to the object so GC can occur automatically
2321                         cache = isNode ? jQuery.cache : elem,
2322
2323                         // Only defining an ID for JS objects if its cache already exists allows
2324                         // the code to shortcut on the same path as a DOM node with no cache
2325                         id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando,
2326                         isEvents = name === "events";
2327
2328                 // Avoid doing any more work than we need to when trying to get data on an
2329                 // object that has no data at all
2330                 if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
2331                         return;
2332                 }
2333
2334                 if ( !id ) {
2335                         // Only DOM nodes need a new unique ID for each element since their data
2336                         // ends up in the global cache
2337                         if ( isNode ) {
2338                                 elem[ jQuery.expando ] = id = ++jQuery.uuid;
2339                         } else {
2340                                 id = jQuery.expando;
2341                         }
2342                 }
2343
2344                 if ( !cache[ id ] ) {
2345                         cache[ id ] = {};
2346
2347                         // Avoids exposing jQuery metadata on plain JS objects when the object
2348                         // is serialized using JSON.stringify
2349                         if ( !isNode ) {
2350                                 cache[ id ].toJSON = jQuery.noop;
2351                         }
2352                 }
2353
2354                 // An object can be passed to jQuery.data instead of a key/value pair; this gets
2355                 // shallow copied over onto the existing cache
2356                 if ( typeof name === "object" || typeof name === "function" ) {
2357                         if ( pvt ) {
2358                                 cache[ id ] = jQuery.extend( cache[ id ], name );
2359                         } else {
2360                                 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
2361                         }
2362                 }
2363
2364                 privateCache = thisCache = cache[ id ];
2365
2366                 // jQuery data() is stored in a separate object inside the object's internal data
2367                 // cache in order to avoid key collisions between internal data and user-defined
2368                 // data.
2369                 if ( !pvt ) {
2370                         if ( !thisCache.data ) {
2371                                 thisCache.data = {};
2372                         }
2373
2374                         thisCache = thisCache.data;
2375                 }
2376
2377                 if ( data !== undefined ) {
2378                         thisCache[ jQuery.camelCase( name ) ] = data;
2379                 }
2380
2381                 // Users should not attempt to inspect the internal events object using jQuery.data,
2382                 // it is undocumented and subject to change. But does anyone listen? No.
2383                 if ( isEvents && !thisCache[ name ] ) {
2384                         return privateCache.events;
2385                 }
2386
2387                 // Check for both converted-to-camel and non-converted data property names
2388                 // If a data property was specified
2389                 if ( getByName ) {
2390
2391                         // First Try to find as-is property data
2392                         ret = thisCache[ name ];
2393
2394                         // Test for null|undefined property data
2395                         if ( ret == null ) {
2396
2397                                 // Try to find the camelCased property
2398                                 ret = thisCache[ jQuery.camelCase( name ) ];
2399                         }
2400                 } else {
2401                         ret = thisCache;
2402                 }
2403
2404                 return ret;
2405         },
2406
2407         removeData: function( elem, name, pvt /* Internal Use Only */ ) {
2408                 if ( !jQuery.acceptData( elem ) ) {
2409                         return;
2410                 }
2411
2412                 var thisCache, i, l,
2413
2414                         // Reference to internal data cache key
2415                         internalKey = jQuery.expando,
2416
2417                         isNode = elem.nodeType,
2418
2419                         // See jQuery.data for more information
2420                         cache = isNode ? jQuery.cache : elem,
2421
2422                         // See jQuery.data for more information
2423                         id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
2424
2425                 // If there is already no cache entry for this object, there is no
2426                 // purpose in continuing
2427                 if ( !cache[ id ] ) {
2428                         return;
2429                 }
2430
2431                 if ( name ) {
2432
2433                         thisCache = pvt ? cache[ id ] : cache[ id ].data;
2434
2435                         if ( thisCache ) {
2436
2437                                 // Support space separated names
2438                                 if ( jQuery.isArray( name ) ) {
2439                                         name = name;
2440                                 } else if ( name in thisCache ) {
2441                                         name = [ name ];
2442                                 } else {
2443
2444                                         // split the camel cased version by spaces
2445                                         name = jQuery.camelCase( name );
2446                                         if ( name in thisCache ) {
2447                                                 name = [ name ];
2448                                         } else {
2449                                                 name = name.split( " " );
2450                                         }
2451                                 }
2452
2453                                 for ( i = 0, l = name.length; i < l; i++ ) {
2454                                         delete thisCache[ name[i] ];
2455                                 }
2456
2457                                 // If there is no data left in the cache, we want to continue
2458                                 // and let the cache object itself get destroyed
2459                                 if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
2460                                         return;
2461                                 }
2462                         }
2463                 }
2464
2465                 // See jQuery.data for more information
2466                 if ( !pvt ) {
2467                         delete cache[ id ].data;
2468
2469                         // Don't destroy the parent cache unless the internal data object
2470                         // had been the only thing left in it
2471                         if ( !isEmptyDataObject(cache[ id ]) ) {
2472                                 return;
2473                         }
2474                 }
2475
2476                 // Browsers that fail expando deletion also refuse to delete expandos on
2477                 // the window, but it will allow it on all other JS objects; other browsers
2478                 // don't care
2479                 // Ensure that `cache` is not a window object #10080
2480                 if ( jQuery.support.deleteExpando || !cache.setInterval ) {
2481                         delete cache[ id ];
2482                 } else {
2483                         cache[ id ] = null;
2484                 }
2485
2486                 // We destroyed the cache and need to eliminate the expando on the node to avoid
2487                 // false lookups in the cache for entries that no longer exist
2488                 if ( isNode ) {
2489                         // IE does not allow us to delete expando properties from nodes,
2490                         // nor does it have a removeAttribute function on Document nodes;
2491                         // we must handle all of these cases
2492                         if ( jQuery.support.deleteExpando ) {
2493                                 delete elem[ jQuery.expando ];
2494                         } else if ( elem.removeAttribute ) {
2495                                 elem.removeAttribute( jQuery.expando );
2496                         } else {
2497                                 elem[ jQuery.expando ] = null;
2498                         }
2499                 }
2500         },
2501
2502         // For internal use only.
2503         _data: function( elem, name, data ) {
2504                 return jQuery.data( elem, name, data, true );
2505         },
2506
2507         // A method for determining if a DOM node can handle the data expando
2508         acceptData: function( elem ) {
2509                 if ( elem.nodeName ) {
2510                         var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
2511
2512                         if ( match ) {
2513                                 return !(match === true || elem.getAttribute("classid") !== match);
2514                         }
2515                 }
2516
2517                 return true;
2518         }
2519 });
2520
2521 jQuery.fn.extend({
2522         data: function( key, value ) {
2523                 var parts, attr, name,
2524                         data = null;
2525
2526                 if ( typeof key === "undefined" ) {
2527                         if ( this.length ) {
2528                                 data = jQuery.data( this[0] );
2529
2530                                 if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
2531                                         attr = this[0].attributes;
2532                                         for ( var i = 0, l = attr.length; i < l; i++ ) {
2533                                                 name = attr[i].name;
2534
2535                                                 if ( name.indexOf( "data-" ) === 0 ) {
2536                                                         name = jQuery.camelCase( name.substring(5) );
2537
2538                                                         dataAttr( this[0], name, data[ name ] );
2539                                                 }
2540                                         }
2541                                         jQuery._data( this[0], "parsedAttrs", true );
2542                                 }
2543                         }
2544
2545                         return data;
2546
2547                 } else if ( typeof key === "object" ) {
2548                         return this.each(function() {
2549                                 jQuery.data( this, key );
2550                         });
2551                 }
2552
2553                 parts = key.split(".");
2554                 parts[1] = parts[1] ? "." + parts[1] : "";
2555
2556                 if ( value === undefined ) {
2557                         data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
2558
2559                         // Try to fetch any internally stored data first
2560                         if ( data === undefined && this.length ) {
2561                                 data = jQuery.data( this[0], key );
2562                                 data = dataAttr( this[0], key, data );
2563                         }
2564
2565                         return data === undefined && parts[1] ?
2566                                 this.data( parts[0] ) :
2567                                 data;
2568
2569                 } else {
2570                         return this.each(function() {
2571                                 var $this = jQuery( this ),
2572                                         args = [ parts[0], value ];
2573
2574                                 $this.triggerHandler( "setData" + parts[1] + "!", args );
2575                                 jQuery.data( this, key, value );
2576                                 $this.triggerHandler( "changeData" + parts[1] + "!", args );
2577                         });
2578                 }
2579         },
2580
2581         removeData: function( key ) {
2582                 return this.each(function() {
2583                         jQuery.removeData( this, key );
2584                 });
2585         }
2586 });
2587
2588 function dataAttr( elem, key, data ) {
2589         // If nothing was found internally, try to fetch any
2590         // data from the HTML5 data-* attribute
2591         if ( data === undefined && elem.nodeType === 1 ) {
2592
2593                 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
2594
2595                 data = elem.getAttribute( name );
2596
2597                 if ( typeof data === "string" ) {
2598                         try {
2599                                 data = data === "true" ? true :
2600                                 data === "false" ? false :
2601                                 data === "null" ? null :
2602                                 jQuery.isNumeric( data ) ? parseFloat( data ) :
2603                                         rbrace.test( data ) ? jQuery.parseJSON( data ) :
2604                                         data;
2605                         } catch( e ) {}
2606
2607                         // Make sure we set the data so it isn't changed later
2608                         jQuery.data( elem, key, data );
2609
2610                 } else {
2611                         data = undefined;
2612                 }
2613         }
2614
2615         return data;
2616 }
2617
2618 // checks a cache object for emptiness
2619 function isEmptyDataObject( obj ) {
2620         for ( var name in obj ) {
2621
2622                 // if the public data object is empty, the private is still empty
2623                 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
2624                         continue;
2625                 }
2626                 if ( name !== "toJSON" ) {
2627                         return false;
2628                 }
2629         }
2630
2631         return true;
2632 }
2633
2634
2635
2636
2637 function handleQueueMarkDefer( elem, type, src ) {
2638         var deferDataKey = type + "defer",
2639                 queueDataKey = type + "queue",
2640                 markDataKey = type + "mark",
2641                 defer = jQuery._data( elem, deferDataKey );
2642         if ( defer &&
2643                 ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
2644                 ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
2645                 // Give room for hard-coded callbacks to fire first
2646                 // and eventually mark/queue something else on the element
2647                 setTimeout( function() {
2648                         if ( !jQuery._data( elem, queueDataKey ) &&
2649                                 !jQuery._data( elem, markDataKey ) ) {
2650                                 jQuery.removeData( elem, deferDataKey, true );
2651                                 defer.fire();
2652                         }
2653                 }, 0 );
2654         }
2655 }
2656
2657 jQuery.extend({
2658
2659         _mark: function( elem, type ) {
2660                 if ( elem ) {
2661                         type = ( type || "fx" ) + "mark";
2662                         jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
2663                 }
2664         },
2665
2666         _unmark: function( force, elem, type ) {
2667                 if ( force !== true ) {
2668                         type = elem;
2669                         elem = force;
2670                         force = false;
2671                 }
2672                 if ( elem ) {
2673                         type = type || "fx";
2674                         var key = type + "mark",
2675                                 count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
2676                         if ( count ) {
2677                                 jQuery._data( elem, key, count );
2678                         } else {
2679                                 jQuery.removeData( elem, key, true );
2680                                 handleQueueMarkDefer( elem, type, "mark" );
2681                         }
2682                 }
2683         },
2684
2685         queue: function( elem, type, data ) {
2686                 var q;
2687                 if ( elem ) {
2688                         type = ( type || "fx" ) + "queue";
2689                         q = jQuery._data( elem, type );
2690
2691                         // Speed up dequeue by getting out quickly if this is just a lookup
2692                         if ( data ) {
2693                                 if ( !q || jQuery.isArray(data) ) {
2694                                         q = jQuery._data( elem, type, jQuery.makeArray(data) );
2695                                 } else {
2696                                         q.push( data );
2697                                 }
2698                         }
2699                         return q || [];
2700                 }
2701         },
2702
2703         dequeue: function( elem, type ) {
2704                 type = type || "fx";
2705
2706                 var queue = jQuery.queue( elem, type ),
2707                         fn = queue.shift(),
2708                         hooks = {};
2709
2710                 // If the fx queue is dequeued, always remove the progress sentinel
2711                 if ( fn === "inprogress" ) {
2712                         fn = queue.shift();
2713                 }
2714
2715                 if ( fn ) {
2716                         // Add a progress sentinel to prevent the fx queue from being
2717                         // automatically dequeued
2718                         if ( type === "fx" ) {
2719                                 queue.unshift( "inprogress" );
2720                         }
2721
2722                         jQuery._data( elem, type + ".run", hooks );
2723                         fn.call( elem, function() {
2724                                 jQuery.dequeue( elem, type );
2725                         }, hooks );
2726                 }
2727
2728                 if ( !queue.length ) {
2729                         jQuery.removeData( elem, type + "queue " + type + ".run", true );
2730                         handleQueueMarkDefer( elem, type, "queue" );
2731                 }
2732         }
2733 });
2734
2735 jQuery.fn.extend({
2736         queue: function( type, data ) {
2737                 if ( typeof type !== "string" ) {
2738                         data = type;
2739                         type = "fx";
2740                 }
2741
2742                 if ( data === undefined ) {
2743                         return jQuery.queue( this[0], type );
2744                 }
2745                 return this.each(function() {
2746                         var queue = jQuery.queue( this, type, data );
2747
2748                         if ( type === "fx" && queue[0] !== "inprogress" ) {
2749                                 jQuery.dequeue( this, type );
2750                         }
2751                 });
2752         },
2753         dequeue: function( type ) {
2754                 return this.each(function() {
2755                         jQuery.dequeue( this, type );
2756                 });
2757         },
2758         // Based off of the plugin by Clint Helfers, with permission.
2759         // http://blindsignals.com/index.php/2009/07/jquery-delay/
2760         delay: function( time, type ) {
2761                 time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
2762                 type = type || "fx";
2763
2764                 return this.queue( type, function( next, hooks ) {
2765                         var timeout = setTimeout( next, time );
2766                         hooks.stop = function() {
2767                                 clearTimeout( timeout );
2768                         };
2769                 });
2770         },
2771         clearQueue: function( type ) {
2772                 return this.queue( type || "fx", [] );
2773         },
2774         // Get a promise resolved when queues of a certain type
2775         // are emptied (fx is the type by default)
2776         promise: function( type, object ) {
2777                 if ( typeof type !== "string" ) {
2778                         object = type;
2779                         type = undefined;
2780                 }
2781                 type = type || "fx";
2782                 var defer = jQuery.Deferred(),
2783                         elements = this,
2784                         i = elements.length,
2785                         count = 1,
2786                         deferDataKey = type + "defer",
2787                         queueDataKey = type + "queue",
2788                         markDataKey = type + "mark",
2789                         tmp;
2790                 function resolve() {
2791                         if ( !( --count ) ) {
2792                                 defer.resolveWith( elements, [ elements ] );
2793                         }
2794                 }
2795                 while( i-- ) {
2796                         if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
2797                                         ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
2798                                                 jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
2799                                         jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
2800                                 count++;
2801                                 tmp.add( resolve );
2802                         }
2803                 }
2804                 resolve();
2805                 return defer.promise();
2806         }
2807 });
2808
2809
2810
2811
2812 var rclass = /[\n\t\r]/g,
2813         rspace = /\s+/,
2814         rreturn = /\r/g,
2815         rtype = /^(?:button|input)$/i,
2816         rfocusable = /^(?:button|input|object|select|textarea)$/i,
2817         rclickable = /^a(?:rea)?$/i,
2818         rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
2819         getSetAttribute = jQuery.support.getSetAttribute,
2820         nodeHook, boolHook, fixSpecified;
2821
2822 jQuery.fn.extend({
2823         attr: function( name, value ) {
2824                 return jQuery.access( this, name, value, true, jQuery.attr );
2825         },
2826
2827         removeAttr: function( name ) {
2828                 return this.each(function() {
2829                         jQuery.removeAttr( this, name );
2830                 });
2831         },
2832
2833         prop: function( name, value ) {
2834                 return jQuery.access( this, name, value, true, jQuery.prop );
2835         },
2836
2837         removeProp: function( name ) {
2838                 name = jQuery.propFix[ name ] || name;
2839                 return this.each(function() {
2840                         // try/catch handles cases where IE balks (such as removing a property on window)
2841                         try {
2842                                 this[ name ] = undefined;
2843                                 delete this[ name ];
2844                         } catch( e ) {}
2845                 });
2846         },
2847
2848         addClass: function( value ) {
2849                 var classNames, i, l, elem,
2850                         setClass, c, cl;
2851
2852                 if ( jQuery.isFunction( value ) ) {
2853                         return this.each(function( j ) {
2854                                 jQuery( this ).addClass( value.call(this, j, this.className) );
2855                         });
2856                 }
2857
2858                 if ( value && typeof value === "string" ) {
2859                         classNames = value.split( rspace );
2860
2861                         for ( i = 0, l = this.length; i < l; i++ ) {
2862                                 elem = this[ i ];
2863
2864                                 if ( elem.nodeType === 1 ) {
2865                                         if ( !elem.className && classNames.length === 1 ) {
2866                                                 elem.className = value;
2867
2868                                         } else {
2869                                                 setClass = " " + elem.className + " ";
2870
2871                                                 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2872                                                         if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
2873                                                                 setClass += classNames[ c ] + " ";
2874                                                         }
2875                                                 }
2876                                                 elem.className = jQuery.trim( setClass );
2877                                         }
2878                                 }
2879                         }
2880                 }
2881
2882                 return this;
2883         },
2884
2885         removeClass: function( value ) {
2886                 var classNames, i, l, elem, className, c, cl;
2887
2888                 if ( jQuery.isFunction( value ) ) {
2889                         return this.each(function( j ) {
2890                                 jQuery( this ).removeClass( value.call(this, j, this.className) );
2891                         });
2892                 }
2893
2894                 if ( (value && typeof value === "string") || value === undefined ) {
2895                         classNames = ( value || "" ).split( rspace );
2896
2897                         for ( i = 0, l = this.length; i < l; i++ ) {
2898                                 elem = this[ i ];
2899
2900                                 if ( elem.nodeType === 1 && elem.className ) {
2901                                         if ( value ) {
2902                                                 className = (" " + elem.className + " ").replace( rclass, " " );
2903                                                 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2904                                                         className = className.replace(" " + classNames[ c ] + " ", " ");
2905                                                 }
2906                                                 elem.className = jQuery.trim( className );
2907
2908                                         } else {
2909                                                 elem.className = "";
2910                                         }
2911                                 }
2912                         }
2913                 }
2914
2915                 return this;
2916         },
2917
2918         toggleClass: function( value, stateVal ) {
2919                 var type = typeof value,
2920                         isBool = typeof stateVal === "boolean";
2921
2922                 if ( jQuery.isFunction( value ) ) {
2923                         return this.each(function( i ) {
2924                                 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2925                         });
2926                 }
2927
2928                 return this.each(function() {
2929                         if ( type === "string" ) {
2930                                 // toggle individual class names
2931                                 var className,
2932                                         i = 0,
2933                                         self = jQuery( this ),
2934                                         state = stateVal,
2935                                         classNames = value.split( rspace );
2936
2937                                 while ( (className = classNames[ i++ ]) ) {
2938                                         // check each className given, space seperated list
2939                                         state = isBool ? state : !self.hasClass( className );
2940                                         self[ state ? "addClass" : "removeClass" ]( className );
2941                                 }
2942
2943                         } else if ( type === "undefined" || type === "boolean" ) {
2944                                 if ( this.className ) {
2945                                         // store className if set
2946                                         jQuery._data( this, "__className__", this.className );
2947                                 }
2948
2949                                 // toggle whole className
2950                                 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2951                         }
2952                 });
2953         },
2954
2955         hasClass: function( selector ) {
2956                 var className = " " + selector + " ",
2957                         i = 0,
2958                         l = this.length;
2959                 for ( ; i < l; i++ ) {
2960                         if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2961                                 return true;
2962                         }
2963                 }
2964
2965                 return false;
2966         },
2967
2968         val: function( value ) {
2969                 var hooks, ret, isFunction,
2970                         elem = this[0];
2971
2972                 if ( !arguments.length ) {
2973                         if ( elem ) {
2974                                 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
2975
2976                                 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2977                                         return ret;
2978                                 }
2979
2980                                 ret = elem.value;
2981
2982                                 return typeof ret === "string" ?
2983                                         // handle most common string cases
2984                                         ret.replace(rreturn, "") :
2985                                         // handle cases where value is null/undef or number
2986                                         ret == null ? "" : ret;
2987                         }
2988
2989                         return undefined;
2990                 }
2991
2992                 isFunction = jQuery.isFunction( value );
2993
2994                 return this.each(function( i ) {
2995                         var self = jQuery(this), val;
2996
2997                         if ( this.nodeType !== 1 ) {
2998                                 return;
2999                         }
3000
3001                         if ( isFunction ) {
3002                                 val = value.call( this, i, self.val() );
3003                         } else {
3004                                 val = value;
3005                         }
3006
3007                         // Treat null/undefined as ""; convert numbers to string
3008                         if ( val == null ) {
3009                                 val = "";
3010                         } else if ( typeof val === "number" ) {
3011                                 val += "";
3012                         } else if ( jQuery.isArray( val ) ) {
3013                                 val = jQuery.map(val, function ( value ) {
3014                                         return value == null ? "" : value + "";
3015                                 });
3016                         }
3017
3018                         hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
3019
3020                         // If set returns undefined, fall back to normal setting
3021                         if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
3022                                 this.value = val;
3023                         }
3024                 });
3025         }
3026 });
3027
3028 jQuery.extend({
3029         valHooks: {
3030                 option: {
3031                         get: function( elem ) {
3032                                 // attributes.value is undefined in Blackberry 4.7 but
3033                                 // uses .value. See #6932
3034                                 var val = elem.attributes.value;
3035                                 return !val || val.specified ? elem.value : elem.text;
3036                         }
3037                 },
3038                 select: {
3039                         get: function( elem ) {
3040                                 var value, i, max, option,
3041                                         index = elem.selectedIndex,
3042                                         values = [],
3043                                         options = elem.options,
3044                                         one = elem.type === "select-one";
3045
3046                                 // Nothing was selected
3047                                 if ( index < 0 ) {
3048                                         return null;
3049                                 }
3050
3051                                 // Loop through all the selected options
3052                                 i = one ? index : 0;
3053                                 max = one ? index + 1 : options.length;
3054                                 for ( ; i < max; i++ ) {
3055                                         option = options[ i ];
3056
3057                                         // Don't return options that are disabled or in a disabled optgroup
3058                                         if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
3059                                                         (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
3060
3061                                                 // Get the specific value for the option
3062                                                 value = jQuery( option ).val();
3063
3064                                                 // We don't need an array for one selects
3065                                                 if ( one ) {
3066                                                         return value;
3067                                                 }
3068
3069                                                 // Multi-Selects return an array
3070                                                 values.push( value );
3071                                         }
3072                                 }
3073
3074                                 // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
3075                                 if ( one && !values.length && options.length ) {
3076                                         return jQuery( options[ index ] ).val();
3077                                 }
3078
3079                                 return values;
3080                         },
3081
3082                         set: function( elem, value ) {
3083                                 var values = jQuery.makeArray( value );
3084
3085                                 jQuery(elem).find("option").each(function() {
3086                                         this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
3087                                 });
3088
3089                                 if ( !values.length ) {
3090                                         elem.selectedIndex = -1;
3091                                 }
3092                                 return values;
3093                         }
3094                 }
3095         },
3096
3097         attrFn: {
3098                 val: true,
3099                 css: true,
3100                 html: true,
3101                 text: true,
3102                 data: true,
3103                 width: true,
3104                 height: true,
3105                 offset: true
3106         },
3107
3108         attr: function( elem, name, value, pass ) {
3109                 var ret, hooks, notxml,
3110                         nType = elem.nodeType;
3111
3112                 // don't get/set attributes on text, comment and attribute nodes
3113                 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
3114                         return undefined;
3115                 }
3116
3117                 if ( pass && name in jQuery.attrFn ) {
3118                         return jQuery( elem )[ name ]( value );
3119                 }
3120
3121                 // Fallback to prop when attributes are not supported
3122                 if ( !("getAttribute" in elem) ) {
3123                         return jQuery.prop( elem, name, value );
3124                 }
3125
3126                 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
3127
3128                 // All attributes are lowercase
3129                 // Grab necessary hook if one is defined
3130                 if ( notxml ) {
3131                         name = name.toLowerCase();
3132                         hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
3133                 }
3134
3135                 if ( value !== undefined ) {
3136
3137                         if ( value === null ) {
3138                                 jQuery.removeAttr( elem, name );
3139                                 return undefined;
3140
3141                         } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
3142                                 return ret;
3143
3144                         } else {
3145                                 elem.setAttribute( name, "" + value );
3146                                 return value;
3147                         }
3148
3149                 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
3150                         return ret;
3151
3152                 } else {
3153
3154                         ret = elem.getAttribute( name );
3155
3156                         // Non-existent attributes return null, we normalize to undefined
3157                         return ret === null ?
3158                                 undefined :
3159                                 ret;
3160                 }
3161         },
3162
3163         removeAttr: function( elem, value ) {
3164                 var propName, attrNames, name, l,
3165                         i = 0;
3166
3167                 if ( elem.nodeType === 1 ) {
3168                         attrNames = ( value || "" ).split( rspace );
3169                         l = attrNames.length;
3170
3171                         for ( ; i < l; i++ ) {
3172                                 name = attrNames[ i ].toLowerCase();
3173                                 propName = jQuery.propFix[ name ] || name;
3174
3175                                 // See #9699 for explanation of this approach (setting first, then removal)
3176                                 jQuery.attr( elem, name, "" );
3177                                 elem.removeAttribute( getSetAttribute ? name : propName );
3178
3179                                 // Set corresponding property to false for boolean attributes
3180                                 if ( rboolean.test( name ) && propName in elem ) {
3181                                         elem[ propName ] = false;
3182                                 }
3183                         }
3184                 }
3185         },
3186
3187         attrHooks: {
3188                 type: {
3189                         set: function( elem, value ) {
3190                                 // We can't allow the type property to be changed (since it causes problems in IE)
3191                                 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
3192                                         jQuery.error( "type property can't be changed" );
3193                                 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
3194                                         // Setting the type on a radio button after the value resets the value in IE6-9
3195                                         // Reset value to it's default in case type is set after value
3196                                         // This is for element creation
3197                                         var val = elem.value;
3198                                         elem.setAttribute( "type", value );
3199                                         if ( val ) {
3200                                                 elem.value = val;
3201                                         }
3202                                         return value;
3203                                 }
3204                         }
3205                 },
3206                 // Use the value property for back compat
3207                 // Use the nodeHook for button elements in IE6/7 (#1954)
3208                 value: {
3209                         get: function( elem, name ) {
3210                                 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
3211                                         return nodeHook.get( elem, name );
3212                                 }
3213                                 return name in elem ?
3214                                         elem.value :
3215                                         null;
3216                         },
3217                         set: function( elem, value, name ) {
3218                                 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
3219                                         return nodeHook.set( elem, value, name );
3220                                 }
3221                                 // Does not return so that setAttribute is also used
3222                                 elem.value = value;
3223                         }
3224                 }
3225         },
3226
3227         propFix: {
3228                 tabindex: "tabIndex",
3229                 readonly: "readOnly",
3230                 "for": "htmlFor",
3231                 "class": "className",
3232                 maxlength: "maxLength",
3233                 cellspacing: "cellSpacing",
3234                 cellpadding: "cellPadding",
3235                 rowspan: "rowSpan",
3236                 colspan: "colSpan",
3237                 usemap: "useMap",
3238                 frameborder: "frameBorder",
3239                 contenteditable: "contentEditable"
3240         },
3241
3242         prop: function( elem, name, value ) {
3243                 var ret, hooks, notxml,
3244                         nType = elem.nodeType;
3245
3246                 // don't get/set properties on text, comment and attribute nodes
3247                 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
3248                         return undefined;
3249                 }
3250
3251                 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
3252
3253                 if ( notxml ) {
3254                         // Fix name and attach hooks
3255                         name = jQuery.propFix[ name ] || name;
3256                         hooks = jQuery.propHooks[ name ];
3257                 }
3258
3259                 if ( value !== undefined ) {
3260                         if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
3261                                 return ret;
3262
3263                         } else {
3264                                 return ( elem[ name ] = value );
3265                         }
3266
3267                 } else {
3268                         if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
3269                                 return ret;
3270
3271                         } else {
3272                                 return elem[ name ];
3273                         }
3274                 }
3275         },
3276
3277         propHooks: {
3278                 tabIndex: {
3279                         get: function( elem ) {
3280                                 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
3281                                 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
3282                                 var attributeNode = elem.getAttributeNode("tabindex");
3283
3284                                 return attributeNode && attributeNode.specified ?
3285                                         parseInt( attributeNode.value, 10 ) :
3286                                         rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
3287                                                 0 :
3288                                                 undefined;
3289                         }
3290                 }
3291         }
3292 });
3293
3294 // Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
3295 jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
3296
3297 // Hook for boolean attributes
3298 boolHook = {
3299         get: function( elem, name ) {
3300                 // Align boolean attributes with corresponding properties
3301                 // Fall back to attribute presence where some booleans are not supported
3302                 var attrNode,
3303                         property = jQuery.prop( elem, name );
3304                 return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
3305                         name.toLowerCase() :
3306                         undefined;
3307         },
3308         set: function( elem, value, name ) {
3309                 var propName;
3310                 if ( value === false ) {
3311                         // Remove boolean attributes when set to false
3312                         jQuery.removeAttr( elem, name );
3313                 } else {
3314                         // value is true since we know at this point it's type boolean and not false
3315                         // Set boolean attributes to the same name and set the DOM property
3316                         propName = jQuery.propFix[ name ] || name;
3317                         if ( propName in elem ) {
3318                                 // Only set the IDL specifically if it already exists on the element
3319                                 elem[ propName ] = true;
3320                         }
3321
3322                         elem.setAttribute( name, name.toLowerCase() );
3323                 }
3324                 return name;
3325         }
3326 };
3327
3328 // IE6/7 do not support getting/setting some attributes with get/setAttribute
3329 if ( !getSetAttribute ) {
3330
3331         fixSpecified = {
3332                 name: true,
3333                 id: true
3334         };
3335
3336         // Use this for any attribute in IE6/7
3337         // This fixes almost every IE6/7 issue
3338         nodeHook = jQuery.valHooks.button = {
3339                 get: function( elem, name ) {
3340                         var ret;
3341                         ret = elem.getAttributeNode( name );
3342                         return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
3343                                 ret.nodeValue :
3344                                 undefined;
3345                 },
3346                 set: function( elem, value, name ) {
3347                         // Set the existing or create a new attribute node
3348                         var ret = elem.getAttributeNode( name );
3349                         if ( !ret ) {
3350                                 ret = document.createAttribute( name );
3351                                 elem.setAttributeNode( ret );
3352                         }
3353                         return ( ret.nodeValue = value + "" );
3354                 }
3355         };
3356
3357         // Apply the nodeHook to tabindex
3358         jQuery.attrHooks.tabindex.set = nodeHook.set;
3359
3360         // Set width and height to auto instead of 0 on empty string( Bug #8150 )
3361         // This is for removals
3362         jQuery.each([ "width", "height" ], function( i, name ) {
3363                 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
3364                         set: function( elem, value ) {
3365                                 if ( value === "" ) {
3366                                         elem.setAttribute( name, "auto" );
3367                                         return value;
3368                                 }
3369                         }
3370                 });
3371         });
3372
3373         // Set contenteditable to false on removals(#10429)
3374         // Setting to empty string throws an error as an invalid value
3375         jQuery.attrHooks.contenteditable = {
3376                 get: nodeHook.get,
3377                 set: function( elem, value, name ) {
3378                         if ( value === "" ) {
3379                                 value = "false";
3380                         }
3381                         nodeHook.set( elem, value, name );
3382                 }
3383         };
3384 }
3385
3386
3387 // Some attributes require a special call on IE
3388 if ( !jQuery.support.hrefNormalized ) {
3389         jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
3390                 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
3391                         get: function( elem ) {
3392                                 var ret = elem.getAttribute( name, 2 );
3393                                 return ret === null ? undefined : ret;
3394                         }
3395                 });
3396         });
3397 }
3398
3399 if ( !jQuery.support.style ) {
3400         jQuery.attrHooks.style = {
3401                 get: function( elem ) {
3402                         // Return undefined in the case of empty string
3403                         // Normalize to lowercase since IE uppercases css property names
3404                         return elem.style.cssText.toLowerCase() || undefined;
3405                 },
3406                 set: function( elem, value ) {
3407                         return ( elem.style.cssText = "" + value );
3408                 }
3409         };
3410 }
3411
3412 // Safari mis-reports the default selected property of an option
3413 // Accessing the parent's selectedIndex property fixes it
3414 if ( !jQuery.support.optSelected ) {
3415         jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
3416                 get: function( elem ) {
3417                         var parent = elem.parentNode;
3418
3419                         if ( parent ) {
3420                                 parent.selectedIndex;
3421
3422                                 // Make sure that it also works with optgroups, see #5701
3423                                 if ( parent.parentNode ) {
3424                                         parent.parentNode.selectedIndex;
3425                                 }
3426                         }
3427                         return null;
3428                 }
3429         });
3430 }
3431
3432 // IE6/7 call enctype encoding
3433 if ( !jQuery.support.enctype ) {
3434         jQuery.propFix.enctype = "encoding";
3435 }
3436
3437 // Radios and checkboxes getter/setter
3438 if ( !jQuery.support.checkOn ) {
3439         jQuery.each([ "radio", "checkbox" ], function() {
3440                 jQuery.valHooks[ this ] = {
3441                         get: function( elem ) {
3442                                 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
3443                                 return elem.getAttribute("value") === null ? "on" : elem.value;
3444                         }
3445                 };
3446         });
3447 }
3448 jQuery.each([ "radio", "checkbox" ], function() {
3449         jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
3450                 set: function( elem, value ) {
3451                         if ( jQuery.isArray( value ) ) {
3452                                 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
3453                         }
3454                 }
3455         });
3456 });
3457
3458
3459
3460
3461 var rnamespaces = /\.(.*)$/,
3462         rformElems = /^(?:textarea|input|select)$/i,
3463         rperiod = /\./g,
3464         rspaces = / /g,
3465         rescape = /[^\w\s.|`]/g,
3466         rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
3467         rhoverHack = /\bhover(\.\S+)?/,
3468         rkeyEvent = /^key/,
3469         rmouseEvent = /^(?:mouse|contextmenu)|click/,
3470         rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
3471         quickParse = function( selector ) {
3472                 var quick = rquickIs.exec( selector );
3473                 if ( quick ) {
3474                         //   0  1    2   3
3475                         // [ _, tag, id, class ]
3476                         quick[1] = ( quick[1] || "" ).toLowerCase();
3477                         quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
3478                 }
3479                 return quick;
3480         },
3481         quickIs = function( elem, m ) {
3482                 return (
3483                         (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
3484                         (!m[2] || elem.id === m[2]) &&
3485                         (!m[3] || m[3].test( elem.className ))
3486                 );
3487         },
3488         hoverHack = function( events ) {
3489                 return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
3490         };
3491
3492 /*
3493  * Helper functions for managing events -- not part of the public interface.
3494  * Props to Dean Edwards' addEvent library for many of the ideas.
3495  */
3496 jQuery.event = {
3497
3498         add: function( elem, types, handler, data, selector ) {
3499
3500                 var elemData, eventHandle, events,
3501                         t, tns, type, namespaces, handleObj,
3502                         handleObjIn, quick, handlers, special;
3503
3504                 // Don't attach events to noData or text/comment nodes (allow plain objects tho)
3505                 if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
3506                         return;
3507                 }
3508
3509                 // Caller can pass in an object of custom data in lieu of the handler
3510                 if ( handler.handler ) {
3511                         handleObjIn = handler;
3512                         handler = handleObjIn.handler;
3513                 }
3514
3515                 // Make sure that the handler has a unique ID, used to find/remove it later
3516                 if ( !handler.guid ) {
3517                         handler.guid = jQuery.guid++;
3518                 }
3519
3520                 // Init the element's event structure and main handler, if this is the first
3521                 events = elemData.events;
3522                 if ( !events ) {
3523                         elemData.events = events = {};
3524                 }
3525                 eventHandle = elemData.handle;
3526                 if ( !eventHandle ) {
3527                         elemData.handle = eventHandle = function( e ) {
3528                                 // Discard the second event of a jQuery.event.trigger() and
3529                                 // when an event is called after a page has unloaded
3530                                 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
3531                                         jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
3532                                         undefined;
3533                         };
3534                         // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
3535                         eventHandle.elem = elem;
3536                 }
3537
3538                 // Handle multiple events separated by a space
3539                 // jQuery(...).bind("mouseover mouseout", fn);
3540                 types = hoverHack(types).split( " " );
3541                 for ( t = 0; t < types.length; t++ ) {
3542
3543                         tns = rtypenamespace.exec( types[t] ) || [];
3544                         type = tns[1];
3545                         namespaces = ( tns[2] || "" ).split( "." ).sort();
3546
3547                         // If event changes its type, use the special event handlers for the changed type
3548                         special = jQuery.event.special[ type ] || {};
3549
3550                         // If selector defined, determine special event api type, otherwise given type
3551                         type = ( selector ? special.delegateType : special.bindType ) || type;
3552
3553                         // Update special based on newly reset type
3554                         special = jQuery.event.special[ type ] || {};
3555
3556                         // handleObj is passed to all event handlers
3557                         handleObj = jQuery.extend({
3558                                 type: type,
3559                                 origType: tns[1],
3560                                 data: data,
3561                                 handler: handler,
3562                                 guid: handler.guid,
3563                                 selector: selector,
3564                                 namespace: namespaces.join(".")
3565                         }, handleObjIn );
3566
3567                         // Delegated event; pre-analyze selector so it's processed quickly on event dispatch
3568                         if ( selector ) {
3569                                 handleObj.quick = quickParse( selector );
3570                                 if ( !handleObj.quick && jQuery.expr.match.POS.test( selector ) ) {
3571                                         handleObj.isPositional = true;
3572                                 }
3573                         }
3574
3575                         // Init the event handler queue if we're the first
3576                         handlers = events[ type ];
3577                         if ( !handlers ) {
3578                                 handlers = events[ type ] = [];
3579                                 handlers.delegateCount = 0;
3580
3581                                 // Only use addEventListener/attachEvent if the special events handler returns false
3582                                 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
3583                                         // Bind the global event handler to the element
3584                                         if ( elem.addEventListener ) {
3585                                                 elem.addEventListener( type, eventHandle, false );
3586
3587                                         } else if ( elem.attachEvent ) {
3588                                                 elem.attachEvent( "on" + type, eventHandle );
3589                                         }
3590                                 }
3591                         }
3592
3593                         if ( special.add ) {
3594                                 special.add.call( elem, handleObj );
3595
3596                                 if ( !handleObj.handler.guid ) {
3597                                         handleObj.handler.guid = handler.guid;
3598                                 }
3599                         }
3600
3601                         // Add to the element's handler list, delegates in front
3602                         if ( selector ) {
3603                                 handlers.splice( handlers.delegateCount++, 0, handleObj );
3604                         } else {
3605                                 handlers.push( handleObj );
3606                         }
3607
3608                         // Keep track of which events have ever been used, for event optimization
3609                         jQuery.event.global[ type ] = true;
3610                 }
3611
3612                 // Nullify elem to prevent memory leaks in IE
3613                 elem = null;
3614         },
3615
3616         global: {},
3617
3618         // Detach an event or set of events from an element
3619         remove: function( elem, types, handler, selector ) {
3620
3621                 var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
3622                         t, tns, type, namespaces, origCount,
3623                         j, events, special, handle, eventType, handleObj;
3624
3625                 if ( !elemData || !(events = elemData.events) ) {
3626                         return;
3627                 }
3628
3629                 // Once for each type.namespace in types; type may be omitted
3630                 types = hoverHack( types || "" ).split(" ");
3631                 for ( t = 0; t < types.length; t++ ) {
3632                         tns = rtypenamespace.exec( types[t] ) || [];
3633                         type = tns[1];
3634                         namespaces = tns[2];
3635
3636                         // Unbind all events (on this namespace, if provided) for the element
3637                         if ( !type ) {
3638                                 namespaces = namespaces? "." + namespaces : "";
3639                                 for ( j in events ) {
3640                                         jQuery.event.remove( elem, j + namespaces, handler, selector );
3641                                 }
3642                                 return;
3643                         }
3644
3645                         special = jQuery.event.special[ type ] || {};
3646                         type = ( selector? special.delegateType : special.bindType ) || type;
3647                         eventType = events[ type ] || [];
3648                         origCount = eventType.length;
3649                         namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
3650
3651                         // Only need to loop for special events or selective removal
3652                         if ( handler || namespaces || selector || special.remove ) {
3653                                 for ( j = 0; j < eventType.length; j++ ) {
3654                                         handleObj = eventType[ j ];
3655
3656                                         if ( !handler || handler.guid === handleObj.guid ) {
3657                                                 if ( !namespaces || namespaces.test( handleObj.namespace ) ) {
3658                                                         if ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) {
3659                                                                 eventType.splice( j--, 1 );
3660
3661                                                                 if ( handleObj.selector ) {
3662                                                                         eventType.delegateCount--;
3663                                                                 }
3664                                                                 if ( special.remove ) {
3665                                                                         special.remove.call( elem, handleObj );
3666                                                                 }
3667                                                         }
3668                                                 }
3669                                         }
3670                                 }
3671                         } else {
3672                                 // Removing all events
3673                                 eventType.length = 0;
3674                         }
3675
3676                         // Remove generic event handler if we removed something and no more handlers exist
3677                         // (avoids potential for endless recursion during removal of special event handlers)
3678                         if ( eventType.length === 0 && origCount !== eventType.length ) {
3679                                 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
3680                                         jQuery.removeEvent( elem, type, elemData.handle );
3681                                 }
3682
3683                                 delete events[ type ];
3684                         }
3685                 }
3686
3687                 // Remove the expando if it's no longer used
3688                 if ( jQuery.isEmptyObject( events ) ) {
3689                         handle = elemData.handle;
3690                         if ( handle ) {
3691                                 handle.elem = null;
3692                         }
3693
3694                         // removeData also checks for emptiness and clears the expando if empty
3695                         // so use it instead of delete
3696                         jQuery.removeData( elem, [ "events", "handle" ], true );
3697                 }
3698         },
3699
3700         // Events that are safe to short-circuit if no handlers are attached.
3701         // Native DOM events should not be added, they may have inline handlers.
3702         customEvent: {
3703                 "getData": true,
3704                 "setData": true,
3705                 "changeData": true
3706         },
3707
3708         trigger: function( event, data, elem, onlyHandlers ) {
3709                 // Don't do events on text and comment nodes
3710                 if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
3711                         return;
3712                 }
3713
3714                 // Event object or event type
3715                 var type = event.type || event,
3716                         namespaces = [],
3717                         cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
3718
3719                 if ( type.indexOf( "!" ) >= 0 ) {
3720                         // Exclusive events trigger only for the exact event (no namespaces)
3721                         type = type.slice(0, -1);
3722                         exclusive = true;
3723                 }
3724
3725                 if ( type.indexOf( "." ) >= 0 ) {
3726                         // Namespaced trigger; create a regexp to match event type in handle()
3727                         namespaces = type.split(".");
3728                         type = namespaces.shift();
3729                         namespaces.sort();
3730                 }
3731
3732                 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
3733                         // No jQuery handlers for this event type, and it can't have inline handlers
3734                         return;
3735                 }
3736
3737                 // Caller can pass in an Event, Object, or just an event type string
3738                 event = typeof event === "object" ?
3739                         // jQuery.Event object
3740                         event[ jQuery.expando ] ? event :
3741                         // Object literal
3742                         new jQuery.Event( type, event ) :
3743                         // Just the event type (string)
3744                         new jQuery.Event( type );
3745
3746                 event.type = type;
3747                 event.isTrigger = true;
3748                 event.exclusive = exclusive;
3749                 event.namespace = namespaces.join( "." );
3750                 event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
3751                 ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
3752
3753                 // triggerHandler() and global events don't bubble or run the default action
3754                 if ( onlyHandlers || !elem ) {
3755                         event.preventDefault();
3756                 }
3757
3758                 // Handle a global trigger
3759                 if ( !elem ) {
3760
3761                         // TODO: Stop taunting the data cache; remove global events and always attach to document
3762                         cache = jQuery.cache;
3763                         for ( i in cache ) {
3764                                 if ( cache[ i ].events && cache[ i ].events[ type ] ) {
3765                                         jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
3766                                 }
3767                         }
3768                         return;
3769                 }
3770
3771                 // Clean up the event in case it is being reused
3772                 event.result = undefined;
3773                 if ( !event.target ) {
3774                         event.target = elem;
3775                 }
3776
3777                 // Clone any incoming data and prepend the event, creating the handler arg list
3778                 data = data != null ? jQuery.makeArray( data ) : [];
3779                 data.unshift( event );
3780
3781                 // Allow special events to draw outside the lines
3782                 special = jQuery.event.special[ type ] || {};
3783                 if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
3784                         return;
3785                 }
3786
3787                 // Determine event propagation path in advance, per W3C events spec (#9951)
3788                 // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
3789                 eventPath = [[ elem, special.bindType || type ]];
3790                 if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
3791
3792                         bubbleType = special.delegateType || type;
3793                         old = null;
3794                         for ( cur = elem.parentNode; cur; cur = cur.parentNode ) {
3795                                 eventPath.push([ cur, bubbleType ]);
3796                                 old = cur;
3797                         }
3798
3799                         // Only add window if we got to document (e.g., not plain obj or detached DOM)
3800                         if ( old && old === elem.ownerDocument ) {
3801                                 eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
3802                         }
3803                 }
3804
3805                 // Fire handlers on the event path
3806                 for ( i = 0; i < eventPath.length; i++ ) {
3807
3808                         cur = eventPath[i][0];
3809                         event.type = eventPath[i][1];
3810
3811                         handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
3812                         if ( handle ) {
3813                                 handle.apply( cur, data );
3814                         }
3815                         handle = ontype && cur[ ontype ];
3816                         if ( handle && jQuery.acceptData( cur ) ) {
3817                                 handle.apply( cur, data );
3818                         }
3819
3820                         if ( event.isPropagationStopped() ) {
3821                                 break;
3822                         }
3823                 }
3824                 event.type = type;
3825
3826                 // If nobody prevented the default action, do it now
3827                 if ( !event.isDefaultPrevented() ) {
3828
3829                         if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
3830                                 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
3831
3832                                 // Call a native DOM method on the target with the same name name as the event.
3833                                 // Can't use an .isFunction() check here because IE6/7 fails that test.
3834                                 // Don't do default actions on window, that's where global variables be (#6170)
3835                                 // IE<9 dies on focus/blur to hidden element (#1486)
3836                                 if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
3837
3838                                         // Don't re-trigger an onFOO event when we call its FOO() method
3839                                         old = elem[ ontype ];
3840
3841                                         if ( old ) {
3842                                                 elem[ ontype ] = null;
3843                                         }
3844
3845                                         // Prevent re-triggering of the same event, since we already bubbled it above
3846                                         jQuery.event.triggered = type;
3847                                         elem[ type ]();
3848                                         jQuery.event.triggered = undefined;
3849
3850                                         if ( old ) {
3851                                                 elem[ ontype ] = old;
3852                                         }
3853                                 }
3854                         }
3855                 }
3856
3857                 return event.result;
3858         },
3859
3860         dispatch: function( event ) {
3861
3862                 // Make a writable jQuery.Event from the native event object
3863                 event = jQuery.event.fix( event || window.event );
3864
3865                 var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
3866                         delegateCount = handlers.delegateCount,
3867                         args = [].slice.call( arguments, 0 ),
3868                         run_all = !event.exclusive && !event.namespace,
3869                         specialHandle = ( jQuery.event.special[ event.type ] || {} ).handle,
3870                         handlerQueue = [],
3871                         i, j, cur, ret, selMatch, matched, matches, handleObj, sel, hit, related;
3872
3873                 // Use the fix-ed jQuery.Event rather than the (read-only) native event
3874                 args[0] = event;
3875                 event.delegateTarget = this;
3876
3877                 // Determine handlers that should run if there are delegated events
3878                 // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
3879                 if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {
3880
3881                         for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
3882                                 selMatch = {};
3883                                 matches = [];
3884                                 for ( i = 0; i < delegateCount; i++ ) {
3885                                         handleObj = handlers[ i ];
3886                                         sel = handleObj.selector;
3887                                         hit = selMatch[ sel ];
3888
3889                                         if ( handleObj.isPositional ) {
3890                                                 // Since .is() does not work for positionals; see http://jsfiddle.net/eJ4yd/3/
3891                                                 hit = ( hit || (selMatch[ sel ] = jQuery( sel )) ).index( cur ) >= 0;
3892                                         } else if ( hit === undefined ) {
3893                                                 hit = selMatch[ sel ] = ( handleObj.quick ? quickIs( cur, handleObj.quick ) : jQuery( cur ).is( sel ) );
3894                                         }
3895                                         if ( hit ) {
3896                                                 matches.push( handleObj );
3897                                         }
3898                                 }
3899                                 if ( matches.length ) {
3900                                         handlerQueue.push({ elem: cur, matches: matches });
3901                                 }
3902                         }
3903                 }
3904
3905                 // Add the remaining (directly-bound) handlers
3906                 if ( handlers.length > delegateCount ) {
3907                         handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
3908                 }
3909
3910                 // Run delegates first; they may want to stop propagation beneath us
3911                 for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
3912                         matched = handlerQueue[ i ];
3913                         event.currentTarget = matched.elem;
3914
3915                         for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
3916                                 handleObj = matched.matches[ j ];
3917
3918                                 // Triggered event must either 1) be non-exclusive and have no namespace, or
3919                                 // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
3920                                 if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
3921
3922                                         event.data = handleObj.data;
3923                                         event.handleObj = handleObj;
3924
3925                                         ret = ( specialHandle || handleObj.handler ).apply( matched.elem, args );
3926
3927                                         if ( ret !== undefined ) {
3928                                                 event.result = ret;
3929                                                 if ( ret === false ) {
3930                                                         event.preventDefault();
3931                                                         event.stopPropagation();
3932                                                 }
3933                                         }
3934                                 }
3935                         }
3936                 }
3937
3938                 return event.result;
3939         },
3940
3941         // Includes some event props shared by KeyEvent and MouseEvent
3942         // *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
3943         props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
3944
3945         fixHooks: {},
3946
3947         keyHooks: {
3948                 props: "char charCode key keyCode".split(" "),
3949                 filter: function( event, original ) {
3950
3951                         // Add which for key events
3952                         if ( event.which == null ) {
3953                                 event.which = original.charCode != null ? original.charCode : original.keyCode;
3954                         }
3955
3956                         return event;
3957                 }
3958         },
3959
3960         mouseHooks: {
3961                 props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement wheelDelta".split(" "),
3962                 filter: function( event, original ) {
3963                         var eventDoc, doc, body,
3964                                 button = original.button,
3965                                 fromElement = original.fromElement;
3966
3967                         // Calculate pageX/Y if missing and clientX/Y available
3968                         if ( event.pageX == null && original.clientX != null ) {
3969                                 eventDoc = event.target.ownerDocument || document;
3970                                 doc = eventDoc.documentElement;
3971                                 body = eventDoc.body;
3972
3973                                 event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
3974                                 event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
3975                         }
3976
3977                         // Add relatedTarget, if necessary
3978                         if ( !event.relatedTarget && fromElement ) {
3979                                 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
3980                         }
3981
3982                         // Add which for click: 1 === left; 2 === middle; 3 === right
3983                         // Note: button is not normalized, so don't use it
3984                         if ( !event.which && button !== undefined ) {
3985                                 event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
3986                         }
3987
3988                         return event;
3989                 }
3990         },
3991
3992         fix: function( event ) {
3993                 if ( event[ jQuery.expando ] ) {
3994                         return event;
3995                 }
3996
3997                 // Create a writable copy of the event object and normalize some properties
3998                 var i, prop,
3999                         originalEvent = event,
4000                         fixHook = jQuery.event.fixHooks[ event.type ] || {},
4001                         copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
4002
4003                 event = jQuery.Event( originalEvent );
4004
4005                 for ( i = copy.length; i; ) {
4006                         prop = copy[ --i ];
4007                         event[ prop ] = originalEvent[ prop ];
4008                 }
4009
4010                 // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
4011                 if ( !event.target ) {
4012                         event.target = originalEvent.srcElement || document;
4013                 }
4014
4015                 // Target should not be a text node (#504, Safari)
4016                 if ( event.target.nodeType === 3 ) {
4017                         event.target = event.target.parentNode;
4018                 }
4019
4020                 // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
4021                 if ( event.metaKey === undefined ) {
4022                         event.metaKey = event.ctrlKey;
4023                 }
4024
4025                 return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
4026         },
4027
4028         special: {
4029                 ready: {
4030                         // Make sure the ready event is setup
4031                         setup: jQuery.bindReady
4032                 },
4033
4034                 focus: {
4035                         delegateType: "focusin",
4036                         noBubble: true
4037                 },
4038                 blur: {
4039                         delegateType: "focusout",
4040                         noBubble: true
4041                 },
4042
4043                 beforeunload: {
4044                         setup: function( data, namespaces, eventHandle ) {
4045                                 // We only want to do this special case on windows
4046                                 if ( jQuery.isWindow( this ) ) {
4047                                         this.onbeforeunload = eventHandle;
4048                                 }
4049                         },
4050
4051                         teardown: function( namespaces, eventHandle ) {
4052                                 if ( this.onbeforeunload === eventHandle ) {
4053                                         this.onbeforeunload = null;
4054                                 }
4055                         }
4056                 }
4057         },
4058
4059         simulate: function( type, elem, event, bubble ) {
4060                 // Piggyback on a donor event to simulate a different one.
4061                 // Fake originalEvent to avoid donor's stopPropagation, but if the
4062                 // simulated event prevents default then we do the same on the donor.
4063                 var e = jQuery.extend(
4064                         new jQuery.Event(),
4065                         event,
4066                         { type: type,
4067                                 isSimulated: true,
4068                                 originalEvent: {}
4069                         }
4070                 );
4071                 if ( bubble ) {
4072                         jQuery.event.trigger( e, null, elem );
4073                 } else {
4074                         jQuery.event.dispatch.call( elem, e );
4075                 }
4076                 if ( e.isDefaultPrevented() ) {
4077                         event.preventDefault();
4078                 }
4079         }
4080 };
4081
4082 // Some plugins are using, but it's undocumented/deprecated and will be removed.
4083 // The 1.7 special event interface should provide all the hooks needed now.
4084 jQuery.event.handle = jQuery.event.dispatch;
4085
4086 jQuery.removeEvent = document.removeEventListener ?
4087         function( elem, type, handle ) {
4088                 if ( elem.removeEventListener ) {
4089                         elem.removeEventListener( type, handle, false );
4090                 }
4091         } :
4092         function( elem, type, handle ) {
4093                 if ( elem.detachEvent ) {
4094                         elem.detachEvent( "on" + type, handle );
4095                 }
4096         };
4097
4098 jQuery.Event = function( src, props ) {
4099         // Allow instantiation without the 'new' keyword
4100         if ( !(this instanceof jQuery.Event) ) {
4101                 return new jQuery.Event( src, props );
4102         }
4103
4104         // Event object
4105         if ( src && src.type ) {
4106                 this.originalEvent = src;
4107                 this.type = src.type;
4108
4109                 // Events bubbling up the document may have been marked as prevented
4110                 // by a handler lower down the tree; reflect the correct value.
4111                 this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
4112                         src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
4113
4114         // Event type
4115         } else {
4116                 this.type = src;
4117         }
4118
4119         // Put explicitly provided properties onto the event object
4120         if ( props ) {
4121                 jQuery.extend( this, props );
4122         }
4123
4124         // Create a timestamp if incoming event doesn't have one
4125         this.timeStamp = src && src.timeStamp || jQuery.now();
4126
4127         // Mark it as fixed
4128         this[ jQuery.expando ] = true;
4129 };
4130
4131 function returnFalse() {
4132         return false;
4133 }
4134 function returnTrue() {
4135         return true;
4136 }
4137
4138 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
4139 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
4140 jQuery.Event.prototype = {
4141         preventDefault: function() {
4142                 this.isDefaultPrevented = returnTrue;
4143
4144                 var e = this.originalEvent;
4145                 if ( !e ) {
4146                         return;
4147                 }
4148
4149                 // if preventDefault exists run it on the original event
4150                 if ( e.preventDefault ) {
4151                         e.preventDefault();
4152
4153                 // otherwise set the returnValue property of the original event to false (IE)
4154                 } else {
4155                         e.returnValue = false;
4156                 }
4157         },
4158         stopPropagation: function() {
4159                 this.isPropagationStopped = returnTrue;
4160
4161                 var e = this.originalEvent;
4162                 if ( !e ) {
4163                         return;
4164                 }
4165                 // if stopPropagation exists run it on the original event
4166                 if ( e.stopPropagation ) {
4167                         e.stopPropagation();
4168                 }
4169                 // otherwise set the cancelBubble property of the original event to true (IE)
4170                 e.cancelBubble = true;
4171         },
4172         stopImmediatePropagation: function() {
4173                 this.isImmediatePropagationStopped = returnTrue;
4174                 this.stopPropagation();
4175         },
4176         isDefaultPrevented: returnFalse,
4177         isPropagationStopped: returnFalse,
4178         isImmediatePropagationStopped: returnFalse
4179 };
4180
4181 // Create mouseenter/leave events using mouseover/out and event-time checks
4182 jQuery.each({
4183         mouseenter: "mouseover",
4184         mouseleave: "mouseout"
4185 }, function( orig, fix ) {
4186         jQuery.event.special[ orig ] = jQuery.event.special[ fix ] = {
4187                 delegateType: fix,
4188                 bindType: fix,
4189
4190                 handle: function( event ) {
4191                         var target = this,
4192                                 related = event.relatedTarget,
4193                                 handleObj = event.handleObj,
4194                                 selector = handleObj.selector,
4195                                 oldType, ret;
4196
4197                         // For a real mouseover/out, always call the handler; for
4198                         // mousenter/leave call the handler if related is outside the target.
4199                         // NB: No relatedTarget if the mouse left/entered the browser window
4200                         if ( !related || handleObj.origType === event.type || (related !== target && !jQuery.contains( target, related )) ) {
4201                                 oldType = event.type;
4202                                 event.type = handleObj.origType;
4203                                 ret = handleObj.handler.apply( this, arguments );
4204                                 event.type = oldType;
4205                         }
4206                         return ret;
4207                 }
4208         };
4209 });
4210
4211 // IE submit delegation
4212 if ( !jQuery.support.submitBubbles ) {
4213
4214         jQuery.event.special.submit = {
4215                 setup: function() {
4216                         // Only need this for delegated form submit events
4217                         if ( jQuery.nodeName( this, "form" ) ) {
4218                                 return false;
4219                         }
4220
4221                         // Lazy-add a submit handler when a descendant form may potentially be submitted
4222                         jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
4223                                 // Node name check avoids a VML-related crash in IE (#9807)
4224                                 var elem = e.target,
4225                                         form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
4226                                 if ( form && !form._submit_attached ) {
4227                                         jQuery.event.add( form, "submit._submit", function( event ) {
4228                                                 // Form was submitted, bubble the event up the tree
4229                                                 if ( this.parentNode ) {
4230                                                         jQuery.event.simulate( "submit", this.parentNode, event, true );
4231                                                 }
4232                                         });
4233                                         form._submit_attached = true;
4234                                 }
4235                         });
4236                         // return undefined since we don't need an event listener
4237                 },
4238
4239                 teardown: function() {
4240                         // Only need this for delegated form submit events
4241                         if ( jQuery.nodeName( this, "form" ) ) {
4242                                 return false;
4243                         }
4244
4245                         // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
4246                         jQuery.event.remove( this, "._submit" );
4247                 }
4248         };
4249 }
4250
4251 // IE change delegation and checkbox/radio fix
4252 if ( !jQuery.support.changeBubbles ) {
4253
4254         jQuery.event.special.change = {
4255
4256                 setup: function() {
4257
4258                         if ( rformElems.test( this.nodeName ) ) {
4259                                 // IE doesn't fire change on a check/radio until blur; trigger it on click
4260                                 // after a propertychange. Eat the blur-change in special.change.handle.
4261                                 // This still fires onchange a second time for check/radio after blur.
4262                                 if ( this.type === "checkbox" || this.type === "radio" ) {
4263                                         jQuery.event.add( this, "propertychange._change", function( event ) {
4264                                                 if ( event.originalEvent.propertyName === "checked" ) {
4265                                                         this._just_changed = true;
4266                                                 }
4267                                         });
4268                                         jQuery.event.add( this, "click._change", function( event ) {
4269                                                 if ( this._just_changed ) {
4270                                                         this._just_changed = false;
4271                                                         jQuery.event.simulate( "change", this, event, true );
4272                                                 }
4273                                         });
4274                                 }
4275                                 return false;
4276                         }
4277                         // Delegated event; lazy-add a change handler on descendant inputs
4278                         jQuery.event.add( this, "beforeactivate._change", function( e ) {
4279                                 var elem = e.target;
4280
4281                                 if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
4282                                         jQuery.event.add( elem, "change._change", function( event ) {
4283                                                 if ( this.parentNode && !event.isSimulated ) {
4284                                                         jQuery.event.simulate( "change", this.parentNode, event, true );
4285                                                 }
4286                                         });
4287                                         elem._change_attached = true;
4288                                 }
4289                         });
4290                 },
4291
4292                 handle: function( event ) {
4293                         var elem = event.target;
4294
4295                         // Swallow native change events from checkbox/radio, we already triggered them above
4296                         if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
4297                                 return event.handleObj.handler.apply( this, arguments );
4298                         }
4299                 },
4300
4301                 teardown: function() {
4302                         jQuery.event.remove( this, "._change" );
4303
4304                         return rformElems.test( this.nodeName );
4305                 }
4306         };
4307 }
4308
4309 // Create "bubbling" focus and blur events
4310 if ( !jQuery.support.focusinBubbles ) {
4311         jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
4312
4313                 // Attach a single capturing handler while someone wants focusin/focusout
4314                 var attaches = 0,
4315                         handler = function( event ) {
4316                                 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
4317                         };
4318
4319                 jQuery.event.special[ fix ] = {
4320                         setup: function() {
4321                                 if ( attaches++ === 0 ) {
4322                                         document.addEventListener( orig, handler, true );
4323                                 }
4324                         },
4325                         teardown: function() {
4326                                 if ( --attaches === 0 ) {
4327                                         document.removeEventListener( orig, handler, true );
4328                                 }
4329                         }
4330                 };
4331         });
4332 }
4333
4334 jQuery.fn.extend({
4335
4336         on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
4337                 var origFn, type;
4338
4339                 // Types can be a map of types/handlers
4340                 if ( typeof types === "object" ) {
4341                         // ( types-Object, selector, data )
4342                         if ( typeof selector !== "string" ) {
4343                                 // ( types-Object, data )
4344                                 data = selector;
4345                                 selector = undefined;
4346                         }
4347                         for ( type in types ) {
4348                                 this.on( type, selector, data, types[ type ], one );
4349                         }
4350                         return this;
4351                 }
4352
4353                 if ( data == null && fn == null ) {
4354                         // ( types, fn )
4355                         fn = selector;
4356                         data = selector = undefined;
4357                 } else if ( fn == null ) {
4358                         if ( typeof selector === "string" ) {
4359                                 // ( types, selector, fn )
4360                                 fn = data;
4361                                 data = undefined;
4362                         } else {
4363                                 // ( types, data, fn )
4364                                 fn = data;
4365                                 data = selector;
4366                                 selector = undefined;
4367                         }
4368                 }
4369                 if ( fn === false ) {
4370                         fn = returnFalse;
4371                 } else if ( !fn ) {
4372                         return this;
4373                 }
4374
4375                 if ( one === 1 ) {
4376                         origFn = fn;
4377                         fn = function( event ) {
4378                                 // Can use an empty set, since event contains the info
4379                                 jQuery().off( event );
4380                                 return origFn.apply( this, arguments );
4381                         };
4382                         // Use same guid so caller can remove using origFn
4383                         fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4384                 }
4385                 return this.each( function() {
4386                         jQuery.event.add( this, types, fn, data, selector );
4387                 });
4388         },
4389         one: function( types, selector, data, fn ) {
4390                 return this.on.call( this, types, selector, data, fn, 1 );
4391         },
4392         off: function( types, selector, fn ) {
4393                 if ( types && types.preventDefault && types.handleObj ) {
4394                         // ( event )  dispatched jQuery.Event
4395                         var handleObj = types.handleObj;
4396                         jQuery( types.delegateTarget ).off(
4397                                 handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
4398                                 handleObj.selector,
4399                                 handleObj.handler
4400                         );
4401                         return this;
4402                 }
4403                 if ( typeof types === "object" ) {
4404                         // ( types-object [, selector] )
4405                         for ( var type in types ) {
4406                                 this.off( type, selector, types[ type ] );
4407                         }
4408                         return this;
4409                 }
4410                 if ( selector === false || typeof selector === "function" ) {
4411                         // ( types [, fn] )
4412                         fn = selector;
4413                         selector = undefined;
4414                 }
4415                 if ( fn === false ) {
4416                         fn = returnFalse;
4417                 }
4418                 return this.each(function() {
4419                         jQuery.event.remove( this, types, fn, selector );
4420                 });
4421         },
4422
4423         bind: function( types, data, fn ) {
4424                 return this.on( types, null, data, fn );
4425         },
4426         unbind: function( types, fn ) {
4427                 return this.off( types, null, fn );
4428         },
4429
4430         live: function( types, data, fn ) {
4431                 jQuery( this.context ).on( types, this.selector, data, fn );
4432                 return this;
4433         },
4434         die: function( types, fn ) {
4435                 jQuery( this.context ).off( types, this.selector || "**", fn );
4436                 return this;
4437         },
4438
4439         delegate: function( selector, types, data, fn ) {
4440                 return this.on( types, selector, data, fn );
4441         },
4442         undelegate: function( selector, types, fn ) {
4443                 // ( namespace ) or ( selector, types [, fn] )
4444                 return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
4445         },
4446
4447         trigger: function( type, data ) {
4448                 return this.each(function() {
4449                         jQuery.event.trigger( type, data, this );
4450                 });
4451         },
4452         triggerHandler: function( type, data ) {
4453                 if ( this[0] ) {
4454                         return jQuery.event.trigger( type, data, this[0], true );
4455                 }
4456         },
4457
4458         toggle: function( fn ) {
4459                 // Save reference to arguments for access in closure
4460                 var args = arguments,
4461                         guid = fn.guid || jQuery.guid++,
4462                         i = 0,
4463                         toggler = function( event ) {
4464                                 // Figure out which function to execute
4465                                 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
4466                                 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
4467
4468                                 // Make sure that clicks stop
4469                                 event.preventDefault();
4470
4471                                 // and execute the function
4472                                 return args[ lastToggle ].apply( this, arguments ) || false;
4473                         };
4474
4475                 // link all the functions, so any of them can unbind this click handler
4476                 toggler.guid = guid;
4477                 while ( i < args.length ) {
4478                         args[ i++ ].guid = guid;
4479                 }
4480
4481                 return this.click( toggler );
4482         },
4483
4484         hover: function( fnOver, fnOut ) {
4485                 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
4486         }
4487 });
4488
4489 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
4490         "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
4491         "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
4492
4493         // Handle event binding
4494         jQuery.fn[ name ] = function( data, fn ) {
4495                 if ( fn == null ) {
4496                         fn = data;
4497                         data = null;
4498                 }
4499
4500                 return arguments.length > 0 ?
4501                         this.bind( name, data, fn ) :
4502                         this.trigger( name );
4503         };
4504
4505         if ( jQuery.attrFn ) {
4506                 jQuery.attrFn[ name ] = true;
4507         }
4508
4509         if ( rkeyEvent.test( name ) ) {
4510                 jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
4511         }
4512
4513         if ( rmouseEvent.test( name ) ) {
4514                 jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
4515         }
4516 });
4517
4518
4519
4520 /*!
4521  * Sizzle CSS Selector Engine
4522  *  Copyright 2011, The Dojo Foundation
4523  *  Released under the MIT, BSD, and GPL Licenses.
4524  *  More information: http://sizzlejs.com/
4525  */
4526 (function(){
4527
4528 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
4529         expando = "sizcache" + (Math.random() + '').replace('.', ''),
4530         done = 0,
4531         toString = Object.prototype.toString,
4532         hasDuplicate = false,
4533         baseHasDuplicate = true,
4534         rBackslash = /\\/g,
4535         rReturn = /\r\n/g,
4536         rNonWord = /\W/;
4537
4538 // Here we check if the JavaScript engine is using some sort of
4539 // optimization where it does not always call our comparision
4540 // function. If that is the case, discard the hasDuplicate value.
4541 //   Thus far that includes Google Chrome.
4542 [0, 0].sort(function() {
4543         baseHasDuplicate = false;
4544         return 0;
4545 });
4546
4547 var Sizzle = function( selector, context, results, seed ) {
4548         results = results || [];
4549         context = context || document;
4550
4551         var origContext = context;
4552
4553         if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
4554                 return [];
4555         }
4556         
4557         if ( !selector || typeof selector !== "string" ) {
4558                 return results;
4559         }
4560
4561         var m, set, checkSet, extra, ret, cur, pop, i,
4562                 prune = true,
4563                 contextXML = Sizzle.isXML( context ),
4564                 parts = [],
4565                 soFar = selector;
4566         
4567         // Reset the position of the chunker regexp (start from head)
4568         do {
4569                 chunker.exec( "" );
4570                 m = chunker.exec( soFar );
4571
4572                 if ( m ) {
4573                         soFar = m[3];
4574                 
4575                         parts.push( m[1] );
4576                 
4577                         if ( m[2] ) {
4578                                 extra = m[3];
4579                                 break;
4580                         }
4581                 }
4582         } while ( m );
4583
4584         if ( parts.length > 1 && origPOS.exec( selector ) ) {
4585
4586                 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
4587                         set = posProcess( parts[0] + parts[1], context, seed );
4588
4589                 } else {
4590                         set = Expr.relative[ parts[0] ] ?
4591                                 [ context ] :
4592                                 Sizzle( parts.shift(), context );
4593
4594                         while ( parts.length ) {
4595                                 selector = parts.shift();
4596
4597                                 if ( Expr.relative[ selector ] ) {
4598                                         selector += parts.shift();
4599                                 }
4600                                 
4601                                 set = posProcess( selector, set, seed );
4602                         }
4603                 }
4604
4605         } else {
4606                 // Take a shortcut and set the context if the root selector is an ID
4607                 // (but not if it'll be faster if the inner selector is an ID)
4608                 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
4609                                 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
4610
4611                         ret = Sizzle.find( parts.shift(), context, contextXML );
4612                         context = ret.expr ?
4613                                 Sizzle.filter( ret.expr, ret.set )[0] :
4614                                 ret.set[0];
4615                 }
4616
4617                 if ( context ) {
4618                         ret = seed ?
4619                                 { expr: parts.pop(), set: makeArray(seed) } :
4620                                 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
4621
4622                         set = ret.expr ?
4623                                 Sizzle.filter( ret.expr, ret.set ) :
4624                                 ret.set;
4625
4626                         if ( parts.length > 0 ) {
4627                                 checkSet = makeArray( set );
4628
4629                         } else {
4630                                 prune = false;
4631                         }
4632
4633                         while ( parts.length ) {
4634                                 cur = parts.pop();
4635                                 pop = cur;
4636
4637                                 if ( !Expr.relative[ cur ] ) {
4638                                         cur = "";
4639                                 } else {
4640                                         pop = parts.pop();
4641                                 }
4642
4643                                 if ( pop == null ) {
4644                                         pop = context;
4645                                 }
4646
4647                                 Expr.relative[ cur ]( checkSet, pop, contextXML );
4648                         }
4649
4650                 } else {
4651                         checkSet = parts = [];
4652                 }
4653         }
4654
4655         if ( !checkSet ) {
4656                 checkSet = set;
4657         }
4658
4659         if ( !checkSet ) {
4660                 Sizzle.error( cur || selector );
4661         }
4662
4663         if ( toString.call(checkSet) === "[object Array]" ) {
4664                 if ( !prune ) {
4665                         results.push.apply( results, checkSet );
4666
4667                 } else if ( context && context.nodeType === 1 ) {
4668                         for ( i = 0; checkSet[i] != null; i++ ) {
4669                                 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
4670                                         results.push( set[i] );
4671                                 }
4672                         }
4673
4674                 } else {
4675                         for ( i = 0; checkSet[i] != null; i++ ) {
4676                                 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
4677                                         results.push( set[i] );
4678                                 }
4679                         }
4680                 }
4681
4682         } else {
4683                 makeArray( checkSet, results );
4684         }
4685
4686         if ( extra ) {
4687                 Sizzle( extra, origContext, results, seed );
4688                 Sizzle.uniqueSort( results );
4689         }
4690
4691         return results;
4692 };
4693
4694 Sizzle.uniqueSort = function( results ) {
4695         if ( sortOrder ) {
4696                 hasDuplicate = baseHasDuplicate;
4697                 results.sort( sortOrder );
4698
4699                 if ( hasDuplicate ) {
4700                         for ( var i = 1; i < results.length; i++ ) {
4701                                 if ( results[i] === results[ i - 1 ] ) {
4702                                         results.splice( i--, 1 );
4703                                 }
4704                         }
4705                 }
4706         }
4707
4708         return results;
4709 };
4710
4711 Sizzle.matches = function( expr, set ) {
4712         return Sizzle( expr, null, null, set );
4713 };
4714
4715 Sizzle.matchesSelector = function( node, expr ) {
4716         return Sizzle( expr, null, null, [node] ).length > 0;
4717 };
4718
4719 Sizzle.find = function( expr, context, isXML ) {
4720         var set, i, len, match, type, left;
4721
4722         if ( !expr ) {
4723                 return [];
4724         }
4725
4726         for ( i = 0, len = Expr.order.length; i < len; i++ ) {
4727                 type = Expr.order[i];
4728                 
4729                 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
4730                         left = match[1];
4731                         match.splice( 1, 1 );
4732
4733                         if ( left.substr( left.length - 1 ) !== "\\" ) {
4734                                 match[1] = (match[1] || "").replace( rBackslash, "" );
4735                                 set = Expr.find[ type ]( match, context, isXML );
4736
4737                                 if ( set != null ) {
4738                                         expr = expr.replace( Expr.match[ type ], "" );
4739                                         break;
4740                                 }
4741                         }
4742                 }
4743         }
4744
4745         if ( !set ) {
4746                 set = typeof context.getElementsByTagName !== "undefined" ?
4747                         context.getElementsByTagName( "*" ) :
4748                         [];
4749         }
4750
4751         return { set: set, expr: expr };
4752 };
4753
4754 Sizzle.filter = function( expr, set, inplace, not ) {
4755         var match, anyFound,
4756                 type, found, item, filter, left,
4757                 i, pass,
4758                 old = expr,
4759                 result = [],
4760                 curLoop = set,
4761                 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
4762
4763         while ( expr && set.length ) {
4764                 for ( type in Expr.filter ) {
4765                         if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
4766                                 filter = Expr.filter[ type ];
4767                                 left = match[1];
4768
4769                                 anyFound = false;
4770
4771                                 match.splice(1,1);
4772
4773                                 if ( left.substr( left.length - 1 ) === "\\" ) {
4774                                         continue;
4775                                 }
4776
4777                                 if ( curLoop === result ) {
4778                                         result = [];
4779                                 }
4780
4781                                 if ( Expr.preFilter[ type ] ) {
4782                                         match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
4783
4784                                         if ( !match ) {
4785                                                 anyFound = found = true;
4786
4787                                         } else if ( match === true ) {
4788                                                 continue;
4789                                         }
4790                                 }
4791
4792                                 if ( match ) {
4793                                         for ( i = 0; (item = curLoop[i]) != null; i++ ) {
4794                                                 if ( item ) {
4795                                                         found = filter( item, match, i, curLoop );
4796                                                         pass = not ^ found;
4797
4798                                                         if ( inplace && found != null ) {
4799                                                                 if ( pass ) {
4800                                                                         anyFound = true;
4801
4802                                                                 } else {
4803                                                                         curLoop[i] = false;
4804                                                                 }
4805
4806                                                         } else if ( pass ) {
4807                                                                 result.push( item );
4808                                                                 anyFound = true;
4809                                                         }
4810                                                 }
4811                                         }
4812                                 }
4813
4814                                 if ( found !== undefined ) {
4815                                         if ( !inplace ) {
4816                                                 curLoop = result;
4817                                         }
4818
4819                                         expr = expr.replace( Expr.match[ type ], "" );
4820
4821                                         if ( !anyFound ) {
4822                                                 return [];
4823                                         }
4824
4825                                         break;
4826                                 }
4827                         }
4828                 }
4829
4830                 // Improper expression
4831                 if ( expr === old ) {
4832                         if ( anyFound == null ) {
4833                                 Sizzle.error( expr );
4834
4835                         } else {
4836                                 break;
4837                         }
4838                 }
4839
4840                 old = expr;
4841         }
4842
4843         return curLoop;
4844 };
4845
4846 Sizzle.error = function( msg ) {
4847         throw "Syntax error, unrecognized expression: " + msg;
4848 };
4849
4850 /**
4851  * Utility function for retreiving the text value of an array of DOM nodes
4852  * @param {Array|Element} elem
4853  */
4854 var getText = Sizzle.getText = function( elem ) {
4855     var i, node,
4856                 nodeType = elem.nodeType,
4857                 ret = "";
4858
4859         if ( nodeType ) {
4860                 if ( nodeType === 1 ) {
4861                         // Use textContent || innerText for elements
4862                         if ( typeof elem.textContent === 'string' ) {
4863                                 return elem.textContent;
4864                         } else if ( typeof elem.innerText === 'string' ) {
4865                                 // Replace IE's carriage returns
4866                                 return elem.innerText.replace( rReturn, '' );
4867                         } else {
4868                                 // Traverse it's children
4869                                 for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
4870                                         ret += getText( elem );
4871                                 }
4872                         }
4873                 } else if ( nodeType === 3 || nodeType === 4 ) {
4874                         return elem.nodeValue;
4875                 }
4876         } else {
4877
4878                 // If no nodeType, this is expected to be an array
4879                 for ( i = 0; (node = elem[i]); i++ ) {
4880                         // Do not traverse comment nodes
4881                         if ( node.nodeType !== 8 ) {
4882                                 ret += getText( node );
4883                         }
4884                 }
4885         }
4886         return ret;
4887 };
4888
4889 var Expr = Sizzle.selectors = {
4890         order: [ "ID", "NAME", "TAG" ],
4891
4892         match: {
4893                 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
4894                 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
4895                 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
4896                 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
4897                 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
4898                 CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
4899                 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
4900                 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
4901         },
4902
4903         leftMatch: {},
4904
4905         attrMap: {
4906                 "class": "className",
4907                 "for": "htmlFor"
4908         },
4909
4910         attrHandle: {
4911                 href: function( elem ) {
4912                         return elem.getAttribute( "href" );
4913                 },
4914                 type: function( elem ) {
4915                         return elem.getAttribute( "type" );
4916                 }
4917         },
4918
4919         relative: {
4920                 "+": function(checkSet, part){
4921                         var isPartStr = typeof part === "string",
4922                                 isTag = isPartStr && !rNonWord.test( part ),
4923                                 isPartStrNotTag = isPartStr && !isTag;
4924
4925                         if ( isTag ) {
4926                                 part = part.toLowerCase();
4927                         }
4928
4929                         for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
4930                                 if ( (elem = checkSet[i]) ) {
4931                                         while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
4932
4933                                         checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
4934                                                 elem || false :
4935                                                 elem === part;
4936                                 }
4937                         }
4938
4939                         if ( isPartStrNotTag ) {
4940                                 Sizzle.filter( part, checkSet, true );
4941                         }
4942                 },
4943
4944                 ">": function( checkSet, part ) {
4945                         var elem,
4946                                 isPartStr = typeof part === "string",
4947                                 i = 0,
4948                                 l = checkSet.length;
4949
4950                         if ( isPartStr && !rNonWord.test( part ) ) {
4951                                 part = part.toLowerCase();
4952
4953                                 for ( ; i < l; i++ ) {
4954                                         elem = checkSet[i];
4955
4956                                         if ( elem ) {
4957                                                 var parent = elem.parentNode;
4958                                                 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
4959                                         }
4960                                 }
4961
4962                         } else {
4963                                 for ( ; i < l; i++ ) {
4964                                         elem = checkSet[i];
4965
4966                                         if ( elem ) {
4967                                                 checkSet[i] = isPartStr ?
4968                                                         elem.parentNode :
4969                                                         elem.parentNode === part;
4970                                         }
4971                                 }
4972
4973                                 if ( isPartStr ) {
4974                                         Sizzle.filter( part, checkSet, true );
4975                                 }
4976                         }
4977                 },
4978
4979                 "": function(checkSet, part, isXML){
4980                         var nodeCheck,
4981                                 doneName = done++,
4982                                 checkFn = dirCheck;
4983
4984                         if ( typeof part === "string" && !rNonWord.test( part ) ) {
4985                                 part = part.toLowerCase();
4986                                 nodeCheck = part;
4987                                 checkFn = dirNodeCheck;
4988                         }
4989
4990                         checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
4991                 },
4992
4993                 "~": function( checkSet, part, isXML ) {
4994                         var nodeCheck,
4995                                 doneName = done++,
4996                                 checkFn = dirCheck;
4997
4998                         if ( typeof part === "string" && !rNonWord.test( part ) ) {
4999                                 part = part.toLowerCase();
5000                                 nodeCheck = part;
5001                                 checkFn = dirNodeCheck;
5002                         }
5003
5004                         checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
5005                 }
5006         },
5007
5008         find: {
5009                 ID: function( match, context, isXML ) {
5010                         if ( typeof context.getElementById !== "undefined" && !isXML ) {
5011                                 var m = context.getElementById(match[1]);
5012                                 // Check parentNode to catch when Blackberry 4.6 returns
5013                                 // nodes that are no longer in the document #6963
5014                                 return m && m.parentNode ? [m] : [];
5015                         }
5016                 },
5017
5018                 NAME: function( match, context ) {
5019                         if ( typeof context.getElementsByName !== "undefined" ) {
5020                                 var ret = [],
5021                                         results = context.getElementsByName( match[1] );
5022
5023                                 for ( var i = 0, l = results.length; i < l; i++ ) {
5024                                         if ( results[i].getAttribute("name") === match[1] ) {
5025                                                 ret.push( results[i] );
5026                                         }
5027                                 }
5028
5029                                 return ret.length === 0 ? null : ret;
5030                         }
5031                 },
5032
5033                 TAG: function( match, context ) {
5034                         if ( typeof context.getElementsByTagName !== "undefined" ) {
5035                                 return context.getElementsByTagName( match[1] );
5036                         }
5037                 }
5038         },
5039         preFilter: {
5040                 CLASS: function( match, curLoop, inplace, result, not, isXML ) {
5041                         match = " " + match[1].replace( rBackslash, "" ) + " ";
5042
5043                         if ( isXML ) {
5044                                 return match;
5045                         }
5046
5047                         for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
5048                                 if ( elem ) {
5049                                         if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
5050                                                 if ( !inplace ) {
5051                                                         result.push( elem );
5052                                                 }
5053
5054                                         } else if ( inplace ) {
5055                                                 curLoop[i] = false;
5056                                         }
5057                                 }
5058                         }
5059
5060                         return false;
5061                 },
5062
5063                 ID: function( match ) {
5064                         return match[1].replace( rBackslash, "" );
5065                 },
5066
5067                 TAG: function( match, curLoop ) {
5068                         return match[1].replace( rBackslash, "" ).toLowerCase();
5069                 },
5070
5071                 CHILD: function( match ) {
5072                         if ( match[1] === "nth" ) {
5073                                 if ( !match[2] ) {
5074                                         Sizzle.error( match[0] );
5075                                 }
5076
5077                                 match[2] = match[2].replace(/^\+|\s*/g, '');
5078
5079                                 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
5080                                 var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
5081                                         match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
5082                                         !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
5083
5084                                 // calculate the numbers (first)n+(last) including if they are negative
5085                                 match[2] = (test[1] + (test[2] || 1)) - 0;
5086                                 match[3] = test[3] - 0;
5087                         }
5088                         else if ( match[2] ) {
5089                                 Sizzle.error( match[0] );
5090                         }
5091
5092                         // TODO: Move to normal caching system
5093                         match[0] = done++;
5094
5095                         return match;
5096                 },
5097
5098                 ATTR: function( match, curLoop, inplace, result, not, isXML ) {
5099                         var name = match[1] = match[1].replace( rBackslash, "" );
5100                         
5101                         if ( !isXML && Expr.attrMap[name] ) {
5102                                 match[1] = Expr.attrMap[name];
5103                         }
5104
5105                         // Handle if an un-quoted value was used
5106                         match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
5107
5108                         if ( match[2] === "~=" ) {
5109                                 match[4] = " " + match[4] + " ";
5110                         }
5111
5112                         return match;
5113                 },
5114
5115                 PSEUDO: function( match, curLoop, inplace, result, not ) {
5116                         if ( match[1] === "not" ) {
5117                                 // If we're dealing with a complex expression, or a simple one
5118                                 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
5119                                         match[3] = Sizzle(match[3], null, null, curLoop);
5120
5121                                 } else {
5122                                         var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
5123
5124                                         if ( !inplace ) {
5125                                                 result.push.apply( result, ret );
5126                                         }
5127
5128                                         return false;
5129                                 }
5130
5131                         } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
5132                                 return true;
5133                         }
5134                         
5135                         return match;
5136                 },
5137
5138                 POS: function( match ) {
5139                         match.unshift( true );
5140
5141                         return match;
5142                 }
5143         },
5144         
5145         filters: {
5146                 enabled: function( elem ) {
5147                         return elem.disabled === false && elem.type !== "hidden";
5148                 },
5149
5150                 disabled: function( elem ) {
5151                         return elem.disabled === true;
5152                 },
5153
5154                 checked: function( elem ) {
5155                         return elem.checked === true;
5156                 },
5157                 
5158                 selected: function( elem ) {
5159                         // Accessing this property makes selected-by-default
5160                         // options in Safari work properly
5161                         if ( elem.parentNode ) {
5162                                 elem.parentNode.selectedIndex;
5163                         }
5164                         
5165                         return elem.selected === true;
5166                 },
5167
5168                 parent: function( elem ) {
5169                         return !!elem.firstChild;
5170                 },
5171
5172                 empty: function( elem ) {
5173                         return !elem.firstChild;
5174                 },
5175
5176                 has: function( elem, i, match ) {
5177                         return !!Sizzle( match[3], elem ).length;
5178                 },
5179
5180                 header: function( elem ) {
5181                         return (/h\d/i).test( elem.nodeName );
5182                 },
5183
5184                 text: function( elem ) {
5185                         var attr = elem.getAttribute( "type" ), type = elem.type;
5186                         // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
5187                         // use getAttribute instead to test this case
5188                         return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
5189                 },
5190
5191                 radio: function( elem ) {
5192                         return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
5193                 },
5194
5195                 checkbox: function( elem ) {
5196                         return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
5197                 },
5198
5199                 file: function( elem ) {
5200                         return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
5201                 },
5202
5203                 password: function( elem ) {
5204                         return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
5205                 },
5206
5207                 submit: function( elem ) {
5208                         var name = elem.nodeName.toLowerCase();
5209                         return (name === "input" || name === "button") && "submit" === elem.type;
5210                 },
5211
5212                 image: function( elem ) {
5213                         return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
5214                 },
5215
5216                 reset: function( elem ) {
5217                         var name = elem.nodeName.toLowerCase();
5218                         return (name === "input" || name === "button") && "reset" === elem.type;
5219                 },
5220
5221                 button: function( elem ) {
5222                         var name = elem.nodeName.toLowerCase();
5223                         return name === "input" && "button" === elem.type || name === "button";
5224                 },
5225
5226                 input: function( elem ) {
5227                         return (/input|select|textarea|button/i).test( elem.nodeName );
5228                 },
5229
5230                 focus: function( elem ) {
5231                         return elem === elem.ownerDocument.activeElement;
5232                 }
5233         },
5234         setFilters: {
5235                 first: function( elem, i ) {
5236                         return i === 0;
5237                 },
5238
5239                 last: function( elem, i, match, array ) {
5240                         return i === array.length - 1;
5241                 },
5242
5243                 even: function( elem, i ) {
5244                         return i % 2 === 0;
5245                 },
5246
5247                 odd: function( elem, i ) {
5248                         return i % 2 === 1;
5249                 },
5250
5251                 lt: function( elem, i, match ) {
5252                         return i < match[3] - 0;
5253                 },
5254
5255                 gt: function( elem, i, match ) {
5256                         return i > match[3] - 0;
5257                 },
5258
5259                 nth: function( elem, i, match ) {
5260                         return match[3] - 0 === i;
5261                 },
5262
5263                 eq: function( elem, i, match ) {
5264                         return match[3] - 0 === i;
5265                 }
5266         },
5267         filter: {
5268                 PSEUDO: function( elem, match, i, array ) {
5269                         var name = match[1],
5270                                 filter = Expr.filters[ name ];
5271
5272                         if ( filter ) {
5273                                 return filter( elem, i, match, array );
5274
5275                         } else if ( name === "contains" ) {
5276                                 return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
5277
5278                         } else if ( name === "not" ) {
5279                                 var not = match[3];
5280
5281                                 for ( var j = 0, l = not.length; j < l; j++ ) {
5282                                         if ( not[j] === elem ) {
5283                                                 return false;
5284                                         }
5285                                 }
5286
5287                                 return true;
5288
5289                         } else {
5290                                 Sizzle.error( name );
5291                         }
5292                 },
5293
5294                 CHILD: function( elem, match ) {
5295                         var first, last,
5296                                 doneName, parent, cache,
5297                                 count, diff,
5298                                 type = match[1],
5299                                 node = elem;
5300
5301                         switch ( type ) {
5302                                 case "only":
5303                                 case "first":
5304                                         while ( (node = node.previousSibling) )  {
5305                                                 if ( node.nodeType === 1 ) { 
5306                                                         return false; 
5307                                                 }
5308                                         }
5309
5310                                         if ( type === "first" ) { 
5311                                                 return true; 
5312                                         }
5313
5314                                         node = elem;
5315
5316                                 case "last":
5317                                         while ( (node = node.nextSibling) )      {
5318                                                 if ( node.nodeType === 1 ) { 
5319                                                         return false; 
5320                                                 }
5321                                         }
5322
5323                                         return true;
5324
5325                                 case "nth":
5326                                         first = match[2];
5327                                         last = match[3];
5328
5329                                         if ( first === 1 && last === 0 ) {
5330                                                 return true;
5331                                         }
5332                                         
5333                                         doneName = match[0];
5334                                         parent = elem.parentNode;
5335         
5336                                         if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
5337                                                 count = 0;
5338                                                 
5339                                                 for ( node = parent.firstChild; node; node = node.nextSibling ) {
5340                                                         if ( node.nodeType === 1 ) {
5341                                                                 node.nodeIndex = ++count;
5342                                                         }
5343                                                 } 
5344
5345                                                 parent[ expando ] = doneName;
5346                                         }
5347                                         
5348                                         diff = elem.nodeIndex - last;
5349
5350                                         if ( first === 0 ) {
5351                                                 return diff === 0;
5352
5353                                         } else {
5354                                                 return ( diff % first === 0 && diff / first >= 0 );
5355                                         }
5356                         }
5357                 },
5358
5359                 ID: function( elem, match ) {
5360                         return elem.nodeType === 1 && elem.getAttribute("id") === match;
5361                 },
5362
5363                 TAG: function( elem, match ) {
5364                         return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
5365                 },
5366                 
5367                 CLASS: function( elem, match ) {
5368                         return (" " + (elem.className || elem.getAttribute("class")) + " ")
5369                                 .indexOf( match ) > -1;
5370                 },
5371
5372                 ATTR: function( elem, match ) {
5373                         var name = match[1],
5374                                 result = Sizzle.attr ?
5375                                         Sizzle.attr( elem, name ) :
5376                                         Expr.attrHandle[ name ] ?
5377                                         Expr.attrHandle[ name ]( elem ) :
5378                                         elem[ name ] != null ?
5379                                                 elem[ name ] :
5380                                                 elem.getAttribute( name ),
5381                                 value = result + "",
5382                                 type = match[2],
5383                                 check = match[4];
5384
5385                         return result == null ?
5386                                 type === "!=" :
5387                                 !type && Sizzle.attr ?
5388                                 result != null :
5389                                 type === "=" ?
5390                                 value === check :
5391                                 type === "*=" ?
5392                                 value.indexOf(check) >= 0 :
5393                                 type === "~=" ?
5394                                 (" " + value + " ").indexOf(check) >= 0 :
5395                                 !check ?
5396                                 value && result !== false :
5397                                 type === "!=" ?
5398                                 value !== check :
5399                                 type === "^=" ?
5400                                 value.indexOf(check) === 0 :
5401                                 type === "$=" ?
5402                                 value.substr(value.length - check.length) === check :
5403                                 type === "|=" ?
5404                                 value === check || value.substr(0, check.length + 1) === check + "-" :
5405                                 false;
5406                 },
5407
5408                 POS: function( elem, match, i, array ) {
5409                         var name = match[2],
5410                                 filter = Expr.setFilters[ name ];
5411
5412                         if ( filter ) {
5413                                 return filter( elem, i, match, array );
5414                         }
5415                 }
5416         }
5417 };
5418
5419 var origPOS = Expr.match.POS,
5420         fescape = function(all, num){
5421                 return "\\" + (num - 0 + 1);
5422         };
5423
5424 for ( var type in Expr.match ) {
5425         Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
5426         Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
5427 }
5428
5429 var makeArray = function( array, results ) {
5430         array = Array.prototype.slice.call( array, 0 );
5431
5432         if ( results ) {
5433                 results.push.apply( results, array );
5434                 return results;
5435         }
5436         
5437         return array;
5438 };
5439
5440 // Perform a simple check to determine if the browser is capable of
5441 // converting a NodeList to an array using builtin methods.
5442 // Also verifies that the returned array holds DOM nodes
5443 // (which is not the case in the Blackberry browser)
5444 try {
5445         Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
5446
5447 // Provide a fallback method if it does not work
5448 } catch( e ) {
5449         makeArray = function( array, results ) {
5450                 var i = 0,
5451                         ret = results || [];
5452
5453                 if ( toString.call(array) === "[object Array]" ) {
5454                         Array.prototype.push.apply( ret, array );
5455
5456                 } else {
5457                         if ( typeof array.length === "number" ) {
5458                                 for ( var l = array.length; i < l; i++ ) {
5459                                         ret.push( array[i] );
5460                                 }
5461
5462                         } else {
5463                                 for ( ; array[i]; i++ ) {
5464                                         ret.push( array[i] );
5465                                 }
5466                         }
5467                 }
5468
5469                 return ret;
5470         };
5471 }
5472
5473 var sortOrder, siblingCheck;
5474
5475 if ( document.documentElement.compareDocumentPosition ) {
5476         sortOrder = function( a, b ) {
5477                 if ( a === b ) {
5478                         hasDuplicate = true;
5479                         return 0;
5480                 }
5481
5482                 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
5483                         return a.compareDocumentPosition ? -1 : 1;
5484                 }
5485
5486                 return a.compareDocumentPosition(b) & 4 ? -1 : 1;
5487         };
5488
5489 } else {
5490         sortOrder = function( a, b ) {
5491                 // The nodes are identical, we can exit early
5492                 if ( a === b ) {
5493                         hasDuplicate = true;
5494                         return 0;
5495
5496                 // Fallback to using sourceIndex (in IE) if it's available on both nodes
5497                 } else if ( a.sourceIndex && b.sourceIndex ) {
5498                         return a.sourceIndex - b.sourceIndex;
5499                 }
5500
5501                 var al, bl,
5502                         ap = [],
5503                         bp = [],
5504                         aup = a.parentNode,
5505                         bup = b.parentNode,
5506                         cur = aup;
5507
5508                 // If the nodes are siblings (or identical) we can do a quick check
5509                 if ( aup === bup ) {
5510                         return siblingCheck( a, b );
5511
5512                 // If no parents were found then the nodes are disconnected
5513                 } else if ( !aup ) {
5514                         return -1;
5515
5516                 } else if ( !bup ) {
5517                         return 1;
5518                 }
5519
5520                 // Otherwise they're somewhere else in the tree so we need
5521                 // to build up a full list of the parentNodes for comparison
5522                 while ( cur ) {
5523                         ap.unshift( cur );
5524                         cur = cur.parentNode;
5525                 }
5526
5527                 cur = bup;
5528
5529                 while ( cur ) {
5530                         bp.unshift( cur );
5531                         cur = cur.parentNode;
5532                 }
5533
5534                 al = ap.length;
5535                 bl = bp.length;
5536
5537                 // Start walking down the tree looking for a discrepancy
5538                 for ( var i = 0; i < al && i < bl; i++ ) {
5539                         if ( ap[i] !== bp[i] ) {
5540                                 return siblingCheck( ap[i], bp[i] );
5541                         }
5542                 }
5543
5544                 // We ended someplace up the tree so do a sibling check
5545                 return i === al ?
5546                         siblingCheck( a, bp[i], -1 ) :
5547                         siblingCheck( ap[i], b, 1 );
5548         };
5549
5550         siblingCheck = function( a, b, ret ) {
5551                 if ( a === b ) {
5552                         return ret;
5553                 }
5554
5555                 var cur = a.nextSibling;
5556
5557                 while ( cur ) {
5558                         if ( cur === b ) {
5559                                 return -1;
5560                         }
5561
5562                         cur = cur.nextSibling;
5563                 }
5564
5565                 return 1;
5566         };
5567 }
5568
5569 // Check to see if the browser returns elements by name when
5570 // querying by getElementById (and provide a workaround)
5571 (function(){
5572         // We're going to inject a fake input element with a specified name
5573         var form = document.createElement("div"),
5574                 id = "script" + (new Date()).getTime(),
5575                 root = document.documentElement;
5576
5577         form.innerHTML = "<a name='" + id + "'/>";
5578
5579         // Inject it into the root element, check its status, and remove it quickly
5580         root.insertBefore( form, root.firstChild );
5581
5582         // The workaround has to do additional checks after a getElementById
5583         // Which slows things down for other browsers (hence the branching)
5584         if ( document.getElementById( id ) ) {
5585                 Expr.find.ID = function( match, context, isXML ) {
5586                         if ( typeof context.getElementById !== "undefined" && !isXML ) {
5587                                 var m = context.getElementById(match[1]);
5588
5589                                 return m ?
5590                                         m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
5591                                                 [m] :
5592                                                 undefined :
5593                                         [];
5594                         }
5595                 };
5596
5597                 Expr.filter.ID = function( elem, match ) {
5598                         var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
5599
5600                         return elem.nodeType === 1 && node && node.nodeValue === match;
5601                 };
5602         }
5603
5604         root.removeChild( form );
5605
5606         // release memory in IE
5607         root = form = null;
5608 })();
5609
5610 (function(){
5611         // Check to see if the browser returns only elements
5612         // when doing getElementsByTagName("*")
5613
5614         // Create a fake element
5615         var div = document.createElement("div");
5616         div.appendChild( document.createComment("") );
5617
5618         // Make sure no comments are found
5619         if ( div.getElementsByTagName("*").length > 0 ) {
5620                 Expr.find.TAG = function( match, context ) {
5621                         var results = context.getElementsByTagName( match[1] );
5622
5623                         // Filter out possible comments
5624                         if ( match[1] === "*" ) {
5625                                 var tmp = [];
5626
5627                                 for ( var i = 0; results[i]; i++ ) {
5628                                         if ( results[i].nodeType === 1 ) {
5629                                                 tmp.push( results[i] );
5630                                         }
5631                                 }
5632
5633                                 results = tmp;
5634                         }
5635
5636                         return results;
5637                 };
5638         }
5639
5640         // Check to see if an attribute returns normalized href attributes
5641         div.innerHTML = "<a href='#'></a>";
5642
5643         if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
5644                         div.firstChild.getAttribute("href") !== "#" ) {
5645
5646                 Expr.attrHandle.href = function( elem ) {
5647                         return elem.getAttribute( "href", 2 );
5648                 };
5649         }
5650
5651         // release memory in IE
5652         div = null;
5653 })();
5654
5655 if ( document.querySelectorAll ) {
5656         (function(){
5657                 var oldSizzle = Sizzle,
5658                         div = document.createElement("div"),
5659                         id = "__sizzle__";
5660
5661                 div.innerHTML = "<p class='TEST'></p>";
5662
5663                 // Safari can't handle uppercase or unicode characters when
5664                 // in quirks mode.
5665                 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
5666                         return;
5667                 }
5668         
5669                 Sizzle = function( query, context, extra, seed ) {
5670                         context = context || document;
5671
5672                         // Only use querySelectorAll on non-XML documents
5673                         // (ID selectors don't work in non-HTML documents)
5674                         if ( !seed && !Sizzle.isXML(context) ) {
5675                                 // See if we find a selector to speed up
5676                                 var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
5677                                 
5678                                 if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
5679                                         // Speed-up: Sizzle("TAG")
5680                                         if ( match[1] ) {
5681                                                 return makeArray( context.getElementsByTagName( query ), extra );
5682                                         
5683                                         // Speed-up: Sizzle(".CLASS")
5684                                         } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
5685                                                 return makeArray( context.getElementsByClassName( match[2] ), extra );
5686                                         }
5687                                 }
5688                                 
5689                                 if ( context.nodeType === 9 ) {
5690                                         // Speed-up: Sizzle("body")
5691                                         // The body element only exists once, optimize finding it
5692                                         if ( query === "body" && context.body ) {
5693                                                 return makeArray( [ context.body ], extra );
5694                                                 
5695                                         // Speed-up: Sizzle("#ID")
5696                                         } else if ( match && match[3] ) {
5697                                                 var elem = context.getElementById( match[3] );
5698
5699                                                 // Check parentNode to catch when Blackberry 4.6 returns
5700                                                 // nodes that are no longer in the document #6963
5701                                                 if ( elem && elem.parentNode ) {
5702                                                         // Handle the case where IE and Opera return items
5703                                                         // by name instead of ID
5704                                                         if ( elem.id === match[3] ) {
5705                                                                 return makeArray( [ elem ], extra );
5706                                                         }
5707                                                         
5708                                                 } else {
5709                                                         return makeArray( [], extra );
5710                                                 }
5711                                         }
5712                                         
5713                                         try {
5714                                                 return makeArray( context.querySelectorAll(query), extra );
5715                                         } catch(qsaError) {}
5716
5717                                 // qSA works strangely on Element-rooted queries
5718                                 // We can work around this by specifying an extra ID on the root
5719                                 // and working up from there (Thanks to Andrew Dupont for the technique)
5720                                 // IE 8 doesn't work on object elements
5721                                 } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
5722                                         var oldContext = context,
5723                                                 old = context.getAttribute( "id" ),
5724                                                 nid = old || id,
5725                                                 hasParent = context.parentNode,
5726                                                 relativeHierarchySelector = /^\s*[+~]/.test( query );
5727
5728                                         if ( !old ) {
5729                                                 context.setAttribute( "id", nid );
5730                                         } else {
5731                                                 nid = nid.replace( /'/g, "\\$&" );
5732                                         }
5733                                         if ( relativeHierarchySelector && hasParent ) {
5734                                                 context = context.parentNode;
5735                                         }
5736
5737                                         try {
5738                                                 if ( !relativeHierarchySelector || hasParent ) {
5739                                                         return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
5740                                                 }
5741
5742                                         } catch(pseudoError) {
5743                                         } finally {
5744                                                 if ( !old ) {
5745                                                         oldContext.removeAttribute( "id" );
5746                                                 }
5747                                         }
5748                                 }
5749                         }
5750                 
5751                         return oldSizzle(query, context, extra, seed);
5752                 };
5753
5754                 for ( var prop in oldSizzle ) {
5755                         Sizzle[ prop ] = oldSizzle[ prop ];
5756                 }
5757
5758                 // release memory in IE
5759                 div = null;
5760         })();
5761 }
5762
5763 (function(){
5764         var html = document.documentElement,
5765                 matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
5766
5767         if ( matches ) {
5768                 // Check to see if it's possible to do matchesSelector
5769                 // on a disconnected node (IE 9 fails this)
5770                 var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
5771                         pseudoWorks = false;
5772
5773                 try {
5774                         // This should fail with an exception
5775                         // Gecko does not error, returns false instead
5776                         matches.call( document.documentElement, "[test!='']:sizzle" );
5777         
5778                 } catch( pseudoError ) {
5779                         pseudoWorks = true;
5780                 }
5781
5782                 Sizzle.matchesSelector = function( node, expr ) {
5783                         // Make sure that attribute selectors are quoted
5784                         expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
5785
5786                         if ( !Sizzle.isXML( node ) ) {
5787                                 try { 
5788                                         if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
5789                                                 var ret = matches.call( node, expr );
5790
5791                                                 // IE 9's matchesSelector returns false on disconnected nodes
5792                                                 if ( ret || !disconnectedMatch ||
5793                                                                 // As well, disconnected nodes are said to be in a document
5794                                                                 // fragment in IE 9, so check for that
5795                                                                 node.document && node.document.nodeType !== 11 ) {
5796                                                         return ret;
5797                                                 }
5798                                         }
5799                                 } catch(e) {}
5800                         }
5801
5802                         return Sizzle(expr, null, null, [node]).length > 0;
5803                 };
5804         }
5805 })();
5806
5807 (function(){
5808         var div = document.createElement("div");
5809
5810         div.innerHTML = "<div class='test e'></div><div class='test'></div>";
5811
5812         // Opera can't find a second classname (in 9.6)
5813         // Also, make sure that getElementsByClassName actually exists
5814         if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
5815                 return;
5816         }
5817
5818         // Safari caches class attributes, doesn't catch changes (in 3.2)
5819         div.lastChild.className = "e";
5820
5821         if ( div.getElementsByClassName("e").length === 1 ) {
5822                 return;
5823         }
5824         
5825         Expr.order.splice(1, 0, "CLASS");
5826         Expr.find.CLASS = function( match, context, isXML ) {
5827                 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
5828                         return context.getElementsByClassName(match[1]);
5829                 }
5830         };
5831
5832         // release memory in IE
5833         div = null;
5834 })();
5835
5836 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5837         for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5838                 var elem = checkSet[i];
5839
5840                 if ( elem ) {
5841                         var match = false;
5842
5843                         elem = elem[dir];
5844
5845                         while ( elem ) {
5846                                 if ( elem[ expando ] === doneName ) {
5847                                         match = checkSet[elem.sizset];
5848                                         break;
5849                                 }
5850
5851                                 if ( elem.nodeType === 1 && !isXML ){
5852                                         elem[ expando ] = doneName;
5853                                         elem.sizset = i;
5854                                 }
5855
5856                                 if ( elem.nodeName.toLowerCase() === cur ) {
5857                                         match = elem;
5858                                         break;
5859                                 }
5860
5861                                 elem = elem[dir];
5862                         }
5863
5864                         checkSet[i] = match;
5865                 }
5866         }
5867 }
5868
5869 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5870         for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5871                 var elem = checkSet[i];
5872
5873                 if ( elem ) {
5874                         var match = false;
5875                         
5876                         elem = elem[dir];
5877
5878                         while ( elem ) {
5879                                 if ( elem[ expando ] === doneName ) {
5880                                         match = checkSet[elem.sizset];
5881                                         break;
5882                                 }
5883
5884                                 if ( elem.nodeType === 1 ) {
5885                                         if ( !isXML ) {
5886                                                 elem[ expando ] = doneName;
5887                                                 elem.sizset = i;
5888                                         }
5889
5890                                         if ( typeof cur !== "string" ) {
5891                                                 if ( elem === cur ) {
5892                                                         match = true;
5893                                                         break;
5894                                                 }
5895
5896                                         } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
5897                                                 match = elem;
5898                                                 break;
5899                                         }
5900                                 }
5901
5902                                 elem = elem[dir];
5903                         }
5904
5905                         checkSet[i] = match;
5906                 }
5907         }
5908 }
5909
5910 if ( document.documentElement.contains ) {
5911         Sizzle.contains = function( a, b ) {
5912                 return a !== b && (a.contains ? a.contains(b) : true);
5913         };
5914
5915 } else if ( document.documentElement.compareDocumentPosition ) {
5916         Sizzle.contains = function( a, b ) {
5917                 return !!(a.compareDocumentPosition(b) & 16);
5918         };
5919
5920 } else {
5921         Sizzle.contains = function() {
5922                 return false;
5923         };
5924 }
5925
5926 Sizzle.isXML = function( elem ) {
5927         // documentElement is verified for cases where it doesn't yet exist
5928         // (such as loading iframes in IE - #4833) 
5929         var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
5930
5931         return documentElement ? documentElement.nodeName !== "HTML" : false;
5932 };
5933
5934 var posProcess = function( selector, context, seed ) {
5935         var match,
5936                 tmpSet = [],
5937                 later = "",
5938                 root = context.nodeType ? [context] : context;
5939
5940         // Position selectors must be done after the filter
5941         // And so must :not(positional) so we move all PSEUDOs to the end
5942         while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
5943                 later += match[0];
5944                 selector = selector.replace( Expr.match.PSEUDO, "" );
5945         }
5946
5947         selector = Expr.relative[selector] ? selector + "*" : selector;
5948
5949         for ( var i = 0, l = root.length; i < l; i++ ) {
5950                 Sizzle( selector, root[i], tmpSet, seed );
5951         }
5952
5953         return Sizzle.filter( later, tmpSet );
5954 };
5955
5956 // EXPOSE
5957 // Override sizzle attribute retrieval
5958 Sizzle.attr = jQuery.attr;
5959 Sizzle.selectors.attrMap = {};
5960 jQuery.find = Sizzle;
5961 jQuery.expr = Sizzle.selectors;
5962 jQuery.expr[":"] = jQuery.expr.filters;
5963 jQuery.unique = Sizzle.uniqueSort;
5964 jQuery.text = Sizzle.getText;
5965 jQuery.isXMLDoc = Sizzle.isXML;
5966 jQuery.contains = Sizzle.contains;
5967
5968
5969 })();
5970
5971
5972 var runtil = /Until$/,
5973         rparentsprev = /^(?:parents|prevUntil|prevAll)/,
5974         // Note: This RegExp should be improved, or likely pulled from Sizzle
5975         rmultiselector = /,/,
5976         isSimple = /^.[^:#\[\.,]*$/,
5977         slice = Array.prototype.slice,
5978         POS = jQuery.expr.match.POS,
5979         // methods guaranteed to produce a unique set when starting from a unique set
5980         guaranteedUnique = {
5981                 children: true,
5982                 contents: true,
5983                 next: true,
5984                 prev: true
5985         };
5986
5987 jQuery.fn.extend({
5988         find: function( selector ) {
5989                 var self = this,
5990                         i, l;
5991
5992                 if ( typeof selector !== "string" ) {
5993                         return jQuery( selector ).filter(function() {
5994                                 for ( i = 0, l = self.length; i < l; i++ ) {
5995                                         if ( jQuery.contains( self[ i ], this ) ) {
5996                                                 return true;
5997                                         }
5998                                 }
5999                         });
6000                 }
6001
6002                 var ret = this.pushStack( "", "find", selector ),
6003                         length, n, r;
6004
6005                 for ( i = 0, l = this.length; i < l; i++ ) {
6006                         length = ret.length;
6007                         jQuery.find( selector, this[i], ret );
6008
6009                         if ( i > 0 ) {
6010                                 // Make sure that the results are unique
6011                                 for ( n = length; n < ret.length; n++ ) {
6012                                         for ( r = 0; r < length; r++ ) {
6013                                                 if ( ret[r] === ret[n] ) {
6014                                                         ret.splice(n--, 1);
6015                                                         break;
6016                                                 }
6017                                         }
6018                                 }
6019                         }
6020                 }
6021
6022                 return ret;
6023         },
6024
6025         has: function( target ) {
6026                 var targets = jQuery( target );
6027                 return this.filter(function() {
6028                         for ( var i = 0, l = targets.length; i < l; i++ ) {
6029                                 if ( jQuery.contains( this, targets[i] ) ) {
6030                                         return true;
6031                                 }
6032                         }
6033                 });
6034         },
6035
6036         not: function( selector ) {
6037                 return this.pushStack( winnow(this, selector, false), "not", selector);
6038         },
6039
6040         filter: function( selector ) {
6041                 return this.pushStack( winnow(this, selector, true), "filter", selector );
6042         },
6043
6044         is: function( selector ) {
6045                 return !!selector && ( 
6046                         typeof selector === "string" ?
6047                                 // If this is a positional selector, check membership in the returned set
6048                                 // so $("p:first").is("p:last") won't return true for a doc with two "p".
6049                                 POS.test( selector ) ? 
6050                                         jQuery( selector, this.context ).index( this[0] ) >= 0 :
6051                                         jQuery.filter( selector, this ).length > 0 :
6052                                 this.filter( selector ).length > 0 );
6053         },
6054
6055         closest: function( selectors, context ) {
6056                 var ret = [], i, l, cur = this[0];
6057                 
6058                 // Array (deprecated as of jQuery 1.7)
6059                 if ( jQuery.isArray( selectors ) ) {
6060                         var level = 1;
6061
6062                         while ( cur && cur.ownerDocument && cur !== context ) {
6063                                 for ( i = 0; i < selectors.length; i++ ) {
6064
6065                                         if ( jQuery( cur ).is( selectors[ i ] ) ) {
6066                                                 ret.push({ selector: selectors[ i ], elem: cur, level: level });
6067                                         }
6068                                 }
6069
6070                                 cur = cur.parentNode;
6071                                 level++;
6072                         }
6073
6074                         return ret;
6075                 }
6076
6077                 // String
6078                 var pos = POS.test( selectors ) || typeof selectors !== "string" ?
6079                                 jQuery( selectors, context || this.context ) :
6080                                 0;
6081
6082                 for ( i = 0, l = this.length; i < l; i++ ) {
6083                         cur = this[i];
6084
6085                         while ( cur ) {
6086                                 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
6087                                         ret.push( cur );
6088                                         break;
6089
6090                                 } else {
6091                                         cur = cur.parentNode;
6092                                         if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
6093                                                 break;
6094                                         }
6095                                 }
6096                         }
6097                 }
6098
6099                 ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
6100
6101                 return this.pushStack( ret, "closest", selectors );
6102         },
6103
6104         // Determine the position of an element within
6105         // the matched set of elements
6106         index: function( elem ) {
6107
6108                 // No argument, return index in parent
6109                 if ( !elem ) {
6110                         return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
6111                 }
6112
6113                 // index in selector
6114                 if ( typeof elem === "string" ) {
6115                         return jQuery.inArray( this[0], jQuery( elem ) );
6116                 }
6117
6118                 // Locate the position of the desired element
6119                 return jQuery.inArray(
6120                         // If it receives a jQuery object, the first element is used
6121                         elem.jquery ? elem[0] : elem, this );
6122         },
6123
6124         add: function( selector, context ) {
6125                 var set = typeof selector === "string" ?
6126                                 jQuery( selector, context ) :
6127                                 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
6128                         all = jQuery.merge( this.get(), set );
6129
6130                 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
6131                         all :
6132                         jQuery.unique( all ) );
6133         },
6134
6135         andSelf: function() {
6136                 return this.add( this.prevObject );
6137         }
6138 });
6139
6140 // A painfully simple check to see if an element is disconnected
6141 // from a document (should be improved, where feasible).
6142 function isDisconnected( node ) {
6143         return !node || !node.parentNode || node.parentNode.nodeType === 11;
6144 }
6145
6146 jQuery.each({
6147         parent: function( elem ) {
6148                 var parent = elem.parentNode;
6149                 return parent && parent.nodeType !== 11 ? parent : null;
6150         },
6151         parents: function( elem ) {
6152                 return jQuery.dir( elem, "parentNode" );
6153         },
6154         parentsUntil: function( elem, i, until ) {
6155                 return jQuery.dir( elem, "parentNode", until );
6156         },
6157         next: function( elem ) {
6158                 return jQuery.nth( elem, 2, "nextSibling" );
6159         },
6160         prev: function( elem ) {
6161                 return jQuery.nth( elem, 2, "previousSibling" );
6162         },
6163         nextAll: function( elem ) {
6164                 return jQuery.dir( elem, "nextSibling" );
6165         },
6166         prevAll: function( elem ) {
6167                 return jQuery.dir( elem, "previousSibling" );
6168         },
6169         nextUntil: function( elem, i, until ) {
6170                 return jQuery.dir( elem, "nextSibling", until );
6171         },
6172         prevUntil: function( elem, i, until ) {
6173                 return jQuery.dir( elem, "previousSibling", until );
6174         },
6175         siblings: function( elem ) {
6176                 return jQuery.sibling( elem.parentNode.firstChild, elem );
6177         },
6178         children: function( elem ) {
6179                 return jQuery.sibling( elem.firstChild );
6180         },
6181         contents: function( elem ) {
6182                 return jQuery.nodeName( elem, "iframe" ) ?
6183                         elem.contentDocument || elem.contentWindow.document :
6184                         jQuery.makeArray( elem.childNodes );
6185         }
6186 }, function( name, fn ) {
6187         jQuery.fn[ name ] = function( until, selector ) {
6188                 var ret = jQuery.map( this, fn, until ),
6189                         // The variable 'args' was introduced in
6190                         // https://github.com/jquery/jquery/commit/52a0238
6191                         // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
6192                         // http://code.google.com/p/v8/issues/detail?id=1050
6193                         args = slice.call(arguments);
6194
6195                 if ( !runtil.test( name ) ) {
6196                         selector = until;
6197                 }
6198
6199                 if ( selector && typeof selector === "string" ) {
6200                         ret = jQuery.filter( selector, ret );
6201                 }
6202
6203                 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
6204
6205                 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
6206                         ret = ret.reverse();
6207                 }
6208
6209                 return this.pushStack( ret, name, args.join(",") );
6210         };
6211 });
6212
6213 jQuery.extend({
6214         filter: function( expr, elems, not ) {
6215                 if ( not ) {
6216                         expr = ":not(" + expr + ")";
6217                 }
6218
6219                 return elems.length === 1 ?
6220                         jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
6221                         jQuery.find.matches(expr, elems);
6222         },
6223
6224         dir: function( elem, dir, until ) {
6225                 var matched = [],
6226                         cur = elem[ dir ];
6227
6228                 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
6229                         if ( cur.nodeType === 1 ) {
6230                                 matched.push( cur );
6231                         }
6232                         cur = cur[dir];
6233                 }
6234                 return matched;
6235         },
6236
6237         nth: function( cur, result, dir, elem ) {
6238                 result = result || 1;
6239                 var num = 0;
6240
6241                 for ( ; cur; cur = cur[dir] ) {
6242                         if ( cur.nodeType === 1 && ++num === result ) {
6243                                 break;
6244                         }
6245                 }
6246
6247                 return cur;
6248         },
6249
6250         sibling: function( n, elem ) {
6251                 var r = [];
6252
6253                 for ( ; n; n = n.nextSibling ) {
6254                         if ( n.nodeType === 1 && n !== elem ) {
6255                                 r.push( n );
6256                         }
6257                 }
6258
6259                 return r;
6260         }
6261 });
6262
6263 // Implement the identical functionality for filter and not
6264 function winnow( elements, qualifier, keep ) {
6265
6266         // Can't pass null or undefined to indexOf in Firefox 4
6267         // Set to 0 to skip string check
6268         qualifier = qualifier || 0;
6269
6270         if ( jQuery.isFunction( qualifier ) ) {
6271                 return jQuery.grep(elements, function( elem, i ) {
6272                         var retVal = !!qualifier.call( elem, i, elem );
6273                         return retVal === keep;
6274                 });
6275
6276         } else if ( qualifier.nodeType ) {
6277                 return jQuery.grep(elements, function( elem, i ) {
6278                         return ( elem === qualifier ) === keep;
6279                 });
6280
6281         } else if ( typeof qualifier === "string" ) {
6282                 var filtered = jQuery.grep(elements, function( elem ) {
6283                         return elem.nodeType === 1;
6284                 });
6285
6286                 if ( isSimple.test( qualifier ) ) {
6287                         return jQuery.filter(qualifier, filtered, !keep);
6288                 } else {
6289                         qualifier = jQuery.filter( qualifier, filtered );
6290                 }
6291         }
6292
6293         return jQuery.grep(elements, function( elem, i ) {
6294                 return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
6295         });
6296 }
6297
6298
6299
6300
6301 function createSafeFragment( document ) {
6302         var list = nodeNames.split( " " ),
6303         safeFrag = document.createDocumentFragment();
6304
6305         if ( safeFrag.createElement ) {
6306                 while ( list.length ) {
6307                         safeFrag.createElement(
6308                                 list.pop()
6309                         );
6310                 }
6311         }
6312         return safeFrag;
6313 }
6314
6315 var nodeNames = "abbr article aside audio canvas datalist details figcaption figure footer " +
6316                 "header hgroup mark meter nav output progress section summary time video",
6317         rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
6318         rleadingWhitespace = /^\s+/,
6319         rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
6320         rtagName = /<([\w:]+)/,
6321         rtbody = /<tbody/i,
6322         rhtml = /<|&#?\w+;/,
6323         rnoInnerhtml = /<(?:script|style)/i,
6324         rnocache = /<(?:script|object|embed|option|style)/i,
6325         rnoshimcache = new RegExp("<(?:" + nodeNames.replace(" ", "|") + ")", "i"),
6326         // checked="checked" or checked
6327         rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
6328         rscriptType = /\/(java|ecma)script/i,
6329         rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
6330         wrapMap = {
6331                 option: [ 1, "<select multiple='multiple'>", "</select>" ],
6332                 legend: [ 1, "<fieldset>", "</fieldset>" ],
6333                 thead: [ 1, "<table>", "</table>" ],
6334                 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
6335                 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
6336                 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
6337                 area: [ 1, "<map>", "</map>" ],
6338                 _default: [ 0, "", "" ]
6339         },
6340         safeFragment = createSafeFragment( document );
6341
6342 wrapMap.optgroup = wrapMap.option;
6343 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
6344 wrapMap.th = wrapMap.td;
6345
6346 // IE can't serialize <link> and <script> tags normally
6347 if ( !jQuery.support.htmlSerialize ) {
6348         wrapMap._default = [ 1, "div<div>", "</div>" ];
6349 }
6350
6351 jQuery.fn.extend({
6352         text: function( text ) {
6353                 if ( jQuery.isFunction(text) ) {
6354                         return this.each(function(i) {
6355                                 var self = jQuery( this );
6356
6357                                 self.text( text.call(this, i, self.text()) );
6358                         });
6359                 }
6360
6361                 if ( typeof text !== "object" && text !== undefined ) {
6362                         return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
6363                 }
6364
6365                 return jQuery.text( this );
6366         },
6367
6368         wrapAll: function( html ) {
6369                 if ( jQuery.isFunction( html ) ) {
6370                         return this.each(function(i) {
6371                                 jQuery(this).wrapAll( html.call(this, i) );
6372                         });
6373                 }
6374
6375                 if ( this[0] ) {
6376                         // The elements to wrap the target around
6377                         var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
6378
6379                         if ( this[0].parentNode ) {
6380                                 wrap.insertBefore( this[0] );
6381                         }
6382
6383                         wrap.map(function() {
6384                                 var elem = this;
6385
6386                                 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
6387                                         elem = elem.firstChild;
6388                                 }
6389
6390                                 return elem;
6391                         }).append( this );
6392                 }
6393
6394                 return this;
6395         },
6396
6397         wrapInner: function( html ) {
6398                 if ( jQuery.isFunction( html ) ) {
6399                         return this.each(function(i) {
6400                                 jQuery(this).wrapInner( html.call(this, i) );
6401                         });
6402                 }
6403
6404                 return this.each(function() {
6405                         var self = jQuery( this ),
6406                                 contents = self.contents();
6407
6408                         if ( contents.length ) {
6409                                 contents.wrapAll( html );
6410
6411                         } else {
6412                                 self.append( html );
6413                         }
6414                 });
6415         },
6416
6417         wrap: function( html ) {
6418                 return this.each(function() {
6419                         jQuery( this ).wrapAll( html );
6420                 });
6421         },
6422
6423         unwrap: function() {
6424                 return this.parent().each(function() {
6425                         if ( !jQuery.nodeName( this, "body" ) ) {
6426                                 jQuery( this ).replaceWith( this.childNodes );
6427                         }
6428                 }).end();
6429         },
6430
6431         append: function() {
6432                 return this.domManip(arguments, true, function( elem ) {
6433                         if ( this.nodeType === 1 ) {
6434                                 this.appendChild( elem );
6435                         }
6436                 });
6437         },
6438
6439         prepend: function() {
6440                 return this.domManip(arguments, true, function( elem ) {
6441                         if ( this.nodeType === 1 ) {
6442                                 this.insertBefore( elem, this.firstChild );
6443                         }
6444                 });
6445         },
6446
6447         before: function() {
6448                 if ( this[0] && this[0].parentNode ) {
6449                         return this.domManip(arguments, false, function( elem ) {
6450                                 this.parentNode.insertBefore( elem, this );
6451                         });
6452                 } else if ( arguments.length ) {
6453                         var set = jQuery(arguments[0]);
6454                         set.push.apply( set, this.toArray() );
6455                         return this.pushStack( set, "before", arguments );
6456                 }
6457         },
6458
6459         after: function() {
6460                 if ( this[0] && this[0].parentNode ) {
6461                         return this.domManip(arguments, false, function( elem ) {
6462                                 this.parentNode.insertBefore( elem, this.nextSibling );
6463                         });
6464                 } else if ( arguments.length ) {
6465                         var set = this.pushStack( this, "after", arguments );
6466                         set.push.apply( set, jQuery(arguments[0]).toArray() );
6467                         return set;
6468                 }
6469         },
6470
6471         // keepData is for internal use only--do not document
6472         remove: function( selector, keepData ) {
6473                 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
6474                         if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
6475                                 if ( !keepData && elem.nodeType === 1 ) {
6476                                         jQuery.cleanData( elem.getElementsByTagName("*") );
6477                                         jQuery.cleanData( [ elem ] );
6478                                 }
6479
6480                                 if ( elem.parentNode ) {
6481                                         elem.parentNode.removeChild( elem );
6482                                 }
6483                         }
6484                 }
6485
6486                 return this;
6487         },
6488
6489         empty: function() {
6490                 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
6491                         // Remove element nodes and prevent memory leaks
6492                         if ( elem.nodeType === 1 ) {
6493                                 jQuery.cleanData( elem.getElementsByTagName("*") );
6494                         }
6495
6496                         // Remove any remaining nodes
6497                         while ( elem.firstChild ) {
6498                                 elem.removeChild( elem.firstChild );
6499                         }
6500                 }
6501
6502                 return this;
6503         },
6504
6505         clone: function( dataAndEvents, deepDataAndEvents ) {
6506                 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6507                 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6508
6509                 return this.map( function () {
6510                         return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6511                 });
6512         },
6513
6514         html: function( value ) {
6515                 if ( value === undefined ) {
6516                         return this[0] && this[0].nodeType === 1 ?
6517                                 this[0].innerHTML.replace(rinlinejQuery, "") :
6518                                 null;
6519
6520                 // See if we can take a shortcut and just use innerHTML
6521                 } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
6522                         (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
6523                         !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
6524
6525                         value = value.replace(rxhtmlTag, "<$1></$2>");
6526
6527                         try {
6528                                 for ( var i = 0, l = this.length; i < l; i++ ) {
6529                                         // Remove element nodes and prevent memory leaks
6530                                         if ( this[i].nodeType === 1 ) {
6531                                                 jQuery.cleanData( this[i].getElementsByTagName("*") );
6532                                                 this[i].innerHTML = value;
6533                                         }
6534                                 }
6535
6536                         // If using innerHTML throws an exception, use the fallback method
6537                         } catch(e) {
6538                                 this.empty().append( value );
6539                         }
6540
6541                 } else if ( jQuery.isFunction( value ) ) {
6542                         this.each(function(i){
6543                                 var self = jQuery( this );
6544
6545                                 self.html( value.call(this, i, self.html()) );
6546                         });
6547
6548                 } else {
6549                         this.empty().append( value );
6550                 }
6551
6552                 return this;
6553         },
6554
6555         replaceWith: function( value ) {
6556                 if ( this[0] && this[0].parentNode ) {
6557                         // Make sure that the elements are removed from the DOM before they are inserted
6558                         // this can help fix replacing a parent with child elements
6559                         if ( jQuery.isFunction( value ) ) {
6560                                 return this.each(function(i) {
6561                                         var self = jQuery(this), old = self.html();
6562                                         self.replaceWith( value.call( this, i, old ) );
6563                                 });
6564                         }
6565
6566                         if ( typeof value !== "string" ) {
6567                                 value = jQuery( value ).detach();
6568                         }
6569
6570                         return this.each(function() {
6571                                 var next = this.nextSibling,
6572                                         parent = this.parentNode;
6573
6574                                 jQuery( this ).remove();
6575
6576                                 if ( next ) {
6577                                         jQuery(next).before( value );
6578                                 } else {
6579                                         jQuery(parent).append( value );
6580                                 }
6581                         });
6582                 } else {
6583                         return this.length ?
6584                                 this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
6585                                 this;
6586                 }
6587         },
6588
6589         detach: function( selector ) {
6590                 return this.remove( selector, true );
6591         },
6592
6593         domManip: function( args, table, callback ) {
6594                 var results, first, fragment, parent,
6595                         value = args[0],
6596                         scripts = [];
6597
6598                 // We can't cloneNode fragments that contain checked, in WebKit
6599                 if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
6600                         return this.each(function() {
6601                                 jQuery(this).domManip( args, table, callback, true );
6602                         });
6603                 }
6604
6605                 if ( jQuery.isFunction(value) ) {
6606                         return this.each(function(i) {
6607                                 var self = jQuery(this);
6608                                 args[0] = value.call(this, i, table ? self.html() : undefined);
6609                                 self.domManip( args, table, callback );
6610                         });
6611                 }
6612
6613                 if ( this[0] ) {
6614                         parent = value && value.parentNode;
6615
6616                         // If we're in a fragment, just use that instead of building a new one
6617                         if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
6618                                 results = { fragment: parent };
6619
6620                         } else {
6621                                 results = jQuery.buildFragment( args, this, scripts );
6622                         }
6623
6624                         fragment = results.fragment;
6625
6626                         if ( fragment.childNodes.length === 1 ) {
6627                                 first = fragment = fragment.firstChild;
6628                         } else {
6629                                 first = fragment.firstChild;
6630                         }
6631
6632                         if ( first ) {
6633                                 table = table && jQuery.nodeName( first, "tr" );
6634
6635                                 for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
6636                                         callback.call(
6637                                                 table ?
6638                                                         root(this[i], first) :
6639                                                         this[i],
6640                                                 // Make sure that we do not leak memory by inadvertently discarding
6641                                                 // the original fragment (which might have attached data) instead of
6642                                                 // using it; in addition, use the original fragment object for the last
6643                                                 // item instead of first because it can end up being emptied incorrectly
6644                                                 // in certain situations (Bug #8070).
6645                                                 // Fragments from the fragment cache must always be cloned and never used
6646                                                 // in place.
6647                                                 results.cacheable || ( l > 1 && i < lastIndex ) ?
6648                                                         jQuery.clone( fragment, true, true ) :
6649                                                         fragment
6650                                         );
6651                                 }
6652                         }
6653
6654                         if ( scripts.length ) {
6655                                 jQuery.each( scripts, evalScript );
6656                         }
6657                 }
6658
6659                 return this;
6660         }
6661 });
6662
6663 function root( elem, cur ) {
6664         return jQuery.nodeName(elem, "table") ?
6665                 (elem.getElementsByTagName("tbody")[0] ||
6666                 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
6667                 elem;
6668 }
6669
6670 function cloneCopyEvent( src, dest ) {
6671
6672         if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6673                 return;
6674         }
6675
6676         var type, i, l,
6677                 oldData = jQuery._data( src ),
6678                 curData = jQuery._data( dest, oldData ),
6679                 events = oldData.events;
6680
6681         if ( events ) {
6682                 delete curData.handle;
6683                 curData.events = {};
6684
6685                 for ( type in events ) {
6686                         for ( i = 0, l = events[ type ].length; i < l; i++ ) {
6687                                 jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
6688                         }
6689                 }
6690         }
6691
6692         // make the cloned public data object a copy from the original
6693         if ( curData.data ) {
6694                 curData.data = jQuery.extend( {}, curData.data );
6695         }
6696 }
6697
6698 function cloneFixAttributes( src, dest ) {
6699         var nodeName;
6700
6701         // We do not need to do anything for non-Elements
6702         if ( dest.nodeType !== 1 ) {
6703                 return;
6704         }
6705
6706         // clearAttributes removes the attributes, which we don't want,
6707         // but also removes the attachEvent events, which we *do* want
6708         if ( dest.clearAttributes ) {
6709                 dest.clearAttributes();
6710         }
6711
6712         // mergeAttributes, in contrast, only merges back on the
6713         // original attributes, not the events
6714         if ( dest.mergeAttributes ) {
6715                 dest.mergeAttributes( src );
6716         }
6717
6718         nodeName = dest.nodeName.toLowerCase();
6719
6720         // IE6-8 fail to clone children inside object elements that use
6721         // the proprietary classid attribute value (rather than the type
6722         // attribute) to identify the type of content to display
6723         if ( nodeName === "object" ) {
6724                 dest.outerHTML = src.outerHTML;
6725
6726         } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
6727                 // IE6-8 fails to persist the checked state of a cloned checkbox
6728                 // or radio button. Worse, IE6-7 fail to give the cloned element
6729                 // a checked appearance if the defaultChecked value isn't also set
6730                 if ( src.checked ) {
6731                         dest.defaultChecked = dest.checked = src.checked;
6732                 }
6733
6734                 // IE6-7 get confused and end up setting the value of a cloned
6735                 // checkbox/radio button to an empty string instead of "on"
6736                 if ( dest.value !== src.value ) {
6737                         dest.value = src.value;
6738                 }
6739
6740         // IE6-8 fails to return the selected option to the default selected
6741         // state when cloning options
6742         } else if ( nodeName === "option" ) {
6743                 dest.selected = src.defaultSelected;
6744
6745         // IE6-8 fails to set the defaultValue to the correct value when
6746         // cloning other types of input fields
6747         } else if ( nodeName === "input" || nodeName === "textarea" ) {
6748                 dest.defaultValue = src.defaultValue;
6749         }
6750
6751         // Event data gets referenced instead of copied if the expando
6752         // gets copied too
6753         dest.removeAttribute( jQuery.expando );
6754 }
6755
6756 jQuery.buildFragment = function( args, nodes, scripts ) {
6757         var fragment, cacheable, cacheresults, doc,
6758         first = args[ 0 ];
6759
6760         // nodes may contain either an explicit document object,
6761         // a jQuery collection or context object.
6762         // If nodes[0] contains a valid object to assign to doc
6763         if ( nodes && nodes[0] ) {
6764                 doc = nodes[0].ownerDocument || nodes[0];
6765         }
6766
6767   // Ensure that an attr object doesn't incorrectly stand in as a document object
6768         // Chrome and Firefox seem to allow this to occur and will throw exception
6769         // Fixes #8950
6770         if ( !doc.createDocumentFragment ) {
6771                 doc = document;
6772         }
6773
6774         // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
6775         // Cloning options loses the selected state, so don't cache them
6776         // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
6777         // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
6778         // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
6779         if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
6780                 first.charAt(0) === "<" && !rnocache.test( first ) &&
6781                 (jQuery.support.checkClone || !rchecked.test( first )) &&
6782                 (!jQuery.support.unknownElems && rnoshimcache.test( first )) ) {
6783
6784                 cacheable = true;
6785
6786                 cacheresults = jQuery.fragments[ first ];
6787                 if ( cacheresults && cacheresults !== 1 ) {
6788                         fragment = cacheresults;
6789                 }
6790         }
6791
6792         if ( !fragment ) {
6793                 fragment = doc.createDocumentFragment();
6794                 jQuery.clean( args, doc, fragment, scripts );
6795         }
6796
6797         if ( cacheable ) {
6798                 jQuery.fragments[ first ] = cacheresults ? fragment : 1;
6799         }
6800
6801         return { fragment: fragment, cacheable: cacheable };
6802 };
6803
6804 jQuery.fragments = {};
6805
6806 jQuery.each({
6807         appendTo: "append",
6808         prependTo: "prepend",
6809         insertBefore: "before",
6810         insertAfter: "after",
6811         replaceAll: "replaceWith"
6812 }, function( name, original ) {
6813         jQuery.fn[ name ] = function( selector ) {
6814                 var ret = [],
6815                         insert = jQuery( selector ),
6816                         parent = this.length === 1 && this[0].parentNode;
6817
6818                 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
6819                         insert[ original ]( this[0] );
6820                         return this;
6821
6822                 } else {
6823                         for ( var i = 0, l = insert.length; i < l; i++ ) {
6824                                 var elems = ( i > 0 ? this.clone(true) : this ).get();
6825                                 jQuery( insert[i] )[ original ]( elems );
6826                                 ret = ret.concat( elems );
6827                         }
6828
6829                         return this.pushStack( ret, name, insert.selector );
6830                 }
6831         };
6832 });
6833
6834 function getAll( elem ) {
6835         if ( typeof elem.getElementsByTagName !== "undefined" ) {
6836                 return elem.getElementsByTagName( "*" );
6837
6838         } else if ( typeof elem.querySelectorAll !== "undefined" ) {
6839                 return elem.querySelectorAll( "*" );
6840
6841         } else {
6842                 return [];
6843         }
6844 }
6845
6846 // Used in clean, fixes the defaultChecked property
6847 function fixDefaultChecked( elem ) {
6848         if ( elem.type === "checkbox" || elem.type === "radio" ) {
6849                 elem.defaultChecked = elem.checked;
6850         }
6851 }
6852 // Finds all inputs and passes them to fixDefaultChecked
6853 function findInputs( elem ) {
6854         var nodeName = ( elem.nodeName || "" ).toLowerCase();
6855         if ( nodeName === "input" ) {
6856                 fixDefaultChecked( elem );
6857         // Skip scripts, get other children
6858         } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
6859                 jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
6860         }
6861 }
6862
6863 jQuery.extend({
6864         clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6865                 var clone = elem.cloneNode(true),
6866                                 srcElements,
6867                                 destElements,
6868                                 i;
6869
6870                 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6871                                 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6872                         // IE copies events bound via attachEvent when using cloneNode.
6873                         // Calling detachEvent on the clone will also remove the events
6874                         // from the original. In order to get around this, we use some
6875                         // proprietary methods to clear the events. Thanks to MooTools
6876                         // guys for this hotness.
6877
6878                         cloneFixAttributes( elem, clone );
6879
6880                         // Using Sizzle here is crazy slow, so we use getElementsByTagName
6881                         // instead
6882                         srcElements = getAll( elem );
6883                         destElements = getAll( clone );
6884
6885                         // Weird iteration because IE will replace the length property
6886                         // with an element if you are cloning the body and one of the
6887                         // elements on the page has a name or id of "length"
6888                         for ( i = 0; srcElements[i]; ++i ) {
6889                                 // Ensure that the destination node is not null; Fixes #9587
6890                                 if ( destElements[i] ) {
6891                                         cloneFixAttributes( srcElements[i], destElements[i] );
6892                                 }
6893                         }
6894                 }
6895
6896                 // Copy the events from the original to the clone
6897                 if ( dataAndEvents ) {
6898                         cloneCopyEvent( elem, clone );
6899
6900                         if ( deepDataAndEvents ) {
6901                                 srcElements = getAll( elem );
6902                                 destElements = getAll( clone );
6903
6904                                 for ( i = 0; srcElements[i]; ++i ) {
6905                                         cloneCopyEvent( srcElements[i], destElements[i] );
6906                                 }
6907                         }
6908                 }
6909
6910                 srcElements = destElements = null;
6911
6912                 // Return the cloned set
6913                 return clone;
6914         },
6915
6916         clean: function( elems, context, fragment, scripts ) {
6917                 var checkScriptType;
6918
6919                 context = context || document;
6920
6921                 // !context.createElement fails in IE with an error but returns typeof 'object'
6922                 if ( typeof context.createElement === "undefined" ) {
6923                         context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
6924                 }
6925
6926                 var ret = [], j;
6927
6928                 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
6929                         if ( typeof elem === "number" ) {
6930                                 elem += "";
6931                         }
6932
6933                         if ( !elem ) {
6934                                 continue;
6935                         }
6936
6937                         // Convert html string into DOM nodes
6938                         if ( typeof elem === "string" ) {
6939                                 if ( !rhtml.test( elem ) ) {
6940                                         elem = context.createTextNode( elem );
6941                                 } else {
6942                                         // Fix "XHTML"-style tags in all browsers
6943                                         elem = elem.replace(rxhtmlTag, "<$1></$2>");
6944
6945                                         // Trim whitespace, otherwise indexOf won't work as expected
6946                                         var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
6947                                                 wrap = wrapMap[ tag ] || wrapMap._default,
6948                                                 depth = wrap[0],
6949                                                 div = context.createElement("div");
6950
6951                                         // Append wrapper element to unknown element safe doc fragment
6952                                         if ( context === document ) {
6953                                                 // Use the fragment we've already created for this document
6954                                                 safeFragment.appendChild( div );
6955                                         } else {
6956                                                 // Use a fragment created with the owner document
6957                                                 createSafeFragment( context ).appendChild( div );
6958                                         }
6959
6960                                         // Go to html and back, then peel off extra wrappers
6961                                         div.innerHTML = wrap[1] + elem + wrap[2];
6962
6963                                         // Move to the right depth
6964                                         while ( depth-- ) {
6965                                                 div = div.lastChild;
6966                                         }
6967
6968                                         // Remove IE's autoinserted <tbody> from table fragments
6969                                         if ( !jQuery.support.tbody ) {
6970
6971                                                 // String was a <table>, *may* have spurious <tbody>
6972                                                 var hasBody = rtbody.test(elem),
6973                                                         tbody = tag === "table" && !hasBody ?
6974                                                                 div.firstChild && div.firstChild.childNodes :
6975
6976                                                                 // String was a bare <thead> or <tfoot>
6977                                                                 wrap[1] === "<table>" && !hasBody ?
6978                                                                         div.childNodes :
6979                                                                         [];
6980
6981                                                 for ( j = tbody.length - 1; j >= 0 ; --j ) {
6982                                                         if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
6983                                                                 tbody[ j ].parentNode.removeChild( tbody[ j ] );
6984                                                         }
6985                                                 }
6986                                         }
6987
6988                                         // IE completely kills leading whitespace when innerHTML is used
6989                                         if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6990                                                 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
6991                                         }
6992
6993                                         elem = div.childNodes;
6994                                 }
6995                         }
6996
6997                         // Resets defaultChecked for any radios and checkboxes
6998                         // about to be appended to the DOM in IE 6/7 (#8060)
6999                         var len;
7000                         if ( !jQuery.support.appendChecked ) {
7001                                 if ( elem[0] && typeof (len = elem.length) === "number" ) {
7002                                         for ( j = 0; j < len; j++ ) {
7003                                                 findInputs( elem[j] );
7004                                         }
7005                                 } else {
7006                                         findInputs( elem );
7007                                 }
7008                         }
7009
7010                         if ( elem.nodeType ) {
7011                                 ret.push( elem );
7012                         } else {
7013                                 ret = jQuery.merge( ret, elem );
7014                         }
7015                 }
7016
7017                 if ( fragment ) {
7018                         checkScriptType = function( elem ) {
7019                                 return !elem.type || rscriptType.test( elem.type );
7020                         };
7021                         for ( i = 0; ret[i]; i++ ) {
7022                                 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
7023                                         scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
7024
7025                                 } else {
7026                                         if ( ret[i].nodeType === 1 ) {
7027                                                 var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
7028
7029                                                 ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
7030                                         }
7031                                         fragment.appendChild( ret[i] );
7032                                 }
7033                         }
7034                 }
7035
7036                 return ret;
7037         },
7038
7039         cleanData: function( elems ) {
7040                 var data, id,
7041                         cache = jQuery.cache,
7042                         special = jQuery.event.special,
7043                         deleteExpando = jQuery.support.deleteExpando;
7044
7045                 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
7046                         if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
7047                                 continue;
7048                         }
7049
7050                         id = elem[ jQuery.expando ];
7051
7052                         if ( id ) {
7053                                 data = cache[ id ];
7054
7055                                 if ( data && data.events ) {
7056                                         for ( var type in data.events ) {
7057                                                 if ( special[ type ] ) {
7058                                                         jQuery.event.remove( elem, type );
7059
7060                                                 // This is a shortcut to avoid jQuery.event.remove's overhead
7061                                                 } else {
7062                                                         jQuery.removeEvent( elem, type, data.handle );
7063                                                 }
7064                                         }
7065
7066                                         // Null the DOM reference to avoid IE6/7/8 leak (#7054)
7067                                         if ( data.handle ) {
7068                                                 data.handle.elem = null;
7069                                         }
7070                                 }
7071
7072                                 if ( deleteExpando ) {
7073                                         delete elem[ jQuery.expando ];
7074
7075                                 } else if ( elem.removeAttribute ) {
7076                                         elem.removeAttribute( jQuery.expando );
7077                                 }
7078
7079                                 delete cache[ id ];
7080                         }
7081                 }
7082         }
7083 });
7084
7085 function evalScript( i, elem ) {
7086         if ( elem.src ) {
7087                 jQuery.ajax({
7088                         url: elem.src,
7089                         async: false,
7090                         dataType: "script"
7091                 });
7092         } else {
7093                 jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
7094         }
7095
7096         if ( elem.parentNode ) {
7097                 elem.parentNode.removeChild( elem );
7098         }
7099 }
7100
7101
7102
7103
7104 var ralpha = /alpha\([^)]*\)/i,
7105         ropacity = /opacity=([^)]*)/,
7106         // fixed for IE9, see #8346
7107         rupper = /([A-Z]|^ms)/g,
7108         rnumpx = /^-?\d+(?:px)?$/i,
7109         rnum = /^-?\d/,
7110         rrelNum = /^([\-+])=([\-+.\de]+)/,
7111
7112         cssShow = { position: "absolute", visibility: "hidden", display: "block" },
7113         cssWidth = [ "Left", "Right" ],
7114         cssHeight = [ "Top", "Bottom" ],
7115         curCSS,
7116
7117         getComputedStyle,
7118         currentStyle;
7119
7120 jQuery.fn.css = function( name, value ) {
7121         // Setting 'undefined' is a no-op
7122         if ( arguments.length === 2 && value === undefined ) {
7123                 return this;
7124         }
7125
7126         return jQuery.access( this, name, value, true, function( elem, name, value ) {
7127                 return value !== undefined ?
7128                         jQuery.style( elem, name, value ) :
7129                         jQuery.css( elem, name );
7130         });
7131 };
7132
7133 jQuery.extend({
7134         // Add in style property hooks for overriding the default
7135         // behavior of getting and setting a style property
7136         cssHooks: {
7137                 opacity: {
7138                         get: function( elem, computed ) {
7139                                 if ( computed ) {
7140                                         // We should always get a number back from opacity
7141                                         var ret = curCSS( elem, "opacity", "opacity" );
7142                                         return ret === "" ? "1" : ret;
7143
7144                                 } else {
7145                                         return elem.style.opacity;
7146                                 }
7147                         }
7148                 }
7149         },
7150
7151         // Exclude the following css properties to add px
7152         cssNumber: {
7153                 "fillOpacity": true,
7154                 "fontWeight": true,
7155                 "lineHeight": true,
7156                 "opacity": true,
7157                 "orphans": true,
7158                 "widows": true,
7159                 "zIndex": true,
7160                 "zoom": true
7161         },
7162
7163         // Add in properties whose names you wish to fix before
7164         // setting or getting the value
7165         cssProps: {
7166                 // normalize float css property
7167                 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
7168         },
7169
7170         // Get and set the style property on a DOM Node
7171         style: function( elem, name, value, extra ) {
7172                 // Don't set styles on text and comment nodes
7173                 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
7174                         return;
7175                 }
7176
7177                 // Make sure that we're working with the right name
7178                 var ret, type, origName = jQuery.camelCase( name ),
7179                         style = elem.style, hooks = jQuery.cssHooks[ origName ];
7180
7181                 name = jQuery.cssProps[ origName ] || origName;
7182
7183                 // Check if we're setting a value
7184                 if ( value !== undefined ) {
7185                         type = typeof value;
7186
7187                         // convert relative number strings (+= or -=) to relative numbers. #7345
7188                         if ( type === "string" && (ret = rrelNum.exec( value )) ) {
7189                                 value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
7190                                 // Fixes bug #9237
7191                                 type = "number";
7192                         }
7193
7194                         // Make sure that NaN and null values aren't set. See: #7116
7195                         if ( value == null || type === "number" && isNaN( value ) ) {
7196                                 return;
7197                         }
7198
7199                         // If a number was passed in, add 'px' to the (except for certain CSS properties)
7200                         if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
7201                                 value += "px";
7202                         }
7203
7204                         // If a hook was provided, use that value, otherwise just set the specified value
7205                         if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
7206                                 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
7207                                 // Fixes bug #5509
7208                                 try {
7209                                         style[ name ] = value;
7210                                 } catch(e) {}
7211                         }
7212
7213                 } else {
7214                         // If a hook was provided get the non-computed value from there
7215                         if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
7216                                 return ret;
7217                         }
7218
7219                         // Otherwise just get the value from the style object
7220                         return style[ name ];
7221                 }
7222         },
7223
7224         css: function( elem, name, extra ) {
7225                 var ret, hooks;
7226
7227                 // Make sure that we're working with the right name
7228                 name = jQuery.camelCase( name );
7229                 hooks = jQuery.cssHooks[ name ];
7230                 name = jQuery.cssProps[ name ] || name;
7231
7232                 // cssFloat needs a special treatment
7233                 if ( name === "cssFloat" ) {
7234                         name = "float";
7235                 }
7236
7237                 // If a hook was provided get the computed value from there
7238                 if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
7239                         return ret;
7240
7241                 // Otherwise, if a way to get the computed value exists, use that
7242                 } else if ( curCSS ) {
7243                         return curCSS( elem, name );
7244                 }
7245         },
7246
7247         // A method for quickly swapping in/out CSS properties to get correct calculations
7248         swap: function( elem, options, callback ) {
7249                 var old = {};
7250
7251                 // Remember the old values, and insert the new ones
7252                 for ( var name in options ) {
7253                         old[ name ] = elem.style[ name ];
7254                         elem.style[ name ] = options[ name ];
7255                 }
7256
7257                 callback.call( elem );
7258
7259                 // Revert the old values
7260                 for ( name in options ) {
7261                         elem.style[ name ] = old[ name ];
7262                 }
7263         }
7264 });
7265
7266 // DEPRECATED, Use jQuery.css() instead
7267 jQuery.curCSS = jQuery.css;
7268
7269 jQuery.each(["height", "width"], function( i, name ) {
7270         jQuery.cssHooks[ name ] = {
7271                 get: function( elem, computed, extra ) {
7272                         var val;
7273
7274                         if ( computed ) {
7275                                 if ( elem.offsetWidth !== 0 ) {
7276                                         return getWH( elem, name, extra );
7277                                 } else {
7278                                         jQuery.swap( elem, cssShow, function() {
7279                                                 val = getWH( elem, name, extra );
7280                                         });
7281                                 }
7282
7283                                 return val;
7284                         }
7285                 },
7286
7287                 set: function( elem, value ) {
7288                         if ( rnumpx.test( value ) ) {
7289                                 // ignore negative width and height values #1599
7290                                 value = parseFloat( value );
7291
7292                                 if ( value >= 0 ) {
7293                                         return value + "px";
7294                                 }
7295
7296                         } else {
7297                                 return value;
7298                         }
7299                 }
7300         };
7301 });
7302
7303 if ( !jQuery.support.opacity ) {
7304         jQuery.cssHooks.opacity = {
7305                 get: function( elem, computed ) {
7306                         // IE uses filters for opacity
7307                         return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7308                                 ( parseFloat( RegExp.$1 ) / 100 ) + "" :
7309                                 computed ? "1" : "";
7310                 },
7311
7312                 set: function( elem, value ) {
7313                         var style = elem.style,
7314                                 currentStyle = elem.currentStyle,
7315                                 opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
7316                                 filter = currentStyle && currentStyle.filter || style.filter || "";
7317
7318                         // IE has trouble with opacity if it does not have layout
7319                         // Force it by setting the zoom level
7320                         style.zoom = 1;
7321
7322                         // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
7323                         if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
7324
7325                                 // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
7326                                 // if "filter:" is present at all, clearType is disabled, we want to avoid this
7327                                 // style.removeAttribute is IE Only, but so apparently is this code path...
7328                                 style.removeAttribute( "filter" );
7329
7330                                 // if there there is no filter style applied in a css rule, we are done
7331                                 if ( currentStyle && !currentStyle.filter ) {
7332                                         return;
7333                                 }
7334                         }
7335
7336                         // otherwise, set new filter values
7337                         style.filter = ralpha.test( filter ) ?
7338                                 filter.replace( ralpha, opacity ) :
7339                                 filter + " " + opacity;
7340                 }
7341         };
7342 }
7343
7344 jQuery(function() {
7345         // This hook cannot be added until DOM ready because the support test
7346         // for it is not run until after DOM ready
7347         if ( !jQuery.support.reliableMarginRight ) {
7348                 jQuery.cssHooks.marginRight = {
7349                         get: function( elem, computed ) {
7350                                 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7351                                 // Work around by temporarily setting element display to inline-block
7352                                 var ret;
7353                                 jQuery.swap( elem, { "display": "inline-block" }, function() {
7354                                         if ( computed ) {
7355                                                 ret = curCSS( elem, "margin-right", "marginRight" );
7356                                         } else {
7357                                                 ret = elem.style.marginRight;
7358                                         }
7359                                 });
7360                                 return ret;
7361                         }
7362                 };
7363         }
7364 });
7365
7366 if ( document.defaultView && document.defaultView.getComputedStyle ) {
7367         getComputedStyle = function( elem, name ) {
7368                 var ret, defaultView, computedStyle;
7369
7370                 name = name.replace( rupper, "-$1" ).toLowerCase();
7371
7372                 if ( !(defaultView = elem.ownerDocument.defaultView) ) {
7373                         return undefined;
7374                 }
7375
7376                 if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
7377                         ret = computedStyle.getPropertyValue( name );
7378                         if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
7379                                 ret = jQuery.style( elem, name );
7380                         }
7381                 }
7382
7383                 return ret;
7384         };
7385 }
7386
7387 if ( document.documentElement.currentStyle ) {
7388         currentStyle = function( elem, name ) {
7389                 var left, rsLeft, uncomputed,
7390                         ret = elem.currentStyle && elem.currentStyle[ name ],
7391                         style = elem.style;
7392
7393                 // Avoid setting ret to empty string here
7394                 // so we don't default to auto
7395                 if ( ret === null && style && (uncomputed = style[ name ]) ) {
7396                         ret = uncomputed;
7397                 }
7398
7399                 // From the awesome hack by Dean Edwards
7400                 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
7401
7402                 // If we're not dealing with a regular pixel number
7403                 // but a number that has a weird ending, we need to convert it to pixels
7404                 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
7405
7406                         // Remember the original values
7407                         left = style.left;
7408                         rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
7409
7410                         // Put in the new values to get a computed value out
7411                         if ( rsLeft ) {
7412                                 elem.runtimeStyle.left = elem.currentStyle.left;
7413                         }
7414                         style.left = name === "fontSize" ? "1em" : ( ret || 0 );
7415                         ret = style.pixelLeft + "px";
7416
7417                         // Revert the changed values
7418                         style.left = left;
7419                         if ( rsLeft ) {
7420                                 elem.runtimeStyle.left = rsLeft;
7421                         }
7422                 }
7423
7424                 return ret === "" ? "auto" : ret;
7425         };
7426 }
7427
7428 curCSS = getComputedStyle || currentStyle;
7429
7430 function getWH( elem, name, extra ) {
7431
7432         // Start with offset property
7433         var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7434                 which = name === "width" ? cssWidth : cssHeight;
7435
7436         if ( val > 0 ) {
7437                 if ( extra !== "border" ) {
7438                         jQuery.each( which, function() {
7439                                 if ( !extra ) {
7440                                         val -= parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
7441                                 }
7442                                 if ( extra === "margin" ) {
7443                                         val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
7444                                 } else {
7445                                         val -= parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
7446                                 }
7447                         });
7448                 }
7449
7450                 return val + "px";
7451         }
7452
7453         // Fall back to computed then uncomputed css if necessary
7454         val = curCSS( elem, name, name );
7455         if ( val < 0 || val == null ) {
7456                 val = elem.style[ name ] || 0;
7457         }
7458         // Normalize "", auto, and prepare for extra
7459         val = parseFloat( val ) || 0;
7460
7461         // Add padding, border, margin
7462         if ( extra ) {
7463                 jQuery.each( which, function() {
7464                         val += parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
7465                         if ( extra !== "padding" ) {
7466                                 val += parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
7467                         }
7468                         if ( extra === "margin" ) {
7469                                 val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
7470                         }
7471                 });
7472         }
7473
7474         return val + "px";
7475 }
7476
7477 if ( jQuery.expr && jQuery.expr.filters ) {
7478         jQuery.expr.filters.hidden = function( elem ) {
7479                 var width = elem.offsetWidth,
7480                         height = elem.offsetHeight;
7481
7482                 return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7483         };
7484
7485         jQuery.expr.filters.visible = function( elem ) {
7486                 return !jQuery.expr.filters.hidden( elem );
7487         };
7488 }
7489
7490
7491
7492
7493 var r20 = /%20/g,
7494         rbracket = /\[\]$/,
7495         rCRLF = /\r?\n/g,
7496         rhash = /#.*$/,
7497         rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7498         rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
7499         // #7653, #8125, #8152: local protocol detection
7500         rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
7501         rnoContent = /^(?:GET|HEAD)$/,
7502         rprotocol = /^\/\//,
7503         rquery = /\?/,
7504         rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
7505         rselectTextarea = /^(?:select|textarea)/i,
7506         rspacesAjax = /\s+/,
7507         rts = /([?&])_=[^&]*/,
7508         rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
7509
7510         // Keep a copy of the old load method
7511         _load = jQuery.fn.load,
7512
7513         /* Prefilters
7514          * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7515          * 2) These are called:
7516          *    - BEFORE asking for a transport
7517          *    - AFTER param serialization (s.data is a string if s.processData is true)
7518          * 3) key is the dataType
7519          * 4) the catchall symbol "*" can be used
7520          * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7521          */
7522         prefilters = {},
7523
7524         /* Transports bindings
7525          * 1) key is the dataType
7526          * 2) the catchall symbol "*" can be used
7527          * 3) selection will start with transport dataType and THEN go to "*" if needed
7528          */
7529         transports = {},
7530
7531         // Document location
7532         ajaxLocation,
7533
7534         // Document location segments
7535         ajaxLocParts,
7536
7537         // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7538         allTypes = ["*/"] + ["*"];
7539
7540 // #8138, IE may throw an exception when accessing
7541 // a field from window.location if document.domain has been set
7542 try {
7543         ajaxLocation = location.href;
7544 } catch( e ) {
7545         // Use the href attribute of an A element
7546         // since IE will modify it given document.location
7547         ajaxLocation = document.createElement( "a" );
7548         ajaxLocation.href = "";
7549         ajaxLocation = ajaxLocation.href;
7550 }
7551
7552 // Segment location into parts
7553 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7554
7555 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7556 function addToPrefiltersOrTransports( structure ) {
7557
7558         // dataTypeExpression is optional and defaults to "*"
7559         return function( dataTypeExpression, func ) {
7560
7561                 if ( typeof dataTypeExpression !== "string" ) {
7562                         func = dataTypeExpression;
7563                         dataTypeExpression = "*";
7564                 }
7565
7566                 if ( jQuery.isFunction( func ) ) {
7567                         var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
7568                                 i = 0,
7569                                 length = dataTypes.length,
7570                                 dataType,
7571                                 list,
7572                                 placeBefore;
7573
7574                         // For each dataType in the dataTypeExpression
7575                         for ( ; i < length; i++ ) {
7576                                 dataType = dataTypes[ i ];
7577                                 // We control if we're asked to add before
7578                                 // any existing element
7579                                 placeBefore = /^\+/.test( dataType );
7580                                 if ( placeBefore ) {
7581                                         dataType = dataType.substr( 1 ) || "*";
7582                                 }
7583                                 list = structure[ dataType ] = structure[ dataType ] || [];
7584                                 // then we add to the structure accordingly
7585                                 list[ placeBefore ? "unshift" : "push" ]( func );
7586                         }
7587                 }
7588         };
7589 }
7590
7591 // Base inspection function for prefilters and transports
7592 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
7593                 dataType /* internal */, inspected /* internal */ ) {
7594
7595         dataType = dataType || options.dataTypes[ 0 ];
7596         inspected = inspected || {};
7597
7598         inspected[ dataType ] = true;
7599
7600         var list = structure[ dataType ],
7601                 i = 0,
7602                 length = list ? list.length : 0,
7603                 executeOnly = ( structure === prefilters ),
7604                 selection;
7605
7606         for ( ; i < length && ( executeOnly || !selection ); i++ ) {
7607                 selection = list[ i ]( options, originalOptions, jqXHR );
7608                 // If we got redirected to another dataType
7609                 // we try there if executing only and not done already
7610                 if ( typeof selection === "string" ) {
7611                         if ( !executeOnly || inspected[ selection ] ) {
7612                                 selection = undefined;
7613                         } else {
7614                                 options.dataTypes.unshift( selection );
7615                                 selection = inspectPrefiltersOrTransports(
7616                                                 structure, options, originalOptions, jqXHR, selection, inspected );
7617                         }
7618                 }
7619         }
7620         // If we're only executing or nothing was selected
7621         // we try the catchall dataType if not done already
7622         if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
7623                 selection = inspectPrefiltersOrTransports(
7624                                 structure, options, originalOptions, jqXHR, "*", inspected );
7625         }
7626         // unnecessary when only executing (prefilters)
7627         // but it'll be ignored by the caller in that case
7628         return selection;
7629 }
7630
7631 // A special extend for ajax options
7632 // that takes "flat" options (not to be deep extended)
7633 // Fixes #9887
7634 function ajaxExtend( target, src ) {
7635         var key, deep,
7636                 flatOptions = jQuery.ajaxSettings.flatOptions || {};
7637         for ( key in src ) {
7638                 if ( src[ key ] !== undefined ) {
7639                         ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
7640                 }
7641         }
7642         if ( deep ) {
7643                 jQuery.extend( true, target, deep );
7644         }
7645 }
7646
7647 jQuery.fn.extend({
7648         load: function( url, params, callback ) {
7649                 if ( typeof url !== "string" && _load ) {
7650                         return _load.apply( this, arguments );
7651
7652                 // Don't do a request if no elements are being requested
7653                 } else if ( !this.length ) {
7654                         return this;
7655                 }
7656
7657                 var off = url.indexOf( " " );
7658                 if ( off >= 0 ) {
7659                         var selector = url.slice( off, url.length );
7660                         url = url.slice( 0, off );
7661                 }
7662
7663                 // Default to a GET request
7664                 var type = "GET";
7665
7666                 // If the second parameter was provided
7667                 if ( params ) {
7668                         // If it's a function
7669                         if ( jQuery.isFunction( params ) ) {
7670                                 // We assume that it's the callback
7671                                 callback = params;
7672                                 params = undefined;
7673
7674                         // Otherwise, build a param string
7675                         } else if ( typeof params === "object" ) {
7676                                 params = jQuery.param( params, jQuery.ajaxSettings.traditional );
7677                                 type = "POST";
7678                         }
7679                 }
7680
7681                 var self = this;
7682
7683                 // Request the remote document
7684                 jQuery.ajax({
7685                         url: url,
7686                         type: type,
7687                         dataType: "html",
7688                         data: params,
7689                         // Complete callback (responseText is used internally)
7690                         complete: function( jqXHR, status, responseText ) {
7691                                 // Store the response as specified by the jqXHR object
7692                                 responseText = jqXHR.responseText;
7693                                 // If successful, inject the HTML into all the matched elements
7694                                 if ( jqXHR.isResolved() ) {
7695                                         // #4825: Get the actual response in case
7696                                         // a dataFilter is present in ajaxSettings
7697                                         jqXHR.done(function( r ) {
7698                                                 responseText = r;
7699                                         });
7700                                         // See if a selector was specified
7701                                         self.html( selector ?
7702                                                 // Create a dummy div to hold the results
7703                                                 jQuery("<div>")
7704                                                         // inject the contents of the document in, removing the scripts
7705                                                         // to avoid any 'Permission Denied' errors in IE
7706                                                         .append(responseText.replace(rscript, ""))
7707
7708                                                         // Locate the specified elements
7709                                                         .find(selector) :
7710
7711                                                 // If not, just inject the full result
7712                                                 responseText );
7713                                 }
7714
7715                                 if ( callback ) {
7716                                         self.each( callback, [ responseText, status, jqXHR ] );
7717                                 }
7718                         }
7719                 });
7720
7721                 return this;
7722         },
7723
7724         serialize: function() {
7725                 return jQuery.param( this.serializeArray() );
7726         },
7727
7728         serializeArray: function() {
7729                 return this.map(function(){
7730                         return this.elements ? jQuery.makeArray( this.elements ) : this;
7731                 })
7732                 .filter(function(){
7733                         return this.name && !this.disabled &&
7734                                 ( this.checked || rselectTextarea.test( this.nodeName ) ||
7735                                         rinput.test( this.type ) );
7736                 })
7737                 .map(function( i, elem ){
7738                         var val = jQuery( this ).val();
7739
7740                         return val == null ?
7741                                 null :
7742                                 jQuery.isArray( val ) ?
7743                                         jQuery.map( val, function( val, i ){
7744                                                 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7745                                         }) :
7746                                         { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7747                 }).get();
7748         }
7749 });
7750
7751 // Attach a bunch of functions for handling common AJAX events
7752 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
7753         jQuery.fn[ o ] = function( f ){
7754                 return this.bind( o, f );
7755         };
7756 });
7757
7758 jQuery.each( [ "get", "post" ], function( i, method ) {
7759         jQuery[ method ] = function( url, data, callback, type ) {
7760                 // shift arguments if data argument was omitted
7761                 if ( jQuery.isFunction( data ) ) {
7762                         type = type || callback;
7763                         callback = data;
7764                         data = undefined;
7765                 }
7766
7767                 return jQuery.ajax({
7768                         type: method,
7769                         url: url,
7770                         data: data,
7771                         success: callback,
7772                         dataType: type
7773                 });
7774         };
7775 });
7776
7777 jQuery.extend({
7778
7779         getScript: function( url, callback ) {
7780                 return jQuery.get( url, undefined, callback, "script" );
7781         },
7782
7783         getJSON: function( url, data, callback ) {
7784                 return jQuery.get( url, data, callback, "json" );
7785         },
7786
7787         // Creates a full fledged settings object into target
7788         // with both ajaxSettings and settings fields.
7789         // If target is omitted, writes into ajaxSettings.
7790         ajaxSetup: function( target, settings ) {
7791                 if ( settings ) {
7792                         // Building a settings object
7793                         ajaxExtend( target, jQuery.ajaxSettings );
7794                 } else {
7795                         // Extending ajaxSettings
7796                         settings = target;
7797                         target = jQuery.ajaxSettings;
7798                 }
7799                 ajaxExtend( target, settings );
7800                 return target;
7801         },
7802
7803         ajaxSettings: {
7804                 url: ajaxLocation,
7805                 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7806                 global: true,
7807                 type: "GET",
7808                 contentType: "application/x-www-form-urlencoded",
7809                 processData: true,
7810                 async: true,
7811                 /*
7812                 timeout: 0,
7813                 data: null,
7814                 dataType: null,
7815                 username: null,
7816                 password: null,
7817                 cache: null,
7818                 traditional: false,
7819                 headers: {},
7820                 */
7821
7822                 accepts: {
7823                         xml: "application/xml, text/xml",
7824                         html: "text/html",
7825                         text: "text/plain",
7826                         json: "application/json, text/javascript",
7827                         "*": allTypes
7828                 },
7829
7830                 contents: {
7831                         xml: /xml/,
7832                         html: /html/,
7833                         json: /json/
7834                 },
7835
7836                 responseFields: {
7837                         xml: "responseXML",
7838                         text: "responseText"
7839                 },
7840
7841                 // List of data converters
7842                 // 1) key format is "source_type destination_type" (a single space in-between)
7843                 // 2) the catchall symbol "*" can be used for source_type
7844                 converters: {
7845
7846                         // Convert anything to text
7847                         "* text": window.String,
7848
7849                         // Text to html (true = no transformation)
7850                         "text html": true,
7851
7852                         // Evaluate text as a json expression
7853                         "text json": jQuery.parseJSON,
7854
7855                         // Parse text as xml
7856                         "text xml": jQuery.parseXML
7857                 },
7858
7859                 // For options that shouldn't be deep extended:
7860                 // you can add your own custom options here if
7861                 // and when you create one that shouldn't be
7862                 // deep extended (see ajaxExtend)
7863                 flatOptions: {
7864                         context: true,
7865                         url: true
7866                 }
7867         },
7868
7869         ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7870         ajaxTransport: addToPrefiltersOrTransports( transports ),
7871
7872         // Main method
7873         ajax: function( url, options ) {
7874
7875                 // If url is an object, simulate pre-1.5 signature
7876                 if ( typeof url === "object" ) {
7877                         options = url;
7878                         url = undefined;
7879                 }
7880
7881                 // Force options to be an object
7882                 options = options || {};
7883
7884                 var // Create the final options object
7885                         s = jQuery.ajaxSetup( {}, options ),
7886                         // Callbacks context
7887                         callbackContext = s.context || s,
7888                         // Context for global events
7889                         // It's the callbackContext if one was provided in the options
7890                         // and if it's a DOM node or a jQuery collection
7891                         globalEventContext = callbackContext !== s &&
7892                                 ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
7893                                                 jQuery( callbackContext ) : jQuery.event,
7894                         // Deferreds
7895                         deferred = jQuery.Deferred(),
7896                         completeDeferred = jQuery.Callbacks( "once memory" ),
7897                         // Status-dependent callbacks
7898                         statusCode = s.statusCode || {},
7899                         // ifModified key
7900                         ifModifiedKey,
7901                         // Headers (they are sent all at once)
7902                         requestHeaders = {},
7903                         requestHeadersNames = {},
7904                         // Response headers
7905                         responseHeadersString,
7906                         responseHeaders,
7907                         // transport
7908                         transport,
7909                         // timeout handle
7910                         timeoutTimer,
7911                         // Cross-domain detection vars
7912                         parts,
7913                         // The jqXHR state
7914                         state = 0,
7915                         // To know if global events are to be dispatched
7916                         fireGlobals,
7917                         // Loop variable
7918                         i,
7919                         // Fake xhr
7920                         jqXHR = {
7921
7922                                 readyState: 0,
7923
7924                                 // Caches the header
7925                                 setRequestHeader: function( name, value ) {
7926                                         if ( !state ) {
7927                                                 var lname = name.toLowerCase();
7928                                                 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7929                                                 requestHeaders[ name ] = value;
7930                                         }
7931                                         return this;
7932                                 },
7933
7934                                 // Raw string
7935                                 getAllResponseHeaders: function() {
7936                                         return state === 2 ? responseHeadersString : null;
7937                                 },
7938
7939                                 // Builds headers hashtable if needed
7940                                 getResponseHeader: function( key ) {
7941                                         var match;
7942                                         if ( state === 2 ) {
7943                                                 if ( !responseHeaders ) {
7944                                                         responseHeaders = {};
7945                                                         while( ( match = rheaders.exec( responseHeadersString ) ) ) {
7946                                                                 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7947                                                         }
7948                                                 }
7949                                                 match = responseHeaders[ key.toLowerCase() ];
7950                                         }
7951                                         return match === undefined ? null : match;
7952                                 },
7953
7954                                 // Overrides response content-type header
7955                                 overrideMimeType: function( type ) {
7956                                         if ( !state ) {
7957                                                 s.mimeType = type;
7958                                         }
7959                                         return this;
7960                                 },
7961
7962                                 // Cancel the request
7963                                 abort: function( statusText ) {
7964                                         statusText = statusText || "abort";
7965                                         if ( transport ) {
7966                                                 transport.abort( statusText );
7967                                         }
7968                                         done( 0, statusText );
7969                                         return this;
7970                                 }
7971                         };
7972
7973                 // Callback for when everything is done
7974                 // It is defined here because jslint complains if it is declared
7975                 // at the end of the function (which would be more logical and readable)
7976                 function done( status, nativeStatusText, responses, headers ) {
7977
7978                         // Called once
7979                         if ( state === 2 ) {
7980                                 return;
7981                         }
7982
7983                         // State is "done" now
7984                         state = 2;
7985
7986                         // Clear timeout if it exists
7987                         if ( timeoutTimer ) {
7988                                 clearTimeout( timeoutTimer );
7989                         }
7990
7991                         // Dereference transport for early garbage collection
7992                         // (no matter how long the jqXHR object will be used)
7993                         transport = undefined;
7994
7995                         // Cache response headers
7996                         responseHeadersString = headers || "";
7997
7998                         // Set readyState
7999                         jqXHR.readyState = status > 0 ? 4 : 0;
8000
8001                         var isSuccess,
8002                                 success,
8003                                 error,
8004                                 statusText = nativeStatusText,
8005                                 response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
8006                                 lastModified,
8007                                 etag;
8008
8009                         // If successful, handle type chaining
8010                         if ( status >= 200 && status < 300 || status === 304 ) {
8011
8012                                 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8013                                 if ( s.ifModified ) {
8014
8015                                         if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
8016                                                 jQuery.lastModified[ ifModifiedKey ] = lastModified;
8017                                         }
8018                                         if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
8019                                                 jQuery.etag[ ifModifiedKey ] = etag;
8020                                         }
8021                                 }
8022
8023                                 // If not modified
8024                                 if ( status === 304 ) {
8025
8026                                         statusText = "notmodified";
8027                                         isSuccess = true;
8028
8029                                 // If we have data
8030                                 } else {
8031
8032                                         try {
8033                                                 success = ajaxConvert( s, response );
8034                                                 statusText = "success";
8035                                                 isSuccess = true;
8036                                         } catch(e) {
8037                                                 // We have a parsererror
8038                                                 statusText = "parsererror";
8039                                                 error = e;
8040                                         }
8041                                 }
8042                         } else {
8043                                 // We extract error from statusText
8044                                 // then normalize statusText and status for non-aborts
8045                                 error = statusText;
8046                                 if ( !statusText || status ) {
8047                                         statusText = "error";
8048                                         if ( status < 0 ) {
8049                                                 status = 0;
8050                                         }
8051                                 }
8052                         }
8053
8054                         // Set data for the fake xhr object
8055                         jqXHR.status = status;
8056                         jqXHR.statusText = "" + ( nativeStatusText || statusText );
8057
8058                         // Success/Error
8059                         if ( isSuccess ) {
8060                                 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8061                         } else {
8062                                 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8063                         }
8064
8065                         // Status-dependent callbacks
8066                         jqXHR.statusCode( statusCode );
8067                         statusCode = undefined;
8068
8069                         if ( fireGlobals ) {
8070                                 globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
8071                                                 [ jqXHR, s, isSuccess ? success : error ] );
8072                         }
8073
8074                         // Complete
8075                         completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8076
8077                         if ( fireGlobals ) {
8078                                 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8079                                 // Handle the global AJAX counter
8080                                 if ( !( --jQuery.active ) ) {
8081                                         jQuery.event.trigger( "ajaxStop" );
8082                                 }
8083                         }
8084                 }
8085
8086                 // Attach deferreds
8087                 deferred.promise( jqXHR );
8088                 jqXHR.success = jqXHR.done;
8089                 jqXHR.error = jqXHR.fail;
8090                 jqXHR.complete = completeDeferred.add;
8091
8092                 // Status-dependent callbacks
8093                 jqXHR.statusCode = function( map ) {
8094                         if ( map ) {
8095                                 var tmp;
8096                                 if ( state < 2 ) {
8097                                         for ( tmp in map ) {
8098                                                 statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
8099                                         }
8100                                 } else {
8101                                         tmp = map[ jqXHR.status ];
8102                                         jqXHR.then( tmp, tmp );
8103                                 }
8104                         }
8105                         return this;
8106                 };
8107
8108                 // Remove hash character (#7531: and string promotion)
8109                 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
8110                 // We also use the url parameter if available
8111                 s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
8112
8113                 // Extract dataTypes list
8114                 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
8115
8116                 // Determine if a cross-domain request is in order
8117                 if ( s.crossDomain == null ) {
8118                         parts = rurl.exec( s.url.toLowerCase() );
8119                         s.crossDomain = !!( parts &&
8120                                 ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
8121                                         ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
8122                                                 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
8123                         );
8124                 }
8125
8126                 // Convert data if not already a string
8127                 if ( s.data && s.processData && typeof s.data !== "string" ) {
8128                         s.data = jQuery.param( s.data, s.traditional );
8129                 }
8130
8131                 // Apply prefilters
8132                 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
8133
8134                 // If request was aborted inside a prefiler, stop there
8135                 if ( state === 2 ) {
8136                         return false;
8137                 }
8138
8139                 // We can fire global events as of now if asked to
8140                 fireGlobals = s.global;
8141
8142                 // Uppercase the type
8143                 s.type = s.type.toUpperCase();
8144
8145                 // Determine if request has content
8146                 s.hasContent = !rnoContent.test( s.type );
8147
8148                 // Watch for a new set of requests
8149                 if ( fireGlobals && jQuery.active++ === 0 ) {
8150                         jQuery.event.trigger( "ajaxStart" );
8151                 }
8152
8153                 // More options handling for requests with no content
8154                 if ( !s.hasContent ) {
8155
8156                         // If data is available, append data to url
8157                         if ( s.data ) {
8158                                 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
8159                                 // #9682: remove data so that it's not used in an eventual retry
8160                                 delete s.data;
8161                         }
8162
8163                         // Get ifModifiedKey before adding the anti-cache parameter
8164                         ifModifiedKey = s.url;
8165
8166                         // Add anti-cache in url if needed
8167                         if ( s.cache === false ) {
8168
8169                                 var ts = jQuery.now(),
8170                                         // try replacing _= if it is there
8171                                         ret = s.url.replace( rts, "$1_=" + ts );
8172
8173                                 // if nothing was replaced, add timestamp to the end
8174                                 s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
8175                         }
8176                 }
8177
8178                 // Set the correct header, if data is being sent
8179                 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
8180                         jqXHR.setRequestHeader( "Content-Type", s.contentType );
8181                 }
8182
8183                 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8184                 if ( s.ifModified ) {
8185                         ifModifiedKey = ifModifiedKey || s.url;
8186                         if ( jQuery.lastModified[ ifModifiedKey ] ) {
8187                                 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
8188                         }
8189                         if ( jQuery.etag[ ifModifiedKey ] ) {
8190                                 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
8191                         }
8192                 }
8193
8194                 // Set the Accepts header for the server, depending on the dataType
8195                 jqXHR.setRequestHeader(
8196                         "Accept",
8197                         s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
8198                                 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
8199                                 s.accepts[ "*" ]
8200                 );
8201
8202                 // Check for headers option
8203                 for ( i in s.headers ) {
8204                         jqXHR.setRequestHeader( i, s.headers[ i ] );
8205                 }
8206
8207                 // Allow custom headers/mimetypes and early abort
8208                 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
8209                                 // Abort if not done already
8210                                 jqXHR.abort();
8211                                 return false;
8212
8213                 }
8214
8215                 // Install callbacks on deferreds
8216                 for ( i in { success: 1, error: 1, complete: 1 } ) {
8217                         jqXHR[ i ]( s[ i ] );
8218                 }
8219
8220                 // Get transport
8221                 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
8222
8223                 // If no transport, we auto-abort
8224                 if ( !transport ) {
8225                         done( -1, "No Transport" );
8226                 } else {
8227                         jqXHR.readyState = 1;
8228                         // Send global event
8229                         if ( fireGlobals ) {
8230                                 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
8231                         }
8232                         // Timeout
8233                         if ( s.async && s.timeout > 0 ) {
8234                                 timeoutTimer = setTimeout( function(){
8235                                         jqXHR.abort( "timeout" );
8236                                 }, s.timeout );
8237                         }
8238
8239                         try {
8240                                 state = 1;
8241                                 transport.send( requestHeaders, done );
8242                         } catch (e) {
8243                                 // Propagate exception as error if not done
8244                                 if ( state < 2 ) {
8245                                         done( -1, e );
8246                                 // Simply rethrow otherwise
8247                                 } else {
8248                                         jQuery.error( e );
8249                                 }
8250                         }
8251                 }
8252
8253                 return jqXHR;
8254         },
8255
8256         // Serialize an array of form elements or a set of
8257         // key/values into a query string
8258         param: function( a, traditional ) {
8259                 var s = [],
8260                         add = function( key, value ) {
8261                                 // If value is a function, invoke it and return its value
8262                                 value = jQuery.isFunction( value ) ? value() : value;
8263                                 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
8264                         };
8265
8266                 // Set traditional to true for jQuery <= 1.3.2 behavior.
8267                 if ( traditional === undefined ) {
8268                         traditional = jQuery.ajaxSettings.traditional;
8269                 }
8270
8271                 // If an array was passed in, assume that it is an array of form elements.
8272                 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
8273                         // Serialize the form elements
8274                         jQuery.each( a, function() {
8275                                 add( this.name, this.value );
8276                         });
8277
8278                 } else {
8279                         // If traditional, encode the "old" way (the way 1.3.2 or older
8280                         // did it), otherwise encode params recursively.
8281                         for ( var prefix in a ) {
8282                                 buildParams( prefix, a[ prefix ], traditional, add );
8283                         }
8284                 }
8285
8286                 // Return the resulting serialization
8287                 return s.join( "&" ).replace( r20, "+" );
8288         }
8289 });
8290
8291 function buildParams( prefix, obj, traditional, add ) {
8292         if ( jQuery.isArray( obj ) ) {
8293                 // Serialize array item.
8294                 jQuery.each( obj, function( i, v ) {
8295                         if ( traditional || rbracket.test( prefix ) ) {
8296                                 // Treat each array item as a scalar.
8297                                 add( prefix, v );
8298
8299                         } else {
8300                                 // If array item is non-scalar (array or object), encode its
8301                                 // numeric index to resolve deserialization ambiguity issues.
8302                                 // Note that rack (as of 1.0.0) can't currently deserialize
8303                                 // nested arrays properly, and attempting to do so may cause
8304                                 // a server error. Possible fixes are to modify rack's
8305                                 // deserialization algorithm or to provide an option or flag
8306                                 // to force array serialization to be shallow.
8307                                 buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
8308                         }
8309                 });
8310
8311         } else if ( !traditional && obj != null && typeof obj === "object" ) {
8312                 // Serialize object item.
8313                 for ( var name in obj ) {
8314                         buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8315                 }
8316
8317         } else {
8318                 // Serialize scalar item.
8319                 add( prefix, obj );
8320         }
8321 }
8322
8323 // This is still on the jQuery object... for now
8324 // Want to move this to jQuery.ajax some day
8325 jQuery.extend({
8326
8327         // Counter for holding the number of active queries
8328         active: 0,
8329
8330         // Last-Modified header cache for next request
8331         lastModified: {},
8332         etag: {}
8333
8334 });
8335
8336 /* Handles responses to an ajax request:
8337  * - sets all responseXXX fields accordingly
8338  * - finds the right dataType (mediates between content-type and expected dataType)
8339  * - returns the corresponding response
8340  */
8341 function ajaxHandleResponses( s, jqXHR, responses ) {
8342
8343         var contents = s.contents,
8344                 dataTypes = s.dataTypes,
8345                 responseFields = s.responseFields,
8346                 ct,
8347                 type,
8348                 finalDataType,
8349                 firstDataType;
8350
8351         // Fill responseXXX fields
8352         for ( type in responseFields ) {
8353                 if ( type in responses ) {
8354                         jqXHR[ responseFields[type] ] = responses[ type ];
8355                 }
8356         }
8357
8358         // Remove auto dataType and get content-type in the process
8359         while( dataTypes[ 0 ] === "*" ) {
8360                 dataTypes.shift();
8361                 if ( ct === undefined ) {
8362                         ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
8363                 }
8364         }
8365
8366         // Check if we're dealing with a known content-type
8367         if ( ct ) {
8368                 for ( type in contents ) {
8369                         if ( contents[ type ] && contents[ type ].test( ct ) ) {
8370                                 dataTypes.unshift( type );
8371                                 break;
8372                         }
8373                 }
8374         }
8375
8376         // Check to see if we have a response for the expected dataType
8377         if ( dataTypes[ 0 ] in responses ) {
8378                 finalDataType = dataTypes[ 0 ];
8379         } else {
8380                 // Try convertible dataTypes
8381                 for ( type in responses ) {
8382                         if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8383                                 finalDataType = type;
8384                                 break;
8385                         }
8386                         if ( !firstDataType ) {
8387                                 firstDataType = type;
8388                         }
8389                 }
8390                 // Or just use first one
8391                 finalDataType = finalDataType || firstDataType;
8392         }
8393
8394         // If we found a dataType
8395         // We add the dataType to the list if needed
8396         // and return the corresponding response
8397         if ( finalDataType ) {
8398                 if ( finalDataType !== dataTypes[ 0 ] ) {
8399                         dataTypes.unshift( finalDataType );
8400                 }
8401                 return responses[ finalDataType ];
8402         }
8403 }
8404
8405 // Chain conversions given the request and the original response
8406 function ajaxConvert( s, response ) {
8407
8408         // Apply the dataFilter if provided
8409         if ( s.dataFilter ) {
8410                 response = s.dataFilter( response, s.dataType );
8411         }
8412
8413         var dataTypes = s.dataTypes,
8414                 converters = {},
8415                 i,
8416                 key,
8417                 length = dataTypes.length,
8418                 tmp,
8419                 // Current and previous dataTypes
8420                 current = dataTypes[ 0 ],
8421                 prev,
8422                 // Conversion expression
8423                 conversion,
8424                 // Conversion function
8425                 conv,
8426                 // Conversion functions (transitive conversion)
8427                 conv1,
8428                 conv2;
8429
8430         // For each dataType in the chain
8431         for ( i = 1; i < length; i++ ) {
8432
8433                 // Create converters map
8434                 // with lowercased keys
8435                 if ( i === 1 ) {
8436                         for ( key in s.converters ) {
8437                                 if ( typeof key === "string" ) {
8438                                         converters[ key.toLowerCase() ] = s.converters[ key ];
8439                                 }
8440                         }
8441                 }
8442
8443                 // Get the dataTypes
8444                 prev = current;
8445                 current = dataTypes[ i ];
8446
8447                 // If current is auto dataType, update it to prev
8448                 if ( current === "*" ) {
8449                         current = prev;
8450                 // If no auto and dataTypes are actually different
8451                 } else if ( prev !== "*" && prev !== current ) {
8452
8453                         // Get the converter
8454                         conversion = prev + " " + current;
8455                         conv = converters[ conversion ] || converters[ "* " + current ];
8456
8457                         // If there is no direct converter, search transitively
8458                         if ( !conv ) {
8459                                 conv2 = undefined;
8460                                 for ( conv1 in converters ) {
8461                                         tmp = conv1.split( " " );
8462                                         if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
8463                                                 conv2 = converters[ tmp[1] + " " + current ];
8464                                                 if ( conv2 ) {
8465                                                         conv1 = converters[ conv1 ];
8466                                                         if ( conv1 === true ) {
8467                                                                 conv = conv2;
8468                                                         } else if ( conv2 === true ) {
8469                                                                 conv = conv1;
8470                                                         }
8471                                                         break;
8472                                                 }
8473                                         }
8474                                 }
8475                         }
8476                         // If we found no converter, dispatch an error
8477                         if ( !( conv || conv2 ) ) {
8478                                 jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
8479                         }
8480                         // If found converter is not an equivalence
8481                         if ( conv !== true ) {
8482                                 // Convert with 1 or 2 converters accordingly
8483                                 response = conv ? conv( response ) : conv2( conv1(response) );
8484                         }
8485                 }
8486         }
8487         return response;
8488 }
8489
8490
8491
8492
8493 var jsc = jQuery.now(),
8494         jsre = /(\=)\?(&|$)|\?\?/i;
8495
8496 // Default jsonp settings
8497 jQuery.ajaxSetup({
8498         jsonp: "callback",
8499         jsonpCallback: function() {
8500                 return jQuery.expando + "_" + ( jsc++ );
8501         }
8502 });
8503
8504 // Detect, normalize options and install callbacks for jsonp requests
8505 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8506
8507         var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
8508                 ( typeof s.data === "string" );
8509
8510         if ( s.dataTypes[ 0 ] === "jsonp" ||
8511                 s.jsonp !== false && ( jsre.test( s.url ) ||
8512                                 inspectData && jsre.test( s.data ) ) ) {
8513
8514                 var responseContainer,
8515                         jsonpCallback = s.jsonpCallback =
8516                                 jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
8517                         previous = window[ jsonpCallback ],
8518                         url = s.url,
8519                         data = s.data,
8520                         replace = "$1" + jsonpCallback + "$2";
8521
8522                 if ( s.jsonp !== false ) {
8523                         url = url.replace( jsre, replace );
8524                         if ( s.url === url ) {
8525                                 if ( inspectData ) {
8526                                         data = data.replace( jsre, replace );
8527                                 }
8528                                 if ( s.data === data ) {
8529                                         // Add callback manually
8530                                         url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
8531                                 }
8532                         }
8533                 }
8534
8535                 s.url = url;
8536                 s.data = data;
8537
8538                 // Install callback
8539                 window[ jsonpCallback ] = function( response ) {
8540                         responseContainer = [ response ];
8541                 };
8542
8543                 // Clean-up function
8544                 jqXHR.always(function() {
8545                         // Set callback back to previous value
8546                         window[ jsonpCallback ] = previous;
8547                         // Call if it was a function and we have a response
8548                         if ( responseContainer && jQuery.isFunction( previous ) ) {
8549                                 window[ jsonpCallback ]( responseContainer[ 0 ] );
8550                         }
8551                 });
8552
8553                 // Use data converter to retrieve json after script execution
8554                 s.converters["script json"] = function() {
8555                         if ( !responseContainer ) {
8556                                 jQuery.error( jsonpCallback + " was not called" );
8557                         }
8558                         return responseContainer[ 0 ];
8559                 };
8560
8561                 // force json dataType
8562                 s.dataTypes[ 0 ] = "json";
8563
8564                 // Delegate to script
8565                 return "script";
8566         }
8567 });
8568
8569
8570
8571
8572 // Install script dataType
8573 jQuery.ajaxSetup({
8574         accepts: {
8575                 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8576         },
8577         contents: {
8578                 script: /javascript|ecmascript/
8579         },
8580         converters: {
8581                 "text script": function( text ) {
8582                         jQuery.globalEval( text );
8583                         return text;
8584                 }
8585         }
8586 });
8587
8588 // Handle cache's special case and global
8589 jQuery.ajaxPrefilter( "script", function( s ) {
8590         if ( s.cache === undefined ) {
8591                 s.cache = false;
8592         }
8593         if ( s.crossDomain ) {
8594                 s.type = "GET";
8595                 s.global = false;
8596         }
8597 });
8598
8599 // Bind script tag hack transport
8600 jQuery.ajaxTransport( "script", function(s) {
8601
8602         // This transport only deals with cross domain requests
8603         if ( s.crossDomain ) {
8604
8605                 var script,
8606                         head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
8607
8608                 return {
8609
8610                         send: function( _, callback ) {
8611
8612                                 script = document.createElement( "script" );
8613
8614                                 script.async = "async";
8615
8616                                 if ( s.scriptCharset ) {
8617                                         script.charset = s.scriptCharset;
8618                                 }
8619
8620                                 script.src = s.url;
8621
8622                                 // Attach handlers for all browsers
8623                                 script.onload = script.onreadystatechange = function( _, isAbort ) {
8624
8625                                         if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8626
8627                                                 // Handle memory leak in IE
8628                                                 script.onload = script.onreadystatechange = null;
8629
8630                                                 // Remove the script
8631                                                 if ( head && script.parentNode ) {
8632                                                         head.removeChild( script );
8633                                                 }
8634
8635                                                 // Dereference the script
8636                                                 script = undefined;
8637
8638                                                 // Callback if not abort
8639                                                 if ( !isAbort ) {
8640                                                         callback( 200, "success" );
8641                                                 }
8642                                         }
8643                                 };
8644                                 // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
8645                                 // This arises when a base node is used (#2709 and #4378).
8646                                 head.insertBefore( script, head.firstChild );
8647                         },
8648
8649                         abort: function() {
8650                                 if ( script ) {
8651                                         script.onload( 0, 1 );
8652                                 }
8653                         }
8654                 };
8655         }
8656 });
8657
8658
8659
8660
8661 var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8662         xhrOnUnloadAbort = window.ActiveXObject ? function() {
8663                 // Abort all pending requests
8664                 for ( var key in xhrCallbacks ) {
8665                         xhrCallbacks[ key ]( 0, 1 );
8666                 }
8667         } : false,
8668         xhrId = 0,
8669         xhrCallbacks;
8670
8671 // Functions to create xhrs
8672 function createStandardXHR() {
8673         try {
8674                 return new window.XMLHttpRequest();
8675         } catch( e ) {}
8676 }
8677
8678 function createActiveXHR() {
8679         try {
8680                 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
8681         } catch( e ) {}
8682 }
8683
8684 // Create the request object
8685 // (This is still attached to ajaxSettings for backward compatibility)
8686 jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8687         /* Microsoft failed to properly
8688          * implement the XMLHttpRequest in IE7 (can't request local files),
8689          * so we use the ActiveXObject when it is available
8690          * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8691          * we need a fallback.
8692          */
8693         function() {
8694                 return !this.isLocal && createStandardXHR() || createActiveXHR();
8695         } :
8696         // For all other browsers, use the standard XMLHttpRequest object
8697         createStandardXHR;
8698
8699 // Determine support properties
8700 (function( xhr ) {
8701         jQuery.extend( jQuery.support, {
8702                 ajax: !!xhr,
8703                 cors: !!xhr && ( "withCredentials" in xhr )
8704         });
8705 })( jQuery.ajaxSettings.xhr() );
8706
8707 // Create transport if the browser can provide an xhr
8708 if ( jQuery.support.ajax ) {
8709
8710         jQuery.ajaxTransport(function( s ) {
8711                 // Cross domain only allowed if supported through XMLHttpRequest
8712                 if ( !s.crossDomain || jQuery.support.cors ) {
8713
8714                         var callback;
8715
8716                         return {
8717                                 send: function( headers, complete ) {
8718
8719                                         // Get a new xhr
8720                                         var xhr = s.xhr(),
8721                                                 handle,
8722                                                 i;
8723
8724                                         // Open the socket
8725                                         // Passing null username, generates a login popup on Opera (#2865)
8726                                         if ( s.username ) {
8727                                                 xhr.open( s.type, s.url, s.async, s.username, s.password );
8728                                         } else {
8729                                                 xhr.open( s.type, s.url, s.async );
8730                                         }
8731
8732                                         // Apply custom fields if provided
8733                                         if ( s.xhrFields ) {
8734                                                 for ( i in s.xhrFields ) {
8735                                                         xhr[ i ] = s.xhrFields[ i ];
8736                                                 }
8737                                         }
8738
8739                                         // Override mime type if needed
8740                                         if ( s.mimeType && xhr.overrideMimeType ) {
8741                                                 xhr.overrideMimeType( s.mimeType );
8742                                         }
8743
8744                                         // X-Requested-With header
8745                                         // For cross-domain requests, seeing as conditions for a preflight are
8746                                         // akin to a jigsaw puzzle, we simply never set it to be sure.
8747                                         // (it can always be set on a per-request basis or even using ajaxSetup)
8748                                         // For same-domain requests, won't change header if already provided.
8749                                         if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8750                                                 headers[ "X-Requested-With" ] = "XMLHttpRequest";
8751                                         }
8752
8753                                         // Need an extra try/catch for cross domain requests in Firefox 3
8754                                         try {
8755                                                 for ( i in headers ) {
8756                                                         xhr.setRequestHeader( i, headers[ i ] );
8757                                                 }
8758                                         } catch( _ ) {}
8759
8760                                         // Do send the request
8761                                         // This may raise an exception which is actually
8762                                         // handled in jQuery.ajax (so no try/catch here)
8763                                         xhr.send( ( s.hasContent && s.data ) || null );
8764
8765                                         // Listener
8766                                         callback = function( _, isAbort ) {
8767
8768                                                 var status,
8769                                                         statusText,
8770                                                         responseHeaders,
8771                                                         responses,
8772                                                         xml;
8773
8774                                                 // Firefox throws exceptions when accessing properties
8775                                                 // of an xhr when a network error occured
8776                                                 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8777                                                 try {
8778
8779                                                         // Was never called and is aborted or complete
8780                                                         if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8781
8782                                                                 // Only called once
8783                                                                 callback = undefined;
8784
8785                                                                 // Do not keep as active anymore
8786                                                                 if ( handle ) {
8787                                                                         xhr.onreadystatechange = jQuery.noop;
8788                                                                         if ( xhrOnUnloadAbort ) {
8789                                                                                 delete xhrCallbacks[ handle ];
8790                                                                         }
8791                                                                 }
8792
8793                                                                 // If it's an abort
8794                                                                 if ( isAbort ) {
8795                                                                         // Abort it manually if needed
8796                                                                         if ( xhr.readyState !== 4 ) {
8797                                                                                 xhr.abort();
8798                                                                         }
8799                                                                 } else {
8800                                                                         status = xhr.status;
8801                                                                         responseHeaders = xhr.getAllResponseHeaders();
8802                                                                         responses = {};
8803                                                                         xml = xhr.responseXML;
8804
8805                                                                         // Construct response list
8806                                                                         if ( xml && xml.documentElement /* #4958 */ ) {
8807                                                                                 responses.xml = xml;
8808                                                                         }
8809                                                                         responses.text = xhr.responseText;
8810
8811                                                                         // Firefox throws an exception when accessing
8812                                                                         // statusText for faulty cross-domain requests
8813                                                                         try {
8814                                                                                 statusText = xhr.statusText;
8815                                                                         } catch( e ) {
8816                                                                                 // We normalize with Webkit giving an empty statusText
8817                                                                                 statusText = "";
8818                                                                         }
8819
8820                                                                         // Filter status for non standard behaviors
8821
8822                                                                         // If the request is local and we have data: assume a success
8823                                                                         // (success with no data won't get notified, that's the best we
8824                                                                         // can do given current implementations)
8825                                                                         if ( !status && s.isLocal && !s.crossDomain ) {
8826                                                                                 status = responses.text ? 200 : 404;
8827                                                                         // IE - #1450: sometimes returns 1223 when it should be 204
8828                                                                         } else if ( status === 1223 ) {
8829                                                                                 status = 204;
8830                                                                         }
8831                                                                 }
8832                                                         }
8833                                                 } catch( firefoxAccessException ) {
8834                                                         if ( !isAbort ) {
8835                                                                 complete( -1, firefoxAccessException );
8836                                                         }
8837                                                 }
8838
8839                                                 // Call complete if needed
8840                                                 if ( responses ) {
8841                                                         complete( status, statusText, responses, responseHeaders );
8842                                                 }
8843                                         };
8844
8845                                         // if we're in sync mode or it's in cache
8846                                         // and has been retrieved directly (IE6 & IE7)
8847                                         // we need to manually fire the callback
8848                                         if ( !s.async || xhr.readyState === 4 ) {
8849                                                 callback();
8850                                         } else {
8851                                                 handle = ++xhrId;
8852                                                 if ( xhrOnUnloadAbort ) {
8853                                                         // Create the active xhrs callbacks list if needed
8854                                                         // and attach the unload handler
8855                                                         if ( !xhrCallbacks ) {
8856                                                                 xhrCallbacks = {};
8857                                                                 jQuery( window ).unload( xhrOnUnloadAbort );
8858                                                         }
8859                                                         // Add to list of active xhrs callbacks
8860                                                         xhrCallbacks[ handle ] = callback;
8861                                                 }
8862                                                 xhr.onreadystatechange = callback;
8863                                         }
8864                                 },
8865
8866                                 abort: function() {
8867                                         if ( callback ) {
8868                                                 callback(0,1);
8869                                         }
8870                                 }
8871                         };
8872                 }
8873         });
8874 }
8875
8876
8877
8878
8879 var elemdisplay = {},
8880         iframe, iframeDoc,
8881         rfxtypes = /^(?:toggle|show|hide)$/,
8882         rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
8883         timerId,
8884         fxAttrs = [
8885                 // height animations
8886                 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
8887                 // width animations
8888                 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
8889                 // opacity animations
8890                 [ "opacity" ]
8891         ],
8892         fxNow;
8893
8894 jQuery.fn.extend({
8895         show: function( speed, easing, callback ) {
8896                 var elem, display;
8897
8898                 if ( speed || speed === 0 ) {
8899                         return this.animate( genFx("show", 3), speed, easing, callback );
8900
8901                 } else {
8902                         for ( var i = 0, j = this.length; i < j; i++ ) {
8903                                 elem = this[ i ];
8904
8905                                 if ( elem.style ) {
8906                                         display = elem.style.display;
8907
8908                                         // Reset the inline display of this element to learn if it is
8909                                         // being hidden by cascaded rules or not
8910                                         if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
8911                                                 display = elem.style.display = "";
8912                                         }
8913
8914                                         // Set elements which have been overridden with display: none
8915                                         // in a stylesheet to whatever the default browser style is
8916                                         // for such an element
8917                                         if ( display === "" && jQuery.css(elem, "display") === "none" ) {
8918                                                 jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
8919                                         }
8920                                 }
8921                         }
8922
8923                         // Set the display of most of the elements in a second loop
8924                         // to avoid the constant reflow
8925                         for ( i = 0; i < j; i++ ) {
8926                                 elem = this[ i ];
8927
8928                                 if ( elem.style ) {
8929                                         display = elem.style.display;
8930
8931                                         if ( display === "" || display === "none" ) {
8932                                                 elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
8933                                         }
8934                                 }
8935                         }
8936
8937                         return this;
8938                 }
8939         },
8940
8941         hide: function( speed, easing, callback ) {
8942                 if ( speed || speed === 0 ) {
8943                         return this.animate( genFx("hide", 3), speed, easing, callback);
8944
8945                 } else {
8946                         var elem, display,
8947                                 i = 0,
8948                                 j = this.length;
8949
8950                         for ( ; i < j; i++ ) {
8951                                 elem = this[i];
8952                                 if ( elem.style ) {
8953                                         display = jQuery.css( elem, "display" );
8954
8955                                         if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
8956                                                 jQuery._data( elem, "olddisplay", display );
8957                                         }
8958                                 }
8959                         }
8960
8961                         // Set the display of the elements in a second loop
8962                         // to avoid the constant reflow
8963                         for ( i = 0; i < j; i++ ) {
8964                                 if ( this[i].style ) {
8965                                         this[i].style.display = "none";
8966                                 }
8967                         }
8968
8969                         return this;
8970                 }
8971         },
8972
8973         // Save the old toggle function
8974         _toggle: jQuery.fn.toggle,
8975
8976         toggle: function( fn, fn2, callback ) {
8977                 var bool = typeof fn === "boolean";
8978
8979                 if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
8980                         this._toggle.apply( this, arguments );
8981
8982                 } else if ( fn == null || bool ) {
8983                         this.each(function() {
8984                                 var state = bool ? fn : jQuery(this).is(":hidden");
8985                                 jQuery(this)[ state ? "show" : "hide" ]();
8986                         });
8987
8988                 } else {
8989                         this.animate(genFx("toggle", 3), fn, fn2, callback);
8990                 }
8991
8992                 return this;
8993         },
8994
8995         fadeTo: function( speed, to, easing, callback ) {
8996                 return this.filter(":hidden").css("opacity", 0).show().end()
8997                                         .animate({opacity: to}, speed, easing, callback);
8998         },
8999
9000         animate: function( prop, speed, easing, callback ) {
9001                 var optall = jQuery.speed( speed, easing, callback );
9002
9003                 if ( jQuery.isEmptyObject( prop ) ) {
9004                         return this.each( optall.complete, [ false ] );
9005                 }
9006
9007                 // Do not change referenced properties as per-property easing will be lost
9008                 prop = jQuery.extend( {}, prop );
9009
9010                 function doAnimation() {
9011                         // XXX 'this' does not always have a nodeName when running the
9012                         // test suite
9013
9014                         if ( optall.queue === false ) {
9015                                 jQuery._mark( this );
9016                         }
9017
9018                         var opt = jQuery.extend( {}, optall ),
9019                                 isElement = this.nodeType === 1,
9020                                 hidden = isElement && jQuery(this).is(":hidden"),
9021                                 name, val, p, e,
9022                                 parts, start, end, unit,
9023                                 method;
9024
9025                         // will store per property easing and be used to determine when an animation is complete
9026                         opt.animatedProperties = {};
9027
9028                         for ( p in prop ) {
9029
9030                                 // property name normalization
9031                                 name = jQuery.camelCase( p );
9032                                 if ( p !== name ) {
9033                                         prop[ name ] = prop[ p ];
9034                                         delete prop[ p ];
9035                                 }
9036
9037                                 val = prop[ name ];
9038
9039                                 // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
9040                                 if ( jQuery.isArray( val ) ) {
9041                                         opt.animatedProperties[ name ] = val[ 1 ];
9042                                         val = prop[ name ] = val[ 0 ];
9043                                 } else {
9044                                         opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
9045                                 }
9046
9047                                 if ( val === "hide" && hidden || val === "show" && !hidden ) {
9048                                         return opt.complete.call( this );
9049                                 }
9050
9051                                 if ( isElement && ( name === "height" || name === "width" ) ) {
9052                                         // Make sure that nothing sneaks out
9053                                         // Record all 3 overflow attributes because IE does not
9054                                         // change the overflow attribute when overflowX and
9055                                         // overflowY are set to the same value
9056                                         opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
9057
9058                                         // Set display property to inline-block for height/width
9059                                         // animations on inline elements that are having width/height animated
9060                                         if ( jQuery.css( this, "display" ) === "inline" &&
9061                                                         jQuery.css( this, "float" ) === "none" ) {
9062
9063                                                 // inline-level elements accept inline-block;
9064                                                 // block-level elements need to be inline with layout
9065                                                 if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
9066                                                         this.style.display = "inline-block";
9067
9068                                                 } else {
9069                                                         this.style.zoom = 1;
9070                                                 }
9071                                         }
9072                                 }
9073                         }
9074
9075                         if ( opt.overflow != null ) {
9076                                 this.style.overflow = "hidden";
9077                         }
9078
9079                         for ( p in prop ) {
9080                                 e = new jQuery.fx( this, opt, p );
9081                                 val = prop[ p ];
9082
9083                                 if ( rfxtypes.test( val ) ) {
9084
9085                                         // Tracks whether to show or hide based on private
9086                                         // data attached to the element
9087                                         method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
9088                                         if ( method ) {
9089                                                 jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
9090                                                 e[ method ]();
9091                                         } else {
9092                                                 e[ val ]();
9093                                         }
9094
9095                                 } else {
9096                                         parts = rfxnum.exec( val );
9097                                         start = e.cur();
9098
9099                                         if ( parts ) {
9100                                                 end = parseFloat( parts[2] );
9101                                                 unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
9102
9103                                                 // We need to compute starting value
9104                                                 if ( unit !== "px" ) {
9105                                                         jQuery.style( this, p, (end || 1) + unit);
9106                                                         start = ( (end || 1) / e.cur() ) * start;
9107                                                         jQuery.style( this, p, start + unit);
9108                                                 }
9109
9110                                                 // If a +=/-= token was provided, we're doing a relative animation
9111                                                 if ( parts[1] ) {
9112                                                         end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
9113                                                 }
9114
9115                                                 e.custom( start, end, unit );
9116
9117                                         } else {
9118                                                 e.custom( start, val, "" );
9119                                         }
9120                                 }
9121                         }
9122
9123                         // For JS strict compliance
9124                         return true;
9125                 }
9126
9127                 return optall.queue === false ?
9128                         this.each( doAnimation ) :
9129                         this.queue( optall.queue, doAnimation );
9130         },
9131
9132         stop: function( type, clearQueue, gotoEnd ) {
9133                 if ( typeof type !== "string" ) {
9134                         gotoEnd = clearQueue;
9135                         clearQueue = type;
9136                         type = undefined;
9137                 }
9138                 if ( clearQueue && type !== false ) {
9139                         this.queue( type || "fx", [] );
9140                 }
9141
9142                 return this.each(function() {
9143                         var i,
9144                                 hadTimers = false,
9145                                 timers = jQuery.timers,
9146                                 data = jQuery._data( this );
9147
9148                         // clear marker counters if we know they won't be
9149                         if ( !gotoEnd ) {
9150                                 jQuery._unmark( true, this );
9151                         }
9152
9153                         function stopQueue( elem, data, i ) {
9154                                 var hooks = data[ i ];
9155                                 jQuery.removeData( elem, i, true );
9156                                 hooks.stop( gotoEnd );
9157                         }
9158
9159                         if ( type == null ) {
9160                                 for ( i in data ) {
9161                                         if ( data[ i ].stop && i.indexOf(".run") === i.length - 4 ) {
9162                                                 stopQueue( this, data, i );
9163                                         }
9164                                 }
9165                         } else if ( data[ i = type + ".run" ] && data[ i ].stop ){
9166                                 stopQueue( this, data, i );
9167                         }
9168
9169                         for ( i = timers.length; i--; ) {
9170                                 if ( timers[ i ].elem === this && (type == null || timers[ i ].queue === type) ) {
9171                                         if ( gotoEnd ) {
9172
9173                                                 // force the next step to be the last
9174                                                 timers[ i ]( true );
9175                                         } else {
9176                                                 timers[ i ].saveState();
9177                                         }
9178                                         hadTimers = true;
9179                                         timers.splice( i, 1 );
9180                                 }
9181                         }
9182
9183                         // start the next in the queue if the last step wasn't forced
9184                         // timers currently will call their complete callbacks, which will dequeue
9185                         // but only if they were gotoEnd
9186                         if ( !( gotoEnd && hadTimers ) ) {
9187                                 jQuery.dequeue( this, type );
9188                         }
9189                 });
9190         }
9191
9192 });
9193
9194 // Animations created synchronously will run synchronously
9195 function createFxNow() {
9196         setTimeout( clearFxNow, 0 );
9197         return ( fxNow = jQuery.now() );
9198 }
9199
9200 function clearFxNow() {
9201         fxNow = undefined;
9202 }
9203
9204 // Generate parameters to create a standard animation
9205 function genFx( type, num ) {
9206         var obj = {};
9207
9208         jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
9209                 obj[ this ] = type;
9210         });
9211
9212         return obj;
9213 }
9214
9215 // Generate shortcuts for custom animations
9216 jQuery.each({
9217         slideDown: genFx( "show", 1 ),
9218         slideUp: genFx( "hide", 1 ),
9219         slideToggle: genFx( "toggle", 1 ),
9220         fadeIn: { opacity: "show" },
9221         fadeOut: { opacity: "hide" },
9222         fadeToggle: { opacity: "toggle" }
9223 }, function( name, props ) {
9224         jQuery.fn[ name ] = function( speed, easing, callback ) {
9225                 return this.animate( props, speed, easing, callback );
9226         };
9227 });
9228
9229 jQuery.extend({
9230         speed: function( speed, easing, fn ) {
9231                 var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
9232                         complete: fn || !fn && easing ||
9233                                 jQuery.isFunction( speed ) && speed,
9234                         duration: speed,
9235                         easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
9236                 };
9237
9238                 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
9239                         opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
9240
9241                 // normalize opt.queue - true/undefined/null -> "fx"
9242                 if ( opt.queue == null || opt.queue === true ) {
9243                         opt.queue = "fx";
9244                 }
9245
9246                 // Queueing
9247                 opt.old = opt.complete;
9248
9249                 opt.complete = function( noUnmark ) {
9250                         if ( jQuery.isFunction( opt.old ) ) {
9251                                 opt.old.call( this );
9252                         }
9253
9254                         if ( opt.queue ) {
9255                                 jQuery.dequeue( this, opt.queue );
9256                         } else if ( noUnmark !== false ) {
9257                                 jQuery._unmark( this );
9258                         }
9259                 };
9260
9261                 return opt;
9262         },
9263
9264         easing: {
9265                 linear: function( p, n, firstNum, diff ) {
9266                         return firstNum + diff * p;
9267                 },
9268                 swing: function( p, n, firstNum, diff ) {
9269                         return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
9270                 }
9271         },
9272
9273         timers: [],
9274
9275         fx: function( elem, options, prop ) {
9276                 this.options = options;
9277                 this.elem = elem;
9278                 this.prop = prop;
9279
9280                 options.orig = options.orig || {};
9281         }
9282
9283 });
9284
9285 jQuery.fx.prototype = {
9286         // Simple function for setting a style value
9287         update: function() {
9288                 if ( this.options.step ) {
9289                         this.options.step.call( this.elem, this.now, this );
9290                 }
9291
9292                 ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
9293         },
9294
9295         // Get the current size
9296         cur: function() {
9297                 if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
9298                         return this.elem[ this.prop ];
9299                 }
9300
9301                 var parsed,
9302                         r = jQuery.css( this.elem, this.prop );
9303                 // Empty strings, null, undefined and "auto" are converted to 0,
9304                 // complex values such as "rotate(1rad)" are returned as is,
9305                 // simple values such as "10px" are parsed to Float.
9306                 return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
9307         },
9308
9309         // Start an animation from one number to another
9310         custom: function( from, to, unit ) {
9311                 var self = this,
9312                         fx = jQuery.fx;
9313
9314                 this.startTime = fxNow || createFxNow();
9315                 this.end = to;
9316                 this.now = this.start = from;
9317                 this.pos = this.state = 0;
9318                 this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
9319
9320                 function t( gotoEnd ) {
9321                         return self.step( gotoEnd );
9322                 }
9323
9324                 t.queue = this.options.queue;
9325                 t.elem = this.elem;
9326                 t.saveState = function() {
9327                         if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
9328                                 jQuery._data( self.elem, "fxshow" + self.prop, self.start );
9329                         }
9330                 };
9331
9332                 if ( t() && jQuery.timers.push(t) && !timerId ) {
9333                         timerId = setInterval( fx.tick, fx.interval );
9334                 }
9335         },
9336
9337         // Simple 'show' function
9338         show: function() {
9339                 var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
9340
9341                 // Remember where we started, so that we can go back to it later
9342                 this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
9343                 this.options.show = true;
9344
9345                 // Begin the animation
9346                 // Make sure that we start at a small width/height to avoid any flash of content
9347                 if ( dataShow !== undefined ) {
9348                         // This show is picking up where a previous hide or show left off
9349                         this.custom( this.cur(), dataShow );
9350                 } else {
9351                         this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
9352                 }
9353
9354                 // Start by showing the element
9355                 jQuery( this.elem ).show();
9356         },
9357
9358         // Simple 'hide' function
9359         hide: function() {
9360                 // Remember where we started, so that we can go back to it later
9361                 this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
9362                 this.options.hide = true;
9363
9364                 // Begin the animation
9365                 this.custom( this.cur(), 0 );
9366         },
9367
9368         // Each step of an animation
9369         step: function( gotoEnd ) {
9370                 var p, n, complete,
9371                         t = fxNow || createFxNow(),
9372                         done = true,
9373                         elem = this.elem,
9374                         options = this.options;
9375
9376                 if ( gotoEnd || t >= options.duration + this.startTime ) {
9377                         this.now = this.end;
9378                         this.pos = this.state = 1;
9379                         this.update();
9380
9381                         options.animatedProperties[ this.prop ] = true;
9382
9383                         for ( p in options.animatedProperties ) {
9384                                 if ( options.animatedProperties[ p ] !== true ) {
9385                                         done = false;
9386                                 }
9387                         }
9388
9389                         if ( done ) {
9390                                 // Reset the overflow
9391                                 if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
9392
9393                                         jQuery.each( [ "", "X", "Y" ], function( index, value ) {
9394                                                 elem.style[ "overflow" + value ] = options.overflow[ index ];
9395                                         });
9396                                 }
9397
9398                                 // Hide the element if the "hide" operation was done
9399                                 if ( options.hide ) {
9400                                         jQuery( elem ).hide();
9401                                 }
9402
9403                                 // Reset the properties, if the item has been hidden or shown
9404                                 if ( options.hide || options.show ) {
9405                                         for ( p in options.animatedProperties ) {
9406                                                 jQuery.style( elem, p, options.orig[ p ] );
9407                                                 jQuery.removeData( elem, "fxshow" + p, true );
9408                                                 // Toggle data is no longer needed
9409                                                 jQuery.removeData( elem, "toggle" + p, true );
9410                                         }
9411                                 }
9412
9413                                 // Execute the complete function
9414                                 // in the event that the complete function throws an exception
9415                                 // we must ensure it won't be called twice. #5684
9416
9417                                 complete = options.complete;
9418                                 if ( complete ) {
9419
9420                                         options.complete = false;
9421                                         complete.call( elem );
9422                                 }
9423                         }
9424
9425                         return false;
9426
9427                 } else {
9428                         // classical easing cannot be used with an Infinity duration
9429                         if ( options.duration == Infinity ) {
9430                                 this.now = t;
9431                         } else {
9432                                 n = t - this.startTime;
9433                                 this.state = n / options.duration;
9434
9435                                 // Perform the easing function, defaults to swing
9436                                 this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
9437                                 this.now = this.start + ( (this.end - this.start) * this.pos );
9438                         }
9439                         // Perform the next step of the animation
9440                         this.update();
9441                 }
9442
9443                 return true;
9444         }
9445 };
9446
9447 jQuery.extend( jQuery.fx, {
9448         tick: function() {
9449                 var timer,
9450                         timers = jQuery.timers,
9451                         i = 0;
9452
9453                 for ( ; i < timers.length; i++ ) {
9454                         timer = timers[ i ];
9455                         // Checks the timer has not already been removed
9456                         if ( !timer() && timers[ i ] === timer ) {
9457                                 timers.splice( i--, 1 );
9458                         }
9459                 }
9460
9461                 if ( !timers.length ) {
9462                         jQuery.fx.stop();
9463                 }
9464         },
9465
9466         interval: 13,
9467
9468         stop: function() {
9469                 clearInterval( timerId );
9470                 timerId = null;
9471         },
9472
9473         speeds: {
9474                 slow: 600,
9475                 fast: 200,
9476                 // Default speed
9477                 _default: 400
9478         },
9479
9480         step: {
9481                 opacity: function( fx ) {
9482                         jQuery.style( fx.elem, "opacity", fx.now );
9483                 },
9484
9485                 _default: function( fx ) {
9486                         if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
9487                                 fx.elem.style[ fx.prop ] = fx.now + fx.unit;
9488                         } else {
9489                                 fx.elem[ fx.prop ] = fx.now;
9490                         }
9491                 }
9492         }
9493 });
9494
9495 // Adds width/height step functions
9496 // Do not set anything below 0
9497 jQuery.each([ "width", "height" ], function( i, prop ) {
9498         jQuery.fx.step[ prop ] = function( fx ) {
9499                 jQuery.style( fx.elem, prop, Math.max(0, fx.now) );
9500         };
9501 });
9502
9503 if ( jQuery.expr && jQuery.expr.filters ) {
9504         jQuery.expr.filters.animated = function( elem ) {
9505                 return jQuery.grep(jQuery.timers, function( fn ) {
9506                         return elem === fn.elem;
9507                 }).length;
9508         };
9509 }
9510
9511 // Try to restore the default display value of an element
9512 function defaultDisplay( nodeName ) {
9513
9514         if ( !elemdisplay[ nodeName ] ) {
9515
9516                 var body = document.body,
9517                         elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
9518                         display = elem.css( "display" );
9519                 elem.remove();
9520
9521                 // If the simple way fails,
9522                 // get element's real default display by attaching it to a temp iframe
9523                 if ( display === "none" || display === "" ) {
9524                         // No iframe to use yet, so create it
9525                         if ( !iframe ) {
9526                                 iframe = document.createElement( "iframe" );
9527                                 iframe.frameBorder = iframe.width = iframe.height = 0;
9528                         }
9529
9530                         body.appendChild( iframe );
9531
9532                         // Create a cacheable copy of the iframe document on first call.
9533                         // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
9534                         // document to it; WebKit & Firefox won't allow reusing the iframe document.
9535                         if ( !iframeDoc || !iframe.createElement ) {
9536                                 iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
9537                                 iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
9538                                 iframeDoc.close();
9539                         }
9540
9541                         elem = iframeDoc.createElement( nodeName );
9542
9543                         iframeDoc.body.appendChild( elem );
9544
9545                         display = jQuery.css( elem, "display" );
9546                         body.removeChild( iframe );
9547                 }
9548
9549                 // Store the correct default display
9550                 elemdisplay[ nodeName ] = display;
9551         }
9552
9553         return elemdisplay[ nodeName ];
9554 }
9555
9556
9557
9558
9559 var rtable = /^t(?:able|d|h)$/i,
9560         rroot = /^(?:body|html)$/i;
9561
9562 if ( "getBoundingClientRect" in document.documentElement ) {
9563         jQuery.fn.offset = function( options ) {
9564                 var elem = this[0], box;
9565
9566                 if ( options ) {
9567                         return this.each(function( i ) {
9568                                 jQuery.offset.setOffset( this, options, i );
9569                         });
9570                 }
9571
9572                 if ( !elem || !elem.ownerDocument ) {
9573                         return null;
9574                 }
9575
9576                 if ( elem === elem.ownerDocument.body ) {
9577                         return jQuery.offset.bodyOffset( elem );
9578                 }
9579
9580                 try {
9581                         box = elem.getBoundingClientRect();
9582                 } catch(e) {}
9583
9584                 var doc = elem.ownerDocument,
9585                         docElem = doc.documentElement;
9586
9587                 // Make sure we're not dealing with a disconnected DOM node
9588                 if ( !box || !jQuery.contains( docElem, elem ) ) {
9589                         return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
9590                 }
9591
9592                 var body = doc.body,
9593                         win = getWindow(doc),
9594                         clientTop  = docElem.clientTop  || body.clientTop  || 0,
9595                         clientLeft = docElem.clientLeft || body.clientLeft || 0,
9596                         scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
9597                         scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
9598                         top  = box.top  + scrollTop  - clientTop,
9599                         left = box.left + scrollLeft - clientLeft;
9600
9601                 return { top: top, left: left };
9602         };
9603
9604 } else {
9605         jQuery.fn.offset = function( options ) {
9606                 var elem = this[0];
9607
9608                 if ( options ) {
9609                         return this.each(function( i ) {
9610                                 jQuery.offset.setOffset( this, options, i );
9611                         });
9612                 }
9613
9614                 if ( !elem || !elem.ownerDocument ) {
9615                         return null;
9616                 }
9617
9618                 if ( elem === elem.ownerDocument.body ) {
9619                         return jQuery.offset.bodyOffset( elem );
9620                 }
9621
9622                 var computedStyle,
9623                         offsetParent = elem.offsetParent,
9624                         prevOffsetParent = elem,
9625                         doc = elem.ownerDocument,
9626                         docElem = doc.documentElement,
9627                         body = doc.body,
9628                         defaultView = doc.defaultView,
9629                         prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
9630                         top = elem.offsetTop,
9631                         left = elem.offsetLeft;
9632
9633                 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
9634                         if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
9635                                 break;
9636                         }
9637
9638                         computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
9639                         top  -= elem.scrollTop;
9640                         left -= elem.scrollLeft;
9641
9642                         if ( elem === offsetParent ) {
9643                                 top  += elem.offsetTop;
9644                                 left += elem.offsetLeft;
9645
9646                                 if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
9647                                         top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
9648                                         left += parseFloat( computedStyle.borderLeftWidth ) || 0;
9649                                 }
9650
9651                                 prevOffsetParent = offsetParent;
9652                                 offsetParent = elem.offsetParent;
9653                         }
9654
9655                         if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
9656                                 top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
9657                                 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
9658                         }
9659
9660                         prevComputedStyle = computedStyle;
9661                 }
9662
9663                 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
9664                         top  += body.offsetTop;
9665                         left += body.offsetLeft;
9666                 }
9667
9668                 if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
9669                         top  += Math.max( docElem.scrollTop, body.scrollTop );
9670                         left += Math.max( docElem.scrollLeft, body.scrollLeft );
9671                 }
9672
9673                 return { top: top, left: left };
9674         };
9675 }
9676
9677 jQuery.offset = {
9678
9679         bodyOffset: function( body ) {
9680                 var top = body.offsetTop,
9681                         left = body.offsetLeft;
9682
9683                 if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
9684                         top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
9685                         left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
9686                 }
9687
9688                 return { top: top, left: left };
9689         },
9690
9691         setOffset: function( elem, options, i ) {
9692                 var position = jQuery.css( elem, "position" );
9693
9694                 // set position first, in-case top/left are set even on static elem
9695                 if ( position === "static" ) {
9696                         elem.style.position = "relative";
9697                 }
9698
9699                 var curElem = jQuery( elem ),
9700                         curOffset = curElem.offset(),
9701                         curCSSTop = jQuery.css( elem, "top" ),
9702                         curCSSLeft = jQuery.css( elem, "left" ),
9703                         calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9704                         props = {}, curPosition = {}, curTop, curLeft;
9705
9706                 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9707                 if ( calculatePosition ) {
9708                         curPosition = curElem.position();
9709                         curTop = curPosition.top;
9710                         curLeft = curPosition.left;
9711                 } else {
9712                         curTop = parseFloat( curCSSTop ) || 0;
9713                         curLeft = parseFloat( curCSSLeft ) || 0;
9714                 }
9715
9716                 if ( jQuery.isFunction( options ) ) {
9717                         options = options.call( elem, i, curOffset );
9718                 }
9719
9720                 if ( options.top != null ) {
9721                         props.top = ( options.top - curOffset.top ) + curTop;
9722                 }
9723                 if ( options.left != null ) {
9724                         props.left = ( options.left - curOffset.left ) + curLeft;
9725                 }
9726
9727                 if ( "using" in options ) {
9728                         options.using.call( elem, props );
9729                 } else {
9730                         curElem.css( props );
9731                 }
9732         }
9733 };
9734
9735
9736 jQuery.fn.extend({
9737
9738         position: function() {
9739                 if ( !this[0] ) {
9740                         return null;
9741                 }
9742
9743                 var elem = this[0],
9744
9745                 // Get *real* offsetParent
9746                 offsetParent = this.offsetParent(),
9747
9748                 // Get correct offsets
9749                 offset       = this.offset(),
9750                 parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
9751
9752                 // Subtract element margins
9753                 // note: when an element has margin: auto the offsetLeft and marginLeft
9754                 // are the same in Safari causing offset.left to incorrectly be 0
9755                 offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
9756                 offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
9757
9758                 // Add offsetParent borders
9759                 parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
9760                 parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
9761
9762                 // Subtract the two offsets
9763                 return {
9764                         top:  offset.top  - parentOffset.top,
9765                         left: offset.left - parentOffset.left
9766                 };
9767         },
9768
9769         offsetParent: function() {
9770                 return this.map(function() {
9771                         var offsetParent = this.offsetParent || document.body;
9772                         while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
9773                                 offsetParent = offsetParent.offsetParent;
9774                         }
9775                         return offsetParent;
9776                 });
9777         }
9778 });
9779
9780
9781 // Create scrollLeft and scrollTop methods
9782 jQuery.each( ["Left", "Top"], function( i, name ) {
9783         var method = "scroll" + name;
9784
9785         jQuery.fn[ method ] = function( val ) {
9786                 var elem, win;
9787
9788                 if ( val === undefined ) {
9789                         elem = this[ 0 ];
9790
9791                         if ( !elem ) {
9792                                 return null;
9793                         }
9794
9795                         win = getWindow( elem );
9796
9797                         // Return the scroll offset
9798                         return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
9799                                 jQuery.support.boxModel && win.document.documentElement[ method ] ||
9800                                         win.document.body[ method ] :
9801                                 elem[ method ];
9802                 }
9803
9804                 // Set the scroll offset
9805                 return this.each(function() {
9806                         win = getWindow( this );
9807
9808                         if ( win ) {
9809                                 win.scrollTo(
9810                                         !i ? val : jQuery( win ).scrollLeft(),
9811                                          i ? val : jQuery( win ).scrollTop()
9812                                 );
9813
9814                         } else {
9815                                 this[ method ] = val;
9816                         }
9817                 });
9818         };
9819 });
9820
9821 function getWindow( elem ) {
9822         return jQuery.isWindow( elem ) ?
9823                 elem :
9824                 elem.nodeType === 9 ?
9825                         elem.defaultView || elem.parentWindow :
9826                         false;
9827 }
9828
9829
9830
9831
9832 // Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
9833 jQuery.each([ "Height", "Width" ], function( i, name ) {
9834
9835         var type = name.toLowerCase();
9836
9837         // innerHeight and innerWidth
9838         jQuery.fn[ "inner" + name ] = function() {
9839                 var elem = this[0];
9840                 return elem ?
9841                         elem.style ?
9842                         parseFloat( jQuery.css( elem, type, "padding" ) ) :
9843                         this[ type ]() :
9844                         null;
9845         };
9846
9847         // outerHeight and outerWidth
9848         jQuery.fn[ "outer" + name ] = function( margin ) {
9849                 var elem = this[0];
9850                 return elem ?
9851                         elem.style ?
9852                         parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
9853                         this[ type ]() :
9854                         null;
9855         };
9856
9857         jQuery.fn[ type ] = function( size ) {
9858                 // Get window width or height
9859                 var elem = this[0];
9860                 if ( !elem ) {
9861                         return size == null ? null : this;
9862                 }
9863
9864                 if ( jQuery.isFunction( size ) ) {
9865                         return this.each(function( i ) {
9866                                 var self = jQuery( this );
9867                                 self[ type ]( size.call( this, i, self[ type ]() ) );
9868                         });
9869                 }
9870
9871                 if ( jQuery.isWindow( elem ) ) {
9872                         // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
9873                         // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
9874                         var docElemProp = elem.document.documentElement[ "client" + name ],
9875                                 body = elem.document.body;
9876                         return elem.document.compatMode === "CSS1Compat" && docElemProp ||
9877                                 body && body[ "client" + name ] || docElemProp;
9878
9879                 // Get document width or height
9880                 } else if ( elem.nodeType === 9 ) {
9881                         // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
9882                         return Math.max(
9883                                 elem.documentElement["client" + name],
9884                                 elem.body["scroll" + name], elem.documentElement["scroll" + name],
9885                                 elem.body["offset" + name], elem.documentElement["offset" + name]
9886                         );
9887
9888                 // Get or set width or height on the element
9889                 } else if ( size === undefined ) {
9890                         var orig = jQuery.css( elem, type ),
9891                                 ret = parseFloat( orig );
9892
9893                         return jQuery.isNumeric( ret ) ? ret : orig;
9894
9895                 // Set the width or height on the element (default to pixels if value is unitless)
9896                 } else {
9897                         return this.css( type, typeof size === "string" ? size : size + "px" );
9898                 }
9899         };
9900
9901 });
9902
9903
9904 // Expose jQuery to the global object
9905 window.jQuery = window.$ = jQuery;
9906 })( window );
9907 </script><script type="text/javascript">/*!
9908  * jQuery UI 1.8.16
9909  *
9910  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9911  * Dual licensed under the MIT or GPL Version 2 licenses.
9912  * http://jquery.org/license
9913  *
9914  * http://docs.jquery.com/UI
9915  */
9916 (function( $, undefined ) {
9917
9918 // prevent duplicate loading
9919 // this is only a problem because we proxy existing functions
9920 // and we don't want to double proxy them
9921 $.ui = $.ui || {};
9922 if ( $.ui.version ) {
9923         return;
9924 }
9925
9926 $.extend( $.ui, {
9927         version: "1.8.16",
9928
9929         keyCode: {
9930                 ALT: 18,
9931                 BACKSPACE: 8,
9932                 CAPS_LOCK: 20,
9933                 COMMA: 188,
9934                 COMMAND: 91,
9935                 COMMAND_LEFT: 91, // COMMAND
9936                 COMMAND_RIGHT: 93,
9937                 CONTROL: 17,
9938                 DELETE: 46,
9939                 DOWN: 40,
9940                 END: 35,
9941                 ENTER: 13,
9942                 ESCAPE: 27,
9943                 HOME: 36,
9944                 INSERT: 45,
9945                 LEFT: 37,
9946                 MENU: 93, // COMMAND_RIGHT
9947                 NUMPAD_ADD: 107,
9948                 NUMPAD_DECIMAL: 110,
9949                 NUMPAD_DIVIDE: 111,
9950                 NUMPAD_ENTER: 108,
9951                 NUMPAD_MULTIPLY: 106,
9952                 NUMPAD_SUBTRACT: 109,
9953                 PAGE_DOWN: 34,
9954                 PAGE_UP: 33,
9955                 PERIOD: 190,
9956                 RIGHT: 39,
9957                 SHIFT: 16,
9958                 SPACE: 32,
9959                 TAB: 9,
9960                 UP: 38,
9961                 WINDOWS: 91 // COMMAND
9962         }
9963 });
9964
9965 // plugins
9966 $.fn.extend({
9967         propAttr: $.fn.prop || $.fn.attr,
9968
9969         _focus: $.fn.focus,
9970         focus: function( delay, fn ) {
9971                 return typeof delay === "number" ?
9972                         this.each(function() {
9973                                 var elem = this;
9974                                 setTimeout(function() {
9975                                         $( elem ).focus();
9976                                         if ( fn ) {
9977                                                 fn.call( elem );
9978                                         }
9979                                 }, delay );
9980                         }) :
9981                         this._focus.apply( this, arguments );
9982         },
9983
9984         scrollParent: function() {
9985                 var scrollParent;
9986                 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
9987                         scrollParent = this.parents().filter(function() {
9988                                 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
9989                         }).eq(0);
9990                 } else {
9991                         scrollParent = this.parents().filter(function() {
9992                                 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
9993                         }).eq(0);
9994                 }
9995
9996                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
9997         },
9998
9999         zIndex: function( zIndex ) {
10000                 if ( zIndex !== undefined ) {
10001                         return this.css( "zIndex", zIndex );
10002                 }
10003
10004                 if ( this.length ) {
10005                         var elem = $( this[ 0 ] ), position, value;
10006                         while ( elem.length && elem[ 0 ] !== document ) {
10007                                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
10008                                 // This makes behavior of this function consistent across browsers
10009                                 // WebKit always returns auto if the element is positioned
10010                                 position = elem.css( "position" );
10011                                 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
10012                                         // IE returns 0 when zIndex is not specified
10013                                         // other browsers return a string
10014                                         // we ignore the case of nested elements with an explicit value of 0
10015                                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
10016                                         value = parseInt( elem.css( "zIndex" ), 10 );
10017                                         if ( !isNaN( value ) && value !== 0 ) {
10018                                                 return value;
10019                                         }
10020                                 }
10021                                 elem = elem.parent();
10022                         }
10023                 }
10024
10025                 return 0;
10026         },
10027
10028         disableSelection: function() {
10029                 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
10030                         ".ui-disableSelection", function( event ) {
10031                                 event.preventDefault();
10032                         });
10033         },
10034
10035         enableSelection: function() {
10036                 return this.unbind( ".ui-disableSelection" );
10037         }
10038 });
10039
10040 $.each( [ "Width", "Height" ], function( i, name ) {
10041         var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
10042                 type = name.toLowerCase(),
10043                 orig = {
10044                         innerWidth: $.fn.innerWidth,
10045                         innerHeight: $.fn.innerHeight,
10046                         outerWidth: $.fn.outerWidth,
10047                         outerHeight: $.fn.outerHeight
10048                 };
10049
10050         function reduce( elem, size, border, margin ) {
10051                 $.each( side, function() {
10052                         size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
10053                         if ( border ) {
10054                                 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
10055                         }
10056                         if ( margin ) {
10057                                 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
10058                         }
10059                 });
10060                 return size;
10061         }
10062
10063         $.fn[ "inner" + name ] = function( size ) {
10064                 if ( size === undefined ) {
10065                         return orig[ "inner" + name ].call( this );
10066                 }
10067
10068                 return this.each(function() {
10069                         $( this ).css( type, reduce( this, size ) + "px" );
10070                 });
10071         };
10072
10073         $.fn[ "outer" + name] = function( size, margin ) {
10074                 if ( typeof size !== "number" ) {
10075                         return orig[ "outer" + name ].call( this, size );
10076                 }
10077
10078                 return this.each(function() {
10079                         $( this).css( type, reduce( this, size, true, margin ) + "px" );
10080                 });
10081         };
10082 });
10083
10084 // selectors
10085 function focusable( element, isTabIndexNotNaN ) {
10086         var nodeName = element.nodeName.toLowerCase();
10087         if ( "area" === nodeName ) {
10088                 var map = element.parentNode,
10089                         mapName = map.name,
10090                         img;
10091                 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
10092                         return false;
10093                 }
10094                 img = $( "img[usemap=#" + mapName + "]" )[0];
10095                 return !!img && visible( img );
10096         }
10097         return ( /input|select|textarea|button|object/.test( nodeName )
10098                 ? !element.disabled
10099                 : "a" == nodeName
10100                         ? element.href || isTabIndexNotNaN
10101                         : isTabIndexNotNaN)
10102                 // the element and all of its ancestors must be visible
10103                 && visible( element );
10104 }
10105
10106 function visible( element ) {
10107         return !$( element ).parents().andSelf().filter(function() {
10108                 return $.curCSS( this, "visibility" ) === "hidden" ||
10109                         $.expr.filters.hidden( this );
10110         }).length;
10111 }
10112
10113 $.extend( $.expr[ ":" ], {
10114         data: function( elem, i, match ) {
10115                 return !!$.data( elem, match[ 3 ] );
10116         },
10117
10118         focusable: function( element ) {
10119                 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
10120         },
10121
10122         tabbable: function( element ) {
10123                 var tabIndex = $.attr( element, "tabindex" ),
10124                         isTabIndexNaN = isNaN( tabIndex );
10125                 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
10126         }
10127 });
10128
10129 // support
10130 $(function() {
10131         var body = document.body,
10132                 div = body.appendChild( div = document.createElement( "div" ) );
10133
10134         $.extend( div.style, {
10135                 minHeight: "100px",
10136                 height: "auto",
10137                 padding: 0,
10138                 borderWidth: 0
10139         });
10140
10141         $.support.minHeight = div.offsetHeight === 100;
10142         $.support.selectstart = "onselectstart" in div;
10143
10144         // set display to none to avoid a layout bug in IE
10145         // http://dev.jquery.com/ticket/4014
10146         body.removeChild( div ).style.display = "none";
10147 });
10148
10149
10150
10151
10152
10153 // deprecated
10154 $.extend( $.ui, {
10155         // $.ui.plugin is deprecated.  Use the proxy pattern instead.
10156         plugin: {
10157                 add: function( module, option, set ) {
10158                         var proto = $.ui[ module ].prototype;
10159                         for ( var i in set ) {
10160                                 proto.plugins[ i ] = proto.plugins[ i ] || [];
10161                                 proto.plugins[ i ].push( [ option, set[ i ] ] );
10162                         }
10163                 },
10164                 call: function( instance, name, args ) {
10165                         var set = instance.plugins[ name ];
10166                         if ( !set || !instance.element[ 0 ].parentNode ) {
10167                                 return;
10168                         }
10169         
10170                         for ( var i = 0; i < set.length; i++ ) {
10171                                 if ( instance.options[ set[ i ][ 0 ] ] ) {
10172                                         set[ i ][ 1 ].apply( instance.element, args );
10173                                 }
10174                         }
10175                 }
10176         },
10177         
10178         // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
10179         contains: function( a, b ) {
10180                 return document.compareDocumentPosition ?
10181                         a.compareDocumentPosition( b ) & 16 :
10182                         a !== b && a.contains( b );
10183         },
10184         
10185         // only used by resizable
10186         hasScroll: function( el, a ) {
10187         
10188                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
10189                 if ( $( el ).css( "overflow" ) === "hidden") {
10190                         return false;
10191                 }
10192         
10193                 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
10194                         has = false;
10195         
10196                 if ( el[ scroll ] > 0 ) {
10197                         return true;
10198                 }
10199         
10200                 // TODO: determine which cases actually cause this to happen
10201                 // if the element doesn't have the scroll set, see if it's possible to
10202                 // set the scroll
10203                 el[ scroll ] = 1;
10204                 has = ( el[ scroll ] > 0 );
10205                 el[ scroll ] = 0;
10206                 return has;
10207         },
10208         
10209         // these are odd functions, fix the API or move into individual plugins
10210         isOverAxis: function( x, reference, size ) {
10211                 //Determines when x coordinate is over "b" element axis
10212                 return ( x > reference ) && ( x < ( reference + size ) );
10213         },
10214         isOver: function( y, x, top, left, height, width ) {
10215                 //Determines when x, y coordinates is over "b" element
10216                 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
10217         }
10218 });
10219
10220 })( jQuery );
10221 /*!
10222  * jQuery UI Widget 1.8.16
10223  *
10224  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10225  * Dual licensed under the MIT or GPL Version 2 licenses.
10226  * http://jquery.org/license
10227  *
10228  * http://docs.jquery.com/UI/Widget
10229  */
10230 (function( $, undefined ) {
10231
10232 // jQuery 1.4+
10233 if ( $.cleanData ) {
10234         var _cleanData = $.cleanData;
10235         $.cleanData = function( elems ) {
10236                 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
10237                         try {
10238                                 $( elem ).triggerHandler( "remove" );
10239                         // http://bugs.jquery.com/ticket/8235
10240                         } catch( e ) {}
10241                 }
10242                 _cleanData( elems );
10243         };
10244 } else {
10245         var _remove = $.fn.remove;
10246         $.fn.remove = function( selector, keepData ) {
10247                 return this.each(function() {
10248                         if ( !keepData ) {
10249                                 if ( !selector || $.filter( selector, [ this ] ).length ) {
10250                                         $( "*", this ).add( [ this ] ).each(function() {
10251                                                 try {
10252                                                         $( this ).triggerHandler( "remove" );
10253                                                 // http://bugs.jquery.com/ticket/8235
10254                                                 } catch( e ) {}
10255                                         });
10256                                 }
10257                         }
10258                         return _remove.call( $(this), selector, keepData );
10259                 });
10260         };
10261 }
10262
10263 $.widget = function( name, base, prototype ) {
10264         var namespace = name.split( "." )[ 0 ],
10265                 fullName;
10266         name = name.split( "." )[ 1 ];
10267         fullName = namespace + "-" + name;
10268
10269         if ( !prototype ) {
10270                 prototype = base;
10271                 base = $.Widget;
10272         }
10273
10274         // create selector for plugin
10275         $.expr[ ":" ][ fullName ] = function( elem ) {
10276                 return !!$.data( elem, name );
10277         };
10278
10279         $[ namespace ] = $[ namespace ] || {};
10280         $[ namespace ][ name ] = function( options, element ) {
10281                 // allow instantiation without initializing for simple inheritance
10282                 if ( arguments.length ) {
10283                         this._createWidget( options, element );
10284                 }
10285         };
10286
10287         var basePrototype = new base();
10288         // we need to make the options hash a property directly on the new instance
10289         // otherwise we'll modify the options hash on the prototype that we're
10290         // inheriting from
10291 //      $.each( basePrototype, function( key, val ) {
10292 //              if ( $.isPlainObject(val) ) {
10293 //                      basePrototype[ key ] = $.extend( {}, val );
10294 //              }
10295 //      });
10296         basePrototype.options = $.extend( true, {}, basePrototype.options );
10297         $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
10298                 namespace: namespace,
10299                 widgetName: name,
10300                 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
10301                 widgetBaseClass: fullName
10302         }, prototype );
10303
10304         $.widget.bridge( name, $[ namespace ][ name ] );
10305 };
10306
10307 $.widget.bridge = function( name, object ) {
10308         $.fn[ name ] = function( options ) {
10309                 var isMethodCall = typeof options === "string",
10310                         args = Array.prototype.slice.call( arguments, 1 ),
10311                         returnValue = this;
10312
10313                 // allow multiple hashes to be passed on init
10314                 options = !isMethodCall && args.length ?
10315                         $.extend.apply( null, [ true, options ].concat(args) ) :
10316                         options;
10317
10318                 // prevent calls to internal methods
10319                 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
10320                         return returnValue;
10321                 }
10322
10323                 if ( isMethodCall ) {
10324                         this.each(function() {
10325                                 var instance = $.data( this, name ),
10326                                         methodValue = instance && $.isFunction( instance[options] ) ?
10327                                                 instance[ options ].apply( instance, args ) :
10328                                                 instance;
10329                                 // TODO: add this back in 1.9 and use $.error() (see #5972)
10330 //                              if ( !instance ) {
10331 //                                      throw "cannot call methods on " + name + " prior to initialization; " +
10332 //                                              "attempted to call method '" + options + "'";
10333 //                              }
10334 //                              if ( !$.isFunction( instance[options] ) ) {
10335 //                                      throw "no such method '" + options + "' for " + name + " widget instance";
10336 //                              }
10337 //                              var methodValue = instance[ options ].apply( instance, args );
10338                                 if ( methodValue !== instance && methodValue !== undefined ) {
10339                                         returnValue = methodValue;
10340                                         return false;
10341                                 }
10342                         });
10343                 } else {
10344                         this.each(function() {
10345                                 var instance = $.data( this, name );
10346                                 if ( instance ) {
10347                                         instance.option( options || {} )._init();
10348                                 } else {
10349                                         $.data( this, name, new object( options, this ) );
10350                                 }
10351                         });
10352                 }
10353
10354                 return returnValue;
10355         };
10356 };
10357
10358 $.Widget = function( options, element ) {
10359         // allow instantiation without initializing for simple inheritance
10360         if ( arguments.length ) {
10361                 this._createWidget( options, element );
10362         }
10363 };
10364
10365 $.Widget.prototype = {
10366         widgetName: "widget",
10367         widgetEventPrefix: "",
10368         options: {
10369                 disabled: false
10370         },
10371         _createWidget: function( options, element ) {
10372                 // $.widget.bridge stores the plugin instance, but we do it anyway
10373                 // so that it's stored even before the _create function runs
10374                 $.data( element, this.widgetName, this );
10375                 this.element = $( element );
10376                 this.options = $.extend( true, {},
10377                         this.options,
10378                         this._getCreateOptions(),
10379                         options );
10380
10381                 var self = this;
10382                 this.element.bind( "remove." + this.widgetName, function() {
10383                         self.destroy();
10384                 });
10385
10386                 this._create();
10387                 this._trigger( "create" );
10388                 this._init();
10389         },
10390         _getCreateOptions: function() {
10391                 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
10392         },
10393         _create: function() {},
10394         _init: function() {},
10395
10396         destroy: function() {
10397                 this.element
10398                         .unbind( "." + this.widgetName )
10399                         .removeData( this.widgetName );
10400                 this.widget()
10401                         .unbind( "." + this.widgetName )
10402                         .removeAttr( "aria-disabled" )
10403                         .removeClass(
10404                                 this.widgetBaseClass + "-disabled " +
10405                                 "ui-state-disabled" );
10406         },
10407
10408         widget: function() {
10409                 return this.element;
10410         },
10411
10412         option: function( key, value ) {
10413                 var options = key;
10414
10415                 if ( arguments.length === 0 ) {
10416                         // don't return a reference to the internal hash
10417                         return $.extend( {}, this.options );
10418                 }
10419
10420                 if  (typeof key === "string" ) {
10421                         if ( value === undefined ) {
10422                                 return this.options[ key ];
10423                         }
10424                         options = {};
10425                         options[ key ] = value;
10426                 }
10427
10428                 this._setOptions( options );
10429
10430                 return this;
10431         },
10432         _setOptions: function( options ) {
10433                 var self = this;
10434                 $.each( options, function( key, value ) {
10435                         self._setOption( key, value );
10436                 });
10437
10438                 return this;
10439         },
10440         _setOption: function( key, value ) {
10441                 this.options[ key ] = value;
10442
10443                 if ( key === "disabled" ) {
10444                         this.widget()
10445                                 [ value ? "addClass" : "removeClass"](
10446                                         this.widgetBaseClass + "-disabled" + " " +
10447                                         "ui-state-disabled" )
10448                                 .attr( "aria-disabled", value );
10449                 }
10450
10451                 return this;
10452         },
10453
10454         enable: function() {
10455                 return this._setOption( "disabled", false );
10456         },
10457         disable: function() {
10458                 return this._setOption( "disabled", true );
10459         },
10460
10461         _trigger: function( type, event, data ) {
10462                 var callback = this.options[ type ];
10463
10464                 event = $.Event( event );
10465                 event.type = ( type === this.widgetEventPrefix ?
10466                         type :
10467                         this.widgetEventPrefix + type ).toLowerCase();
10468                 data = data || {};
10469
10470                 // copy original event properties over to the new event
10471                 // this would happen if we could call $.event.fix instead of $.Event
10472                 // but we don't have a way to force an event to be fixed multiple times
10473                 if ( event.originalEvent ) {
10474                         for ( var i = $.event.props.length, prop; i; ) {
10475                                 prop = $.event.props[ --i ];
10476                                 event[ prop ] = event.originalEvent[ prop ];
10477                         }
10478                 }
10479
10480                 this.element.trigger( event, data );
10481
10482                 return !( $.isFunction(callback) &&
10483                         callback.call( this.element[0], event, data ) === false ||
10484                         event.isDefaultPrevented() );
10485         }
10486 };
10487
10488 })( jQuery );
10489 /*!
10490  * jQuery UI Mouse 1.8.16
10491  *
10492  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10493  * Dual licensed under the MIT or GPL Version 2 licenses.
10494  * http://jquery.org/license
10495  *
10496  * http://docs.jquery.com/UI/Mouse
10497  *
10498  * Depends:
10499  *      jquery.ui.widget.js
10500  */
10501 (function( $, undefined ) {
10502
10503 var mouseHandled = false;
10504 $( document ).mouseup( function( e ) {
10505         mouseHandled = false;
10506 });
10507
10508 $.widget("ui.mouse", {
10509         options: {
10510                 cancel: ':input,option',
10511                 distance: 1,
10512                 delay: 0
10513         },
10514         _mouseInit: function() {
10515                 var self = this;
10516
10517                 this.element
10518                         .bind('mousedown.'+this.widgetName, function(event) {
10519                                 return self._mouseDown(event);
10520                         })
10521                         .bind('click.'+this.widgetName, function(event) {
10522                                 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
10523                                     $.removeData(event.target, self.widgetName + '.preventClickEvent');
10524                                         event.stopImmediatePropagation();
10525                                         return false;
10526                                 }
10527                         });
10528
10529                 this.started = false;
10530         },
10531
10532         // TODO: make sure destroying one instance of mouse doesn't mess with
10533         // other instances of mouse
10534         _mouseDestroy: function() {
10535                 this.element.unbind('.'+this.widgetName);
10536         },
10537
10538         _mouseDown: function(event) {
10539                 // don't let more than one widget handle mouseStart
10540                 if( mouseHandled ) { return };
10541
10542                 // we may have missed mouseup (out of window)
10543                 (this._mouseStarted && this._mouseUp(event));
10544
10545                 this._mouseDownEvent = event;
10546
10547                 var self = this,
10548                         btnIsLeft = (event.which == 1),
10549                         // event.target.nodeName works around a bug in IE 8 with
10550                         // disabled inputs (#7620)
10551                         elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
10552                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
10553                         return true;
10554                 }
10555
10556                 this.mouseDelayMet = !this.options.delay;
10557                 if (!this.mouseDelayMet) {
10558                         this._mouseDelayTimer = setTimeout(function() {
10559                                 self.mouseDelayMet = true;
10560                         }, this.options.delay);
10561                 }
10562
10563                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
10564                         this._mouseStarted = (this._mouseStart(event) !== false);
10565                         if (!this._mouseStarted) {
10566                                 event.preventDefault();
10567                                 return true;
10568                         }
10569                 }
10570
10571                 // Click event may never have fired (Gecko & Opera)
10572                 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
10573                         $.removeData(event.target, this.widgetName + '.preventClickEvent');
10574                 }
10575
10576                 // these delegates are required to keep context
10577                 this._mouseMoveDelegate = function(event) {
10578                         return self._mouseMove(event);
10579                 };
10580                 this._mouseUpDelegate = function(event) {
10581                         return self._mouseUp(event);
10582                 };
10583                 $(document)
10584                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
10585                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
10586
10587                 event.preventDefault();
10588                 
10589                 mouseHandled = true;
10590                 return true;
10591         },
10592
10593         _mouseMove: function(event) {
10594                 // IE mouseup check - mouseup happened when mouse was out of window
10595                 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
10596                         return this._mouseUp(event);
10597                 }
10598
10599                 if (this._mouseStarted) {
10600                         this._mouseDrag(event);
10601                         return event.preventDefault();
10602                 }
10603
10604                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
10605                         this._mouseStarted =
10606                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
10607                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
10608                 }
10609
10610                 return !this._mouseStarted;
10611         },
10612
10613         _mouseUp: function(event) {
10614                 $(document)
10615                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
10616                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
10617
10618                 if (this._mouseStarted) {
10619                         this._mouseStarted = false;
10620
10621                         if (event.target == this._mouseDownEvent.target) {
10622                             $.data(event.target, this.widgetName + '.preventClickEvent', true);
10623                         }
10624
10625                         this._mouseStop(event);
10626                 }
10627
10628                 return false;
10629         },
10630
10631         _mouseDistanceMet: function(event) {
10632                 return (Math.max(
10633                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
10634                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
10635                         ) >= this.options.distance
10636                 );
10637         },
10638
10639         _mouseDelayMet: function(event) {
10640                 return this.mouseDelayMet;
10641         },
10642
10643         // These are placeholder methods, to be overriden by extending plugin
10644         _mouseStart: function(event) {},
10645         _mouseDrag: function(event) {},
10646         _mouseStop: function(event) {},
10647         _mouseCapture: function(event) { return true; }
10648 });
10649
10650 })(jQuery);
10651 /*
10652  * jQuery UI Draggable 1.8.16
10653  *
10654  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10655  * Dual licensed under the MIT or GPL Version 2 licenses.
10656  * http://jquery.org/license
10657  *
10658  * http://docs.jquery.com/UI/Draggables
10659  *
10660  * Depends:
10661  *      jquery.ui.core.js
10662  *      jquery.ui.mouse.js
10663  *      jquery.ui.widget.js
10664  */
10665 (function( $, undefined ) {
10666
10667 $.widget("ui.draggable", $.ui.mouse, {
10668         widgetEventPrefix: "drag",
10669         options: {
10670                 addClasses: true,
10671                 appendTo: "parent",
10672                 axis: false,
10673                 connectToSortable: false,
10674                 containment: false,
10675                 cursor: "auto",
10676                 cursorAt: false,
10677                 grid: false,
10678                 handle: false,
10679                 helper: "original",
10680                 iframeFix: false,
10681                 opacity: false,
10682                 refreshPositions: false,
10683                 revert: false,
10684                 revertDuration: 500,
10685                 scope: "default",
10686                 scroll: true,
10687                 scrollSensitivity: 20,
10688                 scrollSpeed: 20,
10689                 snap: false,
10690                 snapMode: "both",
10691                 snapTolerance: 20,
10692                 stack: false,
10693                 zIndex: false
10694         },
10695         _create: function() {
10696
10697                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
10698                         this.element[0].style.position = 'relative';
10699
10700                 (this.options.addClasses && this.element.addClass("ui-draggable"));
10701                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
10702
10703                 this._mouseInit();
10704
10705         },
10706
10707         destroy: function() {
10708                 if(!this.element.data('draggable')) return;
10709                 this.element
10710                         .removeData("draggable")
10711                         .unbind(".draggable")
10712                         .removeClass("ui-draggable"
10713                                 + " ui-draggable-dragging"
10714                                 + " ui-draggable-disabled");
10715                 this._mouseDestroy();
10716
10717                 return this;
10718         },
10719
10720         _mouseCapture: function(event) {
10721
10722                 var o = this.options;
10723
10724                 // among others, prevent a drag on a resizable-handle
10725                 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
10726                         return false;
10727
10728                 //Quit if we're not on a valid handle
10729                 this.handle = this._getHandle(event);
10730                 if (!this.handle)
10731                         return false;
10732                 
10733                 if ( o.iframeFix ) {
10734                         $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
10735                                 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
10736                                 .css({
10737                                         width: this.offsetWidth+"px", height: this.offsetHeight+"px",
10738                                         position: "absolute", opacity: "0.001", zIndex: 1000
10739                                 })
10740                                 .css($(this).offset())
10741                                 .appendTo("body");
10742                         });
10743                 }
10744
10745                 return true;
10746
10747         },
10748
10749         _mouseStart: function(event) {
10750
10751                 var o = this.options;
10752
10753                 //Create and append the visible helper
10754                 this.helper = this._createHelper(event);
10755
10756                 //Cache the helper size
10757                 this._cacheHelperProportions();
10758
10759                 //If ddmanager is used for droppables, set the global draggable
10760                 if($.ui.ddmanager)
10761                         $.ui.ddmanager.current = this;
10762
10763                 /*
10764                  * - Position generation -
10765                  * This block generates everything position related - it's the core of draggables.
10766                  */
10767
10768                 //Cache the margins of the original element
10769                 this._cacheMargins();
10770
10771                 //Store the helper's css position
10772                 this.cssPosition = this.helper.css("position");
10773                 this.scrollParent = this.helper.scrollParent();
10774
10775                 //The element's absolute position on the page minus margins
10776                 this.offset = this.positionAbs = this.element.offset();
10777                 this.offset = {
10778                         top: this.offset.top - this.margins.top,
10779                         left: this.offset.left - this.margins.left
10780                 };
10781
10782                 $.extend(this.offset, {
10783                         click: { //Where the click happened, relative to the element
10784                                 left: event.pageX - this.offset.left,
10785                                 top: event.pageY - this.offset.top
10786                         },
10787                         parent: this._getParentOffset(),
10788                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
10789                 });
10790
10791                 //Generate the original position
10792                 this.originalPosition = this.position = this._generatePosition(event);
10793                 this.originalPageX = event.pageX;
10794                 this.originalPageY = event.pageY;
10795
10796                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
10797                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
10798
10799                 //Set a containment if given in the options
10800                 if(o.containment)
10801                         this._setContainment();
10802
10803                 //Trigger event + callbacks
10804                 if(this._trigger("start", event) === false) {
10805                         this._clear();
10806                         return false;
10807                 }
10808
10809                 //Recache the helper size
10810                 this._cacheHelperProportions();
10811
10812                 //Prepare the droppable offsets
10813                 if ($.ui.ddmanager && !o.dropBehaviour)
10814                         $.ui.ddmanager.prepareOffsets(this, event);
10815
10816                 this.helper.addClass("ui-draggable-dragging");
10817                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
10818                 
10819                 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
10820                 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
10821                 
10822                 return true;
10823         },
10824
10825         _mouseDrag: function(event, noPropagation) {
10826
10827                 //Compute the helpers position
10828                 this.position = this._generatePosition(event);
10829                 this.positionAbs = this._convertPositionTo("absolute");
10830
10831                 //Call plugins and callbacks and use the resulting position if something is returned
10832                 if (!noPropagation) {
10833                         var ui = this._uiHash();
10834                         if(this._trigger('drag', event, ui) === false) {
10835                                 this._mouseUp({});
10836                                 return false;
10837                         }
10838                         this.position = ui.position;
10839                 }
10840
10841                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
10842                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
10843                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
10844
10845                 return false;
10846         },
10847
10848         _mouseStop: function(event) {
10849
10850                 //If we are using droppables, inform the manager about the drop
10851                 var dropped = false;
10852                 if ($.ui.ddmanager && !this.options.dropBehaviour)
10853                         dropped = $.ui.ddmanager.drop(this, event);
10854
10855                 //if a drop comes from outside (a sortable)
10856                 if(this.dropped) {
10857                         dropped = this.dropped;
10858                         this.dropped = false;
10859                 }
10860                 
10861                 //if the original element is removed, don't bother to continue if helper is set to "original"
10862                 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
10863                         return false;
10864
10865                 if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
10866                         var self = this;
10867                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
10868                                 if(self._trigger("stop", event) !== false) {
10869                                         self._clear();
10870                                 }
10871                         });
10872                 } else {
10873                         if(this._trigger("stop", event) !== false) {
10874                                 this._clear();
10875                         }
10876                 }
10877
10878                 return false;
10879         },
10880         
10881         _mouseUp: function(event) {
10882                 if (this.options.iframeFix === true) {
10883                         $("div.ui-draggable-iframeFix").each(function() { 
10884                                 this.parentNode.removeChild(this); 
10885                         }); //Remove frame helpers
10886                 }
10887                 
10888                 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
10889                 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
10890                 
10891                 return $.ui.mouse.prototype._mouseUp.call(this, event);
10892         },
10893         
10894         cancel: function() {
10895                 
10896                 if(this.helper.is(".ui-draggable-dragging")) {
10897                         this._mouseUp({});
10898                 } else {
10899                         this._clear();
10900                 }
10901                 
10902                 return this;
10903                 
10904         },
10905
10906         _getHandle: function(event) {
10907
10908                 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
10909                 $(this.options.handle, this.element)
10910                         .find("*")
10911                         .andSelf()
10912                         .each(function() {
10913                                 if(this == event.target) handle = true;
10914                         });
10915
10916                 return handle;
10917
10918         },
10919
10920         _createHelper: function(event) {
10921
10922                 var o = this.options;
10923                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
10924
10925                 if(!helper.parents('body').length)
10926                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
10927
10928                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
10929                         helper.css("position", "absolute");
10930
10931                 return helper;
10932
10933         },
10934
10935         _adjustOffsetFromHelper: function(obj) {
10936                 if (typeof obj == 'string') {
10937                         obj = obj.split(' ');
10938                 }
10939                 if ($.isArray(obj)) {
10940                         obj = {left: +obj[0], top: +obj[1] || 0};
10941                 }
10942                 if ('left' in obj) {
10943                         this.offset.click.left = obj.left + this.margins.left;
10944                 }
10945                 if ('right' in obj) {
10946                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
10947                 }
10948                 if ('top' in obj) {
10949                         this.offset.click.top = obj.top + this.margins.top;
10950                 }
10951                 if ('bottom' in obj) {
10952                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
10953                 }
10954         },
10955
10956         _getParentOffset: function() {
10957
10958                 //Get the offsetParent and cache its position
10959                 this.offsetParent = this.helper.offsetParent();
10960                 var po = this.offsetParent.offset();
10961
10962                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
10963                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
10964                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
10965                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
10966                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
10967                         po.left += this.scrollParent.scrollLeft();
10968                         po.top += this.scrollParent.scrollTop();
10969                 }
10970
10971                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
10972                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
10973                         po = { top: 0, left: 0 };
10974
10975                 return {
10976                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
10977                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
10978                 };
10979
10980         },
10981
10982         _getRelativeOffset: function() {
10983
10984                 if(this.cssPosition == "relative") {
10985                         var p = this.element.position();
10986                         return {
10987                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
10988                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
10989                         };
10990                 } else {
10991                         return { top: 0, left: 0 };
10992                 }
10993
10994         },
10995
10996         _cacheMargins: function() {
10997                 this.margins = {
10998                         left: (parseInt(this.element.css("marginLeft"),10) || 0),
10999                         top: (parseInt(this.element.css("marginTop"),10) || 0),
11000                         right: (parseInt(this.element.css("marginRight"),10) || 0),
11001                         bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
11002                 };
11003         },
11004
11005         _cacheHelperProportions: function() {
11006                 this.helperProportions = {
11007                         width: this.helper.outerWidth(),
11008                         height: this.helper.outerHeight()
11009                 };
11010         },
11011
11012         _setContainment: function() {
11013
11014                 var o = this.options;
11015                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
11016                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
11017                         o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
11018                         o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
11019                         (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
11020                         (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
11021                 ];
11022
11023                 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
11024                         var c = $(o.containment);
11025                         var ce = c[0]; if(!ce) return;
11026                         var co = c.offset();
11027                         var over = ($(ce).css("overflow") != 'hidden');
11028
11029                         this.containment = [
11030                                 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
11031                                 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
11032                                 (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
11033                                 (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom
11034                         ];
11035                         this.relative_container = c;
11036
11037                 } else if(o.containment.constructor == Array) {
11038                         this.containment = o.containment;
11039                 }
11040
11041         },
11042
11043         _convertPositionTo: function(d, pos) {
11044
11045                 if(!pos) pos = this.position;
11046                 var mod = d == "absolute" ? 1 : -1;
11047                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
11048
11049                 return {
11050                         top: (
11051                                 pos.top                                                                                                                                 // The absolute mouse position
11052                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
11053                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
11054                                 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
11055                         ),
11056                         left: (
11057                                 pos.left                                                                                                                                // The absolute mouse position
11058                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
11059                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
11060                                 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
11061                         )
11062                 };
11063
11064         },
11065
11066         _generatePosition: function(event) {
11067
11068                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
11069                 var pageX = event.pageX;
11070                 var pageY = event.pageY;
11071
11072                 /*
11073                  * - Position constraining -
11074                  * Constrain the position to a mix of grid, containment.
11075                  */
11076
11077                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
11078                          var containment;
11079                          if(this.containment) {
11080                                  if (this.relative_container){
11081                                      var co = this.relative_container.offset();
11082                                      containment = [ this.containment[0] + co.left,
11083                                                      this.containment[1] + co.top,
11084                                                      this.containment[2] + co.left,
11085                                                      this.containment[3] + co.top ];
11086                                  }
11087                                  else {
11088                                      containment = this.containment;
11089                                  }
11090
11091                                 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
11092                                 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
11093                                 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
11094                                 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
11095                         }
11096
11097                         if(o.grid) {
11098                                 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
11099                                 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
11100                                 pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
11101
11102                                 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
11103                                 pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
11104                         }
11105
11106                 }
11107
11108                 return {
11109                         top: (
11110                                 pageY                                                                                                                           // The absolute mouse position
11111                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
11112                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
11113                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
11114                                 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
11115                         ),
11116                         left: (
11117                                 pageX                                                                                                                           // The absolute mouse position
11118                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
11119                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
11120                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
11121                                 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
11122                         )
11123                 };
11124
11125         },
11126
11127         _clear: function() {
11128                 this.helper.removeClass("ui-draggable-dragging");
11129                 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
11130                 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
11131                 this.helper = null;
11132                 this.cancelHelperRemoval = false;
11133         },
11134
11135         // From now on bulk stuff - mainly helpers
11136
11137         _trigger: function(type, event, ui) {
11138                 ui = ui || this._uiHash();
11139                 $.ui.plugin.call(this, type, [event, ui]);
11140                 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
11141                 return $.Widget.prototype._trigger.call(this, type, event, ui);
11142         },
11143
11144         plugins: {},
11145
11146         _uiHash: function(event) {
11147                 return {
11148                         helper: this.helper,
11149                         position: this.position,
11150                         originalPosition: this.originalPosition,
11151                         offset: this.positionAbs
11152                 };
11153         }
11154
11155 });
11156
11157 $.extend($.ui.draggable, {
11158         version: "1.8.16"
11159 });
11160
11161 $.ui.plugin.add("draggable", "connectToSortable", {
11162         start: function(event, ui) {
11163
11164                 var inst = $(this).data("draggable"), o = inst.options,
11165                         uiSortable = $.extend({}, ui, { item: inst.element });
11166                 inst.sortables = [];
11167                 $(o.connectToSortable).each(function() {
11168                         var sortable = $.data(this, 'sortable');
11169                         if (sortable && !sortable.options.disabled) {
11170                                 inst.sortables.push({
11171                                         instance: sortable,
11172                                         shouldRevert: sortable.options.revert
11173                                 });
11174                                 sortable.refreshPositions();    // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
11175                                 sortable._trigger("activate", event, uiSortable);
11176                         }
11177                 });
11178
11179         },
11180         stop: function(event, ui) {
11181
11182                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
11183                 var inst = $(this).data("draggable"),
11184                         uiSortable = $.extend({}, ui, { item: inst.element });
11185
11186                 $.each(inst.sortables, function() {
11187                         if(this.instance.isOver) {
11188
11189                                 this.instance.isOver = 0;
11190
11191                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
11192                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
11193
11194                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
11195                                 if(this.shouldRevert) this.instance.options.revert = true;
11196
11197                                 //Trigger the stop of the sortable
11198                                 this.instance._mouseStop(event);
11199
11200                                 this.instance.options.helper = this.instance.options._helper;
11201
11202                                 //If the helper has been the original item, restore properties in the sortable
11203                                 if(inst.options.helper == 'original')
11204                                         this.instance.currentItem.css({ top: 'auto', left: 'auto' });
11205
11206                         } else {
11207                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
11208                                 this.instance._trigger("deactivate", event, uiSortable);
11209                         }
11210
11211                 });
11212
11213         },
11214         drag: function(event, ui) {
11215
11216                 var inst = $(this).data("draggable"), self = this;
11217
11218                 var checkPos = function(o) {
11219                         var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
11220                         var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
11221                         var itemHeight = o.height, itemWidth = o.width;
11222                         var itemTop = o.top, itemLeft = o.left;
11223
11224                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
11225                 };
11226
11227                 $.each(inst.sortables, function(i) {
11228                         
11229                         //Copy over some variables to allow calling the sortable's native _intersectsWith
11230                         this.instance.positionAbs = inst.positionAbs;
11231                         this.instance.helperProportions = inst.helperProportions;
11232                         this.instance.offset.click = inst.offset.click;
11233                         
11234                         if(this.instance._intersectsWith(this.instance.containerCache)) {
11235
11236                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
11237                                 if(!this.instance.isOver) {
11238
11239                                         this.instance.isOver = 1;
11240                                         //Now we fake the start of dragging for the sortable instance,
11241                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
11242                                         //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
11243                                         this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
11244                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
11245                                         this.instance.options.helper = function() { return ui.helper[0]; };
11246
11247                                         event.target = this.instance.currentItem[0];
11248                                         this.instance._mouseCapture(event, true);
11249                                         this.instance._mouseStart(event, true, true);
11250
11251                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
11252                                         this.instance.offset.click.top = inst.offset.click.top;
11253                                         this.instance.offset.click.left = inst.offset.click.left;
11254                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
11255                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
11256
11257                                         inst._trigger("toSortable", event);
11258                                         inst.dropped = this.instance.element; //draggable revert needs that
11259                                         //hack so receive/update callbacks work (mostly)
11260                                         inst.currentItem = inst.element;
11261                                         this.instance.fromOutside = inst;
11262
11263                                 }
11264
11265                                 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
11266                                 if(this.instance.currentItem) this.instance._mouseDrag(event);
11267
11268                         } else {
11269
11270                                 //If it doesn't intersect with the sortable, and it intersected before,
11271                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
11272                                 if(this.instance.isOver) {
11273
11274                                         this.instance.isOver = 0;
11275                                         this.instance.cancelHelperRemoval = true;
11276                                         
11277                                         //Prevent reverting on this forced stop
11278                                         this.instance.options.revert = false;
11279                                         
11280                                         // The out event needs to be triggered independently
11281                                         this.instance._trigger('out', event, this.instance._uiHash(this.instance));
11282                                         
11283                                         this.instance._mouseStop(event, true);
11284                                         this.instance.options.helper = this.instance.options._helper;
11285
11286                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
11287                                         this.instance.currentItem.remove();
11288                                         if(this.instance.placeholder) this.instance.placeholder.remove();
11289
11290                                         inst._trigger("fromSortable", event);
11291                                         inst.dropped = false; //draggable revert needs that
11292                                 }
11293
11294                         };
11295
11296                 });
11297
11298         }
11299 });
11300
11301 $.ui.plugin.add("draggable", "cursor", {
11302         start: function(event, ui) {
11303                 var t = $('body'), o = $(this).data('draggable').options;
11304                 if (t.css("cursor")) o._cursor = t.css("cursor");
11305                 t.css("cursor", o.cursor);
11306         },
11307         stop: function(event, ui) {
11308                 var o = $(this).data('draggable').options;
11309                 if (o._cursor) $('body').css("cursor", o._cursor);
11310         }
11311 });
11312
11313 $.ui.plugin.add("draggable", "opacity", {
11314         start: function(event, ui) {
11315                 var t = $(ui.helper), o = $(this).data('draggable').options;
11316                 if(t.css("opacity")) o._opacity = t.css("opacity");
11317                 t.css('opacity', o.opacity);
11318         },
11319         stop: function(event, ui) {
11320                 var o = $(this).data('draggable').options;
11321                 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
11322         }
11323 });
11324
11325 $.ui.plugin.add("draggable", "scroll", {
11326         start: function(event, ui) {
11327                 var i = $(this).data("draggable");
11328                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
11329         },
11330         drag: function(event, ui) {
11331
11332                 var i = $(this).data("draggable"), o = i.options, scrolled = false;
11333
11334                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
11335
11336                         if(!o.axis || o.axis != 'x') {
11337                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
11338                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
11339                                 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
11340                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
11341                         }
11342
11343                         if(!o.axis || o.axis != 'y') {
11344                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
11345                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
11346                                 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
11347                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
11348                         }
11349
11350                 } else {
11351
11352                         if(!o.axis || o.axis != 'x') {
11353                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
11354                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
11355                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
11356                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
11357                         }
11358
11359                         if(!o.axis || o.axis != 'y') {
11360                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
11361                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
11362                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
11363                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
11364                         }
11365
11366                 }
11367
11368                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
11369                         $.ui.ddmanager.prepareOffsets(i, event);
11370
11371         }
11372 });
11373
11374 $.ui.plugin.add("draggable", "snap", {
11375         start: function(event, ui) {
11376
11377                 var i = $(this).data("draggable"), o = i.options;
11378                 i.snapElements = [];
11379
11380                 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
11381                         var $t = $(this); var $o = $t.offset();
11382                         if(this != i.element[0]) i.snapElements.push({
11383                                 item: this,
11384                                 width: $t.outerWidth(), height: $t.outerHeight(),
11385                                 top: $o.top, left: $o.left
11386                         });
11387                 });
11388
11389         },
11390         drag: function(event, ui) {
11391
11392                 var inst = $(this).data("draggable"), o = inst.options;
11393                 var d = o.snapTolerance;
11394
11395                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
11396                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
11397
11398                 for (var i = inst.snapElements.length - 1; i >= 0; i--){
11399
11400                         var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
11401                                 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
11402
11403                         //Yes, I know, this is insane ;)
11404                         if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
11405                                 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
11406                                 inst.snapElements[i].snapping = false;
11407                                 continue;
11408                         }
11409
11410                         if(o.snapMode != 'inner') {
11411                                 var ts = Math.abs(t - y2) <= d;
11412                                 var bs = Math.abs(b - y1) <= d;
11413                                 var ls = Math.abs(l - x2) <= d;
11414                                 var rs = Math.abs(r - x1) <= d;
11415                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
11416                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
11417                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
11418                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
11419                         }
11420
11421                         var first = (ts || bs || ls || rs);
11422
11423                         if(o.snapMode != 'outer') {
11424                                 var ts = Math.abs(t - y1) <= d;
11425                                 var bs = Math.abs(b - y2) <= d;
11426                                 var ls = Math.abs(l - x1) <= d;
11427                                 var rs = Math.abs(r - x2) <= d;
11428                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
11429                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
11430                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
11431                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
11432                         }
11433
11434                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
11435                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
11436                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
11437
11438                 };
11439
11440         }
11441 });
11442
11443 $.ui.plugin.add("draggable", "stack", {
11444         start: function(event, ui) {
11445
11446                 var o = $(this).data("draggable").options;
11447
11448                 var group = $.makeArray($(o.stack)).sort(function(a,b) {
11449                         return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
11450                 });
11451                 if (!group.length) { return; }
11452                 
11453                 var min = parseInt(group[0].style.zIndex) || 0;
11454                 $(group).each(function(i) {
11455                         this.style.zIndex = min + i;
11456                 });
11457
11458                 this[0].style.zIndex = min + group.length;
11459
11460         }
11461 });
11462
11463 $.ui.plugin.add("draggable", "zIndex", {
11464         start: function(event, ui) {
11465                 var t = $(ui.helper), o = $(this).data("draggable").options;
11466                 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
11467                 t.css('zIndex', o.zIndex);
11468         },
11469         stop: function(event, ui) {
11470                 var o = $(this).data("draggable").options;
11471                 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
11472         }
11473 });
11474
11475 })(jQuery);
11476 /*
11477  * jQuery UI Droppable 1.8.16
11478  *
11479  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11480  * Dual licensed under the MIT or GPL Version 2 licenses.
11481  * http://jquery.org/license
11482  *
11483  * http://docs.jquery.com/UI/Droppables
11484  *
11485  * Depends:
11486  *      jquery.ui.core.js
11487  *      jquery.ui.widget.js
11488  *      jquery.ui.mouse.js
11489  *      jquery.ui.draggable.js
11490  */
11491 (function( $, undefined ) {
11492
11493 $.widget("ui.droppable", {
11494         widgetEventPrefix: "drop",
11495         options: {
11496                 accept: '*',
11497                 activeClass: false,
11498                 addClasses: true,
11499                 greedy: false,
11500                 hoverClass: false,
11501                 scope: 'default',
11502                 tolerance: 'intersect'
11503         },
11504         _create: function() {
11505
11506                 var o = this.options, accept = o.accept;
11507                 this.isover = 0; this.isout = 1;
11508
11509                 this.accept = $.isFunction(accept) ? accept : function(d) {
11510                         return d.is(accept);
11511                 };
11512
11513                 //Store the droppable's proportions
11514                 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
11515
11516                 // Add the reference and positions to the manager
11517                 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
11518                 $.ui.ddmanager.droppables[o.scope].push(this);
11519
11520                 (o.addClasses && this.element.addClass("ui-droppable"));
11521
11522         },
11523
11524         destroy: function() {
11525                 var drop = $.ui.ddmanager.droppables[this.options.scope];
11526                 for ( var i = 0; i < drop.length; i++ )
11527                         if ( drop[i] == this )
11528                                 drop.splice(i, 1);
11529
11530                 this.element
11531                         .removeClass("ui-droppable ui-droppable-disabled")
11532                         .removeData("droppable")
11533                         .unbind(".droppable");
11534
11535                 return this;
11536         },
11537
11538         _setOption: function(key, value) {
11539
11540                 if(key == 'accept') {
11541                         this.accept = $.isFunction(value) ? value : function(d) {
11542                                 return d.is(value);
11543                         };
11544                 }
11545                 $.Widget.prototype._setOption.apply(this, arguments);
11546         },
11547
11548         _activate: function(event) {
11549                 var draggable = $.ui.ddmanager.current;
11550                 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
11551                 (draggable && this._trigger('activate', event, this.ui(draggable)));
11552         },
11553
11554         _deactivate: function(event) {
11555                 var draggable = $.ui.ddmanager.current;
11556                 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
11557                 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
11558         },
11559
11560         _over: function(event) {
11561
11562                 var draggable = $.ui.ddmanager.current;
11563                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
11564
11565                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
11566                         if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
11567                         this._trigger('over', event, this.ui(draggable));
11568                 }
11569
11570         },
11571
11572         _out: function(event) {
11573
11574                 var draggable = $.ui.ddmanager.current;
11575                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
11576
11577                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
11578                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
11579                         this._trigger('out', event, this.ui(draggable));
11580                 }
11581
11582         },
11583
11584         _drop: function(event,custom) {
11585
11586                 var draggable = custom || $.ui.ddmanager.current;
11587                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
11588
11589                 var childrenIntersection = false;
11590                 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
11591                         var inst = $.data(this, 'droppable');
11592                         if(
11593                                 inst.options.greedy
11594                                 && !inst.options.disabled
11595                                 && inst.options.scope == draggable.options.scope
11596                                 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
11597                                 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
11598                         ) { childrenIntersection = true; return false; }
11599                 });
11600                 if(childrenIntersection) return false;
11601
11602                 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
11603                         if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
11604                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
11605                         this._trigger('drop', event, this.ui(draggable));
11606                         return this.element;
11607                 }
11608
11609                 return false;
11610
11611         },
11612
11613         ui: function(c) {
11614                 return {
11615                         draggable: (c.currentItem || c.element),
11616                         helper: c.helper,
11617                         position: c.position,
11618                         offset: c.positionAbs
11619                 };
11620         }
11621
11622 });
11623
11624 $.extend($.ui.droppable, {
11625         version: "1.8.16"
11626 });
11627
11628 $.ui.intersect = function(draggable, droppable, toleranceMode) {
11629
11630         if (!droppable.offset) return false;
11631
11632         var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
11633                 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
11634         var l = droppable.offset.left, r = l + droppable.proportions.width,
11635                 t = droppable.offset.top, b = t + droppable.proportions.height;
11636
11637         switch (toleranceMode) {
11638                 case 'fit':
11639                         return (l <= x1 && x2 <= r
11640                                 && t <= y1 && y2 <= b);
11641                         break;
11642                 case 'intersect':
11643                         return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
11644                                 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
11645                                 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
11646                                 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
11647                         break;
11648                 case 'pointer':
11649                         var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
11650                                 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
11651                                 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
11652                         return isOver;
11653                         break;
11654                 case 'touch':
11655                         return (
11656                                         (y1 >= t && y1 <= b) || // Top edge touching
11657                                         (y2 >= t && y2 <= b) || // Bottom edge touching
11658                                         (y1 < t && y2 > b)              // Surrounded vertically
11659                                 ) && (
11660                                         (x1 >= l && x1 <= r) || // Left edge touching
11661                                         (x2 >= l && x2 <= r) || // Right edge touching
11662                                         (x1 < l && x2 > r)              // Surrounded horizontally
11663                                 );
11664                         break;
11665                 default:
11666                         return false;
11667                         break;
11668                 }
11669
11670 };
11671
11672 /*
11673         This manager tracks offsets of draggables and droppables
11674 */
11675 $.ui.ddmanager = {
11676         current: null,
11677         droppables: { 'default': [] },
11678         prepareOffsets: function(t, event) {
11679
11680                 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
11681                 var type = event ? event.type : null; // workaround for #2317
11682                 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
11683
11684                 droppablesLoop: for (var i = 0; i < m.length; i++) {
11685
11686                         if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
11687                         for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
11688                         m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
11689
11690                         if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
11691
11692                         m[i].offset = m[i].element.offset();
11693                         m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
11694
11695                 }
11696
11697         },
11698         drop: function(draggable, event) {
11699
11700                 var dropped = false;
11701                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
11702
11703                         if(!this.options) return;
11704                         if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
11705                                 dropped = dropped || this._drop.call(this, event);
11706
11707                         if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
11708                                 this.isout = 1; this.isover = 0;
11709                                 this._deactivate.call(this, event);
11710                         }
11711
11712                 });
11713                 return dropped;
11714
11715         },
11716         dragStart: function( draggable, event ) {
11717                 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
11718                 draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() {
11719                         if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
11720                 });
11721         },
11722         drag: function(draggable, event) {
11723
11724                 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
11725                 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
11726
11727                 //Run through all droppables and check their positions based on specific tolerance options
11728                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
11729
11730                         if(this.options.disabled || this.greedyChild || !this.visible) return;
11731                         var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
11732
11733                         var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
11734                         if(!c) return;
11735
11736                         var parentInstance;
11737                         if (this.options.greedy) {
11738                                 var parent = this.element.parents(':data(droppable):eq(0)');
11739                                 if (parent.length) {
11740                                         parentInstance = $.data(parent[0], 'droppable');
11741                                         parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
11742                                 }
11743                         }
11744
11745                         // we just moved into a greedy child
11746                         if (parentInstance && c == 'isover') {
11747                                 parentInstance['isover'] = 0;
11748                                 parentInstance['isout'] = 1;
11749                                 parentInstance._out.call(parentInstance, event);
11750                         }
11751
11752                         this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
11753                         this[c == "isover" ? "_over" : "_out"].call(this, event);
11754
11755                         // we just moved out of a greedy child
11756                         if (parentInstance && c == 'isout') {
11757                                 parentInstance['isout'] = 0;
11758                                 parentInstance['isover'] = 1;
11759                                 parentInstance._over.call(parentInstance, event);
11760                         }
11761                 });
11762
11763         },
11764         dragStop: function( draggable, event ) {
11765                 draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" );
11766                 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
11767                 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
11768         }
11769 };
11770
11771 })(jQuery);
11772 /*
11773  * jQuery UI Resizable 1.8.16
11774  *
11775  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11776  * Dual licensed under the MIT or GPL Version 2 licenses.
11777  * http://jquery.org/license
11778  *
11779  * http://docs.jquery.com/UI/Resizables
11780  *
11781  * Depends:
11782  *      jquery.ui.core.js
11783  *      jquery.ui.mouse.js
11784  *      jquery.ui.widget.js
11785  */
11786 (function( $, undefined ) {
11787
11788 $.widget("ui.resizable", $.ui.mouse, {
11789         widgetEventPrefix: "resize",
11790         options: {
11791                 alsoResize: false,
11792                 animate: false,
11793                 animateDuration: "slow",
11794                 animateEasing: "swing",
11795                 aspectRatio: false,
11796                 autoHide: false,
11797                 containment: false,
11798                 ghost: false,
11799                 grid: false,
11800                 handles: "e,s,se",
11801                 helper: false,
11802                 maxHeight: null,
11803                 maxWidth: null,
11804                 minHeight: 10,
11805                 minWidth: 10,
11806                 zIndex: 1000
11807         },
11808         _create: function() {
11809
11810                 var self = this, o = this.options;
11811                 this.element.addClass("ui-resizable");
11812
11813                 $.extend(this, {
11814                         _aspectRatio: !!(o.aspectRatio),
11815                         aspectRatio: o.aspectRatio,
11816                         originalElement: this.element,
11817                         _proportionallyResizeElements: [],
11818                         _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
11819                 });
11820
11821                 //Wrap the element if it cannot hold child nodes
11822                 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
11823
11824                         //Opera fix for relative positioning
11825                         if (/relative/.test(this.element.css('position')) && $.browser.opera)
11826                                 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
11827
11828                         //Create a wrapper element and set the wrapper to the new current internal element
11829                         this.element.wrap(
11830                                 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
11831                                         position: this.element.css('position'),
11832                                         width: this.element.outerWidth(),
11833                                         height: this.element.outerHeight(),
11834                                         top: this.element.css('top'),
11835                                         left: this.element.css('left')
11836                                 })
11837                         );
11838
11839                         //Overwrite the original this.element
11840                         this.element = this.element.parent().data(
11841                                 "resizable", this.element.data('resizable')
11842                         );
11843
11844                         this.elementIsWrapper = true;
11845
11846                         //Move margins to the wrapper
11847                         this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
11848                         this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
11849
11850                         //Prevent Safari textarea resize
11851                         this.originalResizeStyle = this.originalElement.css('resize');
11852                         this.originalElement.css('resize', 'none');
11853
11854                         //Push the actual element to our proportionallyResize internal array
11855                         this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
11856
11857                         // avoid IE jump (hard set the margin)
11858                         this.originalElement.css({ margin: this.originalElement.css('margin') });
11859
11860                         // fix handlers offset
11861                         this._proportionallyResize();
11862
11863                 }
11864
11865                 this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
11866                 if(this.handles.constructor == String) {
11867
11868                         if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
11869                         var n = this.handles.split(","); this.handles = {};
11870
11871                         for(var i = 0; i < n.length; i++) {
11872
11873                                 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
11874                                 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
11875
11876                                 // increase zIndex of sw, se, ne, nw axis
11877                                 //TODO : this modifies original option
11878                                 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
11879
11880                                 //TODO : What's going on here?
11881                                 if ('se' == handle) {
11882                                         axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
11883                                 };
11884
11885                                 //Insert into internal handles object and append to element
11886                                 this.handles[handle] = '.ui-resizable-'+handle;
11887                                 this.element.append(axis);
11888                         }
11889
11890                 }
11891
11892                 this._renderAxis = function(target) {
11893
11894                         target = target || this.element;
11895
11896                         for(var i in this.handles) {
11897
11898                                 if(this.handles[i].constructor == String)
11899                                         this.handles[i] = $(this.handles[i], this.element).show();
11900
11901                                 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
11902                                 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
11903
11904                                         var axis = $(this.handles[i], this.element), padWrapper = 0;
11905
11906                                         //Checking the correct pad and border
11907                                         padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
11908
11909                                         //The padding type i have to apply...
11910                                         var padPos = [ 'padding',
11911                                                 /ne|nw|n/.test(i) ? 'Top' :
11912                                                 /se|sw|s/.test(i) ? 'Bottom' :
11913                                                 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
11914
11915                                         target.css(padPos, padWrapper);
11916
11917                                         this._proportionallyResize();
11918
11919                                 }
11920
11921                                 //TODO: What's that good for? There's not anything to be executed left
11922                                 if(!$(this.handles[i]).length)
11923                                         continue;
11924
11925                         }
11926                 };
11927
11928                 //TODO: make renderAxis a prototype function
11929                 this._renderAxis(this.element);
11930
11931                 this._handles = $('.ui-resizable-handle', this.element)
11932                         .disableSelection();
11933
11934                 //Matching axis name
11935                 this._handles.mouseover(function() {
11936                         if (!self.resizing) {
11937                                 if (this.className)
11938                                         var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
11939                                 //Axis, default = se
11940                                 self.axis = axis && axis[1] ? axis[1] : 'se';
11941                         }
11942                 });
11943
11944                 //If we want to auto hide the elements
11945                 if (o.autoHide) {
11946                         this._handles.hide();
11947                         $(this.element)
11948                                 .addClass("ui-resizable-autohide")
11949                                 .hover(function() {
11950                                         if (o.disabled) return;
11951                                         $(this).removeClass("ui-resizable-autohide");
11952                                         self._handles.show();
11953                                 },
11954                                 function(){
11955                                         if (o.disabled) return;
11956                                         if (!self.resizing) {
11957                                                 $(this).addClass("ui-resizable-autohide");
11958                                                 self._handles.hide();
11959                                         }
11960                                 });
11961                 }
11962
11963                 //Initialize the mouse interaction
11964                 this._mouseInit();
11965
11966         },
11967
11968         destroy: function() {
11969
11970                 this._mouseDestroy();
11971
11972                 var _destroy = function(exp) {
11973                         $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
11974                                 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
11975                 };
11976
11977                 //TODO: Unwrap at same DOM position
11978                 if (this.elementIsWrapper) {
11979                         _destroy(this.element);
11980                         var wrapper = this.element;
11981                         wrapper.after(
11982                                 this.originalElement.css({
11983                                         position: wrapper.css('position'),
11984                                         width: wrapper.outerWidth(),
11985                                         height: wrapper.outerHeight(),
11986                                         top: wrapper.css('top'),
11987                                         left: wrapper.css('left')
11988                                 })
11989                         ).remove();
11990                 }
11991
11992                 this.originalElement.css('resize', this.originalResizeStyle);
11993                 _destroy(this.originalElement);
11994
11995                 return this;
11996         },
11997
11998         _mouseCapture: function(event) {
11999                 var handle = false;
12000                 for (var i in this.handles) {
12001                         if ($(this.handles[i])[0] == event.target) {
12002                                 handle = true;
12003                         }
12004                 }
12005
12006                 return !this.options.disabled && handle;
12007         },
12008
12009         _mouseStart: function(event) {
12010
12011                 var o = this.options, iniPos = this.element.position(), el = this.element;
12012
12013                 this.resizing = true;
12014                 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
12015
12016                 // bugfix for http://dev.jquery.com/ticket/1749
12017                 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
12018                         el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
12019                 }
12020
12021                 //Opera fixing relative position
12022                 if ($.browser.opera && (/relative/).test(el.css('position')))
12023                         el.css({ position: 'relative', top: 'auto', left: 'auto' });
12024
12025                 this._renderProxy();
12026
12027                 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
12028
12029                 if (o.containment) {
12030                         curleft += $(o.containment).scrollLeft() || 0;
12031                         curtop += $(o.containment).scrollTop() || 0;
12032                 }
12033
12034                 //Store needed variables
12035                 this.offset = this.helper.offset();
12036                 this.position = { left: curleft, top: curtop };
12037                 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
12038                 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
12039                 this.originalPosition = { left: curleft, top: curtop };
12040                 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
12041                 this.originalMousePosition = { left: event.pageX, top: event.pageY };
12042
12043                 //Aspect Ratio
12044                 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
12045
12046             var cursor = $('.ui-resizable-' + this.axis).css('cursor');
12047             $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
12048
12049                 el.addClass("ui-resizable-resizing");
12050                 this._propagate("start", event);
12051                 return true;
12052         },
12053
12054         _mouseDrag: function(event) {
12055
12056                 //Increase performance, avoid regex
12057                 var el = this.helper, o = this.options, props = {},
12058                         self = this, smp = this.originalMousePosition, a = this.axis;
12059
12060                 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
12061                 var trigger = this._change[a];
12062                 if (!trigger) return false;
12063
12064                 // Calculate the attrs that will be change
12065                 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
12066
12067                 // Put this in the mouseDrag handler since the user can start pressing shift while resizing
12068                 this._updateVirtualBoundaries(event.shiftKey);
12069                 if (this._aspectRatio || event.shiftKey)
12070                         data = this._updateRatio(data, event);
12071
12072                 data = this._respectSize(data, event);
12073
12074                 // plugins callbacks need to be called first
12075                 this._propagate("resize", event);
12076
12077                 el.css({
12078                         top: this.position.top + "px", left: this.position.left + "px",
12079                         width: this.size.width + "px", height: this.size.height + "px"
12080                 });
12081
12082                 if (!this._helper && this._proportionallyResizeElements.length)
12083                         this._proportionallyResize();
12084
12085                 this._updateCache(data);
12086
12087                 // calling the user callback at the end
12088                 this._trigger('resize', event, this.ui());
12089
12090                 return false;
12091         },
12092
12093         _mouseStop: function(event) {
12094
12095                 this.resizing = false;
12096                 var o = this.options, self = this;
12097
12098                 if(this._helper) {
12099                         var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
12100                                 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
12101                                 soffsetw = ista ? 0 : self.sizeDiff.width;
12102
12103                         var s = { width: (self.helper.width()  - soffsetw), height: (self.helper.height() - soffseth) },
12104                                 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
12105                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
12106
12107                         if (!o.animate)
12108                                 this.element.css($.extend(s, { top: top, left: left }));
12109
12110                         self.helper.height(self.size.height);
12111                         self.helper.width(self.size.width);
12112
12113                         if (this._helper && !o.animate) this._proportionallyResize();
12114                 }
12115
12116                 $('body').css('cursor', 'auto');
12117
12118                 this.element.removeClass("ui-resizable-resizing");
12119
12120                 this._propagate("stop", event);
12121
12122                 if (this._helper) this.helper.remove();
12123                 return false;
12124
12125         },
12126
12127     _updateVirtualBoundaries: function(forceAspectRatio) {
12128         var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
12129
12130         b = {
12131             minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
12132             maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
12133             minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
12134             maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
12135         };
12136
12137         if(this._aspectRatio || forceAspectRatio) {
12138             // We want to create an enclosing box whose aspect ration is the requested one
12139             // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
12140             pMinWidth = b.minHeight * this.aspectRatio;
12141             pMinHeight = b.minWidth / this.aspectRatio;
12142             pMaxWidth = b.maxHeight * this.aspectRatio;
12143             pMaxHeight = b.maxWidth / this.aspectRatio;
12144
12145             if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
12146             if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
12147             if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
12148             if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
12149         }
12150         this._vBoundaries = b;
12151     },
12152
12153         _updateCache: function(data) {
12154                 var o = this.options;
12155                 this.offset = this.helper.offset();
12156                 if (isNumber(data.left)) this.position.left = data.left;
12157                 if (isNumber(data.top)) this.position.top = data.top;
12158                 if (isNumber(data.height)) this.size.height = data.height;
12159                 if (isNumber(data.width)) this.size.width = data.width;
12160         },
12161
12162         _updateRatio: function(data, event) {
12163
12164                 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
12165
12166                 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
12167                 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
12168
12169                 if (a == 'sw') {
12170                         data.left = cpos.left + (csize.width - data.width);
12171                         data.top = null;
12172                 }
12173                 if (a == 'nw') {
12174                         data.top = cpos.top + (csize.height - data.height);
12175                         data.left = cpos.left + (csize.width - data.width);
12176                 }
12177
12178                 return data;
12179         },
12180
12181         _respectSize: function(data, event) {
12182
12183                 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
12184                                 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
12185                                         isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
12186
12187                 if (isminw) data.width = o.minWidth;
12188                 if (isminh) data.height = o.minHeight;
12189                 if (ismaxw) data.width = o.maxWidth;
12190                 if (ismaxh) data.height = o.maxHeight;
12191
12192                 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
12193                 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
12194
12195                 if (isminw && cw) data.left = dw - o.minWidth;
12196                 if (ismaxw && cw) data.left = dw - o.maxWidth;
12197                 if (isminh && ch)       data.top = dh - o.minHeight;
12198                 if (ismaxh && ch)       data.top = dh - o.maxHeight;
12199
12200                 // fixing jump error on top/left - bug #2330
12201                 var isNotwh = !data.width && !data.height;
12202                 if (isNotwh && !data.left && data.top) data.top = null;
12203                 else if (isNotwh && !data.top && data.left) data.left = null;
12204
12205                 return data;
12206         },
12207
12208         _proportionallyResize: function() {
12209
12210                 var o = this.options;
12211                 if (!this._proportionallyResizeElements.length) return;
12212                 var element = this.helper || this.element;
12213
12214                 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
12215
12216                         var prel = this._proportionallyResizeElements[i];
12217
12218                         if (!this.borderDif) {
12219                                 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
12220                                         p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
12221
12222                                 this.borderDif = $.map(b, function(v, i) {
12223                                         var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
12224                                         return border + padding;
12225                                 });
12226                         }
12227
12228                         if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
12229                                 continue;
12230
12231                         prel.css({
12232                                 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
12233                                 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
12234                         });
12235
12236                 };
12237
12238         },
12239
12240         _renderProxy: function() {
12241
12242                 var el = this.element, o = this.options;
12243                 this.elementOffset = el.offset();
12244
12245                 if(this._helper) {
12246
12247                         this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
12248
12249                         // fix ie6 offset TODO: This seems broken
12250                         var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
12251                         pxyoffset = ( ie6 ? 2 : -1 );
12252
12253                         this.helper.addClass(this._helper).css({
12254                                 width: this.element.outerWidth() + pxyoffset,
12255                                 height: this.element.outerHeight() + pxyoffset,
12256                                 position: 'absolute',
12257                                 left: this.elementOffset.left - ie6offset +'px',
12258                                 top: this.elementOffset.top - ie6offset +'px',
12259                                 zIndex: ++o.zIndex //TODO: Don't modify option
12260                         });
12261
12262                         this.helper
12263                                 .appendTo("body")
12264                                 .disableSelection();
12265
12266                 } else {
12267                         this.helper = this.element;
12268                 }
12269
12270         },
12271
12272         _change: {
12273                 e: function(event, dx, dy) {
12274                         return { width: this.originalSize.width + dx };
12275                 },
12276                 w: function(event, dx, dy) {
12277                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
12278                         return { left: sp.left + dx, width: cs.width - dx };
12279                 },
12280                 n: function(event, dx, dy) {
12281                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
12282                         return { top: sp.top + dy, height: cs.height - dy };
12283                 },
12284                 s: function(event, dx, dy) {
12285                         return { height: this.originalSize.height + dy };
12286                 },
12287                 se: function(event, dx, dy) {
12288                         return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
12289                 },
12290                 sw: function(event, dx, dy) {
12291                         return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
12292                 },
12293                 ne: function(event, dx, dy) {
12294                         return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
12295                 },
12296                 nw: function(event, dx, dy) {
12297                         return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
12298                 }
12299         },
12300
12301         _propagate: function(n, event) {
12302                 $.ui.plugin.call(this, n, [event, this.ui()]);
12303                 (n != "resize" && this._trigger(n, event, this.ui()));
12304         },
12305
12306         plugins: {},
12307
12308         ui: function() {
12309                 return {
12310                         originalElement: this.originalElement,
12311                         element: this.element,
12312                         helper: this.helper,
12313                         position: this.position,
12314                         size: this.size,
12315                         originalSize: this.originalSize,
12316                         originalPosition: this.originalPosition
12317                 };
12318         }
12319
12320 });
12321
12322 $.extend($.ui.resizable, {
12323         version: "1.8.16"
12324 });
12325
12326 /*
12327  * Resizable Extensions
12328  */
12329
12330 $.ui.plugin.add("resizable", "alsoResize", {
12331
12332         start: function (event, ui) {
12333                 var self = $(this).data("resizable"), o = self.options;
12334
12335                 var _store = function (exp) {
12336                         $(exp).each(function() {
12337                                 var el = $(this);
12338                                 el.data("resizable-alsoresize", {
12339                                         width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
12340                                         left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
12341                                         position: el.css('position') // to reset Opera on stop()
12342                                 });
12343                         });
12344                 };
12345
12346                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
12347                         if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
12348                         else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
12349                 }else{
12350                         _store(o.alsoResize);
12351                 }
12352         },
12353
12354         resize: function (event, ui) {
12355                 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
12356
12357                 var delta = {
12358                         height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
12359                         top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
12360                 },
12361
12362                 _alsoResize = function (exp, c) {
12363                         $(exp).each(function() {
12364                                 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
12365                                         css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
12366
12367                                 $.each(css, function (i, prop) {
12368                                         var sum = (start[prop]||0) + (delta[prop]||0);
12369                                         if (sum && sum >= 0)
12370                                                 style[prop] = sum || null;
12371                                 });
12372
12373                                 // Opera fixing relative position
12374                                 if ($.browser.opera && /relative/.test(el.css('position'))) {
12375                                         self._revertToRelativePosition = true;
12376                                         el.css({ position: 'absolute', top: 'auto', left: 'auto' });
12377                                 }
12378
12379                                 el.css(style);
12380                         });
12381                 };
12382
12383                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
12384                         $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
12385                 }else{
12386                         _alsoResize(o.alsoResize);
12387                 }
12388         },
12389
12390         stop: function (event, ui) {
12391                 var self = $(this).data("resizable"), o = self.options;
12392
12393                 var _reset = function (exp) {
12394                         $(exp).each(function() {
12395                                 var el = $(this);
12396                                 // reset position for Opera - no need to verify it was changed
12397                                 el.css({ position: el.data("resizable-alsoresize").position });
12398                         });
12399                 };
12400
12401                 if (self._revertToRelativePosition) {
12402                         self._revertToRelativePosition = false;
12403                         if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
12404                                 $.each(o.alsoResize, function (exp) { _reset(exp); });
12405                         }else{
12406                                 _reset(o.alsoResize);
12407                         }
12408                 }
12409
12410                 $(this).removeData("resizable-alsoresize");
12411         }
12412 });
12413
12414 $.ui.plugin.add("resizable", "animate", {
12415
12416         stop: function(event, ui) {
12417                 var self = $(this).data("resizable"), o = self.options;
12418
12419                 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
12420                                         soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
12421                                                 soffsetw = ista ? 0 : self.sizeDiff.width;
12422
12423                 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
12424                                         left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
12425                                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
12426
12427                 self.element.animate(
12428                         $.extend(style, top && left ? { top: top, left: left } : {}), {
12429                                 duration: o.animateDuration,
12430                                 easing: o.animateEasing,
12431                                 step: function() {
12432
12433                                         var data = {
12434                                                 width: parseInt(self.element.css('width'), 10),
12435                                                 height: parseInt(self.element.css('height'), 10),
12436                                                 top: parseInt(self.element.css('top'), 10),
12437                                                 left: parseInt(self.element.css('left'), 10)
12438                                         };
12439
12440                                         if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
12441
12442                                         // propagating resize, and updating values for each animation step
12443                                         self._updateCache(data);
12444                                         self._propagate("resize", event);
12445
12446                                 }
12447                         }
12448                 );
12449         }
12450
12451 });
12452
12453 $.ui.plugin.add("resizable", "containment", {
12454
12455         start: function(event, ui) {
12456                 var self = $(this).data("resizable"), o = self.options, el = self.element;
12457                 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
12458                 if (!ce) return;
12459
12460                 self.containerElement = $(ce);
12461
12462                 if (/document/.test(oc) || oc == document) {
12463                         self.containerOffset = { left: 0, top: 0 };
12464                         self.containerPosition = { left: 0, top: 0 };
12465
12466                         self.parentData = {
12467                                 element: $(document), left: 0, top: 0,
12468                                 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
12469                         };
12470                 }
12471
12472                 // i'm a node, so compute top, left, right, bottom
12473                 else {
12474                         var element = $(ce), p = [];
12475                         $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
12476
12477                         self.containerOffset = element.offset();
12478                         self.containerPosition = element.position();
12479                         self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
12480
12481                         var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
12482                                                 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
12483
12484                         self.parentData = {
12485                                 element: ce, left: co.left, top: co.top, width: width, height: height
12486                         };
12487                 }
12488         },
12489
12490         resize: function(event, ui) {
12491                 var self = $(this).data("resizable"), o = self.options,
12492                                 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
12493                                 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
12494
12495                 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
12496
12497                 if (cp.left < (self._helper ? co.left : 0)) {
12498                         self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
12499                         if (pRatio) self.size.height = self.size.width / o.aspectRatio;
12500                         self.position.left = o.helper ? co.left : 0;
12501                 }
12502
12503                 if (cp.top < (self._helper ? co.top : 0)) {
12504                         self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
12505                         if (pRatio) self.size.width = self.size.height * o.aspectRatio;
12506                         self.position.top = self._helper ? co.top : 0;
12507                 }
12508
12509                 self.offset.left = self.parentData.left+self.position.left;
12510                 self.offset.top = self.parentData.top+self.position.top;
12511
12512                 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
12513                                         hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
12514
12515                 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
12516                     isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
12517
12518                 if(isParent && isOffsetRelative) woset -= self.parentData.left;
12519
12520                 if (woset + self.size.width >= self.parentData.width) {
12521                         self.size.width = self.parentData.width - woset;
12522                         if (pRatio) self.size.height = self.size.width / self.aspectRatio;
12523                 }
12524
12525                 if (hoset + self.size.height >= self.parentData.height) {
12526                         self.size.height = self.parentData.height - hoset;
12527                         if (pRatio) self.size.width = self.size.height * self.aspectRatio;
12528                 }
12529         },
12530
12531         stop: function(event, ui){
12532                 var self = $(this).data("resizable"), o = self.options, cp = self.position,
12533                                 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
12534
12535                 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
12536
12537                 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
12538                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
12539
12540                 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
12541                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
12542
12543         }
12544 });
12545
12546 $.ui.plugin.add("resizable", "ghost", {
12547
12548         start: function(event, ui) {
12549
12550                 var self = $(this).data("resizable"), o = self.options, cs = self.size;
12551
12552                 self.ghost = self.originalElement.clone();
12553                 self.ghost
12554                         .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
12555                         .addClass('ui-resizable-ghost')
12556                         .addClass(typeof o.ghost == 'string' ? o.ghost : '');
12557
12558                 self.ghost.appendTo(self.helper);
12559
12560         },
12561
12562         resize: function(event, ui){
12563                 var self = $(this).data("resizable"), o = self.options;
12564                 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
12565         },
12566
12567         stop: function(event, ui){
12568                 var self = $(this).data("resizable"), o = self.options;
12569                 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
12570         }
12571
12572 });
12573
12574 $.ui.plugin.add("resizable", "grid", {
12575
12576         resize: function(event, ui) {
12577                 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
12578                 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
12579                 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
12580
12581                 if (/^(se|s|e)$/.test(a)) {
12582                         self.size.width = os.width + ox;
12583                         self.size.height = os.height + oy;
12584                 }
12585                 else if (/^(ne)$/.test(a)) {
12586                         self.size.width = os.width + ox;
12587                         self.size.height = os.height + oy;
12588                         self.position.top = op.top - oy;
12589                 }
12590                 else if (/^(sw)$/.test(a)) {
12591                         self.size.width = os.width + ox;
12592                         self.size.height = os.height + oy;
12593                         self.position.left = op.left - ox;
12594                 }
12595                 else {
12596                         self.size.width = os.width + ox;
12597                         self.size.height = os.height + oy;
12598                         self.position.top = op.top - oy;
12599                         self.position.left = op.left - ox;
12600                 }
12601         }
12602
12603 });
12604
12605 var num = function(v) {
12606         return parseInt(v, 10) || 0;
12607 };
12608
12609 var isNumber = function(value) {
12610         return !isNaN(parseInt(value, 10));
12611 };
12612
12613 })(jQuery);
12614 /*
12615  * jQuery UI Selectable 1.8.16
12616  *
12617  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
12618  * Dual licensed under the MIT or GPL Version 2 licenses.
12619  * http://jquery.org/license
12620  *
12621  * http://docs.jquery.com/UI/Selectables
12622  *
12623  * Depends:
12624  *      jquery.ui.core.js
12625  *      jquery.ui.mouse.js
12626  *      jquery.ui.widget.js
12627  */
12628 (function( $, undefined ) {
12629
12630 $.widget("ui.selectable", $.ui.mouse, {
12631         options: {
12632                 appendTo: 'body',
12633                 autoRefresh: true,
12634                 distance: 0,
12635                 filter: '*',
12636                 tolerance: 'touch'
12637         },
12638         _create: function() {
12639                 var self = this;
12640
12641                 this.element.addClass("ui-selectable");
12642
12643                 this.dragged = false;
12644
12645                 // cache selectee children based on filter
12646                 var selectees;
12647                 this.refresh = function() {
12648                         selectees = $(self.options.filter, self.element[0]);
12649                         selectees.each(function() {
12650                                 var $this = $(this);
12651                                 var pos = $this.offset();
12652                                 $.data(this, "selectable-item", {
12653                                         element: this,
12654                                         $element: $this,
12655                                         left: pos.left,
12656                                         top: pos.top,
12657                                         right: pos.left + $this.outerWidth(),
12658                                         bottom: pos.top + $this.outerHeight(),
12659                                         startselected: false,
12660                                         selected: $this.hasClass('ui-selected'),
12661                                         selecting: $this.hasClass('ui-selecting'),
12662                                         unselecting: $this.hasClass('ui-unselecting')
12663                                 });
12664                         });
12665                 };
12666                 this.refresh();
12667
12668                 this.selectees = selectees.addClass("ui-selectee");
12669
12670                 this._mouseInit();
12671
12672                 this.helper = $("<div class='ui-selectable-helper'></div>");
12673         },
12674
12675         destroy: function() {
12676                 this.selectees
12677                         .removeClass("ui-selectee")
12678                         .removeData("selectable-item");
12679                 this.element
12680                         .removeClass("ui-selectable ui-selectable-disabled")
12681                         .removeData("selectable")
12682                         .unbind(".selectable");
12683                 this._mouseDestroy();
12684
12685                 return this;
12686         },
12687
12688         _mouseStart: function(event) {
12689                 var self = this;
12690
12691                 this.opos = [event.pageX, event.pageY];
12692
12693                 if (this.options.disabled)
12694                         return;
12695
12696                 var options = this.options;
12697
12698                 this.selectees = $(options.filter, this.element[0]);
12699
12700                 this._trigger("start", event);
12701
12702                 $(options.appendTo).append(this.helper);
12703                 // position helper (lasso)
12704                 this.helper.css({
12705                         "left": event.clientX,
12706                         "top": event.clientY,
12707                         "width": 0,
12708                         "height": 0
12709                 });
12710
12711                 if (options.autoRefresh) {
12712                         this.refresh();
12713                 }
12714
12715                 this.selectees.filter('.ui-selected').each(function() {
12716                         var selectee = $.data(this, "selectable-item");
12717                         selectee.startselected = true;
12718                         if (!event.metaKey) {
12719                                 selectee.$element.removeClass('ui-selected');
12720                                 selectee.selected = false;
12721                                 selectee.$element.addClass('ui-unselecting');
12722                                 selectee.unselecting = true;
12723                                 // selectable UNSELECTING callback
12724                                 self._trigger("unselecting", event, {
12725                                         unselecting: selectee.element
12726                                 });
12727                         }
12728                 });
12729
12730                 $(event.target).parents().andSelf().each(function() {
12731                         var selectee = $.data(this, "selectable-item");
12732                         if (selectee) {
12733                                 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
12734                                 selectee.$element
12735                                         .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
12736                                         .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
12737                                 selectee.unselecting = !doSelect;
12738                                 selectee.selecting = doSelect;
12739                                 selectee.selected = doSelect;
12740                                 // selectable (UN)SELECTING callback
12741                                 if (doSelect) {
12742                                         self._trigger("selecting", event, {
12743                                                 selecting: selectee.element
12744                                         });
12745                                 } else {
12746                                         self._trigger("unselecting", event, {
12747                                                 unselecting: selectee.element
12748                                         });
12749                                 }
12750                                 return false;
12751                         }
12752                 });
12753
12754         },
12755
12756         _mouseDrag: function(event) {
12757                 var self = this;
12758                 this.dragged = true;
12759
12760                 if (this.options.disabled)
12761                         return;
12762
12763                 var options = this.options;
12764
12765                 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
12766                 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
12767                 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
12768                 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
12769
12770                 this.selectees.each(function() {
12771                         var selectee = $.data(this, "selectable-item");
12772                         //prevent helper from being selected if appendTo: selectable
12773                         if (!selectee || selectee.element == self.element[0])
12774                                 return;
12775                         var hit = false;
12776                         if (options.tolerance == 'touch') {
12777                                 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
12778                         } else if (options.tolerance == 'fit') {
12779                                 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
12780                         }
12781
12782                         if (hit) {
12783                                 // SELECT
12784                                 if (selectee.selected) {
12785                                         selectee.$element.removeClass('ui-selected');
12786                                         selectee.selected = false;
12787                                 }
12788                                 if (selectee.unselecting) {
12789                                         selectee.$element.removeClass('ui-unselecting');
12790                                         selectee.unselecting = false;
12791                                 }
12792                                 if (!selectee.selecting) {
12793                                         selectee.$element.addClass('ui-selecting');
12794                                         selectee.selecting = true;
12795                                         // selectable SELECTING callback
12796                                         self._trigger("selecting", event, {
12797                                                 selecting: selectee.element
12798                                         });
12799                                 }
12800                         } else {
12801                                 // UNSELECT
12802                                 if (selectee.selecting) {
12803                                         if (event.metaKey && selectee.startselected) {
12804                                                 selectee.$element.removeClass('ui-selecting');
12805                                                 selectee.selecting = false;
12806                                                 selectee.$element.addClass('ui-selected');
12807                                                 selectee.selected = true;
12808                                         } else {
12809                                                 selectee.$element.removeClass('ui-selecting');
12810                                                 selectee.selecting = false;
12811                                                 if (selectee.startselected) {
12812                                                         selectee.$element.addClass('ui-unselecting');
12813                                                         selectee.unselecting = true;
12814                                                 }
12815                                                 // selectable UNSELECTING callback
12816                                                 self._trigger("unselecting", event, {
12817                                                         unselecting: selectee.element
12818                                                 });
12819                                         }
12820                                 }
12821                                 if (selectee.selected) {
12822                                         if (!event.metaKey && !selectee.startselected) {
12823                                                 selectee.$element.removeClass('ui-selected');
12824                                                 selectee.selected = false;
12825
12826                                                 selectee.$element.addClass('ui-unselecting');
12827                                                 selectee.unselecting = true;
12828                                                 // selectable UNSELECTING callback
12829                                                 self._trigger("unselecting", event, {
12830                                                         unselecting: selectee.element
12831                                                 });
12832                                         }
12833                                 }
12834                         }
12835                 });
12836
12837                 return false;
12838         },
12839
12840         _mouseStop: function(event) {
12841                 var self = this;
12842
12843                 this.dragged = false;
12844
12845                 var options = this.options;
12846
12847                 $('.ui-unselecting', this.element[0]).each(function() {
12848                         var selectee = $.data(this, "selectable-item");
12849                         selectee.$element.removeClass('ui-unselecting');
12850                         selectee.unselecting = false;
12851                         selectee.startselected = false;
12852                         self._trigger("unselected", event, {
12853                                 unselected: selectee.element
12854                         });
12855                 });
12856                 $('.ui-selecting', this.element[0]).each(function() {
12857                         var selectee = $.data(this, "selectable-item");
12858                         selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
12859                         selectee.selecting = false;
12860                         selectee.selected = true;
12861                         selectee.startselected = true;
12862                         self._trigger("selected", event, {
12863                                 selected: selectee.element
12864                         });
12865                 });
12866                 this._trigger("stop", event);
12867
12868                 this.helper.remove();
12869
12870                 return false;
12871         }
12872
12873 });
12874
12875 $.extend($.ui.selectable, {
12876         version: "1.8.16"
12877 });
12878
12879 })(jQuery);
12880 /*
12881  * jQuery UI Sortable 1.8.16
12882  *
12883  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
12884  * Dual licensed under the MIT or GPL Version 2 licenses.
12885  * http://jquery.org/license
12886  *
12887  * http://docs.jquery.com/UI/Sortables
12888  *
12889  * Depends:
12890  *      jquery.ui.core.js
12891  *      jquery.ui.mouse.js
12892  *      jquery.ui.widget.js
12893  */
12894 (function( $, undefined ) {
12895
12896 $.widget("ui.sortable", $.ui.mouse, {
12897         widgetEventPrefix: "sort",
12898         options: {
12899                 appendTo: "parent",
12900                 axis: false,
12901                 connectWith: false,
12902                 containment: false,
12903                 cursor: 'auto',
12904                 cursorAt: false,
12905                 dropOnEmpty: true,
12906                 forcePlaceholderSize: false,
12907                 forceHelperSize: false,
12908                 grid: false,
12909                 handle: false,
12910                 helper: "original",
12911                 items: '> *',
12912                 opacity: false,
12913                 placeholder: false,
12914                 revert: false,
12915                 scroll: true,
12916                 scrollSensitivity: 20,
12917                 scrollSpeed: 20,
12918                 scope: "default",
12919                 tolerance: "intersect",
12920                 zIndex: 1000
12921         },
12922         _create: function() {
12923
12924                 var o = this.options;
12925                 this.containerCache = {};
12926                 this.element.addClass("ui-sortable");
12927
12928                 //Get the items
12929                 this.refresh();
12930
12931                 //Let's determine if the items are being displayed horizontally
12932                 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
12933
12934                 //Let's determine the parent's offset
12935                 this.offset = this.element.offset();
12936
12937                 //Initialize mouse events for interaction
12938                 this._mouseInit();
12939
12940         },
12941
12942         destroy: function() {
12943                 this.element
12944                         .removeClass("ui-sortable ui-sortable-disabled")
12945                         .removeData("sortable")
12946                         .unbind(".sortable");
12947                 this._mouseDestroy();
12948
12949                 for ( var i = this.items.length - 1; i >= 0; i-- )
12950                         this.items[i].item.removeData("sortable-item");
12951
12952                 return this;
12953         },
12954
12955         _setOption: function(key, value){
12956                 if ( key === "disabled" ) {
12957                         this.options[ key ] = value;
12958         
12959                         this.widget()
12960                                 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
12961                 } else {
12962                         // Don't call widget base _setOption for disable as it adds ui-state-disabled class
12963                         $.Widget.prototype._setOption.apply(this, arguments);
12964                 }
12965         },
12966
12967         _mouseCapture: function(event, overrideHandle) {
12968
12969                 if (this.reverting) {
12970                         return false;
12971                 }
12972
12973                 if(this.options.disabled || this.options.type == 'static') return false;
12974
12975                 //We have to refresh the items data once first
12976                 this._refreshItems(event);
12977
12978                 //Find out if the clicked node (or one of its parents) is a actual item in this.items
12979                 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
12980                         if($.data(this, 'sortable-item') == self) {
12981                                 currentItem = $(this);
12982                                 return false;
12983                         }
12984                 });
12985                 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
12986
12987                 if(!currentItem) return false;
12988                 if(this.options.handle && !overrideHandle) {
12989                         var validHandle = false;
12990
12991                         $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
12992                         if(!validHandle) return false;
12993                 }
12994
12995                 this.currentItem = currentItem;
12996                 this._removeCurrentsFromItems();
12997                 return true;
12998
12999         },
13000
13001         _mouseStart: function(event, overrideHandle, noActivation) {
13002
13003                 var o = this.options, self = this;
13004                 this.currentContainer = this;
13005
13006                 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
13007                 this.refreshPositions();
13008
13009                 //Create and append the visible helper
13010                 this.helper = this._createHelper(event);
13011
13012                 //Cache the helper size
13013                 this._cacheHelperProportions();
13014
13015                 /*
13016                  * - Position generation -
13017                  * This block generates everything position related - it's the core of draggables.
13018                  */
13019
13020                 //Cache the margins of the original element
13021                 this._cacheMargins();
13022
13023                 //Get the next scrolling parent
13024                 this.scrollParent = this.helper.scrollParent();
13025
13026                 //The element's absolute position on the page minus margins
13027                 this.offset = this.currentItem.offset();
13028                 this.offset = {
13029                         top: this.offset.top - this.margins.top,
13030                         left: this.offset.left - this.margins.left
13031                 };
13032
13033                 // Only after we got the offset, we can change the helper's position to absolute
13034                 // TODO: Still need to figure out a way to make relative sorting possible
13035                 this.helper.css("position", "absolute");
13036                 this.cssPosition = this.helper.css("position");
13037
13038                 $.extend(this.offset, {
13039                         click: { //Where the click happened, relative to the element
13040                                 left: event.pageX - this.offset.left,
13041                                 top: event.pageY - this.offset.top
13042                         },
13043                         parent: this._getParentOffset(),
13044                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
13045                 });
13046
13047                 //Generate the original position
13048                 this.originalPosition = this._generatePosition(event);
13049                 this.originalPageX = event.pageX;
13050                 this.originalPageY = event.pageY;
13051
13052                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
13053                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
13054
13055                 //Cache the former DOM position
13056                 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
13057
13058                 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
13059                 if(this.helper[0] != this.currentItem[0]) {
13060                         this.currentItem.hide();
13061                 }
13062
13063                 //Create the placeholder
13064                 this._createPlaceholder();
13065
13066                 //Set a containment if given in the options
13067                 if(o.containment)
13068                         this._setContainment();
13069
13070                 if(o.cursor) { // cursor option
13071                         if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
13072                         $('body').css("cursor", o.cursor);
13073                 }
13074
13075                 if(o.opacity) { // opacity option
13076                         if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
13077                         this.helper.css("opacity", o.opacity);
13078                 }
13079
13080                 if(o.zIndex) { // zIndex option
13081                         if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
13082                         this.helper.css("zIndex", o.zIndex);
13083                 }
13084
13085                 //Prepare scrolling
13086                 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
13087                         this.overflowOffset = this.scrollParent.offset();
13088
13089                 //Call callbacks
13090                 this._trigger("start", event, this._uiHash());
13091
13092                 //Recache the helper size
13093                 if(!this._preserveHelperProportions)
13094                         this._cacheHelperProportions();
13095
13096
13097                 //Post 'activate' events to possible containers
13098                 if(!noActivation) {
13099                          for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
13100                 }
13101
13102                 //Prepare possible droppables
13103                 if($.ui.ddmanager)
13104                         $.ui.ddmanager.current = this;
13105
13106                 if ($.ui.ddmanager && !o.dropBehaviour)
13107                         $.ui.ddmanager.prepareOffsets(this, event);
13108
13109                 this.dragging = true;
13110
13111                 this.helper.addClass("ui-sortable-helper");
13112                 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
13113                 return true;
13114
13115         },
13116
13117         _mouseDrag: function(event) {
13118
13119                 //Compute the helpers position
13120                 this.position = this._generatePosition(event);
13121                 this.positionAbs = this._convertPositionTo("absolute");
13122
13123                 if (!this.lastPositionAbs) {
13124                         this.lastPositionAbs = this.positionAbs;
13125                 }
13126
13127                 //Do scrolling
13128                 if(this.options.scroll) {
13129                         var o = this.options, scrolled = false;
13130                         if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
13131
13132                                 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
13133                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
13134                                 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
13135                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
13136
13137                                 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
13138                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
13139                                 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
13140                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
13141
13142                         } else {
13143
13144                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
13145                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
13146                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
13147                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
13148
13149                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
13150                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
13151                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
13152                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
13153
13154                         }
13155
13156                         if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
13157                                 $.ui.ddmanager.prepareOffsets(this, event);
13158                 }
13159
13160                 //Regenerate the absolute position used for position checks
13161                 this.positionAbs = this._convertPositionTo("absolute");
13162
13163                 //Set the helper position
13164                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
13165                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
13166
13167                 //Rearrange
13168                 for (var i = this.items.length - 1; i >= 0; i--) {
13169
13170                         //Cache variables and intersection, continue if no intersection
13171                         var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
13172                         if (!intersection) continue;
13173
13174                         if(itemElement != this.currentItem[0] //cannot intersect with itself
13175                                 &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
13176                                 &&      !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
13177                                 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
13178                                 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
13179                         ) {
13180
13181                                 this.direction = intersection == 1 ? "down" : "up";
13182
13183                                 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
13184                                         this._rearrange(event, item);
13185                                 } else {
13186                                         break;
13187                                 }
13188
13189                                 this._trigger("change", event, this._uiHash());
13190                                 break;
13191                         }
13192                 }
13193
13194                 //Post events to containers
13195                 this._contactContainers(event);
13196
13197                 //Interconnect with droppables
13198                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
13199
13200                 //Call callbacks
13201                 this._trigger('sort', event, this._uiHash());
13202
13203                 this.lastPositionAbs = this.positionAbs;
13204                 return false;
13205
13206         },
13207
13208         _mouseStop: function(event, noPropagation) {
13209
13210                 if(!event) return;
13211
13212                 //If we are using droppables, inform the manager about the drop
13213                 if ($.ui.ddmanager && !this.options.dropBehaviour)
13214                         $.ui.ddmanager.drop(this, event);
13215
13216                 if(this.options.revert) {
13217                         var self = this;
13218                         var cur = self.placeholder.offset();
13219
13220                         self.reverting = true;
13221
13222                         $(this.helper).animate({
13223                                 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
13224                                 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
13225                         }, parseInt(this.options.revert, 10) || 500, function() {
13226                                 self._clear(event);
13227                         });
13228                 } else {
13229                         this._clear(event, noPropagation);
13230                 }
13231
13232                 return false;
13233
13234         },
13235
13236         cancel: function() {
13237
13238                 var self = this;
13239
13240                 if(this.dragging) {
13241
13242                         this._mouseUp({ target: null });
13243
13244                         if(this.options.helper == "original")
13245                                 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13246                         else
13247                                 this.currentItem.show();
13248
13249                         //Post deactivating events to containers
13250                         for (var i = this.containers.length - 1; i >= 0; i--){
13251                                 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
13252                                 if(this.containers[i].containerCache.over) {
13253                                         this.containers[i]._trigger("out", null, self._uiHash(this));
13254                                         this.containers[i].containerCache.over = 0;
13255                                 }
13256                         }
13257
13258                 }
13259
13260                 if (this.placeholder) {
13261                         //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13262                         if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13263                         if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
13264
13265                         $.extend(this, {
13266                                 helper: null,
13267                                 dragging: false,
13268                                 reverting: false,
13269                                 _noFinalSort: null
13270                         });
13271
13272                         if(this.domPosition.prev) {
13273                                 $(this.domPosition.prev).after(this.currentItem);
13274                         } else {
13275                                 $(this.domPosition.parent).prepend(this.currentItem);
13276                         }
13277                 }
13278
13279                 return this;
13280
13281         },
13282
13283         serialize: function(o) {
13284
13285                 var items = this._getItemsAsjQuery(o && o.connected);
13286                 var str = []; o = o || {};
13287
13288                 $(items).each(function() {
13289                         var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
13290                         if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
13291                 });
13292
13293                 if(!str.length && o.key) {
13294                         str.push(o.key + '=');
13295                 }
13296
13297                 return str.join('&');
13298
13299         },
13300
13301         toArray: function(o) {
13302
13303                 var items = this._getItemsAsjQuery(o && o.connected);
13304                 var ret = []; o = o || {};
13305
13306                 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
13307                 return ret;
13308
13309         },
13310
13311         /* Be careful with the following core functions */
13312         _intersectsWith: function(item) {
13313
13314                 var x1 = this.positionAbs.left,
13315                         x2 = x1 + this.helperProportions.width,
13316                         y1 = this.positionAbs.top,
13317                         y2 = y1 + this.helperProportions.height;
13318
13319                 var l = item.left,
13320                         r = l + item.width,
13321                         t = item.top,
13322                         b = t + item.height;
13323
13324                 var dyClick = this.offset.click.top,
13325                         dxClick = this.offset.click.left;
13326
13327                 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
13328
13329                 if(        this.options.tolerance == "pointer"
13330                         || this.options.forcePointerForContainers
13331                         || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
13332                 ) {
13333                         return isOverElement;
13334                 } else {
13335
13336                         return (l < x1 + (this.helperProportions.width / 2) // Right Half
13337                                 && x2 - (this.helperProportions.width / 2) < r // Left Half
13338                                 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
13339                                 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
13340
13341                 }
13342         },
13343
13344         _intersectsWithPointer: function(item) {
13345
13346                 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
13347                         isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
13348                         isOverElement = isOverElementHeight && isOverElementWidth,
13349                         verticalDirection = this._getDragVerticalDirection(),
13350                         horizontalDirection = this._getDragHorizontalDirection();
13351
13352                 if (!isOverElement)
13353                         return false;
13354
13355                 return this.floating ?
13356                         ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
13357                         : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
13358
13359         },
13360
13361         _intersectsWithSides: function(item) {
13362
13363                 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
13364                         isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
13365                         verticalDirection = this._getDragVerticalDirection(),
13366                         horizontalDirection = this._getDragHorizontalDirection();
13367
13368                 if (this.floating && horizontalDirection) {
13369                         return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
13370                 } else {
13371                         return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
13372                 }
13373
13374         },
13375
13376         _getDragVerticalDirection: function() {
13377                 var delta = this.positionAbs.top - this.lastPositionAbs.top;
13378                 return delta != 0 && (delta > 0 ? "down" : "up");
13379         },
13380
13381         _getDragHorizontalDirection: function() {
13382                 var delta = this.positionAbs.left - this.lastPositionAbs.left;
13383                 return delta != 0 && (delta > 0 ? "right" : "left");
13384         },
13385
13386         refresh: function(event) {
13387                 this._refreshItems(event);
13388                 this.refreshPositions();
13389                 return this;
13390         },
13391
13392         _connectWith: function() {
13393                 var options = this.options;
13394                 return options.connectWith.constructor == String
13395                         ? [options.connectWith]
13396                         : options.connectWith;
13397         },
13398         
13399         _getItemsAsjQuery: function(connected) {
13400
13401                 var self = this;
13402                 var items = [];
13403                 var queries = [];
13404                 var connectWith = this._connectWith();
13405
13406                 if(connectWith && connected) {
13407                         for (var i = connectWith.length - 1; i >= 0; i--){
13408                                 var cur = $(connectWith[i]);
13409                                 for (var j = cur.length - 1; j >= 0; j--){
13410                                         var inst = $.data(cur[j], 'sortable');
13411                                         if(inst && inst != this && !inst.options.disabled) {
13412                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
13413                                         }
13414                                 };
13415                         };
13416                 }
13417
13418                 queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
13419
13420                 for (var i = queries.length - 1; i >= 0; i--){
13421                         queries[i][0].each(function() {
13422                                 items.push(this);
13423                         });
13424                 };
13425
13426                 return $(items);
13427
13428         },
13429
13430         _removeCurrentsFromItems: function() {
13431
13432                 var list = this.currentItem.find(":data(sortable-item)");
13433
13434                 for (var i=0; i < this.items.length; i++) {
13435
13436                         for (var j=0; j < list.length; j++) {
13437                                 if(list[j] == this.items[i].item[0])
13438                                         this.items.splice(i,1);
13439                         };
13440
13441                 };
13442
13443         },
13444
13445         _refreshItems: function(event) {
13446
13447                 this.items = [];
13448                 this.containers = [this];
13449                 var items = this.items;
13450                 var self = this;
13451                 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
13452                 var connectWith = this._connectWith();
13453
13454                 if(connectWith) {
13455                         for (var i = connectWith.length - 1; i >= 0; i--){
13456                                 var cur = $(connectWith[i]);
13457                                 for (var j = cur.length - 1; j >= 0; j--){
13458                                         var inst = $.data(cur[j], 'sortable');
13459                                         if(inst && inst != this && !inst.options.disabled) {
13460                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
13461                                                 this.containers.push(inst);
13462                                         }
13463                                 };
13464                         };
13465                 }
13466
13467                 for (var i = queries.length - 1; i >= 0; i--) {
13468                         var targetData = queries[i][1];
13469                         var _queries = queries[i][0];
13470
13471                         for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
13472                                 var item = $(_queries[j]);
13473
13474                                 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
13475
13476                                 items.push({
13477                                         item: item,
13478                                         instance: targetData,
13479                                         width: 0, height: 0,
13480                                         left: 0, top: 0
13481                                 });
13482                         };
13483                 };
13484
13485         },
13486
13487         refreshPositions: function(fast) {
13488
13489                 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
13490                 if(this.offsetParent && this.helper) {
13491                         this.offset.parent = this._getParentOffset();
13492                 }
13493
13494                 for (var i = this.items.length - 1; i >= 0; i--){
13495                         var item = this.items[i];
13496
13497                         //We ignore calculating positions of all connected containers when we're not over them
13498                         if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
13499                                 continue;
13500
13501                         var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
13502
13503                         if (!fast) {
13504                                 item.width = t.outerWidth();
13505                                 item.height = t.outerHeight();
13506                         }
13507
13508                         var p = t.offset();
13509                         item.left = p.left;
13510                         item.top = p.top;
13511                 };
13512
13513                 if(this.options.custom && this.options.custom.refreshContainers) {
13514                         this.options.custom.refreshContainers.call(this);
13515                 } else {
13516                         for (var i = this.containers.length - 1; i >= 0; i--){
13517                                 var p = this.containers[i].element.offset();
13518                                 this.containers[i].containerCache.left = p.left;
13519                                 this.containers[i].containerCache.top = p.top;
13520                                 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
13521                                 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
13522                         };
13523                 }
13524
13525                 return this;
13526         },
13527
13528         _createPlaceholder: function(that) {
13529
13530                 var self = that || this, o = self.options;
13531
13532                 if(!o.placeholder || o.placeholder.constructor == String) {
13533                         var className = o.placeholder;
13534                         o.placeholder = {
13535                                 element: function() {
13536
13537                                         var el = $(document.createElement(self.currentItem[0].nodeName))
13538                                                 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
13539                                                 .removeClass("ui-sortable-helper")[0];
13540
13541                                         if(!className)
13542                                                 el.style.visibility = "hidden";
13543
13544                                         return el;
13545                                 },
13546                                 update: function(container, p) {
13547
13548                                         // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
13549                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
13550                                         if(className && !o.forcePlaceholderSize) return;
13551
13552                                         //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
13553                                         if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
13554                                         if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
13555                                 }
13556                         };
13557                 }
13558
13559                 //Create the placeholder
13560                 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
13561
13562                 //Append it after the actual current item
13563                 self.currentItem.after(self.placeholder);
13564
13565                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
13566                 o.placeholder.update(self, self.placeholder);
13567
13568         },
13569
13570         _contactContainers: function(event) {
13571                 
13572                 // get innermost container that intersects with item 
13573                 var innermostContainer = null, innermostIndex = null;           
13574                 
13575                 
13576                 for (var i = this.containers.length - 1; i >= 0; i--){
13577
13578                         // never consider a container that's located within the item itself 
13579                         if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
13580                                 continue;
13581
13582                         if(this._intersectsWith(this.containers[i].containerCache)) {
13583
13584                                 // if we've already found a container and it's more "inner" than this, then continue 
13585                                 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
13586                                         continue;
13587
13588                                 innermostContainer = this.containers[i]; 
13589                                 innermostIndex = i;
13590                                         
13591                         } else {
13592                                 // container doesn't intersect. trigger "out" event if necessary 
13593                                 if(this.containers[i].containerCache.over) {
13594                                         this.containers[i]._trigger("out", event, this._uiHash(this));
13595                                         this.containers[i].containerCache.over = 0;
13596                                 }
13597                         }
13598
13599                 }
13600                 
13601                 // if no intersecting containers found, return 
13602                 if(!innermostContainer) return; 
13603
13604                 // move the item into the container if it's not there already
13605                 if(this.containers.length === 1) {
13606                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
13607                         this.containers[innermostIndex].containerCache.over = 1;
13608                 } else if(this.currentContainer != this.containers[innermostIndex]) { 
13609
13610                         //When entering a new container, we will find the item with the least distance and append our item near it 
13611                         var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
13612                         for (var j = this.items.length - 1; j >= 0; j--) { 
13613                                 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
13614                                 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
13615                                 if(Math.abs(cur - base) < dist) { 
13616                                         dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
13617                                 } 
13618                         } 
13619
13620                         if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
13621                                 return; 
13622
13623                         this.currentContainer = this.containers[innermostIndex]; 
13624                         itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
13625                         this._trigger("change", event, this._uiHash()); 
13626                         this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
13627
13628                         //Update the placeholder 
13629                         this.options.placeholder.update(this.currentContainer, this.placeholder); 
13630                 
13631                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
13632                         this.containers[innermostIndex].containerCache.over = 1;
13633                 } 
13634         
13635                 
13636         },
13637
13638         _createHelper: function(event) {
13639
13640                 var o = this.options;
13641                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
13642
13643                 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
13644                         $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
13645
13646                 if(helper[0] == this.currentItem[0])
13647                         this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
13648
13649                 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
13650                 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
13651
13652                 return helper;
13653
13654         },
13655
13656         _adjustOffsetFromHelper: function(obj) {
13657                 if (typeof obj == 'string') {
13658                         obj = obj.split(' ');
13659                 }
13660                 if ($.isArray(obj)) {
13661                         obj = {left: +obj[0], top: +obj[1] || 0};
13662                 }
13663                 if ('left' in obj) {
13664                         this.offset.click.left = obj.left + this.margins.left;
13665                 }
13666                 if ('right' in obj) {
13667                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
13668                 }
13669                 if ('top' in obj) {
13670                         this.offset.click.top = obj.top + this.margins.top;
13671                 }
13672                 if ('bottom' in obj) {
13673                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
13674                 }
13675         },
13676
13677         _getParentOffset: function() {
13678
13679
13680                 //Get the offsetParent and cache its position
13681                 this.offsetParent = this.helper.offsetParent();
13682                 var po = this.offsetParent.offset();
13683
13684                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
13685                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
13686                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
13687                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
13688                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
13689                         po.left += this.scrollParent.scrollLeft();
13690                         po.top += this.scrollParent.scrollTop();
13691                 }
13692
13693                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
13694                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
13695                         po = { top: 0, left: 0 };
13696
13697                 return {
13698                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
13699                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
13700                 };
13701
13702         },
13703
13704         _getRelativeOffset: function() {
13705
13706                 if(this.cssPosition == "relative") {
13707                         var p = this.currentItem.position();
13708                         return {
13709                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
13710                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
13711                         };
13712                 } else {
13713                         return { top: 0, left: 0 };
13714                 }
13715
13716         },
13717
13718         _cacheMargins: function() {
13719                 this.margins = {
13720                         left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
13721                         top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
13722                 };
13723         },
13724
13725         _cacheHelperProportions: function() {
13726                 this.helperProportions = {
13727                         width: this.helper.outerWidth(),
13728                         height: this.helper.outerHeight()
13729                 };
13730         },
13731
13732         _setContainment: function() {
13733
13734                 var o = this.options;
13735                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
13736                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
13737                         0 - this.offset.relative.left - this.offset.parent.left,
13738                         0 - this.offset.relative.top - this.offset.parent.top,
13739                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
13740                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
13741                 ];
13742
13743                 if(!(/^(document|window|parent)$/).test(o.containment)) {
13744                         var ce = $(o.containment)[0];
13745                         var co = $(o.containment).offset();
13746                         var over = ($(ce).css("overflow") != 'hidden');
13747
13748                         this.containment = [
13749                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
13750                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
13751                                 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
13752                                 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
13753                         ];
13754                 }
13755
13756         },
13757
13758         _convertPositionTo: function(d, pos) {
13759
13760                 if(!pos) pos = this.position;
13761                 var mod = d == "absolute" ? 1 : -1;
13762                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
13763
13764                 return {
13765                         top: (
13766                                 pos.top                                                                                                                                 // The absolute mouse position
13767                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
13768                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
13769                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
13770                         ),
13771                         left: (
13772                                 pos.left                                                                                                                                // The absolute mouse position
13773                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
13774                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
13775                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
13776                         )
13777                 };
13778
13779         },
13780
13781         _generatePosition: function(event) {
13782
13783                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
13784
13785                 // This is another very weird special case that only happens for relative elements:
13786                 // 1. If the css position is relative
13787                 // 2. and the scroll parent is the document or similar to the offset parent
13788                 // we have to refresh the relative offset during the scroll so there are no jumps
13789                 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
13790                         this.offset.relative = this._getRelativeOffset();
13791                 }
13792
13793                 var pageX = event.pageX;
13794                 var pageY = event.pageY;
13795
13796                 /*
13797                  * - Position constraining -
13798                  * Constrain the position to a mix of grid, containment.
13799                  */
13800
13801                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
13802
13803                         if(this.containment) {
13804                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
13805                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
13806                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
13807                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
13808                         }
13809
13810                         if(o.grid) {
13811                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
13812                                 pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
13813
13814                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
13815                                 pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
13816                         }
13817
13818                 }
13819
13820                 return {
13821                         top: (
13822                                 pageY                                                                                                                           // The absolute mouse position
13823                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
13824                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
13825                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
13826                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
13827                         ),
13828                         left: (
13829                                 pageX                                                                                                                           // The absolute mouse position
13830                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
13831                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
13832                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
13833                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
13834                         )
13835                 };
13836
13837         },
13838
13839         _rearrange: function(event, i, a, hardRefresh) {
13840
13841                 a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
13842
13843                 //Various things done here to improve the performance:
13844                 // 1. we create a setTimeout, that calls refreshPositions
13845                 // 2. on the instance, we have a counter variable, that get's higher after every append
13846                 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
13847                 // 4. this lets only the last addition to the timeout stack through
13848                 this.counter = this.counter ? ++this.counter : 1;
13849                 var self = this, counter = this.counter;
13850
13851                 window.setTimeout(function() {
13852                         if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
13853                 },0);
13854
13855         },
13856
13857         _clear: function(event, noPropagation) {
13858
13859                 this.reverting = false;
13860                 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
13861                 // everything else normalized again
13862                 var delayedTriggers = [], self = this;
13863
13864                 // We first have to update the dom position of the actual currentItem
13865                 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
13866                 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
13867                 this._noFinalSort = null;
13868
13869                 if(this.helper[0] == this.currentItem[0]) {
13870                         for(var i in this._storedCSS) {
13871                                 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
13872                         }
13873                         this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13874                 } else {
13875                         this.currentItem.show();
13876                 }
13877
13878                 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
13879                 if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
13880                 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
13881                         if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
13882                         for (var i = this.containers.length - 1; i >= 0; i--){
13883                                 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
13884                                         delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
13885                                         delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
13886                                 }
13887                         };
13888                 };
13889
13890                 //Post events to containers
13891                 for (var i = this.containers.length - 1; i >= 0; i--){
13892                         if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
13893                         if(this.containers[i].containerCache.over) {
13894                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
13895                                 this.containers[i].containerCache.over = 0;
13896                         }
13897                 }
13898
13899                 //Do what was originally in plugins
13900                 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
13901                 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
13902                 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
13903
13904                 this.dragging = false;
13905                 if(this.cancelHelperRemoval) {
13906                         if(!noPropagation) {
13907                                 this._trigger("beforeStop", event, this._uiHash());
13908                                 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
13909                                 this._trigger("stop", event, this._uiHash());
13910                         }
13911                         return false;
13912                 }
13913
13914                 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
13915
13916                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13917                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13918
13919                 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
13920
13921                 if(!noPropagation) {
13922                         for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
13923                         this._trigger("stop", event, this._uiHash());
13924                 }
13925
13926                 this.fromOutside = false;
13927                 return true;
13928
13929         },
13930
13931         _trigger: function() {
13932                 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
13933                         this.cancel();
13934                 }
13935         },
13936
13937         _uiHash: function(inst) {
13938                 var self = inst || this;
13939                 return {
13940                         helper: self.helper,
13941                         placeholder: self.placeholder || $([]),
13942                         position: self.position,
13943                         originalPosition: self.originalPosition,
13944                         offset: self.positionAbs,
13945                         item: self.currentItem,
13946                         sender: inst ? inst.element : null
13947                 };
13948         }
13949
13950 });
13951
13952 $.extend($.ui.sortable, {
13953         version: "1.8.16"
13954 });
13955
13956 })(jQuery);
13957 /*
13958  * jQuery UI Effects 1.8.16
13959  *
13960  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
13961  * Dual licensed under the MIT or GPL Version 2 licenses.
13962  * http://jquery.org/license
13963  *
13964  * http://docs.jquery.com/UI/Effects/
13965  */
13966 ;jQuery.effects || (function($, undefined) {
13967
13968 $.effects = {};
13969
13970
13971
13972 /******************************************************************************/
13973 /****************************** COLOR ANIMATIONS ******************************/
13974 /******************************************************************************/
13975
13976 // override the animation for color styles
13977 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
13978         'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
13979 function(i, attr) {
13980         $.fx.step[attr] = function(fx) {
13981                 if (!fx.colorInit) {
13982                         fx.start = getColor(fx.elem, attr);
13983                         fx.end = getRGB(fx.end);
13984                         fx.colorInit = true;
13985                 }
13986
13987                 fx.elem.style[attr] = 'rgb(' +
13988                         Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
13989                         Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
13990                         Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
13991         };
13992 });
13993
13994 // Color Conversion functions from highlightFade
13995 // By Blair Mitchelmore
13996 // http://jquery.offput.ca/highlightFade/
13997
13998 // Parse strings looking for color tuples [255,255,255]
13999 function getRGB(color) {
14000                 var result;
14001
14002                 // Check if we're already dealing with an array of colors
14003                 if ( color && color.constructor == Array && color.length == 3 )
14004                                 return color;
14005
14006                 // Look for rgb(num,num,num)
14007                 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
14008                                 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
14009
14010                 // Look for rgb(num%,num%,num%)
14011                 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
14012                                 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
14013
14014                 // Look for #a0b1c2
14015                 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
14016                                 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
14017
14018                 // Look for #fff
14019                 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
14020                                 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
14021
14022                 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
14023                 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
14024                                 return colors['transparent'];
14025
14026                 // Otherwise, we're most likely dealing with a named color
14027                 return colors[$.trim(color).toLowerCase()];
14028 }
14029
14030 function getColor(elem, attr) {
14031                 var color;
14032
14033                 do {
14034                                 color = $.curCSS(elem, attr);
14035
14036                                 // Keep going until we find an element that has color, or we hit the body
14037                                 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
14038                                                 break;
14039
14040                                 attr = "backgroundColor";
14041                 } while ( elem = elem.parentNode );
14042
14043                 return getRGB(color);
14044 };
14045
14046 // Some named colors to work with
14047 // From Interface by Stefan Petre
14048 // http://interface.eyecon.ro/
14049
14050 var colors = {
14051         aqua:[0,255,255],
14052         azure:[240,255,255],
14053         beige:[245,245,220],
14054         black:[0,0,0],
14055         blue:[0,0,255],
14056         brown:[165,42,42],
14057         cyan:[0,255,255],
14058         darkblue:[0,0,139],
14059         darkcyan:[0,139,139],
14060         darkgrey:[169,169,169],
14061         darkgreen:[0,100,0],
14062         darkkhaki:[189,183,107],
14063         darkmagenta:[139,0,139],
14064         darkolivegreen:[85,107,47],
14065         darkorange:[255,140,0],
14066         darkorchid:[153,50,204],
14067         darkred:[139,0,0],
14068         darksalmon:[233,150,122],
14069         darkviolet:[148,0,211],
14070         fuchsia:[255,0,255],
14071         gold:[255,215,0],
14072         green:[0,128,0],
14073         indigo:[75,0,130],
14074         khaki:[240,230,140],
14075         lightblue:[173,216,230],
14076         lightcyan:[224,255,255],
14077         lightgreen:[144,238,144],
14078         lightgrey:[211,211,211],
14079         lightpink:[255,182,193],
14080         lightyellow:[255,255,224],
14081         lime:[0,255,0],
14082         magenta:[255,0,255],
14083         maroon:[128,0,0],
14084         navy:[0,0,128],
14085         olive:[128,128,0],
14086         orange:[255,165,0],
14087         pink:[255,192,203],
14088         purple:[128,0,128],
14089         violet:[128,0,128],
14090         red:[255,0,0],
14091         silver:[192,192,192],
14092         white:[255,255,255],
14093         yellow:[255,255,0],
14094         transparent: [255,255,255]
14095 };
14096
14097
14098
14099 /******************************************************************************/
14100 /****************************** CLASS ANIMATIONS ******************************/
14101 /******************************************************************************/
14102
14103 var classAnimationActions = ['add', 'remove', 'toggle'],
14104         shorthandStyles = {
14105                 border: 1,
14106                 borderBottom: 1,
14107                 borderColor: 1,
14108                 borderLeft: 1,
14109                 borderRight: 1,
14110                 borderTop: 1,
14111                 borderWidth: 1,
14112                 margin: 1,
14113                 padding: 1
14114         };
14115
14116 function getElementStyles() {
14117         var style = document.defaultView
14118                         ? document.defaultView.getComputedStyle(this, null)
14119                         : this.currentStyle,
14120                 newStyle = {},
14121                 key,
14122                 camelCase;
14123
14124         // webkit enumerates style porperties
14125         if (style && style.length && style[0] && style[style[0]]) {
14126                 var len = style.length;
14127                 while (len--) {
14128                         key = style[len];
14129                         if (typeof style[key] == 'string') {
14130                                 camelCase = key.replace(/\-(\w)/g, function(all, letter){
14131                                         return letter.toUpperCase();
14132                                 });
14133                                 newStyle[camelCase] = style[key];
14134                         }
14135                 }
14136         } else {
14137                 for (key in style) {
14138                         if (typeof style[key] === 'string') {
14139                                 newStyle[key] = style[key];
14140                         }
14141                 }
14142         }
14143         
14144         return newStyle;
14145 }
14146
14147 function filterStyles(styles) {
14148         var name, value;
14149         for (name in styles) {
14150                 value = styles[name];
14151                 if (
14152                         // ignore null and undefined values
14153                         value == null ||
14154                         // ignore functions (when does this occur?)
14155                         $.isFunction(value) ||
14156                         // shorthand styles that need to be expanded
14157                         name in shorthandStyles ||
14158                         // ignore scrollbars (break in IE)
14159                         (/scrollbar/).test(name) ||
14160
14161                         // only colors or values that can be converted to numbers
14162                         (!(/color/i).test(name) && isNaN(parseFloat(value)))
14163                 ) {
14164                         delete styles[name];
14165                 }
14166         }
14167         
14168         return styles;
14169 }
14170
14171 function styleDifference(oldStyle, newStyle) {
14172         var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
14173                 name;
14174
14175         for (name in newStyle) {
14176                 if (oldStyle[name] != newStyle[name]) {
14177                         diff[name] = newStyle[name];
14178                 }
14179         }
14180
14181         return diff;
14182 }
14183
14184 $.effects.animateClass = function(value, duration, easing, callback) {
14185         if ($.isFunction(easing)) {
14186                 callback = easing;
14187                 easing = null;
14188         }
14189
14190         return this.queue(function() {
14191                 var that = $(this),
14192                         originalStyleAttr = that.attr('style') || ' ',
14193                         originalStyle = filterStyles(getElementStyles.call(this)),
14194                         newStyle,
14195                         className = that.attr('class');
14196
14197                 $.each(classAnimationActions, function(i, action) {
14198                         if (value[action]) {
14199                                 that[action + 'Class'](value[action]);
14200                         }
14201                 });
14202                 newStyle = filterStyles(getElementStyles.call(this));
14203                 that.attr('class', className);
14204
14205                 that.animate(styleDifference(originalStyle, newStyle), {
14206                         queue: false,
14207                         duration: duration,
14208                         easing: easing,
14209                         complete: function() {
14210                                 $.each(classAnimationActions, function(i, action) {
14211                                         if (value[action]) { that[action + 'Class'](value[action]); }
14212                                 });
14213                                 // work around bug in IE by clearing the cssText before setting it
14214                                 if (typeof that.attr('style') == 'object') {
14215                                         that.attr('style').cssText = '';
14216                                         that.attr('style').cssText = originalStyleAttr;
14217                                 } else {
14218                                         that.attr('style', originalStyleAttr);
14219                                 }
14220                                 if (callback) { callback.apply(this, arguments); }
14221                                 $.dequeue( this );
14222                         }
14223                 });
14224         });
14225 };
14226
14227 $.fn.extend({
14228         _addClass: $.fn.addClass,
14229         addClass: function(classNames, speed, easing, callback) {
14230                 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
14231         },
14232
14233         _removeClass: $.fn.removeClass,
14234         removeClass: function(classNames,speed,easing,callback) {
14235                 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
14236         },
14237
14238         _toggleClass: $.fn.toggleClass,
14239         toggleClass: function(classNames, force, speed, easing, callback) {
14240                 if ( typeof force == "boolean" || force === undefined ) {
14241                         if ( !speed ) {
14242                                 // without speed parameter;
14243                                 return this._toggleClass(classNames, force);
14244                         } else {
14245                                 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
14246                         }
14247                 } else {
14248                         // without switch parameter;
14249                         return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
14250                 }
14251         },
14252
14253         switchClass: function(remove,add,speed,easing,callback) {
14254                 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
14255         }
14256 });
14257
14258
14259
14260 /******************************************************************************/
14261 /*********************************** EFFECTS **********************************/
14262 /******************************************************************************/
14263
14264 $.extend($.effects, {
14265         version: "1.8.16",
14266
14267         // Saves a set of properties in a data storage
14268         save: function(element, set) {
14269                 for(var i=0; i < set.length; i++) {
14270                         if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
14271                 }
14272         },
14273
14274         // Restores a set of previously saved properties from a data storage
14275         restore: function(element, set) {
14276                 for(var i=0; i < set.length; i++) {
14277                         if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
14278                 }
14279         },
14280
14281         setMode: function(el, mode) {
14282                 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
14283                 return mode;
14284         },
14285
14286         getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
14287                 // this should be a little more flexible in the future to handle a string & hash
14288                 var y, x;
14289                 switch (origin[0]) {
14290                         case 'top': y = 0; break;
14291                         case 'middle': y = 0.5; break;
14292                         case 'bottom': y = 1; break;
14293                         default: y = origin[0] / original.height;
14294                 };
14295                 switch (origin[1]) {
14296                         case 'left': x = 0; break;
14297                         case 'center': x = 0.5; break;
14298                         case 'right': x = 1; break;
14299                         default: x = origin[1] / original.width;
14300                 };
14301                 return {x: x, y: y};
14302         },
14303
14304         // Wraps the element around a wrapper that copies position properties
14305         createWrapper: function(element) {
14306
14307                 // if the element is already wrapped, return it
14308                 if (element.parent().is('.ui-effects-wrapper')) {
14309                         return element.parent();
14310                 }
14311
14312                 // wrap the element
14313                 var props = {
14314                                 width: element.outerWidth(true),
14315                                 height: element.outerHeight(true),
14316                                 'float': element.css('float')
14317                         },
14318                         wrapper = $('<div></div>')
14319                                 .addClass('ui-effects-wrapper')
14320                                 .css({
14321                                         fontSize: '100%',
14322                                         background: 'transparent',
14323                                         border: 'none',
14324                                         margin: 0,
14325                                         padding: 0
14326                                 }),
14327                         active = document.activeElement;
14328
14329                 element.wrap(wrapper);
14330
14331                 // Fixes #7595 - Elements lose focus when wrapped.
14332                 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
14333                         $( active ).focus();
14334                 }
14335                 
14336                 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
14337
14338                 // transfer positioning properties to the wrapper
14339                 if (element.css('position') == 'static') {
14340                         wrapper.css({ position: 'relative' });
14341                         element.css({ position: 'relative' });
14342                 } else {
14343                         $.extend(props, {
14344                                 position: element.css('position'),
14345                                 zIndex: element.css('z-index')
14346                         });
14347                         $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
14348                                 props[pos] = element.css(pos);
14349                                 if (isNaN(parseInt(props[pos], 10))) {
14350                                         props[pos] = 'auto';
14351                                 }
14352                         });
14353                         element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
14354                 }
14355
14356                 return wrapper.css(props).show();
14357         },
14358
14359         removeWrapper: function(element) {
14360                 var parent,
14361                         active = document.activeElement;
14362                 
14363                 if (element.parent().is('.ui-effects-wrapper')) {
14364                         parent = element.parent().replaceWith(element);
14365                         // Fixes #7595 - Elements lose focus when wrapped.
14366                         if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
14367                                 $( active ).focus();
14368                         }
14369                         return parent;
14370                 }
14371                         
14372                 return element;
14373         },
14374
14375         setTransition: function(element, list, factor, value) {
14376                 value = value || {};
14377                 $.each(list, function(i, x){
14378                         unit = element.cssUnit(x);
14379                         if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
14380                 });
14381                 return value;
14382         }
14383 });
14384
14385
14386 function _normalizeArguments(effect, options, speed, callback) {
14387         // shift params for method overloading
14388         if (typeof effect == 'object') {
14389                 callback = options;
14390                 speed = null;
14391                 options = effect;
14392                 effect = options.effect;
14393         }
14394         if ($.isFunction(options)) {
14395                 callback = options;
14396                 speed = null;
14397                 options = {};
14398         }
14399         if (typeof options == 'number' || $.fx.speeds[options]) {
14400                 callback = speed;
14401                 speed = options;
14402                 options = {};
14403         }
14404         if ($.isFunction(speed)) {
14405                 callback = speed;
14406                 speed = null;
14407         }
14408
14409         options = options || {};
14410
14411         speed = speed || options.duration;
14412         speed = $.fx.off ? 0 : typeof speed == 'number'
14413                 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
14414
14415         callback = callback || options.complete;
14416
14417         return [effect, options, speed, callback];
14418 }
14419
14420 function standardSpeed( speed ) {
14421         // valid standard speeds
14422         if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
14423                 return true;
14424         }
14425         
14426         // invalid strings - treat as "normal" speed
14427         if ( typeof speed === "string" && !$.effects[ speed ] ) {
14428                 return true;
14429         }
14430         
14431         return false;
14432 }
14433
14434 $.fn.extend({
14435         effect: function(effect, options, speed, callback) {
14436                 var args = _normalizeArguments.apply(this, arguments),
14437                         // TODO: make effects take actual parameters instead of a hash
14438                         args2 = {
14439                                 options: args[1],
14440                                 duration: args[2],
14441                                 callback: args[3]
14442                         },
14443                         mode = args2.options.mode,
14444                         effectMethod = $.effects[effect];
14445                 
14446                 if ( $.fx.off || !effectMethod ) {
14447                         // delegate to the original method (e.g., .show()) if possible
14448                         if ( mode ) {
14449                                 return this[ mode ]( args2.duration, args2.callback );
14450                         } else {
14451                                 return this.each(function() {
14452                                         if ( args2.callback ) {
14453                                                 args2.callback.call( this );
14454                                         }
14455                                 });
14456                         }
14457                 }
14458                 
14459                 return effectMethod.call(this, args2);
14460         },
14461
14462         _show: $.fn.show,
14463         show: function(speed) {
14464                 if ( standardSpeed( speed ) ) {
14465                         return this._show.apply(this, arguments);
14466                 } else {
14467                         var args = _normalizeArguments.apply(this, arguments);
14468                         args[1].mode = 'show';
14469                         return this.effect.apply(this, args);
14470                 }
14471         },
14472
14473         _hide: $.fn.hide,
14474         hide: function(speed) {
14475                 if ( standardSpeed( speed ) ) {
14476                         return this._hide.apply(this, arguments);
14477                 } else {
14478                         var args = _normalizeArguments.apply(this, arguments);
14479                         args[1].mode = 'hide';
14480                         return this.effect.apply(this, args);
14481                 }
14482         },
14483
14484         // jQuery core overloads toggle and creates _toggle
14485         __toggle: $.fn.toggle,
14486         toggle: function(speed) {
14487                 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
14488                         return this.__toggle.apply(this, arguments);
14489                 } else {
14490                         var args = _normalizeArguments.apply(this, arguments);
14491                         args[1].mode = 'toggle';
14492                         return this.effect.apply(this, args);
14493                 }
14494         },
14495
14496         // helper functions
14497         cssUnit: function(key) {
14498                 var style = this.css(key), val = [];
14499                 $.each( ['em','px','%','pt'], function(i, unit){
14500                         if(style.indexOf(unit) > 0)
14501                                 val = [parseFloat(style), unit];
14502                 });
14503                 return val;
14504         }
14505 });
14506
14507
14508
14509 /******************************************************************************/
14510 /*********************************** EASING ***********************************/
14511 /******************************************************************************/
14512
14513 /*
14514  * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
14515  *
14516  * Uses the built in easing capabilities added In jQuery 1.1
14517  * to offer multiple easing options
14518  *
14519  * TERMS OF USE - jQuery Easing
14520  *
14521  * Open source under the BSD License.
14522  *
14523  * Copyright 2008 George McGinley Smith
14524  * All rights reserved.
14525  *
14526  * Redistribution and use in source and binary forms, with or without modification,
14527  * are permitted provided that the following conditions are met:
14528  *
14529  * Redistributions of source code must retain the above copyright notice, this list of
14530  * conditions and the following disclaimer.
14531  * Redistributions in binary form must reproduce the above copyright notice, this list
14532  * of conditions and the following disclaimer in the documentation and/or other materials
14533  * provided with the distribution.
14534  *
14535  * Neither the name of the author nor the names of contributors may be used to endorse
14536  * or promote products derived from this software without specific prior written permission.
14537  *
14538  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
14539  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14540  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
14541  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14542  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
14543  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
14544  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14545  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
14546  * OF THE POSSIBILITY OF SUCH DAMAGE.
14547  *
14548 */
14549
14550 // t: current time, b: begInnIng value, c: change In value, d: duration
14551 $.easing.jswing = $.easing.swing;
14552
14553 $.extend($.easing,
14554 {
14555         def: 'easeOutQuad',
14556         swing: function (x, t, b, c, d) {
14557                 //alert($.easing.default);
14558                 return $.easing[$.easing.def](x, t, b, c, d);
14559         },
14560         easeInQuad: function (x, t, b, c, d) {
14561                 return c*(t/=d)*t + b;
14562         },
14563         easeOutQuad: function (x, t, b, c, d) {
14564                 return -c *(t/=d)*(t-2) + b;
14565         },
14566         easeInOutQuad: function (x, t, b, c, d) {
14567                 if ((t/=d/2) < 1) return c/2*t*t + b;
14568                 return -c/2 * ((--t)*(t-2) - 1) + b;
14569         },
14570         easeInCubic: function (x, t, b, c, d) {
14571                 return c*(t/=d)*t*t + b;
14572         },
14573         easeOutCubic: function (x, t, b, c, d) {
14574                 return c*((t=t/d-1)*t*t + 1) + b;
14575         },
14576         easeInOutCubic: function (x, t, b, c, d) {
14577                 if ((t/=d/2) < 1) return c/2*t*t*t + b;
14578                 return c/2*((t-=2)*t*t + 2) + b;
14579         },
14580         easeInQuart: function (x, t, b, c, d) {
14581                 return c*(t/=d)*t*t*t + b;
14582         },
14583         easeOutQuart: function (x, t, b, c, d) {
14584                 return -c * ((t=t/d-1)*t*t*t - 1) + b;
14585         },
14586         easeInOutQuart: function (x, t, b, c, d) {
14587                 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
14588                 return -c/2 * ((t-=2)*t*t*t - 2) + b;
14589         },
14590         easeInQuint: function (x, t, b, c, d) {
14591                 return c*(t/=d)*t*t*t*t + b;
14592         },
14593         easeOutQuint: function (x, t, b, c, d) {
14594                 return c*((t=t/d-1)*t*t*t*t + 1) + b;
14595         },
14596         easeInOutQuint: function (x, t, b, c, d) {
14597                 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
14598                 return c/2*((t-=2)*t*t*t*t + 2) + b;
14599         },
14600         easeInSine: function (x, t, b, c, d) {
14601                 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
14602         },
14603         easeOutSine: function (x, t, b, c, d) {
14604                 return c * Math.sin(t/d * (Math.PI/2)) + b;
14605         },
14606         easeInOutSine: function (x, t, b, c, d) {
14607                 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
14608         },
14609         easeInExpo: function (x, t, b, c, d) {
14610                 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
14611         },
14612         easeOutExpo: function (x, t, b, c, d) {
14613                 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
14614         },
14615         easeInOutExpo: function (x, t, b, c, d) {
14616                 if (t==0) return b;
14617                 if (t==d) return b+c;
14618                 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
14619                 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
14620         },
14621         easeInCirc: function (x, t, b, c, d) {
14622                 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
14623         },
14624         easeOutCirc: function (x, t, b, c, d) {
14625                 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
14626         },
14627         easeInOutCirc: function (x, t, b, c, d) {
14628                 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
14629                 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
14630         },
14631         easeInElastic: function (x, t, b, c, d) {
14632                 var s=1.70158;var p=0;var a=c;
14633                 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
14634                 if (a < Math.abs(c)) { a=c; var s=p/4; }
14635                 else var s = p/(2*Math.PI) * Math.asin (c/a);
14636                 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
14637         },
14638         easeOutElastic: function (x, t, b, c, d) {
14639                 var s=1.70158;var p=0;var a=c;
14640                 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
14641                 if (a < Math.abs(c)) { a=c; var s=p/4; }
14642                 else var s = p/(2*Math.PI) * Math.asin (c/a);
14643                 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
14644         },
14645         easeInOutElastic: function (x, t, b, c, d) {
14646                 var s=1.70158;var p=0;var a=c;
14647                 if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
14648                 if (a < Math.abs(c)) { a=c; var s=p/4; }
14649                 else var s = p/(2*Math.PI) * Math.asin (c/a);
14650                 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
14651                 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
14652         },
14653         easeInBack: function (x, t, b, c, d, s) {
14654                 if (s == undefined) s = 1.70158;
14655                 return c*(t/=d)*t*((s+1)*t - s) + b;
14656         },
14657         easeOutBack: function (x, t, b, c, d, s) {
14658                 if (s == undefined) s = 1.70158;
14659                 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
14660         },
14661         easeInOutBack: function (x, t, b, c, d, s) {
14662                 if (s == undefined) s = 1.70158;
14663                 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
14664                 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
14665         },
14666         easeInBounce: function (x, t, b, c, d) {
14667                 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
14668         },
14669         easeOutBounce: function (x, t, b, c, d) {
14670                 if ((t/=d) < (1/2.75)) {
14671                         return c*(7.5625*t*t) + b;
14672                 } else if (t < (2/2.75)) {
14673                         return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
14674                 } else if (t < (2.5/2.75)) {
14675                         return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
14676                 } else {
14677                         return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
14678                 }
14679         },
14680         easeInOutBounce: function (x, t, b, c, d) {
14681                 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
14682                 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
14683         }
14684 });
14685
14686 /*
14687  *
14688  * TERMS OF USE - EASING EQUATIONS
14689  *
14690  * Open source under the BSD License.
14691  *
14692  * Copyright 2001 Robert Penner
14693  * All rights reserved.
14694  *
14695  * Redistribution and use in source and binary forms, with or without modification,
14696  * are permitted provided that the following conditions are met:
14697  *
14698  * Redistributions of source code must retain the above copyright notice, this list of
14699  * conditions and the following disclaimer.
14700  * Redistributions in binary form must reproduce the above copyright notice, this list
14701  * of conditions and the following disclaimer in the documentation and/or other materials
14702  * provided with the distribution.
14703  *
14704  * Neither the name of the author nor the names of contributors may be used to endorse
14705  * or promote products derived from this software without specific prior written permission.
14706  *
14707  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
14708  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14709  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
14710  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14711  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
14712  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
14713  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14714  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
14715  * OF THE POSSIBILITY OF SUCH DAMAGE.
14716  *
14717  */
14718
14719 })(jQuery);
14720 /*
14721  * jQuery UI Effects Blind 1.8.16
14722  *
14723  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14724  * Dual licensed under the MIT or GPL Version 2 licenses.
14725  * http://jquery.org/license
14726  *
14727  * http://docs.jquery.com/UI/Effects/Blind
14728  *
14729  * Depends:
14730  *      jquery.effects.core.js
14731  */
14732 (function( $, undefined ) {
14733
14734 $.effects.blind = function(o) {
14735
14736         return this.queue(function() {
14737
14738                 // Create element
14739                 var el = $(this), props = ['position','top','bottom','left','right'];
14740
14741                 // Set options
14742                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14743                 var direction = o.options.direction || 'vertical'; // Default direction
14744
14745                 // Adjust
14746                 $.effects.save(el, props); el.show(); // Save & Show
14747                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
14748                 var ref = (direction == 'vertical') ? 'height' : 'width';
14749                 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
14750                 if(mode == 'show') wrapper.css(ref, 0); // Shift
14751
14752                 // Animation
14753                 var animation = {};
14754                 animation[ref] = mode == 'show' ? distance : 0;
14755
14756                 // Animate
14757                 wrapper.animate(animation, o.duration, o.options.easing, function() {
14758                         if(mode == 'hide') el.hide(); // Hide
14759                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14760                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
14761                         el.dequeue();
14762                 });
14763
14764         });
14765
14766 };
14767
14768 })(jQuery);
14769 /*
14770  * jQuery UI Effects Bounce 1.8.16
14771  *
14772  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14773  * Dual licensed under the MIT or GPL Version 2 licenses.
14774  * http://jquery.org/license
14775  *
14776  * http://docs.jquery.com/UI/Effects/Bounce
14777  *
14778  * Depends:
14779  *      jquery.effects.core.js
14780  */
14781 (function( $, undefined ) {
14782
14783 $.effects.bounce = function(o) {
14784
14785         return this.queue(function() {
14786
14787                 // Create element
14788                 var el = $(this), props = ['position','top','bottom','left','right'];
14789
14790                 // Set options
14791                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
14792                 var direction = o.options.direction || 'up'; // Default direction
14793                 var distance = o.options.distance || 20; // Default distance
14794                 var times = o.options.times || 5; // Default # of times
14795                 var speed = o.duration || 250; // Default speed per bounce
14796                 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
14797
14798                 // Adjust
14799                 $.effects.save(el, props); el.show(); // Save & Show
14800                 $.effects.createWrapper(el); // Create Wrapper
14801                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
14802                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
14803                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
14804                 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
14805                 if (mode == 'hide') distance = distance / (times * 2);
14806                 if (mode != 'hide') times--;
14807
14808                 // Animate
14809                 if (mode == 'show') { // Show Bounce
14810                         var animation = {opacity: 1};
14811                         animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
14812                         el.animate(animation, speed / 2, o.options.easing);
14813                         distance = distance / 2;
14814                         times--;
14815                 };
14816                 for (var i = 0; i < times; i++) { // Bounces
14817                         var animation1 = {}, animation2 = {};
14818                         animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
14819                         animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
14820                         el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
14821                         distance = (mode == 'hide') ? distance * 2 : distance / 2;
14822                 };
14823                 if (mode == 'hide') { // Last Bounce
14824                         var animation = {opacity: 0};
14825                         animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
14826                         el.animate(animation, speed / 2, o.options.easing, function(){
14827                                 el.hide(); // Hide
14828                                 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14829                                 if(o.callback) o.callback.apply(this, arguments); // Callback
14830                         });
14831                 } else {
14832                         var animation1 = {}, animation2 = {};
14833                         animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
14834                         animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
14835                         el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
14836                                 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14837                                 if(o.callback) o.callback.apply(this, arguments); // Callback
14838                         });
14839                 };
14840                 el.queue('fx', function() { el.dequeue(); });
14841                 el.dequeue();
14842         });
14843
14844 };
14845
14846 })(jQuery);
14847 /*
14848  * jQuery UI Effects Clip 1.8.16
14849  *
14850  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14851  * Dual licensed under the MIT or GPL Version 2 licenses.
14852  * http://jquery.org/license
14853  *
14854  * http://docs.jquery.com/UI/Effects/Clip
14855  *
14856  * Depends:
14857  *      jquery.effects.core.js
14858  */
14859 (function( $, undefined ) {
14860
14861 $.effects.clip = function(o) {
14862
14863         return this.queue(function() {
14864
14865                 // Create element
14866                 var el = $(this), props = ['position','top','bottom','left','right','height','width'];
14867
14868                 // Set options
14869                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14870                 var direction = o.options.direction || 'vertical'; // Default direction
14871
14872                 // Adjust
14873                 $.effects.save(el, props); el.show(); // Save & Show
14874                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
14875                 var animate = el[0].tagName == 'IMG' ? wrapper : el;
14876                 var ref = {
14877                         size: (direction == 'vertical') ? 'height' : 'width',
14878                         position: (direction == 'vertical') ? 'top' : 'left'
14879                 };
14880                 var distance = (direction == 'vertical') ? animate.height() : animate.width();
14881                 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
14882
14883                 // Animation
14884                 var animation = {};
14885                 animation[ref.size] = mode == 'show' ? distance : 0;
14886                 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
14887
14888                 // Animate
14889                 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
14890                         if(mode == 'hide') el.hide(); // Hide
14891                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14892                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
14893                         el.dequeue();
14894                 }});
14895
14896         });
14897
14898 };
14899
14900 })(jQuery);
14901 /*
14902  * jQuery UI Effects Drop 1.8.16
14903  *
14904  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14905  * Dual licensed under the MIT or GPL Version 2 licenses.
14906  * http://jquery.org/license
14907  *
14908  * http://docs.jquery.com/UI/Effects/Drop
14909  *
14910  * Depends:
14911  *      jquery.effects.core.js
14912  */
14913 (function( $, undefined ) {
14914
14915 $.effects.drop = function(o) {
14916
14917         return this.queue(function() {
14918
14919                 // Create element
14920                 var el = $(this), props = ['position','top','bottom','left','right','opacity'];
14921
14922                 // Set options
14923                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14924                 var direction = o.options.direction || 'left'; // Default Direction
14925
14926                 // Adjust
14927                 $.effects.save(el, props); el.show(); // Save & Show
14928                 $.effects.createWrapper(el); // Create Wrapper
14929                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
14930                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
14931                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
14932                 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
14933
14934                 // Animation
14935                 var animation = {opacity: mode == 'show' ? 1 : 0};
14936                 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
14937
14938                 // Animate
14939                 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
14940                         if(mode == 'hide') el.hide(); // Hide
14941                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14942                         if(o.callback) o.callback.apply(this, arguments); // Callback
14943                         el.dequeue();
14944                 }});
14945
14946         });
14947
14948 };
14949
14950 })(jQuery);
14951 /*
14952  * jQuery UI Effects Explode 1.8.16
14953  *
14954  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14955  * Dual licensed under the MIT or GPL Version 2 licenses.
14956  * http://jquery.org/license
14957  *
14958  * http://docs.jquery.com/UI/Effects/Explode
14959  *
14960  * Depends:
14961  *      jquery.effects.core.js
14962  */
14963 (function( $, undefined ) {
14964
14965 $.effects.explode = function(o) {
14966
14967         return this.queue(function() {
14968
14969         var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
14970         var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
14971
14972         o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
14973         var el = $(this).show().css('visibility', 'hidden');
14974         var offset = el.offset();
14975
14976         //Substract the margins - not fixing the problem yet.
14977         offset.top -= parseInt(el.css("marginTop"),10) || 0;
14978         offset.left -= parseInt(el.css("marginLeft"),10) || 0;
14979
14980         var width = el.outerWidth(true);
14981         var height = el.outerHeight(true);
14982
14983         for(var i=0;i<rows;i++) { // =
14984                 for(var j=0;j<cells;j++) { // ||
14985                         el
14986                                 .clone()
14987                                 .appendTo('body')
14988                                 .wrap('<div></div>')
14989                                 .css({
14990                                         position: 'absolute',
14991                                         visibility: 'visible',
14992                                         left: -j*(width/cells),
14993                                         top: -i*(height/rows)
14994                                 })
14995                                 .parent()
14996                                 .addClass('ui-effects-explode')
14997                                 .css({
14998                                         position: 'absolute',
14999                                         overflow: 'hidden',
15000                                         width: width/cells,
15001                                         height: height/rows,
15002                                         left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
15003                                         top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
15004                                         opacity: o.options.mode == 'show' ? 0 : 1
15005                                 }).animate({
15006                                         left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
15007                                         top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
15008                                         opacity: o.options.mode == 'show' ? 1 : 0
15009                                 }, o.duration || 500);
15010                 }
15011         }
15012
15013         // Set a timeout, to call the callback approx. when the other animations have finished
15014         setTimeout(function() {
15015
15016                 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
15017                                 if(o.callback) o.callback.apply(el[0]); // Callback
15018                                 el.dequeue();
15019
15020                                 $('div.ui-effects-explode').remove();
15021
15022         }, o.duration || 500);
15023
15024
15025         });
15026
15027 };
15028
15029 })(jQuery);
15030 /*
15031  * jQuery UI Effects Fade 1.8.16
15032  *
15033  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15034  * Dual licensed under the MIT or GPL Version 2 licenses.
15035  * http://jquery.org/license
15036  *
15037  * http://docs.jquery.com/UI/Effects/Fade
15038  *
15039  * Depends:
15040  *      jquery.effects.core.js
15041  */
15042 (function( $, undefined ) {
15043
15044 $.effects.fade = function(o) {
15045         return this.queue(function() {
15046                 var elem = $(this),
15047                         mode = $.effects.setMode(elem, o.options.mode || 'hide');
15048
15049                 elem.animate({ opacity: mode }, {
15050                         queue: false,
15051                         duration: o.duration,
15052                         easing: o.options.easing,
15053                         complete: function() {
15054                                 (o.callback && o.callback.apply(this, arguments));
15055                                 elem.dequeue();
15056                         }
15057                 });
15058         });
15059 };
15060
15061 })(jQuery);
15062 /*
15063  * jQuery UI Effects Fold 1.8.16
15064  *
15065  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15066  * Dual licensed under the MIT or GPL Version 2 licenses.
15067  * http://jquery.org/license
15068  *
15069  * http://docs.jquery.com/UI/Effects/Fold
15070  *
15071  * Depends:
15072  *      jquery.effects.core.js
15073  */
15074 (function( $, undefined ) {
15075
15076 $.effects.fold = function(o) {
15077
15078         return this.queue(function() {
15079
15080                 // Create element
15081                 var el = $(this), props = ['position','top','bottom','left','right'];
15082
15083                 // Set options
15084                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
15085                 var size = o.options.size || 15; // Default fold size
15086                 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
15087                 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
15088
15089                 // Adjust
15090                 $.effects.save(el, props); el.show(); // Save & Show
15091                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
15092                 var widthFirst = ((mode == 'show') != horizFirst);
15093                 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
15094                 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
15095                 var percent = /([0-9]+)%/.exec(size);
15096                 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
15097                 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
15098
15099                 // Animation
15100                 var animation1 = {}, animation2 = {};
15101                 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
15102                 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
15103
15104                 // Animate
15105                 wrapper.animate(animation1, duration, o.options.easing)
15106                 .animate(animation2, duration, o.options.easing, function() {
15107                         if(mode == 'hide') el.hide(); // Hide
15108                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
15109                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
15110                         el.dequeue();
15111                 });
15112
15113         });
15114
15115 };
15116
15117 })(jQuery);
15118 /*
15119  * jQuery UI Effects Highlight 1.8.16
15120  *
15121  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15122  * Dual licensed under the MIT or GPL Version 2 licenses.
15123  * http://jquery.org/license
15124  *
15125  * http://docs.jquery.com/UI/Effects/Highlight
15126  *
15127  * Depends:
15128  *      jquery.effects.core.js
15129  */
15130 (function( $, undefined ) {
15131
15132 $.effects.highlight = function(o) {
15133         return this.queue(function() {
15134                 var elem = $(this),
15135                         props = ['backgroundImage', 'backgroundColor', 'opacity'],
15136                         mode = $.effects.setMode(elem, o.options.mode || 'show'),
15137                         animation = {
15138                                 backgroundColor: elem.css('backgroundColor')
15139                         };
15140
15141                 if (mode == 'hide') {
15142                         animation.opacity = 0;
15143                 }
15144
15145                 $.effects.save(elem, props);
15146                 elem
15147                         .show()
15148                         .css({
15149                                 backgroundImage: 'none',
15150                                 backgroundColor: o.options.color || '#ffff99'
15151                         })
15152                         .animate(animation, {
15153                                 queue: false,
15154                                 duration: o.duration,
15155                                 easing: o.options.easing,
15156                                 complete: function() {
15157                                         (mode == 'hide' && elem.hide());
15158                                         $.effects.restore(elem, props);
15159                                         (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
15160                                         (o.callback && o.callback.apply(this, arguments));
15161                                         elem.dequeue();
15162                                 }
15163                         });
15164         });
15165 };
15166
15167 })(jQuery);
15168 /*
15169  * jQuery UI Effects Pulsate 1.8.16
15170  *
15171  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15172  * Dual licensed under the MIT or GPL Version 2 licenses.
15173  * http://jquery.org/license
15174  *
15175  * http://docs.jquery.com/UI/Effects/Pulsate
15176  *
15177  * Depends:
15178  *      jquery.effects.core.js
15179  */
15180 (function( $, undefined ) {
15181
15182 $.effects.pulsate = function(o) {
15183         return this.queue(function() {
15184                 var elem = $(this),
15185                         mode = $.effects.setMode(elem, o.options.mode || 'show');
15186                         times = ((o.options.times || 5) * 2) - 1;
15187                         duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
15188                         isVisible = elem.is(':visible'),
15189                         animateTo = 0;
15190
15191                 if (!isVisible) {
15192                         elem.css('opacity', 0).show();
15193                         animateTo = 1;
15194                 }
15195
15196                 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
15197                         times--;
15198                 }
15199
15200                 for (var i = 0; i < times; i++) {
15201                         elem.animate({ opacity: animateTo }, duration, o.options.easing);
15202                         animateTo = (animateTo + 1) % 2;
15203                 }
15204
15205                 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
15206                         if (animateTo == 0) {
15207                                 elem.hide();
15208                         }
15209                         (o.callback && o.callback.apply(this, arguments));
15210                 });
15211
15212                 elem
15213                         .queue('fx', function() { elem.dequeue(); })
15214                         .dequeue();
15215         });
15216 };
15217
15218 })(jQuery);
15219 /*
15220  * jQuery UI Effects Scale 1.8.16
15221  *
15222  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15223  * Dual licensed under the MIT or GPL Version 2 licenses.
15224  * http://jquery.org/license
15225  *
15226  * http://docs.jquery.com/UI/Effects/Scale
15227  *
15228  * Depends:
15229  *      jquery.effects.core.js
15230  */
15231 (function( $, undefined ) {
15232
15233 $.effects.puff = function(o) {
15234         return this.queue(function() {
15235                 var elem = $(this),
15236                         mode = $.effects.setMode(elem, o.options.mode || 'hide'),
15237                         percent = parseInt(o.options.percent, 10) || 150,
15238                         factor = percent / 100,
15239                         original = { height: elem.height(), width: elem.width() };
15240
15241                 $.extend(o.options, {
15242                         fade: true,
15243                         mode: mode,
15244                         percent: mode == 'hide' ? percent : 100,
15245                         from: mode == 'hide'
15246                                 ? original
15247                                 : {
15248                                         height: original.height * factor,
15249                                         width: original.width * factor
15250                                 }
15251                 });
15252
15253                 elem.effect('scale', o.options, o.duration, o.callback);
15254                 elem.dequeue();
15255         });
15256 };
15257
15258 $.effects.scale = function(o) {
15259
15260         return this.queue(function() {
15261
15262                 // Create element
15263                 var el = $(this);
15264
15265                 // Set options
15266                 var options = $.extend(true, {}, o.options);
15267                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
15268                 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
15269                 var direction = o.options.direction || 'both'; // Set default axis
15270                 var origin = o.options.origin; // The origin of the scaling
15271                 if (mode != 'effect') { // Set default origin and restore for show/hide
15272                         options.origin = origin || ['middle','center'];
15273                         options.restore = true;
15274                 }
15275                 var original = {height: el.height(), width: el.width()}; // Save original
15276                 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
15277
15278                 // Adjust
15279                 var factor = { // Set scaling factor
15280                         y: direction != 'horizontal' ? (percent / 100) : 1,
15281                         x: direction != 'vertical' ? (percent / 100) : 1
15282                 };
15283                 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
15284
15285                 if (o.options.fade) { // Fade option to support puff
15286                         if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
15287                         if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
15288                 };
15289
15290                 // Animation
15291                 options.from = el.from; options.to = el.to; options.mode = mode;
15292
15293                 // Animate
15294                 el.effect('size', options, o.duration, o.callback);
15295                 el.dequeue();
15296         });
15297
15298 };
15299
15300 $.effects.size = function(o) {
15301
15302         return this.queue(function() {
15303
15304                 // Create element
15305                 var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
15306                 var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
15307                 var props2 = ['width','height','overflow']; // Copy for children
15308                 var cProps = ['fontSize'];
15309                 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
15310                 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
15311
15312                 // Set options
15313                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
15314                 var restore = o.options.restore || false; // Default restore
15315                 var scale = o.options.scale || 'both'; // Default scale mode
15316                 var origin = o.options.origin; // The origin of the sizing
15317                 var original = {height: el.height(), width: el.width()}; // Save original
15318                 el.from = o.options.from || original; // Default from state
15319                 el.to = o.options.to || original; // Default to state
15320                 // Adjust
15321                 if (origin) { // Calculate baseline shifts
15322                         var baseline = $.effects.getBaseline(origin, original);
15323                         el.from.top = (original.height - el.from.height) * baseline.y;
15324                         el.from.left = (original.width - el.from.width) * baseline.x;
15325                         el.to.top = (original.height - el.to.height) * baseline.y;
15326                         el.to.left = (original.width - el.to.width) * baseline.x;
15327                 };
15328                 var factor = { // Set scaling factor
15329                         from: {y: el.from.height / original.height, x: el.from.width / original.width},
15330                         to: {y: el.to.height / original.height, x: el.to.width / original.width}
15331                 };
15332                 if (scale == 'box' || scale == 'both') { // Scale the css box
15333                         if (factor.from.y != factor.to.y) { // Vertical props scaling
15334                                 props = props.concat(vProps);
15335                                 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
15336                                 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
15337                         };
15338                         if (factor.from.x != factor.to.x) { // Horizontal props scaling
15339                                 props = props.concat(hProps);
15340                                 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
15341                                 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
15342                         };
15343                 };
15344                 if (scale == 'content' || scale == 'both') { // Scale the content
15345                         if (factor.from.y != factor.to.y) { // Vertical props scaling
15346                                 props = props.concat(cProps);
15347                                 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
15348                                 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
15349                         };
15350                 };
15351                 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
15352                 $.effects.createWrapper(el); // Create Wrapper
15353                 el.css('overflow','hidden').css(el.from); // Shift
15354
15355                 // Animate
15356                 if (scale == 'content' || scale == 'both') { // Scale the children
15357                         vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
15358                         hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
15359                         props2 = props.concat(vProps).concat(hProps); // Concat
15360                         el.find("*[width]").each(function(){
15361                                 child = $(this);
15362                                 if (restore) $.effects.save(child, props2);
15363                                 var c_original = {height: child.height(), width: child.width()}; // Save original
15364                                 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
15365                                 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
15366                                 if (factor.from.y != factor.to.y) { // Vertical props scaling
15367                                         child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
15368                                         child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
15369                                 };
15370                                 if (factor.from.x != factor.to.x) { // Horizontal props scaling
15371                                         child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
15372                                         child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
15373                                 };
15374                                 child.css(child.from); // Shift children
15375                                 child.animate(child.to, o.duration, o.options.easing, function(){
15376                                         if (restore) $.effects.restore(child, props2); // Restore children
15377                                 }); // Animate children
15378                         });
15379                 };
15380
15381                 // Animate
15382                 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
15383                         if (el.to.opacity === 0) {
15384                                 el.css('opacity', el.from.opacity);
15385                         }
15386                         if(mode == 'hide') el.hide(); // Hide
15387                         $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
15388                         if(o.callback) o.callback.apply(this, arguments); // Callback
15389                         el.dequeue();
15390                 }});
15391
15392         });
15393
15394 };
15395
15396 })(jQuery);
15397 /*
15398  * jQuery UI Effects Shake 1.8.16
15399  *
15400  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15401  * Dual licensed under the MIT or GPL Version 2 licenses.
15402  * http://jquery.org/license
15403  *
15404  * http://docs.jquery.com/UI/Effects/Shake
15405  *
15406  * Depends:
15407  *      jquery.effects.core.js
15408  */
15409 (function( $, undefined ) {
15410
15411 $.effects.shake = function(o) {
15412
15413         return this.queue(function() {
15414
15415                 // Create element
15416                 var el = $(this), props = ['position','top','bottom','left','right'];
15417
15418                 // Set options
15419                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
15420                 var direction = o.options.direction || 'left'; // Default direction
15421                 var distance = o.options.distance || 20; // Default distance
15422                 var times = o.options.times || 3; // Default # of times
15423                 var speed = o.duration || o.options.duration || 140; // Default speed per shake
15424
15425                 // Adjust
15426                 $.effects.save(el, props); el.show(); // Save & Show
15427                 $.effects.createWrapper(el); // Create Wrapper
15428                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
15429                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
15430
15431                 // Animation
15432                 var animation = {}, animation1 = {}, animation2 = {};
15433                 animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
15434                 animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
15435                 animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
15436
15437                 // Animate
15438                 el.animate(animation, speed, o.options.easing);
15439                 for (var i = 1; i < times; i++) { // Shakes
15440                         el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
15441                 };
15442                 el.animate(animation1, speed, o.options.easing).
15443                 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
15444                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
15445                         if(o.callback) o.callback.apply(this, arguments); // Callback
15446                 });
15447                 el.queue('fx', function() { el.dequeue(); });
15448                 el.dequeue();
15449         });
15450
15451 };
15452
15453 })(jQuery);
15454 /*
15455  * jQuery UI Effects Slide 1.8.16
15456  *
15457  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15458  * Dual licensed under the MIT or GPL Version 2 licenses.
15459  * http://jquery.org/license
15460  *
15461  * http://docs.jquery.com/UI/Effects/Slide
15462  *
15463  * Depends:
15464  *      jquery.effects.core.js
15465  */
15466 (function( $, undefined ) {
15467
15468 $.effects.slide = function(o) {
15469
15470         return this.queue(function() {
15471
15472                 // Create element
15473                 var el = $(this), props = ['position','top','bottom','left','right'];
15474
15475                 // Set options
15476                 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
15477                 var direction = o.options.direction || 'left'; // Default Direction
15478
15479                 // Adjust
15480                 $.effects.save(el, props); el.show(); // Save & Show
15481                 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
15482                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
15483                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
15484                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
15485                 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
15486
15487                 // Animation
15488                 var animation = {};
15489                 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
15490
15491                 // Animate
15492                 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
15493                         if(mode == 'hide') el.hide(); // Hide
15494                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
15495                         if(o.callback) o.callback.apply(this, arguments); // Callback
15496                         el.dequeue();
15497                 }});
15498
15499         });
15500
15501 };
15502
15503 })(jQuery);
15504 /*
15505  * jQuery UI Effects Transfer 1.8.16
15506  *
15507  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15508  * Dual licensed under the MIT or GPL Version 2 licenses.
15509  * http://jquery.org/license
15510  *
15511  * http://docs.jquery.com/UI/Effects/Transfer
15512  *
15513  * Depends:
15514  *      jquery.effects.core.js
15515  */
15516 (function( $, undefined ) {
15517
15518 $.effects.transfer = function(o) {
15519         return this.queue(function() {
15520                 var elem = $(this),
15521                         target = $(o.options.to),
15522                         endPosition = target.offset(),
15523                         animation = {
15524                                 top: endPosition.top,
15525                                 left: endPosition.left,
15526                                 height: target.innerHeight(),
15527                                 width: target.innerWidth()
15528                         },
15529                         startPosition = elem.offset(),
15530                         transfer = $('<div class="ui-effects-transfer"></div>')
15531                                 .appendTo(document.body)
15532                                 .addClass(o.options.className)
15533                                 .css({
15534                                         top: startPosition.top,
15535                                         left: startPosition.left,
15536                                         height: elem.innerHeight(),
15537                                         width: elem.innerWidth(),
15538                                         position: 'absolute'
15539                                 })
15540                                 .animate(animation, o.duration, o.options.easing, function() {
15541                                         transfer.remove();
15542                                         (o.callback && o.callback.apply(elem[0], arguments));
15543                                         elem.dequeue();
15544                                 });
15545         });
15546 };
15547
15548 })(jQuery);
15549 /*
15550  * jQuery UI Accordion 1.8.16
15551  *
15552  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15553  * Dual licensed under the MIT or GPL Version 2 licenses.
15554  * http://jquery.org/license
15555  *
15556  * http://docs.jquery.com/UI/Accordion
15557  *
15558  * Depends:
15559  *      jquery.ui.core.js
15560  *      jquery.ui.widget.js
15561  */
15562 (function( $, undefined ) {
15563
15564 $.widget( "ui.accordion", {
15565         options: {
15566                 active: 0,
15567                 animated: "slide",
15568                 autoHeight: true,
15569                 clearStyle: false,
15570                 collapsible: false,
15571                 event: "click",
15572                 fillSpace: false,
15573                 header: "> li > :first-child,> :not(li):even",
15574                 icons: {
15575                         header: "ui-icon-triangle-1-e",
15576                         headerSelected: "ui-icon-triangle-1-s"
15577                 },
15578                 navigation: false,
15579                 navigationFilter: function() {
15580                         return this.href.toLowerCase() === location.href.toLowerCase();
15581                 }
15582         },
15583
15584         _create: function() {
15585                 var self = this,
15586                         options = self.options;
15587
15588                 self.running = 0;
15589
15590                 self.element
15591                         .addClass( "ui-accordion ui-widget ui-helper-reset" )
15592                         // in lack of child-selectors in CSS
15593                         // we need to mark top-LIs in a UL-accordion for some IE-fix
15594                         .children( "li" )
15595                                 .addClass( "ui-accordion-li-fix" );
15596
15597                 self.headers = self.element.find( options.header )
15598                         .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
15599                         .bind( "mouseenter.accordion", function() {
15600                                 if ( options.disabled ) {
15601                                         return;
15602                                 }
15603                                 $( this ).addClass( "ui-state-hover" );
15604                         })
15605                         .bind( "mouseleave.accordion", function() {
15606                                 if ( options.disabled ) {
15607                                         return;
15608                                 }
15609                                 $( this ).removeClass( "ui-state-hover" );
15610                         })
15611                         .bind( "focus.accordion", function() {
15612                                 if ( options.disabled ) {
15613                                         return;
15614                                 }
15615                                 $( this ).addClass( "ui-state-focus" );
15616                         })
15617                         .bind( "blur.accordion", function() {
15618                                 if ( options.disabled ) {
15619                                         return;
15620                                 }
15621                                 $( this ).removeClass( "ui-state-focus" );
15622                         });
15623
15624                 self.headers.next()
15625                         .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
15626
15627                 if ( options.navigation ) {
15628                         var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
15629                         if ( current.length ) {
15630                                 var header = current.closest( ".ui-accordion-header" );
15631                                 if ( header.length ) {
15632                                         // anchor within header
15633                                         self.active = header;
15634                                 } else {
15635                                         // anchor within content
15636                                         self.active = current.closest( ".ui-accordion-content" ).prev();
15637                                 }
15638                         }
15639                 }
15640
15641                 self.active = self._findActive( self.active || options.active )
15642                         .addClass( "ui-state-default ui-state-active" )
15643                         .toggleClass( "ui-corner-all" )
15644                         .toggleClass( "ui-corner-top" );
15645                 self.active.next().addClass( "ui-accordion-content-active" );
15646
15647                 self._createIcons();
15648                 self.resize();
15649                 
15650                 // ARIA
15651                 self.element.attr( "role", "tablist" );
15652
15653                 self.headers
15654                         .attr( "role", "tab" )
15655                         .bind( "keydown.accordion", function( event ) {
15656                                 return self._keydown( event );
15657                         })
15658                         .next()
15659                                 .attr( "role", "tabpanel" );
15660
15661                 self.headers
15662                         .not( self.active || "" )
15663                         .attr({
15664                                 "aria-expanded": "false",
15665                                 "aria-selected": "false",
15666                                 tabIndex: -1
15667                         })
15668                         .next()
15669                                 .hide();
15670
15671                 // make sure at least one header is in the tab order
15672                 if ( !self.active.length ) {
15673                         self.headers.eq( 0 ).attr( "tabIndex", 0 );
15674                 } else {
15675                         self.active
15676                                 .attr({
15677                                         "aria-expanded": "true",
15678                                         "aria-selected": "true",
15679                                         tabIndex: 0
15680                                 });
15681                 }
15682
15683                 // only need links in tab order for Safari
15684                 if ( !$.browser.safari ) {
15685                         self.headers.find( "a" ).attr( "tabIndex", -1 );
15686                 }
15687
15688                 if ( options.event ) {
15689                         self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
15690                                 self._clickHandler.call( self, event, this );
15691                                 event.preventDefault();
15692                         });
15693                 }
15694         },
15695
15696         _createIcons: function() {
15697                 var options = this.options;
15698                 if ( options.icons ) {
15699                         $( "<span></span>" )
15700                                 .addClass( "ui-icon " + options.icons.header )
15701                                 .prependTo( this.headers );
15702                         this.active.children( ".ui-icon" )
15703                                 .toggleClass(options.icons.header)
15704                                 .toggleClass(options.icons.headerSelected);
15705                         this.element.addClass( "ui-accordion-icons" );
15706                 }
15707         },
15708
15709         _destroyIcons: function() {
15710                 this.headers.children( ".ui-icon" ).remove();
15711                 this.element.removeClass( "ui-accordion-icons" );
15712         },
15713
15714         destroy: function() {
15715                 var options = this.options;
15716
15717                 this.element
15718                         .removeClass( "ui-accordion ui-widget ui-helper-reset" )
15719                         .removeAttr( "role" );
15720
15721                 this.headers
15722                         .unbind( ".accordion" )
15723                         .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
15724                         .removeAttr( "role" )
15725                         .removeAttr( "aria-expanded" )
15726                         .removeAttr( "aria-selected" )
15727                         .removeAttr( "tabIndex" );
15728
15729                 this.headers.find( "a" ).removeAttr( "tabIndex" );
15730                 this._destroyIcons();
15731                 var contents = this.headers.next()
15732                         .css( "display", "" )
15733                         .removeAttr( "role" )
15734                         .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
15735                 if ( options.autoHeight || options.fillHeight ) {
15736                         contents.css( "height", "" );
15737                 }
15738
15739                 return $.Widget.prototype.destroy.call( this );
15740         },
15741
15742         _setOption: function( key, value ) {
15743                 $.Widget.prototype._setOption.apply( this, arguments );
15744                         
15745                 if ( key == "active" ) {
15746                         this.activate( value );
15747                 }
15748                 if ( key == "icons" ) {
15749                         this._destroyIcons();
15750                         if ( value ) {
15751                                 this._createIcons();
15752                         }
15753                 }
15754                 // #5332 - opacity doesn't cascade to positioned elements in IE
15755                 // so we need to add the disabled class to the headers and panels
15756                 if ( key == "disabled" ) {
15757                         this.headers.add(this.headers.next())
15758                                 [ value ? "addClass" : "removeClass" ](
15759                                         "ui-accordion-disabled ui-state-disabled" );
15760                 }
15761         },
15762
15763         _keydown: function( event ) {
15764                 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
15765                         return;
15766                 }
15767
15768                 var keyCode = $.ui.keyCode,
15769                         length = this.headers.length,
15770                         currentIndex = this.headers.index( event.target ),
15771                         toFocus = false;
15772
15773                 switch ( event.keyCode ) {
15774                         case keyCode.RIGHT:
15775                         case keyCode.DOWN:
15776                                 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
15777                                 break;
15778                         case keyCode.LEFT:
15779                         case keyCode.UP:
15780                                 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
15781                                 break;
15782                         case keyCode.SPACE:
15783                         case keyCode.ENTER:
15784                                 this._clickHandler( { target: event.target }, event.target );
15785                                 event.preventDefault();
15786                 }
15787
15788                 if ( toFocus ) {
15789                         $( event.target ).attr( "tabIndex", -1 );
15790                         $( toFocus ).attr( "tabIndex", 0 );
15791                         toFocus.focus();
15792                         return false;
15793                 }
15794
15795                 return true;
15796         },
15797
15798         resize: function() {
15799                 var options = this.options,
15800                         maxHeight;
15801
15802                 if ( options.fillSpace ) {
15803                         if ( $.browser.msie ) {
15804                                 var defOverflow = this.element.parent().css( "overflow" );
15805                                 this.element.parent().css( "overflow", "hidden");
15806                         }
15807                         maxHeight = this.element.parent().height();
15808                         if ($.browser.msie) {
15809                                 this.element.parent().css( "overflow", defOverflow );
15810                         }
15811
15812                         this.headers.each(function() {
15813                                 maxHeight -= $( this ).outerHeight( true );
15814                         });
15815
15816                         this.headers.next()
15817                                 .each(function() {
15818                                         $( this ).height( Math.max( 0, maxHeight -
15819                                                 $( this ).innerHeight() + $( this ).height() ) );
15820                                 })
15821                                 .css( "overflow", "auto" );
15822                 } else if ( options.autoHeight ) {
15823                         maxHeight = 0;
15824                         this.headers.next()
15825                                 .each(function() {
15826                                         maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15827                                 })
15828                                 .height( maxHeight );
15829                 }
15830
15831                 return this;
15832         },
15833
15834         activate: function( index ) {
15835                 // TODO this gets called on init, changing the option without an explicit call for that
15836                 this.options.active = index;
15837                 // call clickHandler with custom event
15838                 var active = this._findActive( index )[ 0 ];
15839                 this._clickHandler( { target: active }, active );
15840
15841                 return this;
15842         },
15843
15844         _findActive: function( selector ) {
15845                 return selector
15846                         ? typeof selector === "number"
15847                                 ? this.headers.filter( ":eq(" + selector + ")" )
15848                                 : this.headers.not( this.headers.not( selector ) )
15849                         : selector === false
15850                                 ? $( [] )
15851                                 : this.headers.filter( ":eq(0)" );
15852         },
15853
15854         // TODO isn't event.target enough? why the separate target argument?
15855         _clickHandler: function( event, target ) {
15856                 var options = this.options;
15857                 if ( options.disabled ) {
15858                         return;
15859                 }
15860
15861                 // called only when using activate(false) to close all parts programmatically
15862                 if ( !event.target ) {
15863                         if ( !options.collapsible ) {
15864                                 return;
15865                         }
15866                         this.active
15867                                 .removeClass( "ui-state-active ui-corner-top" )
15868                                 .addClass( "ui-state-default ui-corner-all" )
15869                                 .children( ".ui-icon" )
15870                                         .removeClass( options.icons.headerSelected )
15871                                         .addClass( options.icons.header );
15872                         this.active.next().addClass( "ui-accordion-content-active" );
15873                         var toHide = this.active.next(),
15874                                 data = {
15875                                         options: options,
15876                                         newHeader: $( [] ),
15877                                         oldHeader: options.active,
15878                                         newContent: $( [] ),
15879                                         oldContent: toHide
15880                                 },
15881                                 toShow = ( this.active = $( [] ) );
15882                         this._toggle( toShow, toHide, data );
15883                         return;
15884                 }
15885
15886                 // get the click target
15887                 var clicked = $( event.currentTarget || target ),
15888                         clickedIsActive = clicked[0] === this.active[0];
15889
15890                 // TODO the option is changed, is that correct?
15891                 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
15892                 options.active = options.collapsible && clickedIsActive ?
15893                         false :
15894                         this.headers.index( clicked );
15895
15896                 // if animations are still active, or the active header is the target, ignore click
15897                 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
15898                         return;
15899                 }
15900
15901                 // find elements to show and hide
15902                 var active = this.active,
15903                         toShow = clicked.next(),
15904                         toHide = this.active.next(),
15905                         data = {
15906                                 options: options,
15907                                 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
15908                                 oldHeader: this.active,
15909                                 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
15910                                 oldContent: toHide
15911                         },
15912                         down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
15913
15914                 // when the call to ._toggle() comes after the class changes
15915                 // it causes a very odd bug in IE 8 (see #6720)
15916                 this.active = clickedIsActive ? $([]) : clicked;
15917                 this._toggle( toShow, toHide, data, clickedIsActive, down );
15918
15919                 // switch classes
15920                 active
15921                         .removeClass( "ui-state-active ui-corner-top" )
15922                         .addClass( "ui-state-default ui-corner-all" )
15923                         .children( ".ui-icon" )
15924                                 .removeClass( options.icons.headerSelected )
15925                                 .addClass( options.icons.header );
15926                 if ( !clickedIsActive ) {
15927                         clicked
15928                                 .removeClass( "ui-state-default ui-corner-all" )
15929                                 .addClass( "ui-state-active ui-corner-top" )
15930                                 .children( ".ui-icon" )
15931                                         .removeClass( options.icons.header )
15932                                         .addClass( options.icons.headerSelected );
15933                         clicked
15934                                 .next()
15935                                 .addClass( "ui-accordion-content-active" );
15936                 }
15937
15938                 return;
15939         },
15940
15941         _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
15942                 var self = this,
15943                         options = self.options;
15944
15945                 self.toShow = toShow;
15946                 self.toHide = toHide;
15947                 self.data = data;
15948
15949                 var complete = function() {
15950                         if ( !self ) {
15951                                 return;
15952                         }
15953                         return self._completed.apply( self, arguments );
15954                 };
15955
15956                 // trigger changestart event
15957                 self._trigger( "changestart", null, self.data );
15958
15959                 // count elements to animate
15960                 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
15961
15962                 if ( options.animated ) {
15963                         var animOptions = {};
15964
15965                         if ( options.collapsible && clickedIsActive ) {
15966                                 animOptions = {
15967                                         toShow: $( [] ),
15968                                         toHide: toHide,
15969                                         complete: complete,
15970                                         down: down,
15971                                         autoHeight: options.autoHeight || options.fillSpace
15972                                 };
15973                         } else {
15974                                 animOptions = {
15975                                         toShow: toShow,
15976                                         toHide: toHide,
15977                                         complete: complete,
15978                                         down: down,
15979                                         autoHeight: options.autoHeight || options.fillSpace
15980                                 };
15981                         }
15982
15983                         if ( !options.proxied ) {
15984                                 options.proxied = options.animated;
15985                         }
15986
15987                         if ( !options.proxiedDuration ) {
15988                                 options.proxiedDuration = options.duration;
15989                         }
15990
15991                         options.animated = $.isFunction( options.proxied ) ?
15992                                 options.proxied( animOptions ) :
15993                                 options.proxied;
15994
15995                         options.duration = $.isFunction( options.proxiedDuration ) ?
15996                                 options.proxiedDuration( animOptions ) :
15997                                 options.proxiedDuration;
15998
15999                         var animations = $.ui.accordion.animations,
16000                                 duration = options.duration,
16001                                 easing = options.animated;
16002
16003                         if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
16004                                 easing = "slide";
16005                         }
16006                         if ( !animations[ easing ] ) {
16007                                 animations[ easing ] = function( options ) {
16008                                         this.slide( options, {
16009                                                 easing: easing,
16010                                                 duration: duration || 700
16011                                         });
16012                                 };
16013                         }
16014
16015                         animations[ easing ]( animOptions );
16016                 } else {
16017                         if ( options.collapsible && clickedIsActive ) {
16018                                 toShow.toggle();
16019                         } else {
16020                                 toHide.hide();
16021                                 toShow.show();
16022                         }
16023
16024                         complete( true );
16025                 }
16026
16027                 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
16028                 toHide.prev()
16029                         .attr({
16030                                 "aria-expanded": "false",
16031                                 "aria-selected": "false",
16032                                 tabIndex: -1
16033                         })
16034                         .blur();
16035                 toShow.prev()
16036                         .attr({
16037                                 "aria-expanded": "true",
16038                                 "aria-selected": "true",
16039                                 tabIndex: 0
16040                         })
16041                         .focus();
16042         },
16043
16044         _completed: function( cancel ) {
16045                 this.running = cancel ? 0 : --this.running;
16046                 if ( this.running ) {
16047                         return;
16048                 }
16049
16050                 if ( this.options.clearStyle ) {
16051                         this.toShow.add( this.toHide ).css({
16052                                 height: "",
16053                                 overflow: ""
16054                         });
16055                 }
16056
16057                 // other classes are removed before the animation; this one needs to stay until completed
16058                 this.toHide.removeClass( "ui-accordion-content-active" );
16059                 // Work around for rendering bug in IE (#5421)
16060                 if ( this.toHide.length ) {
16061                         this.toHide.parent()[0].className = this.toHide.parent()[0].className;
16062                 }
16063
16064                 this._trigger( "change", null, this.data );
16065         }
16066 });
16067
16068 $.extend( $.ui.accordion, {
16069         version: "1.8.16",
16070         animations: {
16071                 slide: function( options, additions ) {
16072                         options = $.extend({
16073                                 easing: "swing",
16074                                 duration: 300
16075                         }, options, additions );
16076                         if ( !options.toHide.size() ) {
16077                                 options.toShow.animate({
16078                                         height: "show",
16079                                         paddingTop: "show",
16080                                         paddingBottom: "show"
16081                                 }, options );
16082                                 return;
16083                         }
16084                         if ( !options.toShow.size() ) {
16085                                 options.toHide.animate({
16086                                         height: "hide",
16087                                         paddingTop: "hide",
16088                                         paddingBottom: "hide"
16089                                 }, options );
16090                                 return;
16091                         }
16092                         var overflow = options.toShow.css( "overflow" ),
16093                                 percentDone = 0,
16094                                 showProps = {},
16095                                 hideProps = {},
16096                                 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
16097                                 originalWidth;
16098                         // fix width before calculating height of hidden element
16099                         var s = options.toShow;
16100                         originalWidth = s[0].style.width;
16101                         s.width( parseInt( s.parent().width(), 10 )
16102                                 - parseInt( s.css( "paddingLeft" ), 10 )
16103                                 - parseInt( s.css( "paddingRight" ), 10 )
16104                                 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
16105                                 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
16106
16107                         $.each( fxAttrs, function( i, prop ) {
16108                                 hideProps[ prop ] = "hide";
16109
16110                                 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
16111                                 showProps[ prop ] = {
16112                                         value: parts[ 1 ],
16113                                         unit: parts[ 2 ] || "px"
16114                                 };
16115                         });
16116                         options.toShow.css({ height: 0, overflow: "hidden" }).show();
16117                         options.toHide
16118                                 .filter( ":hidden" )
16119                                         .each( options.complete )
16120                                 .end()
16121                                 .filter( ":visible" )
16122                                 .animate( hideProps, {
16123                                 step: function( now, settings ) {
16124                                         // only calculate the percent when animating height
16125                                         // IE gets very inconsistent results when animating elements
16126                                         // with small values, which is common for padding
16127                                         if ( settings.prop == "height" ) {
16128                                                 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
16129                                                         ( settings.now - settings.start ) / ( settings.end - settings.start );
16130                                         }
16131
16132                                         options.toShow[ 0 ].style[ settings.prop ] =
16133                                                 ( percentDone * showProps[ settings.prop ].value )
16134                                                 + showProps[ settings.prop ].unit;
16135                                 },
16136                                 duration: options.duration,
16137                                 easing: options.easing,
16138                                 complete: function() {
16139                                         if ( !options.autoHeight ) {
16140                                                 options.toShow.css( "height", "" );
16141                                         }
16142                                         options.toShow.css({
16143                                                 width: originalWidth,
16144                                                 overflow: overflow
16145                                         });
16146                                         options.complete();
16147                                 }
16148                         });
16149                 },
16150                 bounceslide: function( options ) {
16151                         this.slide( options, {
16152                                 easing: options.down ? "easeOutBounce" : "swing",
16153                                 duration: options.down ? 1000 : 200
16154                         });
16155                 }
16156         }
16157 });
16158
16159 })( jQuery );
16160 /*
16161  * jQuery UI Autocomplete 1.8.16
16162  *
16163  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
16164  * Dual licensed under the MIT or GPL Version 2 licenses.
16165  * http://jquery.org/license
16166  *
16167  * http://docs.jquery.com/UI/Autocomplete
16168  *
16169  * Depends:
16170  *      jquery.ui.core.js
16171  *      jquery.ui.widget.js
16172  *      jquery.ui.position.js
16173  */
16174 (function( $, undefined ) {
16175
16176 // used to prevent race conditions with remote data sources
16177 var requestIndex = 0;
16178
16179 $.widget( "ui.autocomplete", {
16180         options: {
16181                 appendTo: "body",
16182                 autoFocus: false,
16183                 delay: 300,
16184                 minLength: 1,
16185                 position: {
16186                         my: "left top",
16187                         at: "left bottom",
16188                         collision: "none"
16189                 },
16190                 source: null
16191         },
16192
16193         pending: 0,
16194
16195         _create: function() {
16196                 var self = this,
16197                         doc = this.element[ 0 ].ownerDocument,
16198                         suppressKeyPress;
16199
16200                 this.element
16201                         .addClass( "ui-autocomplete-input" )
16202                         .attr( "autocomplete", "off" )
16203                         // TODO verify these actually work as intended
16204                         .attr({
16205                                 role: "textbox",
16206                                 "aria-autocomplete": "list",
16207                                 "aria-haspopup": "true"
16208                         })
16209                         .bind( "keydown.autocomplete", function( event ) {
16210                                 if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
16211                                         return;
16212                                 }
16213
16214                                 suppressKeyPress = false;
16215                                 var keyCode = $.ui.keyCode;
16216                                 switch( event.keyCode ) {
16217                                 case keyCode.PAGE_UP:
16218                                         self._move( "previousPage", event );
16219                                         break;
16220                                 case keyCode.PAGE_DOWN:
16221                                         self._move( "nextPage", event );
16222                                         break;
16223                                 case keyCode.UP:
16224                                         self._move( "previous", event );
16225                                         // prevent moving cursor to beginning of text field in some browsers
16226                                         event.preventDefault();
16227                                         break;
16228                                 case keyCode.DOWN:
16229                                         self._move( "next", event );
16230                                         // prevent moving cursor to end of text field in some browsers
16231                                         event.preventDefault();
16232                                         break;
16233                                 case keyCode.ENTER:
16234                                 case keyCode.NUMPAD_ENTER:
16235                                         // when menu is open and has focus
16236                                         if ( self.menu.active ) {
16237                                                 // #6055 - Opera still allows the keypress to occur
16238                                                 // which causes forms to submit
16239                                                 suppressKeyPress = true;
16240                                                 event.preventDefault();
16241                                         }
16242                                         //passthrough - ENTER and TAB both select the current element
16243                                 case keyCode.TAB:
16244                                         if ( !self.menu.active ) {
16245                                                 return;
16246                                         }
16247                                         self.menu.select( event );
16248                                         break;
16249                                 case keyCode.ESCAPE:
16250                                         self.element.val( self.term );
16251                                         self.close( event );
16252                                         break;
16253                                 default:
16254                                         // keypress is triggered before the input value is changed
16255                                         clearTimeout( self.searching );
16256                                         self.searching = setTimeout(function() {
16257                                                 // only search if the value has changed
16258                                                 if ( self.term != self.element.val() ) {
16259                                                         self.selectedItem = null;
16260                                                         self.search( null, event );
16261                                                 }
16262                                         }, self.options.delay );
16263                                         break;
16264                                 }
16265                         })
16266                         .bind( "keypress.autocomplete", function( event ) {
16267                                 if ( suppressKeyPress ) {
16268                                         suppressKeyPress = false;
16269                                         event.preventDefault();
16270                                 }
16271                         })
16272                         .bind( "focus.autocomplete", function() {
16273                                 if ( self.options.disabled ) {
16274                                         return;
16275                                 }
16276
16277                                 self.selectedItem = null;
16278                                 self.previous = self.element.val();
16279                         })
16280                         .bind( "blur.autocomplete", function( event ) {
16281                                 if ( self.options.disabled ) {
16282                                         return;
16283                                 }
16284
16285                                 clearTimeout( self.searching );
16286                                 // clicks on the menu (or a button to trigger a search) will cause a blur event
16287                                 self.closing = setTimeout(function() {
16288                                         self.close( event );
16289                                         self._change( event );
16290                                 }, 150 );
16291                         });
16292                 this._initSource();
16293                 this.response = function() {
16294                         return self._response.apply( self, arguments );
16295                 };
16296                 this.menu = $( "<ul></ul>" )
16297                         .addClass( "ui-autocomplete" )
16298                         .appendTo( $( this.options.appendTo || "body", doc )[0] )
16299                         // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
16300                         .mousedown(function( event ) {
16301                                 // clicking on the scrollbar causes focus to shift to the body
16302                                 // but we can't detect a mouseup or a click immediately afterward
16303                                 // so we have to track the next mousedown and close the menu if
16304                                 // the user clicks somewhere outside of the autocomplete
16305                                 var menuElement = self.menu.element[ 0 ];
16306                                 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
16307                                         setTimeout(function() {
16308                                                 $( document ).one( 'mousedown', function( event ) {
16309                                                         if ( event.target !== self.element[ 0 ] &&
16310                                                                 event.target !== menuElement &&
16311                                                                 !$.ui.contains( menuElement, event.target ) ) {
16312                                                                 self.close();
16313                                                         }
16314                                                 });
16315                                         }, 1 );
16316                                 }
16317
16318                                 // use another timeout to make sure the blur-event-handler on the input was already triggered
16319                                 setTimeout(function() {
16320                                         clearTimeout( self.closing );
16321                                 }, 13);
16322                         })
16323                         .menu({
16324                                 focus: function( event, ui ) {
16325                                         var item = ui.item.data( "item.autocomplete" );
16326                                         if ( false !== self._trigger( "focus", event, { item: item } ) ) {
16327                                                 // use value to match what will end up in the input, if it was a key event
16328                                                 if ( /^key/.test(event.originalEvent.type) ) {
16329                                                         self.element.val( item.value );
16330                                                 }
16331                                         }
16332                                 },
16333                                 selected: function( event, ui ) {
16334                                         var item = ui.item.data( "item.autocomplete" ),
16335                                                 previous = self.previous;
16336
16337                                         // only trigger when focus was lost (click on menu)
16338                                         if ( self.element[0] !== doc.activeElement ) {
16339                                                 self.element.focus();
16340                                                 self.previous = previous;
16341                                                 // #6109 - IE triggers two focus events and the second
16342                                                 // is asynchronous, so we need to reset the previous
16343                                                 // term synchronously and asynchronously :-(
16344                                                 setTimeout(function() {
16345                                                         self.previous = previous;
16346                                                         self.selectedItem = item;
16347                                                 }, 1);
16348                                         }
16349
16350                                         if ( false !== self._trigger( "select", event, { item: item } ) ) {
16351                                                 self.element.val( item.value );
16352                                         }
16353                                         // reset the term after the select event
16354                                         // this allows custom select handling to work properly
16355                                         self.term = self.element.val();
16356
16357                                         self.close( event );
16358                                         self.selectedItem = item;
16359                                 },
16360                                 blur: function( event, ui ) {
16361                                         // don't set the value of the text field if it's already correct
16362                                         // this prevents moving the cursor unnecessarily
16363                                         if ( self.menu.element.is(":visible") &&
16364                                                 ( self.element.val() !== self.term ) ) {
16365                                                 self.element.val( self.term );
16366                                         }
16367                                 }
16368                         })
16369                         .zIndex( this.element.zIndex() + 1 )
16370                         // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
16371                         .css({ top: 0, left: 0 })
16372                         .hide()
16373                         .data( "menu" );
16374                 if ( $.fn.bgiframe ) {
16375                          this.menu.element.bgiframe();
16376                 }
16377         },
16378
16379         destroy: function() {
16380                 this.element
16381                         .removeClass( "ui-autocomplete-input" )
16382                         .removeAttr( "autocomplete" )
16383                         .removeAttr( "role" )
16384                         .removeAttr( "aria-autocomplete" )
16385                         .removeAttr( "aria-haspopup" );
16386                 this.menu.element.remove();
16387                 $.Widget.prototype.destroy.call( this );
16388         },
16389
16390         _setOption: function( key, value ) {
16391                 $.Widget.prototype._setOption.apply( this, arguments );
16392                 if ( key === "source" ) {
16393                         this._initSource();
16394                 }
16395                 if ( key === "appendTo" ) {
16396                         this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
16397                 }
16398                 if ( key === "disabled" && value && this.xhr ) {
16399                         this.xhr.abort();
16400                 }
16401         },
16402
16403         _initSource: function() {
16404                 var self = this,
16405                         array,
16406                         url;
16407                 if ( $.isArray(this.options.source) ) {
16408                         array = this.options.source;
16409                         this.source = function( request, response ) {
16410                                 response( $.ui.autocomplete.filter(array, request.term) );
16411                         };
16412                 } else if ( typeof this.options.source === "string" ) {
16413                         url = this.options.source;
16414                         this.source = function( request, response ) {
16415                                 if ( self.xhr ) {
16416                                         self.xhr.abort();
16417                                 }
16418                                 self.xhr = $.ajax({
16419                                         url: url,
16420                                         data: request,
16421                                         dataType: "json",
16422                                         autocompleteRequest: ++requestIndex,
16423                                         success: function( data, status ) {
16424                                                 if ( this.autocompleteRequest === requestIndex ) {
16425                                                         response( data );
16426                                                 }
16427                                         },
16428                                         error: function() {
16429                                                 if ( this.autocompleteRequest === requestIndex ) {
16430                                                         response( [] );
16431                                                 }
16432                                         }
16433                                 });
16434                         };
16435                 } else {
16436                         this.source = this.options.source;
16437                 }
16438         },
16439
16440         search: function( value, event ) {
16441                 value = value != null ? value : this.element.val();
16442
16443                 // always save the actual value, not the one passed as an argument
16444                 this.term = this.element.val();
16445
16446                 if ( value.length < this.options.minLength ) {
16447                         return this.close( event );
16448                 }
16449
16450                 clearTimeout( this.closing );
16451                 if ( this._trigger( "search", event ) === false ) {
16452                         return;
16453                 }
16454
16455                 return this._search( value );
16456         },
16457
16458         _search: function( value ) {
16459                 this.pending++;
16460                 this.element.addClass( "ui-autocomplete-loading" );
16461
16462                 this.source( { term: value }, this.response );
16463         },
16464
16465         _response: function( content ) {
16466                 if ( !this.options.disabled && content && content.length ) {
16467                         content = this._normalize( content );
16468                         this._suggest( content );
16469                         this._trigger( "open" );
16470                 } else {
16471                         this.close();
16472                 }
16473                 this.pending--;
16474                 if ( !this.pending ) {
16475                         this.element.removeClass( "ui-autocomplete-loading" );
16476                 }
16477         },
16478
16479         close: function( event ) {
16480                 clearTimeout( this.closing );
16481                 if ( this.menu.element.is(":visible") ) {
16482                         this.menu.element.hide();
16483                         this.menu.deactivate();
16484                         this._trigger( "close", event );
16485                 }
16486         },
16487         
16488         _change: function( event ) {
16489                 if ( this.previous !== this.element.val() ) {
16490                         this._trigger( "change", event, { item: this.selectedItem } );
16491                 }
16492         },
16493
16494         _normalize: function( items ) {
16495                 // assume all items have the right format when the first item is complete
16496                 if ( items.length && items[0].label && items[0].value ) {
16497                         return items;
16498                 }
16499                 return $.map( items, function(item) {
16500                         if ( typeof item === "string" ) {
16501                                 return {
16502                                         label: item,
16503                                         value: item
16504                                 };
16505                         }
16506                         return $.extend({
16507                                 label: item.label || item.value,
16508                                 value: item.value || item.label
16509                         }, item );
16510                 });
16511         },
16512
16513         _suggest: function( items ) {
16514                 var ul = this.menu.element
16515                         .empty()
16516                         .zIndex( this.element.zIndex() + 1 );
16517                 this._renderMenu( ul, items );
16518                 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
16519                 this.menu.deactivate();
16520                 this.menu.refresh();
16521
16522                 // size and position menu
16523                 ul.show();
16524                 this._resizeMenu();
16525                 ul.position( $.extend({
16526                         of: this.element
16527                 }, this.options.position ));
16528
16529                 if ( this.options.autoFocus ) {
16530                         this.menu.next( new $.Event("mouseover") );
16531                 }
16532         },
16533
16534         _resizeMenu: function() {
16535                 var ul = this.menu.element;
16536                 ul.outerWidth( Math.max(
16537                         ul.width( "" ).outerWidth(),
16538                         this.element.outerWidth()
16539                 ) );
16540         },
16541
16542         _renderMenu: function( ul, items ) {
16543                 var self = this;
16544                 $.each( items, function( index, item ) {
16545                         self._renderItem( ul, item );
16546                 });
16547         },
16548
16549         _renderItem: function( ul, item) {
16550                 return $( "<li></li>" )
16551                         .data( "item.autocomplete", item )
16552                         .append( $( "<a></a>" ).text( item.label ) )
16553                         .appendTo( ul );
16554         },
16555
16556         _move: function( direction, event ) {
16557                 if ( !this.menu.element.is(":visible") ) {
16558                         this.search( null, event );
16559                         return;
16560                 }
16561                 if ( this.menu.first() && /^previous/.test(direction) ||
16562                                 this.menu.last() && /^next/.test(direction) ) {
16563                         this.element.val( this.term );
16564                         this.menu.deactivate();
16565                         return;
16566                 }
16567                 this.menu[ direction ]( event );
16568         },
16569
16570         widget: function() {
16571                 return this.menu.element;
16572         }
16573 });
16574
16575 $.extend( $.ui.autocomplete, {
16576         escapeRegex: function( value ) {
16577                 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
16578         },
16579         filter: function(array, term) {
16580                 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
16581                 return $.grep( array, function(value) {
16582                         return matcher.test( value.label || value.value || value );
16583                 });
16584         }
16585 });
16586
16587 }( jQuery ));
16588
16589 /*
16590  * jQuery UI Menu (not officially released)
16591  * 
16592  * This widget isn't yet finished and the API is subject to change. We plan to finish
16593  * it for the next release. You're welcome to give it a try anyway and give us feedback,
16594  * as long as you're okay with migrating your code later on. We can help with that, too.
16595  *
16596  * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
16597  * Dual licensed under the MIT or GPL Version 2 licenses.
16598  * http://jquery.org/license
16599  *
16600  * http://docs.jquery.com/UI/Menu
16601  *
16602  * Depends:
16603  *      jquery.ui.core.js
16604  *  jquery.ui.widget.js
16605  */
16606 (function($) {
16607
16608 $.widget("ui.menu", {
16609         _create: function() {
16610                 var self = this;
16611                 this.element
16612                         .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
16613                         .attr({
16614                                 role: "listbox",
16615                                 "aria-activedescendant": "ui-active-menuitem"
16616                         })
16617                         .click(function( event ) {
16618                                 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
16619                                         return;
16620                                 }
16621                                 // temporary
16622                                 event.preventDefault();
16623                                 self.select( event );
16624                         });
16625                 this.refresh();
16626         },
16627         
16628         refresh: function() {
16629                 var self = this;
16630
16631                 // don't refresh list items that are already adapted
16632                 var items = this.element.children("li:not(.ui-menu-item):has(a)")
16633                         .addClass("ui-menu-item")
16634                         .attr("role", "menuitem");
16635                 
16636                 items.children("a")
16637                         .addClass("ui-corner-all")
16638                         .attr("tabindex", -1)
16639                         // mouseenter doesn't work with event delegation
16640                         .mouseenter(function( event ) {
16641                                 self.activate( event, $(this).parent() );
16642                         })
16643                         .mouseleave(function() {
16644                                 self.deactivate();
16645                         });
16646         },
16647
16648         activate: function( event, item ) {
16649                 this.deactivate();
16650                 if (this.hasScroll()) {
16651                         var offset = item.offset().top - this.element.offset().top,
16652                                 scroll = this.element.scrollTop(),
16653                                 elementHeight = this.element.height();
16654                         if (offset < 0) {
16655                                 this.element.scrollTop( scroll + offset);
16656                         } else if (offset >= elementHeight) {
16657                                 this.element.scrollTop( scroll + offset - elementHeight + item.height());
16658                         }
16659                 }
16660                 this.active = item.eq(0)
16661                         .children("a")
16662                                 .addClass("ui-state-hover")
16663                                 .attr("id", "ui-active-menuitem")
16664                         .end();
16665                 this._trigger("focus", event, { item: item });
16666         },
16667
16668         deactivate: function() {
16669                 if (!this.active) { return; }
16670
16671                 this.active.children("a")
16672                         .removeClass("ui-state-hover")
16673                         .removeAttr("id");
16674                 this._trigger("blur");
16675                 this.active = null;
16676         },
16677
16678         next: function(event) {
16679                 this.move("next", ".ui-menu-item:first", event);
16680         },
16681
16682         previous: function(event) {
16683                 this.move("prev", ".ui-menu-item:last", event);
16684         },
16685
16686         first: function() {
16687                 return this.active && !this.active.prevAll(".ui-menu-item").length;
16688         },
16689
16690         last: function() {
16691                 return this.active && !this.active.nextAll(".ui-menu-item").length;
16692         },
16693
16694         move: function(direction, edge, event) {
16695                 if (!this.active) {
16696                         this.activate(event, this.element.children(edge));
16697                         return;
16698                 }
16699                 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
16700                 if (next.length) {
16701                         this.activate(event, next);
16702                 } else {
16703                         this.activate(event, this.element.children(edge));
16704                 }
16705         },
16706
16707         // TODO merge with previousPage
16708         nextPage: function(event) {
16709                 if (this.hasScroll()) {
16710                         // TODO merge with no-scroll-else
16711                         if (!this.active || this.last()) {
16712                                 this.activate(event, this.element.children(".ui-menu-item:first"));
16713                                 return;
16714                         }
16715                         var base = this.active.offset().top,
16716                                 height = this.element.height(),
16717                                 result = this.element.children(".ui-menu-item").filter(function() {
16718                                         var close = $(this).offset().top - base - height + $(this).height();
16719                                         // TODO improve approximation
16720                                         return close < 10 && close > -10;
16721                                 });
16722
16723                         // TODO try to catch this earlier when scrollTop indicates the last page anyway
16724                         if (!result.length) {
16725                                 result = this.element.children(".ui-menu-item:last");
16726                         }
16727                         this.activate(event, result);
16728                 } else {
16729                         this.activate(event, this.element.children(".ui-menu-item")
16730                                 .filter(!this.active || this.last() ? ":first" : ":last"));
16731                 }
16732         },
16733
16734         // TODO merge with nextPage
16735         previousPage: function(event) {
16736                 if (this.hasScroll()) {
16737                         // TODO merge with no-scroll-else
16738                         if (!this.active || this.first()) {
16739                                 this.activate(event, this.element.children(".ui-menu-item:last"));
16740                                 return;
16741                         }
16742
16743                         var base = this.active.offset().top,
16744                                 height = this.element.height();
16745                                 result = this.element.children(".ui-menu-item").filter(function() {
16746                                         var close = $(this).offset().top - base + height - $(this).height();
16747                                         // TODO improve approximation
16748                                         return close < 10 && close > -10;
16749                                 });
16750
16751                         // TODO try to catch this earlier when scrollTop indicates the last page anyway
16752                         if (!result.length) {
16753                                 result = this.element.children(".ui-menu-item:first");
16754                         }
16755                         this.activate(event, result);
16756                 } else {
16757                         this.activate(event, this.element.children(".ui-menu-item")
16758                                 .filter(!this.active || this.first() ? ":last" : ":first"));
16759                 }
16760         },
16761
16762         hasScroll: function() {
16763                 return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
16764         },
16765
16766         select: function( event ) {
16767                 this._trigger("selected", event, { item: this.active });
16768         }
16769 });
16770
16771 }(jQuery));
16772 /*
16773  * jQuery UI Button 1.8.16
16774  *
16775  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
16776  * Dual licensed under the MIT or GPL Version 2 licenses.
16777  * http://jquery.org/license
16778  *
16779  * http://docs.jquery.com/UI/Button
16780  *
16781  * Depends:
16782  *      jquery.ui.core.js
16783  *      jquery.ui.widget.js
16784  */
16785 (function( $, undefined ) {
16786
16787 var lastActive, startXPos, startYPos, clickDragged,
16788         baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
16789         stateClasses = "ui-state-hover ui-state-active ",
16790         typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
16791         formResetHandler = function() {
16792                 var buttons = $( this ).find( ":ui-button" );
16793                 setTimeout(function() {
16794                         buttons.button( "refresh" );
16795                 }, 1 );
16796         },
16797         radioGroup = function( radio ) {
16798                 var name = radio.name,
16799                         form = radio.form,
16800                         radios = $( [] );
16801                 if ( name ) {
16802                         if ( form ) {
16803                                 radios = $( form ).find( "[name='" + name + "']" );
16804                         } else {
16805                                 radios = $( "[name='" + name + "']", radio.ownerDocument )
16806                                         .filter(function() {
16807                                                 return !this.form;
16808                                         });
16809                         }
16810                 }
16811                 return radios;
16812         };
16813
16814 $.widget( "ui.button", {
16815         options: {
16816                 disabled: null,
16817                 text: true,
16818                 label: null,
16819                 icons: {
16820                         primary: null,
16821                         secondary: null
16822                 }
16823         },
16824         _create: function() {
16825                 this.element.closest( "form" )
16826                         .unbind( "reset.button" )
16827                         .bind( "reset.button", formResetHandler );
16828
16829                 if ( typeof this.options.disabled !== "boolean" ) {
16830                         this.options.disabled = this.element.propAttr( "disabled" );
16831                 }
16832
16833                 this._determineButtonType();
16834                 this.hasTitle = !!this.buttonElement.attr( "title" );
16835
16836                 var self = this,
16837                         options = this.options,
16838                         toggleButton = this.type === "checkbox" || this.type === "radio",
16839                         hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
16840                         focusClass = "ui-state-focus";
16841
16842                 if ( options.label === null ) {
16843                         options.label = this.buttonElement.html();
16844                 }
16845
16846                 if ( this.element.is( ":disabled" ) ) {
16847                         options.disabled = true;
16848                 }
16849
16850                 this.buttonElement
16851                         .addClass( baseClasses )
16852                         .attr( "role", "button" )
16853                         .bind( "mouseenter.button", function() {
16854                                 if ( options.disabled ) {
16855                                         return;
16856                                 }
16857                                 $( this ).addClass( "ui-state-hover" );
16858                                 if ( this === lastActive ) {
16859                                         $( this ).addClass( "ui-state-active" );
16860                                 }
16861                         })
16862                         .bind( "mouseleave.button", function() {
16863                                 if ( options.disabled ) {
16864                                         return;
16865                                 }
16866                                 $( this ).removeClass( hoverClass );
16867                         })
16868                         .bind( "click.button", function( event ) {
16869                                 if ( options.disabled ) {
16870                                         event.preventDefault();
16871                                         event.stopImmediatePropagation();
16872                                 }
16873                         });
16874
16875                 this.element
16876                         .bind( "focus.button", function() {
16877                                 // no need to check disabled, focus won't be triggered anyway
16878                                 self.buttonElement.addClass( focusClass );
16879                         })
16880                         .bind( "blur.button", function() {
16881                                 self.buttonElement.removeClass( focusClass );
16882                         });
16883
16884                 if ( toggleButton ) {
16885                         this.element.bind( "change.button", function() {
16886                                 if ( clickDragged ) {
16887                                         return;
16888                                 }
16889                                 self.refresh();
16890                         });
16891                         // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
16892                         // prevents issue where button state changes but checkbox/radio checked state
16893                         // does not in Firefox (see ticket #6970)
16894                         this.buttonElement
16895                                 .bind( "mousedown.button", function( event ) {
16896                                         if ( options.disabled ) {
16897                                                 return;
16898                                         }
16899                                         clickDragged = false;
16900                                         startXPos = event.pageX;
16901                                         startYPos = event.pageY;
16902                                 })
16903                                 .bind( "mouseup.button", function( event ) {
16904                                         if ( options.disabled ) {
16905                                                 return;
16906                                         }
16907                                         if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
16908                                                 clickDragged = true;
16909                                         }
16910                         });
16911                 }
16912
16913                 if ( this.type === "checkbox" ) {
16914                         this.buttonElement.bind( "click.button", function() {
16915                                 if ( options.disabled || clickDragged ) {
16916                                         return false;
16917                                 }
16918                                 $( this ).toggleClass( "ui-state-active" );
16919                                 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
16920                         });
16921                 } else if ( this.type === "radio" ) {
16922                         this.buttonElement.bind( "click.button", function() {
16923                                 if ( options.disabled || clickDragged ) {
16924                                         return false;
16925                                 }
16926                                 $( this ).addClass( "ui-state-active" );
16927                                 self.buttonElement.attr( "aria-pressed", "true" );
16928
16929                                 var radio = self.element[ 0 ];
16930                                 radioGroup( radio )
16931                                         .not( radio )
16932                                         .map(function() {
16933                                                 return $( this ).button( "widget" )[ 0 ];
16934                                         })
16935                                         .removeClass( "ui-state-active" )
16936                                         .attr( "aria-pressed", "false" );
16937                         });
16938                 } else {
16939                         this.buttonElement
16940                                 .bind( "mousedown.button", function() {
16941                                         if ( options.disabled ) {
16942                                                 return false;
16943                                         }
16944                                         $( this ).addClass( "ui-state-active" );
16945                                         lastActive = this;
16946                                         $( document ).one( "mouseup", function() {
16947                                                 lastActive = null;
16948                                         });
16949                                 })
16950                                 .bind( "mouseup.button", function() {
16951                                         if ( options.disabled ) {
16952                                                 return false;
16953                                         }
16954                                         $( this ).removeClass( "ui-state-active" );
16955                                 })
16956                                 .bind( "keydown.button", function(event) {
16957                                         if ( options.disabled ) {
16958                                                 return false;
16959                                         }
16960                                         if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
16961                                                 $( this ).addClass( "ui-state-active" );
16962                                         }
16963                                 })
16964                                 .bind( "keyup.button", function() {
16965                                         $( this ).removeClass( "ui-state-active" );
16966                                 });
16967
16968                         if ( this.buttonElement.is("a") ) {
16969                                 this.buttonElement.keyup(function(event) {
16970                                         if ( event.keyCode === $.ui.keyCode.SPACE ) {
16971                                                 // TODO pass through original event correctly (just as 2nd argument doesn't work)
16972                                                 $( this ).click();
16973                                         }
16974                                 });
16975                         }
16976                 }
16977
16978                 // TODO: pull out $.Widget's handling for the disabled option into
16979                 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
16980                 // be overridden by individual plugins
16981                 this._setOption( "disabled", options.disabled );
16982                 this._resetButton();
16983         },
16984
16985         _determineButtonType: function() {
16986
16987                 if ( this.element.is(":checkbox") ) {
16988                         this.type = "checkbox";
16989                 } else if ( this.element.is(":radio") ) {
16990                         this.type = "radio";
16991                 } else if ( this.element.is("input") ) {
16992                         this.type = "input";
16993                 } else {
16994                         this.type = "button";
16995                 }
16996
16997                 if ( this.type === "checkbox" || this.type === "radio" ) {
16998                         // we don't search against the document in case the element
16999                         // is disconnected from the DOM
17000                         var ancestor = this.element.parents().filter(":last"),
17001                                 labelSelector = "label[for='" + this.element.attr("id") + "']";
17002                         this.buttonElement = ancestor.find( labelSelector );
17003                         if ( !this.buttonElement.length ) {
17004                                 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
17005                                 this.buttonElement = ancestor.filter( labelSelector );
17006                                 if ( !this.buttonElement.length ) {
17007                                         this.buttonElement = ancestor.find( labelSelector );
17008                                 }
17009                         }
17010                         this.element.addClass( "ui-helper-hidden-accessible" );
17011
17012                         var checked = this.element.is( ":checked" );
17013                         if ( checked ) {
17014                                 this.buttonElement.addClass( "ui-state-active" );
17015                         }
17016                         this.buttonElement.attr( "aria-pressed", checked );
17017                 } else {
17018                         this.buttonElement = this.element;
17019                 }
17020         },
17021
17022         widget: function() {
17023                 return this.buttonElement;
17024         },
17025
17026         destroy: function() {
17027                 this.element
17028                         .removeClass( "ui-helper-hidden-accessible" );
17029                 this.buttonElement
17030                         .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
17031                         .removeAttr( "role" )
17032                         .removeAttr( "aria-pressed" )
17033                         .html( this.buttonElement.find(".ui-button-text").html() );
17034
17035                 if ( !this.hasTitle ) {
17036                         this.buttonElement.removeAttr( "title" );
17037                 }
17038
17039                 $.Widget.prototype.destroy.call( this );
17040         },
17041
17042         _setOption: function( key, value ) {
17043                 $.Widget.prototype._setOption.apply( this, arguments );
17044                 if ( key === "disabled" ) {
17045                         if ( value ) {
17046                                 this.element.propAttr( "disabled", true );
17047                         } else {
17048                                 this.element.propAttr( "disabled", false );
17049                         }
17050                         return;
17051                 }
17052                 this._resetButton();
17053         },
17054
17055         refresh: function() {
17056                 var isDisabled = this.element.is( ":disabled" );
17057                 if ( isDisabled !== this.options.disabled ) {
17058                         this._setOption( "disabled", isDisabled );
17059                 }
17060                 if ( this.type === "radio" ) {
17061                         radioGroup( this.element[0] ).each(function() {
17062                                 if ( $( this ).is( ":checked" ) ) {
17063                                         $( this ).button( "widget" )
17064                                                 .addClass( "ui-state-active" )
17065                                                 .attr( "aria-pressed", "true" );
17066                                 } else {
17067                                         $( this ).button( "widget" )
17068                                                 .removeClass( "ui-state-active" )
17069                                                 .attr( "aria-pressed", "false" );
17070                                 }
17071                         });
17072                 } else if ( this.type === "checkbox" ) {
17073                         if ( this.element.is( ":checked" ) ) {
17074                                 this.buttonElement
17075                                         .addClass( "ui-state-active" )
17076                                         .attr( "aria-pressed", "true" );
17077                         } else {
17078                                 this.buttonElement
17079                                         .removeClass( "ui-state-active" )
17080                                         .attr( "aria-pressed", "false" );
17081                         }
17082                 }
17083         },
17084
17085         _resetButton: function() {
17086                 if ( this.type === "input" ) {
17087                         if ( this.options.label ) {
17088                                 this.element.val( this.options.label );
17089                         }
17090                         return;
17091                 }
17092                 var buttonElement = this.buttonElement.removeClass( typeClasses ),
17093                         buttonText = $( "<span></span>" )
17094                                 .addClass( "ui-button-text" )
17095                                 .html( this.options.label )
17096                                 .appendTo( buttonElement.empty() )
17097                                 .text(),
17098                         icons = this.options.icons,
17099                         multipleIcons = icons.primary && icons.secondary,
17100                         buttonClasses = [];  
17101
17102                 if ( icons.primary || icons.secondary ) {
17103                         if ( this.options.text ) {
17104                                 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
17105                         }
17106
17107                         if ( icons.primary ) {
17108                                 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
17109                         }
17110
17111                         if ( icons.secondary ) {
17112                                 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
17113                         }
17114
17115                         if ( !this.options.text ) {
17116                                 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
17117
17118                                 if ( !this.hasTitle ) {
17119                                         buttonElement.attr( "title", buttonText );
17120                                 }
17121                         }
17122                 } else {
17123                         buttonClasses.push( "ui-button-text-only" );
17124                 }
17125                 buttonElement.addClass( buttonClasses.join( " " ) );
17126         }
17127 });
17128
17129 $.widget( "ui.buttonset", {
17130         options: {
17131                 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
17132         },
17133
17134         _create: function() {
17135                 this.element.addClass( "ui-buttonset" );
17136         },
17137         
17138         _init: function() {
17139                 this.refresh();
17140         },
17141
17142         _setOption: function( key, value ) {
17143                 if ( key === "disabled" ) {
17144                         this.buttons.button( "option", key, value );
17145                 }
17146
17147                 $.Widget.prototype._setOption.apply( this, arguments );
17148         },
17149         
17150         refresh: function() {
17151                 var ltr = this.element.css( "direction" ) === "ltr";
17152                 
17153                 this.buttons = this.element.find( this.options.items )
17154                         .filter( ":ui-button" )
17155                                 .button( "refresh" )
17156                         .end()
17157                         .not( ":ui-button" )
17158                                 .button()
17159                         .end()
17160                         .map(function() {
17161                                 return $( this ).button( "widget" )[ 0 ];
17162                         })
17163                                 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
17164                                 .filter( ":first" )
17165                                         .addClass( ltr ? "ui-corner-left" : "ui-corner-right" )
17166                                 .end()
17167                                 .filter( ":last" )
17168                                         .addClass( ltr ? "ui-corner-right" : "ui-corner-left" )
17169                                 .end()
17170                         .end();
17171         },
17172
17173         destroy: function() {
17174                 this.element.removeClass( "ui-buttonset" );
17175                 this.buttons
17176                         .map(function() {
17177                                 return $( this ).button( "widget" )[ 0 ];
17178                         })
17179                                 .removeClass( "ui-corner-left ui-corner-right" )
17180                         .end()
17181                         .button( "destroy" );
17182
17183                 $.Widget.prototype.destroy.call( this );
17184         }
17185 });
17186
17187 }( jQuery ) );
17188 /*
17189  * jQuery UI Datepicker 1.8.16
17190  *
17191  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
17192  * Dual licensed under the MIT or GPL Version 2 licenses.
17193  * http://jquery.org/license
17194  *
17195  * http://docs.jquery.com/UI/Datepicker
17196  *
17197  * Depends:
17198  *      jquery.ui.core.js
17199  */
17200 (function( $, undefined ) {
17201
17202 $.extend($.ui, { datepicker: { version: "1.8.16" } });
17203
17204 var PROP_NAME = 'datepicker';
17205 var dpuuid = new Date().getTime();
17206 var instActive;
17207
17208 /* Date picker manager.
17209    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
17210    Settings for (groups of) date pickers are maintained in an instance object,
17211    allowing multiple different settings on the same page. */
17212
17213 function Datepicker() {
17214         this.debug = false; // Change this to true to start debugging
17215         this._curInst = null; // The current instance in use
17216         this._keyEvent = false; // If the last event was a key event
17217         this._disabledInputs = []; // List of date picker inputs that have been disabled
17218         this._datepickerShowing = false; // True if the popup picker is showing , false if not
17219         this._inDialog = false; // True if showing within a "dialog", false if not
17220         this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
17221         this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
17222         this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
17223         this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
17224         this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
17225         this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
17226         this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
17227         this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
17228         this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
17229         this.regional = []; // Available regional settings, indexed by language code
17230         this.regional[''] = { // Default regional settings
17231                 closeText: 'Done', // Display text for close link
17232                 prevText: 'Prev', // Display text for previous month link
17233                 nextText: 'Next', // Display text for next month link
17234                 currentText: 'Today', // Display text for current month link
17235                 monthNames: ['January','February','March','April','May','June',
17236                         'July','August','September','October','November','December'], // Names of months for drop-down and formatting
17237                 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
17238                 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
17239                 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
17240                 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
17241                 weekHeader: 'Wk', // Column header for week of the year
17242                 dateFormat: 'mm/dd/yy', // See format options on parseDate
17243                 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
17244                 isRTL: false, // True if right-to-left language, false if left-to-right
17245                 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
17246                 yearSuffix: '' // Additional text to append to the year in the month headers
17247         };
17248         this._defaults = { // Global defaults for all the date picker instances
17249                 showOn: 'focus', // 'focus' for popup on focus,
17250                         // 'button' for trigger button, or 'both' for either
17251                 showAnim: 'fadeIn', // Name of jQuery animation for popup
17252                 showOptions: {}, // Options for enhanced animations
17253                 defaultDate: null, // Used when field is blank: actual date,
17254                         // +/-number for offset from today, null for today
17255                 appendText: '', // Display text following the input box, e.g. showing the format
17256                 buttonText: '...', // Text for trigger button
17257                 buttonImage: '', // URL for trigger button image
17258                 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
17259                 hideIfNoPrevNext: false, // True to hide next/previous month links
17260                         // if not applicable, false to just disable them
17261                 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
17262                 gotoCurrent: false, // True if today link goes back to current selection instead
17263                 changeMonth: false, // True if month can be selected directly, false if only prev/next
17264                 changeYear: false, // True if year can be selected directly, false if only prev/next
17265                 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
17266                         // either relative to today's year (-nn:+nn), relative to currently displayed year
17267                         // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
17268                 showOtherMonths: false, // True to show dates in other months, false to leave blank
17269                 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
17270                 showWeek: false, // True to show week of the year, false to not show it
17271                 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
17272                         // takes a Date and returns the number of the week for it
17273                 shortYearCutoff: '+10', // Short year values < this are in the current century,
17274                         // > this are in the previous century,
17275                         // string value starting with '+' for current year + value
17276                 minDate: null, // The earliest selectable date, or null for no limit
17277                 maxDate: null, // The latest selectable date, or null for no limit
17278                 duration: 'fast', // Duration of display/closure
17279                 beforeShowDay: null, // Function that takes a date and returns an array with
17280                         // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
17281                         // [2] = cell title (optional), e.g. $.datepicker.noWeekends
17282                 beforeShow: null, // Function that takes an input field and
17283                         // returns a set of custom settings for the date picker
17284                 onSelect: null, // Define a callback function when a date is selected
17285                 onChangeMonthYear: null, // Define a callback function when the month or year is changed
17286                 onClose: null, // Define a callback function when the datepicker is closed
17287                 numberOfMonths: 1, // Number of months to show at a time
17288                 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
17289                 stepMonths: 1, // Number of months to step back/forward
17290                 stepBigMonths: 12, // Number of months to step back/forward for the big links
17291                 altField: '', // Selector for an alternate field to store selected dates into
17292                 altFormat: '', // The date format to use for the alternate field
17293                 constrainInput: true, // The input is constrained by the current date format
17294                 showButtonPanel: false, // True to show button panel, false to not show it
17295                 autoSize: false, // True to size the input for the date format, false to leave as is
17296                 disabled: false // The initial disabled state
17297         };
17298         $.extend(this._defaults, this.regional['']);
17299         this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
17300 }
17301
17302 $.extend(Datepicker.prototype, {
17303         /* Class name added to elements to indicate already configured with a date picker. */
17304         markerClassName: 'hasDatepicker',
17305         
17306         //Keep track of the maximum number of rows displayed (see #7043)
17307         maxRows: 4,
17308
17309         /* Debug logging (if enabled). */
17310         log: function () {
17311                 if (this.debug)
17312                         console.log.apply('', arguments);
17313         },
17314         
17315         // TODO rename to "widget" when switching to widget factory
17316         _widgetDatepicker: function() {
17317                 return this.dpDiv;
17318         },
17319
17320         /* Override the default settings for all instances of the date picker.
17321            @param  settings  object - the new settings to use as defaults (anonymous object)
17322            @return the manager object */
17323         setDefaults: function(settings) {
17324                 extendRemove(this._defaults, settings || {});
17325                 return this;
17326         },
17327
17328         /* Attach the date picker to a jQuery selection.
17329            @param  target    element - the target input field or division or span
17330            @param  settings  object - the new settings to use for this date picker instance (anonymous) */
17331         _attachDatepicker: function(target, settings) {
17332                 // check for settings on the control itself - in namespace 'date:'
17333                 var inlineSettings = null;
17334                 for (var attrName in this._defaults) {
17335                         var attrValue = target.getAttribute('date:' + attrName);
17336                         if (attrValue) {
17337                                 inlineSettings = inlineSettings || {};
17338                                 try {
17339                                         inlineSettings[attrName] = eval(attrValue);
17340                                 } catch (err) {
17341                                         inlineSettings[attrName] = attrValue;
17342                                 }
17343                         }
17344                 }
17345                 var nodeName = target.nodeName.toLowerCase();
17346                 var inline = (nodeName == 'div' || nodeName == 'span');
17347                 if (!target.id) {
17348                         this.uuid += 1;
17349                         target.id = 'dp' + this.uuid;
17350                 }
17351                 var inst = this._newInst($(target), inline);
17352                 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
17353                 if (nodeName == 'input') {
17354                         this._connectDatepicker(target, inst);
17355                 } else if (inline) {
17356                         this._inlineDatepicker(target, inst);
17357                 }
17358         },
17359
17360         /* Create a new instance object. */
17361         _newInst: function(target, inline) {
17362                 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
17363                 return {id: id, input: target, // associated target
17364                         selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
17365                         drawMonth: 0, drawYear: 0, // month being drawn
17366                         inline: inline, // is datepicker inline or not
17367                         dpDiv: (!inline ? this.dpDiv : // presentation div
17368                         bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
17369         },
17370
17371         /* Attach the date picker to an input field. */
17372         _connectDatepicker: function(target, inst) {
17373                 var input = $(target);
17374                 inst.append = $([]);
17375                 inst.trigger = $([]);
17376                 if (input.hasClass(this.markerClassName))
17377                         return;
17378                 this._attachments(input, inst);
17379                 input.addClass(this.markerClassName).keydown(this._doKeyDown).
17380                         keypress(this._doKeyPress).keyup(this._doKeyUp).
17381                         bind("setData.datepicker", function(event, key, value) {
17382                                 inst.settings[key] = value;
17383                         }).bind("getData.datepicker", function(event, key) {
17384                                 return this._get(inst, key);
17385                         });
17386                 this._autoSize(inst);
17387                 $.data(target, PROP_NAME, inst);
17388                 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
17389                 if( inst.settings.disabled ) {
17390                         this._disableDatepicker( target );
17391                 }
17392         },
17393
17394         /* Make attachments based on settings. */
17395         _attachments: function(input, inst) {
17396                 var appendText = this._get(inst, 'appendText');
17397                 var isRTL = this._get(inst, 'isRTL');
17398                 if (inst.append)
17399                         inst.append.remove();
17400                 if (appendText) {
17401                         inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
17402                         input[isRTL ? 'before' : 'after'](inst.append);
17403                 }
17404                 input.unbind('focus', this._showDatepicker);
17405                 if (inst.trigger)
17406                         inst.trigger.remove();
17407                 var showOn = this._get(inst, 'showOn');
17408                 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
17409                         input.focus(this._showDatepicker);
17410                 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
17411                         var buttonText = this._get(inst, 'buttonText');
17412                         var buttonImage = this._get(inst, 'buttonImage');
17413                         inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
17414                                 $('<img/>').addClass(this._triggerClass).
17415                                         attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
17416                                 $('<button type="button"></button>').addClass(this._triggerClass).
17417                                         html(buttonImage == '' ? buttonText : $('<img/>').attr(
17418                                         { src:buttonImage, alt:buttonText, title:buttonText })));
17419                         input[isRTL ? 'before' : 'after'](inst.trigger);
17420                         inst.trigger.click(function() {
17421                                 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
17422                                         $.datepicker._hideDatepicker();
17423                                 else
17424                                         $.datepicker._showDatepicker(input[0]);
17425                                 return false;
17426                         });
17427                 }
17428         },
17429
17430         /* Apply the maximum length for the date format. */
17431         _autoSize: function(inst) {
17432                 if (this._get(inst, 'autoSize') && !inst.inline) {
17433                         var date = new Date(2009, 12 - 1, 20); // Ensure double digits
17434                         var dateFormat = this._get(inst, 'dateFormat');
17435                         if (dateFormat.match(/[DM]/)) {
17436                                 var findMax = function(names) {
17437                                         var max = 0;
17438                                         var maxI = 0;
17439                                         for (var i = 0; i < names.length; i++) {
17440                                                 if (names[i].length > max) {
17441                                                         max = names[i].length;
17442                                                         maxI = i;
17443                                                 }
17444                                         }
17445                                         return maxI;
17446                                 };
17447                                 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
17448                                         'monthNames' : 'monthNamesShort'))));
17449                                 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
17450                                         'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
17451                         }
17452                         inst.input.attr('size', this._formatDate(inst, date).length);
17453                 }
17454         },
17455
17456         /* Attach an inline date picker to a div. */
17457         _inlineDatepicker: function(target, inst) {
17458                 var divSpan = $(target);
17459                 if (divSpan.hasClass(this.markerClassName))
17460                         return;
17461                 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
17462                         bind("setData.datepicker", function(event, key, value){
17463                                 inst.settings[key] = value;
17464                         }).bind("getData.datepicker", function(event, key){
17465                                 return this._get(inst, key);
17466                         });
17467                 $.data(target, PROP_NAME, inst);
17468                 this._setDate(inst, this._getDefaultDate(inst), true);
17469                 this._updateDatepicker(inst);
17470                 this._updateAlternate(inst);
17471                 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
17472                 if( inst.settings.disabled ) {
17473                         this._disableDatepicker( target );
17474                 }
17475                 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
17476                 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
17477                 inst.dpDiv.css( "display", "block" );
17478         },
17479
17480         /* Pop-up the date picker in a "dialog" box.
17481            @param  input     element - ignored
17482            @param  date      string or Date - the initial date to display
17483            @param  onSelect  function - the function to call when a date is selected
17484            @param  settings  object - update the dialog date picker instance's settings (anonymous object)
17485            @param  pos       int[2] - coordinates for the dialog's position within the screen or
17486                              event - with x/y coordinates or
17487                              leave empty for default (screen centre)
17488            @return the manager object */
17489         _dialogDatepicker: function(input, date, onSelect, settings, pos) {
17490                 var inst = this._dialogInst; // internal instance
17491                 if (!inst) {
17492                         this.uuid += 1;
17493                         var id = 'dp' + this.uuid;
17494                         this._dialogInput = $('<input type="text" id="' + id +
17495                                 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
17496                         this._dialogInput.keydown(this._doKeyDown);
17497                         $('body').append(this._dialogInput);
17498                         inst = this._dialogInst = this._newInst(this._dialogInput, false);
17499                         inst.settings = {};
17500                         $.data(this._dialogInput[0], PROP_NAME, inst);
17501                 }
17502                 extendRemove(inst.settings, settings || {});
17503                 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
17504                 this._dialogInput.val(date);
17505
17506                 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
17507                 if (!this._pos) {
17508                         var browserWidth = document.documentElement.clientWidth;
17509                         var browserHeight = document.documentElement.clientHeight;
17510                         var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
17511                         var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
17512                         this._pos = // should use actual width/height below
17513                                 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
17514                 }
17515
17516                 // move input on screen for focus, but hidden behind dialog
17517                 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
17518                 inst.settings.onSelect = onSelect;
17519                 this._inDialog = true;
17520                 this.dpDiv.addClass(this._dialogClass);
17521                 this._showDatepicker(this._dialogInput[0]);
17522                 if ($.blockUI)
17523                         $.blockUI(this.dpDiv);
17524                 $.data(this._dialogInput[0], PROP_NAME, inst);
17525                 return this;
17526         },
17527
17528         /* Detach a datepicker from its control.
17529            @param  target    element - the target input field or division or span */
17530         _destroyDatepicker: function(target) {
17531                 var $target = $(target);
17532                 var inst = $.data(target, PROP_NAME);
17533                 if (!$target.hasClass(this.markerClassName)) {
17534                         return;
17535                 }
17536                 var nodeName = target.nodeName.toLowerCase();
17537                 $.removeData(target, PROP_NAME);
17538                 if (nodeName == 'input') {
17539                         inst.append.remove();
17540                         inst.trigger.remove();
17541                         $target.removeClass(this.markerClassName).
17542                                 unbind('focus', this._showDatepicker).
17543                                 unbind('keydown', this._doKeyDown).
17544                                 unbind('keypress', this._doKeyPress).
17545                                 unbind('keyup', this._doKeyUp);
17546                 } else if (nodeName == 'div' || nodeName == 'span')
17547                         $target.removeClass(this.markerClassName).empty();
17548         },
17549
17550         /* Enable the date picker to a jQuery selection.
17551            @param  target    element - the target input field or division or span */
17552         _enableDatepicker: function(target) {
17553                 var $target = $(target);
17554                 var inst = $.data(target, PROP_NAME);
17555                 if (!$target.hasClass(this.markerClassName)) {
17556                         return;
17557                 }
17558                 var nodeName = target.nodeName.toLowerCase();
17559                 if (nodeName == 'input') {
17560                         target.disabled = false;
17561                         inst.trigger.filter('button').
17562                                 each(function() { this.disabled = false; }).end().
17563                                 filter('img').css({opacity: '1.0', cursor: ''});
17564                 }
17565                 else if (nodeName == 'div' || nodeName == 'span') {
17566                         var inline = $target.children('.' + this._inlineClass);
17567                         inline.children().removeClass('ui-state-disabled');
17568                         inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
17569                                 removeAttr("disabled");
17570                 }
17571                 this._disabledInputs = $.map(this._disabledInputs,
17572                         function(value) { return (value == target ? null : value); }); // delete entry
17573         },
17574
17575         /* Disable the date picker to a jQuery selection.
17576            @param  target    element - the target input field or division or span */
17577         _disableDatepicker: function(target) {
17578                 var $target = $(target);
17579                 var inst = $.data(target, PROP_NAME);
17580                 if (!$target.hasClass(this.markerClassName)) {
17581                         return;
17582                 }
17583                 var nodeName = target.nodeName.toLowerCase();
17584                 if (nodeName == 'input') {
17585                         target.disabled = true;
17586                         inst.trigger.filter('button').
17587                                 each(function() { this.disabled = true; }).end().
17588                                 filter('img').css({opacity: '0.5', cursor: 'default'});
17589                 }
17590                 else if (nodeName == 'div' || nodeName == 'span') {
17591                         var inline = $target.children('.' + this._inlineClass);
17592                         inline.children().addClass('ui-state-disabled');
17593                         inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
17594                                 attr("disabled", "disabled");
17595                 }
17596                 this._disabledInputs = $.map(this._disabledInputs,
17597                         function(value) { return (value == target ? null : value); }); // delete entry
17598                 this._disabledInputs[this._disabledInputs.length] = target;
17599         },
17600
17601         /* Is the first field in a jQuery collection disabled as a datepicker?
17602            @param  target    element - the target input field or division or span
17603            @return boolean - true if disabled, false if enabled */
17604         _isDisabledDatepicker: function(target) {
17605                 if (!target) {
17606                         return false;
17607                 }
17608                 for (var i = 0; i < this._disabledInputs.length; i++) {
17609                         if (this._disabledInputs[i] == target)
17610                                 return true;
17611                 }
17612                 return false;
17613         },
17614
17615         /* Retrieve the instance data for the target control.
17616            @param  target  element - the target input field or division or span
17617            @return  object - the associated instance data
17618            @throws  error if a jQuery problem getting data */
17619         _getInst: function(target) {
17620                 try {
17621                         return $.data(target, PROP_NAME);
17622                 }
17623                 catch (err) {
17624                         throw 'Missing instance data for this datepicker';
17625                 }
17626         },
17627
17628         /* Update or retrieve the settings for a date picker attached to an input field or division.
17629            @param  target  element - the target input field or division or span
17630            @param  name    object - the new settings to update or
17631                            string - the name of the setting to change or retrieve,
17632                            when retrieving also 'all' for all instance settings or
17633                            'defaults' for all global defaults
17634            @param  value   any - the new value for the setting
17635                            (omit if above is an object or to retrieve a value) */
17636         _optionDatepicker: function(target, name, value) {
17637                 var inst = this._getInst(target);
17638                 if (arguments.length == 2 && typeof name == 'string') {
17639                         return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
17640                                 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
17641                                 this._get(inst, name)) : null));
17642                 }
17643                 var settings = name || {};
17644                 if (typeof name == 'string') {
17645                         settings = {};
17646                         settings[name] = value;
17647                 }
17648                 if (inst) {
17649                         if (this._curInst == inst) {
17650                                 this._hideDatepicker();
17651                         }
17652                         var date = this._getDateDatepicker(target, true);
17653                         var minDate = this._getMinMaxDate(inst, 'min');
17654                         var maxDate = this._getMinMaxDate(inst, 'max');
17655                         extendRemove(inst.settings, settings);
17656                         // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
17657                         if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
17658                                 inst.settings.minDate = this._formatDate(inst, minDate);
17659                         if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
17660                                 inst.settings.maxDate = this._formatDate(inst, maxDate);
17661                         this._attachments($(target), inst);
17662                         this._autoSize(inst);
17663                         this._setDate(inst, date);
17664                         this._updateAlternate(inst);
17665                         this._updateDatepicker(inst);
17666                 }
17667         },
17668
17669         // change method deprecated
17670         _changeDatepicker: function(target, name, value) {
17671                 this._optionDatepicker(target, name, value);
17672         },
17673
17674         /* Redraw the date picker attached to an input field or division.
17675            @param  target  element - the target input field or division or span */
17676         _refreshDatepicker: function(target) {
17677                 var inst = this._getInst(target);
17678                 if (inst) {
17679                         this._updateDatepicker(inst);
17680                 }
17681         },
17682
17683         /* Set the dates for a jQuery selection.
17684            @param  target   element - the target input field or division or span
17685            @param  date     Date - the new date */
17686         _setDateDatepicker: function(target, date) {
17687                 var inst = this._getInst(target);
17688                 if (inst) {
17689                         this._setDate(inst, date);
17690                         this._updateDatepicker(inst);
17691                         this._updateAlternate(inst);
17692                 }
17693         },
17694
17695         /* Get the date(s) for the first entry in a jQuery selection.
17696            @param  target     element - the target input field or division or span
17697            @param  noDefault  boolean - true if no default date is to be used
17698            @return Date - the current date */
17699         _getDateDatepicker: function(target, noDefault) {
17700                 var inst = this._getInst(target);
17701                 if (inst && !inst.inline)
17702                         this._setDateFromField(inst, noDefault);
17703                 return (inst ? this._getDate(inst) : null);
17704         },
17705
17706         /* Handle keystrokes. */
17707         _doKeyDown: function(event) {
17708                 var inst = $.datepicker._getInst(event.target);
17709                 var handled = true;
17710                 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
17711                 inst._keyEvent = true;
17712                 if ($.datepicker._datepickerShowing)
17713                         switch (event.keyCode) {
17714                                 case 9: $.datepicker._hideDatepicker();
17715                                                 handled = false;
17716                                                 break; // hide on tab out
17717                                 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 
17718                                                                         $.datepicker._currentClass + ')', inst.dpDiv);
17719                                                 if (sel[0])
17720                                                         $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
17721                                                         var onSelect = $.datepicker._get(inst, 'onSelect');
17722                                                         if (onSelect) {
17723                                                                 var dateStr = $.datepicker._formatDate(inst);
17724
17725                                                                 // trigger custom callback
17726                                                                 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
17727                                                         }
17728                                                 else
17729                                                         $.datepicker._hideDatepicker();
17730                                                 return false; // don't submit the form
17731                                                 break; // select the value on enter
17732                                 case 27: $.datepicker._hideDatepicker();
17733                                                 break; // hide on escape
17734                                 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
17735                                                         -$.datepicker._get(inst, 'stepBigMonths') :
17736                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');
17737                                                 break; // previous month/year on page up/+ ctrl
17738                                 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
17739                                                         +$.datepicker._get(inst, 'stepBigMonths') :
17740                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');
17741                                                 break; // next month/year on page down/+ ctrl
17742                                 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
17743                                                 handled = event.ctrlKey || event.metaKey;
17744                                                 break; // clear on ctrl or command +end
17745                                 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
17746                                                 handled = event.ctrlKey || event.metaKey;
17747                                                 break; // current on ctrl or command +home
17748                                 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
17749                                                 handled = event.ctrlKey || event.metaKey;
17750                                                 // -1 day on ctrl or command +left
17751                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
17752                                                                         -$.datepicker._get(inst, 'stepBigMonths') :
17753                                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');
17754                                                 // next month/year on alt +left on Mac
17755                                                 break;
17756                                 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
17757                                                 handled = event.ctrlKey || event.metaKey;
17758                                                 break; // -1 week on ctrl or command +up
17759                                 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
17760                                                 handled = event.ctrlKey || event.metaKey;
17761                                                 // +1 day on ctrl or command +right
17762                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
17763                                                                         +$.datepicker._get(inst, 'stepBigMonths') :
17764                                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');
17765                                                 // next month/year on alt +right
17766                                                 break;
17767                                 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
17768                                                 handled = event.ctrlKey || event.metaKey;
17769                                                 break; // +1 week on ctrl or command +down
17770                                 default: handled = false;
17771                         }
17772                 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
17773                         $.datepicker._showDatepicker(this);
17774                 else {
17775                         handled = false;
17776                 }
17777                 if (handled) {
17778                         event.preventDefault();
17779                         event.stopPropagation();
17780                 }
17781         },
17782
17783         /* Filter entered characters - based on date format. */
17784         _doKeyPress: function(event) {
17785                 var inst = $.datepicker._getInst(event.target);
17786                 if ($.datepicker._get(inst, 'constrainInput')) {
17787                         var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
17788                         var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
17789                         return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
17790                 }
17791         },
17792
17793         /* Synchronise manual entry and field/alternate field. */
17794         _doKeyUp: function(event) {
17795                 var inst = $.datepicker._getInst(event.target);
17796                 if (inst.input.val() != inst.lastVal) {
17797                         try {
17798                                 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
17799                                         (inst.input ? inst.input.val() : null),
17800                                         $.datepicker._getFormatConfig(inst));
17801                                 if (date) { // only if valid
17802                                         $.datepicker._setDateFromField(inst);
17803                                         $.datepicker._updateAlternate(inst);
17804                                         $.datepicker._updateDatepicker(inst);
17805                                 }
17806                         }
17807                         catch (event) {
17808                                 $.datepicker.log(event);
17809                         }
17810                 }
17811                 return true;
17812         },
17813
17814         /* Pop-up the date picker for a given input field.
17815        If false returned from beforeShow event handler do not show. 
17816            @param  input  element - the input field attached to the date picker or
17817                           event - if triggered by focus */
17818         _showDatepicker: function(input) {
17819                 input = input.target || input;
17820                 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
17821                         input = $('input', input.parentNode)[0];
17822                 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
17823                         return;
17824                 var inst = $.datepicker._getInst(input);
17825                 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
17826                         if ( $.datepicker._datepickerShowing ) {
17827                                 $.datepicker._triggerOnClose($.datepicker._curInst);
17828                         }
17829                         $.datepicker._curInst.dpDiv.stop(true, true);
17830                 }
17831                 var beforeShow = $.datepicker._get(inst, 'beforeShow');
17832                 var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
17833                 if(beforeShowSettings === false){
17834             //false
17835                         return;
17836                 }
17837                 extendRemove(inst.settings, beforeShowSettings);
17838                 inst.lastVal = null;
17839                 $.datepicker._lastInput = input;
17840                 $.datepicker._setDateFromField(inst);
17841                 if ($.datepicker._inDialog) // hide cursor
17842                         input.value = '';
17843                 if (!$.datepicker._pos) { // position below input
17844                         $.datepicker._pos = $.datepicker._findPos(input);
17845                         $.datepicker._pos[1] += input.offsetHeight; // add the height
17846                 }
17847                 var isFixed = false;
17848                 $(input).parents().each(function() {
17849                         isFixed |= $(this).css('position') == 'fixed';
17850                         return !isFixed;
17851                 });
17852                 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
17853                         $.datepicker._pos[0] -= document.documentElement.scrollLeft;
17854                         $.datepicker._pos[1] -= document.documentElement.scrollTop;
17855                 }
17856                 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
17857                 $.datepicker._pos = null;
17858                 //to avoid flashes on Firefox
17859                 inst.dpDiv.empty();
17860                 // determine sizing offscreen
17861                 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
17862                 $.datepicker._updateDatepicker(inst);
17863                 // fix width for dynamic number of date pickers
17864                 // and adjust position before showing
17865                 offset = $.datepicker._checkOffset(inst, offset, isFixed);
17866                 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
17867                         'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
17868                         left: offset.left + 'px', top: offset.top + 'px'});
17869                 if (!inst.inline) {
17870                         var showAnim = $.datepicker._get(inst, 'showAnim');
17871                         var duration = $.datepicker._get(inst, 'duration');
17872                         var postProcess = function() {
17873                                 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
17874                                 if( !! cover.length ){
17875                                         var borders = $.datepicker._getBorders(inst.dpDiv);
17876                                         cover.css({left: -borders[0], top: -borders[1],
17877                                                 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
17878                                 }
17879                         };
17880                         inst.dpDiv.zIndex($(input).zIndex()+1);
17881                         $.datepicker._datepickerShowing = true;
17882                         if ($.effects && $.effects[showAnim])
17883                                 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
17884                         else
17885                                 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
17886                         if (!showAnim || !duration)
17887                                 postProcess();
17888                         if (inst.input.is(':visible') && !inst.input.is(':disabled'))
17889                                 inst.input.focus();
17890                         $.datepicker._curInst = inst;
17891                 }
17892         },
17893
17894         /* Generate the date picker content. */
17895         _updateDatepicker: function(inst) {
17896                 var self = this;
17897                 self.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
17898                 var borders = $.datepicker._getBorders(inst.dpDiv);
17899                 instActive = inst; // for delegate hover events
17900                 inst.dpDiv.empty().append(this._generateHTML(inst));
17901                 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
17902                 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
17903                         cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
17904                 }
17905                 inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
17906                 var numMonths = this._getNumberOfMonths(inst);
17907                 var cols = numMonths[1];
17908                 var width = 17;
17909                 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
17910                 if (cols > 1)
17911                         inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
17912                 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
17913                         'Class']('ui-datepicker-multi');
17914                 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
17915                         'Class']('ui-datepicker-rtl');
17916                 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
17917                                 // #6694 - don't focus the input if it's already focused
17918                                 // this breaks the change event in IE
17919                                 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
17920                         inst.input.focus();
17921                 // deffered render of the years select (to avoid flashes on Firefox) 
17922                 if( inst.yearshtml ){
17923                         var origyearshtml = inst.yearshtml;
17924                         setTimeout(function(){
17925                                 //assure that inst.yearshtml didn't change.
17926                                 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
17927                                         inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
17928                                 }
17929                                 origyearshtml = inst.yearshtml = null;
17930                         }, 0);
17931                 }
17932         },
17933
17934         /* Retrieve the size of left and top borders for an element.
17935            @param  elem  (jQuery object) the element of interest
17936            @return  (number[2]) the left and top borders */
17937         _getBorders: function(elem) {
17938                 var convert = function(value) {
17939                         return {thin: 1, medium: 2, thick: 3}[value] || value;
17940                 };
17941                 return [parseFloat(convert(elem.css('border-left-width'))),
17942                         parseFloat(convert(elem.css('border-top-width')))];
17943         },
17944
17945         /* Check positioning to remain on screen. */
17946         _checkOffset: function(inst, offset, isFixed) {
17947                 var dpWidth = inst.dpDiv.outerWidth();
17948                 var dpHeight = inst.dpDiv.outerHeight();
17949                 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
17950                 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
17951                 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
17952                 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
17953
17954                 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
17955                 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
17956                 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
17957
17958                 // now check if datepicker is showing outside window viewport - move to a better place if so.
17959                 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
17960                         Math.abs(offset.left + dpWidth - viewWidth) : 0);
17961                 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
17962                         Math.abs(dpHeight + inputHeight) : 0);
17963
17964                 return offset;
17965         },
17966
17967         /* Find an object's position on the screen. */
17968         _findPos: function(obj) {
17969                 var inst = this._getInst(obj);
17970                 var isRTL = this._get(inst, 'isRTL');
17971         while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
17972             obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
17973         }
17974         var position = $(obj).offset();
17975             return [position.left, position.top];
17976         },
17977
17978         /* Trigger custom callback of onClose. */
17979         _triggerOnClose: function(inst) {
17980                 var onClose = this._get(inst, 'onClose');
17981                 if (onClose)
17982                         onClose.apply((inst.input ? inst.input[0] : null),
17983                                                   [(inst.input ? inst.input.val() : ''), inst]);
17984         },
17985
17986         /* Hide the date picker from view.
17987            @param  input  element - the input field attached to the date picker */
17988         _hideDatepicker: function(input) {
17989                 var inst = this._curInst;
17990                 if (!inst || (input && inst != $.data(input, PROP_NAME)))
17991                         return;
17992                 if (this._datepickerShowing) {
17993                         var showAnim = this._get(inst, 'showAnim');
17994                         var duration = this._get(inst, 'duration');
17995                         var postProcess = function() {
17996                                 $.datepicker._tidyDialog(inst);
17997                                 this._curInst = null;
17998                         };
17999                         if ($.effects && $.effects[showAnim])
18000                                 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
18001                         else
18002                                 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
18003                                         (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
18004                         if (!showAnim)
18005                                 postProcess();
18006                         $.datepicker._triggerOnClose(inst);
18007                         this._datepickerShowing = false;
18008                         this._lastInput = null;
18009                         if (this._inDialog) {
18010                                 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
18011                                 if ($.blockUI) {
18012                                         $.unblockUI();
18013                                         $('body').append(this.dpDiv);
18014                                 }
18015                         }
18016                         this._inDialog = false;
18017                 }
18018         },
18019
18020         /* Tidy up after a dialog display. */
18021         _tidyDialog: function(inst) {
18022                 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
18023         },
18024
18025         /* Close date picker if clicked elsewhere. */
18026         _checkExternalClick: function(event) {
18027                 if (!$.datepicker._curInst)
18028                         return;
18029                 var $target = $(event.target);
18030                 if ($target[0].id != $.datepicker._mainDivId &&
18031                                 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
18032                                 !$target.hasClass($.datepicker.markerClassName) &&
18033                                 !$target.hasClass($.datepicker._triggerClass) &&
18034                                 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
18035                         $.datepicker._hideDatepicker();
18036         },
18037
18038         /* Adjust one of the date sub-fields. */
18039         _adjustDate: function(id, offset, period) {
18040                 var target = $(id);
18041                 var inst = this._getInst(target[0]);
18042                 if (this._isDisabledDatepicker(target[0])) {
18043                         return;
18044                 }
18045                 this._adjustInstDate(inst, offset +
18046                         (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
18047                         period);
18048                 this._updateDatepicker(inst);
18049         },
18050
18051         /* Action for current link. */
18052         _gotoToday: function(id) {
18053                 var target = $(id);
18054                 var inst = this._getInst(target[0]);
18055                 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
18056                         inst.selectedDay = inst.currentDay;
18057                         inst.drawMonth = inst.selectedMonth = inst.currentMonth;
18058                         inst.drawYear = inst.selectedYear = inst.currentYear;
18059                 }
18060                 else {
18061                         var date = new Date();
18062                         inst.selectedDay = date.getDate();
18063                         inst.drawMonth = inst.selectedMonth = date.getMonth();
18064                         inst.drawYear = inst.selectedYear = date.getFullYear();
18065                 }
18066                 this._notifyChange(inst);
18067                 this._adjustDate(target);
18068         },
18069
18070         /* Action for selecting a new month/year. */
18071         _selectMonthYear: function(id, select, period) {
18072                 var target = $(id);
18073                 var inst = this._getInst(target[0]);
18074                 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
18075                 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
18076                         parseInt(select.options[select.selectedIndex].value,10);
18077                 this._notifyChange(inst);
18078                 this._adjustDate(target);
18079         },
18080
18081         /* Action for selecting a day. */
18082         _selectDay: function(id, month, year, td) {
18083                 var target = $(id);
18084                 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
18085                         return;
18086                 }
18087                 var inst = this._getInst(target[0]);
18088                 inst.selectedDay = inst.currentDay = $('a', td).html();
18089                 inst.selectedMonth = inst.currentMonth = month;
18090                 inst.selectedYear = inst.currentYear = year;
18091                 this._selectDate(id, this._formatDate(inst,
18092                         inst.currentDay, inst.currentMonth, inst.currentYear));
18093         },
18094
18095         /* Erase the input field and hide the date picker. */
18096         _clearDate: function(id) {
18097                 var target = $(id);
18098                 var inst = this._getInst(target[0]);
18099                 this._selectDate(target, '');
18100         },
18101
18102         /* Update the input field with the selected date. */
18103         _selectDate: function(id, dateStr) {
18104                 var target = $(id);
18105                 var inst = this._getInst(target[0]);
18106                 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
18107                 if (inst.input)
18108                         inst.input.val(dateStr);
18109                 this._updateAlternate(inst);
18110                 var onSelect = this._get(inst, 'onSelect');
18111                 if (onSelect)
18112                         onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
18113                 else if (inst.input)
18114                         inst.input.trigger('change'); // fire the change event
18115                 if (inst.inline)
18116                         this._updateDatepicker(inst);
18117                 else {
18118                         this._hideDatepicker();
18119                         this._lastInput = inst.input[0];
18120                         if (typeof(inst.input[0]) != 'object')
18121                                 inst.input.focus(); // restore focus
18122                         this._lastInput = null;
18123                 }
18124         },
18125
18126         /* Update any alternate field to synchronise with the main field. */
18127         _updateAlternate: function(inst) {
18128                 var altField = this._get(inst, 'altField');
18129                 if (altField) { // update alternate field too
18130                         var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
18131                         var date = this._getDate(inst);
18132                         var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
18133                         $(altField).each(function() { $(this).val(dateStr); });
18134                 }
18135         },
18136
18137         /* Set as beforeShowDay function to prevent selection of weekends.
18138            @param  date  Date - the date to customise
18139            @return [boolean, string] - is this date selectable?, what is its CSS class? */
18140         noWeekends: function(date) {
18141                 var day = date.getDay();
18142                 return [(day > 0 && day < 6), ''];
18143         },
18144
18145         /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
18146            @param  date  Date - the date to get the week for
18147            @return  number - the number of the week within the year that contains this date */
18148         iso8601Week: function(date) {
18149                 var checkDate = new Date(date.getTime());
18150                 // Find Thursday of this week starting on Monday
18151                 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
18152                 var time = checkDate.getTime();
18153                 checkDate.setMonth(0); // Compare with Jan 1
18154                 checkDate.setDate(1);
18155                 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
18156         },
18157
18158         /* Parse a string value into a date object.
18159            See formatDate below for the possible formats.
18160
18161            @param  format    string - the expected format of the date
18162            @param  value     string - the date in the above format
18163            @param  settings  Object - attributes include:
18164                              shortYearCutoff  number - the cutoff year for determining the century (optional)
18165                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
18166                              dayNames         string[7] - names of the days from Sunday (optional)
18167                              monthNamesShort  string[12] - abbreviated names of the months (optional)
18168                              monthNames       string[12] - names of the months (optional)
18169            @return  Date - the extracted date value or null if value is blank */
18170         parseDate: function (format, value, settings) {
18171                 if (format == null || value == null)
18172                         throw 'Invalid arguments';
18173                 value = (typeof value == 'object' ? value.toString() : value + '');
18174                 if (value == '')
18175                         return null;
18176                 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
18177                 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
18178                                 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
18179                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
18180                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
18181                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
18182                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
18183                 var year = -1;
18184                 var month = -1;
18185                 var day = -1;
18186                 var doy = -1;
18187                 var literal = false;
18188                 // Check whether a format character is doubled
18189                 var lookAhead = function(match) {
18190                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
18191                         if (matches)
18192                                 iFormat++;
18193                         return matches;
18194                 };
18195                 // Extract a number from the string value
18196                 var getNumber = function(match) {
18197                         var isDoubled = lookAhead(match);
18198                         var size = (match == '@' ? 14 : (match == '!' ? 20 :
18199                                 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
18200                         var digits = new RegExp('^\\d{1,' + size + '}');
18201                         var num = value.substring(iValue).match(digits);
18202                         if (!num)
18203                                 throw 'Missing number at position ' + iValue;
18204                         iValue += num[0].length;
18205                         return parseInt(num[0], 10);
18206                 };
18207                 // Extract a name from the string value and convert to an index
18208                 var getName = function(match, shortNames, longNames) {
18209                         var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
18210                                 return [ [k, v] ];
18211                         }).sort(function (a, b) {
18212                                 return -(a[1].length - b[1].length);
18213                         });
18214                         var index = -1;
18215                         $.each(names, function (i, pair) {
18216                                 var name = pair[1];
18217                                 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
18218                                         index = pair[0];
18219                                         iValue += name.length;
18220                                         return false;
18221                                 }
18222                         });
18223                         if (index != -1)
18224                                 return index + 1;
18225                         else
18226                                 throw 'Unknown name at position ' + iValue;
18227                 };
18228                 // Confirm that a literal character matches the string value
18229                 var checkLiteral = function() {
18230                         if (value.charAt(iValue) != format.charAt(iFormat))
18231                                 throw 'Unexpected literal at position ' + iValue;
18232                         iValue++;
18233                 };
18234                 var iValue = 0;
18235                 for (var iFormat = 0; iFormat < format.length; iFormat++) {
18236                         if (literal)
18237                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
18238                                         literal = false;
18239                                 else
18240                                         checkLiteral();
18241                         else
18242                                 switch (format.charAt(iFormat)) {
18243                                         case 'd':
18244                                                 day = getNumber('d');
18245                                                 break;
18246                                         case 'D':
18247                                                 getName('D', dayNamesShort, dayNames);
18248                                                 break;
18249                                         case 'o':
18250                                                 doy = getNumber('o');
18251                                                 break;
18252                                         case 'm':
18253                                                 month = getNumber('m');
18254                                                 break;
18255                                         case 'M':
18256                                                 month = getName('M', monthNamesShort, monthNames);
18257                                                 break;
18258                                         case 'y':
18259                                                 year = getNumber('y');
18260                                                 break;
18261                                         case '@':
18262                                                 var date = new Date(getNumber('@'));
18263                                                 year = date.getFullYear();
18264                                                 month = date.getMonth() + 1;
18265                                                 day = date.getDate();
18266                                                 break;
18267                                         case '!':
18268                                                 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
18269                                                 year = date.getFullYear();
18270                                                 month = date.getMonth() + 1;
18271                                                 day = date.getDate();
18272                                                 break;
18273                                         case "'":
18274                                                 if (lookAhead("'"))
18275                                                         checkLiteral();
18276                                                 else
18277                                                         literal = true;
18278                                                 break;
18279                                         default:
18280                                                 checkLiteral();
18281                                 }
18282                 }
18283                 if (iValue < value.length){
18284                         throw "Extra/unparsed characters found in date: " + value.substring(iValue);
18285                 }
18286                 if (year == -1)
18287                         year = new Date().getFullYear();
18288                 else if (year < 100)
18289                         year += new Date().getFullYear() - new Date().getFullYear() % 100 +
18290                                 (year <= shortYearCutoff ? 0 : -100);
18291                 if (doy > -1) {
18292                         month = 1;
18293                         day = doy;
18294                         do {
18295                                 var dim = this._getDaysInMonth(year, month - 1);
18296                                 if (day <= dim)
18297                                         break;
18298                                 month++;
18299                                 day -= dim;
18300                         } while (true);
18301                 }
18302                 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
18303                 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
18304                         throw 'Invalid date'; // E.g. 31/02/00
18305                 return date;
18306         },
18307
18308         /* Standard date formats. */
18309         ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
18310         COOKIE: 'D, dd M yy',
18311         ISO_8601: 'yy-mm-dd',
18312         RFC_822: 'D, d M y',
18313         RFC_850: 'DD, dd-M-y',
18314         RFC_1036: 'D, d M y',
18315         RFC_1123: 'D, d M yy',
18316         RFC_2822: 'D, d M yy',
18317         RSS: 'D, d M y', // RFC 822
18318         TICKS: '!',
18319         TIMESTAMP: '@',
18320         W3C: 'yy-mm-dd', // ISO 8601
18321
18322         _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
18323                 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
18324
18325         /* Format a date object into a string value.
18326            The format can be combinations of the following:
18327            d  - day of month (no leading zero)
18328            dd - day of month (two digit)
18329            o  - day of year (no leading zeros)
18330            oo - day of year (three digit)
18331            D  - day name short
18332            DD - day name long
18333            m  - month of year (no leading zero)
18334            mm - month of year (two digit)
18335            M  - month name short
18336            MM - month name long
18337            y  - year (two digit)
18338            yy - year (four digit)
18339            @ - Unix timestamp (ms since 01/01/1970)
18340            ! - Windows ticks (100ns since 01/01/0001)
18341            '...' - literal text
18342            '' - single quote
18343
18344            @param  format    string - the desired format of the date
18345            @param  date      Date - the date value to format
18346            @param  settings  Object - attributes include:
18347                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
18348                              dayNames         string[7] - names of the days from Sunday (optional)
18349                              monthNamesShort  string[12] - abbreviated names of the months (optional)
18350                              monthNames       string[12] - names of the months (optional)
18351            @return  string - the date in the above format */
18352         formatDate: function (format, date, settings) {
18353                 if (!date)
18354                         return '';
18355                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
18356                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
18357                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
18358                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
18359                 // Check whether a format character is doubled
18360                 var lookAhead = function(match) {
18361                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
18362                         if (matches)
18363                                 iFormat++;
18364                         return matches;
18365                 };
18366                 // Format a number, with leading zero if necessary
18367                 var formatNumber = function(match, value, len) {
18368                         var num = '' + value;
18369                         if (lookAhead(match))
18370                                 while (num.length < len)
18371                                         num = '0' + num;
18372                         return num;
18373                 };
18374                 // Format a name, short or long as requested
18375                 var formatName = function(match, value, shortNames, longNames) {
18376                         return (lookAhead(match) ? longNames[value] : shortNames[value]);
18377                 };
18378                 var output = '';
18379                 var literal = false;
18380                 if (date)
18381                         for (var iFormat = 0; iFormat < format.length; iFormat++) {
18382                                 if (literal)
18383                                         if (format.charAt(iFormat) == "'" && !lookAhead("'"))
18384                                                 literal = false;
18385                                         else
18386                                                 output += format.charAt(iFormat);
18387                                 else
18388                                         switch (format.charAt(iFormat)) {
18389                                                 case 'd':
18390                                                         output += formatNumber('d', date.getDate(), 2);
18391                                                         break;
18392                                                 case 'D':
18393                                                         output += formatName('D', date.getDay(), dayNamesShort, dayNames);
18394                                                         break;
18395                                                 case 'o':
18396                                                         output += formatNumber('o',
18397                                                                 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
18398                                                         break;
18399                                                 case 'm':
18400                                                         output += formatNumber('m', date.getMonth() + 1, 2);
18401                                                         break;
18402                                                 case 'M':
18403                                                         output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
18404                                                         break;
18405                                                 case 'y':
18406                                                         output += (lookAhead('y') ? date.getFullYear() :
18407                                                                 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
18408                                                         break;
18409                                                 case '@':
18410                                                         output += date.getTime();
18411                                                         break;
18412                                                 case '!':
18413                                                         output += date.getTime() * 10000 + this._ticksTo1970;
18414                                                         break;
18415                                                 case "'":
18416                                                         if (lookAhead("'"))
18417                                                                 output += "'";
18418                                                         else
18419                                                                 literal = true;
18420                                                         break;
18421                                                 default:
18422                                                         output += format.charAt(iFormat);
18423                                         }
18424                         }
18425                 return output;
18426         },
18427
18428         /* Extract all possible characters from the date format. */
18429         _possibleChars: function (format) {
18430                 var chars = '';
18431                 var literal = false;
18432                 // Check whether a format character is doubled
18433                 var lookAhead = function(match) {
18434                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
18435                         if (matches)
18436                                 iFormat++;
18437                         return matches;
18438                 };
18439                 for (var iFormat = 0; iFormat < format.length; iFormat++)
18440                         if (literal)
18441                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
18442                                         literal = false;
18443                                 else
18444                                         chars += format.charAt(iFormat);
18445                         else
18446                                 switch (format.charAt(iFormat)) {
18447                                         case 'd': case 'm': case 'y': case '@':
18448                                                 chars += '0123456789';
18449                                                 break;
18450                                         case 'D': case 'M':
18451                                                 return null; // Accept anything
18452                                         case "'":
18453                                                 if (lookAhead("'"))
18454                                                         chars += "'";
18455                                                 else
18456                                                         literal = true;
18457                                                 break;
18458                                         default:
18459                                                 chars += format.charAt(iFormat);
18460                                 }
18461                 return chars;
18462         },
18463
18464         /* Get a setting value, defaulting if necessary. */
18465         _get: function(inst, name) {
18466                 return inst.settings[name] !== undefined ?
18467                         inst.settings[name] : this._defaults[name];
18468         },
18469
18470         /* Parse existing date and initialise date picker. */
18471         _setDateFromField: function(inst, noDefault) {
18472                 if (inst.input.val() == inst.lastVal) {
18473                         return;
18474                 }
18475                 var dateFormat = this._get(inst, 'dateFormat');
18476                 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
18477                 var date, defaultDate;
18478                 date = defaultDate = this._getDefaultDate(inst);
18479                 var settings = this._getFormatConfig(inst);
18480                 try {
18481                         date = this.parseDate(dateFormat, dates, settings) || defaultDate;
18482                 } catch (event) {
18483                         this.log(event);
18484                         dates = (noDefault ? '' : dates);
18485                 }
18486                 inst.selectedDay = date.getDate();
18487                 inst.drawMonth = inst.selectedMonth = date.getMonth();
18488                 inst.drawYear = inst.selectedYear = date.getFullYear();
18489                 inst.currentDay = (dates ? date.getDate() : 0);
18490                 inst.currentMonth = (dates ? date.getMonth() : 0);
18491                 inst.currentYear = (dates ? date.getFullYear() : 0);
18492                 this._adjustInstDate(inst);
18493         },
18494
18495         /* Retrieve the default date shown on opening. */
18496         _getDefaultDate: function(inst) {
18497                 return this._restrictMinMax(inst,
18498                         this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
18499         },
18500
18501         /* A date may be specified as an exact value or a relative one. */
18502         _determineDate: function(inst, date, defaultDate) {
18503                 var offsetNumeric = function(offset) {
18504                         var date = new Date();
18505                         date.setDate(date.getDate() + offset);
18506                         return date;
18507                 };
18508                 var offsetString = function(offset) {
18509                         try {
18510                                 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
18511                                         offset, $.datepicker._getFormatConfig(inst));
18512                         }
18513                         catch (e) {
18514                                 // Ignore
18515                         }
18516                         var date = (offset.toLowerCase().match(/^c/) ?
18517                                 $.datepicker._getDate(inst) : null) || new Date();
18518                         var year = date.getFullYear();
18519                         var month = date.getMonth();
18520                         var day = date.getDate();
18521                         var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
18522                         var matches = pattern.exec(offset);
18523                         while (matches) {
18524                                 switch (matches[2] || 'd') {
18525                                         case 'd' : case 'D' :
18526                                                 day += parseInt(matches[1],10); break;
18527                                         case 'w' : case 'W' :
18528                                                 day += parseInt(matches[1],10) * 7; break;
18529                                         case 'm' : case 'M' :
18530                                                 month += parseInt(matches[1],10);
18531                                                 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
18532                                                 break;
18533                                         case 'y': case 'Y' :
18534                                                 year += parseInt(matches[1],10);
18535                                                 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
18536                                                 break;
18537                                 }
18538                                 matches = pattern.exec(offset);
18539                         }
18540                         return new Date(year, month, day);
18541                 };
18542                 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
18543                         (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
18544                 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
18545                 if (newDate) {
18546                         newDate.setHours(0);
18547                         newDate.setMinutes(0);
18548                         newDate.setSeconds(0);
18549                         newDate.setMilliseconds(0);
18550                 }
18551                 return this._daylightSavingAdjust(newDate);
18552         },
18553
18554         /* Handle switch to/from daylight saving.
18555            Hours may be non-zero on daylight saving cut-over:
18556            > 12 when midnight changeover, but then cannot generate
18557            midnight datetime, so jump to 1AM, otherwise reset.
18558            @param  date  (Date) the date to check
18559            @return  (Date) the corrected date */
18560         _daylightSavingAdjust: function(date) {
18561                 if (!date) return null;
18562                 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
18563                 return date;
18564         },
18565
18566         /* Set the date(s) directly. */
18567         _setDate: function(inst, date, noChange) {
18568                 var clear = !date;
18569                 var origMonth = inst.selectedMonth;
18570                 var origYear = inst.selectedYear;
18571                 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
18572                 inst.selectedDay = inst.currentDay = newDate.getDate();
18573                 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
18574                 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
18575                 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
18576                         this._notifyChange(inst);
18577                 this._adjustInstDate(inst);
18578                 if (inst.input) {
18579                         inst.input.val(clear ? '' : this._formatDate(inst));
18580                 }
18581         },
18582
18583         /* Retrieve the date(s) directly. */
18584         _getDate: function(inst) {
18585                 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
18586                         this._daylightSavingAdjust(new Date(
18587                         inst.currentYear, inst.currentMonth, inst.currentDay)));
18588                         return startDate;
18589         },
18590
18591         /* Generate the HTML for the current state of the date picker. */
18592         _generateHTML: function(inst) {
18593                 var today = new Date();
18594                 today = this._daylightSavingAdjust(
18595                         new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
18596                 var isRTL = this._get(inst, 'isRTL');
18597                 var showButtonPanel = this._get(inst, 'showButtonPanel');
18598                 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
18599                 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
18600                 var numMonths = this._getNumberOfMonths(inst);
18601                 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
18602                 var stepMonths = this._get(inst, 'stepMonths');
18603                 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
18604                 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
18605                         new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
18606                 var minDate = this._getMinMaxDate(inst, 'min');
18607                 var maxDate = this._getMinMaxDate(inst, 'max');
18608                 var drawMonth = inst.drawMonth - showCurrentAtPos;
18609                 var drawYear = inst.drawYear;
18610                 if (drawMonth < 0) {
18611                         drawMonth += 12;
18612                         drawYear--;
18613                 }
18614                 if (maxDate) {
18615                         var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
18616                                 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
18617                         maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
18618                         while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
18619                                 drawMonth--;
18620                                 if (drawMonth < 0) {
18621                                         drawMonth = 11;
18622                                         drawYear--;
18623                                 }
18624                         }
18625                 }
18626                 inst.drawMonth = drawMonth;
18627                 inst.drawYear = drawYear;
18628                 var prevText = this._get(inst, 'prevText');
18629                 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
18630                         this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
18631                         this._getFormatConfig(inst)));
18632                 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
18633                         '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
18634                         '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
18635                         ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
18636                         (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
18637                 var nextText = this._get(inst, 'nextText');
18638                 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
18639                         this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
18640                         this._getFormatConfig(inst)));
18641                 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
18642                         '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
18643                         '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
18644                         ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
18645                         (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
18646                 var currentText = this._get(inst, 'currentText');
18647                 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
18648                 currentText = (!navigationAsDateFormat ? currentText :
18649                         this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
18650                 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
18651                         '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
18652                 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
18653                         (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
18654                         '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
18655                         '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
18656                 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
18657                 firstDay = (isNaN(firstDay) ? 0 : firstDay);
18658                 var showWeek = this._get(inst, 'showWeek');
18659                 var dayNames = this._get(inst, 'dayNames');
18660                 var dayNamesShort = this._get(inst, 'dayNamesShort');
18661                 var dayNamesMin = this._get(inst, 'dayNamesMin');
18662                 var monthNames = this._get(inst, 'monthNames');
18663                 var monthNamesShort = this._get(inst, 'monthNamesShort');
18664                 var beforeShowDay = this._get(inst, 'beforeShowDay');
18665                 var showOtherMonths = this._get(inst, 'showOtherMonths');
18666                 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
18667                 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
18668                 var defaultDate = this._getDefaultDate(inst);
18669                 var html = '';
18670                 for (var row = 0; row < numMonths[0]; row++) {
18671                         var group = '';
18672                         this.maxRows = 4;
18673                         for (var col = 0; col < numMonths[1]; col++) {
18674                                 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
18675                                 var cornerClass = ' ui-corner-all';
18676                                 var calender = '';
18677                                 if (isMultiMonth) {
18678                                         calender += '<div class="ui-datepicker-group';
18679                                         if (numMonths[1] > 1)
18680                                                 switch (col) {
18681                                                         case 0: calender += ' ui-datepicker-group-first';
18682                                                                 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
18683                                                         case numMonths[1]-1: calender += ' ui-datepicker-group-last';
18684                                                                 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
18685                                                         default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
18686                                                 }
18687                                         calender += '">';
18688                                 }
18689                                 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
18690                                         (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
18691                                         (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
18692                                         this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
18693                                         row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
18694                                         '</div><table class="ui-datepicker-calendar"><thead>' +
18695                                         '<tr>';
18696                                 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
18697                                 for (var dow = 0; dow < 7; dow++) { // days of the week
18698                                         var day = (dow + firstDay) % 7;
18699                                         thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
18700                                                 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
18701                                 }
18702                                 calender += thead + '</tr></thead><tbody>';
18703                                 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
18704                                 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
18705                                         inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
18706                                 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
18707                                 var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
18708                                 var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
18709                                 this.maxRows = numRows;
18710                                 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
18711                                 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
18712                                         calender += '<tr>';
18713                                         var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
18714                                                 this._get(inst, 'calculateWeek')(printDate) + '</td>');
18715                                         for (var dow = 0; dow < 7; dow++) { // create date picker days
18716                                                 var daySettings = (beforeShowDay ?
18717                                                         beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
18718                                                 var otherMonth = (printDate.getMonth() != drawMonth);
18719                                                 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
18720                                                         (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
18721                                                 tbody += '<td class="' +
18722                                                         ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
18723                                                         (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
18724                                                         ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
18725                                                         (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
18726                                                         // or defaultDate is current printedDate and defaultDate is selectedDate
18727                                                         ' ' + this._dayOverClass : '') + // highlight selected day
18728                                                         (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
18729                                                         (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
18730                                                         (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
18731                                                         (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
18732                                                         ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
18733                                                         (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
18734                                                         inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
18735                                                         (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
18736                                                         (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
18737                                                         (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
18738                                                         (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
18739                                                         (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
18740                                                         '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
18741                                                 printDate.setDate(printDate.getDate() + 1);
18742                                                 printDate = this._daylightSavingAdjust(printDate);
18743                                         }
18744                                         calender += tbody + '</tr>';
18745                                 }
18746                                 drawMonth++;
18747                                 if (drawMonth > 11) {
18748                                         drawMonth = 0;
18749                                         drawYear++;
18750                                 }
18751                                 calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
18752                                                         ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
18753                                 group += calender;
18754                         }
18755                         html += group;
18756                 }
18757                 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
18758                         '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
18759                 inst._keyEvent = false;
18760                 return html;
18761         },
18762
18763         /* Generate the month and year header. */
18764         _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
18765                         secondary, monthNames, monthNamesShort) {
18766                 var changeMonth = this._get(inst, 'changeMonth');
18767                 var changeYear = this._get(inst, 'changeYear');
18768                 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
18769                 var html = '<div class="ui-datepicker-title">';
18770                 var monthHtml = '';
18771                 // month selection
18772                 if (secondary || !changeMonth)
18773                         monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
18774                 else {
18775                         var inMinYear = (minDate && minDate.getFullYear() == drawYear);
18776                         var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
18777                         monthHtml += '<select class="ui-datepicker-month" ' +
18778                                 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
18779                                 '>';
18780                         for (var month = 0; month < 12; month++) {
18781                                 if ((!inMinYear || month >= minDate.getMonth()) &&
18782                                                 (!inMaxYear || month <= maxDate.getMonth()))
18783                                         monthHtml += '<option value="' + month + '"' +
18784                                                 (month == drawMonth ? ' selected="selected"' : '') +
18785                                                 '>' + monthNamesShort[month] + '</option>';
18786                         }
18787                         monthHtml += '</select>';
18788                 }
18789                 if (!showMonthAfterYear)
18790                         html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
18791                 // year selection
18792                 if ( !inst.yearshtml ) {
18793                         inst.yearshtml = '';
18794                         if (secondary || !changeYear)
18795                                 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
18796                         else {
18797                                 // determine range of years to display
18798                                 var years = this._get(inst, 'yearRange').split(':');
18799                                 var thisYear = new Date().getFullYear();
18800                                 var determineYear = function(value) {
18801                                         var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
18802                                                 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
18803                                                 parseInt(value, 10)));
18804                                         return (isNaN(year) ? thisYear : year);
18805                                 };
18806                                 var year = determineYear(years[0]);
18807                                 var endYear = Math.max(year, determineYear(years[1] || ''));
18808                                 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
18809                                 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
18810                                 inst.yearshtml += '<select class="ui-datepicker-year" ' +
18811                                         'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
18812                                         '>';
18813                                 for (; year <= endYear; year++) {
18814                                         inst.yearshtml += '<option value="' + year + '"' +
18815                                                 (year == drawYear ? ' selected="selected"' : '') +
18816                                                 '>' + year + '</option>';
18817                                 }
18818                                 inst.yearshtml += '</select>';
18819                                 
18820                                 html += inst.yearshtml;
18821                                 inst.yearshtml = null;
18822                         }
18823                 }
18824                 html += this._get(inst, 'yearSuffix');
18825                 if (showMonthAfterYear)
18826                         html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
18827                 html += '</div>'; // Close datepicker_header
18828                 return html;
18829         },
18830
18831         /* Adjust one of the date sub-fields. */
18832         _adjustInstDate: function(inst, offset, period) {
18833                 var year = inst.drawYear + (period == 'Y' ? offset : 0);
18834                 var month = inst.drawMonth + (period == 'M' ? offset : 0);
18835                 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
18836                         (period == 'D' ? offset : 0);
18837                 var date = this._restrictMinMax(inst,
18838                         this._daylightSavingAdjust(new Date(year, month, day)));
18839                 inst.selectedDay = date.getDate();
18840                 inst.drawMonth = inst.selectedMonth = date.getMonth();
18841                 inst.drawYear = inst.selectedYear = date.getFullYear();
18842                 if (period == 'M' || period == 'Y')
18843                         this._notifyChange(inst);
18844         },
18845
18846         /* Ensure a date is within any min/max bounds. */
18847         _restrictMinMax: function(inst, date) {
18848                 var minDate = this._getMinMaxDate(inst, 'min');
18849                 var maxDate = this._getMinMaxDate(inst, 'max');
18850                 var newDate = (minDate && date < minDate ? minDate : date);
18851                 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
18852                 return newDate;
18853         },
18854
18855         /* Notify change of month/year. */
18856         _notifyChange: function(inst) {
18857                 var onChange = this._get(inst, 'onChangeMonthYear');
18858                 if (onChange)
18859                         onChange.apply((inst.input ? inst.input[0] : null),
18860                                 [inst.selectedYear, inst.selectedMonth + 1, inst]);
18861         },
18862
18863         /* Determine the number of months to show. */
18864         _getNumberOfMonths: function(inst) {
18865                 var numMonths = this._get(inst, 'numberOfMonths');
18866                 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
18867         },
18868
18869         /* Determine the current maximum date - ensure no time components are set. */
18870         _getMinMaxDate: function(inst, minMax) {
18871                 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
18872         },
18873
18874         /* Find the number of days in a given month. */
18875         _getDaysInMonth: function(year, month) {
18876                 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
18877         },
18878
18879         /* Find the day of the week of the first of a month. */
18880         _getFirstDayOfMonth: function(year, month) {
18881                 return new Date(year, month, 1).getDay();
18882         },
18883
18884         /* Determines if we should allow a "next/prev" month display change. */
18885         _canAdjustMonth: function(inst, offset, curYear, curMonth) {
18886                 var numMonths = this._getNumberOfMonths(inst);
18887                 var date = this._daylightSavingAdjust(new Date(curYear,
18888                         curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
18889                 if (offset < 0)
18890                         date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
18891                 return this._isInRange(inst, date);
18892         },
18893
18894         /* Is the given date in the accepted range? */
18895         _isInRange: function(inst, date) {
18896                 var minDate = this._getMinMaxDate(inst, 'min');
18897                 var maxDate = this._getMinMaxDate(inst, 'max');
18898                 return ((!minDate || date.getTime() >= minDate.getTime()) &&
18899                         (!maxDate || date.getTime() <= maxDate.getTime()));
18900         },
18901
18902         /* Provide the configuration settings for formatting/parsing. */
18903         _getFormatConfig: function(inst) {
18904                 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
18905                 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
18906                         new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
18907                 return {shortYearCutoff: shortYearCutoff,
18908                         dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
18909                         monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
18910         },
18911
18912         /* Format the given date for display. */
18913         _formatDate: function(inst, day, month, year) {
18914                 if (!day) {
18915                         inst.currentDay = inst.selectedDay;
18916                         inst.currentMonth = inst.selectedMonth;
18917                         inst.currentYear = inst.selectedYear;
18918                 }
18919                 var date = (day ? (typeof day == 'object' ? day :
18920                         this._daylightSavingAdjust(new Date(year, month, day))) :
18921                         this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
18922                 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
18923         }
18924 });
18925
18926 /*
18927  * Bind hover events for datepicker elements.
18928  * Done via delegate so the binding only occurs once in the lifetime of the parent div.
18929  * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
18930  */ 
18931 function bindHover(dpDiv) {
18932         var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
18933         return dpDiv.bind('mouseout', function(event) {
18934                         var elem = $( event.target ).closest( selector );
18935                         if ( !elem.length ) {
18936                                 return;
18937                         }
18938                         elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
18939                 })
18940                 .bind('mouseover', function(event) {
18941                         var elem = $( event.target ).closest( selector );
18942                         if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
18943                                         !elem.length ) {
18944                                 return;
18945                         }
18946                         elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
18947                         elem.addClass('ui-state-hover');
18948                         if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover');
18949                         if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover');
18950                 });
18951 }
18952
18953 /* jQuery extend now ignores nulls! */
18954 function extendRemove(target, props) {
18955         $.extend(target, props);
18956         for (var name in props)
18957                 if (props[name] == null || props[name] == undefined)
18958                         target[name] = props[name];
18959         return target;
18960 };
18961
18962 /* Determine whether an object is an array. */
18963 function isArray(a) {
18964         return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
18965                 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
18966 };
18967
18968 /* Invoke the datepicker functionality.
18969    @param  options  string - a command, optionally followed by additional parameters or
18970                     Object - settings for attaching new datepicker functionality
18971    @return  jQuery object */
18972 $.fn.datepicker = function(options){
18973         
18974         /* Verify an empty collection wasn't passed - Fixes #6976 */
18975         if ( !this.length ) {
18976                 return this;
18977         }
18978         
18979         /* Initialise the date picker. */
18980         if (!$.datepicker.initialized) {
18981                 $(document).mousedown($.datepicker._checkExternalClick).
18982                         find('body').append($.datepicker.dpDiv);
18983                 $.datepicker.initialized = true;
18984         }
18985
18986         var otherArgs = Array.prototype.slice.call(arguments, 1);
18987         if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
18988                 return $.datepicker['_' + options + 'Datepicker'].
18989                         apply($.datepicker, [this[0]].concat(otherArgs));
18990         if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
18991                 return $.datepicker['_' + options + 'Datepicker'].
18992                         apply($.datepicker, [this[0]].concat(otherArgs));
18993         return this.each(function() {
18994                 typeof options == 'string' ?
18995                         $.datepicker['_' + options + 'Datepicker'].
18996                                 apply($.datepicker, [this].concat(otherArgs)) :
18997                         $.datepicker._attachDatepicker(this, options);
18998         });
18999 };
19000
19001 $.datepicker = new Datepicker(); // singleton instance
19002 $.datepicker.initialized = false;
19003 $.datepicker.uuid = new Date().getTime();
19004 $.datepicker.version = "1.8.16";
19005
19006 // Workaround for #4055
19007 // Add another global to avoid noConflict issues with inline event handlers
19008 window['DP_jQuery_' + dpuuid] = $;
19009
19010 })(jQuery);
19011 /*
19012  * jQuery UI Dialog 1.8.16
19013  *
19014  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
19015  * Dual licensed under the MIT or GPL Version 2 licenses.
19016  * http://jquery.org/license
19017  *
19018  * http://docs.jquery.com/UI/Dialog
19019  *
19020  * Depends:
19021  *      jquery.ui.core.js
19022  *      jquery.ui.widget.js
19023  *  jquery.ui.button.js
19024  *      jquery.ui.draggable.js
19025  *      jquery.ui.mouse.js
19026  *      jquery.ui.position.js
19027  *      jquery.ui.resizable.js
19028  */
19029 (function( $, undefined ) {
19030
19031 var uiDialogClasses =
19032                 'ui-dialog ' +
19033                 'ui-widget ' +
19034                 'ui-widget-content ' +
19035                 'ui-corner-all ',
19036         sizeRelatedOptions = {
19037                 buttons: true,
19038                 height: true,
19039                 maxHeight: true,
19040                 maxWidth: true,
19041                 minHeight: true,
19042                 minWidth: true,
19043                 width: true
19044         },
19045         resizableRelatedOptions = {
19046                 maxHeight: true,
19047                 maxWidth: true,
19048                 minHeight: true,
19049                 minWidth: true
19050         },
19051         // support for jQuery 1.3.2 - handle common attrFn methods for dialog
19052         attrFn = $.attrFn || {
19053                 val: true,
19054                 css: true,
19055                 html: true,
19056                 text: true,
19057                 data: true,
19058                 width: true,
19059                 height: true,
19060                 offset: true,
19061                 click: true
19062         };
19063
19064 $.widget("ui.dialog", {
19065         options: {
19066                 autoOpen: true,
19067                 buttons: {},
19068                 closeOnEscape: true,
19069                 closeText: 'close',
19070                 dialogClass: '',
19071                 draggable: true,
19072                 hide: null,
19073                 height: 'auto',
19074                 maxHeight: false,
19075                 maxWidth: false,
19076                 minHeight: 150,
19077                 minWidth: 150,
19078                 modal: false,
19079                 position: {
19080                         my: 'center',
19081                         at: 'center',
19082                         collision: 'fit',
19083                         // ensure that the titlebar is never outside the document
19084                         using: function(pos) {
19085                                 var topOffset = $(this).css(pos).offset().top;
19086                                 if (topOffset < 0) {
19087                                         $(this).css('top', pos.top - topOffset);
19088                                 }
19089                         }
19090                 },
19091                 resizable: true,
19092                 show: null,
19093                 stack: true,
19094                 title: '',
19095                 width: 300,
19096                 zIndex: 1000
19097         },
19098
19099         _create: function() {
19100                 this.originalTitle = this.element.attr('title');
19101                 // #5742 - .attr() might return a DOMElement
19102                 if ( typeof this.originalTitle !== "string" ) {
19103                         this.originalTitle = "";
19104                 }
19105
19106                 this.options.title = this.options.title || this.originalTitle;
19107                 var self = this,
19108                         options = self.options,
19109
19110                         title = options.title || '&#160;',
19111                         titleId = $.ui.dialog.getTitleId(self.element),
19112
19113                         uiDialog = (self.uiDialog = $('<div></div>'))
19114                                 .appendTo(document.body)
19115                                 .hide()
19116                                 .addClass(uiDialogClasses + options.dialogClass)
19117                                 .css({
19118                                         zIndex: options.zIndex
19119                                 })
19120                                 // setting tabIndex makes the div focusable
19121                                 // setting outline to 0 prevents a border on focus in Mozilla
19122                                 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
19123                                         if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
19124                                                 event.keyCode === $.ui.keyCode.ESCAPE) {
19125                                                 
19126                                                 self.close(event);
19127                                                 event.preventDefault();
19128                                         }
19129                                 })
19130                                 .attr({
19131                                         role: 'dialog',
19132                                         'aria-labelledby': titleId
19133                                 })
19134                                 .mousedown(function(event) {
19135                                         self.moveToTop(false, event);
19136                                 }),
19137
19138                         uiDialogContent = self.element
19139                                 .show()
19140                                 .removeAttr('title')
19141                                 .addClass(
19142                                         'ui-dialog-content ' +
19143                                         'ui-widget-content')
19144                                 .appendTo(uiDialog),
19145
19146                         uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
19147                                 .addClass(
19148                                         'ui-dialog-titlebar ' +
19149                                         'ui-widget-header ' +
19150                                         'ui-corner-all ' +
19151                                         'ui-helper-clearfix'
19152                                 )
19153                                 .prependTo(uiDialog),
19154
19155                         uiDialogTitlebarClose = $('<a href="#"></a>')
19156                                 .addClass(
19157                                         'ui-dialog-titlebar-close ' +
19158                                         'ui-corner-all'
19159                                 )
19160                                 .attr('role', 'button')
19161                                 .hover(
19162                                         function() {
19163                                                 uiDialogTitlebarClose.addClass('ui-state-hover');
19164                                         },
19165                                         function() {
19166                                                 uiDialogTitlebarClose.removeClass('ui-state-hover');
19167                                         }
19168                                 )
19169                                 .focus(function() {
19170                                         uiDialogTitlebarClose.addClass('ui-state-focus');
19171                                 })
19172                                 .blur(function() {
19173                                         uiDialogTitlebarClose.removeClass('ui-state-focus');
19174                                 })
19175                                 .click(function(event) {
19176                                         self.close(event);
19177                                         return false;
19178                                 })
19179                                 .appendTo(uiDialogTitlebar),
19180
19181                         uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
19182                                 .addClass(
19183                                         'ui-icon ' +
19184                                         'ui-icon-closethick'
19185                                 )
19186                                 .text(options.closeText)
19187                                 .appendTo(uiDialogTitlebarClose),
19188
19189                         uiDialogTitle = $('<span></span>')
19190                                 .addClass('ui-dialog-title')
19191                                 .attr('id', titleId)
19192                                 .html(title)
19193                                 .prependTo(uiDialogTitlebar);
19194
19195                 //handling of deprecated beforeclose (vs beforeClose) option
19196                 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
19197                 //TODO: remove in 1.9pre
19198                 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
19199                         options.beforeClose = options.beforeclose;
19200                 }
19201
19202                 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
19203
19204                 if (options.draggable && $.fn.draggable) {
19205                         self._makeDraggable();
19206                 }
19207                 if (options.resizable && $.fn.resizable) {
19208                         self._makeResizable();
19209                 }
19210
19211                 self._createButtons(options.buttons);
19212                 self._isOpen = false;
19213
19214                 if ($.fn.bgiframe) {
19215                         uiDialog.bgiframe();
19216                 }
19217         },
19218
19219         _init: function() {
19220                 if ( this.options.autoOpen ) {
19221                         this.open();
19222                 }
19223         },
19224
19225         destroy: function() {
19226                 var self = this;
19227                 
19228                 if (self.overlay) {
19229                         self.overlay.destroy();
19230                 }
19231                 self.uiDialog.hide();
19232                 self.element
19233                         .unbind('.dialog')
19234                         .removeData('dialog')
19235                         .removeClass('ui-dialog-content ui-widget-content')
19236                         .hide().appendTo('body');
19237                 self.uiDialog.remove();
19238
19239                 if (self.originalTitle) {
19240                         self.element.attr('title', self.originalTitle);
19241                 }
19242
19243                 return self;
19244         },
19245
19246         widget: function() {
19247                 return this.uiDialog;
19248         },
19249
19250         close: function(event) {
19251                 var self = this,
19252                         maxZ, thisZ;
19253                 
19254                 if (false === self._trigger('beforeClose', event)) {
19255                         return;
19256                 }
19257
19258                 if (self.overlay) {
19259                         self.overlay.destroy();
19260                 }
19261                 self.uiDialog.unbind('keypress.ui-dialog');
19262
19263                 self._isOpen = false;
19264
19265                 if (self.options.hide) {
19266                         self.uiDialog.hide(self.options.hide, function() {
19267                                 self._trigger('close', event);
19268                         });
19269                 } else {
19270                         self.uiDialog.hide();
19271                         self._trigger('close', event);
19272                 }
19273
19274                 $.ui.dialog.overlay.resize();
19275
19276                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
19277                 if (self.options.modal) {
19278                         maxZ = 0;
19279                         $('.ui-dialog').each(function() {
19280                                 if (this !== self.uiDialog[0]) {
19281                                         thisZ = $(this).css('z-index');
19282                                         if(!isNaN(thisZ)) {
19283                                                 maxZ = Math.max(maxZ, thisZ);
19284                                         }
19285                                 }
19286                         });
19287                         $.ui.dialog.maxZ = maxZ;
19288                 }
19289
19290                 return self;
19291         },
19292
19293         isOpen: function() {
19294                 return this._isOpen;
19295         },
19296
19297         // the force parameter allows us to move modal dialogs to their correct
19298         // position on open
19299         moveToTop: function(force, event) {
19300                 var self = this,
19301                         options = self.options,
19302                         saveScroll;
19303
19304                 if ((options.modal && !force) ||
19305                         (!options.stack && !options.modal)) {
19306                         return self._trigger('focus', event);
19307                 }
19308
19309                 if (options.zIndex > $.ui.dialog.maxZ) {
19310                         $.ui.dialog.maxZ = options.zIndex;
19311                 }
19312                 if (self.overlay) {
19313                         $.ui.dialog.maxZ += 1;
19314                         self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
19315                 }
19316
19317                 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
19318                 //  http://ui.jquery.com/bugs/ticket/3193
19319                 saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() };
19320                 $.ui.dialog.maxZ += 1;
19321                 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
19322                 self.element.attr(saveScroll);
19323                 self._trigger('focus', event);
19324
19325                 return self;
19326         },
19327
19328         open: function() {
19329                 if (this._isOpen) { return; }
19330
19331                 var self = this,
19332                         options = self.options,
19333                         uiDialog = self.uiDialog;
19334
19335                 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
19336                 self._size();
19337                 self._position(options.position);
19338                 uiDialog.show(options.show);
19339                 self.moveToTop(true);
19340
19341                 // prevent tabbing out of modal dialogs
19342                 if (options.modal) {
19343                         uiDialog.bind('keypress.ui-dialog', function(event) {
19344                                 if (event.keyCode !== $.ui.keyCode.TAB) {
19345                                         return;
19346                                 }
19347
19348                                 var tabbables = $(':tabbable', this),
19349                                         first = tabbables.filter(':first'),
19350                                         last  = tabbables.filter(':last');
19351
19352                                 if (event.target === last[0] && !event.shiftKey) {
19353                                         first.focus(1);
19354                                         return false;
19355                                 } else if (event.target === first[0] && event.shiftKey) {
19356                                         last.focus(1);
19357                                         return false;
19358                                 }
19359                         });
19360                 }
19361
19362                 // set focus to the first tabbable element in the content area or the first button
19363                 // if there are no tabbable elements, set focus on the dialog itself
19364                 $(self.element.find(':tabbable').get().concat(
19365                         uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
19366                                 uiDialog.get()))).eq(0).focus();
19367
19368                 self._isOpen = true;
19369                 self._trigger('open');
19370
19371                 return self;
19372         },
19373
19374         _createButtons: function(buttons) {
19375                 var self = this,
19376                         hasButtons = false,
19377                         uiDialogButtonPane = $('<div></div>')
19378                                 .addClass(
19379                                         'ui-dialog-buttonpane ' +
19380                                         'ui-widget-content ' +
19381                                         'ui-helper-clearfix'
19382                                 ),
19383                         uiButtonSet = $( "<div></div>" )
19384                                 .addClass( "ui-dialog-buttonset" )
19385                                 .appendTo( uiDialogButtonPane );
19386
19387                 // if we already have a button pane, remove it
19388                 self.uiDialog.find('.ui-dialog-buttonpane').remove();
19389
19390                 if (typeof buttons === 'object' && buttons !== null) {
19391                         $.each(buttons, function() {
19392                                 return !(hasButtons = true);
19393                         });
19394                 }
19395                 if (hasButtons) {
19396                         $.each(buttons, function(name, props) {
19397                                 props = $.isFunction( props ) ?
19398                                         { click: props, text: name } :
19399                                         props;
19400                                 var button = $('<button type="button"></button>')
19401                                         .click(function() {
19402                                                 props.click.apply(self.element[0], arguments);
19403                                         })
19404                                         .appendTo(uiButtonSet);
19405                                 // can't use .attr( props, true ) with jQuery 1.3.2.
19406                                 $.each( props, function( key, value ) {
19407                                         if ( key === "click" ) {
19408                                                 return;
19409                                         }
19410                                         if ( key in attrFn ) {
19411                                                 button[ key ]( value );
19412                                         } else {
19413                                                 button.attr( key, value );
19414                                         }
19415                                 });
19416                                 if ($.fn.button) {
19417                                         button.button();
19418                                 }
19419                         });
19420                         uiDialogButtonPane.appendTo(self.uiDialog);
19421                 }
19422         },
19423
19424         _makeDraggable: function() {
19425                 var self = this,
19426                         options = self.options,
19427                         doc = $(document),
19428                         heightBeforeDrag;
19429
19430                 function filteredUi(ui) {
19431                         return {
19432                                 position: ui.position,
19433                                 offset: ui.offset
19434                         };
19435                 }
19436
19437                 self.uiDialog.draggable({
19438                         cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
19439                         handle: '.ui-dialog-titlebar',
19440                         containment: 'document',
19441                         start: function(event, ui) {
19442                                 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
19443                                 $(this).height($(this).height()).addClass("ui-dialog-dragging");
19444                                 self._trigger('dragStart', event, filteredUi(ui));
19445                         },
19446                         drag: function(event, ui) {
19447                                 self._trigger('drag', event, filteredUi(ui));
19448                         },
19449                         stop: function(event, ui) {
19450                                 options.position = [ui.position.left - doc.scrollLeft(),
19451                                         ui.position.top - doc.scrollTop()];
19452                                 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
19453                                 self._trigger('dragStop', event, filteredUi(ui));
19454                                 $.ui.dialog.overlay.resize();
19455                         }
19456                 });
19457         },
19458
19459         _makeResizable: function(handles) {
19460                 handles = (handles === undefined ? this.options.resizable : handles);
19461                 var self = this,
19462                         options = self.options,
19463                         // .ui-resizable has position: relative defined in the stylesheet
19464                         // but dialogs have to use absolute or fixed positioning
19465                         position = self.uiDialog.css('position'),
19466                         resizeHandles = (typeof handles === 'string' ?
19467                                 handles :
19468                                 'n,e,s,w,se,sw,ne,nw'
19469                         );
19470
19471                 function filteredUi(ui) {
19472                         return {
19473                                 originalPosition: ui.originalPosition,
19474                                 originalSize: ui.originalSize,
19475                                 position: ui.position,
19476                                 size: ui.size
19477                         };
19478                 }
19479
19480                 self.uiDialog.resizable({
19481                         cancel: '.ui-dialog-content',
19482                         containment: 'document',
19483                         alsoResize: self.element,
19484                         maxWidth: options.maxWidth,
19485                         maxHeight: options.maxHeight,
19486                         minWidth: options.minWidth,
19487                         minHeight: self._minHeight(),
19488                         handles: resizeHandles,
19489                         start: function(event, ui) {
19490                                 $(this).addClass("ui-dialog-resizing");
19491                                 self._trigger('resizeStart', event, filteredUi(ui));
19492                         },
19493                         resize: function(event, ui) {
19494                                 self._trigger('resize', event, filteredUi(ui));
19495                         },
19496                         stop: function(event, ui) {
19497                                 $(this).removeClass("ui-dialog-resizing");
19498                                 options.height = $(this).height();
19499                                 options.width = $(this).width();
19500                                 self._trigger('resizeStop', event, filteredUi(ui));
19501                                 $.ui.dialog.overlay.resize();
19502                         }
19503                 })
19504                 .css('position', position)
19505                 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
19506         },
19507
19508         _minHeight: function() {
19509                 var options = this.options;
19510
19511                 if (options.height === 'auto') {
19512                         return options.minHeight;
19513                 } else {
19514                         return Math.min(options.minHeight, options.height);
19515                 }
19516         },
19517
19518         _position: function(position) {
19519                 var myAt = [],
19520                         offset = [0, 0],
19521                         isVisible;
19522
19523                 if (position) {
19524                         // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
19525         //              if (typeof position == 'string' || $.isArray(position)) {
19526         //                      myAt = $.isArray(position) ? position : position.split(' ');
19527
19528                         if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
19529                                 myAt = position.split ? position.split(' ') : [position[0], position[1]];
19530                                 if (myAt.length === 1) {
19531                                         myAt[1] = myAt[0];
19532                                 }
19533
19534                                 $.each(['left', 'top'], function(i, offsetPosition) {
19535                                         if (+myAt[i] === myAt[i]) {
19536                                                 offset[i] = myAt[i];
19537                                                 myAt[i] = offsetPosition;
19538                                         }
19539                                 });
19540
19541                                 position = {
19542                                         my: myAt.join(" "),
19543                                         at: myAt.join(" "),
19544                                         offset: offset.join(" ")
19545                                 };
19546                         } 
19547
19548                         position = $.extend({}, $.ui.dialog.prototype.options.position, position);
19549                 } else {
19550                         position = $.ui.dialog.prototype.options.position;
19551                 }
19552
19553                 // need to show the dialog to get the actual offset in the position plugin
19554                 isVisible = this.uiDialog.is(':visible');
19555                 if (!isVisible) {
19556                         this.uiDialog.show();
19557                 }
19558                 this.uiDialog
19559                         // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
19560                         .css({ top: 0, left: 0 })
19561                         .position($.extend({ of: window }, position));
19562                 if (!isVisible) {
19563                         this.uiDialog.hide();
19564                 }
19565         },
19566
19567         _setOptions: function( options ) {
19568                 var self = this,
19569                         resizableOptions = {},
19570                         resize = false;
19571
19572                 $.each( options, function( key, value ) {
19573                         self._setOption( key, value );
19574                         
19575                         if ( key in sizeRelatedOptions ) {
19576                                 resize = true;
19577                         }
19578                         if ( key in resizableRelatedOptions ) {
19579                                 resizableOptions[ key ] = value;
19580                         }
19581                 });
19582
19583                 if ( resize ) {
19584                         this._size();
19585                 }
19586                 if ( this.uiDialog.is( ":data(resizable)" ) ) {
19587                         this.uiDialog.resizable( "option", resizableOptions );
19588                 }
19589         },
19590
19591         _setOption: function(key, value){
19592                 var self = this,
19593                         uiDialog = self.uiDialog;
19594
19595                 switch (key) {
19596                         //handling of deprecated beforeclose (vs beforeClose) option
19597                         //Ticket #4669 http://dev.jqueryui.com/ticket/4669
19598                         //TODO: remove in 1.9pre
19599                         case "beforeclose":
19600                                 key = "beforeClose";
19601                                 break;
19602                         case "buttons":
19603                                 self._createButtons(value);
19604                                 break;
19605                         case "closeText":
19606                                 // ensure that we always pass a string
19607                                 self.uiDialogTitlebarCloseText.text("" + value);
19608                                 break;
19609                         case "dialogClass":
19610                                 uiDialog
19611                                         .removeClass(self.options.dialogClass)
19612                                         .addClass(uiDialogClasses + value);
19613                                 break;
19614                         case "disabled":
19615                                 if (value) {
19616                                         uiDialog.addClass('ui-dialog-disabled');
19617                                 } else {
19618                                         uiDialog.removeClass('ui-dialog-disabled');
19619                                 }
19620                                 break;
19621                         case "draggable":
19622                                 var isDraggable = uiDialog.is( ":data(draggable)" );
19623                                 if ( isDraggable && !value ) {
19624                                         uiDialog.draggable( "destroy" );
19625                                 }
19626                                 
19627                                 if ( !isDraggable && value ) {
19628                                         self._makeDraggable();
19629                                 }
19630                                 break;
19631                         case "position":
19632                                 self._position(value);
19633                                 break;
19634                         case "resizable":
19635                                 // currently resizable, becoming non-resizable
19636                                 var isResizable = uiDialog.is( ":data(resizable)" );
19637                                 if (isResizable && !value) {
19638                                         uiDialog.resizable('destroy');
19639                                 }
19640
19641                                 // currently resizable, changing handles
19642                                 if (isResizable && typeof value === 'string') {
19643                                         uiDialog.resizable('option', 'handles', value);
19644                                 }
19645
19646                                 // currently non-resizable, becoming resizable
19647                                 if (!isResizable && value !== false) {
19648                                         self._makeResizable(value);
19649                                 }
19650                                 break;
19651                         case "title":
19652                                 // convert whatever was passed in o a string, for html() to not throw up
19653                                 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
19654                                 break;
19655                 }
19656
19657                 $.Widget.prototype._setOption.apply(self, arguments);
19658         },
19659
19660         _size: function() {
19661                 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
19662                  * divs will both have width and height set, so we need to reset them
19663                  */
19664                 var options = this.options,
19665                         nonContentHeight,
19666                         minContentHeight,
19667                         isVisible = this.uiDialog.is( ":visible" );
19668
19669                 // reset content sizing
19670                 this.element.show().css({
19671                         width: 'auto',
19672                         minHeight: 0,
19673                         height: 0
19674                 });
19675
19676                 if (options.minWidth > options.width) {
19677                         options.width = options.minWidth;
19678                 }
19679
19680                 // reset wrapper sizing
19681                 // determine the height of all the non-content elements
19682                 nonContentHeight = this.uiDialog.css({
19683                                 height: 'auto',
19684                                 width: options.width
19685                         })
19686                         .height();
19687                 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
19688                 
19689                 if ( options.height === "auto" ) {
19690                         // only needed for IE6 support
19691                         if ( $.support.minHeight ) {
19692                                 this.element.css({
19693                                         minHeight: minContentHeight,
19694                                         height: "auto"
19695                                 });
19696                         } else {
19697                                 this.uiDialog.show();
19698                                 var autoHeight = this.element.css( "height", "auto" ).height();
19699                                 if ( !isVisible ) {
19700                                         this.uiDialog.hide();
19701                                 }
19702                                 this.element.height( Math.max( autoHeight, minContentHeight ) );
19703                         }
19704                 } else {
19705                         this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
19706                 }
19707
19708                 if (this.uiDialog.is(':data(resizable)')) {
19709                         this.uiDialog.resizable('option', 'minHeight', this._minHeight());
19710                 }
19711         }
19712 });
19713
19714 $.extend($.ui.dialog, {
19715         version: "1.8.16",
19716
19717         uuid: 0,
19718         maxZ: 0,
19719
19720         getTitleId: function($el) {
19721                 var id = $el.attr('id');
19722                 if (!id) {
19723                         this.uuid += 1;
19724                         id = this.uuid;
19725                 }
19726                 return 'ui-dialog-title-' + id;
19727         },
19728
19729         overlay: function(dialog) {
19730                 this.$el = $.ui.dialog.overlay.create(dialog);
19731         }
19732 });
19733
19734 $.extend($.ui.dialog.overlay, {
19735         instances: [],
19736         // reuse old instances due to IE memory leak with alpha transparency (see #5185)
19737         oldInstances: [],
19738         maxZ: 0,
19739         events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
19740                 function(event) { return event + '.dialog-overlay'; }).join(' '),
19741         create: function(dialog) {
19742                 if (this.instances.length === 0) {
19743                         // prevent use of anchors and inputs
19744                         // we use a setTimeout in case the overlay is created from an
19745                         // event that we're going to be cancelling (see #2804)
19746                         setTimeout(function() {
19747                                 // handle $(el).dialog().dialog('close') (see #4065)
19748                                 if ($.ui.dialog.overlay.instances.length) {
19749                                         $(document).bind($.ui.dialog.overlay.events, function(event) {
19750                                                 // stop events if the z-index of the target is < the z-index of the overlay
19751                                                 // we cannot return true when we don't want to cancel the event (#3523)
19752                                                 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
19753                                                         return false;
19754                                                 }
19755                                         });
19756                                 }
19757                         }, 1);
19758
19759                         // allow closing by pressing the escape key
19760                         $(document).bind('keydown.dialog-overlay', function(event) {
19761                                 if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
19762                                         event.keyCode === $.ui.keyCode.ESCAPE) {
19763                                         
19764                                         dialog.close(event);
19765                                         event.preventDefault();
19766                                 }
19767                         });
19768
19769                         // handle window resize
19770                         $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
19771                 }
19772
19773                 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
19774                         .appendTo(document.body)
19775                         .css({
19776                                 width: this.width(),
19777                                 height: this.height()
19778                         });
19779
19780                 if ($.fn.bgiframe) {
19781                         $el.bgiframe();
19782                 }
19783
19784                 this.instances.push($el);
19785                 return $el;
19786         },
19787
19788         destroy: function($el) {
19789                 var indexOf = $.inArray($el, this.instances);
19790                 if (indexOf != -1){
19791                         this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
19792                 }
19793
19794                 if (this.instances.length === 0) {
19795                         $([document, window]).unbind('.dialog-overlay');
19796                 }
19797
19798                 $el.remove();
19799                 
19800                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
19801                 var maxZ = 0;
19802                 $.each(this.instances, function() {
19803                         maxZ = Math.max(maxZ, this.css('z-index'));
19804                 });
19805                 this.maxZ = maxZ;
19806         },
19807
19808         height: function() {
19809                 var scrollHeight,
19810                         offsetHeight;
19811                 // handle IE 6
19812                 if ($.browser.msie && $.browser.version < 7) {
19813                         scrollHeight = Math.max(
19814                                 document.documentElement.scrollHeight,
19815                                 document.body.scrollHeight
19816                         );
19817                         offsetHeight = Math.max(
19818                                 document.documentElement.offsetHeight,
19819                                 document.body.offsetHeight
19820                         );
19821
19822                         if (scrollHeight < offsetHeight) {
19823                                 return $(window).height() + 'px';
19824                         } else {
19825                                 return scrollHeight + 'px';
19826                         }
19827                 // handle "good" browsers
19828                 } else {
19829                         return $(document).height() + 'px';
19830                 }
19831         },
19832
19833         width: function() {
19834                 var scrollWidth,
19835                         offsetWidth;
19836                 // handle IE
19837                 if ( $.browser.msie ) {
19838                         scrollWidth = Math.max(
19839                                 document.documentElement.scrollWidth,
19840                                 document.body.scrollWidth
19841                         );
19842                         offsetWidth = Math.max(
19843                                 document.documentElement.offsetWidth,
19844                                 document.body.offsetWidth
19845                         );
19846
19847                         if (scrollWidth < offsetWidth) {
19848                                 return $(window).width() + 'px';
19849                         } else {
19850                                 return scrollWidth + 'px';
19851                         }
19852                 // handle "good" browsers
19853                 } else {
19854                         return $(document).width() + 'px';
19855                 }
19856         },
19857
19858         resize: function() {
19859                 /* If the dialog is draggable and the user drags it past the
19860                  * right edge of the window, the document becomes wider so we
19861                  * need to stretch the overlay. If the user then drags the
19862                  * dialog back to the left, the document will become narrower,
19863                  * so we need to shrink the overlay to the appropriate size.
19864                  * This is handled by shrinking the overlay before setting it
19865                  * to the full document size.
19866                  */
19867                 var $overlays = $([]);
19868                 $.each($.ui.dialog.overlay.instances, function() {
19869                         $overlays = $overlays.add(this);
19870                 });
19871
19872                 $overlays.css({
19873                         width: 0,
19874                         height: 0
19875                 }).css({
19876                         width: $.ui.dialog.overlay.width(),
19877                         height: $.ui.dialog.overlay.height()
19878                 });
19879         }
19880 });
19881
19882 $.extend($.ui.dialog.overlay.prototype, {
19883         destroy: function() {
19884                 $.ui.dialog.overlay.destroy(this.$el);
19885         }
19886 });
19887
19888 }(jQuery));
19889 /*
19890  * jQuery UI Position 1.8.16
19891  *
19892  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
19893  * Dual licensed under the MIT or GPL Version 2 licenses.
19894  * http://jquery.org/license
19895  *
19896  * http://docs.jquery.com/UI/Position
19897  */
19898 (function( $, undefined ) {
19899
19900 $.ui = $.ui || {};
19901
19902 var horizontalPositions = /left|center|right/,
19903         verticalPositions = /top|center|bottom/,
19904         center = "center",
19905         _position = $.fn.position,
19906         _offset = $.fn.offset;
19907
19908 $.fn.position = function( options ) {
19909         if ( !options || !options.of ) {
19910                 return _position.apply( this, arguments );
19911         }
19912
19913         // make a copy, we don't want to modify arguments
19914         options = $.extend( {}, options );
19915
19916         var target = $( options.of ),
19917                 targetElem = target[0],
19918                 collision = ( options.collision || "flip" ).split( " " ),
19919                 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
19920                 targetWidth,
19921                 targetHeight,
19922                 basePosition;
19923
19924         if ( targetElem.nodeType === 9 ) {
19925                 targetWidth = target.width();
19926                 targetHeight = target.height();
19927                 basePosition = { top: 0, left: 0 };
19928         // TODO: use $.isWindow() in 1.9
19929         } else if ( targetElem.setTimeout ) {
19930                 targetWidth = target.width();
19931                 targetHeight = target.height();
19932                 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
19933         } else if ( targetElem.preventDefault ) {
19934                 // force left top to allow flipping
19935                 options.at = "left top";
19936                 targetWidth = targetHeight = 0;
19937                 basePosition = { top: options.of.pageY, left: options.of.pageX };
19938         } else {
19939                 targetWidth = target.outerWidth();
19940                 targetHeight = target.outerHeight();
19941                 basePosition = target.offset();
19942         }
19943
19944         // force my and at to have valid horizontal and veritcal positions
19945         // if a value is missing or invalid, it will be converted to center 
19946         $.each( [ "my", "at" ], function() {
19947                 var pos = ( options[this] || "" ).split( " " );
19948                 if ( pos.length === 1) {
19949                         pos = horizontalPositions.test( pos[0] ) ?
19950                                 pos.concat( [center] ) :
19951                                 verticalPositions.test( pos[0] ) ?
19952                                         [ center ].concat( pos ) :
19953                                         [ center, center ];
19954                 }
19955                 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
19956                 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
19957                 options[ this ] = pos;
19958         });
19959
19960         // normalize collision option
19961         if ( collision.length === 1 ) {
19962                 collision[ 1 ] = collision[ 0 ];
19963         }
19964
19965         // normalize offset option
19966         offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
19967         if ( offset.length === 1 ) {
19968                 offset[ 1 ] = offset[ 0 ];
19969         }
19970         offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
19971
19972         if ( options.at[0] === "right" ) {
19973                 basePosition.left += targetWidth;
19974         } else if ( options.at[0] === center ) {
19975                 basePosition.left += targetWidth / 2;
19976         }
19977
19978         if ( options.at[1] === "bottom" ) {
19979                 basePosition.top += targetHeight;
19980         } else if ( options.at[1] === center ) {
19981                 basePosition.top += targetHeight / 2;
19982         }
19983
19984         basePosition.left += offset[ 0 ];
19985         basePosition.top += offset[ 1 ];
19986
19987         return this.each(function() {
19988                 var elem = $( this ),
19989                         elemWidth = elem.outerWidth(),
19990                         elemHeight = elem.outerHeight(),
19991                         marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
19992                         marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
19993                         collisionWidth = elemWidth + marginLeft +
19994                                 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
19995                         collisionHeight = elemHeight + marginTop +
19996                                 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
19997                         position = $.extend( {}, basePosition ),
19998                         collisionPosition;
19999
20000                 if ( options.my[0] === "right" ) {
20001                         position.left -= elemWidth;
20002                 } else if ( options.my[0] === center ) {
20003                         position.left -= elemWidth / 2;
20004                 }
20005
20006                 if ( options.my[1] === "bottom" ) {
20007                         position.top -= elemHeight;
20008                 } else if ( options.my[1] === center ) {
20009                         position.top -= elemHeight / 2;
20010                 }
20011
20012                 // prevent fractions (see #5280)
20013                 position.left = Math.round( position.left );
20014                 position.top = Math.round( position.top );
20015
20016                 collisionPosition = {
20017                         left: position.left - marginLeft,
20018                         top: position.top - marginTop
20019                 };
20020
20021                 $.each( [ "left", "top" ], function( i, dir ) {
20022                         if ( $.ui.position[ collision[i] ] ) {
20023                                 $.ui.position[ collision[i] ][ dir ]( position, {
20024                                         targetWidth: targetWidth,
20025                                         targetHeight: targetHeight,
20026                                         elemWidth: elemWidth,
20027                                         elemHeight: elemHeight,
20028                                         collisionPosition: collisionPosition,
20029                                         collisionWidth: collisionWidth,
20030                                         collisionHeight: collisionHeight,
20031                                         offset: offset,
20032                                         my: options.my,
20033                                         at: options.at
20034                                 });
20035                         }
20036                 });
20037
20038                 if ( $.fn.bgiframe ) {
20039                         elem.bgiframe();
20040                 }
20041                 elem.offset( $.extend( position, { using: options.using } ) );
20042         });
20043 };
20044
20045 $.ui.position = {
20046         fit: {
20047                 left: function( position, data ) {
20048                         var win = $( window ),
20049                                 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
20050                         position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
20051                 },
20052                 top: function( position, data ) {
20053                         var win = $( window ),
20054                                 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
20055                         position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
20056                 }
20057         },
20058
20059         flip: {
20060                 left: function( position, data ) {
20061                         if ( data.at[0] === center ) {
20062                                 return;
20063                         }
20064                         var win = $( window ),
20065                                 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
20066                                 myOffset = data.my[ 0 ] === "left" ?
20067                                         -data.elemWidth :
20068                                         data.my[ 0 ] === "right" ?
20069                                                 data.elemWidth :
20070                                                 0,
20071                                 atOffset = data.at[ 0 ] === "left" ?
20072                                         data.targetWidth :
20073                                         -data.targetWidth,
20074                                 offset = -2 * data.offset[ 0 ];
20075                         position.left += data.collisionPosition.left < 0 ?
20076                                 myOffset + atOffset + offset :
20077                                 over > 0 ?
20078                                         myOffset + atOffset + offset :
20079                                         0;
20080                 },
20081                 top: function( position, data ) {
20082                         if ( data.at[1] === center ) {
20083                                 return;
20084                         }
20085                         var win = $( window ),
20086                                 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
20087                                 myOffset = data.my[ 1 ] === "top" ?
20088                                         -data.elemHeight :
20089                                         data.my[ 1 ] === "bottom" ?
20090                                                 data.elemHeight :
20091                                                 0,
20092                                 atOffset = data.at[ 1 ] === "top" ?
20093                                         data.targetHeight :
20094                                         -data.targetHeight,
20095                                 offset = -2 * data.offset[ 1 ];
20096                         position.top += data.collisionPosition.top < 0 ?
20097                                 myOffset + atOffset + offset :
20098                                 over > 0 ?
20099                                         myOffset + atOffset + offset :
20100                                         0;
20101                 }
20102         }
20103 };
20104
20105 // offset setter from jQuery 1.4
20106 if ( !$.offset.setOffset ) {
20107         $.offset.setOffset = function( elem, options ) {
20108                 // set position first, in-case top/left are set even on static elem
20109                 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
20110                         elem.style.position = "relative";
20111                 }
20112                 var curElem   = $( elem ),
20113                         curOffset = curElem.offset(),
20114                         curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
20115                         curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
20116                         props     = {
20117                                 top:  (options.top  - curOffset.top)  + curTop,
20118                                 left: (options.left - curOffset.left) + curLeft
20119                         };
20120                 
20121                 if ( 'using' in options ) {
20122                         options.using.call( elem, props );
20123                 } else {
20124                         curElem.css( props );
20125                 }
20126         };
20127
20128         $.fn.offset = function( options ) {
20129                 var elem = this[ 0 ];
20130                 if ( !elem || !elem.ownerDocument ) { return null; }
20131                 if ( options ) { 
20132                         return this.each(function() {
20133                                 $.offset.setOffset( this, options );
20134                         });
20135                 }
20136                 return _offset.call( this );
20137         };
20138 }
20139
20140 }( jQuery ));
20141 /*
20142  * jQuery UI Progressbar 1.8.16
20143  *
20144  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
20145  * Dual licensed under the MIT or GPL Version 2 licenses.
20146  * http://jquery.org/license
20147  *
20148  * http://docs.jquery.com/UI/Progressbar
20149  *
20150  * Depends:
20151  *   jquery.ui.core.js
20152  *   jquery.ui.widget.js
20153  */
20154 (function( $, undefined ) {
20155
20156 $.widget( "ui.progressbar", {
20157         options: {
20158                 value: 0,
20159                 max: 100
20160         },
20161
20162         min: 0,
20163
20164         _create: function() {
20165                 this.element
20166                         .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
20167                         .attr({
20168                                 role: "progressbar",
20169                                 "aria-valuemin": this.min,
20170                                 "aria-valuemax": this.options.max,
20171                                 "aria-valuenow": this._value()
20172                         });
20173
20174                 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
20175                         .appendTo( this.element );
20176
20177                 this.oldValue = this._value();
20178                 this._refreshValue();
20179         },
20180
20181         destroy: function() {
20182                 this.element
20183                         .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
20184                         .removeAttr( "role" )
20185                         .removeAttr( "aria-valuemin" )
20186                         .removeAttr( "aria-valuemax" )
20187                         .removeAttr( "aria-valuenow" );
20188
20189                 this.valueDiv.remove();
20190
20191                 $.Widget.prototype.destroy.apply( this, arguments );
20192         },
20193
20194         value: function( newValue ) {
20195                 if ( newValue === undefined ) {
20196                         return this._value();
20197                 }
20198
20199                 this._setOption( "value", newValue );
20200                 return this;
20201         },
20202
20203         _setOption: function( key, value ) {
20204                 if ( key === "value" ) {
20205                         this.options.value = value;
20206                         this._refreshValue();
20207                         if ( this._value() === this.options.max ) {
20208                                 this._trigger( "complete" );
20209                         }
20210                 }
20211
20212                 $.Widget.prototype._setOption.apply( this, arguments );
20213         },
20214
20215         _value: function() {
20216                 var val = this.options.value;
20217                 // normalize invalid value
20218                 if ( typeof val !== "number" ) {
20219                         val = 0;
20220                 }
20221                 return Math.min( this.options.max, Math.max( this.min, val ) );
20222         },
20223
20224         _percentage: function() {
20225                 return 100 * this._value() / this.options.max;
20226         },
20227
20228         _refreshValue: function() {
20229                 var value = this.value();
20230                 var percentage = this._percentage();
20231
20232                 if ( this.oldValue !== value ) {
20233                         this.oldValue = value;
20234                         this._trigger( "change" );
20235                 }
20236
20237                 this.valueDiv
20238                         .toggle( value > this.min )
20239                         .toggleClass( "ui-corner-right", value === this.options.max )
20240                         .width( percentage.toFixed(0) + "%" );
20241                 this.element.attr( "aria-valuenow", value );
20242         }
20243 });
20244
20245 $.extend( $.ui.progressbar, {
20246         version: "1.8.16"
20247 });
20248
20249 })( jQuery );
20250 /*
20251  * jQuery UI Slider 1.8.16
20252  *
20253  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
20254  * Dual licensed under the MIT or GPL Version 2 licenses.
20255  * http://jquery.org/license
20256  *
20257  * http://docs.jquery.com/UI/Slider
20258  *
20259  * Depends:
20260  *      jquery.ui.core.js
20261  *      jquery.ui.mouse.js
20262  *      jquery.ui.widget.js
20263  */
20264 (function( $, undefined ) {
20265
20266 // number of pages in a slider
20267 // (how many times can you page up/down to go through the whole range)
20268 var numPages = 5;
20269
20270 $.widget( "ui.slider", $.ui.mouse, {
20271
20272         widgetEventPrefix: "slide",
20273
20274         options: {
20275                 animate: false,
20276                 distance: 0,
20277                 max: 100,
20278                 min: 0,
20279                 orientation: "horizontal",
20280                 range: false,
20281                 step: 1,
20282                 value: 0,
20283                 values: null
20284         },
20285
20286         _create: function() {
20287                 var self = this,
20288                         o = this.options,
20289                         existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
20290                         handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
20291                         handleCount = ( o.values && o.values.length ) || 1,
20292                         handles = [];
20293
20294                 this._keySliding = false;
20295                 this._mouseSliding = false;
20296                 this._animateOff = true;
20297                 this._handleIndex = null;
20298                 this._detectOrientation();
20299                 this._mouseInit();
20300
20301                 this.element
20302                         .addClass( "ui-slider" +
20303                                 " ui-slider-" + this.orientation +
20304                                 " ui-widget" +
20305                                 " ui-widget-content" +
20306                                 " ui-corner-all" +
20307                                 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
20308
20309                 this.range = $([]);
20310
20311                 if ( o.range ) {
20312                         if ( o.range === true ) {
20313                                 if ( !o.values ) {
20314                                         o.values = [ this._valueMin(), this._valueMin() ];
20315                                 }
20316                                 if ( o.values.length && o.values.length !== 2 ) {
20317                                         o.values = [ o.values[0], o.values[0] ];
20318                                 }
20319                         }
20320
20321                         this.range = $( "<div></div>" )
20322                                 .appendTo( this.element )
20323                                 .addClass( "ui-slider-range" +
20324                                 // note: this isn't the most fittingly semantic framework class for this element,
20325                                 // but worked best visually with a variety of themes
20326                                 " ui-widget-header" + 
20327                                 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
20328                 }
20329
20330                 for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
20331                         handles.push( handle );
20332                 }
20333
20334                 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
20335
20336                 this.handle = this.handles.eq( 0 );
20337
20338                 this.handles.add( this.range ).filter( "a" )
20339                         .click(function( event ) {
20340                                 event.preventDefault();
20341                         })
20342                         .hover(function() {
20343                                 if ( !o.disabled ) {
20344                                         $( this ).addClass( "ui-state-hover" );
20345                                 }
20346                         }, function() {
20347                                 $( this ).removeClass( "ui-state-hover" );
20348                         })
20349                         .focus(function() {
20350                                 if ( !o.disabled ) {
20351                                         $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
20352                                         $( this ).addClass( "ui-state-focus" );
20353                                 } else {
20354                                         $( this ).blur();
20355                                 }
20356                         })
20357                         .blur(function() {
20358                                 $( this ).removeClass( "ui-state-focus" );
20359                         });
20360
20361                 this.handles.each(function( i ) {
20362                         $( this ).data( "index.ui-slider-handle", i );
20363                 });
20364
20365                 this.handles
20366                         .keydown(function( event ) {
20367                                 var ret = true,
20368                                         index = $( this ).data( "index.ui-slider-handle" ),
20369                                         allowed,
20370                                         curVal,
20371                                         newVal,
20372                                         step;
20373         
20374                                 if ( self.options.disabled ) {
20375                                         return;
20376                                 }
20377         
20378                                 switch ( event.keyCode ) {
20379                                         case $.ui.keyCode.HOME:
20380                                         case $.ui.keyCode.END:
20381                                         case $.ui.keyCode.PAGE_UP:
20382                                         case $.ui.keyCode.PAGE_DOWN:
20383                                         case $.ui.keyCode.UP:
20384                                         case $.ui.keyCode.RIGHT:
20385                                         case $.ui.keyCode.DOWN:
20386                                         case $.ui.keyCode.LEFT:
20387                                                 ret = false;
20388                                                 if ( !self._keySliding ) {
20389                                                         self._keySliding = true;
20390                                                         $( this ).addClass( "ui-state-active" );
20391                                                         allowed = self._start( event, index );
20392                                                         if ( allowed === false ) {
20393                                                                 return;
20394                                                         }
20395                                                 }
20396                                                 break;
20397                                 }
20398         
20399                                 step = self.options.step;
20400                                 if ( self.options.values && self.options.values.length ) {
20401                                         curVal = newVal = self.values( index );
20402                                 } else {
20403                                         curVal = newVal = self.value();
20404                                 }
20405         
20406                                 switch ( event.keyCode ) {
20407                                         case $.ui.keyCode.HOME:
20408                                                 newVal = self._valueMin();
20409                                                 break;
20410                                         case $.ui.keyCode.END:
20411                                                 newVal = self._valueMax();
20412                                                 break;
20413                                         case $.ui.keyCode.PAGE_UP:
20414                                                 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
20415                                                 break;
20416                                         case $.ui.keyCode.PAGE_DOWN:
20417                                                 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
20418                                                 break;
20419                                         case $.ui.keyCode.UP:
20420                                         case $.ui.keyCode.RIGHT:
20421                                                 if ( curVal === self._valueMax() ) {
20422                                                         return;
20423                                                 }
20424                                                 newVal = self._trimAlignValue( curVal + step );
20425                                                 break;
20426                                         case $.ui.keyCode.DOWN:
20427                                         case $.ui.keyCode.LEFT:
20428                                                 if ( curVal === self._valueMin() ) {
20429                                                         return;
20430                                                 }
20431                                                 newVal = self._trimAlignValue( curVal - step );
20432                                                 break;
20433                                 }
20434         
20435                                 self._slide( event, index, newVal );
20436         
20437                                 return ret;
20438         
20439                         })
20440                         .keyup(function( event ) {
20441                                 var index = $( this ).data( "index.ui-slider-handle" );
20442         
20443                                 if ( self._keySliding ) {
20444                                         self._keySliding = false;
20445                                         self._stop( event, index );
20446                                         self._change( event, index );
20447                                         $( this ).removeClass( "ui-state-active" );
20448                                 }
20449         
20450                         });
20451
20452                 this._refreshValue();
20453
20454                 this._animateOff = false;
20455         },
20456
20457         destroy: function() {
20458                 this.handles.remove();
20459                 this.range.remove();
20460
20461                 this.element
20462                         .removeClass( "ui-slider" +
20463                                 " ui-slider-horizontal" +
20464                                 " ui-slider-vertical" +
20465                                 " ui-slider-disabled" +
20466                                 " ui-widget" +
20467                                 " ui-widget-content" +
20468                                 " ui-corner-all" )
20469                         .removeData( "slider" )
20470                         .unbind( ".slider" );
20471
20472                 this._mouseDestroy();
20473
20474                 return this;
20475         },
20476
20477         _mouseCapture: function( event ) {
20478                 var o = this.options,
20479                         position,
20480                         normValue,
20481                         distance,
20482                         closestHandle,
20483                         self,
20484                         index,
20485                         allowed,
20486                         offset,
20487                         mouseOverHandle;
20488
20489                 if ( o.disabled ) {
20490                         return false;
20491                 }
20492
20493                 this.elementSize = {
20494                         width: this.element.outerWidth(),
20495                         height: this.element.outerHeight()
20496                 };
20497                 this.elementOffset = this.element.offset();
20498
20499                 position = { x: event.pageX, y: event.pageY };
20500                 normValue = this._normValueFromMouse( position );
20501                 distance = this._valueMax() - this._valueMin() + 1;
20502                 self = this;
20503                 this.handles.each(function( i ) {
20504                         var thisDistance = Math.abs( normValue - self.values(i) );
20505                         if ( distance > thisDistance ) {
20506                                 distance = thisDistance;
20507                                 closestHandle = $( this );
20508                                 index = i;
20509                         }
20510                 });
20511
20512                 // workaround for bug #3736 (if both handles of a range are at 0,
20513                 // the first is always used as the one with least distance,
20514                 // and moving it is obviously prevented by preventing negative ranges)
20515                 if( o.range === true && this.values(1) === o.min ) {
20516                         index += 1;
20517                         closestHandle = $( this.handles[index] );
20518                 }
20519
20520                 allowed = this._start( event, index );
20521                 if ( allowed === false ) {
20522                         return false;
20523                 }
20524                 this._mouseSliding = true;
20525
20526                 self._handleIndex = index;
20527
20528                 closestHandle
20529                         .addClass( "ui-state-active" )
20530                         .focus();
20531                 
20532                 offset = closestHandle.offset();
20533                 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
20534                 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
20535                         left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
20536                         top: event.pageY - offset.top -
20537                                 ( closestHandle.height() / 2 ) -
20538                                 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
20539                                 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
20540                                 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
20541                 };
20542
20543                 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
20544                         this._slide( event, index, normValue );
20545                 }
20546                 this._animateOff = true;
20547                 return true;
20548         },
20549
20550         _mouseStart: function( event ) {
20551                 return true;
20552         },
20553
20554         _mouseDrag: function( event ) {
20555                 var position = { x: event.pageX, y: event.pageY },
20556                         normValue = this._normValueFromMouse( position );
20557                 
20558                 this._slide( event, this._handleIndex, normValue );
20559
20560                 return false;
20561         },
20562
20563         _mouseStop: function( event ) {
20564                 this.handles.removeClass( "ui-state-active" );
20565                 this._mouseSliding = false;
20566
20567                 this._stop( event, this._handleIndex );
20568                 this._change( event, this._handleIndex );
20569
20570                 this._handleIndex = null;
20571                 this._clickOffset = null;
20572                 this._animateOff = false;
20573
20574                 return false;
20575         },
20576         
20577         _detectOrientation: function() {
20578                 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
20579         },
20580
20581         _normValueFromMouse: function( position ) {
20582                 var pixelTotal,
20583                         pixelMouse,
20584                         percentMouse,
20585                         valueTotal,
20586                         valueMouse;
20587
20588                 if ( this.orientation === "horizontal" ) {
20589                         pixelTotal = this.elementSize.width;
20590                         pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
20591                 } else {
20592                         pixelTotal = this.elementSize.height;
20593                         pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
20594                 }
20595
20596                 percentMouse = ( pixelMouse / pixelTotal );
20597                 if ( percentMouse > 1 ) {
20598                         percentMouse = 1;
20599                 }
20600                 if ( percentMouse < 0 ) {
20601                         percentMouse = 0;
20602                 }
20603                 if ( this.orientation === "vertical" ) {
20604                         percentMouse = 1 - percentMouse;
20605                 }
20606
20607                 valueTotal = this._valueMax() - this._valueMin();
20608                 valueMouse = this._valueMin() + percentMouse * valueTotal;
20609
20610                 return this._trimAlignValue( valueMouse );
20611         },
20612
20613         _start: function( event, index ) {
20614                 var uiHash = {
20615                         handle: this.handles[ index ],
20616                         value: this.value()
20617                 };
20618                 if ( this.options.values && this.options.values.length ) {
20619                         uiHash.value = this.values( index );
20620                         uiHash.values = this.values();
20621                 }
20622                 return this._trigger( "start", event, uiHash );
20623         },
20624
20625         _slide: function( event, index, newVal ) {
20626                 var otherVal,
20627                         newValues,
20628                         allowed;
20629
20630                 if ( this.options.values && this.options.values.length ) {
20631                         otherVal = this.values( index ? 0 : 1 );
20632
20633                         if ( ( this.options.values.length === 2 && this.options.range === true ) && 
20634                                         ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
20635                                 ) {
20636                                 newVal = otherVal;
20637                         }
20638
20639                         if ( newVal !== this.values( index ) ) {
20640                                 newValues = this.values();
20641                                 newValues[ index ] = newVal;
20642                                 // A slide can be canceled by returning false from the slide callback
20643                                 allowed = this._trigger( "slide", event, {
20644                                         handle: this.handles[ index ],
20645                                         value: newVal,
20646                                         values: newValues
20647                                 } );
20648                                 otherVal = this.values( index ? 0 : 1 );
20649                                 if ( allowed !== false ) {
20650                                         this.values( index, newVal, true );
20651                                 }
20652                         }
20653                 } else {
20654                         if ( newVal !== this.value() ) {
20655                                 // A slide can be canceled by returning false from the slide callback
20656                                 allowed = this._trigger( "slide", event, {
20657                                         handle: this.handles[ index ],
20658                                         value: newVal
20659                                 } );
20660                                 if ( allowed !== false ) {
20661                                         this.value( newVal );
20662                                 }
20663                         }
20664                 }
20665         },
20666
20667         _stop: function( event, index ) {
20668                 var uiHash = {
20669                         handle: this.handles[ index ],
20670                         value: this.value()
20671                 };
20672                 if ( this.options.values && this.options.values.length ) {
20673                         uiHash.value = this.values( index );
20674                         uiHash.values = this.values();
20675                 }
20676
20677                 this._trigger( "stop", event, uiHash );
20678         },
20679
20680         _change: function( event, index ) {
20681                 if ( !this._keySliding && !this._mouseSliding ) {
20682                         var uiHash = {
20683                                 handle: this.handles[ index ],
20684                                 value: this.value()
20685                         };
20686                         if ( this.options.values && this.options.values.length ) {
20687                                 uiHash.value = this.values( index );
20688                                 uiHash.values = this.values();
20689                         }
20690
20691                         this._trigger( "change", event, uiHash );
20692                 }
20693         },
20694
20695         value: function( newValue ) {
20696                 if ( arguments.length ) {
20697                         this.options.value = this._trimAlignValue( newValue );
20698                         this._refreshValue();
20699                         this._change( null, 0 );
20700                         return;
20701                 }
20702
20703                 return this._value();
20704         },
20705
20706         values: function( index, newValue ) {
20707                 var vals,
20708                         newValues,
20709                         i;
20710
20711                 if ( arguments.length > 1 ) {
20712                         this.options.values[ index ] = this._trimAlignValue( newValue );
20713                         this._refreshValue();
20714                         this._change( null, index );
20715                         return;
20716                 }
20717
20718                 if ( arguments.length ) {
20719                         if ( $.isArray( arguments[ 0 ] ) ) {
20720                                 vals = this.options.values;
20721                                 newValues = arguments[ 0 ];
20722                                 for ( i = 0; i < vals.length; i += 1 ) {
20723                                         vals[ i ] = this._trimAlignValue( newValues[ i ] );
20724                                         this._change( null, i );
20725                                 }
20726                                 this._refreshValue();
20727                         } else {
20728                                 if ( this.options.values && this.options.values.length ) {
20729                                         return this._values( index );
20730                                 } else {
20731                                         return this.value();
20732                                 }
20733                         }
20734                 } else {
20735                         return this._values();
20736                 }
20737         },
20738
20739         _setOption: function( key, value ) {
20740                 var i,
20741                         valsLength = 0;
20742
20743                 if ( $.isArray( this.options.values ) ) {
20744                         valsLength = this.options.values.length;
20745                 }
20746
20747                 $.Widget.prototype._setOption.apply( this, arguments );
20748
20749                 switch ( key ) {
20750                         case "disabled":
20751                                 if ( value ) {
20752                                         this.handles.filter( ".ui-state-focus" ).blur();
20753                                         this.handles.removeClass( "ui-state-hover" );
20754                                         this.handles.propAttr( "disabled", true );
20755                                         this.element.addClass( "ui-disabled" );
20756                                 } else {
20757                                         this.handles.propAttr( "disabled", false );
20758                                         this.element.removeClass( "ui-disabled" );
20759                                 }
20760                                 break;
20761                         case "orientation":
20762                                 this._detectOrientation();
20763                                 this.element
20764                                         .removeClass( "ui-slider-horizontal ui-slider-vertical" )
20765                                         .addClass( "ui-slider-" + this.orientation );
20766                                 this._refreshValue();
20767                                 break;
20768                         case "value":
20769                                 this._animateOff = true;
20770                                 this._refreshValue();
20771                                 this._change( null, 0 );
20772                                 this._animateOff = false;
20773                                 break;
20774                         case "values":
20775                                 this._animateOff = true;
20776                                 this._refreshValue();
20777                                 for ( i = 0; i < valsLength; i += 1 ) {
20778                                         this._change( null, i );
20779                                 }
20780                                 this._animateOff = false;
20781                                 break;
20782                 }
20783         },
20784
20785         //internal value getter
20786         // _value() returns value trimmed by min and max, aligned by step
20787         _value: function() {
20788                 var val = this.options.value;
20789                 val = this._trimAlignValue( val );
20790
20791                 return val;
20792         },
20793
20794         //internal values getter
20795         // _values() returns array of values trimmed by min and max, aligned by step
20796         // _values( index ) returns single value trimmed by min and max, aligned by step
20797         _values: function( index ) {
20798                 var val,
20799                         vals,
20800                         i;
20801
20802                 if ( arguments.length ) {
20803                         val = this.options.values[ index ];
20804                         val = this._trimAlignValue( val );
20805
20806                         return val;
20807                 } else {
20808                         // .slice() creates a copy of the array
20809                         // this copy gets trimmed by min and max and then returned
20810                         vals = this.options.values.slice();
20811                         for ( i = 0; i < vals.length; i+= 1) {
20812                                 vals[ i ] = this._trimAlignValue( vals[ i ] );
20813                         }
20814
20815                         return vals;
20816                 }
20817         },
20818         
20819         // returns the step-aligned value that val is closest to, between (inclusive) min and max
20820         _trimAlignValue: function( val ) {
20821                 if ( val <= this._valueMin() ) {
20822                         return this._valueMin();
20823                 }
20824                 if ( val >= this._valueMax() ) {
20825                         return this._valueMax();
20826                 }
20827                 var step = ( this.options.step > 0 ) ? this.options.step : 1,
20828                         valModStep = (val - this._valueMin()) % step,
20829                         alignValue = val - valModStep;
20830
20831                 if ( Math.abs(valModStep) * 2 >= step ) {
20832                         alignValue += ( valModStep > 0 ) ? step : ( -step );
20833                 }
20834
20835                 // Since JavaScript has problems with large floats, round
20836                 // the final value to 5 digits after the decimal point (see #4124)
20837                 return parseFloat( alignValue.toFixed(5) );
20838         },
20839
20840         _valueMin: function() {
20841                 return this.options.min;
20842         },
20843
20844         _valueMax: function() {
20845                 return this.options.max;
20846         },
20847         
20848         _refreshValue: function() {
20849                 var oRange = this.options.range,
20850                         o = this.options,
20851                         self = this,
20852                         animate = ( !this._animateOff ) ? o.animate : false,
20853                         valPercent,
20854                         _set = {},
20855                         lastValPercent,
20856                         value,
20857                         valueMin,
20858                         valueMax;
20859
20860                 if ( this.options.values && this.options.values.length ) {
20861                         this.handles.each(function( i, j ) {
20862                                 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
20863                                 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
20864                                 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
20865                                 if ( self.options.range === true ) {
20866                                         if ( self.orientation === "horizontal" ) {
20867                                                 if ( i === 0 ) {
20868                                                         self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
20869                                                 }
20870                                                 if ( i === 1 ) {
20871                                                         self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
20872                                                 }
20873                                         } else {
20874                                                 if ( i === 0 ) {
20875                                                         self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
20876                                                 }
20877                                                 if ( i === 1 ) {
20878                                                         self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
20879                                                 }
20880                                         }
20881                                 }
20882                                 lastValPercent = valPercent;
20883                         });
20884                 } else {
20885                         value = this.value();
20886                         valueMin = this._valueMin();
20887                         valueMax = this._valueMax();
20888                         valPercent = ( valueMax !== valueMin ) ?
20889                                         ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
20890                                         0;
20891                         _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
20892                         this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
20893
20894                         if ( oRange === "min" && this.orientation === "horizontal" ) {
20895                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
20896                         }
20897                         if ( oRange === "max" && this.orientation === "horizontal" ) {
20898                                 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
20899                         }
20900                         if ( oRange === "min" && this.orientation === "vertical" ) {
20901                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
20902                         }
20903                         if ( oRange === "max" && this.orientation === "vertical" ) {
20904                                 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
20905                         }
20906                 }
20907         }
20908
20909 });
20910
20911 $.extend( $.ui.slider, {
20912         version: "1.8.16"
20913 });
20914
20915 }(jQuery));
20916 /*
20917  * jQuery UI Tabs 1.8.16
20918  *
20919  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
20920  * Dual licensed under the MIT or GPL Version 2 licenses.
20921  * http://jquery.org/license
20922  *
20923  * http://docs.jquery.com/UI/Tabs
20924  *
20925  * Depends:
20926  *      jquery.ui.core.js
20927  *      jquery.ui.widget.js
20928  */
20929 (function( $, undefined ) {
20930
20931 var tabId = 0,
20932         listId = 0;
20933
20934 function getNextTabId() {
20935         return ++tabId;
20936 }
20937
20938 function getNextListId() {
20939         return ++listId;
20940 }
20941
20942 $.widget( "ui.tabs", {
20943         options: {
20944                 add: null,
20945                 ajaxOptions: null,
20946                 cache: false,
20947                 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
20948                 collapsible: false,
20949                 disable: null,
20950                 disabled: [],
20951                 enable: null,
20952                 event: "click",
20953                 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
20954                 idPrefix: "ui-tabs-",
20955                 load: null,
20956                 panelTemplate: "<div></div>",
20957                 remove: null,
20958                 select: null,
20959                 show: null,
20960                 spinner: "<em>Loading&#8230;</em>",
20961                 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
20962         },
20963
20964         _create: function() {
20965                 this._tabify( true );
20966         },
20967
20968         _setOption: function( key, value ) {
20969                 if ( key == "selected" ) {
20970                         if (this.options.collapsible && value == this.options.selected ) {
20971                                 return;
20972                         }
20973                         this.select( value );
20974                 } else {
20975                         this.options[ key ] = value;
20976                         this._tabify();
20977                 }
20978         },
20979
20980         _tabId: function( a ) {
20981                 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
20982                         this.options.idPrefix + getNextTabId();
20983         },
20984
20985         _sanitizeSelector: function( hash ) {
20986                 // we need this because an id may contain a ":"
20987                 return hash.replace( /:/g, "\\:" );
20988         },
20989
20990         _cookie: function() {
20991                 var cookie = this.cookie ||
20992                         ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
20993                 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
20994         },
20995
20996         _ui: function( tab, panel ) {
20997                 return {
20998                         tab: tab,
20999                         panel: panel,
21000                         index: this.anchors.index( tab )
21001                 };
21002         },
21003
21004         _cleanup: function() {
21005                 // restore all former loading tabs labels
21006                 this.lis.filter( ".ui-state-processing" )
21007                         .removeClass( "ui-state-processing" )
21008                         .find( "span:data(label.tabs)" )
21009                                 .each(function() {
21010                                         var el = $( this );
21011                                         el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
21012                                 });
21013         },
21014
21015         _tabify: function( init ) {
21016                 var self = this,
21017                         o = this.options,
21018                         fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
21019
21020                 this.list = this.element.find( "ol,ul" ).eq( 0 );
21021                 this.lis = $( " > li:has(a[href])", this.list );
21022                 this.anchors = this.lis.map(function() {
21023                         return $( "a", this )[ 0 ];
21024                 });
21025                 this.panels = $( [] );
21026
21027                 this.anchors.each(function( i, a ) {
21028                         var href = $( a ).attr( "href" );
21029                         // For dynamically created HTML that contains a hash as href IE < 8 expands
21030                         // such href to the full page url with hash and then misinterprets tab as ajax.
21031                         // Same consideration applies for an added tab with a fragment identifier
21032                         // since a[href=#fragment-identifier] does unexpectedly not match.
21033                         // Thus normalize href attribute...
21034                         var hrefBase = href.split( "#" )[ 0 ],
21035                                 baseEl;
21036                         if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
21037                                         ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
21038                                 href = a.hash;
21039                                 a.href = href;
21040                         }
21041
21042                         // inline tab
21043                         if ( fragmentId.test( href ) ) {
21044                                 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
21045                         // remote tab
21046                         // prevent loading the page itself if href is just "#"
21047                         } else if ( href && href !== "#" ) {
21048                                 // required for restore on destroy
21049                                 $.data( a, "href.tabs", href );
21050
21051                                 // TODO until #3808 is fixed strip fragment identifier from url
21052                                 // (IE fails to load from such url)
21053                                 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
21054
21055                                 var id = self._tabId( a );
21056                                 a.href = "#" + id;
21057                                 var $panel = self.element.find( "#" + id );
21058                                 if ( !$panel.length ) {
21059                                         $panel = $( o.panelTemplate )
21060                                                 .attr( "id", id )
21061                                                 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
21062                                                 .insertAfter( self.panels[ i - 1 ] || self.list );
21063                                         $panel.data( "destroy.tabs", true );
21064                                 }
21065                                 self.panels = self.panels.add( $panel );
21066                         // invalid tab href
21067                         } else {
21068                                 o.disabled.push( i );
21069                         }
21070                 });
21071
21072                 // initialization from scratch
21073                 if ( init ) {
21074                         // attach necessary classes for styling
21075                         this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
21076                         this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
21077                         this.lis.addClass( "ui-state-default ui-corner-top" );
21078                         this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
21079
21080                         // Selected tab
21081                         // use "selected" option or try to retrieve:
21082                         // 1. from fragment identifier in url
21083                         // 2. from cookie
21084                         // 3. from selected class attribute on <li>
21085                         if ( o.selected === undefined ) {
21086                                 if ( location.hash ) {
21087                                         this.anchors.each(function( i, a ) {
21088                                                 if ( a.hash == location.hash ) {
21089                                                         o.selected = i;
21090                                                         return false;
21091                                                 }
21092                                         });
21093                                 }
21094                                 if ( typeof o.selected !== "number" && o.cookie ) {
21095                                         o.selected = parseInt( self._cookie(), 10 );
21096                                 }
21097                                 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
21098                                         o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
21099                                 }
21100                                 o.selected = o.selected || ( this.lis.length ? 0 : -1 );
21101                         } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
21102                                 o.selected = -1;
21103                         }
21104
21105                         // sanity check - default to first tab...
21106                         o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
21107                                 ? o.selected
21108                                 : 0;
21109
21110                         // Take disabling tabs via class attribute from HTML
21111                         // into account and update option properly.
21112                         // A selected tab cannot become disabled.
21113                         o.disabled = $.unique( o.disabled.concat(
21114                                 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
21115                                         return self.lis.index( n );
21116                                 })
21117                         ) ).sort();
21118
21119                         if ( $.inArray( o.selected, o.disabled ) != -1 ) {
21120                                 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
21121                         }
21122
21123                         // highlight selected tab
21124                         this.panels.addClass( "ui-tabs-hide" );
21125                         this.lis.removeClass( "ui-tabs-selected ui-state-active" );
21126                         // check for length avoids error when initializing empty list
21127                         if ( o.selected >= 0 && this.anchors.length ) {
21128                                 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
21129                                 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
21130
21131                                 // seems to be expected behavior that the show callback is fired
21132                                 self.element.queue( "tabs", function() {
21133                                         self._trigger( "show", null,
21134                                                 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
21135                                 });
21136
21137                                 this.load( o.selected );
21138                         }
21139
21140                         // clean up to avoid memory leaks in certain versions of IE 6
21141                         // TODO: namespace this event
21142                         $( window ).bind( "unload", function() {
21143                                 self.lis.add( self.anchors ).unbind( ".tabs" );
21144                                 self.lis = self.anchors = self.panels = null;
21145                         });
21146                 // update selected after add/remove
21147                 } else {
21148                         o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
21149                 }
21150
21151                 // update collapsible
21152                 // TODO: use .toggleClass()
21153                 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
21154
21155                 // set or update cookie after init and add/remove respectively
21156                 if ( o.cookie ) {
21157                         this._cookie( o.selected, o.cookie );
21158                 }
21159
21160                 // disable tabs
21161                 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
21162                         $( li )[ $.inArray( i, o.disabled ) != -1 &&
21163                                 // TODO: use .toggleClass()
21164                                 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
21165                 }
21166
21167                 // reset cache if switching from cached to not cached
21168                 if ( o.cache === false ) {
21169                         this.anchors.removeData( "cache.tabs" );
21170                 }
21171
21172                 // remove all handlers before, tabify may run on existing tabs after add or option change
21173                 this.lis.add( this.anchors ).unbind( ".tabs" );
21174
21175                 if ( o.event !== "mouseover" ) {
21176                         var addState = function( state, el ) {
21177                                 if ( el.is( ":not(.ui-state-disabled)" ) ) {
21178                                         el.addClass( "ui-state-" + state );
21179                                 }
21180                         };
21181                         var removeState = function( state, el ) {
21182                                 el.removeClass( "ui-state-" + state );
21183                         };
21184                         this.lis.bind( "mouseover.tabs" , function() {
21185                                 addState( "hover", $( this ) );
21186                         });
21187                         this.lis.bind( "mouseout.tabs", function() {
21188                                 removeState( "hover", $( this ) );
21189                         });
21190                         this.anchors.bind( "focus.tabs", function() {
21191                                 addState( "focus", $( this ).closest( "li" ) );
21192                         });
21193                         this.anchors.bind( "blur.tabs", function() {
21194                                 removeState( "focus", $( this ).closest( "li" ) );
21195                         });
21196                 }
21197
21198                 // set up animations
21199                 var hideFx, showFx;
21200                 if ( o.fx ) {
21201                         if ( $.isArray( o.fx ) ) {
21202                                 hideFx = o.fx[ 0 ];
21203                                 showFx = o.fx[ 1 ];
21204                         } else {
21205                                 hideFx = showFx = o.fx;
21206                         }
21207                 }
21208
21209                 // Reset certain styles left over from animation
21210                 // and prevent IE's ClearType bug...
21211                 function resetStyle( $el, fx ) {
21212                         $el.css( "display", "" );
21213                         if ( !$.support.opacity && fx.opacity ) {
21214                                 $el[ 0 ].style.removeAttribute( "filter" );
21215                         }
21216                 }
21217
21218                 // Show a tab...
21219                 var showTab = showFx
21220                         ? function( clicked, $show ) {
21221                                 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
21222                                 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
21223                                         .animate( showFx, showFx.duration || "normal", function() {
21224                                                 resetStyle( $show, showFx );
21225                                                 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
21226                                         });
21227                         }
21228                         : function( clicked, $show ) {
21229                                 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
21230                                 $show.removeClass( "ui-tabs-hide" );
21231                                 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
21232                         };
21233
21234                 // Hide a tab, $show is optional...
21235                 var hideTab = hideFx
21236                         ? function( clicked, $hide ) {
21237                                 $hide.animate( hideFx, hideFx.duration || "normal", function() {
21238                                         self.lis.removeClass( "ui-tabs-selected ui-state-active" );
21239                                         $hide.addClass( "ui-tabs-hide" );
21240                                         resetStyle( $hide, hideFx );
21241                                         self.element.dequeue( "tabs" );
21242                                 });
21243                         }
21244                         : function( clicked, $hide, $show ) {
21245                                 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
21246                                 $hide.addClass( "ui-tabs-hide" );
21247                                 self.element.dequeue( "tabs" );
21248                         };
21249
21250                 // attach tab event handler, unbind to avoid duplicates from former tabifying...
21251                 this.anchors.bind( o.event + ".tabs", function() {
21252                         var el = this,
21253                                 $li = $(el).closest( "li" ),
21254                                 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
21255                                 $show = self.element.find( self._sanitizeSelector( el.hash ) );
21256
21257                         // If tab is already selected and not collapsible or tab disabled or
21258                         // or is already loading or click callback returns false stop here.
21259                         // Check if click handler returns false last so that it is not executed
21260                         // for a disabled or loading tab!
21261                         if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
21262                                 $li.hasClass( "ui-state-disabled" ) ||
21263                                 $li.hasClass( "ui-state-processing" ) ||
21264                                 self.panels.filter( ":animated" ).length ||
21265                                 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
21266                                 this.blur();
21267                                 return false;
21268                         }
21269
21270                         o.selected = self.anchors.index( this );
21271
21272                         self.abort();
21273
21274                         // if tab may be closed
21275                         if ( o.collapsible ) {
21276                                 if ( $li.hasClass( "ui-tabs-selected" ) ) {
21277                                         o.selected = -1;
21278
21279                                         if ( o.cookie ) {
21280                                                 self._cookie( o.selected, o.cookie );
21281                                         }
21282
21283                                         self.element.queue( "tabs", function() {
21284                                                 hideTab( el, $hide );
21285                                         }).dequeue( "tabs" );
21286
21287                                         this.blur();
21288                                         return false;
21289                                 } else if ( !$hide.length ) {
21290                                         if ( o.cookie ) {
21291                                                 self._cookie( o.selected, o.cookie );
21292                                         }
21293
21294                                         self.element.queue( "tabs", function() {
21295                                                 showTab( el, $show );
21296                                         });
21297
21298                                         // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
21299                                         self.load( self.anchors.index( this ) );
21300
21301                                         this.blur();
21302                                         return false;
21303                                 }
21304                         }
21305
21306                         if ( o.cookie ) {
21307                                 self._cookie( o.selected, o.cookie );
21308                         }
21309
21310                         // show new tab
21311                         if ( $show.length ) {
21312                                 if ( $hide.length ) {
21313                                         self.element.queue( "tabs", function() {
21314                                                 hideTab( el, $hide );
21315                                         });
21316                                 }
21317                                 self.element.queue( "tabs", function() {
21318                                         showTab( el, $show );
21319                                 });
21320
21321                                 self.load( self.anchors.index( this ) );
21322                         } else {
21323                                 throw "jQuery UI Tabs: Mismatching fragment identifier.";
21324                         }
21325
21326                         // Prevent IE from keeping other link focussed when using the back button
21327                         // and remove dotted border from clicked link. This is controlled via CSS
21328                         // in modern browsers; blur() removes focus from address bar in Firefox
21329                         // which can become a usability and annoying problem with tabs('rotate').
21330                         if ( $.browser.msie ) {
21331                                 this.blur();
21332                         }
21333                 });
21334
21335                 // disable click in any case
21336                 this.anchors.bind( "click.tabs", function(){
21337                         return false;
21338                 });
21339         },
21340
21341     _getIndex: function( index ) {
21342                 // meta-function to give users option to provide a href string instead of a numerical index.
21343                 // also sanitizes numerical indexes to valid values.
21344                 if ( typeof index == "string" ) {
21345                         index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
21346                 }
21347
21348                 return index;
21349         },
21350
21351         destroy: function() {
21352                 var o = this.options;
21353
21354                 this.abort();
21355
21356                 this.element
21357                         .unbind( ".tabs" )
21358                         .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
21359                         .removeData( "tabs" );
21360
21361                 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
21362
21363                 this.anchors.each(function() {
21364                         var href = $.data( this, "href.tabs" );
21365                         if ( href ) {
21366                                 this.href = href;
21367                         }
21368                         var $this = $( this ).unbind( ".tabs" );
21369                         $.each( [ "href", "load", "cache" ], function( i, prefix ) {
21370                                 $this.removeData( prefix + ".tabs" );
21371                         });
21372                 });
21373
21374                 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
21375                         if ( $.data( this, "destroy.tabs" ) ) {
21376                                 $( this ).remove();
21377                         } else {
21378                                 $( this ).removeClass([
21379                                         "ui-state-default",
21380                                         "ui-corner-top",
21381                                         "ui-tabs-selected",
21382                                         "ui-state-active",
21383                                         "ui-state-hover",
21384                                         "ui-state-focus",
21385                                         "ui-state-disabled",
21386                                         "ui-tabs-panel",
21387                                         "ui-widget-content",
21388                                         "ui-corner-bottom",
21389                                         "ui-tabs-hide"
21390                                 ].join( " " ) );
21391                         }
21392                 });
21393
21394                 if ( o.cookie ) {
21395                         this._cookie( null, o.cookie );
21396                 }
21397
21398                 return this;
21399         },
21400
21401         add: function( url, label, index ) {
21402                 if ( index === undefined ) {
21403                         index = this.anchors.length;
21404                 }
21405
21406                 var self = this,
21407                         o = this.options,
21408                         $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
21409                         id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
21410
21411                 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
21412
21413                 // try to find an existing element before creating a new one
21414                 var $panel = self.element.find( "#" + id );
21415                 if ( !$panel.length ) {
21416                         $panel = $( o.panelTemplate )
21417                                 .attr( "id", id )
21418                                 .data( "destroy.tabs", true );
21419                 }
21420                 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
21421
21422                 if ( index >= this.lis.length ) {
21423                         $li.appendTo( this.list );
21424                         $panel.appendTo( this.list[ 0 ].parentNode );
21425                 } else {
21426                         $li.insertBefore( this.lis[ index ] );
21427                         $panel.insertBefore( this.panels[ index ] );
21428                 }
21429
21430                 o.disabled = $.map( o.disabled, function( n, i ) {
21431                         return n >= index ? ++n : n;
21432                 });
21433
21434                 this._tabify();
21435
21436                 if ( this.anchors.length == 1 ) {
21437                         o.selected = 0;
21438                         $li.addClass( "ui-tabs-selected ui-state-active" );
21439                         $panel.removeClass( "ui-tabs-hide" );
21440                         this.element.queue( "tabs", function() {
21441                                 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
21442                         });
21443
21444                         this.load( 0 );
21445                 }
21446
21447                 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
21448                 return this;
21449         },
21450
21451         remove: function( index ) {
21452                 index = this._getIndex( index );
21453                 var o = this.options,
21454                         $li = this.lis.eq( index ).remove(),
21455                         $panel = this.panels.eq( index ).remove();
21456
21457                 // If selected tab was removed focus tab to the right or
21458                 // in case the last tab was removed the tab to the left.
21459                 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
21460                         this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
21461                 }
21462
21463                 o.disabled = $.map(
21464                         $.grep( o.disabled, function(n, i) {
21465                                 return n != index;
21466                         }),
21467                         function( n, i ) {
21468                                 return n >= index ? --n : n;
21469                         });
21470
21471                 this._tabify();
21472
21473                 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
21474                 return this;
21475         },
21476
21477         enable: function( index ) {
21478                 index = this._getIndex( index );
21479                 var o = this.options;
21480                 if ( $.inArray( index, o.disabled ) == -1 ) {
21481                         return;
21482                 }
21483
21484                 this.lis.eq( index ).removeClass( "ui-state-disabled" );
21485                 o.disabled = $.grep( o.disabled, function( n, i ) {
21486                         return n != index;
21487                 });
21488
21489                 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
21490                 return this;
21491         },
21492
21493         disable: function( index ) {
21494                 index = this._getIndex( index );
21495                 var self = this, o = this.options;
21496                 // cannot disable already selected tab
21497                 if ( index != o.selected ) {
21498                         this.lis.eq( index ).addClass( "ui-state-disabled" );
21499
21500                         o.disabled.push( index );
21501                         o.disabled.sort();
21502
21503                         this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
21504                 }
21505
21506                 return this;
21507         },
21508
21509         select: function( index ) {
21510                 index = this._getIndex( index );
21511                 if ( index == -1 ) {
21512                         if ( this.options.collapsible && this.options.selected != -1 ) {
21513                                 index = this.options.selected;
21514                         } else {
21515                                 return this;
21516                         }
21517                 }
21518                 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
21519                 return this;
21520         },
21521
21522         load: function( index ) {
21523                 index = this._getIndex( index );
21524                 var self = this,
21525                         o = this.options,
21526                         a = this.anchors.eq( index )[ 0 ],
21527                         url = $.data( a, "load.tabs" );
21528
21529                 this.abort();
21530
21531                 // not remote or from cache
21532                 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
21533                         this.element.dequeue( "tabs" );
21534                         return;
21535                 }
21536
21537                 // load remote from here on
21538                 this.lis.eq( index ).addClass( "ui-state-processing" );
21539
21540                 if ( o.spinner ) {
21541                         var span = $( "span", a );
21542                         span.data( "label.tabs", span.html() ).html( o.spinner );
21543                 }
21544
21545                 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
21546                         url: url,
21547                         success: function( r, s ) {
21548                                 self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
21549
21550                                 // take care of tab labels
21551                                 self._cleanup();
21552
21553                                 if ( o.cache ) {
21554                                         $.data( a, "cache.tabs", true );
21555                                 }
21556
21557                                 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
21558                                 try {
21559                                         o.ajaxOptions.success( r, s );
21560                                 }
21561                                 catch ( e ) {}
21562                         },
21563                         error: function( xhr, s, e ) {
21564                                 // take care of tab labels
21565                                 self._cleanup();
21566
21567                                 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
21568                                 try {
21569                                         // Passing index avoid a race condition when this method is
21570                                         // called after the user has selected another tab.
21571                                         // Pass the anchor that initiated this request allows
21572                                         // loadError to manipulate the tab content panel via $(a.hash)
21573                                         o.ajaxOptions.error( xhr, s, index, a );
21574                                 }
21575                                 catch ( e ) {}
21576                         }
21577                 } ) );
21578
21579                 // last, so that load event is fired before show...
21580                 self.element.dequeue( "tabs" );
21581
21582                 return this;
21583         },
21584
21585         abort: function() {
21586                 // stop possibly running animations
21587                 this.element.queue( [] );
21588                 this.panels.stop( false, true );
21589
21590                 // "tabs" queue must not contain more than two elements,
21591                 // which are the callbacks for the latest clicked tab...
21592                 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
21593
21594                 // terminate pending requests from other tabs
21595                 if ( this.xhr ) {
21596                         this.xhr.abort();
21597                         delete this.xhr;
21598                 }
21599
21600                 // take care of tab labels
21601                 this._cleanup();
21602                 return this;
21603         },
21604
21605         url: function( index, url ) {
21606                 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
21607                 return this;
21608         },
21609
21610         length: function() {
21611                 return this.anchors.length;
21612         }
21613 });
21614
21615 $.extend( $.ui.tabs, {
21616         version: "1.8.16"
21617 });
21618
21619 /*
21620  * Tabs Extensions
21621  */
21622
21623 /*
21624  * Rotate
21625  */
21626 $.extend( $.ui.tabs.prototype, {
21627         rotation: null,
21628         rotate: function( ms, continuing ) {
21629                 var self = this,
21630                         o = this.options;
21631
21632                 var rotate = self._rotate || ( self._rotate = function( e ) {
21633                         clearTimeout( self.rotation );
21634                         self.rotation = setTimeout(function() {
21635                                 var t = o.selected;
21636                                 self.select( ++t < self.anchors.length ? t : 0 );
21637                         }, ms );
21638                         
21639                         if ( e ) {
21640                                 e.stopPropagation();
21641                         }
21642                 });
21643
21644                 var stop = self._unrotate || ( self._unrotate = !continuing
21645                         ? function(e) {
21646                                 if (e.clientX) { // in case of a true click
21647                                         self.rotate(null);
21648                                 }
21649                         }
21650                         : function( e ) {
21651                                 t = o.selected;
21652                                 rotate();
21653                         });
21654
21655                 // start rotation
21656                 if ( ms ) {
21657                         this.element.bind( "tabsshow", rotate );
21658                         this.anchors.bind( o.event + ".tabs", stop );
21659                         rotate();
21660                 // stop rotation
21661                 } else {
21662                         clearTimeout( self.rotation );
21663                         this.element.unbind( "tabsshow", rotate );
21664                         this.anchors.unbind( o.event + ".tabs", stop );
21665                         delete this._rotate;
21666                         delete this._unrotate;
21667                 }
21668
21669                 return this;
21670         }
21671 });
21672
21673 })( jQuery );
21674 </script><script type="text/javascript">/*
21675  * $Id$
21676  *
21677  * Copyright 2011, Juniper Network Inc, All rights reserved
21678  * See ../Copyright for more information.
21679  */
21680
21681 jQuery(function ($) {
21682     /*
21683      * dbgpr() is our old-and-trusted debug print function
21684      */
21685     $.dbgpr = function () {
21686         /* The actual work is pretty trivial */
21687         $('#debug-log').prepend(Array.prototype.slice
21688                                 .call(arguments).join(" ") + "\n");
21689     }
21690 });
21691 </script><script type="text/javascript">/*
21692  * $Id$
21693  *
21694  * Copyright (c) 2006-2011, Juniper Networks, Inc.
21695  * All rights reserved.
21696  * This SOFTWARE is licensed under the LICENSE provided in the
21697  * ../Copyright file. By downloading, installing, copying, or otherwise
21698  * using the SOFTWARE, you agree to be bound by the terms of that
21699  * LICENSE.
21700  */
21701
21702 function popClick(event, objectId) {
21703     var sc = window["stickyClick"];
21704     if (sc && sc[objectId]) {
21705         popDown(event, objectId);
21706         sc[objectId] = false;
21707     } else {
21708         popUp(event, objectId);
21709         if (!sc) {
21710             window["stickyClick"] = sc = [];
21711         }
21712         sc[objectId] = true;
21713     }
21714     return false;
21715 }
21716
21717 function popUp(event, objectId) {
21718     var sc = window["stickyClick"];
21719     if (sc && sc[objectId]) {
21720         return;
21721     }
21722
21723     if (document.getElementById == null)
21724         return;
21725     var ie = document.all ? 1 : 0;      /* Is this Internet Explorer? */
21726     var dm = document.getElementById(objectId);
21727     if (dm == null)
21728         return;
21729
21730     var ds = dm.style;
21731     var widthPage = window.innerWidth ? window.innerWidth
21732                 : document.body.clientWidth;
21733
21734     var elementWidth = dm.offsetWidth;
21735     var top;
21736     var left;
21737
21738     if (event.pageY) {
21739         top = event.pageY + 10;
21740         left = event.pageX + 10;
21741     } else if (event.clientY) {
21742         top = event.clientY + 10;
21743         left = event.clientX + 10;
21744     } else {
21745         return;
21746     }    
21747
21748     if (left + elementWidth > widthPage)
21749         left = widthPage - elementWidth - 25;
21750
21751     if (ie) {
21752         ds.width = "1200px";
21753         ds.display = "block";
21754         var cw = dm.firstChild.clientWidth;
21755         if (cw > widthPage - left - 10) {
21756             cw = widthPage - left - 10;
21757         }
21758         ds.width = cw + "px";
21759     }
21760
21761     ds.left = "10px";
21762     ds.top = top + "px";
21763     ds.width = widthPage / 2 + "px";
21764     ds.display = "block";
21765
21766     var tm = document.getElementById("table-" + objectId);
21767     if (tm == null)
21768         return;
21769
21770     elementWidth = tm.offsetWidth;
21771     if (left + elementWidth > widthPage)
21772         left = widthPage - elementWidth - 25;
21773
21774     ds.left = left + "px";
21775 }
21776
21777 function popDown(event, objectId) {
21778     var sc = window["stickyClick"];
21779     if (sc && sc[objectId]) {
21780         return;
21781     }
21782
21783     if (document.getElementById == null)
21784         return;
21785     var dm = document.getElementById(objectId);
21786     if (dm) {
21787         dm.style.display = "none";
21788     }
21789 }
21790 </script><script type="text/javascript">/*
21791  * $Id$
21792  *
21793  * Copyright (c) 2006-2011, Juniper Networks, Inc.
21794  * All rights reserved.
21795  * This SOFTWARE is licensed under the LICENSE provided in the
21796  * ../Copyright file. By downloading, installing, copying, or otherwise
21797  * using the SOFTWARE, you agree to be bound by the terms of that
21798  * LICENSE.
21799  */
21800
21801 jQuery(function ($) {
21802     var $body = $("body");
21803     var $newp = $("<div id='top'><div id='top-left'/>"
21804         + "<div id='top-right'/></div");
21805     var $left = $("div#top-left", $newp);
21806     var $right = $("div#top-right", $newp);
21807
21808     $right.append($("<div id='nav-bar'><button id='nav-prev'/>"
21809                     + "<button id='nav-next'/></div>"));
21810
21811     $body.append($newp);
21812     $left.append($("div#toc"));
21813
21814     $("div.content, div.index, div.note", $body).each(function (i, elt) {
21815         $(elt).appendTo($right);
21816     });
21817
21818     $("body > ul.toc").remove();
21819     $("#rfc.toc").remove();
21820     $("div.note").remove();
21821     $("h1", $left).remove();
21822
21823     /* $body.append($("<div id='debug-log'/>")); */
21824     $left.append($("<div class='padding'/>"));
21825
21826     var active;
21827     var tocactive;
21828
21829     {
21830         var $active = $($right.children("div.content").get(0));
21831         if (this.URL) {
21832             var last = this.URL.lastIndexOf("#");
21833             if (last) {
21834                 var $found = $(this.URL.substring(last));
21835                 if ($found.length > 0)
21836                     $active = $found.parent();
21837                     if (!$active.hasClass("content"))
21838                         $active = $active.parent();
21839             }
21840         }
21841         setActive($active);
21842     }
21843
21844     function setActive ($elt, toggle) {
21845         if ($elt && $elt.length > 0 && $elt.hasClass("content")) {
21846             /* Mark a new element "active" */
21847             if (active)
21848                 active.removeClass("active");
21849             active = $elt;
21850             active.addClass("active");
21851
21852             /* Now we want to find the matching TOC entry and mark it */
21853             if (tocactive)
21854                 tocactive.removeClass("toc-active");
21855
21856             var id = $elt.get(0).children[0].id
21857             $.dbgpr("sa:", id);
21858             if (id) {
21859                 id = "#toc_" + id;
21860                 tocactive = $("a", $(id).parent());
21861                 $.dbgpr("ta:", tocactive.length, id);
21862                 if (tocactive.length) {
21863                     tocactive = $(tocactive[0]);
21864                     tocactive.addClass("toc-active");
21865
21866                     var $tt = tocactive.parents("li.tocline0");
21867                     $.dbgpr("tt:", $tt.length);
21868                     if (toggle)
21869                         $("ul.top-toc", $tt).toggleClass("top-toc-open");
21870                     else
21871                         $("ul.top-toc", $tt).addClass("top-toc-open");
21872                 }
21873             }
21874
21875             var szr = $("div#top-right div.active").innerHeight();
21876             var sz = $("p#title").innerHeight();
21877             sz = window.innerHeight - sz;
21878             sz -= 66;
21879             if (sz < 200)
21880                 sz = 300;
21881             if (sz < szr)
21882                 sz = szr;
21883             $("div#toc > ul.toc").innerHeight(sz);
21884
21885         }
21886     }
21887
21888     function findParent ($elt, className) {
21889         while ($elt) {
21890             if ($elt.hasClass(className))
21891                 return $elt;
21892             $elt = $elt.parent();
21893         }
21894         return null;
21895     }
21896
21897     $("a", $left).click(function (event) {
21898         event.preventDefault();
21899         var $this = $(this);
21900         var id = this.href.split("#");
21901         id = id[id.length - 1];
21902
21903         var toggle = $(this).parent().hasClass("tocline0");
21904
21905         var $target = $(document.getElementById(id));
21906         $.dbgpr("id: ", id, " + ", $target, " + ", $target.length);
21907
21908         var $parent = findParent($target, "content");
21909         $.dbgpr("pr: ", $parent);
21910         setActive($parent, toggle);
21911         $.dbgpr("done");
21912
21913         $("html").animate({ scrollTop: 0 }, 500);
21914     });
21915
21916
21917     $("a", $right).each(function (idx, elt) {
21918         /* Put the @title as the link value */
21919         var $elt = $(elt);
21920         var href = $elt.attr("href");
21921         var proto;
21922
21923         if (href) {
21924             var len = href.indexOf(":");
21925             if (len > 0) {
21926                 proto = href.substr(0, len);
21927             }
21928         }
21929         if (proto != "http" && proto != "https") {
21930             var t = $elt.attr("title");
21931             if (t !== undefined && href !== undefined)
21932                 $elt.text(t);
21933             $elt.click(function (event) {
21934                 event.preventDefault();
21935                 var id = this.href.split("#");
21936                 id = id[id.length - 1];
21937
21938                 var $target = $(document.getElementById(id));
21939                 setActive($target.parents("div.content"));
21940
21941                 $("html").animate({ scrollTop: 0 }, 500);
21942             });
21943         }
21944     });
21945
21946     $("button#nav-prev").button({
21947         label: "<< Previous",
21948     }).click(function (event) {
21949         setActive(active.prev());
21950     });
21951
21952     $("button#nav-next").button({
21953         label: "Next >>",
21954     }).click(function (event) {
21955         setActive(active.next());
21956     });
21957
21958     $("p", $right).each(function (idx, elt) {
21959         var $elt = $(elt);
21960         var val = $elt.get(0);
21961         if (val && val.textContent && val.textContent.startsWith("Section Contents")) {
21962             $elt.addClass("section-contents");
21963         }
21964     });
21965
21966
21967     function getMedia () {
21968         var mediaInspector = document.getElementById('media-inspector');
21969         var zIndex;
21970
21971         if (mediaInspector === null)
21972             return -1;
21973
21974         if (mediaInspector.currentStyle) {
21975             zIndex = mediaInspector.currentStyle['zIndex'];
21976         } else if (window.getComputedStyle) {
21977             zIndex = window.getComputedStyle(mediaInspector, '')
21978                         .getPropertyValue("z-index");
21979         }
21980         return zIndex;
21981     }
21982 });
21983 </script><link rel="Contents" href="#doc.toc">
21984 <link rel="Author" href="#doc.authors">
21985 <link rel="Chapter" title="1 Overview" href="#doc_section_1">
21986 <link rel="Chapter" title="2 Getting libxo" href="#doc_section_2">
21987 <link rel="Chapter" title="3 Formatting with libxo" href="#doc_section_3">
21988 <link rel="Chapter" title="4 Command-line Arguments" href="#doc_section_4">
21989 <link rel="Chapter" title="5 The libxo API" href="#doc_section_5">
21990 <link rel="Chapter" title='6 The "xo" Utility' href="#doc_section_6">
21991 <link rel="Chapter" title="7 xolint" href="#doc_section_7">
21992 <link rel="Chapter" title="8 xohtml" href="#doc_section_8">
21993 <link rel="Chapter" title="9 xopo" href="#doc_section_9">
21994 <link rel="Chapter" title="10 FAQs" href="#doc_section_10">
21995 <link rel="Chapter" title="11 Howtos: Focused Directions" href="#doc_section_11">
21996 <link rel="Chapter" title="12 Examples" href="#doc_section_12">
21997 <meta name="generator" content="http://greenbytes.de/tech/webdav/rfc2629.xslt, Revision 1.389, 2008-08-20 14:21:35, XSLT vendor: libxslt http://xmlsoft.org/XSLT/">
21998 <link rel="schema.DC" href="http://purl.org/dc/elements/1.1/">
21999 <meta name="DC.Creator" content="Shafer, P.">
22000 </head>
22001 <body style="font-size: 80%">
22002 <div id="media-inspector"></div>
22003 <div id="header"><table summary="header information" class="header" border="0" cellpadding="1" cellspacing="1">
22004 <tr>
22005 <td class="header left">The libxo Project</td>
22006 <td class="header right">P. Shafer</td>
22007 </tr>
22008 <tr>
22009 <td class="header left"></td>
22010 <td class="header right">Juniper Networks</td>
22011 </tr>
22012 <tr>
22013 <td class="header left"></td>
22014 <td class="header right">May 21, 2018</td>
22015 </tr>
22016 </table></div>
22017 <p id="title" class="title">libxo: The Easy Way to Generate text, XML, JSON, and HTML output<br><span class="filename">libxo-manual</span></p>
22018 <div id="toc">
22019 <h1 class="np" id="doc.toc"><a href="#doc.toc">Table of Contents</a></h1>
22020 <ul class="toc">
22021 <li class="tocline0">
22022 <div class="section-number" id="toc_doc_section_1">1   </div>
22023 <a href="#overview">Overview</a>
22024 </li>
22025 <li class="tocline0">
22026 <div class="section-number" id="toc_doc_section_2">2   </div>
22027 <a href="#getting-libxo">Getting libxo</a><ul class="toc top-toc">
22028 <li class="tocline1">
22029 <div class="section-number" id="toc_doc_section_2_1">2.1   </div>
22030 <a href="#downloading-libxo-source-code">Downloading libxo Source Code</a>
22031 </li>
22032 <li class="tocline1">
22033 <div class="section-number" id="toc_doc_section_2_2">2.2   </div>
22034 <a href="#building-libxo">Building libxo</a><ul class="toc">
22035 <li class="tocline1">
22036 <div class="section-number" id="toc_doc_section_2_2_1">2.2.1   </div>
22037 <a href="#setting-up-the-build">Setting up the build</a>
22038 </li>
22039 <li class="tocline1">
22040 <div class="section-number" id="toc_doc_section_2_2_2">2.2.2   </div>
22041 <a href="#running-the-configure-script">Running the "configure" Script</a><ul class="toc">
22042 <li class="tocline1">
22043 <div class="section-number" id="toc_doc_section_2_2_2_1">2.2.2.1   </div>
22044 <a href="#running-the-make-command">Running the "make" command</a>
22045 </li>
22046 <li class="tocline1">
22047 <div class="section-number" id="toc_doc_section_2_2_2_2">2.2.2.2   </div>
22048 <a href="#running-the-regression-tests">Running the Regression Tests</a>
22049 </li>
22050 </ul>
22051 </li>
22052 <li class="tocline1">
22053 <div class="section-number" id="toc_doc_section_2_2_3">2.2.3   </div>
22054 <a href="#installing-libxo">Installing libxo</a>
22055 </li>
22056 </ul>
22057 </li>
22058 </ul>
22059 </li>
22060 <li class="tocline0">
22061 <div class="section-number" id="toc_doc_section_3">3   </div>
22062 <a href="#formatting-with-libxo">Formatting with libxo</a><ul class="toc top-toc">
22063 <li class="tocline1">
22064 <div class="section-number" id="toc_doc_section_3_1">3.1   </div>
22065 <a href="#encoding-styles">Encoding Styles</a><ul class="toc">
22066 <li class="tocline1">
22067 <div class="section-number" id="toc_doc_section_3_1_1">3.1.1   </div>
22068 <a href="#text-output">Text Output</a>
22069 </li>
22070 <li class="tocline1">
22071 <div class="section-number" id="toc_doc_section_3_1_2">3.1.2   </div>
22072 <a href="#xml-output">XML Output</a>
22073 </li>
22074 <li class="tocline1">
22075 <div class="section-number" id="toc_doc_section_3_1_3">3.1.3   </div>
22076 <a href="#json-output">JSON Output</a>
22077 </li>
22078 <li class="tocline1">
22079 <div class="section-number" id="toc_doc_section_3_1_4">3.1.4   </div>
22080 <a href="#html-output">HTML Output</a>
22081 </li>
22082 </ul>
22083 </li>
22084 <li class="tocline1">
22085 <div class="section-number" id="toc_doc_section_3_2">3.2   </div>
22086 <a href="#format-strings">Format Strings</a><ul class="toc">
22087 <li class="tocline1">
22088 <div class="section-number" id="toc_doc_section_3_2_1">3.2.1   </div>
22089 <a href="#field-roles">Field Roles</a><ul class="toc">
22090 <li class="tocline1">
22091 <div class="section-number" id="toc_doc_section_3_2_1_1">3.2.1.1   </div>
22092 <a href="#color-role">The Color Role ({C:})</a>
22093 </li>
22094 <li class="tocline1">
22095 <div class="section-number" id="toc_doc_section_3_2_1_2">3.2.1.2   </div>
22096 <a href="#the-decoration-role-d">The Decoration Role ({D:})</a>
22097 </li>
22098 <li class="tocline1">
22099 <div class="section-number" id="toc_doc_section_3_2_1_3">3.2.1.3   </div>
22100 <a href="#gettext-role">The Gettext Role ({G:})</a>
22101 </li>
22102 <li class="tocline1">
22103 <div class="section-number" id="toc_doc_section_3_2_1_4">3.2.1.4   </div>
22104 <a href="#the-label-role-l">The Label Role ({L:})</a>
22105 </li>
22106 <li class="tocline1">
22107 <div class="section-number" id="toc_doc_section_3_2_1_5">3.2.1.5   </div>
22108 <a href="#the-note-role-n">The Note Role ({N:})</a>
22109 </li>
22110 <li class="tocline1">
22111 <div class="section-number" id="toc_doc_section_3_2_1_6">3.2.1.6   </div>
22112 <a href="#padding-role">The Padding Role ({P:})</a>
22113 </li>
22114 <li class="tocline1">
22115 <div class="section-number" id="toc_doc_section_3_2_1_7">3.2.1.7   </div>
22116 <a href="#the-title-role-t">The Title Role ({T:})</a>
22117 </li>
22118 <li class="tocline1">
22119 <div class="section-number" id="toc_doc_section_3_2_1_8">3.2.1.8   </div>
22120 <a href="#the-units-role-u">The Units Role ({U:})</a>
22121 </li>
22122 <li class="tocline1">
22123 <div class="section-number" id="toc_doc_section_3_2_1_9">3.2.1.9   </div>
22124 <a href="#the-value-role-v-and-">The Value Role ({V:} and {:})</a>
22125 </li>
22126 <li class="tocline1">
22127 <div class="section-number" id="toc_doc_section_3_2_1_10">3.2.1.10   </div>
22128 <a href="#anchor-role">The Anchor Roles ({[:} and {]:})</a>
22129 </li>
22130 </ul>
22131 </li>
22132 <li class="tocline1">
22133 <div class="section-number" id="toc_doc_section_3_2_2">3.2.2   </div>
22134 <a href="#field-modifiers">Field Modifiers</a><ul class="toc">
22135 <li class="tocline1">
22136 <div class="section-number" id="toc_doc_section_3_2_2_1">3.2.2.1   </div>
22137 <a href="#the-argument-modifier-a">The Argument Modifier ({a:})</a>
22138 </li>
22139 <li class="tocline1">
22140 <div class="section-number" id="toc_doc_section_3_2_2_2">3.2.2.2   </div>
22141 <a href="#the-colon-modifier-c">The Colon Modifier ({c:})</a>
22142 </li>
22143 <li class="tocline1">
22144 <div class="section-number" id="toc_doc_section_3_2_2_3">3.2.2.3   </div>
22145 <a href="#the-display-modifier-d">The Display Modifier ({d:})</a>
22146 </li>
22147 <li class="tocline1">
22148 <div class="section-number" id="toc_doc_section_3_2_2_4">3.2.2.4   </div>
22149 <a href="#e-modifier">The Encoding Modifier ({e:})</a>
22150 </li>
22151 <li class="tocline1">
22152 <div class="section-number" id="toc_doc_section_3_2_2_5">3.2.2.5   </div>
22153 <a href="#gettext-modifier">The Gettext Modifier ({g:})</a>
22154 </li>
22155 <li class="tocline1">
22156 <div class="section-number" id="toc_doc_section_3_2_2_6">3.2.2.6   </div>
22157 <a href="#the-humanize-modifier-h">The Humanize Modifier ({h:})</a>
22158 </li>
22159 <li class="tocline1">
22160 <div class="section-number" id="toc_doc_section_3_2_2_7">3.2.2.7   </div>
22161 <a href="#the-key-modifier-k">The Key Modifier ({k:})</a>
22162 </li>
22163 <li class="tocline1">
22164 <div class="section-number" id="toc_doc_section_3_2_2_8">3.2.2.8   </div>
22165 <a href="#the-leaf-list-modifier-l">The Leaf-List Modifier ({l:})</a>
22166 </li>
22167 <li class="tocline1">
22168 <div class="section-number" id="toc_doc_section_3_2_2_9">3.2.2.9   </div>
22169 <a href="#the-no-quotes-modifier-n">The No-Quotes Modifier ({n:})</a>
22170 </li>
22171 <li class="tocline1">
22172 <div class="section-number" id="toc_doc_section_3_2_2_10">3.2.2.10   </div>
22173 <a href="#plural-modifier">The Plural Modifier ({p:})</a>
22174 </li>
22175 <li class="tocline1">
22176 <div class="section-number" id="toc_doc_section_3_2_2_11">3.2.2.11   </div>
22177 <a href="#the-quotes-modifier-q">The Quotes Modifier ({q:})</a>
22178 </li>
22179 <li class="tocline1">
22180 <div class="section-number" id="toc_doc_section_3_2_2_12">3.2.2.12   </div>
22181 <a href="#the-trim-modifier-t">The Trim Modifier ({t:})</a>
22182 </li>
22183 <li class="tocline1">
22184 <div class="section-number" id="toc_doc_section_3_2_2_13">3.2.2.13   </div>
22185 <a href="#the-white-space-modifier-w">The White Space Modifier ({w:})</a>
22186 </li>
22187 </ul>
22188 </li>
22189 <li class="tocline1">
22190 <div class="section-number" id="toc_doc_section_3_2_3">3.2.3   </div>
22191 <a href="#field-formatting">Field Formatting</a>
22192 </li>
22193 <li class="tocline1">
22194 <div class="section-number" id="toc_doc_section_3_2_4">3.2.4   </div>
22195 <a href="#utf-8-and-locale-strings">UTF-8 and Locale Strings</a>
22196 </li>
22197 <li class="tocline1">
22198 <div class="section-number" id="toc_doc_section_3_2_5">3.2.5   </div>
22199 <a href="#characters-outside-of-field-definitions">Characters Outside of Field Definitions</a>
22200 </li>
22201 <li class="tocline1">
22202 <div class="section-number" id="toc_doc_section_3_2_6">3.2.6   </div>
22203 <a href="#m-is-supported">"%m" Is Supported</a>
22204 </li>
22205 <li class="tocline1">
22206 <div class="section-number" id="toc_doc_section_3_2_7">3.2.7   </div>
22207 <a href="#n-is-not-supported">"%n" Is Not Supported</a>
22208 </li>
22209 <li class="tocline1">
22210 <div class="section-number" id="toc_doc_section_3_2_8">3.2.8   </div>
22211 <a href="#the-encoding-format-eformat">The Encoding Format (eformat)</a>
22212 </li>
22213 <li class="tocline1">
22214 <div class="section-number" id="toc_doc_section_3_2_9">3.2.9   </div>
22215 <a href="#content-strings">Content Strings</a>
22216 </li>
22217 <li class="tocline1">
22218 <div class="section-number" id="toc_doc_section_3_2_10">3.2.10   </div>
22219 <a href="#printf-like">Argument Validation</a>
22220 </li>
22221 <li class="tocline1">
22222 <div class="section-number" id="toc_doc_section_3_2_11">3.2.11   </div>
22223 <a href="#retain">Retaining Parsed Format Information</a>
22224 </li>
22225 <li class="tocline1">
22226 <div class="section-number" id="toc_doc_section_3_2_12">3.2.12   </div>
22227 <a href="#example">Example</a>
22228 </li>
22229 </ul>
22230 </li>
22231 <li class="tocline1">
22232 <div class="section-number" id="toc_doc_section_3_3">3.3   </div>
22233 <a href="#representing-hierarchy">Representing Hierarchy</a><ul class="toc">
22234 <li class="tocline1">
22235 <div class="section-number" id="toc_doc_section_3_3_1">3.3.1   </div>
22236 <a href="#containers">Containers</a>
22237 </li>
22238 <li class="tocline1">
22239 <div class="section-number" id="toc_doc_section_3_3_2">3.3.2   </div>
22240 <a href="#lists-and-instances">Lists and Instances</a>
22241 </li>
22242 <li class="tocline1">
22243 <div class="section-number" id="toc_doc_section_3_3_3">3.3.3   </div>
22244 <a href="#dtrt-mode">DTRT Mode</a>
22245 </li>
22246 <li class="tocline1">
22247 <div class="section-number" id="toc_doc_section_3_3_4">3.3.4   </div>
22248 <a href="#markers">Markers</a>
22249 </li>
22250 </ul>
22251 </li>
22252 </ul>
22253 </li>
22254 <li class="tocline0">
22255 <div class="section-number" id="toc_doc_section_4">4   </div>
22256 <a href="#options">Command-line Arguments</a><ul class="toc top-toc">
22257 <li class="tocline1">
22258 <div class="section-number" id="toc_doc_section_4_1">4.1   </div>
22259 <a href="#option-keywords">Option keywords</a>
22260 </li>
22261 <li class="tocline1">
22262 <div class="section-number" id="toc_doc_section_4_2">4.2   </div>
22263 <a href="#brief-options">Brief Options</a>
22264 </li>
22265 <li class="tocline1">
22266 <div class="section-number" id="toc_doc_section_4_3">4.3   </div>
22267 <a href="#color-mapping">Color Mapping</a>
22268 </li>
22269 </ul>
22270 </li>
22271 <li class="tocline0">
22272 <div class="section-number" id="toc_doc_section_5">5   </div>
22273 <a href="#the-libxo-api">The libxo API</a><ul class="toc top-toc">
22274 <li class="tocline1">
22275 <div class="section-number" id="toc_doc_section_5_1">5.1   </div>
22276 <a href="#handles">Handles</a><ul class="toc">
22277 <li class="tocline1">
22278 <div class="section-number" id="toc_doc_section_5_1_1">5.1.1   </div>
22279 <a href="#xo_create">xo_create</a>
22280 </li>
22281 <li class="tocline1">
22282 <div class="section-number" id="toc_doc_section_5_1_2">5.1.2   </div>
22283 <a href="#xo_create_to_file">xo_create_to_file</a>
22284 </li>
22285 <li class="tocline1">
22286 <div class="section-number" id="toc_doc_section_5_1_3">5.1.3   </div>
22287 <a href="#xo_set_writer">xo_set_writer</a>
22288 </li>
22289 <li class="tocline1">
22290 <div class="section-number" id="toc_doc_section_5_1_4">5.1.4   </div>
22291 <a href="#xo_set_style">xo_set_style</a>
22292 </li>
22293 <li class="tocline1">
22294 <div class="section-number" id="toc_doc_section_5_1_5">5.1.5   </div>
22295 <a href="#xo_get_style">xo_get_style</a><ul class="toc">
22296 <li class="tocline1">
22297 <div class="section-number" id="toc_doc_section_5_1_5_1">5.1.5.1   </div>
22298 <a href="#styles">Output Styles (XO_STYLE_*)</a>
22299 </li>
22300 <li class="tocline1">
22301 <div class="section-number" id="toc_doc_section_5_1_5_2">5.1.5.2   </div>
22302 <a href="#xo_set_style_name">xo_set_style_name</a>
22303 </li>
22304 </ul>
22305 </li>
22306 <li class="tocline1">
22307 <div class="section-number" id="toc_doc_section_5_1_6">5.1.6   </div>
22308 <a href="#xo_set_flags">xo_set_flags</a><ul class="toc">
22309 <li class="tocline1">
22310 <div class="section-number" id="toc_doc_section_5_1_6_1">5.1.6.1   </div>
22311 <a href="#flags">Flags (XOF_*)</a>
22312 </li>
22313 <li class="tocline1">
22314 <div class="section-number" id="toc_doc_section_5_1_6_2">5.1.6.2   </div>
22315 <a href="#xo_clear_flags">xo_clear_flags</a>
22316 </li>
22317 <li class="tocline1">
22318 <div class="section-number" id="toc_doc_section_5_1_6_3">5.1.6.3   </div>
22319 <a href="#xo_set_options">xo_set_options</a>
22320 </li>
22321 </ul>
22322 </li>
22323 <li class="tocline1">
22324 <div class="section-number" id="toc_doc_section_5_1_7">5.1.7   </div>
22325 <a href="#xo_destroy">xo_destroy</a>
22326 </li>
22327 </ul>
22328 </li>
22329 <li class="tocline1">
22330 <div class="section-number" id="toc_doc_section_5_2">5.2   </div>
22331 <a href="#emitting-content-xo_emit">Emitting Content (xo_emit)</a><ul class="toc">
22332 <li class="tocline1">
22333 <div class="section-number" id="toc_doc_section_5_2_1">5.2.1   </div>
22334 <a href="#xo_emit_field">Single Field Emitting Functions (xo_emit_field)</a>
22335 </li>
22336 <li class="tocline1">
22337 <div class="section-number" id="toc_doc_section_5_2_2">5.2.2   </div>
22338 <a href="#xo_attr">Attributes (xo_attr)</a>
22339 </li>
22340 <li class="tocline1">
22341 <div class="section-number" id="toc_doc_section_5_2_3">5.2.3   </div>
22342 <a href="#flushing-output-xo_flush">Flushing Output (xo_flush)</a>
22343 </li>
22344 <li class="tocline1">
22345 <div class="section-number" id="toc_doc_section_5_2_4">5.2.4   </div>
22346 <a href="#finishing-output-xo_finish">Finishing Output (xo_finish)</a>
22347 </li>
22348 </ul>
22349 </li>
22350 <li class="tocline1">
22351 <div class="section-number" id="toc_doc_section_5_3">5.3   </div>
22352 <a href="#emitting-hierarchy">Emitting Hierarchy</a><ul class="toc"><li class="tocline1">
22353 <div class="section-number" id="toc_doc_section_5_3_1">5.3.1   </div>
22354 <a href="#lists-and-instances-2">Lists and Instances</a>
22355 </li></ul>
22356 </li>
22357 <li class="tocline1">
22358 <div class="section-number" id="toc_doc_section_5_4">5.4   </div>
22359 <a href="#support-functions">Support Functions</a><ul class="toc">
22360 <li class="tocline1">
22361 <div class="section-number" id="toc_doc_section_5_4_1">5.4.1   </div>
22362 <a href="#xo_parse_args">Parsing Command-line Arguments (xo_parse_args)</a>
22363 </li>
22364 <li class="tocline1">
22365 <div class="section-number" id="toc_doc_section_5_4_2">5.4.2   </div>
22366 <a href="#xo_set_program">xo_set_program</a>
22367 </li>
22368 <li class="tocline1">
22369 <div class="section-number" id="toc_doc_section_5_4_3">5.4.3   </div>
22370 <a href="#xo_set_version">xo_set_version</a>
22371 </li>
22372 <li class="tocline1">
22373 <div class="section-number" id="toc_doc_section_5_4_4">5.4.4   </div>
22374 <a href="#info">Field Information (xo_info_t)</a>
22375 </li>
22376 <li class="tocline1">
22377 <div class="section-number" id="toc_doc_section_5_4_5">5.4.5   </div>
22378 <a href="#memory-allocation">Memory Allocation</a>
22379 </li>
22380 <li class="tocline1">
22381 <div class="section-number" id="toc_doc_section_5_4_6">5.4.6   </div>
22382 <a href="#LIBXO_OPTIONS">LIBXO_OPTIONS</a>
22383 </li>
22384 <li class="tocline1">
22385 <div class="section-number" id="toc_doc_section_5_4_7">5.4.7   </div>
22386 <a href="#errors-warnings-and-messages">Errors, Warnings, and Messages</a>
22387 </li>
22388 <li class="tocline1">
22389 <div class="section-number" id="toc_doc_section_5_4_8">5.4.8   </div>
22390 <a href="#xo_error">xo_error</a>
22391 </li>
22392 <li class="tocline1">
22393 <div class="section-number" id="toc_doc_section_5_4_9">5.4.9   </div>
22394 <a href="#xo_no_setlocale">xo_no_setlocale</a>
22395 </li>
22396 </ul>
22397 </li>
22398 <li class="tocline1">
22399 <div class="section-number" id="toc_doc_section_5_5">5.5   </div>
22400 <a href="#emitting-syslog-messages">Emitting syslog Messages</a><ul class="toc">
22401 <li class="tocline1">
22402 <div class="section-number" id="toc_doc_section_5_5_1">5.5.1   </div>
22403 <a href="#priority">Priority, Facility, and Flags</a>
22404 </li>
22405 <li class="tocline1">
22406 <div class="section-number" id="toc_doc_section_5_5_2">5.5.2   </div>
22407 <a href="#xo_syslog">xo_syslog</a>
22408 </li>
22409 <li class="tocline1">
22410 <div class="section-number" id="toc_doc_section_5_5_3">5.5.3   </div>
22411 <a href="#support-functions-2">Support functions</a><ul class="toc">
22412 <li class="tocline1">
22413 <div class="section-number" id="toc_doc_section_5_5_3_1">5.5.3.1   </div>
22414 <a href="#xo_vsyslog">xo_vsyslog</a>
22415 </li>
22416 <li class="tocline1">
22417 <div class="section-number" id="toc_doc_section_5_5_3_2">5.5.3.2   </div>
22418 <a href="#xo_open_log">xo_open_log</a>
22419 </li>
22420 <li class="tocline1">
22421 <div class="section-number" id="toc_doc_section_5_5_3_3">5.5.3.3   </div>
22422 <a href="#xo_close_log">xo_close_log</a>
22423 </li>
22424 <li class="tocline1">
22425 <div class="section-number" id="toc_doc_section_5_5_3_4">5.5.3.4   </div>
22426 <a href="#xo_set_logmask">xo_set_logmask</a>
22427 </li>
22428 <li class="tocline1">
22429 <div class="section-number" id="toc_doc_section_5_5_3_5">5.5.3.5   </div>
22430 <a href="#xo_set_syslog_enterprise_id">xo_set_syslog_enterprise_id</a>
22431 </li>
22432 </ul>
22433 </li>
22434 </ul>
22435 </li>
22436 <li class="tocline1">
22437 <div class="section-number" id="toc_doc_section_5_6">5.6   </div>
22438 <a href="#creating-custom-encoders">Creating Custom Encoders</a><ul class="toc">
22439 <li class="tocline1">
22440 <div class="section-number" id="toc_doc_section_5_6_1">5.6.1   </div>
22441 <a href="#loading-encoders">Loading Encoders</a>
22442 </li>
22443 <li class="tocline1">
22444 <div class="section-number" id="toc_doc_section_5_6_2">5.6.2   </div>
22445 <a href="#encoder-initialization">Encoder Initialization</a>
22446 </li>
22447 <li class="tocline1">
22448 <div class="section-number" id="toc_doc_section_5_6_3">5.6.3   </div>
22449 <a href="#operations">Operations</a>
22450 </li>
22451 </ul>
22452 </li>
22453 </ul>
22454 </li>
22455 <li class="tocline0">
22456 <div class="section-number" id="toc_doc_section_6">6   </div>
22457 <a href="#the-xo-utility">The "xo" Utility</a><ul class="toc top-toc">
22458 <li class="tocline1">
22459 <div class="section-number" id="toc_doc_section_6_1">6.1   </div>
22460 <a href="#command-line-options">Command Line Options</a>
22461 </li>
22462 <li class="tocline1">
22463 <div class="section-number" id="toc_doc_section_6_2">6.2   </div>
22464 <a href="#example-2">Example</a>
22465 </li>
22466 </ul>
22467 </li>
22468 <li class="tocline0">
22469 <div class="section-number" id="toc_doc_section_7">7   </div>
22470 <a href="#xolint">xolint</a>
22471 </li>
22472 <li class="tocline0">
22473 <div class="section-number" id="toc_doc_section_8">8   </div>
22474 <a href="#xohtml">xohtml</a>
22475 </li>
22476 <li class="tocline0">
22477 <div class="section-number" id="toc_doc_section_9">9   </div>
22478 <a href="#xopo">xopo</a>
22479 </li>
22480 <li class="tocline0">
22481 <div class="section-number" id="toc_doc_section_10">10   </div>
22482 <a href="#faqs">FAQs</a><ul class="toc top-toc">
22483 <li class="tocline1">
22484 <div class="section-number" id="toc_doc_section_10_1">10.1   </div>
22485 <a href="#general">General</a><ul class="toc">
22486 <li class="tocline1">
22487 <div class="section-number" id="toc_doc_section_10_1_1">10.1.1   </div>
22488 <a href="#can-you-share-the-history-of-libxo">Can you share the history of libxo?</a>
22489 </li>
22490 <li class="tocline1">
22491 <div class="section-number" id="toc_doc_section_10_1_2">10.1.2   </div>
22492 <a href="#did-the-complex-semantics-of-format-strings-evolve-over-time">Did the complex semantics of format strings evolve over time?</a>
22493 </li>
22494 <li class="tocline1">
22495 <div class="section-number" id="toc_doc_section_10_1_3">10.1.3   </div>
22496 <a href="#good-field-names">What makes a good field name?</a>
22497 </li>
22498 </ul>
22499 </li>
22500 <li class="tocline1">
22501 <div class="section-number" id="toc_doc_section_10_2">10.2   </div>
22502 <a href="#what-does-this-message-mean">What does this message mean?</a><ul class="toc">
22503 <li class="tocline1">
22504 <div class="section-number" id="toc_doc_section_10_2_1">10.2.1   </div>
22505 <a href="#a-percent-sign-appearing-in-text-is-a-literal">'A percent sign appearing in text is a literal'</a>
22506 </li>
22507 <li class="tocline1">
22508 <div class="section-number" id="toc_doc_section_10_2_2">10.2.2   </div>
22509 <a href="#unknown-long-name-for-rolemodifier">'Unknown long name for role/modifier'</a>
22510 </li>
22511 <li class="tocline1">
22512 <div class="section-number" id="toc_doc_section_10_2_3">10.2.3   </div>
22513 <a href="#last-character-before-field-definition-is-a-field-type">'Last character before field definition is a field type'</a>
22514 </li>
22515 <li class="tocline1">
22516 <div class="section-number" id="toc_doc_section_10_2_4">10.2.4   </div>
22517 <a href="#encoding-format-uses-different-number-of-arguments">'Encoding format uses different number of arguments'</a>
22518 </li>
22519 <li class="tocline1">
22520 <div class="section-number" id="toc_doc_section_10_2_5">10.2.5   </div>
22521 <a href="#only-one-field-role-can-be-used">'Only one field role can be used'</a>
22522 </li>
22523 <li class="tocline1">
22524 <div class="section-number" id="toc_doc_section_10_2_6">10.2.6   </div>
22525 <a href="#potential-missing-slash-after-c-d-n-l-or-t-with-format">'Potential missing slash after C, D, N, L, or T with format'</a>
22526 </li>
22527 <li class="tocline1">
22528 <div class="section-number" id="toc_doc_section_10_2_7">10.2.7   </div>
22529 <a href="#an-encoding-format-cannot-be-given-roles-dnlt">'An encoding format cannot be given (roles: DNLT)'</a>
22530 </li>
22531 <li class="tocline1">
22532 <div class="section-number" id="toc_doc_section_10_2_8">10.2.8   </div>
22533 <a href="#format-cannot-be-given-when-content-is-present-roles-cdln">'Format cannot be given when content is present (roles: CDLN)'</a>
22534 </li>
22535 <li class="tocline1">
22536 <div class="section-number" id="toc_doc_section_10_2_9">10.2.9   </div>
22537 <a href="#field-has-color-without-fg--or-bg--role-c">'Field has color without fg- or bg- (role: C)'</a>
22538 </li>
22539 <li class="tocline1">
22540 <div class="section-number" id="toc_doc_section_10_2_10">10.2.10   </div>
22541 <a href="#field-has-invalid-color-or-effect-role-c">'Field has invalid color or effect (role: C)'</a>
22542 </li>
22543 <li class="tocline1">
22544 <div class="section-number" id="toc_doc_section_10_2_11">10.2.11   </div>
22545 <a href="#field-has-humanize-modifier-but-no-format-string">'Field has humanize modifier but no format string'</a>
22546 </li>
22547 <li class="tocline1">
22548 <div class="section-number" id="toc_doc_section_10_2_12">10.2.12   </div>
22549 <a href="#field-has-hn--modifier-but-not-h-modifier">'Field has hn-* modifier but not 'h' modifier'</a>
22550 </li>
22551 <li class="tocline1">
22552 <div class="section-number" id="toc_doc_section_10_2_13">10.2.13   </div>
22553 <a href="#value-field-must-have-a-name-as-content">'Value field must have a name (as content)")'</a>
22554 </li>
22555 <li class="tocline1">
22556 <div class="section-number" id="toc_doc_section_10_2_14">10.2.14   </div>
22557 <a href="#use-hyphens-not-underscores-for-value-field-name">'Use hyphens, not underscores, for value field name'</a>
22558 </li>
22559 <li class="tocline1">
22560 <div class="section-number" id="toc_doc_section_10_2_15">10.2.15   </div>
22561 <a href="#value-field-name-cannot-start-with-digit">'Value field name cannot start with digit'</a>
22562 </li>
22563 <li class="tocline1">
22564 <div class="section-number" id="toc_doc_section_10_2_16">10.2.16   </div>
22565 <a href="#value-field-name-should-be-lower-case">'Value field name should be lower case'</a>
22566 </li>
22567 <li class="tocline1">
22568 <div class="section-number" id="toc_doc_section_10_2_17">10.2.17   </div>
22569 <a href="#value-field-name-should-be-longer-than-two-characters">'Value field name should be longer than two characters'</a>
22570 </li>
22571 <li class="tocline1">
22572 <div class="section-number" id="toc_doc_section_10_2_18">10.2.18   </div>
22573 <a href="#value-field-name-contains-invalid-character">'Value field name contains invalid character'</a>
22574 </li>
22575 <li class="tocline1">
22576 <div class="section-number" id="toc_doc_section_10_2_19">10.2.19   </div>
22577 <a href="#decoration-field-contains-invalid-character">'decoration field contains invalid character'</a>
22578 </li>
22579 <li class="tocline1">
22580 <div class="section-number" id="toc_doc_section_10_2_20">10.2.20   </div>
22581 <a href="#anchor-content-should-be-decimal-width">'Anchor content should be decimal width'</a>
22582 </li>
22583 <li class="tocline1">
22584 <div class="section-number" id="toc_doc_section_10_2_21">10.2.21   </div>
22585 <a href="#anchor-format-should-be-d">'Anchor format should be "%d"'</a>
22586 </li>
22587 <li class="tocline1">
22588 <div class="section-number" id="toc_doc_section_10_2_22">10.2.22   </div>
22589 <a href="#anchor-cannot-have-both-format-and-encoding-format">'Anchor cannot have both format and encoding format")'</a>
22590 </li>
22591 <li class="tocline1">
22592 <div class="section-number" id="toc_doc_section_10_2_23">10.2.23   </div>
22593 <a href="#max-width-only-valid-for-strings">'Max width only valid for strings'</a>
22594 </li>
22595 </ul>
22596 </li>
22597 </ul>
22598 </li>
22599 <li class="tocline0">
22600 <div class="section-number" id="toc_doc_section_11">11   </div>
22601 <a href="#howtos-focused-directions">Howtos: Focused Directions</a><ul class="toc top-toc">
22602 <li class="tocline1">
22603 <div class="section-number" id="toc_doc_section_11_1">11.1   </div>
22604 <a href="#howto-report-bugs">Howto: Report bugs</a>
22605 </li>
22606 <li class="tocline1">
22607 <div class="section-number" id="toc_doc_section_11_2">11.2   </div>
22608 <a href="#howto-install-libxo">Howto: Install libxo</a>
22609 </li>
22610 <li class="tocline1">
22611 <div class="section-number" id="toc_doc_section_11_3">11.3   </div>
22612 <a href="#howto-convert-command-line-applications">Howto: Convert command line applications</a><ul class="toc">
22613 <li class="tocline1">
22614 <div class="section-number" id="toc_doc_section_11_3_1">11.3.1   </div>
22615 <a href="#setting-up-the-context">Setting up the context</a>
22616 </li>
22617 <li class="tocline1">
22618 <div class="section-number" id="toc_doc_section_11_3_2">11.3.2   </div>
22619 <a href="#converting-printf-calls">Converting printf Calls</a>
22620 </li>
22621 <li class="tocline1">
22622 <div class="section-number" id="toc_doc_section_11_3_3">11.3.3   </div>
22623 <a href="#creating-hierarchy">Creating Hierarchy</a>
22624 </li>
22625 <li class="tocline1">
22626 <div class="section-number" id="toc_doc_section_11_3_4">11.3.4   </div>
22627 <a href="#converting-error-functions">Converting Error Functions</a>
22628 </li>
22629 </ul>
22630 </li>
22631 <li class="tocline1">
22632 <div class="section-number" id="toc_doc_section_11_4">11.4   </div>
22633 <a href="#howto-use-xo-in-shell-scripts">Howto: Use "xo" in Shell Scripts</a>
22634 </li>
22635 <li class="tocline1">
22636 <div class="section-number" id="toc_doc_section_11_5">11.5   </div>
22637 <a href="#howto-i18n">Howto: Internationalization (i18n)</a><ul class="toc"><li class="tocline1">
22638 <div class="section-number" id="toc_doc_section_11_5_1">11.5.1   </div>
22639 <a href="#i18n-and-xo_emit">i18n and xo_emit</a>
22640 </li></ul>
22641 </li>
22642 </ul>
22643 </li>
22644 <li class="tocline0">
22645 <div class="section-number" id="toc_doc_section_12">12   </div>
22646 <a href="#examples">Examples</a><ul class="toc top-toc"><li class="tocline1">
22647 <div class="section-number" id="toc_doc_section_12_1">12.1   </div>
22648 <a href="#unit-test">Unit Test</a>
22649 </li></ul>
22650 </li>
22651 <li class="tocline0"><a href="#doc.authors">Author's Address</a></li>
22652 </ul>
22653 </div>
22654 <hr class="noprint">
22655 <div class="content">
22656 <h1 id="doc_section_1" class="np">
22657 <div class="self-section-number">
22658 <a href="#doc_section_1">1_</a> </div>
22659 <a id="overview" href="#overview">Overview</a>
22660 </h1>
22661 <p id="doc_section_1_p_1">libxo - A Library for Generating Text, XML, JSON, and HTML Output</p>
22662 <p id="doc_section_1_p_2">You want to prepare for the future, but you need to live in the present. You'd love a flying car, but need to get to work today. You want to support features like XML, JSON, and HTML rendering to allow integration with NETCONF, REST, and web browsers, but you need to make text output for command line users.</p>
22663 <p id="doc_section_1_p_3">And you don't want multiple code paths that can't help but get out of sync:</p>
22664 <div id="doc_figure_u.1"></div> <pre>
22665     /* None of this "if (xml) {... } else {...}"  logic */
22666     if (xml) {
22667         /* some code to make xml*/
22668     } else {
22669         /* other code to make text */
22670         /* oops forgot to add something on both clauses! */
22671     }
22672
22673     /* And ifdefs are right out. */
22674     #ifdef MAKE_XML
22675         /* icky */
22676     #else
22677         /* pooh */
22678     #endif
22679             </pre> <p id="doc_section_1_p_5">But you'd really, really like all the fancy features that modern encoding formats can provide. libxo can help.</p>
22680 <p id="doc_section_1_p_6">The libxo library allows an application to generate text, XML, JSON, and HTML output using a common set of function calls. The application decides at run time which output style should be produced. The application calls a function "xo_emit" to product output that is described in a format string. A "field descriptor" tells libxo what the field is and what it means. Each field descriptor is placed in braces with a printf-like format string (<a href="#format-strings" title="Format Strings">Section 3.2</a>):</p>
22681 <div id="doc_figure_u.2"></div> <pre>
22682     xo_emit(" {:lines/%7ju} {:words/%7ju} "
22683             "{:characters/%7ju} {d:filename/%s}\n",
22684             linect, wordct, charct, file);
22685             </pre> <p id="doc_section_1_p_8">Each field can have a role, with the 'value' role being the default, and the role tells libxo how and when to render that field (see <a href="#field-roles" title="Field Roles">Section 3.2.1</a> for details). Modifiers change how the field is rendered in different output styles (see <a href="#field-modifiers" title="Field Modifiers">Section 3.2.2</a> for details. Output can then be generated in various style, using the "&#8209;&#8209;libxo" option:</p>
22686 <div id="doc_figure_u.3"></div> <pre>
22687     % wc /etc/motd
22688           25     165    1140 /etc/motd
22689     % wc --libxo xml,pretty,warn /etc/motd
22690     &lt;wc&gt;
22691       &lt;file&gt;
22692         &lt;lines&gt;25&lt;/lines&gt;
22693         &lt;words&gt;165&lt;/words&gt;
22694         &lt;characters&gt;1140&lt;/characters&gt;
22695         &lt;filename&gt;/etc/motd&lt;/filename&gt;
22696       &lt;/file&gt;
22697     &lt;/wc&gt;
22698     % wc --libxo json,pretty,warn /etc/motd
22699     {
22700       "wc": {
22701         "file": [
22702           {
22703             "lines": 25,
22704             "words": 165,
22705             "characters": 1140,
22706             "filename": "/etc/motd"
22707           }
22708         ]
22709       }
22710     }
22711     % wc --libxo html,pretty,warn /etc/motd
22712     &lt;div class="line"&gt;
22713       &lt;div class="text"&gt; &lt;/div&gt;
22714       &lt;div class="data" data-tag="lines"&gt;     25&lt;/div&gt;
22715       &lt;div class="text"&gt; &lt;/div&gt;
22716       &lt;div class="data" data-tag="words"&gt;    165&lt;/div&gt;
22717       &lt;div class="text"&gt; &lt;/div&gt;
22718       &lt;div class="data" data-tag="characters"&gt;   1140&lt;/div&gt;
22719       &lt;div class="text"&gt; &lt;/div&gt;
22720       &lt;div class="data" data-tag="filename"&gt;/etc/motd&lt;/div&gt;
22721     &lt;/div&gt;
22722             </pre> <p id="doc_section_1_p_10">Same code path, same format strings, same information, but it's rendered in distinct styles based on run-time flags.</p>
22723 </div>
22724 <hr class="noprint">
22725 <div class="content">
22726 <h1 id="doc_section_2" class="np">
22727 <div class="self-section-number">
22728 <a href="#doc_section_2">2_</a> </div>
22729 <a id="getting-libxo" href="#getting-libxo">Getting libxo</a>
22730 </h1>
22731 <p id="doc_section_2_p_1">libxo now ships as part of the FreeBSD Operating System (as of -11).</p>
22732 <p id="doc_section_2_p_2">libxo lives on github as:</p>
22733 <p id="doc_section_2_p_3"> <a href="https://github.com/Juniper/libxo">https://github.com/Juniper/libxo</a></p>
22734 <p id="doc_section_2_p_4">The latest release of libxo is available at:</p>
22735 <p id="doc_section_2_p_5"> <a href="https://github.com/Juniper/libxo/releases">https://github.com/Juniper/libxo/releases</a></p>
22736 <p id="doc_section_2_p_6">We are following the branching scheme from <a href="http://nvie.com/posts/a-successful-git-branching-model/">http://nvie.com/posts/a-successful-git-branching-model/</a> which means we will do development under the "develop" branch, and release from the "master" branch. To clone a developer tree, run the following command:</p>
22737 <div id="doc_figure_u.4"></div> <pre>
22738   git clone https://github.com/Juniper/libxo.git -b develop
22739             </pre> <p id="doc_section_2_p_8">We're using semantic release numbering, as defined in <a href="http://semver.org/spec/v2.0.0.html">http://semver.org/spec/v2.0.0.html</a>.</p>
22740 <p id="doc_section_2_p_9">libxo is open source, distributed under the BSD license. It shipped as part of the FreeBSD operating system starting with release 11.0.</p>
22741 <p id="doc_section_2_p_10">Issues, problems, and bugs should be directly to the issues page on our github site.</p>
22742 <p id="doc_section_2_p_11">Section Contents: </p>
22743 <ul>
22744 <li><a href="#downloading-libxo-source-code" title="Downloading libxo Source Code">Section 2.1</a></li>
22745 <li><a href="#building-libxo" title="Building libxo">Section 2.2</a></li>
22746 </ul>
22747 <div class="content">
22748 <h2 id="doc_section_2_1">
22749 <div class="self-section-number">
22750 <a href="#doc_section_2_1">2.1</a> </div>
22751 <a id="downloading-libxo-source-code" href="#downloading-libxo-source-code">Downloading libxo Source Code</a>
22752 </h2>
22753 <p id="doc_section_2_1_p_1">You can retrieve the source for libxo in two ways:</p>
22754 <p id="doc_section_2_1_p_2">A) Use a "distfile" for a specific release. We use github to maintain our releases. Visit github release page (<a href="https://github.com/Juniper/libxo/releases">https://github.com/Juniper/libxo/releases</a>) to see the list of releases. To download the latest, look for the release with the green "Latest release" button and the green "libxo&#8209;RELEASE.tar.gz" button under that section.</p>
22755 <p id="doc_section_2_1_p_3">After downloading that release's distfile, untar it as follows:</p>
22756 <div id="doc_figure_u.5"></div> <pre>
22757     tar -zxf libxo-RELEASE.tar.gz
22758     cd libxo-RELEASE
22759             </pre> <p id="doc_section_2_1_p_5">[Note: for Solaris users, your "tar" command lacks the "&#8209;z" flag, so you'll need to substitute "gzip -dc "file" | tar xf -" instead of "tar -zxf "file"".]</p>
22760 <p id="doc_section_2_1_p_6">B) Use the current build from github. This gives you the most recent source code, which might be less stable than a specific release. To build libxo from the git repo:</p>
22761 <div id="doc_figure_u.6"></div> <pre>
22762     git clone https://github.com/Juniper/libxo.git
22763     cd libxo
22764             </pre> <p id="doc_section_2_1_p_8">_BE AWARE_: The github repository does _not_ contain the files generated by "autoreconf", with the notable exception of the "m4" directory. Since these files (depcomp, configure, missing, install-sh, etc) are generated files, we keep them out of the source code repository.</p>
22765 <p id="doc_section_2_1_p_9">This means that if you download the a release distfile, these files will be ready and you'll just need to run "configure", but if you download the source code from svn, then you'll need to run "autoreconf" by hand. This step is done for you by the "setup.sh" script, described in the next section.</p>
22766 </div>
22767 <div class="content">
22768 <h2 id="doc_section_2_2">
22769 <div class="self-section-number">
22770 <a href="#doc_section_2_2">2.2</a> </div>
22771 <a id="building-libxo" href="#building-libxo">Building libxo</a>
22772 </h2>
22773 <p id="doc_section_2_2_p_1">To build libxo, you'll need to set up the build, run the "configure" script, run the "make" command, and run the regression tests.</p>
22774 <p id="doc_section_2_2_p_2">The following is a summary of the commands needed. These commands are explained in detail in the rest of this section.</p>
22775 <div id="doc_figure_u.7"></div> <pre>
22776     sh bin/setup.sh
22777     cd build
22778     ../configure
22779     make
22780     make test
22781     sudo make install
22782             </pre> <p id="doc_section_2_2_p_4">The following sections will walk through each of these steps with additional details and options, but the above directions should be all that's needed.</p>
22783 <p id="doc_section_2_2_p_5">Section Contents: </p>
22784 <ul>
22785 <li><a href="#setting-up-the-build" title="Setting up the build">Section 2.2.1</a></li>
22786 <li><a href="#running-the-configure-script" title='Running the "configure" Script'>Section 2.2.2</a></li>
22787 <li><a href="#installing-libxo" title="Installing libxo">Section 2.2.3</a></li>
22788 </ul>
22789 <div class="content">
22790 <h3 id="doc_section_2_2_1">
22791 <div class="self-section-number">
22792 <a href="#doc_section_2_2_1">2.2.1</a> </div>
22793 <a id="setting-up-the-build" href="#setting-up-the-build">Setting up the build</a>
22794 </h3>
22795 <p id="doc_section_2_2_1_p_1">[If you downloaded a distfile, you can skip this step.]</p>
22796 <p id="doc_section_2_2_1_p_2">Run the "setup.sh" script to set up the build. This script runs the "autoreconf" command to generate the "configure" script and other generated files.</p>
22797 <div id="doc_figure_u.8"></div> <pre>
22798     sh bin/setup.sh
22799             </pre> <p id="doc_section_2_2_1_p_4">Note: We're are currently using autoreconf version 2.69.</p>
22800 </div>
22801 <div class="content">
22802 <h3 id="doc_section_2_2_2">
22803 <div class="self-section-number">
22804 <a href="#doc_section_2_2_2">2.2.2</a> </div>
22805 <a id="running-the-configure-script" href="#running-the-configure-script">Running the "configure" Script</a>
22806 </h3>
22807 <p id="doc_section_2_2_2_p_1">Configure (and autoconf in general) provides a means of building software in diverse environments. Our configure script supports a set of options that can be used to adjust to your operating environment. Use "configure --help" to view these options.</p>
22808 <p id="doc_section_2_2_2_p_2">We use the "build" directory to keep object files and generated files away from the source tree.</p>
22809 <p id="doc_section_2_2_2_p_3">To run the configure script, change into the "build" directory, and run the "configure" script. Add any required options to the "../configure" command line.</p>
22810 <div id="doc_figure_u.9"></div> <pre>
22811     cd build
22812     ../configure
22813             </pre> <p id="doc_section_2_2_2_p_5">Expect to see the "configure" script generate the following error:</p>
22814 <div id="doc_figure_u.10"></div> <pre>
22815     /usr/bin/rm: cannot remove `libtoolT': No such file or directory
22816             </pre> <p id="doc_section_2_2_2_p_7">This error is harmless and can be safely ignored.</p>
22817 <p id="doc_section_2_2_2_p_8">By default, libxo installs architecture-independent files, including extension library files, in the /usr/local directories. To specify an installation prefix other than /usr/local for all installation files, include the --prefix=prefix option and specify an alternate location. To install just the extension library files in a different, user-defined location, include the --with-extensions-dir=dir option and specify the location where the extension libraries will live.</p>
22818 <div id="doc_figure_u.11"></div> <pre>
22819     cd build
22820     ../configure [OPTION]... [VAR=VALUE]...
22821             </pre> <p id="doc_section_2_2_2_p_10">Section Contents: </p>
22822 <ul>
22823 <li><a href="#running-the-make-command" title='Running the "make" command'>Section 2.2.2.1</a></li>
22824 <li><a href="#running-the-regression-tests" title="Running the Regression Tests">Section 2.2.2.2</a></li>
22825 </ul>
22826 <div class="content">
22827 <h4 id="doc_section_2_2_2_1">
22828 <div class="self-section-number">
22829 <a href="#doc_section_2_2_2_1">2.2.2.1</a> </div>
22830 <a id="running-the-make-command" href="#running-the-make-command">Running the "make" command</a>
22831 </h4>
22832 <p id="doc_section_2_2_2_1_p_1">Once the "configure" script is run, build the images using the "make" command:</p>
22833 <div id="doc_figure_u.12"></div> <pre>
22834     make
22835             </pre> </div>
22836 <div class="content">
22837 <h4 id="doc_section_2_2_2_2">
22838 <div class="self-section-number">
22839 <a href="#doc_section_2_2_2_2">2.2.2.2</a> </div>
22840 <a id="running-the-regression-tests" href="#running-the-regression-tests">Running the Regression Tests</a>
22841 </h4>
22842 <p id="doc_section_2_2_2_2_p_1">libxo includes a set of regression tests that can be run to ensure the software is working properly. These test are optional, but will help determine if there are any issues running libxo on your machine. To run the regression tests:</p>
22843 <div id="doc_figure_u.13"></div> <pre>
22844     make test
22845             </pre> </div>
22846 </div>
22847 <div class="content">
22848 <h3 id="doc_section_2_2_3">
22849 <div class="self-section-number">
22850 <a href="#doc_section_2_2_3">2.2.3</a> </div>
22851 <a id="installing-libxo" href="#installing-libxo">Installing libxo</a>
22852 </h3>
22853 <p id="doc_section_2_2_3_p_1">Once the software is built, you'll need to install libxo using the "make install" command. If you are the root user, or the owner of the installation directory, simply issue the command:</p>
22854 <div id="doc_figure_u.14"></div> <pre>
22855     make install
22856             </pre> <p id="doc_section_2_2_3_p_3">If you are not the "root" user and are using the "sudo" package, use:</p>
22857 <div id="doc_figure_u.15"></div> <pre>
22858     sudo make install
22859             </pre> <p id="doc_section_2_2_3_p_5">Verify the installation by viewing the output of "xo --version":</p>
22860 <div id="doc_figure_u.16"></div> <pre>
22861     % xo --version
22862     libxo version 0.3.5-git-develop
22863     xo version 0.3.5-git-develop
22864             </pre> </div>
22865 </div>
22866 </div>
22867 <hr class="noprint">
22868 <div class="content">
22869 <h1 id="doc_section_3" class="np">
22870 <div class="self-section-number">
22871 <a href="#doc_section_3">3_</a> </div>
22872 <a id="formatting-with-libxo" href="#formatting-with-libxo">Formatting with libxo</a>
22873 </h1>
22874 <p id="doc_section_3_p_1">Most unix commands emit text output aimed at humans. It is designed to be parsed and understood by a user. Humans are gifted at extracting details and pattern matching in such output. Often programmers need to extract information from this human-oriented output. Programmers use tools like grep, awk, and regular expressions to ferret out the pieces of information they need. Such solutions are fragile and require maintenance when output contents change or evolve, along with testing and validation.</p>
22875 <p id="doc_section_3_p_2">Modern tool developers favor encoding schemes like XML and JSON, which allow trivial parsing and extraction of data. Such formats are simple, well understood, hierarchical, easily parsed, and often integrate easier with common tools and environments. Changes to content can be done in ways that do not break existing users of the data, which can reduce maintenance costs and increase feature velocity.</p>
22876 <p id="doc_section_3_p_3">In addition, modern reality means that more output ends up in web browsers than in terminals, making HTML output valuable.</p>
22877 <p id="doc_section_3_p_4">libxo allows a single set of function calls in source code to generate traditional text output, as well as XML and JSON formatted data. HTML can also be generated; "&lt;div&gt;" elements surround the traditional text output, with attributes that detail how to render the data.</p>
22878 <p id="doc_section_3_p_5">A single libxo function call in source code is all that's required:</p>
22879 <div id="doc_figure_u.17"></div> <pre>
22880     xo_emit("Connecting to {:host}.{:domain}...\n", host, domain);
22881
22882     TEXT:
22883       Connecting to my-box.example.com...
22884     XML:
22885       &lt;host&gt;my-box&lt;/host&gt;
22886       &lt;domain&gt;example.com&lt;/domain&gt;
22887     JSON:
22888       "host": "my-box",
22889       "domain": "example.com"
22890     HTML:
22891        &lt;div class="line"&gt;
22892          &lt;div class="text"&gt;Connecting to &lt;/div&gt;
22893          &lt;div class="data" data-tag="host" 
22894               data-xpath="/top/host"&gt;my-box&lt;/div&gt;
22895          &lt;div class="text"&gt;.&lt;/div&gt;
22896          &lt;div class="data" data-tag="domain"
22897               data-xpath="/top/domain"&gt;example.com&lt;/div&gt;
22898          &lt;div class="text"&gt;...&lt;/div&gt;
22899        &lt;/div&gt;
22900             </pre> <p id="doc_section_3_p_7">Section Contents: </p>
22901 <ul>
22902 <li><a href="#encoding-styles" title="Encoding Styles">Section 3.1</a></li>
22903 <li><a href="#format-strings" title="Format Strings">Section 3.2</a></li>
22904 <li><a href="#representing-hierarchy" title="Representing Hierarchy">Section 3.3</a></li>
22905 </ul>
22906 <div class="content">
22907 <h2 id="doc_section_3_1">
22908 <div class="self-section-number">
22909 <a href="#doc_section_3_1">3.1</a> </div>
22910 <a id="encoding-styles" href="#encoding-styles">Encoding Styles</a>
22911 </h2>
22912 <p id="doc_section_3_1_p_1">There are four encoding styles supported by libxo:</p>
22913 <p id="doc_section_3_1_p_2"> </p>
22914 <ul>
22915 <li>TEXT output can be display on a terminal session, allowing compatibility with traditional command line usage.</li>
22916 <li>XML output is suitable for tools like XPath and protocols like NETCONF.</li>
22917 <li>JSON output can be used for RESTful APIs and integration with languages like Javascript and Python.</li>
22918 <li>HTML can be matched with a small CSS file to permit rendering in any HTML5 browser.</li>
22919 </ul>
22920 <p id="doc_section_3_1_p_3">In general, XML and JSON are suitable for encoding data, while TEXT is suited for terminal output and HTML is suited for display in a web browser (see <a href="#xohtml" title="xohtml">Section 8</a>).</p>
22921 <p id="doc_section_3_1_p_4">Section Contents: </p>
22922 <ul>
22923 <li><a href="#text-output" title="Text Output">Section 3.1.1</a></li>
22924 <li><a href="#xml-output" title="XML Output">Section 3.1.2</a></li>
22925 <li><a href="#json-output" title="JSON Output">Section 3.1.3</a></li>
22926 <li><a href="#html-output" title="HTML Output">Section 3.1.4</a></li>
22927 </ul>
22928 <div class="content">
22929 <h3 id="doc_section_3_1_1">
22930 <div class="self-section-number">
22931 <a href="#doc_section_3_1_1">3.1.1</a> </div>
22932 <a id="text-output" href="#text-output">Text Output</a>
22933 </h3>
22934 <p id="doc_section_3_1_1_p_1">Most traditional programs generate text output on standard output, with contents like:</p>
22935 <div id="doc_figure_u.18"></div> <pre>
22936     36      ./src
22937     40      ./bin
22938     90      .
22939             </pre> <p id="doc_section_3_1_1_p_3">In this example (taken from du source code), the code to generate this data might look like:</p>
22940 <div id="doc_figure_u.19"></div> <pre>
22941     printf("%d\t%s\n", num_blocks, path);
22942             </pre> <p id="doc_section_3_1_1_p_5">Simple, direct, obvious. But it's only making text output. Imagine using a single code path to make TEXT, XML, JSON or HTML, deciding at run time which to generate.</p>
22943 <p id="doc_section_3_1_1_p_6">libxo expands on the idea of printf format strings to make a single format containing instructions for creating multiple output styles:</p>
22944 <div id="doc_figure_u.20"></div> <pre>
22945     xo_emit("{:blocks/%d}\t{:path/%s}\n", num_blocks, path);
22946             </pre> <p id="doc_section_3_1_1_p_8">This line will generate the same text output as the earlier printf call, but also has enough information to generate XML, JSON, and HTML.</p>
22947 <p id="doc_section_3_1_1_p_9">The following sections introduce the other formats.</p>
22948 </div>
22949 <div class="content">
22950 <h3 id="doc_section_3_1_2">
22951 <div class="self-section-number">
22952 <a href="#doc_section_3_1_2">3.1.2</a> </div>
22953 <a id="xml-output" href="#xml-output">XML Output</a>
22954 </h3>
22955 <p id="doc_section_3_1_2_p_1">XML output consists of a hierarchical set of elements, each encoded with a start tag and an end tag. The element should be named for data value that it is encoding:</p>
22956 <div id="doc_figure_u.21"></div> <pre>
22957     &lt;item&gt;
22958       &lt;blocks&gt;36&lt;/blocks&gt;
22959       &lt;path&gt;./src&lt;/path&gt;
22960     &lt;/item&gt;
22961     &lt;item&gt;
22962       &lt;blocks&gt;40&lt;/blocks&gt;
22963       &lt;path&gt;./bin&lt;/path&gt;
22964     &lt;/item&gt;
22965     &lt;item&gt;
22966       &lt;blocks&gt;90&lt;/blocks&gt;
22967       &lt;path&gt;.&lt;/path&gt;
22968     &lt;/item&gt;
22969             </pre> <p id="doc_section_3_1_2_p_3">XML is a W3C standard for encoding data. See w3c.org/TR/xml for additional information.</p>
22970 </div>
22971 <div class="content">
22972 <h3 id="doc_section_3_1_3">
22973 <div class="self-section-number">
22974 <a href="#doc_section_3_1_3">3.1.3</a> </div>
22975 <a id="json-output" href="#json-output">JSON Output</a>
22976 </h3>
22977 <p id="doc_section_3_1_3_p_1">JSON output consists of a hierarchical set of objects and lists, each encoded with a quoted name, a colon, and a value. If the value is a string, it must be quoted, but numbers are not quoted. Objects are encoded using braces; lists are encoded using square brackets. Data inside objects and lists is separated using commas:</p>
22978 <div id="doc_figure_u.22"></div> <pre>
22979     items: [
22980         { "blocks": 36, "path" : "./src" },
22981         { "blocks": 40, "path" : "./bin" },
22982         { "blocks": 90, "path" : "./" }
22983     ]
22984             </pre> </div>
22985 <div class="content">
22986 <h3 id="doc_section_3_1_4">
22987 <div class="self-section-number">
22988 <a href="#doc_section_3_1_4">3.1.4</a> </div>
22989 <a id="html-output" href="#html-output">HTML Output</a>
22990 </h3>
22991 <p id="doc_section_3_1_4_p_1">HTML output is designed to allow the output to be rendered in a web browser with minimal effort. Each piece of output data is rendered inside a &lt;div&gt; element, with a class name related to the role of the data. By using a small set of class attribute values, a CSS stylesheet can render the HTML into rich text that mirrors the traditional text content.</p>
22992 <p id="doc_section_3_1_4_p_2">Additional attributes can be enabled to provide more details about the data, including data type, description, and an XPath location.</p>
22993 <div id="doc_figure_u.23"></div> <pre>
22994     &lt;div class="line"&gt;
22995       &lt;div class="data" data-tag="blocks"&gt;36&lt;/div&gt;
22996       &lt;div class="padding"&gt;      &lt;/div&gt;
22997       &lt;div class="data" data-tag="path"&gt;./src&lt;/div&gt;
22998     &lt;/div&gt;
22999     &lt;div class="line"&gt;
23000       &lt;div class="data" data-tag="blocks"&gt;40&lt;/div&gt;
23001       &lt;div class="padding"&gt;      &lt;/div&gt;
23002       &lt;div class="data" data-tag="path"&gt;./bin&lt;/div&gt;
23003     &lt;/div&gt;
23004     &lt;div class="line"&gt;
23005       &lt;div class="data" data-tag="blocks"&gt;90&lt;/div&gt;
23006       &lt;div class="padding"&gt;      &lt;/div&gt;
23007       &lt;div class="data" data-tag="path"&gt;./&lt;/div&gt;
23008     &lt;/div&gt;
23009             </pre> </div>
23010 </div>
23011 <div class="content">
23012 <h2 id="doc_section_3_2">
23013 <div class="self-section-number">
23014 <a href="#doc_section_3_2">3.2</a> </div>
23015 <a id="format-strings" href="#format-strings">Format Strings</a>
23016 </h2>
23017 <p id="doc_section_3_2_p_1">libxo uses format strings to control the rendering of data into the various output styles. Each format string contains a set of zero or more field descriptions, which describe independent data fields. Each field description contains a set of modifiers, a content string, and zero, one, or two format descriptors. The modifiers tell libxo what the field is and how to treat it, while the format descriptors are formatting instructions using printf-style format strings, telling libxo how to format the field. The field description is placed inside a set of braces, with a colon (":") after the modifiers and a slash ("/") before each format descriptors. Text may be intermixed with field descriptions within the format string.</p>
23018 <p id="doc_section_3_2_p_2">The field description is given as follows:</p>
23019 <div id="doc_figure_u.24"></div> <pre>
23020     '{' [ role | modifier ]* [',' long-names ]* ':' [ content ]
23021             [ '/' field-format [ '/' encoding-format ]] '}'
23022             </pre> <p id="doc_section_3_2_p_4">The role describes the function of the field, while the modifiers enable optional behaviors. The contents, field-format, and encoding-format are used in varying ways, based on the role. These are described in the following sections.</p>
23023 <p id="doc_section_3_2_p_5">In the following example, three field descriptors appear. The first is a padding field containing three spaces of padding, the second is a label ("In stock"), and the third is a value field ("in&#8209;stock"). The in-stock field has a "%u" format that will parse the next argument passed to the xo_emit function as an unsigned integer.</p>
23024 <div id="doc_figure_u.25"></div> <pre>
23025     xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\n", 65);
23026             </pre> <p id="doc_section_3_2_p_7">This single line of code can generate text (" In stock: 65\n"), XML ("&lt;in&#8209;stock&gt;65&lt;/in&#8209;stock&gt;"), JSON ('"in&#8209;stock": 6'), or HTML (too lengthy to be listed here).</p>
23027 <p id="doc_section_3_2_p_8">While roles and modifiers typically use single character for brevity, there are alternative names for each which allow more verbose formatting strings. These names must be preceded by a comma, and may follow any single-character values:</p>
23028 <div id="doc_figure_u.26"></div> <pre>
23029     xo_emit("{L,white,colon:In stock}{,key:in-stock/%u}\n", 65);
23030             </pre> <p id="doc_section_3_2_p_10">Section Contents: </p>
23031 <ul>
23032 <li><a href="#field-roles" title="Field Roles">Section 3.2.1</a></li>
23033 <li><a href="#field-modifiers" title="Field Modifiers">Section 3.2.2</a></li>
23034 <li><a href="#field-formatting" title="Field Formatting">Section 3.2.3</a></li>
23035 <li><a href="#utf-8-and-locale-strings" title="UTF-8 and Locale Strings">Section 3.2.4</a></li>
23036 <li><a href="#characters-outside-of-field-definitions" title="Characters Outside of Field Definitions">Section 3.2.5</a></li>
23037 <li><a href="#m-is-supported" title='"%m" Is Supported'>Section 3.2.6</a></li>
23038 <li><a href="#n-is-not-supported" title='"%n" Is Not Supported'>Section 3.2.7</a></li>
23039 <li><a href="#the-encoding-format-eformat" title="The Encoding Format (eformat)">Section 3.2.8</a></li>
23040 <li><a href="#content-strings" title="Content Strings">Section 3.2.9</a></li>
23041 <li><a href="#printf-like" title="Argument Validation">Section 3.2.10</a></li>
23042 <li><a href="#retain" title="Retaining Parsed Format Information">Section 3.2.11</a></li>
23043 <li><a href="#example" title="Example">Section 3.2.12</a></li>
23044 </ul>
23045 <div class="content">
23046 <h3 id="doc_section_3_2_1">
23047 <div class="self-section-number">
23048 <a href="#doc_section_3_2_1">3.2.1</a> </div>
23049 <a id="field-roles" href="#field-roles">Field Roles</a>
23050 </h3>
23051 <p id="doc_section_3_2_1_p_1">Field roles are optional, and indicate the role and formatting of the content. The roles are listed below; only one role is permitted:</p>
23052 <div id="doc_table_u.1"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23053 <thead><tr>
23054 <th class="left">R</th>
23055 <th class="left">Name</th>
23056 <th class="left">Description</th>
23057 </tr></thead>
23058 <tbody>
23059 <tr>
23060 <td>C</td>
23061 <td>color</td>
23062 <td>Field has color and effect controls</td>
23063 </tr>
23064 <tr>
23065 <td>D</td>
23066 <td>decoration</td>
23067 <td>Field is non-text (e.g., colon, comma)</td>
23068 </tr>
23069 <tr>
23070 <td>E</td>
23071 <td>error</td>
23072 <td>Field is an error message</td>
23073 </tr>
23074 <tr>
23075 <td>G</td>
23076 <td>gettext</td>
23077 <td>Call gettext(3) on the format string</td>
23078 </tr>
23079 <tr>
23080 <td>L</td>
23081 <td>label</td>
23082 <td>Field is text that prefixes a value</td>
23083 </tr>
23084 <tr>
23085 <td>N</td>
23086 <td>note</td>
23087 <td>Field is text that follows a value</td>
23088 </tr>
23089 <tr>
23090 <td>P</td>
23091 <td>padding</td>
23092 <td>Field is spaces needed for vertical alignment</td>
23093 </tr>
23094 <tr>
23095 <td>T</td>
23096 <td>title</td>
23097 <td>Field is a title value for headings</td>
23098 </tr>
23099 <tr>
23100 <td>U</td>
23101 <td>units</td>
23102 <td>Field is the units for the previous value field</td>
23103 </tr>
23104 <tr>
23105 <td>V</td>
23106 <td>value</td>
23107 <td>Field is the name of field (the default)</td>
23108 </tr>
23109 <tr>
23110 <td>W</td>
23111 <td>warning</td>
23112 <td>Field is a warning message</td>
23113 </tr>
23114 <tr>
23115 <td>[</td>
23116 <td>start-anchor</td>
23117 <td>Begin a section of anchored variable-width text</td>
23118 </tr>
23119 <tr>
23120 <td>]</td>
23121 <td>stop-anchor</td>
23122 <td>End a section of anchored variable-width text</td>
23123 </tr>
23124 </tbody>
23125 </table></div>
23126 <div id="doc_figure_u.27"></div> <pre>
23127     EXAMPLE:
23128         xo_emit("{L:Free}{D::}{P:   }{:free/%u} {U:Blocks}\n",
23129                 free_blocks);
23130             </pre> <p id="doc_section_3_2_1_p_3">When a role is not provided, the "value" role is used as the default.</p>
23131 <p id="doc_section_3_2_1_p_4">Roles and modifiers can also use more verbose names, when preceded by a comma:</p>
23132 <div id="doc_figure_u.28"></div> <pre>
23133     EXAMPLE:
23134         xo_emit("{,label:Free}{,decoration::}{,padding:   }"
23135                 "{,value:free/%u} {,units:Blocks}\n",
23136                 free_blocks);
23137             </pre> <p id="doc_section_3_2_1_p_6">Section Contents: </p>
23138 <ul>
23139 <li><a href="#color-role" title="The Color Role ({C:})">Section 3.2.1.1</a></li>
23140 <li><a href="#the-decoration-role-d" title="The Decoration Role ({D:})">Section 3.2.1.2</a></li>
23141 <li><a href="#gettext-role" title="The Gettext Role ({G:})">Section 3.2.1.3</a></li>
23142 <li><a href="#the-label-role-l" title="The Label Role ({L:})">Section 3.2.1.4</a></li>
23143 <li><a href="#the-note-role-n" title="The Note Role ({N:})">Section 3.2.1.5</a></li>
23144 <li><a href="#padding-role" title="The Padding Role ({P:})">Section 3.2.1.6</a></li>
23145 <li><a href="#the-title-role-t" title="The Title Role ({T:})">Section 3.2.1.7</a></li>
23146 <li><a href="#the-units-role-u" title="The Units Role ({U:})">Section 3.2.1.8</a></li>
23147 <li><a href="#the-value-role-v-and-" title="The Value Role ({V:} and {:})">Section 3.2.1.9</a></li>
23148 <li><a href="#anchor-role" title="The Anchor Roles ({[:} and {]:})">Section 3.2.1.10</a></li>
23149 </ul>
23150 <div class="content">
23151 <h4 id="doc_section_3_2_1_1">
23152 <div class="self-section-number">
23153 <a href="#doc_section_3_2_1_1">3.2.1.1</a> </div>
23154 <a id="color-role" href="#color-role">The Color Role ({C:})</a>
23155 </h4>
23156 <p id="doc_section_3_2_1_1_p_1">Colors and effects control how text values are displayed; they are used for display styles (TEXT and HTML).</p>
23157 <div id="doc_figure_u.29"></div> <pre>
23158     xo_emit("{C:bold}{:value}{C:no-bold}\n", value);
23159             </pre> <p id="doc_section_3_2_1_1_p_3">Colors and effects remain in effect until modified by other "C"-role fields.</p>
23160 <div id="doc_figure_u.30"></div> <pre>
23161     xo_emit("{C:bold}{C:inverse}both{C:no-bold}only inverse\n");
23162             </pre> <p id="doc_section_3_2_1_1_p_5">If the content is empty, the "reset" action is performed.</p>
23163 <div id="doc_figure_u.31"></div> <pre>
23164     xo_emit("{C:both,underline}{:value}{C:}\n", value);
23165             </pre> <p id="doc_section_3_2_1_1_p_7">The content should be a comma-separated list of zero or more colors or display effects.</p>
23166 <div id="doc_figure_u.32"></div> <pre>
23167     xo_emit("{C:bold,inverse}Ugly{C:no-bold,no-inverse}\n");
23168             </pre> <p id="doc_section_3_2_1_1_p_9">The color content can be either static, when placed directly within the field descriptor, or a printf-style format descriptor can be used, if preceded by a slash ("/"):</p>
23169 <div id="doc_figure_u.33"></div> <pre>
23170    xo_emit("{C:/%s%s}{:value}{C:}", need_bold ? "bold" : "",
23171            need_underline ? "underline" : "", value);
23172             </pre> <p id="doc_section_3_2_1_1_p_11">Color names are prefixed with either "fg&#8209;" or "bg&#8209;" to change the foreground and background colors, respectively.</p>
23173 <div id="doc_figure_u.34"></div> <pre>
23174     xo_emit("{C:/fg-%s,bg-%s}{Lwc:Cost}{:cost/%u}{C:reset}\n",
23175             fg_color, bg_color, cost);
23176             </pre> <p id="doc_section_3_2_1_1_p_13">The following table lists the supported effects:</p>
23177 <div id="doc_table_u.2"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23178 <thead><tr>
23179 <th class="left">Name</th>
23180 <th class="left">Description</th>
23181 </tr></thead>
23182 <tbody>
23183 <tr>
23184 <td>bg-XXXXX</td>
23185 <td>Change background color</td>
23186 </tr>
23187 <tr>
23188 <td>bold</td>
23189 <td>Start bold text effect</td>
23190 </tr>
23191 <tr>
23192 <td>fg-XXXXX</td>
23193 <td>Change foreground color</td>
23194 </tr>
23195 <tr>
23196 <td>inverse</td>
23197 <td>Start inverse (aka reverse) text effect</td>
23198 </tr>
23199 <tr>
23200 <td>no-bold</td>
23201 <td>Stop bold text effect</td>
23202 </tr>
23203 <tr>
23204 <td>no-inverse</td>
23205 <td>Stop inverse (aka reverse) text effect</td>
23206 </tr>
23207 <tr>
23208 <td>no-underline</td>
23209 <td>Stop underline text effect</td>
23210 </tr>
23211 <tr>
23212 <td>normal</td>
23213 <td>Reset effects (only)</td>
23214 </tr>
23215 <tr>
23216 <td>reset</td>
23217 <td>Reset colors and effects (restore defaults)</td>
23218 </tr>
23219 <tr>
23220 <td>underline</td>
23221 <td>Start underline text effect</td>
23222 </tr>
23223 </tbody>
23224 </table></div>
23225 <p id="doc_section_3_2_1_1_p_14">The following color names are supported:</p>
23226 <div id="doc_table_u.3"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23227 <thead><tr>
23228 <th class="left">Name</th>
23229 <th class="left">Description</th>
23230 </tr></thead>
23231 <tbody>
23232 <tr>
23233 <td>black</td>
23234 <td></td>
23235 </tr>
23236 <tr>
23237 <td>blue</td>
23238 <td></td>
23239 </tr>
23240 <tr>
23241 <td>cyan</td>
23242 <td></td>
23243 </tr>
23244 <tr>
23245 <td>default</td>
23246 <td>Default color for foreground or background</td>
23247 </tr>
23248 <tr>
23249 <td>green</td>
23250 <td></td>
23251 </tr>
23252 <tr>
23253 <td>magenta</td>
23254 <td></td>
23255 </tr>
23256 <tr>
23257 <td>red</td>
23258 <td></td>
23259 </tr>
23260 <tr>
23261 <td>white</td>
23262 <td></td>
23263 </tr>
23264 <tr>
23265 <td>yellow</td>
23266 <td></td>
23267 </tr>
23268 </tbody>
23269 </table></div>
23270 <p id="doc_section_3_2_1_1_p_15">When using colors, the developer should remember that users will change the foreground and background colors of terminal session according to their own tastes, so assuming that "blue" looks nice is never safe, and is a constant annoyance to your dear author. In addition, a significant percentage of users (1 in 12) will be color blind. Depending on color to convey critical information is not a good idea. Color should enhance output, but should not be used as the sole means of encoding information.</p>
23271 </div>
23272 <div class="content">
23273 <h4 id="doc_section_3_2_1_2">
23274 <div class="self-section-number">
23275 <a href="#doc_section_3_2_1_2">3.2.1.2</a> </div>
23276 <a id="the-decoration-role-d" href="#the-decoration-role-d">The Decoration Role ({D:})</a>
23277 </h4>
23278 <p id="doc_section_3_2_1_2_p_1">Decorations are typically punctuation marks such as colons, semi-colons, and commas used to decorate the text and make it simpler for human readers. By marking these distinctly, HTML usage scenarios can use CSS to direct their display parameters.</p>
23279 <div id="doc_figure_u.35"></div> <pre>
23280     xo_emit("{D:((}{:name}{D:))}\n", name);
23281             </pre> </div>
23282 <div class="content">
23283 <h4 id="doc_section_3_2_1_3">
23284 <div class="self-section-number">
23285 <a href="#doc_section_3_2_1_3">3.2.1.3</a> </div>
23286 <a id="gettext-role" href="#gettext-role">The Gettext Role ({G:})</a>
23287 </h4>
23288 <p id="doc_section_3_2_1_3_p_1">libxo supports internationalization (i18n) through its use of gettext(3). Use the "{G:}" role to request that the remaining part of the format string, following the "{G:}" field, be handled using gettext().</p>
23289 <p id="doc_section_3_2_1_3_p_2">Since gettext() uses the string as the key into the message catalog, libxo uses a simplified version of the format string that removes unimportant field formatting and modifiers, stopping minor formatting changes from impacting the expensive translation process. A developer change such as changing "/%06d" to "/%08d" should not force hand inspection of all .po files.</p>
23290 <p id="doc_section_3_2_1_3_p_3">The simplified version can be generated for a single message using the "xopo -s &lt;text&gt;" command, or an entire .pot can be translated using the "xopo -f &lt;input&gt; -o &lt;output&gt;" command.</p>
23291 <div id="doc_figure_u.36"></div> <pre>
23292    xo_emit("{G:}Invalid token\n");
23293             </pre> <p id="doc_section_3_2_1_3_p_5">The {G:} role allows a domain name to be set. gettext calls will continue to use that domain name until the current format string processing is complete, enabling a library function to emit strings using it's own catalog. The domain name can be either static as the content of the field, or a format can be used to get the domain name from the arguments.</p>
23294 <div id="doc_figure_u.37"></div> <pre>
23295    xo_emit("{G:libc}Service unavailable in restricted mode\n");
23296             </pre> <p id="doc_section_3_2_1_3_p_7">See <a href="#howto-i18n" title="Howto: Internationalization (i18n)">Section 11.5</a> for additional details.</p>
23297 </div>
23298 <div class="content">
23299 <h4 id="doc_section_3_2_1_4">
23300 <div class="self-section-number">
23301 <a href="#doc_section_3_2_1_4">3.2.1.4</a> </div>
23302 <a id="the-label-role-l" href="#the-label-role-l">The Label Role ({L:})</a>
23303 </h4>
23304 <p id="doc_section_3_2_1_4_p_1">Labels are text that appears before a value.</p>
23305 <div id="doc_figure_u.38"></div> <pre>
23306     xo_emit("{Lwc:Cost}{:cost/%u}\n", cost);
23307             </pre> </div>
23308 <div class="content">
23309 <h4 id="doc_section_3_2_1_5">
23310 <div class="self-section-number">
23311 <a href="#doc_section_3_2_1_5">3.2.1.5</a> </div>
23312 <a id="the-note-role-n" href="#the-note-role-n">The Note Role ({N:})</a>
23313 </h4>
23314 <p id="doc_section_3_2_1_5_p_1">Notes are text that appears after a value.</p>
23315 <div id="doc_figure_u.39"></div> <pre>
23316     xo_emit("{:cost/%u} {N:per year}\n", cost);
23317             </pre> </div>
23318 <div class="content">
23319 <h4 id="doc_section_3_2_1_6">
23320 <div class="self-section-number">
23321 <a href="#doc_section_3_2_1_6">3.2.1.6</a> </div>
23322 <a id="padding-role" href="#padding-role">The Padding Role ({P:})</a>
23323 </h4>
23324 <p id="doc_section_3_2_1_6_p_1">Padding represents whitespace used before and between fields.</p>
23325 <p id="doc_section_3_2_1_6_p_2">The padding content can be either static, when placed directly within the field descriptor, or a printf-style format descriptor can be used, if preceded by a slash ("/"):</p>
23326 <div id="doc_figure_u.40"></div> <pre>
23327     xo_emit("{P:        }{Lwc:Cost}{:cost/%u}\n", cost);
23328     xo_emit("{P:/%30s}{Lwc:Cost}{:cost/%u}\n", "", cost);
23329             </pre> </div>
23330 <div class="content">
23331 <h4 id="doc_section_3_2_1_7">
23332 <div class="self-section-number">
23333 <a href="#doc_section_3_2_1_7">3.2.1.7</a> </div>
23334 <a id="the-title-role-t" href="#the-title-role-t">The Title Role ({T:})</a>
23335 </h4>
23336 <p id="doc_section_3_2_1_7_p_1">Title are heading or column headers that are meant to be displayed to the user. The title can be either static, when placed directly within the field descriptor, or a printf-style format descriptor can be used, if preceded by a slash ("/"):</p>
23337 <div id="doc_figure_u.41"></div> <pre>
23338     xo_emit("{T:Interface Statistics}\n");
23339     xo_emit("{T:/%20.20s}{T:/%6.6s}\n", "Item Name", "Cost");
23340             </pre> <p id="doc_section_3_2_1_7_p_3">Title fields have an extra convenience feature; if both content and format are specified, instead of looking to the argument list for a value, the content is used, allowing a mixture of format and content within the field descriptor:</p>
23341 <div id="doc_figure_u.42"></div> <pre>
23342     xo_emit("{T:Name/%20s}{T:Count/%6s}\n");
23343             </pre> <p id="doc_section_3_2_1_7_p_5">Since the incoming argument is a string, the format must be "%s" or something suitable.</p>
23344 </div>
23345 <div class="content">
23346 <h4 id="doc_section_3_2_1_8">
23347 <div class="self-section-number">
23348 <a href="#doc_section_3_2_1_8">3.2.1.8</a> </div>
23349 <a id="the-units-role-u" href="#the-units-role-u">The Units Role ({U:})</a>
23350 </h4>
23351 <p id="doc_section_3_2_1_8_p_1">Units are the dimension by which values are measured, such as degrees, miles, bytes, and decibels. The units field carries this information for the previous value field.</p>
23352 <div id="doc_figure_u.43"></div> <pre>
23353     xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\n", miles);
23354             </pre> <p id="doc_section_3_2_1_8_p_3">Note that the sense of the 'w' modifier is reversed for units; a blank is added before the contents, rather than after it.</p>
23355 <p id="doc_section_3_2_1_8_p_4">When the XOF_UNITS flag is set, units are rendered in XML as the "units" attribute:</p>
23356 <div id="doc_figure_u.44"></div> <pre>
23357     &lt;distance units="miles"&gt;50&lt;/distance&gt;
23358             </pre> <p id="doc_section_3_2_1_8_p_6">Units can also be rendered in HTML as the "data&#8209;units" attribute:</p>
23359 <div id="doc_figure_u.45"></div> <pre>
23360     &lt;div class="data" data-tag="distance" data-units="miles"
23361          data-xpath="/top/data/distance"&gt;50&lt;/div&gt;
23362             </pre> </div>
23363 <div class="content">
23364 <h4 id="doc_section_3_2_1_9">
23365 <div class="self-section-number">
23366 <a href="#doc_section_3_2_1_9">3.2.1.9</a> </div>
23367 <a id="the-value-role-v-and-" href="#the-value-role-v-and-">The Value Role ({V:} and {:})</a>
23368 </h4>
23369 <p id="doc_section_3_2_1_9_p_1">The value role is used to represent the a data value that is interesting for the non-display output styles (XML and JSON). Value is the default role; if no other role designation is given, the field is a value. The field name must appear within the field descriptor, followed by one or two format descriptors. The first format descriptor is used for display styles (TEXT and HTML), while the second one is used for encoding styles (XML and JSON). If no second format is given, the encoding format defaults to the first format, with any minimum width removed. If no first format is given, both format descriptors default to "%s".</p>
23370 <div id="doc_figure_u.46"></div> <pre>
23371     xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\n",
23372             length, width, height);
23373     xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\n,
23374             author, poem, year);
23375             </pre> </div>
23376 <div class="content">
23377 <h4 id="doc_section_3_2_1_10">
23378 <div class="self-section-number">
23379 <a href="#doc_section_3_2_1_10">3.2.1.10</a> </div>
23380 <a id="anchor-role" href="#anchor-role">The Anchor Roles ({[:} and {]:})</a>
23381 </h4>
23382 <p id="doc_section_3_2_1_10_p_1">The anchor roles allow a set of strings by be padded as a group, but still be visible to xo_emit as distinct fields. Either the start or stop anchor can give a field width and it can be either directly in the descriptor or passed as an argument. Any fields between the start and stop anchor are padded to meet the minimum width given.</p>
23383 <p id="doc_section_3_2_1_10_p_2">To give a width directly, encode it as the content of the anchor tag:</p>
23384 <div id="doc_figure_u.47"></div> <pre>
23385     xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\n", min, max);
23386             </pre> <p id="doc_section_3_2_1_10_p_4">To pass a width as an argument, use "%d" as the format, which must appear after the "/". Note that only "%d" is supported for widths. Using any other value could ruin your day.</p>
23387 <div id="doc_figure_u.48"></div> <pre>
23388     xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\n", width, min, max);
23389             </pre> <p id="doc_section_3_2_1_10_p_6">If the width is negative, padding will be added on the right, suitable for left justification. Otherwise the padding will be added to the left of the fields between the start and stop anchors, suitable for right justification. If the width is zero, nothing happens. If the number of columns of output between the start and stop anchors is less than the absolute value of the given width, nothing happens.</p>
23390 <p id="doc_section_3_2_1_10_p_7">Widths over 8k are considered probable errors and not supported. If XOF_WARN is set, a warning will be generated.</p>
23391 </div>
23392 </div>
23393 <div class="content">
23394 <h3 id="doc_section_3_2_2">
23395 <div class="self-section-number">
23396 <a href="#doc_section_3_2_2">3.2.2</a> </div>
23397 <a id="field-modifiers" href="#field-modifiers">Field Modifiers</a>
23398 </h3>
23399 <p id="doc_section_3_2_2_p_1">Field modifiers are flags which modify the way content emitted for particular output styles:</p>
23400 <div id="doc_table_u.4"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23401 <thead><tr>
23402 <th class="left">M</th>
23403 <th class="left">Name</th>
23404 <th class="left">Description</th>
23405 </tr></thead>
23406 <tbody>
23407 <tr>
23408 <td>a</td>
23409 <td>argument</td>
23410 <td>The content appears as a 'const char *' argument</td>
23411 </tr>
23412 <tr>
23413 <td>c</td>
23414 <td>colon</td>
23415 <td>A colon (":") is appended after the label</td>
23416 </tr>
23417 <tr>
23418 <td>d</td>
23419 <td>display</td>
23420 <td>Only emit field for display styles (text/HTML)</td>
23421 </tr>
23422 <tr>
23423 <td>e</td>
23424 <td>encoding</td>
23425 <td>Only emit for encoding styles (XML/JSON)</td>
23426 </tr>
23427 <tr>
23428 <td>g</td>
23429 <td>gettext</td>
23430 <td>Call gettext on field's render content</td>
23431 </tr>
23432 <tr>
23433 <td>h</td>
23434 <td>humanize (hn)</td>
23435 <td>Format large numbers in human-readable style</td>
23436 </tr>
23437 <tr>
23438 <td></td>
23439 <td>hn-space</td>
23440 <td>Humanize: Place space between numeric and unit</td>
23441 </tr>
23442 <tr>
23443 <td></td>
23444 <td>hn-decimal</td>
23445 <td>Humanize: Add a decimal digit, if number &lt; 10</td>
23446 </tr>
23447 <tr>
23448 <td></td>
23449 <td>hn-1000</td>
23450 <td>Humanize: Use 1000 as divisor instead of 1024</td>
23451 </tr>
23452 <tr>
23453 <td>k</td>
23454 <td>key</td>
23455 <td>Field is a key, suitable for XPath predicates</td>
23456 </tr>
23457 <tr>
23458 <td>l</td>
23459 <td>leaf-list</td>
23460 <td>Field is a leaf-list</td>
23461 </tr>
23462 <tr>
23463 <td>n</td>
23464 <td>no-quotes</td>
23465 <td>Do not quote the field when using JSON style</td>
23466 </tr>
23467 <tr>
23468 <td>p</td>
23469 <td>plural</td>
23470 <td>Gettext: Use comma-separated plural form</td>
23471 </tr>
23472 <tr>
23473 <td>q</td>
23474 <td>quotes</td>
23475 <td>Quote the field when using JSON style</td>
23476 </tr>
23477 <tr>
23478 <td>t</td>
23479 <td>trim</td>
23480 <td>Trim leading and trailing whitespace</td>
23481 </tr>
23482 <tr>
23483 <td>w</td>
23484 <td>white</td>
23485 <td>A blank (" ") is appended after the label</td>
23486 </tr>
23487 </tbody>
23488 </table></div>
23489 <p id="doc_section_3_2_2_p_2">Roles and modifiers can also use more verbose names, when preceded by a comma. For example, the modifier string "Lwc" (or "L,white,colon") means the field has a label role (text that describes the next field) and should be followed by a colon ('c') and a space ('w'). The modifier string "Vkq" (or ":key,quote") means the field has a value role (the default role), that it is a key for the current instance, and that the value should be quoted when encoded for JSON.</p>
23490 <p id="doc_section_3_2_2_p_3">Section Contents: </p>
23491 <ul>
23492 <li><a href="#the-argument-modifier-a" title="The Argument Modifier ({a:})">Section 3.2.2.1</a></li>
23493 <li><a href="#the-colon-modifier-c" title="The Colon Modifier ({c:})">Section 3.2.2.2</a></li>
23494 <li><a href="#the-display-modifier-d" title="The Display Modifier ({d:})">Section 3.2.2.3</a></li>
23495 <li><a href="#e-modifier" title="The Encoding Modifier ({e:})">Section 3.2.2.4</a></li>
23496 <li><a href="#gettext-modifier" title="The Gettext Modifier ({g:})">Section 3.2.2.5</a></li>
23497 <li><a href="#the-humanize-modifier-h" title="The Humanize Modifier ({h:})">Section 3.2.2.6</a></li>
23498 <li><a href="#the-key-modifier-k" title="The Key Modifier ({k:})">Section 3.2.2.7</a></li>
23499 <li><a href="#the-leaf-list-modifier-l" title="The Leaf-List Modifier ({l:})">Section 3.2.2.8</a></li>
23500 <li><a href="#the-no-quotes-modifier-n" title="The No-Quotes Modifier ({n:})">Section 3.2.2.9</a></li>
23501 <li><a href="#plural-modifier" title="The Plural Modifier ({p:})">Section 3.2.2.10</a></li>
23502 <li><a href="#the-quotes-modifier-q" title="The Quotes Modifier ({q:})">Section 3.2.2.11</a></li>
23503 <li><a href="#the-trim-modifier-t" title="The Trim Modifier ({t:})">Section 3.2.2.12</a></li>
23504 <li><a href="#the-white-space-modifier-w" title="The White Space Modifier ({w:})">Section 3.2.2.13</a></li>
23505 </ul>
23506 <div class="content">
23507 <h4 id="doc_section_3_2_2_1">
23508 <div class="self-section-number">
23509 <a href="#doc_section_3_2_2_1">3.2.2.1</a> </div>
23510 <a id="the-argument-modifier-a" href="#the-argument-modifier-a">The Argument Modifier ({a:})</a>
23511 </h4>
23512 <p id="doc_section_3_2_2_1_p_1">The argument modifier indicates that the content of the field descriptor will be placed as a UTF-8 string (const char *) argument within the xo_emit parameters.</p>
23513 <div id="doc_figure_u.49"></div> <pre>
23514     EXAMPLE:
23515       xo_emit("{La:} {a:}\n", "Label text", "label", "value");
23516     TEXT:
23517       Label text value
23518     JSON:
23519       "label": "value"
23520     XML:
23521       &lt;label&gt;value&lt;/label&gt;
23522             </pre> <p id="doc_section_3_2_2_1_p_3">The argument modifier allows field names for value fields to be passed on the stack, avoiding the need to build a field descriptor using snprintf. For many field roles, the argument modifier is not needed, since those roles have specific mechanisms for arguments, such as "{C:fg&#8209;%s}".</p>
23523 </div>
23524 <div class="content">
23525 <h4 id="doc_section_3_2_2_2">
23526 <div class="self-section-number">
23527 <a href="#doc_section_3_2_2_2">3.2.2.2</a> </div>
23528 <a id="the-colon-modifier-c" href="#the-colon-modifier-c">The Colon Modifier ({c:})</a>
23529 </h4>
23530 <p id="doc_section_3_2_2_2_p_1">The colon modifier appends a single colon to the data value:</p>
23531 <div id="doc_figure_u.50"></div> <pre>
23532     EXAMPLE:
23533       xo_emit("{Lc:Name}{:name}\n", "phil");
23534     TEXT:
23535       Name:phil
23536             </pre> <p id="doc_section_3_2_2_2_p_3">The colon modifier is only used for the TEXT and HTML output styles. It is commonly combined with the space modifier ('{w:}'). It is purely a convenience feature.</p>
23537 </div>
23538 <div class="content">
23539 <h4 id="doc_section_3_2_2_3">
23540 <div class="self-section-number">
23541 <a href="#doc_section_3_2_2_3">3.2.2.3</a> </div>
23542 <a id="the-display-modifier-d" href="#the-display-modifier-d">The Display Modifier ({d:})</a>
23543 </h4>
23544 <p id="doc_section_3_2_2_3_p_1">The display modifier indicated the field should only be generated for the display output styles, TEXT and HTML.</p>
23545 <div id="doc_figure_u.51"></div> <pre>
23546     EXAMPLE:
23547       xo_emit("{Lcw:Name}{d:name} {:id/%d}\n", "phil", 1);
23548     TEXT:
23549       Name: phil 1
23550     XML:
23551       &lt;id&gt;1&lt;/id&gt;
23552             </pre> <p id="doc_section_3_2_2_3_p_3">The display modifier is the opposite of the encoding modifier, and they are often used to give to distinct views of the underlying data.</p>
23553 </div>
23554 <div class="content">
23555 <h4 id="doc_section_3_2_2_4">
23556 <div class="self-section-number">
23557 <a href="#doc_section_3_2_2_4">3.2.2.4</a> </div>
23558 <a id="e-modifier" href="#e-modifier">The Encoding Modifier ({e:})</a>
23559 </h4>
23560 <p id="doc_section_3_2_2_4_p_1">The display modifier indicated the field should only be generated for the display output styles, TEXT and HTML.</p>
23561 <div id="doc_figure_u.52"></div> <pre>
23562     EXAMPLE:
23563       xo_emit("{Lcw:Name}{:name} {e:id/%d}\n", "phil", 1);
23564     TEXT:
23565       Name: phil
23566     XML:
23567       &lt;name&gt;phil&lt;/name&gt;&lt;id&gt;1&lt;/id&gt;
23568             </pre> <p id="doc_section_3_2_2_4_p_3">The encoding modifier is the opposite of the display modifier, and they are often used to give to distinct views of the underlying data.</p>
23569 </div>
23570 <div class="content">
23571 <h4 id="doc_section_3_2_2_5">
23572 <div class="self-section-number">
23573 <a href="#doc_section_3_2_2_5">3.2.2.5</a> </div>
23574 <a id="gettext-modifier" href="#gettext-modifier">The Gettext Modifier ({g:})</a>
23575 </h4>
23576 <p id="doc_section_3_2_2_5_p_1">The gettext modifier is used to translate individual fields using the gettext domain (typically set using the "{G:}" role) and current language settings. Once libxo renders the field value, it is passed to gettext(3), where it is used as a key to find the native language translation.</p>
23577 <p id="doc_section_3_2_2_5_p_2">In the following example, the strings "State" and "full" are passed to gettext() to find locale-based translated strings.</p>
23578 <div id="doc_figure_u.53"></div> <pre>
23579     xo_emit("{Lgwc:State}{g:state}\n", "full");
23580             </pre> <p id="doc_section_3_2_2_5_p_4">See <a href="#gettext-role" title="The Gettext Role ({G:})">Section 3.2.1.3</a>, <a href="#plural-modifier" title="The Plural Modifier ({p:})">Section 3.2.2.10</a>, and <a href="#howto-i18n" title="Howto: Internationalization (i18n)">Section 11.5</a> for additional details.</p>
23581 </div>
23582 <div class="content">
23583 <h4 id="doc_section_3_2_2_6">
23584 <div class="self-section-number">
23585 <a href="#doc_section_3_2_2_6">3.2.2.6</a> </div>
23586 <a id="the-humanize-modifier-h" href="#the-humanize-modifier-h">The Humanize Modifier ({h:})</a>
23587 </h4>
23588 <p id="doc_section_3_2_2_6_p_1">The humanize modifier is used to render large numbers as in a human-readable format. While numbers like "44470272" are completely readable to computers and savants, humans will generally find "44M" more meaningful.</p>
23589 <p id="doc_section_3_2_2_6_p_2">"hn" can be used as an alias for "humanize".</p>
23590 <p id="doc_section_3_2_2_6_p_3">The humanize modifier only affects display styles (TEXT and HMTL). The "no&#8209;humanize" option (See <a href="#options" title="Command-line Arguments">Section 4</a>) will block the function of the humanize modifier.</p>
23591 <p id="doc_section_3_2_2_6_p_4">There are a number of modifiers that affect details of humanization. These are only available in as full names, not single characters. The "hn&#8209;space" modifier places a space between the number and any multiplier symbol, such as "M" or "K" (ex: "44 K"). The "hn&#8209;decimal" modifier will add a decimal point and a single tenths digit when the number is less than 10 (ex: "4.4K"). The "hn&#8209;1000" modifier will use 1000 as divisor instead of 1024, following the JEDEC-standard instead of the more natural binary powers-of-two tradition.</p>
23592 <div id="doc_figure_u.54"></div> <pre>
23593     EXAMPLE:
23594         xo_emit("{h:input/%u}, {h,hn-space:output/%u}, "
23595             "{h,hn-decimal:errors/%u}, {h,hn-1000:capacity/%u}, "
23596             "{h,hn-decimal:remaining/%u}\n",
23597             input, output, errors, capacity, remaining);
23598     TEXT:
23599         21, 57 K, 96M, 44M, 1.2G
23600             </pre> <p id="doc_section_3_2_2_6_p_6">In the HTML style, the original numeric value is rendered in the "data&#8209;number" attribute on the &lt;div&gt; element:</p>
23601 <div id="doc_figure_u.55"></div> <pre>
23602     &lt;div class="data" data-tag="errors"
23603          data-number="100663296"&gt;96M&lt;/div&gt;
23604             </pre> </div>
23605 <div class="content">
23606 <h4 id="doc_section_3_2_2_7">
23607 <div class="self-section-number">
23608 <a href="#doc_section_3_2_2_7">3.2.2.7</a> </div>
23609 <a id="the-key-modifier-k" href="#the-key-modifier-k">The Key Modifier ({k:})</a>
23610 </h4>
23611 <p id="doc_section_3_2_2_7_p_1">The key modifier is used to indicate that a particular field helps uniquely identify an instance of list data.</p>
23612 <div id="doc_figure_u.56"></div> <pre>
23613     EXAMPLE:
23614         xo_open_list("user");
23615         for (i = 0; i &lt; num_users; i++) {
23616             xo_open_instance("user");
23617             xo_emit("User {k:name} has {:count} tickets\n",
23618                user[i].u_name, user[i].u_tickets);
23619             xo_close_instance("user");
23620         }
23621         xo_close_list("user");
23622             </pre> <p id="doc_section_3_2_2_7_p_3">Currently the key modifier is only used when generating XPath value for the HTML output style when XOF_XPATH is set, but other uses are likely in the near future.</p>
23623 </div>
23624 <div class="content">
23625 <h4 id="doc_section_3_2_2_8">
23626 <div class="self-section-number">
23627 <a href="#doc_section_3_2_2_8">3.2.2.8</a> </div>
23628 <a id="the-leaf-list-modifier-l" href="#the-leaf-list-modifier-l">The Leaf-List Modifier ({l:})</a>
23629 </h4>
23630 <p id="doc_section_3_2_2_8_p_1">The leaf-list modifier is used to distinguish lists where each instance consists of only a single value. In XML, these are rendered as single elements, where JSON renders them as arrays.</p>
23631 <div id="doc_figure_u.57"></div> <pre>
23632     EXAMPLE:
23633         for (i = 0; i &lt; num_users; i++) {
23634             xo_emit("Member {l:user}\n", user[i].u_name);
23635         }
23636     XML:
23637         &lt;user&gt;phil&lt;/user&gt;
23638         &lt;user&gt;pallavi&lt;/user&gt;
23639     JSON:
23640         "user": [ "phil", "pallavi" ]
23641             </pre> <p id="doc_section_3_2_2_8_p_3">The name of the field must match the name of the leaf list.</p>
23642 </div>
23643 <div class="content">
23644 <h4 id="doc_section_3_2_2_9">
23645 <div class="self-section-number">
23646 <a href="#doc_section_3_2_2_9">3.2.2.9</a> </div>
23647 <a id="the-no-quotes-modifier-n" href="#the-no-quotes-modifier-n">The No-Quotes Modifier ({n:})</a>
23648 </h4>
23649 <p id="doc_section_3_2_2_9_p_1">The no-quotes modifier (and its twin, the 'quotes' modifier) affect the quoting of values in the JSON output style. JSON uses quotes for string value, but no quotes for numeric, boolean, and null data. xo_emit applies a simple heuristic to determine whether quotes are needed, but often this needs to be controlled by the caller.</p>
23650 <div id="doc_figure_u.58"></div> <pre>
23651     EXAMPLE:
23652       const char *bool = is_true ? "true" : "false";
23653       xo_emit("{n:fancy/%s}", bool);
23654     JSON:
23655       "fancy": true
23656             </pre> </div>
23657 <div class="content">
23658 <h4 id="doc_section_3_2_2_10">
23659 <div class="self-section-number">
23660 <a href="#doc_section_3_2_2_10">3.2.2.10</a> </div>
23661 <a id="plural-modifier" href="#plural-modifier">The Plural Modifier ({p:})</a>
23662 </h4>
23663 <p id="doc_section_3_2_2_10_p_1">The plural modifier selects the appropriate plural form of an expression based on the most recent number emitted and the current language settings. The contents of the field should be the singular and plural English values, separated by a comma:</p>
23664 <div id="doc_figure_u.59"></div> <pre>
23665     xo_emit("{:bytes} {Ngp:byte,bytes}\n", bytes);
23666             </pre> <p id="doc_section_3_2_2_10_p_3">The plural modifier is meant to work with the gettext modifier ({g:}) but can work independently. See <a href="#gettext-modifier" title="The Gettext Modifier ({g:})">Section 3.2.2.5</a>.</p>
23667 <p id="doc_section_3_2_2_10_p_4">When used without the gettext modifier or when the message does not appear in the message catalog, the first token is chosen when the last numeric value is equal to 1; otherwise the second value is used, mimicking the simple pluralization rules of English.</p>
23668 <p id="doc_section_3_2_2_10_p_5">When used with the gettext modifier, the ngettext(3) function is called to handle the heavy lifting, using the message catalog to convert the singular and plural forms into the native language.</p>
23669 </div>
23670 <div class="content">
23671 <h4 id="doc_section_3_2_2_11">
23672 <div class="self-section-number">
23673 <a href="#doc_section_3_2_2_11">3.2.2.11</a> </div>
23674 <a id="the-quotes-modifier-q" href="#the-quotes-modifier-q">The Quotes Modifier ({q:})</a>
23675 </h4>
23676 <p id="doc_section_3_2_2_11_p_1">The quotes modifier (and its twin, the 'no&#8209;quotes' modifier) affect the quoting of values in the JSON output style. JSON uses quotes for string value, but no quotes for numeric, boolean, and null data. xo_emit applies a simple heuristic to determine whether quotes are needed, but often this needs to be controlled by the caller.</p>
23677 <div id="doc_figure_u.60"></div> <pre>
23678     EXAMPLE:
23679       xo_emit("{q:time/%d}", 2014);
23680     JSON:
23681       "year": "2014"
23682             </pre> <p id="doc_section_3_2_2_11_p_3">The heuristic is based on the format; if the format uses any of the following conversion specifiers, then no quotes are used:</p>
23683 <div id="doc_figure_u.61"></div> <pre>
23684     d i o u x X D O U e E f F g G a A c C p
23685             </pre> </div>
23686 <div class="content">
23687 <h4 id="doc_section_3_2_2_12">
23688 <div class="self-section-number">
23689 <a href="#doc_section_3_2_2_12">3.2.2.12</a> </div>
23690 <a id="the-trim-modifier-t" href="#the-trim-modifier-t">The Trim Modifier ({t:})</a>
23691 </h4>
23692 <p id="doc_section_3_2_2_12_p_1">The trim modifier removes any leading or trailing whitespace from the value.</p>
23693 <div id="doc_figure_u.62"></div> <pre>
23694     EXAMPLE:
23695       xo_emit("{t:description}", "   some  input   ");
23696     JSON:
23697       "description": "some input"
23698             </pre> </div>
23699 <div class="content">
23700 <h4 id="doc_section_3_2_2_13">
23701 <div class="self-section-number">
23702 <a href="#doc_section_3_2_2_13">3.2.2.13</a> </div>
23703 <a id="the-white-space-modifier-w" href="#the-white-space-modifier-w">The White Space Modifier ({w:})</a>
23704 </h4>
23705 <p id="doc_section_3_2_2_13_p_1">The white space modifier appends a single space to the data value:</p>
23706 <div id="doc_figure_u.63"></div> <pre>
23707     EXAMPLE:
23708       xo_emit("{Lw:Name}{:name}\n", "phil");
23709     TEXT:
23710       Name phil
23711             </pre> <p id="doc_section_3_2_2_13_p_3">The white space modifier is only used for the TEXT and HTML output styles. It is commonly combined with the colon modifier ('{c:}'). It is purely a convenience feature.</p>
23712 <p id="doc_section_3_2_2_13_p_4">Note that the sense of the 'w' modifier is reversed for the units role ({Uw:}); a blank is added before the contents, rather than after it.</p>
23713 </div>
23714 </div>
23715 <div class="content">
23716 <h3 id="doc_section_3_2_3">
23717 <div class="self-section-number">
23718 <a href="#doc_section_3_2_3">3.2.3</a> </div>
23719 <a id="field-formatting" href="#field-formatting">Field Formatting</a>
23720 </h3>
23721 <p id="doc_section_3_2_3_p_1">The field format is similar to the format string for printf(3). Its use varies based on the role of the field, but generally is used to format the field's contents.</p>
23722 <p id="doc_section_3_2_3_p_2">If the format string is not provided for a value field, it defaults to "%s".</p>
23723 <p id="doc_section_3_2_3_p_3">Note a field definition can contain zero or more printf-style 'directives', which are sequences that start with a '%' and end with one of following characters: "diouxXDOUeEfFgGaAcCsSp". Each directive is matched by one of more arguments to the xo_emit function.</p>
23724 <p id="doc_section_3_2_3_p_4">The format string has the form:</p>
23725 <div id="doc_figure_u.64"></div> <pre>
23726   '%' format-modifier * format-character
23727             </pre> <p id="doc_section_3_2_3_p_6">The format- modifier can be:</p>
23728 <p id="doc_section_3_2_3_p_7"> </p>
23729 <ul>
23730 <li>a '#' character, indicating the output value should be prefixed with '0x', typically to indicate a base 16 (hex) value.</li>
23731 <li>a minus sign ('&#8209;'), indicating the output value should be padded on the right instead of the left.</li>
23732 <li>a leading zero ('0') indicating the output value should be padded on the left with zeroes instead of spaces (' ').</li>
23733 <li>one or more digits ('0' - '9') indicating the minimum width of the argument. If the width in columns of the output value is less than the minimum width, the value will be padded to reach the minimum.</li>
23734 <li>a period followed by one or more digits indicating the maximum number of bytes which will be examined for a string argument, or the maximum width for a non-string argument. When handling ASCII strings this functions as the field width but for multi-byte characters, a single character may be composed of multiple bytes. xo_emit will never dereference memory beyond the given number of bytes.</li>
23735 <li>a second period followed by one or more digits indicating the maximum width for a string argument. This modifier cannot be given for non-string arguments.</li>
23736 <li>one or more 'h' characters, indicating shorter input data.</li>
23737 <li>one or more 'l' characters, indicating longer input data.</li>
23738 <li>a 'z' character, indicating a 'size_t' argument.</li>
23739 <li>a 't' character, indicating a 'ptrdiff_t' argument.</li>
23740 <li>a ' ' character, indicating a space should be emitted before positive numbers.</li>
23741 <li>a '+' character, indicating sign should emitted before any number.</li>
23742 </ul>
23743 <p id="doc_section_3_2_3_p_8">Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be removed eventually.</p>
23744 <p id="doc_section_3_2_3_p_9">The format character is described in the following table:</p>
23745 <div id="doc_table_u.5"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23746 <thead><tr>
23747 <th class="left">Ltr</th>
23748 <th class="left">Argument Type</th>
23749 <th class="left">Format</th>
23750 </tr></thead>
23751 <tbody>
23752 <tr>
23753 <td>d</td>
23754 <td>int</td>
23755 <td>base 10 (decimal)</td>
23756 </tr>
23757 <tr>
23758 <td>i</td>
23759 <td>int</td>
23760 <td>base 10 (decimal)</td>
23761 </tr>
23762 <tr>
23763 <td>o</td>
23764 <td>int</td>
23765 <td>base 8 (octal)</td>
23766 </tr>
23767 <tr>
23768 <td>u</td>
23769 <td>unsigned</td>
23770 <td>base 10 (decimal)</td>
23771 </tr>
23772 <tr>
23773 <td>x</td>
23774 <td>unsigned</td>
23775 <td>base 16 (hex)</td>
23776 </tr>
23777 <tr>
23778 <td>X</td>
23779 <td>unsigned long</td>
23780 <td>base 16 (hex)</td>
23781 </tr>
23782 <tr>
23783 <td>D</td>
23784 <td>long</td>
23785 <td>base 10 (decimal)</td>
23786 </tr>
23787 <tr>
23788 <td>O</td>
23789 <td>unsigned long</td>
23790 <td>base 8 (octal)</td>
23791 </tr>
23792 <tr>
23793 <td>U</td>
23794 <td>unsigned long</td>
23795 <td>base 10 (decimal)</td>
23796 </tr>
23797 <tr>
23798 <td>e</td>
23799 <td>double</td>
23800 <td>[-]d.ddde+-dd</td>
23801 </tr>
23802 <tr>
23803 <td>E</td>
23804 <td>double</td>
23805 <td>[-]d.dddE+-dd</td>
23806 </tr>
23807 <tr>
23808 <td>f</td>
23809 <td>double</td>
23810 <td>[-]ddd.ddd</td>
23811 </tr>
23812 <tr>
23813 <td>F</td>
23814 <td>double</td>
23815 <td>[-]ddd.ddd</td>
23816 </tr>
23817 <tr>
23818 <td>g</td>
23819 <td>double</td>
23820 <td>as 'e' or 'f'</td>
23821 </tr>
23822 <tr>
23823 <td>G</td>
23824 <td>double</td>
23825 <td>as 'E' or 'F'</td>
23826 </tr>
23827 <tr>
23828 <td>a</td>
23829 <td>double</td>
23830 <td>[-]0xh.hhhp[+-]d</td>
23831 </tr>
23832 <tr>
23833 <td>A</td>
23834 <td>double</td>
23835 <td>[-]0Xh.hhhp[+-]d</td>
23836 </tr>
23837 <tr>
23838 <td>c</td>
23839 <td>unsigned char</td>
23840 <td>a character</td>
23841 </tr>
23842 <tr>
23843 <td>C</td>
23844 <td>wint_t</td>
23845 <td>a character</td>
23846 </tr>
23847 <tr>
23848 <td>s</td>
23849 <td>char *</td>
23850 <td>a UTF-8 string</td>
23851 </tr>
23852 <tr>
23853 <td>S</td>
23854 <td>wchar_t *</td>
23855 <td>a unicode/WCS string</td>
23856 </tr>
23857 <tr>
23858 <td>p</td>
23859 <td>void *</td>
23860 <td>'%#lx'</td>
23861 </tr>
23862 </tbody>
23863 </table></div>
23864 <p id="doc_section_3_2_3_p_10">The 'h' and 'l' modifiers affect the size and treatment of the argument:</p>
23865 <div id="doc_table_u.6"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23866 <thead><tr>
23867 <th class="left">Mod</th>
23868 <th class="left">d, i</th>
23869 <th class="left">o, u, x, X</th>
23870 </tr></thead>
23871 <tbody>
23872 <tr>
23873 <td>hh</td>
23874 <td>signed char</td>
23875 <td>unsigned char</td>
23876 </tr>
23877 <tr>
23878 <td>h</td>
23879 <td>short</td>
23880 <td>unsigned short</td>
23881 </tr>
23882 <tr>
23883 <td>l</td>
23884 <td>long</td>
23885 <td>unsigned long</td>
23886 </tr>
23887 <tr>
23888 <td>ll</td>
23889 <td>long long</td>
23890 <td>unsigned long long</td>
23891 </tr>
23892 <tr>
23893 <td>j</td>
23894 <td>intmax_t</td>
23895 <td>uintmax_t</td>
23896 </tr>
23897 <tr>
23898 <td>t</td>
23899 <td>ptrdiff_t</td>
23900 <td>ptrdiff_t</td>
23901 </tr>
23902 <tr>
23903 <td>z</td>
23904 <td>size_t</td>
23905 <td>size_t</td>
23906 </tr>
23907 <tr>
23908 <td>q</td>
23909 <td>quad_t</td>
23910 <td>u_quad_t</td>
23911 </tr>
23912 </tbody>
23913 </table></div>
23914 </div>
23915 <div class="content">
23916 <h3 id="doc_section_3_2_4">
23917 <div class="self-section-number">
23918 <a href="#doc_section_3_2_4">3.2.4</a> </div>
23919 <a id="utf-8-and-locale-strings" href="#utf-8-and-locale-strings">UTF-8 and Locale Strings</a>
23920 </h3>
23921 <p id="doc_section_3_2_4_p_1">For strings, the 'h' and 'l' modifiers affect the interpretation of the bytes pointed to argument. The default '%s' string is a 'char *' pointer to a string encoded as UTF-8. Since UTF-8 is compatible with ASCII data, a normal 7-bit ASCII string can be used. '%ls' expects a 'wchar_t *' pointer to a wide-character string, encoded as a 32-bit Unicode values. '%hs' expects a 'char *' pointer to a multi-byte string encoded with the current locale, as given by the LC_CTYPE, LANG, or LC_ALL environment varibles. The first of this list of variables is used and if none of the variables are set, the locale defaults to "UTF&#8209;8".</p>
23922 <p id="doc_section_3_2_4_p_2">libxo will convert these arguments as needed to either UTF-8 (for XML, JSON, and HTML styles) or locale-based strings for display in text style.</p>
23923 <div id="doc_figure_u.65"></div> <pre>
23924    xo_emit("All strings are utf-8 content {:tag/%ls}",
23925            L"except for wide strings");
23926             </pre> <p id="doc_section_3_2_4_p_4">"%S" is equivalent to "%ls".</p>
23927 <div id="doc_table_u.7"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23928 <thead><tr>
23929 <th class="left">Format</th>
23930 <th class="left">Argument Type</th>
23931 <th class="left">Argument Contents</th>
23932 </tr></thead>
23933 <tbody>
23934 <tr>
23935 <td>%s</td>
23936 <td>const char *</td>
23937 <td>UTF-8 string</td>
23938 </tr>
23939 <tr>
23940 <td>%S</td>
23941 <td>const char *</td>
23942 <td>UTF-8 string (alias for '%s')</td>
23943 </tr>
23944 <tr>
23945 <td>%ls</td>
23946 <td>const wchar_t *</td>
23947 <td>Wide character UNICODE string</td>
23948 </tr>
23949 <tr>
23950 <td>%hs</td>
23951 <td>const char *</td>
23952 <td>locale-based string</td>
23953 </tr>
23954 </tbody>
23955 </table></div>
23956 <p id="doc_section_3_2_4_p_5">For example, a function is passed a locale-base name, a hat size, and a time value. The hat size is formatted in a UTF-8 (ASCII) string, and the time value is formatted into a wchar_t string.</p>
23957 <div id="doc_figure_u.66"></div> <pre>
23958     void print_order (const char *name, int size,
23959                       struct tm *timep) {
23960         char buf[32];
23961         const char *size_val = "unknown";
23962
23963         if (size &gt; 0)
23964             snprintf(buf, sizeof(buf), "%d", size);
23965             size_val = buf;
23966         }
23967
23968         wchar_t when[32];
23969         wcsftime(when, sizeof(when), L"%d%b%y", timep);
23970
23971         xo_emit("The hat for {:name/%hs} is {:size/%s}.\n",
23972                 name, size_val);
23973         xo_emit("It was ordered on {:order-time/%ls}.\n",
23974                 when);
23975     }
23976             </pre> <p id="doc_section_3_2_4_p_7">It is important to note that xo_emit will perform the conversion required to make appropriate output. Text style output uses the current locale (as described above), while XML, JSON, and HTML use UTF-8.</p>
23977 <p id="doc_section_3_2_4_p_8">UTF-8 and locale-encoded strings can use multiple bytes to encode one column of data. The traditional "precision'" (aka "max&#8209;width") value for "%s" printf formatting becomes overloaded since it specifies both the number of bytes that can be safely referenced and the maximum number of columns to emit. xo_emit uses the precision as the former, and adds a third value for specifying the maximum number of columns.</p>
23978 <p id="doc_section_3_2_4_p_9">In this example, the name field is printed with a minimum of 3 columns and a maximum of 6. Up to ten bytes of data at the location given by 'name' are in used in filling those columns.</p>
23979 <div id="doc_figure_u.67"></div> <pre>
23980     xo_emit("{:name/%3.10.6s}", name);
23981             </pre> </div>
23982 <div class="content">
23983 <h3 id="doc_section_3_2_5">
23984 <div class="self-section-number">
23985 <a href="#doc_section_3_2_5">3.2.5</a> </div>
23986 <a id="characters-outside-of-field-definitions" href="#characters-outside-of-field-definitions">Characters Outside of Field Definitions</a>
23987 </h3>
23988 <p id="doc_section_3_2_5_p_1">Characters in the format string that are not part of a field definition are copied to the output for the TEXT style, and are ignored for the JSON and XML styles. For HTML, these characters are placed in a &lt;div&gt; with class "text".</p>
23989 <div id="doc_figure_u.68"></div> <pre>
23990   EXAMPLE:
23991       xo_emit("The hat is {:size/%s}.\n", size_val);
23992   TEXT:
23993       The hat is extra small.
23994   XML:
23995       &lt;size&gt;extra small&lt;/size&gt;
23996   JSON:
23997       "size": "extra small"
23998   HTML:
23999       &lt;div class="text"&gt;The hat is &lt;/div&gt;
24000       &lt;div class="data" data-tag="size"&gt;extra small&lt;/div&gt;
24001       &lt;div class="text"&gt;.&lt;/div&gt;
24002             </pre> </div>
24003 <div class="content">
24004 <h3 id="doc_section_3_2_6">
24005 <div class="self-section-number">
24006 <a href="#doc_section_3_2_6">3.2.6</a> </div>
24007 <a id="m-is-supported" href="#m-is-supported">"%m" Is Supported</a>
24008 </h3>
24009 <p id="doc_section_3_2_6_p_1">libxo supports the '%m' directive, which formats the error message associated with the current value of "errno". It is the equivalent of "%s" with the argument strerror(errno).</p>
24010 <div id="doc_figure_u.69"></div> <pre>
24011     xo_emit("{:filename} cannot be opened: {:error/%m}", filename);
24012     xo_emit("{:filename} cannot be opened: {:error/%s}",
24013             filename, strerror(errno));
24014             </pre> </div>
24015 <div class="content">
24016 <h3 id="doc_section_3_2_7">
24017 <div class="self-section-number">
24018 <a href="#doc_section_3_2_7">3.2.7</a> </div>
24019 <a id="n-is-not-supported" href="#n-is-not-supported">"%n" Is Not Supported</a>
24020 </h3>
24021 <p id="doc_section_3_2_7_p_1">libxo does not support the '%n' directive. It's a bad idea and we just don't do it.</p>
24022 </div>
24023 <div class="content">
24024 <h3 id="doc_section_3_2_8">
24025 <div class="self-section-number">
24026 <a href="#doc_section_3_2_8">3.2.8</a> </div>
24027 <a id="the-encoding-format-eformat" href="#the-encoding-format-eformat">The Encoding Format (eformat)</a>
24028 </h3>
24029 <p id="doc_section_3_2_8_p_1">The "eformat" string is the format string used when encoding the field for JSON and XML. If not provided, it defaults to the primary format with any minimum width removed. If the primary is not given, both default to "%s".</p>
24030 </div>
24031 <div class="content">
24032 <h3 id="doc_section_3_2_9">
24033 <div class="self-section-number">
24034 <a href="#doc_section_3_2_9">3.2.9</a> </div>
24035 <a id="content-strings" href="#content-strings">Content Strings</a>
24036 </h3>
24037 <p id="doc_section_3_2_9_p_1">For padding and labels, the content string is considered the content, unless a format is given.</p>
24038 </div>
24039 <div class="content">
24040 <h3 id="doc_section_3_2_10">
24041 <div class="self-section-number">
24042 <a href="#doc_section_3_2_10">3.2.10</a> </div>
24043 <a id="printf-like" href="#printf-like">Argument Validation</a>
24044 </h3>
24045 <p id="doc_section_3_2_10_p_1">Many compilers and tool chains support validation of printf-like arguments. When the format string fails to match the argument list, a warning is generated. This is a valuable feature and while the formatting strings for libxo differ considerably from printf, many of these checks can still provide build-time protection against bugs.</p>
24046 <p id="doc_section_3_2_10_p_2">libxo provide variants of functions that provide this ability, if the "&#8209;&#8209;enable&#8209;printflike" option is passed to the "configure" script. These functions use the "_p" suffix, like "xo_emit_p()", xo_emit_hp()", etc.</p>
24047 <p id="doc_section_3_2_10_p_3">The following are features of libxo formatting strings that are incompatible with printf-like testing:</p>
24048 <p id="doc_section_3_2_10_p_4"> </p>
24049 <ul>
24050 <li>implicit formats, where "{:tag}" has an implicit "%s";</li>
24051 <li>the "max" parameter for strings, where "{:tag/%4.10.6s}" means up to ten bytes of data can be inspected to fill a minimum of 4 columns and a maximum of 6;</li>
24052 <li>percent signs in strings, where "{:filled}%" makes a single, trailing percent sign;</li>
24053 <li>the "l" and "h" modifiers for strings, where "{:tag/%hs}" means locale-based string and "{:tag/%ls}" means a wide character string;</li>
24054 <li>distinct encoding formats, where "{:tag/#%s/%s}" means the display styles (text and HTML) will use "#%s" where other styles use "%s";</li>
24055 </ul>
24056 <p id="doc_section_3_2_10_p_5">If none of these features are in use by your code, then using the "_p" variants might be wise.</p>
24057 <div id="doc_table_u.8"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24058 <thead><tr>
24059 <th class="left">Function</th>
24060 <th class="left">printf-like Equivalent</th>
24061 </tr></thead>
24062 <tbody>
24063 <tr>
24064 <td>xo_emit_hv</td>
24065 <td>xo_emit_hvp</td>
24066 </tr>
24067 <tr>
24068 <td>xo_emit_h</td>
24069 <td>xo_emit_hp</td>
24070 </tr>
24071 <tr>
24072 <td>xo_emit</td>
24073 <td>xo_emit_p</td>
24074 </tr>
24075 <tr>
24076 <td>xo_emit_warn_hcv</td>
24077 <td>xo_emit_warn_hcvp</td>
24078 </tr>
24079 <tr>
24080 <td>xo_emit_warn_hc</td>
24081 <td>xo_emit_warn_hcp</td>
24082 </tr>
24083 <tr>
24084 <td>xo_emit_warn_c</td>
24085 <td>xo_emit_warn_cp</td>
24086 </tr>
24087 <tr>
24088 <td>xo_emit_warn</td>
24089 <td>xo_emit_warn_p</td>
24090 </tr>
24091 <tr>
24092 <td>xo_emit_warnx_</td>
24093 <td>xo_emit_warnx_p</td>
24094 </tr>
24095 <tr>
24096 <td>xo_emit_err</td>
24097 <td>xo_emit_err_p</td>
24098 </tr>
24099 <tr>
24100 <td>xo_emit_errx</td>
24101 <td>xo_emit_errx_p</td>
24102 </tr>
24103 <tr>
24104 <td>xo_emit_errc</td>
24105 <td>xo_emit_errc_p</td>
24106 </tr>
24107 </tbody>
24108 </table></div>
24109 </div>
24110 <div class="content">
24111 <h3 id="doc_section_3_2_11">
24112 <div class="self-section-number">
24113 <a href="#doc_section_3_2_11">3.2.11</a> </div>
24114 <a id="retain" href="#retain">Retaining Parsed Format Information</a>
24115 </h3>
24116 <p id="doc_section_3_2_11_p_1">libxo can retain the parsed internal information related to the given format string, allowing subsequent xo_emit calls, the retained information is used, avoiding repetitive parsing of the format string.</p>
24117 <div id="doc_figure_u.70"></div> <pre>
24118     SYNTAX:
24119       int xo_emit_f(xo_emit_flags_t flags, const char fmt, ...);
24120     EXAMPLE:
24121       xo_emit_f(XOEF_RETAIN, "{:some/%02d}{:thing/%-6s}{:fancy}\n",
24122                      some, thing, fancy);
24123             </pre> <p id="doc_section_3_2_11_p_3">To retain parsed format information, use the XOEF_RETAIN flag to the xo_emit_f() function. A complete set of xo_emit_f functions exist to match all the xo_emit function signatures (with handles, varadic argument, and printf-like flags):</p>
24124 <div id="doc_table_u.9"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24125 <thead><tr>
24126 <th class="left">Function</th>
24127 <th class="left">Flags Equivalent</th>
24128 </tr></thead>
24129 <tbody>
24130 <tr>
24131 <td>xo_emit_hv</td>
24132 <td>xo_emit_hvf</td>
24133 </tr>
24134 <tr>
24135 <td>xo_emit_h</td>
24136 <td>xo_emit_hf</td>
24137 </tr>
24138 <tr>
24139 <td>xo_emit</td>
24140 <td>xo_emit_f</td>
24141 </tr>
24142 <tr>
24143 <td>xo_emit_hvp</td>
24144 <td>xo_emit_hvfp</td>
24145 </tr>
24146 <tr>
24147 <td>xo_emit_hp</td>
24148 <td>xo_emit_hfp</td>
24149 </tr>
24150 <tr>
24151 <td>xo_emit_p</td>
24152 <td>xo_emit_fp</td>
24153 </tr>
24154 </tbody>
24155 </table></div>
24156 <p id="doc_section_3_2_11_p_4">The format string must be immutable across multiple calls to xo_emit_f(), since the library retains the string. Typically this is done by using static constant strings, such as string literals. If the string is not immutable, the XOEF_RETAIN flag must not be used.</p>
24157 <p id="doc_section_3_2_11_p_5">The functions xo_retain_clear() and xo_retain_clear_all() release internal information on either a single format string or all format strings, respectively. Neither is required, but the library will retain this information until it is cleared or the process exits.</p>
24158 <div id="doc_figure_u.71"></div> <pre>
24159     const char *fmt = "{:name}  {:count/%d}\n";
24160     for (i = 0; i &lt; 1000; i++) {
24161         xo_open_instance("item");
24162         xo_emit_f(XOEF_RETAIN, fmt, name[i], count[i]);
24163     }
24164     xo_retain_clear(fmt);
24165             </pre> <p id="doc_section_3_2_11_p_7">The retained information is kept as thread-specific data.</p>
24166 </div>
24167 <div class="content">
24168 <h3 id="doc_section_3_2_12">
24169 <div class="self-section-number">
24170 <a href="#doc_section_3_2_12">3.2.12</a> </div>
24171 <a id="example" href="#example">Example</a>
24172 </h3>
24173 <p id="doc_section_3_2_12_p_1">In this example, the value for the number of items in stock is emitted:</p>
24174 <div id="doc_figure_u.72"></div> <pre>
24175         xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\n",
24176                 instock);
24177             </pre> <p id="doc_section_3_2_12_p_3">This call will generate the following output:</p>
24178 <div id="doc_figure_u.73"></div> <pre>
24179   TEXT: 
24180        In stock: 144
24181   XML:
24182       &lt;in-stock&gt;144&lt;/in-stock&gt;
24183   JSON:
24184       "in-stock": 144,
24185   HTML:
24186       &lt;div class="line"&gt;
24187         &lt;div class="padding"&gt;   &lt;/div&gt;
24188         &lt;div class="label"&gt;In stock&lt;/div&gt;
24189         &lt;div class="decoration"&gt;:&lt;/div&gt;
24190         &lt;div class="padding"&gt; &lt;/div&gt;
24191         &lt;div class="data" data-tag="in-stock"&gt;144&lt;/div&gt;
24192       &lt;/div&gt;
24193             </pre> <p id="doc_section_3_2_12_p_5">Clearly HTML wins the verbosity award, and this output does not include XOF_XPATH or XOF_INFO data, which would expand the penultimate line to:</p>
24194 <div id="doc_figure_u.74"></div> <pre>
24195        &lt;div class="data" data-tag="in-stock"
24196           data-xpath="/top/data/item/in-stock"
24197           data-type="number"
24198           data-help="Number of items in stock"&gt;144&lt;/div&gt;
24199             </pre> </div>
24200 </div>
24201 <div class="content">
24202 <h2 id="doc_section_3_3">
24203 <div class="self-section-number">
24204 <a href="#doc_section_3_3">3.3</a> </div>
24205 <a id="representing-hierarchy" href="#representing-hierarchy">Representing Hierarchy</a>
24206 </h2>
24207 <p id="doc_section_3_3_p_1">For XML and JSON, individual fields appear inside hierarchies which provide context and meaning to the fields. Unfortunately, these encoding have a basic disconnect between how lists is similar objects are represented.</p>
24208 <p id="doc_section_3_3_p_2">XML encodes lists as set of sequential elements:</p>
24209 <div id="doc_figure_u.75"></div> <pre>
24210     &lt;user&gt;phil&lt;/user&gt;
24211     &lt;user&gt;pallavi&lt;/user&gt;
24212     &lt;user&gt;sjg&lt;/user&gt;
24213             </pre> <p id="doc_section_3_3_p_4">JSON encodes lists using a single name and square brackets:</p>
24214 <div id="doc_figure_u.76"></div> <pre>
24215     "user": [ "phil", "pallavi", "sjg" ]
24216             </pre> <p id="doc_section_3_3_p_6">This means libxo needs three distinct indications of hierarchy: one for containers of hierarchy appear only once for any specific parent, one for lists, and one for each item in a list.</p>
24217 <p id="doc_section_3_3_p_7">Section Contents: </p>
24218 <ul>
24219 <li><a href="#containers" title="Containers">Section 3.3.1</a></li>
24220 <li><a href="#lists-and-instances" title="Lists and Instances">Section 3.3.2</a></li>
24221 <li><a href="#dtrt-mode" title="DTRT Mode">Section 3.3.3</a></li>
24222 <li><a href="#markers" title="Markers">Section 3.3.4</a></li>
24223 </ul>
24224 <div class="content">
24225 <h3 id="doc_section_3_3_1">
24226 <div class="self-section-number">
24227 <a href="#doc_section_3_3_1">3.3.1</a> </div>
24228 <a id="containers" href="#containers">Containers</a>
24229 </h3>
24230 <p id="doc_section_3_3_1_p_1">A "container" is an element of a hierarchy that appears only once under any specific parent. The container has no value, but serves to contain other nodes.</p>
24231 <p id="doc_section_3_3_1_p_2">To open a container, call xo_open_container() or xo_open_container_h(). The former uses the default handle and the latter accepts a specific handle.</p>
24232 <div id="doc_figure_u.77"></div> <pre>
24233     int xo_open_container_h (xo_handle_t *xop, const char *name);
24234     int xo_open_container (const char *name);
24235             </pre> <p id="doc_section_3_3_1_p_4">To close a level, use the xo_close_container() or xo_close_container_h() functions:</p>
24236 <div id="doc_figure_u.78"></div> <pre>
24237     int xo_close_container_h (xo_handle_t *xop, const char *name);
24238     int xo_close_container (const char *name);
24239             </pre> <p id="doc_section_3_3_1_p_6">Each open call must have a matching close call. If the XOF_WARN flag is set and the name given does not match the name of the currently open container, a warning will be generated.</p>
24240 <div id="doc_figure_u.79"></div> <pre>
24241     Example:
24242
24243         xo_open_container("top");
24244         xo_open_container("system");
24245         xo_emit("{:host-name/%s%s%s", hostname,
24246                 domainname ? "." : "", domainname ?: "");
24247         xo_close_container("system");
24248         xo_close_container("top");
24249
24250     Sample Output:
24251       Text:
24252         my-host.example.org
24253       XML:
24254         &lt;top&gt;
24255           &lt;system&gt;
24256               &lt;host-name&gt;my-host.example.org&lt;/host-name&gt;
24257           &lt;/system&gt;
24258         &lt;/top&gt;
24259       JSON:
24260         "top" : {
24261           "system" : {
24262               "host-name": "my-host.example.org"
24263           }
24264         }
24265       HTML:
24266         &lt;div class="data"
24267              data-tag="host-name"&gt;my-host.example.org&lt;/div&gt;
24268             </pre> </div>
24269 <div class="content">
24270 <h3 id="doc_section_3_3_2">
24271 <div class="self-section-number">
24272 <a href="#doc_section_3_3_2">3.3.2</a> </div>
24273 <a id="lists-and-instances" href="#lists-and-instances">Lists and Instances</a>
24274 </h3>
24275 <p id="doc_section_3_3_2_p_1">A list is set of one or more instances that appear under the same parent. The instances contain details about a specific object. One can think of instances as objects or records. A call is needed to open and close the list, while a distinct call is needed to open and close each instance of the list:</p>
24276 <div id="doc_figure_u.80"></div> <pre>
24277     xo_open_list("item");
24278
24279     for (ip = list; ip-&gt;i_title; ip++) {
24280         xo_open_instance("item");
24281         xo_emit("{L:Item} '{:name/%s}':\n", ip-&gt;i_title);
24282         xo_close_instance("item");
24283     }
24284
24285     xo_close_list("item");
24286             </pre> <p id="doc_section_3_3_2_p_3">Getting the list and instance calls correct is critical to the proper generation of XML and JSON data.</p>
24287 </div>
24288 <div class="content">
24289 <h3 id="doc_section_3_3_3">
24290 <div class="self-section-number">
24291 <a href="#doc_section_3_3_3">3.3.3</a> </div>
24292 <a id="dtrt-mode" href="#dtrt-mode">DTRT Mode</a>
24293 </h3>
24294 <p id="doc_section_3_3_3_p_1">Some users may find tracking the names of open containers, lists, and instances inconvenient. libxo offers a "Do The Right Thing" mode, where libxo will track the names of open containers, lists, and instances so the close function can be called without a name. To enable DTRT mode, turn on the XOF_DTRT flag prior to making any other libxo output.</p>
24295 <div id="doc_figure_u.81"></div> <pre>
24296     xo_set_flags(NULL, XOF_DTRT);
24297             </pre> <p id="doc_section_3_3_3_p_3">Each open and close function has a version with the suffix "_d", which will close the open container, list, or instance:</p>
24298 <div id="doc_figure_u.82"></div> <pre>
24299     xo_open_container("top");
24300     ...
24301     xo_close_container_d();
24302             </pre> <p id="doc_section_3_3_3_p_5">This also works for lists and instances:</p>
24303 <div id="doc_figure_u.83"></div> <pre>
24304     xo_open_list("item");
24305     for (...) {
24306         xo_open_instance("item");
24307         xo_emit(...);
24308         xo_close_instance_d();
24309     }
24310     xo_close_list_d();
24311             </pre> <p id="doc_section_3_3_3_p_7">Note that the XOF_WARN flag will also cause libxo to track open containers, lists, and instances. A warning is generated when the name given to the close function and the name recorded do not match.</p>
24312 </div>
24313 <div class="content">
24314 <h3 id="doc_section_3_3_4">
24315 <div class="self-section-number">
24316 <a href="#doc_section_3_3_4">3.3.4</a> </div>
24317 <a id="markers" href="#markers">Markers</a>
24318 </h3>
24319 <p id="doc_section_3_3_4_p_1">Markers are used to protect and restore the state of open constructs. While a marker is open, no other open constructs can be closed. When a marker is closed, all constructs open since the marker was opened will be closed.</p>
24320 <p id="doc_section_3_3_4_p_2">Markers use names which are not user-visible, allowing the caller to choose appropriate internal names.</p>
24321 <p id="doc_section_3_3_4_p_3">In this example, the code whiffles through a list of fish, calling a function to emit details about each fish. The marker "fish&#8209;guts" is used to ensure that any constructs opened by the function are closed properly.</p>
24322 <div id="doc_figure_u.84"></div> <pre>
24323     for (i = 0; fish[i]; i++) {
24324         xo_open_instance("fish");
24325         xo_open_marker("fish-guts");
24326         dump_fish_details(i);
24327         xo_close_marker("fish-guts");
24328     }
24329             </pre> </div>
24330 </div>
24331 </div>
24332 <hr class="noprint">
24333 <div class="content">
24334 <h1 id="doc_section_4" class="np">
24335 <div class="self-section-number">
24336 <a href="#doc_section_4">4_</a> </div>
24337 <a id="options" href="#options">Command-line Arguments</a>
24338 </h1>
24339 <p id="doc_section_4_p_1">libxo uses command line options to trigger rendering behavior. The following options are recognised:</p>
24340 <p id="doc_section_4_p_2"> </p>
24341 <ul>
24342 <li>--libxo &lt;options&gt;</li>
24343 <li>--libxo=&lt;options&gt;</li>
24344 <li>--libxo:&lt;brief&#8209;options&gt;</li>
24345 </ul>
24346 <p id="doc_section_4_p_3">The following invocations are all identical in outcome:</p>
24347 <div id="doc_figure_u.85"></div> <pre>
24348   my-app --libxo warn,pretty arg1
24349   my-app --libxo=warn,pretty arg1
24350   my-app --libxo:WP arg1
24351             </pre> <p id="doc_section_4_p_5">Programs using libxo are expecting to call the xo_parse_args function to parse these arguments. See <a href="#xo_parse_args" title="Parsing Command-line Arguments (xo_parse_args)">Section 5.4.1</a> for details.</p>
24352 <p id="doc_section_4_p_6">Section Contents: </p>
24353 <ul>
24354 <li><a href="#option-keywords" title="Option keywords">Section 4.1</a></li>
24355 <li><a href="#brief-options" title="Brief Options">Section 4.2</a></li>
24356 <li><a href="#color-mapping" title="Color Mapping">Section 4.3</a></li>
24357 </ul>
24358 <div class="content">
24359 <h2 id="doc_section_4_1">
24360 <div class="self-section-number">
24361 <a href="#doc_section_4_1">4.1</a> </div>
24362 <a id="option-keywords" href="#option-keywords">Option keywords</a>
24363 </h2>
24364 <p id="doc_section_4_1_p_1">Options is a comma-separated list of tokens that correspond to output styles, flags, or features:</p>
24365 <div id="doc_table_u.10"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24366 <thead><tr>
24367 <th class="left">Token</th>
24368 <th class="left">Action</th>
24369 </tr></thead>
24370 <tbody>
24371 <tr>
24372 <td>color</td>
24373 <td>Enable colors/effects for display styles (TEXT, HTML)</td>
24374 </tr>
24375 <tr>
24376 <td>colors=xxxx</td>
24377 <td>Adjust color output values</td>
24378 </tr>
24379 <tr>
24380 <td>dtrt</td>
24381 <td>Enable "Do The Right Thing" mode</td>
24382 </tr>
24383 <tr>
24384 <td>flush</td>
24385 <td>Flush after every libxo function call</td>
24386 </tr>
24387 <tr>
24388 <td>flush-line</td>
24389 <td>Flush after every line (line-buffered)</td>
24390 </tr>
24391 <tr>
24392 <td>html</td>
24393 <td>Emit HTML output</td>
24394 </tr>
24395 <tr>
24396 <td>indent=xx</td>
24397 <td>Set the indentation level</td>
24398 </tr>
24399 <tr>
24400 <td>info</td>
24401 <td>Add info attributes (HTML)</td>
24402 </tr>
24403 <tr>
24404 <td>json</td>
24405 <td>Emit JSON output</td>
24406 </tr>
24407 <tr>
24408 <td>keys</td>
24409 <td>Emit the key attribute for keys (XML)</td>
24410 </tr>
24411 <tr>
24412 <td>log-gettext</td>
24413 <td>Log (via stderr) each gettext(3) string lookup</td>
24414 </tr>
24415 <tr>
24416 <td>log-syslog</td>
24417 <td>Log (via stderr) each syslog message (via xo_syslog)</td>
24418 </tr>
24419 <tr>
24420 <td>no-humanize</td>
24421 <td>Ignore the {h:} modifier (TEXT, HTML)</td>
24422 </tr>
24423 <tr>
24424 <td>no-locale</td>
24425 <td>Do not initialize the locale setting</td>
24426 </tr>
24427 <tr>
24428 <td>no-retain</td>
24429 <td>Prevent retaining formatting information</td>
24430 </tr>
24431 <tr>
24432 <td>no-top</td>
24433 <td>Do not emit a top set of braces (JSON)</td>
24434 </tr>
24435 <tr>
24436 <td>not-first</td>
24437 <td>Pretend the 1st output item was not 1st (JSON)</td>
24438 </tr>
24439 <tr>
24440 <td>pretty</td>
24441 <td>Emit pretty-printed output</td>
24442 </tr>
24443 <tr>
24444 <td>retain</td>
24445 <td>Force retaining formatting information</td>
24446 </tr>
24447 <tr>
24448 <td>text</td>
24449 <td>Emit TEXT output</td>
24450 </tr>
24451 <tr>
24452 <td>underscores</td>
24453 <td>Replace XML-friendly "-"s with JSON friendly "_"s</td>
24454 </tr>
24455 <tr>
24456 <td>units</td>
24457 <td>Add the 'units' (XML) or 'data-units (HTML) attribute</td>
24458 </tr>
24459 <tr>
24460 <td>warn</td>
24461 <td>Emit warnings when libxo detects bad calls</td>
24462 </tr>
24463 <tr>
24464 <td>warn-xml</td>
24465 <td>Emit warnings in XML</td>
24466 </tr>
24467 <tr>
24468 <td>xml</td>
24469 <td>Emit XML output</td>
24470 </tr>
24471 <tr>
24472 <td>xpath</td>
24473 <td>Add XPath expressions (HTML)</td>
24474 </tr>
24475 </tbody>
24476 </table></div>
24477 <p id="doc_section_4_1_p_2">Most of these option are simple and direct, but some require additional details:</p>
24478 <p id="doc_section_4_1_p_3"> </p>
24479 <ul>
24480 <li>"colors" is described in <a href="#color-mapping" title="Color Mapping">Section 4.3</a>.</li>
24481 <li>"flush&#8209;line" performs line buffering, even when the output is not directed to a TTY device.</li>
24482 <li>"info" generates additional data for HTML, encoded in attributes using names that state with "data&#8209;".</li>
24483 <li>"keys" adds a "key" attribute for XML output to indicate that a leaf is an identifier for the list member.</li>
24484 <li>"no&#8209;humanize"avoids "humanizing" numeric output (see humanize_number(3) for details).</li>
24485 <li>"no&#8209;locale" instructs libxo to avoid translating output to the current locale.</li>
24486 <li>"no&#8209;retain" disables the ability of libxo to internally retain "compiled" information about formatting strings.</li>
24487 <li>"underscores" can be used with JSON output to change XML-friendly names with dashes into JSON-friendly name with underscores.</li>
24488 <li>"warn" allows libxo to emit warnings on stderr when application code make incorrect calls.</li>
24489 <li>"warn&#8209;xml" causes those warnings to be placed in XML inside the output.</li>
24490 </ul>
24491 </div>
24492 <div class="content">
24493 <h2 id="doc_section_4_2">
24494 <div class="self-section-number">
24495 <a href="#doc_section_4_2">4.2</a> </div>
24496 <a id="brief-options" href="#brief-options">Brief Options</a>
24497 </h2>
24498 <p id="doc_section_4_2_p_1">The brief options are simple single-letter aliases to the normal keywords, as detailed below:</p>
24499 <div id="doc_table_u.11"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24500 <thead><tr>
24501 <th class="left">Option</th>
24502 <th class="left">Action</th>
24503 </tr></thead>
24504 <tbody>
24505 <tr>
24506 <td>c</td>
24507 <td>Enable color/effects for TEXT/HTML</td>
24508 </tr>
24509 <tr>
24510 <td>F</td>
24511 <td>Force line-buffered flushing</td>
24512 </tr>
24513 <tr>
24514 <td>H</td>
24515 <td>Enable HTML output (XO_STYLE_HTML)</td>
24516 </tr>
24517 <tr>
24518 <td>I</td>
24519 <td>Enable info output (XOF_INFO)</td>
24520 </tr>
24521 <tr>
24522 <td>i&lt;num&gt;</td>
24523 <td>Indent by &lt;number&gt;</td>
24524 </tr>
24525 <tr>
24526 <td>J</td>
24527 <td>Enable JSON output (XO_STYLE_JSON)</td>
24528 </tr>
24529 <tr>
24530 <td>k</td>
24531 <td>Add keys to XPATH expressions in HTML</td>
24532 </tr>
24533 <tr>
24534 <td>n</td>
24535 <td>Disable humanization (TEXT, HTML)</td>
24536 </tr>
24537 <tr>
24538 <td>P</td>
24539 <td>Enable pretty-printed output (XOF_PRETTY)</td>
24540 </tr>
24541 <tr>
24542 <td>T</td>
24543 <td>Enable text output (XO_STYLE_TEXT)</td>
24544 </tr>
24545 <tr>
24546 <td>U</td>
24547 <td>Add units to HTML output</td>
24548 </tr>
24549 <tr>
24550 <td>u</td>
24551 <td>Change "-"s to "_"s in element names (JSON)</td>
24552 </tr>
24553 <tr>
24554 <td>W</td>
24555 <td>Enable warnings (XOF_WARN)</td>
24556 </tr>
24557 <tr>
24558 <td>X</td>
24559 <td>Enable XML output (XO_STYLE_XML)</td>
24560 </tr>
24561 <tr>
24562 <td>x</td>
24563 <td>Enable XPath data (XOF_XPATH)</td>
24564 </tr>
24565 </tbody>
24566 </table></div>
24567 </div>
24568 <div class="content">
24569 <h2 id="doc_section_4_3">
24570 <div class="self-section-number">
24571 <a href="#doc_section_4_3">4.3</a> </div>
24572 <a id="color-mapping" href="#color-mapping">Color Mapping</a>
24573 </h2>
24574 <p id="doc_section_4_3_p_1">The "colors" option takes a value that is a set of mappings from the pre-defined set of colors to new foreground and background colors. The value is a series of "fg/bg" values, separated by a "+". Each pair of "fg/bg" values gives the colors to which a basic color is mapped when used as a foreground or background color. The order is the mappings is:</p>
24575 <p id="doc_section_4_3_p_2"> </p>
24576 <ul>
24577 <li>black</li>
24578 <li>red</li>
24579 <li>green</li>
24580 <li>yellow</li>
24581 <li>blue</li>
24582 <li>magenta</li>
24583 <li>cyan</li>
24584 <li>white</li>
24585 </ul>
24586 <p id="doc_section_4_3_p_3">Pairs may be skipped, leaving them mapped as normal, as are missing pairs or single colors.</p>
24587 <p id="doc_section_4_3_p_4">For example consider the following xo_emit call:</p>
24588 <div id="doc_figure_u.86"></div> <pre>
24589     xo_emit("{C:fg-red,bg-green}Merry XMas!!{C:}\n");
24590             </pre> <p id="doc_section_4_3_p_6">To turn all colored output to red-on-blue, use eight pairs of "red/blue" mappings separated by "+"s:</p>
24591 <div id="doc_figure_u.87"></div> <pre>
24592     --libxo colors=red/blue+red/blue+red/blue+red/blue+\
24593                    red/blue+red/blue+red/blue+red/blue
24594             </pre> <p id="doc_section_4_3_p_8">To turn the red-on-green text to magenta-on-cyan, give a "magenta" foreground value for red (the second mapping) and a "cyan" background to green (the third mapping):</p>
24595 <div id="doc_figure_u.88"></div> <pre>
24596     --libxo colors=+magenta+/cyan
24597             </pre> <p id="doc_section_4_3_p_10">Consider the common situation where blue output looks unreadable on a terminal session with a black background. To turn both "blue" foreground and background output to "yellow", give only the fifth mapping, skipping the first four mappings with bare "+"s:</p>
24598 <div id="doc_figure_u.89"></div> <pre>
24599     --libxo colors=++++yellow/yellow
24600             </pre> </div>
24601 </div>
24602 <hr class="noprint">
24603 <div class="content">
24604 <h1 id="doc_section_5" class="np">
24605 <div class="self-section-number">
24606 <a href="#doc_section_5">5_</a> </div>
24607 <a id="the-libxo-api" href="#the-libxo-api">The libxo API</a>
24608 </h1>
24609 <p id="doc_section_5_p_1">This section gives details about the functions in libxo, how to call them, and the actions they perform.</p>
24610 <p id="doc_section_5_p_2">Section Contents: </p>
24611 <ul>
24612 <li><a href="#handles" title="Handles">Section 5.1</a></li>
24613 <li><a href="#emitting-content-xo_emit" title="Emitting Content (xo_emit)">Section 5.2</a></li>
24614 <li><a href="#emitting-hierarchy" title="Emitting Hierarchy">Section 5.3</a></li>
24615 <li><a href="#support-functions" title="Support Functions">Section 5.4</a></li>
24616 <li><a href="#emitting-syslog-messages" title="Emitting syslog Messages">Section 5.5</a></li>
24617 <li><a href="#creating-custom-encoders" title="Creating Custom Encoders">Section 5.6</a></li>
24618 </ul>
24619 <div class="content">
24620 <h2 id="doc_section_5_1">
24621 <div class="self-section-number">
24622 <a href="#doc_section_5_1">5.1</a> </div>
24623 <a id="handles" href="#handles">Handles</a>
24624 </h2>
24625 <p id="doc_section_5_1_p_1">libxo uses "handles" to control its rendering functionality. The handle contains state and buffered data, as well as callback functions to process data.</p>
24626 <p id="doc_section_5_1_p_2">Handles give an abstraction for libxo that encapsulates the state of a stream of output. Handles have the data type "xo_handle_t" and are opaque to the caller.</p>
24627 <p id="doc_section_5_1_p_3">The library has a default handle that is automatically initialized. By default, this handle will send text style output (XO_STYLE_TEXT) to standard output. The xo_set_style and xo_set_flags functions can be used to change this behavior.</p>
24628 <p id="doc_section_5_1_p_4">For the typical command that is generating output on standard output, there is no need to create an explicit handle, but they are available when needed, e.g., for daemons that generate multiple streams of output.</p>
24629 <p id="doc_section_5_1_p_5">Many libxo functions take a handle as their first parameter; most that do not use the default handle. Any function taking a handle can be passed NULL to access the default handle. For the convenience of callers, the libxo library includes handle-less functions that implicitly use the default handle.</p>
24630 <p id="doc_section_5_1_p_6">For example, the following are equivalent:</p>
24631 <div id="doc_figure_u.90"></div> <pre>
24632     xo_emit("test");
24633     xo_emit_h(NULL, "test");
24634             </pre> <p id="doc_section_5_1_p_8">Handles are created using xo_create() and destroy using xo_destroy().</p>
24635 <p id="doc_section_5_1_p_9">Section Contents: </p>
24636 <ul>
24637 <li><a href="#xo_create" title="xo_create">Section 5.1.1</a></li>
24638 <li><a href="#xo_create_to_file" title="xo_create_to_file">Section 5.1.2</a></li>
24639 <li><a href="#xo_set_writer" title="xo_set_writer">Section 5.1.3</a></li>
24640 <li><a href="#xo_set_style" title="xo_set_style">Section 5.1.4</a></li>
24641 <li><a href="#xo_get_style" title="xo_get_style">Section 5.1.5</a></li>
24642 <li><a href="#xo_set_flags" title="xo_set_flags">Section 5.1.6</a></li>
24643 <li><a href="#xo_destroy" title="xo_destroy">Section 5.1.7</a></li>
24644 </ul>
24645 <div class="content">
24646 <h3 id="doc_section_5_1_1">
24647 <div class="self-section-number">
24648 <a href="#doc_section_5_1_1">5.1.1</a> </div>
24649 <a id="xo_create" href="#xo_create">xo_create</a>
24650 </h3>
24651 <p id="doc_section_5_1_1_p_1">A handle can be allocated using the xo_create() function:</p>
24652 <div id="doc_figure_u.91"></div> <pre>
24653     xo_handle_t *xo_create (unsigned style, unsigned flags);
24654
24655   Example:
24656     xo_handle_t *xop = xo_create(XO_STYLE_JSON, XOF_WARN);
24657     ....
24658     xo_emit_h(xop, "testing\n");
24659             </pre> <p id="doc_section_5_1_1_p_3">See also <a href="#styles" title="Output Styles (XO_STYLE_*)">Section 5.1.5.1</a> and <a href="#flags" title="Flags (XOF_*)">Section 5.1.6.1</a>.</p>
24660 </div>
24661 <div class="content">
24662 <h3 id="doc_section_5_1_2">
24663 <div class="self-section-number">
24664 <a href="#doc_section_5_1_2">5.1.2</a> </div>
24665 <a id="xo_create_to_file" href="#xo_create_to_file">xo_create_to_file</a>
24666 </h3>
24667 <p id="doc_section_5_1_2_p_1">By default, libxo writes output to standard output. A convenience function is provided for situations when output should be written to a different file:</p>
24668 <div id="doc_figure_u.92"></div> <pre>
24669     xo_handle_t *xo_create_to_file (FILE *fp, unsigned style,
24670                                     unsigned flags);
24671             </pre> <p id="doc_section_5_1_2_p_3">Use the XOF_CLOSE_FP flag to trigger a call to fclose() for the FILE pointer when the handle is destroyed.</p>
24672 </div>
24673 <div class="content">
24674 <h3 id="doc_section_5_1_3">
24675 <div class="self-section-number">
24676 <a href="#doc_section_5_1_3">5.1.3</a> </div>
24677 <a id="xo_set_writer" href="#xo_set_writer">xo_set_writer</a>
24678 </h3>
24679 <p id="doc_section_5_1_3_p_1">The xo_set_writer function allows custom 'write' functions which can tailor how libxo writes data. An opaque argument is recorded and passed back to the write function, allowing the function to acquire context information. The 'close' function can release this opaque data and any other resources as needed. The flush function can flush buffered data associated with the opaque object.</p>
24680 <div id="doc_figure_u.93"></div> <pre>
24681     void xo_set_writer (xo_handle_t *xop, void *opaque,
24682                         xo_write_func_t write_func,
24683                         xo_close_func_t close_func);
24684                         xo_flush_func_t flush_func);
24685             </pre> </div>
24686 <div class="content">
24687 <h3 id="doc_section_5_1_4">
24688 <div class="self-section-number">
24689 <a href="#doc_section_5_1_4">5.1.4</a> </div>
24690 <a id="xo_set_style" href="#xo_set_style">xo_set_style</a>
24691 </h3>
24692 <p id="doc_section_5_1_4_p_1">To set the style, use the xo_set_style() function:</p>
24693 <div id="doc_figure_u.94"></div> <pre>
24694     void xo_set_style(xo_handle_t *xop, unsigned style);
24695             </pre> <p id="doc_section_5_1_4_p_3">To use the default handle, pass a NULL handle:</p>
24696 <div id="doc_figure_u.95"></div> <pre>
24697     xo_set_style(NULL, XO_STYLE_XML);
24698             </pre> </div>
24699 <div class="content">
24700 <h3 id="doc_section_5_1_5">
24701 <div class="self-section-number">
24702 <a href="#doc_section_5_1_5">5.1.5</a> </div>
24703 <a id="xo_get_style" href="#xo_get_style">xo_get_style</a>
24704 </h3>
24705 <p id="doc_section_5_1_5_p_1">To find the current style, use the xo_get_style() function:</p>
24706 <div id="doc_figure_u.96"></div> <pre>
24707     xo_style_t xo_get_style(xo_handle_t *xop);
24708             </pre> <p id="doc_section_5_1_5_p_3">To use the default handle, pass a NULL handle:</p>
24709 <div id="doc_figure_u.97"></div> <pre>
24710     style = xo_get_style(NULL);
24711             </pre> <p id="doc_section_5_1_5_p_5">Section Contents: </p>
24712 <ul>
24713 <li><a href="#styles" title="Output Styles (XO_STYLE_*)">Section 5.1.5.1</a></li>
24714 <li><a href="#xo_set_style_name" title="xo_set_style_name">Section 5.1.5.2</a></li>
24715 </ul>
24716 <div class="content">
24717 <h4 id="doc_section_5_1_5_1">
24718 <div class="self-section-number">
24719 <a href="#doc_section_5_1_5_1">5.1.5.1</a> </div>
24720 <a id="styles" href="#styles">Output Styles (XO_STYLE_*)</a>
24721 </h4>
24722 <p id="doc_section_5_1_5_1_p_1">The libxo functions accept a set of output styles:</p>
24723 <div id="doc_table_u.12"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24724 <thead><tr>
24725 <th class="left">Flag</th>
24726 <th class="left">Description</th>
24727 </tr></thead>
24728 <tbody>
24729 <tr>
24730 <td>XO_STYLE_TEXT</td>
24731 <td>Traditional text output</td>
24732 </tr>
24733 <tr>
24734 <td>XO_STYLE_XML</td>
24735 <td>XML encoded data</td>
24736 </tr>
24737 <tr>
24738 <td>XO_STYLE_JSON</td>
24739 <td>JSON encoded data</td>
24740 </tr>
24741 <tr>
24742 <td>XO_STYLE_HTML</td>
24743 <td>HTML encoded data</td>
24744 </tr>
24745 </tbody>
24746 </table></div>
24747 </div>
24748 <div class="content">
24749 <h4 id="doc_section_5_1_5_2">
24750 <div class="self-section-number">
24751 <a href="#doc_section_5_1_5_2">5.1.5.2</a> </div>
24752 <a id="xo_set_style_name" href="#xo_set_style_name">xo_set_style_name</a>
24753 </h4>
24754 <p id="doc_section_5_1_5_2_p_1">The xo_set_style_name() can be used to set the style based on a name encoded as a string:</p>
24755 <div id="doc_figure_u.98"></div> <pre>
24756     int xo_set_style_name (xo_handle_t *xop, const char *style);
24757             </pre> <p id="doc_section_5_1_5_2_p_3">The name can be any of the styles: "text", "xml", "json", or "html".</p>
24758 <div id="doc_figure_u.99"></div> <pre>
24759     EXAMPLE:
24760         xo_set_style_name(NULL, "html");
24761             </pre> </div>
24762 </div>
24763 <div class="content">
24764 <h3 id="doc_section_5_1_6">
24765 <div class="self-section-number">
24766 <a href="#doc_section_5_1_6">5.1.6</a> </div>
24767 <a id="xo_set_flags" href="#xo_set_flags">xo_set_flags</a>
24768 </h3>
24769 <p id="doc_section_5_1_6_p_1">To set the flags, use the xo_set_flags() function:</p>
24770 <div id="doc_figure_u.100"></div> <pre>
24771     void xo_set_flags(xo_handle_t *xop, unsigned flags);
24772             </pre> <p id="doc_section_5_1_6_p_3">To use the default handle, pass a NULL handle:</p>
24773 <div id="doc_figure_u.101"></div> <pre>
24774     xo_set_style(NULL, XO_STYLE_XML);
24775             </pre> <p id="doc_section_5_1_6_p_5">Section Contents: </p>
24776 <ul>
24777 <li><a href="#flags" title="Flags (XOF_*)">Section 5.1.6.1</a></li>
24778 <li><a href="#xo_clear_flags" title="xo_clear_flags">Section 5.1.6.2</a></li>
24779 <li><a href="#xo_set_options" title="xo_set_options">Section 5.1.6.3</a></li>
24780 </ul>
24781 <div class="content">
24782 <h4 id="doc_section_5_1_6_1">
24783 <div class="self-section-number">
24784 <a href="#doc_section_5_1_6_1">5.1.6.1</a> </div>
24785 <a id="flags" href="#flags">Flags (XOF_*)</a>
24786 </h4>
24787 <p id="doc_section_5_1_6_1_p_1">The set of valid flags include:</p>
24788 <div id="doc_table_u.13"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24789 <thead><tr>
24790 <th class="left">Flag</th>
24791 <th class="left">Description</th>
24792 </tr></thead>
24793 <tbody>
24794 <tr>
24795 <td>XOF_CLOSE_FP</td>
24796 <td>Close file pointer on xo_destroy()</td>
24797 </tr>
24798 <tr>
24799 <td>XOF_COLOR</td>
24800 <td>Enable color and effects in output</td>
24801 </tr>
24802 <tr>
24803 <td>XOF_COLOR_ALLOWED</td>
24804 <td>Allow color/effect for terminal output</td>
24805 </tr>
24806 <tr>
24807 <td>XOF_DTRT</td>
24808 <td>Enable "do the right thing" mode</td>
24809 </tr>
24810 <tr>
24811 <td>XOF_INFO</td>
24812 <td>Display info data attributes (HTML)</td>
24813 </tr>
24814 <tr>
24815 <td>XOF_KEYS</td>
24816 <td>Emit the key attribute (XML)</td>
24817 </tr>
24818 <tr>
24819 <td>XOF_NO_ENV</td>
24820 <td>Do not use the LIBXO_OPTIONS env var</td>
24821 </tr>
24822 <tr>
24823 <td>XOF_NO_HUMANIZE</td>
24824 <td>Display humanization (TEXT, HTML)</td>
24825 </tr>
24826 <tr>
24827 <td>XOF_PRETTY</td>
24828 <td>Make 'pretty printed' output</td>
24829 </tr>
24830 <tr>
24831 <td>XOF_UNDERSCORES</td>
24832 <td>Replaces hyphens with underscores</td>
24833 </tr>
24834 <tr>
24835 <td>XOF_UNITS</td>
24836 <td>Display units (XML, HMTL)</td>
24837 </tr>
24838 <tr>
24839 <td>XOF_WARN</td>
24840 <td>Generate warnings for broken calls</td>
24841 </tr>
24842 <tr>
24843 <td>XOF_WARN_XML</td>
24844 <td>Generate warnings in XML on stdout</td>
24845 </tr>
24846 <tr>
24847 <td>XOF_XPATH</td>
24848 <td>Emit XPath expressions (HTML)</td>
24849 </tr>
24850 <tr>
24851 <td>XOF_COLUMNS</td>
24852 <td>Force xo_emit to return columns used</td>
24853 </tr>
24854 <tr>
24855 <td>XOF_FLUSH</td>
24856 <td>Flush output after each xo_emit call</td>
24857 </tr>
24858 </tbody>
24859 </table></div>
24860 <p id="doc_section_5_1_6_1_p_2">The XOF_CLOSE_FP flag will trigger the call of the close_func (provided via xo_set_writer()) when the handle is destroyed.</p>
24861 <p id="doc_section_5_1_6_1_p_3">The XOF_COLOR flag enables color and effects in output regardless of output device, while the XOF_COLOR_ALLOWED flag allows color and effects only if the output device is a terminal.</p>
24862 <p id="doc_section_5_1_6_1_p_4">The XOF_PRETTY flag requests 'pretty printing', which will trigger the addition of indentation and newlines to enhance the readability of XML, JSON, and HTML output. Text output is not affected.</p>
24863 <p id="doc_section_5_1_6_1_p_5">The XOF_WARN flag requests that warnings will trigger diagnostic output (on standard error) when the library notices errors during operations, or with arguments to functions. Without warnings enabled, such conditions are ignored.</p>
24864 <p id="doc_section_5_1_6_1_p_6">Warnings allow developers to debug their interaction with libxo. The function "xo_failure" can used as a breakpoint for a debugger, regardless of whether warnings are enabled.</p>
24865 <p id="doc_section_5_1_6_1_p_7">If the style is XO_STYLE_HTML, the following additional flags can be used:</p>
24866 <div id="doc_table_u.14"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24867 <thead><tr>
24868 <th class="left">Flag</th>
24869 <th class="left">Description</th>
24870 </tr></thead>
24871 <tbody>
24872 <tr>
24873 <td>XOF_XPATH</td>
24874 <td>Emit "data-xpath" attributes</td>
24875 </tr>
24876 <tr>
24877 <td>XOF_INFO</td>
24878 <td>Emit additional info fields</td>
24879 </tr>
24880 </tbody>
24881 </table></div>
24882 <p id="doc_section_5_1_6_1_p_8">The XOF_XPATH flag enables the emission of XPath expressions detailing the hierarchy of XML elements used to encode the data field, if the XPATH style of output were requested.</p>
24883 <p id="doc_section_5_1_6_1_p_9">The XOF_INFO flag encodes additional informational fields for HTML output. See <a href="#info" title="Field Information (xo_info_t)">Section 5.4.4</a> for details.</p>
24884 <p id="doc_section_5_1_6_1_p_10">If the style is XO_STYLE_XML, the following additional flags can be used:</p>
24885 <div id="doc_table_u.15"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24886 <thead><tr>
24887 <th class="left">Flag</th>
24888 <th class="left">Description</th>
24889 </tr></thead>
24890 <tbody><tr>
24891 <td>XOF_KEYS</td>
24892 <td>Flag 'key' fields for xml</td>
24893 </tr></tbody>
24894 </table></div>
24895 <p id="doc_section_5_1_6_1_p_11">The XOF_KEYS flag adds 'key' attribute to the XML encoding for field definitions that use the 'k' modifier. The key attribute has the value "key":</p>
24896 <div id="doc_figure_u.102"></div> <pre>
24897     xo_emit("{k:name}", item);
24898
24899   XML:
24900       &lt;name key="key"&gt;truck&lt;/name&gt;
24901             </pre> </div>
24902 <div class="content">
24903 <h4 id="doc_section_5_1_6_2">
24904 <div class="self-section-number">
24905 <a href="#doc_section_5_1_6_2">5.1.6.2</a> </div>
24906 <a id="xo_clear_flags" href="#xo_clear_flags">xo_clear_flags</a>
24907 </h4>
24908 <p id="doc_section_5_1_6_2_p_1">The xo_clear_flags() function turns off the given flags in a specific handle.</p>
24909 <div id="doc_figure_u.103"></div> <pre>
24910     void xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags);
24911             </pre> </div>
24912 <div class="content">
24913 <h4 id="doc_section_5_1_6_3">
24914 <div class="self-section-number">
24915 <a href="#doc_section_5_1_6_3">5.1.6.3</a> </div>
24916 <a id="xo_set_options" href="#xo_set_options">xo_set_options</a>
24917 </h4>
24918 <p id="doc_section_5_1_6_3_p_1">The xo_set_options() function accepts a comma-separated list of styles and flags and enables them for a specific handle.</p>
24919 <div id="doc_figure_u.104"></div> <pre>
24920     int xo_set_options (xo_handle_t *xop, const char *input);
24921             </pre> <p id="doc_section_5_1_6_3_p_3">The options are identical to those listed in <a href="#options" title="Command-line Arguments">Section 4</a>.</p>
24922 </div>
24923 </div>
24924 <div class="content">
24925 <h3 id="doc_section_5_1_7">
24926 <div class="self-section-number">
24927 <a href="#doc_section_5_1_7">5.1.7</a> </div>
24928 <a id="xo_destroy" href="#xo_destroy">xo_destroy</a>
24929 </h3>
24930 <p id="doc_section_5_1_7_p_1">The xo_destroy function releases a handle and any resources it is using. Calling xo_destroy with a NULL handle will release any resources associated with the default handle.</p>
24931 <div id="doc_figure_u.105"></div> <pre>
24932     void xo_destroy(xo_handle_t *xop);
24933             </pre> </div>
24934 </div>
24935 <div class="content">
24936 <h2 id="doc_section_5_2">
24937 <div class="self-section-number">
24938 <a href="#doc_section_5_2">5.2</a> </div>
24939 <a id="emitting-content-xo_emit" href="#emitting-content-xo_emit">Emitting Content (xo_emit)</a>
24940 </h2>
24941 <p id="doc_section_5_2_p_1">The following functions are used to emit output:</p>
24942 <div id="doc_figure_u.106"></div> <pre>
24943     int xo_emit (const char *fmt, ...);
24944     int xo_emit_h (xo_handle_t *xop, const char *fmt, ...);
24945     int xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap);
24946             </pre> <p id="doc_section_5_2_p_3">The "fmt" argument is a string containing field descriptors as specified in <a href="#format-strings" title="Format Strings">Section 3.2</a>. The use of a handle is optional and NULL can be passed to access the internal 'default' handle. See <a href="#handles" title="Handles">Section 5.1</a>.</p>
24947 <p id="doc_section_5_2_p_4">The remaining arguments to xo_emit() and xo_emit_h() are a set of arguments corresponding to the fields in the format string. Care must be taken to ensure the argument types match the fields in the format string, since an inappropriate cast can ruin your day. The vap argument to xo_emit_hv() points to a variable argument list that can be used to retrieve arguments via va_arg().</p>
24948 <p id="doc_section_5_2_p_5">Section Contents: </p>
24949 <ul>
24950 <li><a href="#xo_emit_field" title="Single Field Emitting Functions (xo_emit_field)">Section 5.2.1</a></li>
24951 <li><a href="#xo_attr" title="Attributes (xo_attr)">Section 5.2.2</a></li>
24952 <li><a href="#flushing-output-xo_flush" title="Flushing Output (xo_flush)">Section 5.2.3</a></li>
24953 <li><a href="#finishing-output-xo_finish" title="Finishing Output (xo_finish)">Section 5.2.4</a></li>
24954 </ul>
24955 <div class="content">
24956 <h3 id="doc_section_5_2_1">
24957 <div class="self-section-number">
24958 <a href="#doc_section_5_2_1">5.2.1</a> </div>
24959 <a id="xo_emit_field" href="#xo_emit_field">Single Field Emitting Functions (xo_emit_field)</a>
24960 </h3>
24961 <p id="doc_section_5_2_1_p_1">The following functions can also make output, but only make a single field at a time:</p>
24962 <div id="doc_figure_u.107"></div> <pre>
24963     int xo_emit_field_hv (xo_handle_t *xop, const char *rolmod,
24964                   const char *contents, const char *fmt, 
24965                   const char *efmt, va_list vap);
24966
24967     int xo_emit_field_h (xo_handle_t *xop, const char *rolmod, 
24968                  const char *contents, const char *fmt,
24969                  const char *efmt, ...);
24970
24971     int xo_emit_field (const char *rolmod, const char *contents,
24972                  const char *fmt, const char *efmt, ...);
24973             </pre> <p id="doc_section_5_2_1_p_3">These functions are intended to avoid the scenario where one would otherwise need to compose a format descriptors using snprintf(). The individual parts of the format descriptor are passed in distinctly.</p>
24974 <div id="doc_figure_u.108"></div> <pre>
24975     xo_emit("T", "Host name is ", NULL, NULL);
24976     xo_emit("V", "host-name", NULL, NULL, host-name);
24977             </pre> </div>
24978 <div class="content">
24979 <h3 id="doc_section_5_2_2">
24980 <div class="self-section-number">
24981 <a href="#doc_section_5_2_2">5.2.2</a> </div>
24982 <a id="xo_attr" href="#xo_attr">Attributes (xo_attr)</a>
24983 </h3>
24984 <p id="doc_section_5_2_2_p_1">The xo_attr() function emits attributes for the XML output style.</p>
24985 <div id="doc_figure_u.109"></div> <pre>
24986     int xo_attr (const char *name, const char *fmt, ...);
24987     int xo_attr_h (xo_handle_t *xop, const char *name, 
24988                    const char *fmt, ...);
24989     int xo_attr_hv (xo_handle_t *xop, const char *name, 
24990                    const char *fmt, va_list vap);
24991             </pre> <p id="doc_section_5_2_2_p_3">The name parameter give the name of the attribute to be encoded. The fmt parameter gives a printf-style format string used to format the value of the attribute using any remaining arguments, or the vap parameter passed to xo_attr_hv().</p>
24992 <div id="doc_figure_u.110"></div> <pre>
24993     EXAMPLE:
24994       xo_attr("seconds", "%ld", (unsigned long) login_time);
24995       struct tm *tmp = localtime(login_time);
24996       strftime(buf, sizeof(buf), "%R", tmp);
24997       xo_emit("Logged in at {:login-time}\n", buf);
24998     XML:
24999         &lt;login-time seconds="1408336270"&gt;00:14&lt;/login-time&gt;
25000             </pre> <p id="doc_section_5_2_2_p_5">xo_attr is placed on the next container, instance, leaf, or leaf list that is emitted.</p>
25001 <p id="doc_section_5_2_2_p_6">Since attributes are only emitted in XML, their use should be limited to meta-data and additional or redundant representations of data already emitted in other form.</p>
25002 </div>
25003 <div class="content">
25004 <h3 id="doc_section_5_2_3">
25005 <div class="self-section-number">
25006 <a href="#doc_section_5_2_3">5.2.3</a> </div>
25007 <a id="flushing-output-xo_flush" href="#flushing-output-xo_flush">Flushing Output (xo_flush)</a>
25008 </h3>
25009 <p id="doc_section_5_2_3_p_1">libxo buffers data, both for performance and consistency, but also to allow some advanced features to work properly. At various times, the caller may wish to flush any data buffered within the library. The xo_flush() call is used for this:</p>
25010 <div id="doc_figure_u.111"></div> <pre>
25011     void xo_flush (void);
25012     void xo_flush_h (xo_handle_t *xop);
25013             </pre> <p id="doc_section_5_2_3_p_3">Calling xo_flush also triggers the flush function associated with the handle. For the default handle, this is equivalent to "fflush(stdio);".</p>
25014 </div>
25015 <div class="content">
25016 <h3 id="doc_section_5_2_4">
25017 <div class="self-section-number">
25018 <a href="#doc_section_5_2_4">5.2.4</a> </div>
25019 <a id="finishing-output-xo_finish" href="#finishing-output-xo_finish">Finishing Output (xo_finish)</a>
25020 </h3>
25021 <p id="doc_section_5_2_4_p_1">When the program is ready to exit or close a handle, a call to xo_finish() is required. This flushes any buffered data, closes open libxo constructs, and completes any pending operations.</p>
25022 <div id="doc_figure_u.112"></div> <pre>
25023     int xo_finish (void);
25024     int xo_finish_h (xo_handle_t *xop);
25025     void xo_finish_atexit (void);
25026             </pre> <p id="doc_section_5_2_4_p_3">Calling this function is vital to the proper operation of libxo, especially for the non-TEXT output styles.</p>
25027 <p id="doc_section_5_2_4_p_4">xo_finish_atexit is suitable for use with atexit(3).</p>
25028 </div>
25029 </div>
25030 <div class="content">
25031 <h2 id="doc_section_5_3">
25032 <div class="self-section-number">
25033 <a href="#doc_section_5_3">5.3</a> </div>
25034 <a id="emitting-hierarchy" href="#emitting-hierarchy">Emitting Hierarchy</a>
25035 </h2>
25036 <p id="doc_section_5_3_p_1">libxo represents to types of hierarchy: containers and lists. A container appears once under a given parent where a list contains instances that can appear multiple times. A container is used to hold related fields and to give the data organization and scope.</p>
25037 <p id="doc_section_5_3_p_2">To create a container, use the xo_open_container and xo_close_container functions:</p>
25038 <div id="doc_figure_u.113"></div> <pre>
25039     int xo_open_container (const char *name);
25040     int xo_open_container_h (xo_handle_t *xop, const char *name);
25041     int xo_open_container_hd (xo_handle_t *xop, const char *name);
25042     int xo_open_container_d (const char *name);
25043
25044     int xo_close_container (const char *name);
25045     int xo_close_container_h (xo_handle_t *xop, const char *name);
25046     int xo_close_container_hd (xo_handle_t *xop);
25047     int xo_close_container_d (void);
25048             </pre> <p id="doc_section_5_3_p_4">The name parameter gives the name of the container, encoded in UTF-8. Since ASCII is a proper subset of UTF-8, traditional C strings can be used directly.</p>
25049 <p id="doc_section_5_3_p_5">The close functions with the "_d" suffix are used in "Do The Right Thing" mode, where the name of the open containers, lists, and instances are maintained internally by libxo to allow the caller to avoid keeping track of the open container name.</p>
25050 <p id="doc_section_5_3_p_6">Use the XOF_WARN flag to generate a warning if the name given on the close does not match the current open container.</p>
25051 <p id="doc_section_5_3_p_7">For TEXT and HTML output, containers are not rendered into output text, though for HTML they are used when the XOF_XPATH flag is set.</p>
25052 <div id="doc_figure_u.114"></div> <pre>
25053     EXAMPLE:
25054        xo_open_container("system");
25055        xo_emit("The host name is {:host-name}\n", hn);
25056        xo_close_container("system");
25057     XML:
25058        &lt;system&gt;&lt;host-name&gt;foo&lt;/host-name&gt;&lt;/system&gt;
25059             </pre> <p id="doc_section_5_3_p_9">Section Contents: </p>
25060 <ul><li><a href="#lists-and-instances-2" title="Lists and Instances">Section 5.3.1</a></li></ul>
25061 <div class="content">
25062 <h3 id="doc_section_5_3_1">
25063 <div class="self-section-number">
25064 <a href="#doc_section_5_3_1">5.3.1</a> </div>
25065 <a id="lists-and-instances-2" href="#lists-and-instances-2">Lists and Instances</a>
25066 </h3>
25067 <p id="doc_section_5_3_1_p_1">Lists are sequences of instances of homogeneous data objects. Two distinct levels of calls are needed to represent them in our output styles. Calls must be made to open and close a list, and for each instance of data in that list, calls must be make to open and close that instance.</p>
25068 <p id="doc_section_5_3_1_p_2">The name given to all calls must be identical, and it is strongly suggested that the name be singular, not plural, as a matter of style and usage expectations.</p>
25069 <div id="doc_figure_u.115"></div> <pre>
25070     EXAMPLE:
25071         xo_open_list("user");
25072         for (i = 0; i &lt; num_users; i++) {
25073             xo_open_instance("user");
25074             xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\n",
25075                     pw[i].pw_name, pw[i].pw_uid,
25076                     pw[i].pw_gid, pw[i].pw_dir);
25077             xo_close_instance("user");
25078         }
25079         xo_close_list("user");
25080     TEXT:
25081         phil:1001:1001:/home/phil
25082         pallavi:1002:1002:/home/pallavi
25083     XML:
25084         &lt;user&gt;
25085             &lt;name&gt;phil&lt;/name&gt;
25086             &lt;uid&gt;1001&lt;/uid&gt;
25087             &lt;gid&gt;1001&lt;/gid&gt;
25088             &lt;home&gt;/home/phil&lt;/home&gt;
25089         &lt;/user&gt;
25090         &lt;user&gt;
25091             &lt;name&gt;pallavi&lt;/name&gt;
25092             &lt;uid&gt;1002&lt;/uid&gt;
25093             &lt;gid&gt;1002&lt;/gid&gt;
25094             &lt;home&gt;/home/pallavi&lt;/home&gt;
25095         &lt;/user&gt;
25096     JSON:
25097         user: [
25098             {
25099                 "name": "phil",
25100                 "uid": 1001,
25101                 "gid": 1001,
25102                 "home": "/home/phil",
25103             },
25104             {
25105                 "name": "pallavi",
25106                 "uid": 1002,
25107                 "gid": 1002,
25108                 "home": "/home/pallavi",
25109             }
25110         ]
25111             </pre> </div>
25112 </div>
25113 <div class="content">
25114 <h2 id="doc_section_5_4">
25115 <div class="self-section-number">
25116 <a href="#doc_section_5_4">5.4</a> </div>
25117 <a id="support-functions" href="#support-functions">Support Functions</a>
25118 </h2>
25119 <p id="doc_section_5_4_p_1">Section Contents: </p>
25120 <ul>
25121 <li><a href="#xo_parse_args" title="Parsing Command-line Arguments (xo_parse_args)">Section 5.4.1</a></li>
25122 <li><a href="#xo_set_program" title="xo_set_program">Section 5.4.2</a></li>
25123 <li><a href="#xo_set_version" title="xo_set_version">Section 5.4.3</a></li>
25124 <li><a href="#info" title="Field Information (xo_info_t)">Section 5.4.4</a></li>
25125 <li><a href="#memory-allocation" title="Memory Allocation">Section 5.4.5</a></li>
25126 <li><a href="#LIBXO_OPTIONS" title="LIBXO_OPTIONS">Section 5.4.6</a></li>
25127 <li><a href="#errors-warnings-and-messages" title="Errors, Warnings, and Messages">Section 5.4.7</a></li>
25128 <li><a href="#xo_error" title="xo_error">Section 5.4.8</a></li>
25129 <li><a href="#xo_no_setlocale" title="xo_no_setlocale">Section 5.4.9</a></li>
25130 </ul>
25131 <div class="content">
25132 <h3 id="doc_section_5_4_1">
25133 <div class="self-section-number">
25134 <a href="#doc_section_5_4_1">5.4.1</a> </div>
25135 <a id="xo_parse_args" href="#xo_parse_args">Parsing Command-line Arguments (xo_parse_args)</a>
25136 </h3>
25137 <p id="doc_section_5_4_1_p_1">The xo_parse_args() function is used to process a program's arguments. libxo-specific options are processed and removed from the argument list so the calling application does not need to process them. If successful, a new value for argc is returned. On failure, a message it emitted and -1 is returned.</p>
25138 <div id="doc_figure_u.116"></div> <pre>
25139     argc = xo_parse_args(argc, argv);
25140     if (argc &lt; 0)
25141         exit(EXIT_FAILURE);
25142             </pre> <p id="doc_section_5_4_1_p_3">Following the call to xo_parse_args, the application can process the remaining arguments in a normal manner. See <a href="#options" title="Command-line Arguments">Section 4</a> for a description of valid arguments.</p>
25143 </div>
25144 <div class="content">
25145 <h3 id="doc_section_5_4_2">
25146 <div class="self-section-number">
25147 <a href="#doc_section_5_4_2">5.4.2</a> </div>
25148 <a id="xo_set_program" href="#xo_set_program">xo_set_program</a>
25149 </h3>
25150 <p id="doc_section_5_4_2_p_1">The xo_set_program function sets name of the program as reported by functions like xo_failure, xo_warn, xo_err, etc. The program name is initialized by xo_parse_args, but subsequent calls to xo_set_program can override this value.</p>
25151 <div id="doc_figure_u.117"></div> <pre>
25152     xo_set_program(argv[0]);
25153             </pre> <p id="doc_section_5_4_2_p_3">Note that the value is not copied, so the memory passed to xo_set_program (and xo_parse_args) must be maintained by the caller.</p>
25154 </div>
25155 <div class="content">
25156 <h3 id="doc_section_5_4_3">
25157 <div class="self-section-number">
25158 <a href="#doc_section_5_4_3">5.4.3</a> </div>
25159 <a id="xo_set_version" href="#xo_set_version">xo_set_version</a>
25160 </h3>
25161 <p id="doc_section_5_4_3_p_1">The xo_set_version function records a version number to be emitted as part of the data for encoding styles (XML and JSON). This version number is suitable for tracking changes in the content, allowing a user of the data to discern which version of the data model is in use.</p>
25162 <div id="doc_figure_u.118"></div> <pre>
25163      void xo_set_version (const char *version);
25164      void xo_set_version_h (xo_handle_t *xop, const char *version);
25165             </pre> </div>
25166 <div class="content">
25167 <h3 id="doc_section_5_4_4">
25168 <div class="self-section-number">
25169 <a href="#doc_section_5_4_4">5.4.4</a> </div>
25170 <a id="info" href="#info">Field Information (xo_info_t)</a>
25171 </h3>
25172 <p id="doc_section_5_4_4_p_1">HTML data can include additional information in attributes that begin with "data&#8209;". To enable this, three things must occur:</p>
25173 <p id="doc_section_5_4_4_p_2">First the application must build an array of xo_info_t structures, one per tag. The array must be sorted by name, since libxo uses a binary search to find the entry that matches names from format instructions.</p>
25174 <p id="doc_section_5_4_4_p_3">Second, the application must inform libxo about this information using the xo_set_info() call:</p>
25175 <div id="doc_figure_u.119"></div> <pre>
25176     typedef struct xo_info_s {
25177         const char *xi_name;    /* Name of the element */
25178         const char *xi_type;    /* Type of field */
25179         const char *xi_help;    /* Description of field */
25180     } xo_info_t;
25181
25182     void xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count);
25183             </pre> <p id="doc_section_5_4_4_p_5">Like other libxo calls, passing NULL for the handle tells libxo to use the default handle.</p>
25184 <p id="doc_section_5_4_4_p_6">If the count is -1, libxo will count the elements of infop, but there must be an empty element at the end. More typically, the number is known to the application:</p>
25185 <div id="doc_figure_u.120"></div> <pre>
25186     xo_info_t info[] = {
25187         { "in-stock", "number", "Number of items in stock" },
25188         { "name", "string", "Name of the item" },
25189         { "on-order", "number", "Number of items on order" },
25190         { "sku", "string", "Stock Keeping Unit" },
25191         { "sold", "number", "Number of items sold" },
25192     };
25193     int info_count = (sizeof(info) / sizeof(info[0]));
25194     ...
25195     xo_set_info(NULL, info, info_count);
25196             </pre> <p id="doc_section_5_4_4_p_8">Third, the emission of info must be triggered with the XOF_INFO flag using either the xo_set_flags() function or the "&#8209;&#8209;libxo=info" command line argument.</p>
25197 <p id="doc_section_5_4_4_p_9">The type and help values, if present, are emitted as the "data&#8209;type" and "data&#8209;help" attributes:</p>
25198 <div id="doc_figure_u.121"></div> <pre>
25199   &lt;div class="data" data-tag="sku" data-type="string" 
25200        data-help="Stock Keeping Unit"&gt;GRO-000-533&lt;/div&gt;
25201             </pre> </div>
25202 <div class="content">
25203 <h3 id="doc_section_5_4_5">
25204 <div class="self-section-number">
25205 <a href="#doc_section_5_4_5">5.4.5</a> </div>
25206 <a id="memory-allocation" href="#memory-allocation">Memory Allocation</a>
25207 </h3>
25208 <p id="doc_section_5_4_5_p_1">The xo_set_allocator function allows libxo to be used in environments where the standard realloc() and free() functions are not available.</p>
25209 <div id="doc_figure_u.122"></div> <pre>
25210     void xo_set_allocator (xo_realloc_func_t realloc_func,
25211                            xo_free_func_t free_func);
25212             </pre> <p id="doc_section_5_4_5_p_3">realloc_func should expect the same arguments as realloc(3) and return a pointer to memory following the same convention. free_func will receive the same argument as free(3) and should release it, as appropriate for the environment.</p>
25213 <p id="doc_section_5_4_5_p_4">By default, the standard realloc() and free() functions are used.</p>
25214 </div>
25215 <div class="content">
25216 <h3 id="doc_section_5_4_6">
25217 <div class="self-section-number">
25218 <a href="#doc_section_5_4_6">5.4.6</a> </div>
25219 <a id="LIBXO_OPTIONS" href="#LIBXO_OPTIONS">LIBXO_OPTIONS</a>
25220 </h3>
25221 <p id="doc_section_5_4_6_p_1">The environment variable "LIBXO_OPTIONS" can be set to a subset of libxo options, including:</p>
25222 <p id="doc_section_5_4_6_p_2"> </p>
25223 <ul>
25224 <li>color</li>
25225 <li>flush</li>
25226 <li>flush-line</li>
25227 <li>no-color</li>
25228 <li>no-humanize</li>
25229 <li>no-locale</li>
25230 <li>no-retain</li>
25231 <li>pretty</li>
25232 <li>retain</li>
25233 <li>underscores</li>
25234 <li>warn</li>
25235 </ul>
25236 <p id="doc_section_5_4_6_p_3">For example, warnings can be enabled by:</p>
25237 <div id="doc_figure_u.123"></div> <pre>
25238     % env LIBXO_OPTIONS=warn my-app
25239             </pre> <p id="doc_section_5_4_6_p_5">Since environment variables are inherited, child processes will have the same options, which may be undesirable, making the use of the "&#8209;&#8209;libxo" option is preferable in most situations.</p>
25240 </div>
25241 <div class="content">
25242 <h3 id="doc_section_5_4_7">
25243 <div class="self-section-number">
25244 <a href="#doc_section_5_4_7">5.4.7</a> </div>
25245 <a id="errors-warnings-and-messages" href="#errors-warnings-and-messages">Errors, Warnings, and Messages</a>
25246 </h3>
25247 <p id="doc_section_5_4_7_p_1">Many programs make use of the standard library functions err() and warn() to generate errors and warnings for the user. libxo wants to pass that information via the current output style, and provides compatible functions to allow this:</p>
25248 <div id="doc_figure_u.124"></div> <pre>
25249     void xo_warn (const char *fmt, ...);
25250     void xo_warnx (const char *fmt, ...);
25251     void xo_warn_c (int code, const char *fmt, ...);
25252     void xo_warn_hc (xo_handle_t *xop, int code,
25253                      const char *fmt, ...);
25254     void xo_err (int eval, const char *fmt, ...);
25255     void xo_errc (int eval, int code, const char *fmt, ...);
25256     void xo_errx (int eval, const char *fmt, ...);
25257     void xo_message (const char *fmt, ...);
25258     void xo_message_c (int code, const char *fmt, ...);
25259     void xo_message_hc (xo_handle_t *xop, int code,
25260                         const char *fmt, ...);
25261     void xo_message_hcv (xo_handle_t *xop, int code, 
25262                          const char *fmt, va_list vap);
25263             </pre> <p id="doc_section_5_4_7_p_3">These functions display the program name, a colon, a formatted message based on the arguments, and then optionally a colon and an error message associated with either "errno" or the "code" parameter.</p>
25264 <div id="doc_figure_u.125"></div> <pre>
25265     EXAMPLE:
25266         if (open(filename, O_RDONLY) &lt; 0)
25267             xo_err(1, "cannot open file '%s'", filename);
25268             </pre> </div>
25269 <div class="content">
25270 <h3 id="doc_section_5_4_8">
25271 <div class="self-section-number">
25272 <a href="#doc_section_5_4_8">5.4.8</a> </div>
25273 <a id="xo_error" href="#xo_error">xo_error</a>
25274 </h3>
25275 <p id="doc_section_5_4_8_p_1">The xo_error function can be used for generic errors that should be reported over the handle, rather than to stderr. The xo_error function behaves like xo_err for TEXT and HTML output styles, but puts the error into XML or JSON elements:</p>
25276 <div id="doc_figure_u.126"></div> <pre>
25277     EXAMPLE::
25278         xo_error("Does not %s", "compute");
25279     XML::
25280         &lt;error&gt;&lt;message&gt;Does not compute&lt;/message&gt;&lt;/error&gt;
25281     JSON::
25282         "error": { "message": "Does not compute" }
25283             </pre> </div>
25284 <div class="content">
25285 <h3 id="doc_section_5_4_9">
25286 <div class="self-section-number">
25287 <a href="#doc_section_5_4_9">5.4.9</a> </div>
25288 <a id="xo_no_setlocale" href="#xo_no_setlocale">xo_no_setlocale</a>
25289 </h3>
25290 <p id="doc_section_5_4_9_p_1">libxo automatically initializes the locale based on setting of the environment variables LC_CTYPE, LANG, and LC_ALL. The first of this list of variables is used and if none of the variables, the locale defaults to "UTF&#8209;8". The caller may wish to avoid this behavior, and can do so by calling the xo_no_setlocale() function.</p>
25291 <div id="doc_figure_u.127"></div> <pre>
25292     void xo_no_setlocale (void);
25293             </pre> </div>
25294 </div>
25295 <div class="content">
25296 <h2 id="doc_section_5_5">
25297 <div class="self-section-number">
25298 <a href="#doc_section_5_5">5.5</a> </div>
25299 <a id="emitting-syslog-messages" href="#emitting-syslog-messages">Emitting syslog Messages</a>
25300 </h2>
25301 <p id="doc_section_5_5_p_1">syslog is the system logging facility used throughout the unix world. Messages are sent from commands, applications, and daemons to a hierarchy of servers, where they are filtered, saved, and forwarded based on configuration behaviors.</p>
25302 <p id="doc_section_5_5_p_2">syslog is an older protocol, originally documented only in source code. By the time RFC 3164 published, variation and mutation left the leading "&lt;pri&gt;" string as only common content. RFC 5424 defines a new version (version 1) of syslog and introduces structured data into the messages. Structured data is a set of name/value pairs transmitted distinctly alongside the traditional text message, allowing filtering on precise values instead of regular expressions.</p>
25303 <p id="doc_section_5_5_p_3">These name/value pairs are scoped by a two-part identifier; an enterprise identifier names the party responsible for the message catalog and a name identifying that message. Enterprise IDs are defined by IANA, the Internet Assigned Numbers Authority:</p>
25304 <p id="doc_section_5_5_p_4">https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers</p>
25305 <p id="doc_section_5_5_p_5">Use the <a href="#xo_set_syslog_enterprise_id" title="xo_set_syslog_enterprise_id">Section 5.5.3.5</a>() function to set the Enterprise ID, as needed.</p>
25306 <p id="doc_section_5_5_p_6">The message name should follow the conventions in <a href="#good-field-names" title="What makes a good field name?">Section 10.1.3</a>, as should the fields within the message.</p>
25307 <div id="doc_figure_u.128"></div> <pre>
25308     /* Both of these calls are optional */
25309     xo_set_syslog_enterprise_id(32473);
25310     xo_open_log("my-program", 0, LOG_DAEMON);
25311
25312     /* Generate a syslog message */
25313     xo_syslog(LOG_ERR, "upload-failed",
25314               "error &lt;%d&gt; uploading file '{:filename}' "
25315               "as '{:target/%s:%s}'",
25316               code, filename, protocol, remote);
25317
25318     xo_syslog(LOG_INFO, "poofd-invalid-state",
25319               "state {:current/%u} is invalid {:connection/%u}",
25320               state, conn);
25321             </pre> <p id="doc_section_5_5_p_8">The developer should be aware that the message name may be used in the future to allow access to further information, including documentation. Care should be taken to choose quality, descriptive names.</p>
25322 <p id="doc_section_5_5_p_9">Section Contents: </p>
25323 <ul>
25324 <li><a href="#priority" title="Priority, Facility, and Flags">Section 5.5.1</a></li>
25325 <li><a href="#xo_syslog" title="xo_syslog">Section 5.5.2</a></li>
25326 <li><a href="#support-functions-2" title="Support functions">Section 5.5.3</a></li>
25327 </ul>
25328 <div class="content">
25329 <h3 id="doc_section_5_5_1">
25330 <div class="self-section-number">
25331 <a href="#doc_section_5_5_1">5.5.1</a> </div>
25332 <a id="priority" href="#priority">Priority, Facility, and Flags</a>
25333 </h3>
25334 <p id="doc_section_5_5_1_p_1">The xo_syslog, xo_vsyslog, and xo_open_log functions accept a set of flags which provide the priority of the message, the source facility, and some additional features. These values are OR'd together to create a single integer argument:</p>
25335 <div id="doc_figure_u.129"></div> <pre>
25336     xo_syslog(LOG_ERR | LOG_AUTH, "login-failed",
25337              "Login failed; user '{:user}' from host '{:address}'",
25338              user, addr);
25339             </pre> <p id="doc_section_5_5_1_p_3">These values are defined in &lt;syslog.h&gt;.</p>
25340 <p id="doc_section_5_5_1_p_4">The priority value indicates the importance and potential impact of each message.</p>
25341 <div id="doc_table_u.16"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25342 <thead><tr>
25343 <th class="left">Priority</th>
25344 <th class="left">Description</th>
25345 </tr></thead>
25346 <tbody>
25347 <tr>
25348 <td>LOG_EMERG</td>
25349 <td>A panic condition, normally broadcast to all users</td>
25350 </tr>
25351 <tr>
25352 <td>LOG_ALERT</td>
25353 <td>A condition that should be corrected immediately</td>
25354 </tr>
25355 <tr>
25356 <td>LOG_CRIT</td>
25357 <td>Critical conditions</td>
25358 </tr>
25359 <tr>
25360 <td>LOG_ERR</td>
25361 <td>Generic errors</td>
25362 </tr>
25363 <tr>
25364 <td>LOG_WARNING</td>
25365 <td>Warning messages</td>
25366 </tr>
25367 <tr>
25368 <td>LOG_NOTICE</td>
25369 <td>Non-error conditions that might need special handling</td>
25370 </tr>
25371 <tr>
25372 <td>LOG_INFO</td>
25373 <td>Informational messages</td>
25374 </tr>
25375 <tr>
25376 <td>LOG_DEBUG</td>
25377 <td>Developer-oriented messages</td>
25378 </tr>
25379 </tbody>
25380 </table></div>
25381 <p id="doc_section_5_5_1_p_5">The facility value indicates the source of message, in fairly generic terms.</p>
25382 <div id="doc_table_u.17"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25383 <thead><tr>
25384 <th class="left">Facility</th>
25385 <th class="left">Description</th>
25386 </tr></thead>
25387 <tbody>
25388 <tr>
25389 <td>LOG_AUTH</td>
25390 <td>The authorization system (e.g. login(1))</td>
25391 </tr>
25392 <tr>
25393 <td>LOG_AUTHPRIV</td>
25394 <td>As LOG_AUTH, but logged to a privileged file</td>
25395 </tr>
25396 <tr>
25397 <td>LOG_CRON</td>
25398 <td>The cron daemon: cron(8)</td>
25399 </tr>
25400 <tr>
25401 <td>LOG_DAEMON</td>
25402 <td>System daemons, not otherwise explicitly listed</td>
25403 </tr>
25404 <tr>
25405 <td>LOG_FTP</td>
25406 <td>The file transfer protocol daemons</td>
25407 </tr>
25408 <tr>
25409 <td>LOG_KERN</td>
25410 <td>Messages generated by the kernel</td>
25411 </tr>
25412 <tr>
25413 <td>LOG_LPR</td>
25414 <td>The line printer spooling system</td>
25415 </tr>
25416 <tr>
25417 <td>LOG_MAIL</td>
25418 <td>The mail system</td>
25419 </tr>
25420 <tr>
25421 <td>LOG_NEWS</td>
25422 <td>The network news system</td>
25423 </tr>
25424 <tr>
25425 <td>LOG_SECURITY</td>
25426 <td>Security subsystems, such as ipfw(4)</td>
25427 </tr>
25428 <tr>
25429 <td>LOG_SYSLOG</td>
25430 <td>Messages generated internally by syslogd(8)</td>
25431 </tr>
25432 <tr>
25433 <td>LOG_USER</td>
25434 <td>Messages generated by user processes (default)</td>
25435 </tr>
25436 <tr>
25437 <td>LOG_UUCP</td>
25438 <td>The uucp system</td>
25439 </tr>
25440 <tr>
25441 <td>LOG_LOCAL0..7</td>
25442 <td>Reserved for local use</td>
25443 </tr>
25444 </tbody>
25445 </table></div>
25446 <p id="doc_section_5_5_1_p_6">In addition to the values listed above, xo_open_log accepts a set of addition flags requesting specific behaviors.</p>
25447 <div id="doc_table_u.18"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25448 <thead><tr>
25449 <th class="left">Flag</th>
25450 <th class="left">Description</th>
25451 </tr></thead>
25452 <tbody>
25453 <tr>
25454 <td>LOG_CONS</td>
25455 <td>If syslogd fails, attempt to write to /dev/console</td>
25456 </tr>
25457 <tr>
25458 <td>LOG_NDELAY</td>
25459 <td>Open the connection to syslogd(8) immediately</td>
25460 </tr>
25461 <tr>
25462 <td>LOG_PERROR</td>
25463 <td>Write the message also to standard error output</td>
25464 </tr>
25465 <tr>
25466 <td>LOG_PID</td>
25467 <td>Log the process id with each message</td>
25468 </tr>
25469 </tbody>
25470 </table></div>
25471 </div>
25472 <div class="content">
25473 <h3 id="doc_section_5_5_2">
25474 <div class="self-section-number">
25475 <a href="#doc_section_5_5_2">5.5.2</a> </div>
25476 <a id="xo_syslog" href="#xo_syslog">xo_syslog</a>
25477 </h3>
25478 <p id="doc_section_5_5_2_p_1">Use the xo_syslog function to generate syslog messages by calling it with a log priority and facility, a message name, a format string, and a set of arguments. The priority/facility argument are discussed above, as is the message name.</p>
25479 <p id="doc_section_5_5_2_p_2">The format string follows the same conventions as xo_emit's format string, with each field being rendered as an SD-PARAM pair.</p>
25480 <div id="doc_figure_u.130"></div> <pre>
25481     xo_syslog(LOG_ERR, "poofd-missing-file",
25482               "'{:filename}' not found: {:error/%m}", filename);
25483
25484     ... [poofd-missing-file@32473 filename="/etc/poofd.conf"
25485           error="Permission denied"] '/etc/poofd.conf' not
25486           found: Permission denied
25487             </pre> </div>
25488 <div class="content">
25489 <h3 id="doc_section_5_5_3">
25490 <div class="self-section-number">
25491 <a href="#doc_section_5_5_3">5.5.3</a> </div>
25492 <a id="support-functions-2" href="#support-functions-2">Support functions</a>
25493 </h3>
25494 <p id="doc_section_5_5_3_p_1">Section Contents: </p>
25495 <ul>
25496 <li><a href="#xo_vsyslog" title="xo_vsyslog">Section 5.5.3.1</a></li>
25497 <li><a href="#xo_open_log" title="xo_open_log">Section 5.5.3.2</a></li>
25498 <li><a href="#xo_close_log" title="xo_close_log">Section 5.5.3.3</a></li>
25499 <li><a href="#xo_set_logmask" title="xo_set_logmask">Section 5.5.3.4</a></li>
25500 <li><a href="#xo_set_syslog_enterprise_id" title="xo_set_syslog_enterprise_id">Section 5.5.3.5</a></li>
25501 </ul>
25502 <div class="content">
25503 <h4 id="doc_section_5_5_3_1">
25504 <div class="self-section-number">
25505 <a href="#doc_section_5_5_3_1">5.5.3.1</a> </div>
25506 <a id="xo_vsyslog" href="#xo_vsyslog">xo_vsyslog</a>
25507 </h4>
25508 <p id="doc_section_5_5_3_1_p_1">xo_vsyslog is identical in function to xo_syslog, but takes the set of arguments using a va_list.</p>
25509 <div id="doc_figure_u.131"></div> <pre>
25510     void my_log (const char *name, const char *fmt, ...)
25511     {
25512         va_list vap;
25513         va_start(vap, fmt);
25514         xo_vsyslog(LOG_ERR, name, fmt, vap);
25515         va_end(vap);
25516     }
25517             </pre> </div>
25518 <div class="content">
25519 <h4 id="doc_section_5_5_3_2">
25520 <div class="self-section-number">
25521 <a href="#doc_section_5_5_3_2">5.5.3.2</a> </div>
25522 <a id="xo_open_log" href="#xo_open_log">xo_open_log</a>
25523 </h4>
25524 <p id="doc_section_5_5_3_2_p_1">xo_open_log functions similar to openlog(3), allowing customization of the program name, the log facility number, and the additional option flags described in <a href="#priority" title="Priority, Facility, and Flags">Section 5.5.1</a>.</p>
25525 <div id="doc_figure_u.132"></div> <pre>
25526     void
25527     xo_open_log (const char *ident, int logopt, int facility);
25528             </pre> </div>
25529 <div class="content">
25530 <h4 id="doc_section_5_5_3_3">
25531 <div class="self-section-number">
25532 <a href="#doc_section_5_5_3_3">5.5.3.3</a> </div>
25533 <a id="xo_close_log" href="#xo_close_log">xo_close_log</a>
25534 </h4>
25535 <p id="doc_section_5_5_3_3_p_1">xo_close_log functions similar to closelog(3), closing the log file and releasing any associated resources.</p>
25536 <div id="doc_figure_u.133"></div> <pre>
25537     void
25538     xo_close_log (void);
25539             </pre> </div>
25540 <div class="content">
25541 <h4 id="doc_section_5_5_3_4">
25542 <div class="self-section-number">
25543 <a href="#doc_section_5_5_3_4">5.5.3.4</a> </div>
25544 <a id="xo_set_logmask" href="#xo_set_logmask">xo_set_logmask</a>
25545 </h4>
25546 <p id="doc_section_5_5_3_4_p_1">xo_set_logmask function similar to setlogmask(3), restricting the set of generated log event to those whose associated bit is set in maskpri. Use LOG_MASK(pri) to find the appropriate bit, or LOG_UPTO(toppri) to create a mask for all priorities up to and including toppri.</p>
25547 <div id="doc_figure_u.134"></div> <pre>
25548     int
25549     xo_set_logmask (int maskpri);
25550
25551   Example:
25552     setlogmask(LOG_UPTO(LOG_WARN));
25553             </pre> </div>
25554 <div class="content">
25555 <h4 id="doc_section_5_5_3_5">
25556 <div class="self-section-number">
25557 <a href="#doc_section_5_5_3_5">5.5.3.5</a> </div>
25558 <a id="xo_set_syslog_enterprise_id" href="#xo_set_syslog_enterprise_id">xo_set_syslog_enterprise_id</a>
25559 </h4>
25560 <p id="doc_section_5_5_3_5_p_1">Use the xo_set_syslog_enterprise_id to supply a platform- or application-specific enterprise id. This value is used in any future syslog messages.</p>
25561 <p id="doc_section_5_5_3_5_p_2">Ideally, the operating system should supply a default value via the "kern.syslog.enterprise_id" sysctl value. Lacking that, the application should provide a suitable value.</p>
25562 <div id="doc_figure_u.135"></div> <pre>
25563     void
25564     xo_set_syslog_enterprise_id (unsigned short eid);
25565             </pre> <p id="doc_section_5_5_3_5_p_4">Enterprise IDs are administered by IANA, the Internet Assigned Number Authority. The complete list is EIDs on their web site:</p>
25566 <p id="doc_section_5_5_3_5_p_5"> <a href="https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers">https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers</a></p>
25567 <p id="doc_section_5_5_3_5_p_6">New EIDs can be requested from IANA using the following page:</p>
25568 <p id="doc_section_5_5_3_5_p_7"> <a href="http://pen.iana.org/pen/PenApplication.page">http://pen.iana.org/pen/PenApplication.page</a></p>
25569 <p id="doc_section_5_5_3_5_p_8">Each software development organization that defines a set of syslog messages should register their own EID and use that value in their software to ensure that messages can be uniquely identified by the combination of EID + message name.</p>
25570 </div>
25571 </div>
25572 </div>
25573 <div class="content">
25574 <h2 id="doc_section_5_6">
25575 <div class="self-section-number">
25576 <a href="#doc_section_5_6">5.6</a> </div>
25577 <a id="creating-custom-encoders" href="#creating-custom-encoders">Creating Custom Encoders</a>
25578 </h2>
25579 <p id="doc_section_5_6_p_1">The number of encoding schemes in current use is staggering, with new and distinct schemes appearing daily. While libxo provide XML, JSON, HMTL, and text natively, there are requirements for other encodings.</p>
25580 <p id="doc_section_5_6_p_2">Rather than bake support for all possible encoders into libxo, the API allows them to be defined externally. libxo can then interfaces with these encoding modules using a simplistic API. libxo processes all functions calls, handles state transitions, performs all formatting, and then passes the results as operations to a customized encoding function, which implements specific encoding logic as required. This means your encoder doesn't need to detect errors with unbalanced open/close operations but can rely on libxo to pass correct data.</p>
25581 <p id="doc_section_5_6_p_3">By making a simple API, libxo internals are not exposed, insulating the encoder and the library from future or internal changes.</p>
25582 <p id="doc_section_5_6_p_4">The three elements of the API are:</p>
25583 <p id="doc_section_5_6_p_5"> </p>
25584 <ul>
25585 <li>loading</li>
25586 <li>initialization</li>
25587 <li>operations</li>
25588 </ul>
25589 <p id="doc_section_5_6_p_6">The following sections provide details about these topics.</p>
25590 <p id="doc_section_5_6_p_7">libxo source contain an encoder for Concise Binary Object Representation, aka CBOR (RFC 7049) which can be used as used as an example for the API.</p>
25591 <p id="doc_section_5_6_p_8">Section Contents: </p>
25592 <ul>
25593 <li><a href="#loading-encoders" title="Loading Encoders">Section 5.6.1</a></li>
25594 <li><a href="#encoder-initialization" title="Encoder Initialization">Section 5.6.2</a></li>
25595 <li><a href="#operations" title="Operations">Section 5.6.3</a></li>
25596 </ul>
25597 <div class="content">
25598 <h3 id="doc_section_5_6_1">
25599 <div class="self-section-number">
25600 <a href="#doc_section_5_6_1">5.6.1</a> </div>
25601 <a id="loading-encoders" href="#loading-encoders">Loading Encoders</a>
25602 </h3>
25603 <p id="doc_section_5_6_1_p_1">Encoders can be registered statically or discovered dynamically. Applications can choose to call the xo_encoder_register() function to explicitly register encoders, but more typically they are built as shared libraries, placed in the libxo/extensions directory, and loaded based on name. libxo looks for a file with the name of the encoder and an extension of ".enc". This can be a file or a symlink to the shared library file that supports the encoder.</p>
25604 <div id="doc_figure_u.136"></div> <pre>
25605     % ls -1 lib/libxo/extensions/*.enc
25606     lib/libxo/extensions/cbor.enc
25607     lib/libxo/extensions/test.enc
25608             </pre> </div>
25609 <div class="content">
25610 <h3 id="doc_section_5_6_2">
25611 <div class="self-section-number">
25612 <a href="#doc_section_5_6_2">5.6.2</a> </div>
25613 <a id="encoder-initialization" href="#encoder-initialization">Encoder Initialization</a>
25614 </h3>
25615 <p id="doc_section_5_6_2_p_1">Each encoder must export a symbol used to access the library, which must have the following signature:</p>
25616 <div id="doc_figure_u.137"></div> <pre>
25617     int xo_encoder_library_init (XO_ENCODER_INIT_ARGS);
25618             </pre> <p id="doc_section_5_6_2_p_3">XO_ENCODER_INIT_ARGS is a macro defined in xo_encoder.h that defines an argument called "arg", a pointer of the type xo_encoder_init_args_t. This structure contains two fields:</p>
25619 <p id="doc_section_5_6_2_p_4"> </p>
25620 <ul>
25621 <li>xei_version is the version number of the API as implemented within libxo. This version is currently as 1 using XO_ENCODER_VERSION. This number can be checked to ensure compatibility. The working assumption is that all versions should be backward compatible, but each side may need to accurately know the version supported by the other side. xo_encoder_library_init can optionally check this value, and must then set it to the version number used by the encoder, allowing libxo to detect version differences and react accordingly. For example, if version 2 adds new operations, then libxo will know that an encoding library that set xei_version to 1 cannot be expected to handle those new operations.</li>
25622 <li>xei_handler must be set to a pointer to a function of type xo_encoder_func_t, as defined in xo_encoder.h. This function takes a set of parameters: -- xop is a pointer to the opaque xo_handle_t structure -- op is an integer representing the current operation -- name is a string whose meaning differs by operation -- value is a string whose meaning differs by operation -- private is an opaque structure provided by the encoder</li>
25623 </ul>
25624 <p id="doc_section_5_6_2_p_5">Additional arguments may be added in the future, so handler functions should use the XO_ENCODER_HANDLER_ARGS macro. An appropriate "extern" declaration is provided to help catch errors.</p>
25625 <p id="doc_section_5_6_2_p_6">Once the encoder initialization function has completed processing, it should return zero to indicate that no error has occurred. A non-zero return code will cause the handle initialization to fail.</p>
25626 </div>
25627 <div class="content">
25628 <h3 id="doc_section_5_6_3">
25629 <div class="self-section-number">
25630 <a href="#doc_section_5_6_3">5.6.3</a> </div>
25631 <a id="operations" href="#operations">Operations</a>
25632 </h3>
25633 <p id="doc_section_5_6_3_p_1">The encoder API defines a set of operations representing the processing model of libxo. Content is formatted within libxo, and callbacks are made to the encoder's handler function when data is ready to be processed.</p>
25634 <div id="doc_table_u.19"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25635 <thead><tr>
25636 <th class="left">Operation</th>
25637 <th class="left">Meaning (Base function)</th>
25638 </tr></thead>
25639 <tbody>
25640 <tr>
25641 <td>XO_OP_CREATE</td>
25642 <td>Called when the handle is created</td>
25643 </tr>
25644 <tr>
25645 <td>XO_OP_OPEN_CONTAINER</td>
25646 <td>Container opened (xo_open_container)</td>
25647 </tr>
25648 <tr>
25649 <td>XO_OP_CLOSE_CONTAINER</td>
25650 <td>Container closed (xo_close_container)</td>
25651 </tr>
25652 <tr>
25653 <td>XO_OP_OPEN_LIST</td>
25654 <td>List opened (xo_open_list)</td>
25655 </tr>
25656 <tr>
25657 <td>XO_OP_CLOSE_LIST</td>
25658 <td>List closed (xo_close_list)</td>
25659 </tr>
25660 <tr>
25661 <td>XO_OP_OPEN_LEAF_LIST</td>
25662 <td>Leaf list opened (xo_open_leaf_list)</td>
25663 </tr>
25664 <tr>
25665 <td>XO_OP_CLOSE_LEAF_LIST</td>
25666 <td>Leaf list closed (xo_close_leaf_list)</td>
25667 </tr>
25668 <tr>
25669 <td>XO_OP_OPEN_INSTANCE</td>
25670 <td>Instance opened (xo_open_instance)</td>
25671 </tr>
25672 <tr>
25673 <td>XO_OP_CLOSE_INSTANCE</td>
25674 <td>Instance closed (xo_close_instance)</td>
25675 </tr>
25676 <tr>
25677 <td>XO_OP_STRING</td>
25678 <td>Field with Quoted UTF-8 string</td>
25679 </tr>
25680 <tr>
25681 <td>XO_OP_CONTENT</td>
25682 <td>Field with content</td>
25683 </tr>
25684 <tr>
25685 <td>XO_OP_FINISH</td>
25686 <td>Finish any pending output</td>
25687 </tr>
25688 <tr>
25689 <td>XO_OP_FLUSH</td>
25690 <td>Flush any buffered output</td>
25691 </tr>
25692 <tr>
25693 <td>XO_OP_DESTROY</td>
25694 <td>Clean up resources</td>
25695 </tr>
25696 <tr>
25697 <td>XO_OP_ATTRIBUTE</td>
25698 <td>An attribute name/value pair</td>
25699 </tr>
25700 <tr>
25701 <td>XO_OP_VERSION</td>
25702 <td>A version string</td>
25703 </tr>
25704 </tbody>
25705 </table></div>
25706 <p id="doc_section_5_6_3_p_2">For all the open and close operations, the name parameter holds the name of the construct. For string, content, and attribute operations, the name parameter is the name of the field and the value parameter is the value. "string" are differentiated from "content" to allow differing treatment of true, false, null, and numbers from real strings, though content values are formatted as strings before the handler is called. For version operations, the value parameter contains the version.</p>
25707 <p id="doc_section_5_6_3_p_3">All strings are encoded in UTF-8.</p>
25708 </div>
25709 </div>
25710 </div>
25711 <hr class="noprint">
25712 <div class="content">
25713 <h1 id="doc_section_6" class="np">
25714 <div class="self-section-number">
25715 <a href="#doc_section_6">6_</a> </div>
25716 <a id="the-xo-utility" href="#the-xo-utility">The "xo" Utility</a>
25717 </h1>
25718 <p id="doc_section_6_p_1">The "xo" utility allows command line access to the functionality of the libxo library. Using "xo", shell scripts can emit XML, JSON, and HTML using the same commands that emit text output.</p>
25719 <p id="doc_section_6_p_2">The style of output can be selected using a specific option: "&#8209;X" for XML, "&#8209;J" for JSON, "&#8209;H" for HTML, or "&#8209;T" for TEXT, which is the default. The "--style &lt;style&gt;" option can also be used. The standard set of "&#8209;&#8209;libxo" options are available (see <a href="#options" title="Command-line Arguments">Section 4</a>), as well as the LIBXO_OPTIONS environment variable (see <a href="#LIBXO_OPTIONS" title="LIBXO_OPTIONS">Section 5.4.6</a>).</p>
25720 <p id="doc_section_6_p_3">The "xo" utility accepts a format string suitable for xo_emit() and a set of zero or more arguments used to supply data for that string.</p>
25721 <div id="doc_figure_u.138"></div> <pre>
25722     xo "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
25723
25724   TEXT:
25725     The fish weighs 6 pounds.
25726   XML:
25727     &lt;name&gt;fish&lt;/name&gt;
25728     &lt;weight&gt;6&lt;/weight&gt;
25729   JSON:
25730     "name": "fish",
25731     "weight": 6
25732   HTML:
25733     &lt;div class="line"&gt;
25734       &lt;div class="text"&gt;The &lt;/div&gt;
25735       &lt;div class="data" data-tag="name"&gt;fish&lt;/div&gt;
25736       &lt;div class="text"&gt; weighs &lt;/div&gt;
25737       &lt;div class="data" data-tag="weight"&gt;6&lt;/div&gt;
25738       &lt;div class="text"&gt; pounds.&lt;/div&gt;
25739     &lt;/div&gt;
25740             </pre> <p id="doc_section_6_p_5">The "--wrap &lt;path&gt;" option can be used to wrap emitted content in a specific hierarchy. The path is a set of hierarchical names separated by the '/' character.</p>
25741 <div id="doc_figure_u.139"></div> <pre>
25742     xo --wrap top/a/b/c '{:tag}' value
25743
25744   XML:
25745     &lt;top&gt;
25746       &lt;a&gt;
25747         &lt;b&gt;
25748           &lt;c&gt;
25749             &lt;tag&gt;value&lt;/tag&gt;
25750           &lt;/c&gt;
25751         &lt;/b&gt;
25752       &lt;/a&gt;
25753     &lt;/top&gt;
25754   JSON:
25755     "top": {
25756       "a": {
25757         "b": {
25758           "c": {
25759             "tag": "value"
25760           }
25761         }
25762       }
25763     }
25764             </pre> <p id="doc_section_6_p_7">The "--open &lt;path&gt;" and "--close &lt;path&gt;" can be used to emit hierarchical information without the matching close and open tag. This allows a shell script to emit open tags, data, and then close tags. The "&#8209;&#8209;depth" option may be used to set the depth for indentation. The "&#8209;&#8209;leading&#8209;xpath" may be used to prepend data to the XPath values used for HTML output style.</p>
25765 <div id="doc_figure_u.140"></div> <pre>
25766     #!/bin/sh
25767     xo --open top/data
25768     xo --depth 2 '{tag}' value
25769     xo --close top/data
25770   XML:
25771     &lt;top&gt;
25772       &lt;data&gt;
25773         &lt;tag&gt;value&lt;/tag&gt;
25774       &lt;/data&gt;
25775     &lt;/top&gt;
25776   JSON:
25777     "top": {
25778       "data": {
25779         "tag": "value"
25780       }
25781     }
25782             </pre> <p id="doc_section_6_p_9">Section Contents: </p>
25783 <ul>
25784 <li><a href="#command-line-options" title="Command Line Options">Section 6.1</a></li>
25785 <li><a href="#example-2" title="Example">Section 6.2</a></li>
25786 </ul>
25787 <div class="content">
25788 <h2 id="doc_section_6_1">
25789 <div class="self-section-number">
25790 <a href="#doc_section_6_1">6.1</a> </div>
25791 <a id="command-line-options" href="#command-line-options">Command Line Options</a>
25792 </h2>
25793 <p id="doc_section_6_1_p_1">Usage: xo [options] format [fields]</p>
25794 <div id="doc_figure_u.141"></div> <pre>
25795   --close &lt;path&gt;        Close tags for the given path
25796   --depth &lt;num&gt;         Set the depth for pretty printing
25797   --help                Display this help text
25798   --html OR -H          Generate HTML output
25799   --json OR -J          Generate JSON output
25800   --leading-xpath &lt;path&gt; Add a prefix to generated XPaths (HTML)
25801   --open &lt;path&gt;         Open tags for the given path
25802   --pretty OR -p        Make 'pretty' output (add indent, newlines)
25803   --style &lt;style&gt;       Generate given style (xml, json, text, html)
25804   --text OR -T          Generate text output (the default style)
25805   --version             Display version information
25806   --warn OR -W          Display warnings in text on stderr
25807   --warn-xml            Display warnings in xml on stdout
25808   --wrap &lt;path&gt;         Wrap output in a set of containers
25809   --xml OR -X           Generate XML output
25810   --xpath               Add XPath data to HTML output);
25811             </pre> </div>
25812 <div class="content">
25813 <h2 id="doc_section_6_2">
25814 <div class="self-section-number">
25815 <a href="#doc_section_6_2">6.2</a> </div>
25816 <a id="example-2" href="#example-2">Example</a>
25817 </h2>
25818 <div id="doc_figure_u.142"></div> <pre>
25819   % xo 'The {:product} is {:status}\n' stereo "in route"
25820   The stereo is in route
25821   % ./xo/xo -p -X 'The {:product} is {:status}\n' stereo "in route"
25822   &lt;product&gt;stereo&lt;/product&gt;
25823   &lt;status&gt;in route&lt;/status&gt;
25824             </pre> </div>
25825 </div>
25826 <hr class="noprint">
25827 <div class="content">
25828 <h1 id="doc_section_7" class="np">
25829 <div class="self-section-number">
25830 <a href="#doc_section_7">7_</a> </div>
25831 <a id="xolint" href="#xolint">xolint</a>
25832 </h1>
25833 <p id="doc_section_7_p_1">xolint is a tool for reporting common mistakes in format strings in source code that invokes xo_emit(). It allows these errors to be diagnosed at build time, rather than waiting until runtime.</p>
25834 <p id="doc_section_7_p_2">xolint takes the one or more C files as arguments, and reports and errors, warning, or informational messages as needed.</p>
25835 <div id="doc_table_u.20"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25836 <thead><tr>
25837 <th class="left">Option</th>
25838 <th class="left">Meaning</th>
25839 </tr></thead>
25840 <tbody>
25841 <tr>
25842 <td>-c</td>
25843 <td>Invoke 'cpp' against the input file</td>
25844 </tr>
25845 <tr>
25846 <td>-C &lt;flags&gt;</td>
25847 <td>Flags that are passed to 'cpp</td>
25848 </tr>
25849 <tr>
25850 <td>-d</td>
25851 <td>Enable debug output</td>
25852 </tr>
25853 <tr>
25854 <td>-D</td>
25855 <td>Generate documentation for all xolint messages</td>
25856 </tr>
25857 <tr>
25858 <td>-I</td>
25859 <td>Generate info table code</td>
25860 </tr>
25861 <tr>
25862 <td>-p</td>
25863 <td>Print the offending lines after the message</td>
25864 </tr>
25865 <tr>
25866 <td>-V</td>
25867 <td>Print vocabulary of all field names</td>
25868 </tr>
25869 <tr>
25870 <td>-X</td>
25871 <td>Extract samples from xolint, suitable for testing</td>
25872 </tr>
25873 </tbody>
25874 </table></div>
25875 <p id="doc_section_7_p_3">The output message will contain the source filename and line number, the class of the message, the message, and, if -p is given, the line that contains the error:</p>
25876 <div id="doc_figure_u.143"></div> <pre>
25877     % xolint.pl -t xolint.c
25878     xolint.c: 16: error: anchor format should be "%d"
25879     16         xo_emit("{[:/%s}");
25880             </pre> <p id="doc_section_7_p_5">The "&#8209;I" option will generate a table of xo_info_t structures ,</p>
25881 <p id="doc_section_7_p_6">The "&#8209;V" option does not report errors, but prints a complete list of all field names, sorted alphabetically. The output can help spot inconsistencies and spelling errors.</p>
25882 </div>
25883 <hr class="noprint">
25884 <div class="content">
25885 <h1 id="doc_section_8" class="np">
25886 <div class="self-section-number">
25887 <a href="#doc_section_8">8_</a> </div>
25888 <a id="xohtml" href="#xohtml">xohtml</a>
25889 </h1>
25890 <p id="doc_section_8_p_1">xohtml is a tool for turning the output of libxo-enabled commands into html files suitable for display in modern HTML web browsers. It can be used to test and debug HTML output, as well as to make the user ache to escape the world of 70s terminal devices.</p>
25891 <p id="doc_section_8_p_2">xohtml is given a command, either on the command line or via the "&#8209;c" option. If not command is given, standard input is used. The command's output is wrapped in HTML tags, with references to supporting CSS and Javascript files, and written to standard output or the file given in the "&#8209;f" option. The "&#8209;b" option can be used to provide an alternative base path for the support files.</p>
25892 <div id="doc_table_u.21"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25893 <thead><tr>
25894 <th class="left">Option</th>
25895 <th class="left">Meaning</th>
25896 </tr></thead>
25897 <tbody>
25898 <tr>
25899 <td>-b &lt;base&gt;</td>
25900 <td>Base path for finding css/javascript files</td>
25901 </tr>
25902 <tr>
25903 <td>-c &lt;command&gt;</td>
25904 <td>Command to execute</td>
25905 </tr>
25906 <tr>
25907 <td>-f &lt;file&gt;</td>
25908 <td>Output file name</td>
25909 </tr>
25910 </tbody>
25911 </table></div>
25912 <p id="doc_section_8_p_3">The "&#8209;c" option takes a full command with arguments, including any libxo options needed to generate html ("&#8209;&#8209;libxo=html"). This value must be quoted if it consists of multiple tokens.</p>
25913 </div>
25914 <hr class="noprint">
25915 <div class="content">
25916 <h1 id="doc_section_9" class="np">
25917 <div class="self-section-number">
25918 <a href="#doc_section_9">9_</a> </div>
25919 <a id="xopo" href="#xopo">xopo</a>
25920 </h1>
25921 <p id="doc_section_9_p_1">The "xopo" utility filters ".pot" files generated by the "xgettext" utility to remove formatting information suitable for use with the "{G:}" modifier. This means that when the developer changes the formatting portion of the field definitions, or the fields modifiers, the string passed to gettext(3) is unchanged, avoiding the expense of updating any existing translation files (".po" files).</p>
25922 <p id="doc_section_9_p_2">The syntax for the xopo command is one of two forms; it can be used as a filter for processing a .po or .pot file, rewriting the "msgid" strings with a simplified message string. In this mode, the input is either standard input or a file given by the "&#8209;f" option, and the output is either standard output or a file given by the "&#8209;o" option.</p>
25923 <p id="doc_section_9_p_3">In the second mode, a simple message given using the "&#8209;s" option on the command, and the simplified version of that message is printed on stdout.</p>
25924 <div id="doc_table_u.22"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25925 <thead><tr>
25926 <th class="left">Option</th>
25927 <th class="left">Meaning</th>
25928 </tr></thead>
25929 <tbody>
25930 <tr>
25931 <td>-o &lt;file&gt;</td>
25932 <td>Output file name</td>
25933 </tr>
25934 <tr>
25935 <td>-f &lt;file&gt;</td>
25936 <td>Use the given .po file as input</td>
25937 </tr>
25938 <tr>
25939 <td>-s &lt;text&gt;</td>
25940 <td>Simplify a format string</td>
25941 </tr>
25942 </tbody>
25943 </table></div>
25944 <div id="doc_figure_u.144"></div> <pre>
25945     EXAMPLE:
25946         % xopo -s "There are {:count/%u} {:event/%.6s} events\n"
25947         There are {:count} {:event} events\n
25948
25949         % xgettext --default-domain=foo --no-wrap \
25950             --add-comments --keyword=xo_emit --keyword=xo_emit_h \
25951             --keyword=xo_emit_warn -C -E -n --foreign-user \
25952             -o foo.pot.raw foo.c
25953         % xopo -f foo.pot.raw -o foo.pot
25954             </pre> <p id="doc_section_9_p_5">Use of the "&#8209;&#8209;no&#8209;wrap" option for xgettext is required to ensure that incoming msgid strings are not wrapped across multiple lines.</p>
25955 </div>
25956 <hr class="noprint">
25957 <div class="content">
25958 <h1 id="doc_section_10" class="np">
25959 <div class="self-section-number">
25960 <a href="#doc_section_10">10_</a> </div>
25961 <a id="faqs" href="#faqs">FAQs</a>
25962 </h1>
25963 <p id="doc_section_10_p_1">This section contains the set of questions that users typically ask, along with answers that might be helpful.</p>
25964 <p id="doc_section_10_p_2">Section Contents: </p>
25965 <ul>
25966 <li><a href="#general" title="General">Section 10.1</a></li>
25967 <li><a href="#what-does-this-message-mean" title="What does this message mean?">Section 10.2</a></li>
25968 </ul>
25969 <p id="doc_section_10_p_3">Section Contents: </p>
25970 <ul>
25971 <li><a href="#general" title="General">Section 10.1</a></li>
25972 <li><a href="#what-does-this-message-mean" title="What does this message mean?">Section 10.2</a></li>
25973 </ul>
25974 <div class="content">
25975 <h2 id="doc_section_10_1">
25976 <div class="self-section-number">
25977 <a href="#doc_section_10_1">10.1</a> </div>
25978 <a id="general" href="#general">General</a>
25979 </h2>
25980 <p id="doc_section_10_1_p_1">Section Contents: </p>
25981 <ul>
25982 <li><a href="#can-you-share-the-history-of-libxo" title="Can you share the history of libxo?">Section 10.1.1</a></li>
25983 <li><a href="#did-the-complex-semantics-of-format-strings-evolve-over-time" title="Did the complex semantics of format strings evolve over time?">Section 10.1.2</a></li>
25984 <li><a href="#good-field-names" title="What makes a good field name?">Section 10.1.3</a></li>
25985 </ul>
25986 <div class="content">
25987 <h3 id="doc_section_10_1_1">
25988 <div class="self-section-number">
25989 <a href="#doc_section_10_1_1">10.1.1</a> </div>
25990 <a id="can-you-share-the-history-of-libxo" href="#can-you-share-the-history-of-libxo">Can you share the history of libxo?</a>
25991 </h3>
25992 <p id="doc_section_10_1_1_p_1">In 2001, we added an XML API to the JUNOS operating system, which is built on top of FreeBSD. Eventually this API became standardized as the NETCONF API (RFC 6241). As part of this effort, we modified many FreeBSD utilities to emit XML, typically via a "&#8209;X" switch. The results were mixed. The cost of maintaining this code, updating it, and carrying it were non-trivial, and contributed to our expense (and the associated delay) with upgrading the version of FreeBSD on which each release of JUNOS is based.</p>
25993 <p id="doc_section_10_1_1_p_2">A recent (2014) effort within JUNOS aims at removing our modifications to the underlying FreeBSD code as a means of reducing the expense and delay in tracking HEAD. JUNOS is structured to have system components generate XML that is rendered by the CLI (think: login shell) into human-readable text. This allows the API to use the same plumbing as the CLI, and ensures that all components emit XML, and that it is emitted with knowledge of the consumer of that XML, yielding an API that have no incremental cost or feature delay.</p>
25994 <p id="doc_section_10_1_1_p_3">libxo is an effort to mix the best aspects of the JUNOS strategy into FreeBSD in a seemless way, allowing commands to make printf-like output calls with a single code path.</p>
25995 </div>
25996 <div class="content">
25997 <h3 id="doc_section_10_1_2">
25998 <div class="self-section-number">
25999 <a href="#doc_section_10_1_2">10.1.2</a> </div>
26000 <a id="did-the-complex-semantics-of-format-strings-evolve-over-time" href="#did-the-complex-semantics-of-format-strings-evolve-over-time">Did the complex semantics of format strings evolve over time?</a>
26001 </h3>
26002 <p id="doc_section_10_1_2_p_1">The history is both long and short: libxo's functionality is based on what JUNOS does in a data modeling language called ODL (output definition language). In JUNOS, all subcomponents generate XML, which is feed to the CLI, where data from the ODL files tell is how to render that XML into text. ODL might had a set of tags like:</p>
26003 <div id="doc_figure_u.145"></div> <pre>
26004      tag docsis-state {
26005          help "State of the DOCSIS interface";
26006          type string;
26007      }
26008
26009      tag docsis-mode {
26010          help "DOCSIS mode (2.0/3.0) of the DOCSIS interface";
26011          type string;
26012      }
26013
26014      tag docsis-upstream-speed {
26015          help "Operational upstream speed of the interface";
26016          type string;
26017      }
26018
26019      tag downstream-scanning {
26020          help "Result of scanning in downstream direction";
26021          type string;
26022      }
26023
26024      tag ranging {
26025          help "Result of ranging action";
26026          type string;
26027      }
26028
26029      tag signal-to-noise-ratio {
26030          help "Signal to noise ratio for all channels";
26031          type string;
26032      }
26033
26034      tag power {
26035          help "Operational power of the signal on all channels";
26036          type string;
26037      }
26038
26039      format docsis-status-format {
26040          picture "
26041    State   : @, Mode: @, Upstream speed: @
26042    Downstream scanning: @, Ranging: @
26043    Signal to noise ratio: @
26044    Power: @
26045 ";
26046          line {
26047              field docsis-state;
26048              field docsis-mode;
26049              field docsis-upstream-speed;
26050              field downstream-scanning;
26051              field ranging;
26052              field signal-to-noise-ratio;
26053              field power;
26054          }
26055      }
26056             </pre> <p id="doc_section_10_1_2_p_3">These tag definitions are compiled into field definitions that are triggered when matching XML elements are seen. ODL also supports other means of defining output.</p>
26057 <p id="doc_section_10_1_2_p_4">The roles and modifiers describe these details.</p>
26058 <p id="doc_section_10_1_2_p_5">In moving these ideas to bsd, two things had to happen: the formatting had to happen at the source since BSD won't have a JUNOS-like CLI to do the rendering, and we can't depend on external data models like ODL, which was seen as too hard a sell to the BSD community.</p>
26059 <p id="doc_section_10_1_2_p_6">The results were that the xo_emit strings are used to encode the roles, modifiers, names, and formats. They are dense and a bit cryptic, but not so unlike printf format strings that developers will be lost.</p>
26060 <p id="doc_section_10_1_2_p_7">libxo is a new implementation of these ideas and is distinct from the previous implementation in JUNOS.</p>
26061 </div>
26062 <div class="content">
26063 <h3 id="doc_section_10_1_3">
26064 <div class="self-section-number">
26065 <a href="#doc_section_10_1_3">10.1.3</a> </div>
26066 <a id="good-field-names" href="#good-field-names">What makes a good field name?</a>
26067 </h3>
26068 <p id="doc_section_10_1_3_p_1">To make useful, consistent field names, follow these guidelines:</p>
26069 <p id="doc_section_10_1_3_p_2"> </p>
26070 <dl>
26071 <dt>Use lower case, even for TLAs</dt>
26072 <dd>Lower case is more civilized. Even TLAs should be lower case to avoid scenarios where the differences between "XPath" and "Xpath" drive your users crazy. Using "xpath" is simpler and better.</dd>
26073 <dt>Use hyphens, not underscores</dt>
26074 <dd>Use of hyphens is traditional in XML, and the XOF_UNDERSCORES flag can be used to generate underscores in JSON, if desired. But the raw field name should use hyphens.</dd>
26075 <dt>Use full words</dt>
26076 <dd>Don't abbreviate especially when the abbreviation is not obvious or not widely used. Use "data&#8209;size", not "dsz" or "dsize". Use "interface" instead of "ifname", "if&#8209;name", "iface", "if", or "intf".</dd>
26077 <dt>Use &lt;verb&gt;-&lt;units&gt;</dt>
26078 <dd>Using the form &lt;verb&gt;-&lt;units&gt; or &lt;verb&gt;-&lt;classifier&gt;-&lt;units&gt; helps in making consistent, useful names, avoiding the situation where one app uses "sent&#8209;packet" and another "packets&#8209;sent" and another "packets&#8209;we&#8209;have&#8209;sent". The &lt;units&gt; can be dropped when it is obvious, as can obvious words in the classification. Use "receive&#8209;after&#8209;window&#8209;packets" instead of "received&#8209;packets&#8209;of&#8209;data&#8209;after&#8209;window".</dd>
26079 <dt>Reuse existing field names</dt>
26080 <dd>Nothing's worse than writing expressions like:</dd>
26081 </dl>
26082 <div id="doc_figure_u.146"></div> <pre>
26083     if ($src1/process[pid == $pid]/name == 
26084         $src2/proc-table/proc-list
26085                    /proc-entry[process-id == $pid]/proc-name) {
26086         ...
26087     }
26088             </pre> <p id="doc_section_10_1_3_p_4">Find someone else who is expressing similar data and follow their fields and hierarchy. Remember the quote is not "Consistency is the hobgoblin of little minds", but "A foolish consistency is the hobgoblin of little minds".</p>
26089 <p id="doc_section_10_1_3_p_5"> </p>
26090 <dl>
26091 <dt>Use containment as scoping</dt>
26092 <dd>In the previous example, all the names are prefixed with "proc&#8209;", which is redundant given that they are nested under the process table.</dd>
26093 <dt>Think about your users</dt>
26094 <dd>Have empathy for your users, choosing clear and useful fields that contain clear and useful data. You may need to augment the display content with xo_attr() calls (<a href="#xo_attr" title="Attributes (xo_attr)">Section 5.2.2</a>) or "{e:}" fields (<a href="#e-modifier" title="The Encoding Modifier ({e:})">Section 3.2.2.4</a>) to make the data useful.</dd>
26095 <dt>Don't use an arbitrary number postfix</dt>
26096 <dd>What does "errors2" mean? No one will know. "errors&#8209;after&#8209;restart" would be a better choice. Think of your users, and think of the future. If you make "errors2", the next guy will happily make "errors3" and before you know it, someone will be asking what's the difference between errors37 and errors63.</dd>
26097 <dt>Be consistent, uniform, unsurprising, and predictable</dt>
26098 <dd>Think of your field vocabulary as an API. You want it useful, expressive, meaningful, direct, and obvious. You want the client application's programmer to move between without the need to understand a variety of opinions on how fields are named. They should see the system as a single cohesive whole, not a sack of cats.</dd>
26099 </dl>
26100 <p id="doc_section_10_1_3_p_6">Field names constitute the means by which client programmers interact with our system. By choosing wise names now, you are making their lives better.</p>
26101 <p id="doc_section_10_1_3_p_7">After using "xolint" to find errors in your field descriptors, use "xolint -V" to spell check your field names and to detect different names for the same data. "dropped&#8209;short" and "dropped&#8209;too&#8209;short" are both reasonable names, but using them both will lead users to ask the difference between the two fields. If there is no difference, use only one of the field names. If there is a difference, change the names to make that difference more obvious.</p>
26102 </div>
26103 </div>
26104 <div class="content">
26105 <h2 id="doc_section_10_2">
26106 <div class="self-section-number">
26107 <a href="#doc_section_10_2">10.2</a> </div>
26108 <a id="what-does-this-message-mean" href="#what-does-this-message-mean">What does this message mean?</a>
26109 </h2>
26110 <p id="doc_section_10_2_p_1">Section Contents: </p>
26111 <ul>
26112 <li><a href="#a-percent-sign-appearing-in-text-is-a-literal" title="'A percent sign appearing in text is a literal'">Section 10.2.1</a></li>
26113 <li><a href="#unknown-long-name-for-rolemodifier" title="'Unknown long name for role/modifier'">Section 10.2.2</a></li>
26114 <li><a href="#last-character-before-field-definition-is-a-field-type" title="'Last character before field definition is a field type'">Section 10.2.3</a></li>
26115 <li><a href="#encoding-format-uses-different-number-of-arguments" title="'Encoding format uses different number of arguments'">Section 10.2.4</a></li>
26116 <li><a href="#only-one-field-role-can-be-used" title="'Only one field role can be used'">Section 10.2.5</a></li>
26117 <li><a href="#potential-missing-slash-after-c-d-n-l-or-t-with-format" title="'Potential missing slash after C, D, N, L, or T with format'">Section 10.2.6</a></li>
26118 <li><a href="#an-encoding-format-cannot-be-given-roles-dnlt" title="'An encoding format cannot be given (roles: DNLT)'">Section 10.2.7</a></li>
26119 <li><a href="#format-cannot-be-given-when-content-is-present-roles-cdln" title="'Format cannot be given when content is present (roles: CDLN)'">Section 10.2.8</a></li>
26120 <li><a href="#field-has-color-without-fg--or-bg--role-c" title="'Field has color without fg- or bg- (role: C)'">Section 10.2.9</a></li>
26121 <li><a href="#field-has-invalid-color-or-effect-role-c" title="'Field has invalid color or effect (role: C)'">Section 10.2.10</a></li>
26122 <li><a href="#field-has-humanize-modifier-but-no-format-string" title="'Field has humanize modifier but no format string'">Section 10.2.11</a></li>
26123 <li><a href="#field-has-hn--modifier-but-not-h-modifier" title="'Field has hn-* modifier but not 'h' modifier'">Section 10.2.12</a></li>
26124 <li><a href="#value-field-must-have-a-name-as-content" title="'Value field must have a name (as content)&quot;)'">Section 10.2.13</a></li>
26125 <li><a href="#use-hyphens-not-underscores-for-value-field-name" title="'Use hyphens, not underscores, for value field name'">Section 10.2.14</a></li>
26126 <li><a href="#value-field-name-cannot-start-with-digit" title="'Value field name cannot start with digit'">Section 10.2.15</a></li>
26127 <li><a href="#value-field-name-should-be-lower-case" title="'Value field name should be lower case'">Section 10.2.16</a></li>
26128 <li><a href="#value-field-name-should-be-longer-than-two-characters" title="'Value field name should be longer than two characters'">Section 10.2.17</a></li>
26129 <li><a href="#value-field-name-contains-invalid-character" title="'Value field name contains invalid character'">Section 10.2.18</a></li>
26130 <li><a href="#decoration-field-contains-invalid-character" title="'decoration field contains invalid character'">Section 10.2.19</a></li>
26131 <li><a href="#anchor-content-should-be-decimal-width" title="'Anchor content should be decimal width'">Section 10.2.20</a></li>
26132 <li><a href="#anchor-format-should-be-d" title="'Anchor format should be &quot;%d&quot;'">Section 10.2.21</a></li>
26133 <li><a href="#anchor-cannot-have-both-format-and-encoding-format" title="'Anchor cannot have both format and encoding format&quot;)'">Section 10.2.22</a></li>
26134 <li><a href="#max-width-only-valid-for-strings" title="'Max width only valid for strings'">Section 10.2.23</a></li>
26135 </ul>
26136 <div class="content">
26137 <h3 id="doc_section_10_2_1">
26138 <div class="self-section-number">
26139 <a href="#doc_section_10_2_1">10.2.1</a> </div>
26140 <a id="a-percent-sign-appearing-in-text-is-a-literal" href="#a-percent-sign-appearing-in-text-is-a-literal">'A percent sign appearing in text is a literal'</a>
26141 </h3>
26142 <p id="doc_section_10_2_1_p_1">The message "A percent sign appearing in text is a literal" can be caused by code like:</p>
26143 <div id="doc_figure_u.147"></div> <pre>
26144     xo_emit("cost: %d", cost);
26145             </pre> <p id="doc_section_10_2_1_p_3">This code should be replaced with code like:</p>
26146 <div id="doc_figure_u.148"></div> <pre>
26147     xo_emit("{L:cost}: {:cost/%d}", cost);
26148             </pre> <p id="doc_section_10_2_1_p_5">This can be a bit surprising and could be a field that was not properly converted to a libxo-style format string.</p>
26149 </div>
26150 <div class="content">
26151 <h3 id="doc_section_10_2_2">
26152 <div class="self-section-number">
26153 <a href="#doc_section_10_2_2">10.2.2</a> </div>
26154 <a id="unknown-long-name-for-rolemodifier" href="#unknown-long-name-for-rolemodifier">'Unknown long name for role/modifier'</a>
26155 </h3>
26156 <p id="doc_section_10_2_2_p_1">The message "Unknown long name for role/modifier" can be caused by code like:</p>
26157 <div id="doc_figure_u.149"></div> <pre>
26158     xo_emit("{,humanization:value}", value);
26159             </pre> <p id="doc_section_10_2_2_p_3">This code should be replaced with code like:</p>
26160 <div id="doc_figure_u.150"></div> <pre>
26161     xo_emit("{,humanize:value}", value);
26162             </pre> <p id="doc_section_10_2_2_p_5">The hn-* modifiers (hn-decimal, hn-space, hn-1000) are only valid for fields with the {h:} modifier.</p>
26163 </div>
26164 <div class="content">
26165 <h3 id="doc_section_10_2_3">
26166 <div class="self-section-number">
26167 <a href="#doc_section_10_2_3">10.2.3</a> </div>
26168 <a id="last-character-before-field-definition-is-a-field-type" href="#last-character-before-field-definition-is-a-field-type">'Last character before field definition is a field type'</a>
26169 </h3>
26170 <p id="doc_section_10_2_3_p_1">The message "Last character before field definition is a field type" can be caused by code like:</p>
26171 <p id="doc_section_10_2_3_p_2">A common typo:</p>
26172 <div id="doc_figure_u.151"></div> <pre>
26173     xo_emit("{T:Min} T{:Max}");
26174             </pre> <p id="doc_section_10_2_3_p_4">This code should be replaced with code like:</p>
26175 <div id="doc_figure_u.152"></div> <pre>
26176     xo_emit("{T:Min} {T:Max}");
26177             </pre> <p id="doc_section_10_2_3_p_6">Twiddling the "{" and the field role is a common typo.</p>
26178 </div>
26179 <div class="content">
26180 <h3 id="doc_section_10_2_4">
26181 <div class="self-section-number">
26182 <a href="#doc_section_10_2_4">10.2.4</a> </div>
26183 <a id="encoding-format-uses-different-number-of-arguments" href="#encoding-format-uses-different-number-of-arguments">'Encoding format uses different number of arguments'</a>
26184 </h3>
26185 <p id="doc_section_10_2_4_p_1">The message "Encoding format uses different number of arguments" can be caused by code like:</p>
26186 <div id="doc_figure_u.153"></div> <pre>
26187     xo_emit("{:name/%6.6s %%04d/%s}", name, number);
26188             </pre> <p id="doc_section_10_2_4_p_3">This code should be replaced with code like:</p>
26189 <div id="doc_figure_u.154"></div> <pre>
26190     xo_emit("{:name/%6.6s %04d/%s-%d}", name, number);
26191             </pre> <p id="doc_section_10_2_4_p_5">Both format should consume the same number of arguments off the stack</p>
26192 </div>
26193 <div class="content">
26194 <h3 id="doc_section_10_2_5">
26195 <div class="self-section-number">
26196 <a href="#doc_section_10_2_5">10.2.5</a> </div>
26197 <a id="only-one-field-role-can-be-used" href="#only-one-field-role-can-be-used">'Only one field role can be used'</a>
26198 </h3>
26199 <p id="doc_section_10_2_5_p_1">The message "Only one field role can be used" can be caused by code like:</p>
26200 <div id="doc_figure_u.155"></div> <pre>
26201     xo_emit("{LT:Max}");
26202             </pre> <p id="doc_section_10_2_5_p_3">This code should be replaced with code like:</p>
26203 <div id="doc_figure_u.156"></div> <pre>
26204     xo_emit("{T:Max}");
26205             </pre> </div>
26206 <div class="content">
26207 <h3 id="doc_section_10_2_6">
26208 <div class="self-section-number">
26209 <a href="#doc_section_10_2_6">10.2.6</a> </div>
26210 <a id="potential-missing-slash-after-c-d-n-l-or-t-with-format" href="#potential-missing-slash-after-c-d-n-l-or-t-with-format">'Potential missing slash after C, D, N, L, or T with format'</a>
26211 </h3>
26212 <p id="doc_section_10_2_6_p_1">The message "Potential missing slash after C, D, N, L, or T with format" can be caused by code like:</p>
26213 <div id="doc_figure_u.157"></div> <pre>
26214     xo_emit("{T:%6.6s}\n", "Max");
26215             </pre> <p id="doc_section_10_2_6_p_3">This code should be replaced with code like:</p>
26216 <div id="doc_figure_u.158"></div> <pre>
26217     xo_emit("{T:/%6.6s}\n", "Max");
26218             </pre> <p id="doc_section_10_2_6_p_5">The "%6.6s" will be a literal, not a field format. While it's possibly valid, it's likely a missing "/".</p>
26219 </div>
26220 <div class="content">
26221 <h3 id="doc_section_10_2_7">
26222 <div class="self-section-number">
26223 <a href="#doc_section_10_2_7">10.2.7</a> </div>
26224 <a id="an-encoding-format-cannot-be-given-roles-dnlt" href="#an-encoding-format-cannot-be-given-roles-dnlt">'An encoding format cannot be given (roles: DNLT)'</a>
26225 </h3>
26226 <p id="doc_section_10_2_7_p_1">The message "An encoding format cannot be given (roles: DNLT)" can be caused by code like:</p>
26227 <div id="doc_figure_u.159"></div> <pre>
26228     xo_emit("{T:Max//%s}", "Max");
26229             </pre> <p id="doc_section_10_2_7_p_3">Fields with the C, D, N, L, and T roles are not emitted in the 'encoding' style (JSON, XML), so an encoding format would make no sense.</p>
26230 </div>
26231 <div class="content">
26232 <h3 id="doc_section_10_2_8">
26233 <div class="self-section-number">
26234 <a href="#doc_section_10_2_8">10.2.8</a> </div>
26235 <a id="format-cannot-be-given-when-content-is-present-roles-cdln" href="#format-cannot-be-given-when-content-is-present-roles-cdln">'Format cannot be given when content is present (roles: CDLN)'</a>
26236 </h3>
26237 <p id="doc_section_10_2_8_p_1">The message "Format cannot be given when content is present (roles: CDLN)" can be caused by code like:</p>
26238 <div id="doc_figure_u.160"></div> <pre>
26239     xo_emit("{N:Max/%6.6s}", "Max");
26240             </pre> <p id="doc_section_10_2_8_p_3">Fields with the C, D, L, or N roles can't have both static literal content ("{L:Label}") and a format ("{L:/%s}"). This error will also occur when the content has a backslash in it, like "{N:Type of I/O}"; backslashes should be escaped, like "{N:Type of I\\/O}". Note the double backslash, one for handling 'C' strings, and one for libxo.</p>
26241 </div>
26242 <div class="content">
26243 <h3 id="doc_section_10_2_9">
26244 <div class="self-section-number">
26245 <a href="#doc_section_10_2_9">10.2.9</a> </div>
26246 <a id="field-has-color-without-fg--or-bg--role-c" href="#field-has-color-without-fg--or-bg--role-c">'Field has color without fg- or bg- (role: C)'</a>
26247 </h3>
26248 <p id="doc_section_10_2_9_p_1">The message "Field has color without fg- or bg- (role: C)" can be caused by code like:</p>
26249 <div id="doc_figure_u.161"></div> <pre>
26250     xo_emit("{C:green}{:foo}{C:}", x);
26251             </pre> <p id="doc_section_10_2_9_p_3">This code should be replaced with code like:</p>
26252 <div id="doc_figure_u.162"></div> <pre>
26253     xo_emit("{C:fg-green}{:foo}{C:}", x);
26254             </pre> <p id="doc_section_10_2_9_p_5">Colors must be prefixed by either "fg&#8209;" or "bg&#8209;".</p>
26255 </div>
26256 <div class="content">
26257 <h3 id="doc_section_10_2_10">
26258 <div class="self-section-number">
26259 <a href="#doc_section_10_2_10">10.2.10</a> </div>
26260 <a id="field-has-invalid-color-or-effect-role-c" href="#field-has-invalid-color-or-effect-role-c">'Field has invalid color or effect (role: C)'</a>
26261 </h3>
26262 <p id="doc_section_10_2_10_p_1">The message "Field has invalid color or effect (role: C)" can be caused by code like:</p>
26263 <div id="doc_figure_u.163"></div> <pre>
26264     xo_emit("{C:fg-purple,bold}{:foo}{C:gween}", x);
26265             </pre> <p id="doc_section_10_2_10_p_3">This code should be replaced with code like:</p>
26266 <div id="doc_figure_u.164"></div> <pre>
26267     xo_emit("{C:fg-red,bold}{:foo}{C:fg-green}", x);
26268             </pre> <p id="doc_section_10_2_10_p_5">The list of colors and effects are limited. The set of colors includes default, black, red, green, yellow, blue, magenta, cyan, and white, which must be prefixed by either "fg&#8209;" or "bg&#8209;". Effects are limited to bold, no-bold, underline, no-underline, inverse, no-inverse, normal, and reset. Values must be separated by commas.</p>
26269 </div>
26270 <div class="content">
26271 <h3 id="doc_section_10_2_11">
26272 <div class="self-section-number">
26273 <a href="#doc_section_10_2_11">10.2.11</a> </div>
26274 <a id="field-has-humanize-modifier-but-no-format-string" href="#field-has-humanize-modifier-but-no-format-string">'Field has humanize modifier but no format string'</a>
26275 </h3>
26276 <p id="doc_section_10_2_11_p_1">The message "Field has humanize modifier but no format string" can be caused by code like:</p>
26277 <div id="doc_figure_u.165"></div> <pre>
26278     xo_emit("{h:value}", value);
26279             </pre> <p id="doc_section_10_2_11_p_3">This code should be replaced with code like:</p>
26280 <div id="doc_figure_u.166"></div> <pre>
26281     xo_emit("{h:value/%d}", value);
26282             </pre> <p id="doc_section_10_2_11_p_5">Humanization is only value for numbers, which are not likely to use the default format ("%s").</p>
26283 </div>
26284 <div class="content">
26285 <h3 id="doc_section_10_2_12">
26286 <div class="self-section-number">
26287 <a href="#doc_section_10_2_12">10.2.12</a> </div>
26288 <a id="field-has-hn--modifier-but-not-h-modifier" href="#field-has-hn--modifier-but-not-h-modifier">'Field has hn-* modifier but not 'h' modifier'</a>
26289 </h3>
26290 <p id="doc_section_10_2_12_p_1">The message "Field has hn-* modifier but not 'h' modifier" can be caused by code like:</p>
26291 <div id="doc_figure_u.167"></div> <pre>
26292     xo_emit("{,hn-1000:value}", value);
26293             </pre> <p id="doc_section_10_2_12_p_3">This code should be replaced with code like:</p>
26294 <div id="doc_figure_u.168"></div> <pre>
26295     xo_emit("{h,hn-1000:value}", value);
26296             </pre> <p id="doc_section_10_2_12_p_5">The hn-* modifiers (hn-decimal, hn-space, hn-1000) are only valid for fields with the {h:} modifier.</p>
26297 </div>
26298 <div class="content">
26299 <h3 id="doc_section_10_2_13">
26300 <div class="self-section-number">
26301 <a href="#doc_section_10_2_13">10.2.13</a> </div>
26302 <a id="value-field-must-have-a-name-as-content" href="#value-field-must-have-a-name-as-content">'Value field must have a name (as content)")'</a>
26303 </h3>
26304 <p id="doc_section_10_2_13_p_1">The message "Value field must have a name (as content)")" can be caused by code like:</p>
26305 <div id="doc_figure_u.169"></div> <pre>
26306     xo_emit("{:/%s}", "value");
26307             </pre> <p id="doc_section_10_2_13_p_3">This code should be replaced with code like:</p>
26308 <div id="doc_figure_u.170"></div> <pre>
26309     xo_emit("{:tag-name/%s}", "value");
26310             </pre> <p id="doc_section_10_2_13_p_5">The field name is used for XML and JSON encodings. These tags names are static and must appear directly in the field descriptor.</p>
26311 </div>
26312 <div class="content">
26313 <h3 id="doc_section_10_2_14">
26314 <div class="self-section-number">
26315 <a href="#doc_section_10_2_14">10.2.14</a> </div>
26316 <a id="use-hyphens-not-underscores-for-value-field-name" href="#use-hyphens-not-underscores-for-value-field-name">'Use hyphens, not underscores, for value field name'</a>
26317 </h3>
26318 <p id="doc_section_10_2_14_p_1">The message "Use hyphens, not underscores, for value field name" can be caused by code like:</p>
26319 <div id="doc_figure_u.171"></div> <pre>
26320     xo_emit("{:no_under_scores}", "bad");
26321             </pre> <p id="doc_section_10_2_14_p_3">This code should be replaced with code like:</p>
26322 <div id="doc_figure_u.172"></div> <pre>
26323     xo_emit("{:no-under-scores}", "bad");
26324             </pre> <p id="doc_section_10_2_14_p_5">Use of hyphens is traditional in XML, and the XOF_UNDERSCORES flag can be used to generate underscores in JSON, if desired. But the raw field name should use hyphens.</p>
26325 </div>
26326 <div class="content">
26327 <h3 id="doc_section_10_2_15">
26328 <div class="self-section-number">
26329 <a href="#doc_section_10_2_15">10.2.15</a> </div>
26330 <a id="value-field-name-cannot-start-with-digit" href="#value-field-name-cannot-start-with-digit">'Value field name cannot start with digit'</a>
26331 </h3>
26332 <p id="doc_section_10_2_15_p_1">The message "Value field name cannot start with digit" can be caused by code like:</p>
26333 <div id="doc_figure_u.173"></div> <pre>
26334     xo_emit("{:10-gig/}");
26335             </pre> <p id="doc_section_10_2_15_p_3">This code should be replaced with code like:</p>
26336 <div id="doc_figure_u.174"></div> <pre>
26337     xo_emit("{:ten-gig/}");
26338             </pre> <p id="doc_section_10_2_15_p_5">XML element names cannot start with a digit.</p>
26339 </div>
26340 <div class="content">
26341 <h3 id="doc_section_10_2_16">
26342 <div class="self-section-number">
26343 <a href="#doc_section_10_2_16">10.2.16</a> </div>
26344 <a id="value-field-name-should-be-lower-case" href="#value-field-name-should-be-lower-case">'Value field name should be lower case'</a>
26345 </h3>
26346 <p id="doc_section_10_2_16_p_1">The message "Value field name should be lower case" can be caused by code like:</p>
26347 <div id="doc_figure_u.175"></div> <pre>
26348     xo_emit("{:WHY-ARE-YOU-SHOUTING}", "NO REASON");
26349             </pre> <p id="doc_section_10_2_16_p_3">This code should be replaced with code like:</p>
26350 <div id="doc_figure_u.176"></div> <pre>
26351     xo_emit("{:why-are-you-shouting}", "no reason");
26352             </pre> <p id="doc_section_10_2_16_p_5">Lower case is more civilized. Even TLAs should be lower case to avoid scenarios where the differences between "XPath" and "Xpath" drive your users crazy. Lower case rules the seas.</p>
26353 </div>
26354 <div class="content">
26355 <h3 id="doc_section_10_2_17">
26356 <div class="self-section-number">
26357 <a href="#doc_section_10_2_17">10.2.17</a> </div>
26358 <a id="value-field-name-should-be-longer-than-two-characters" href="#value-field-name-should-be-longer-than-two-characters">'Value field name should be longer than two characters'</a>
26359 </h3>
26360 <p id="doc_section_10_2_17_p_1">The message "Value field name should be longer than two characters" can be caused by code like:</p>
26361 <div id="doc_figure_u.177"></div> <pre>
26362     xo_emit("{:x}", "mumble");
26363             </pre> <p id="doc_section_10_2_17_p_3">This code should be replaced with code like:</p>
26364 <div id="doc_figure_u.178"></div> <pre>
26365     xo_emit("{:something-meaningful}", "mumble");
26366             </pre> <p id="doc_section_10_2_17_p_5">Field names should be descriptive, and it's hard to be descriptive in less than two characters. Consider your users and try to make something more useful. Note that this error often occurs when the field type is placed after the colon ("{:T/%20s}"), instead of before it ("{T:/20s}").</p>
26367 </div>
26368 <div class="content">
26369 <h3 id="doc_section_10_2_18">
26370 <div class="self-section-number">
26371 <a href="#doc_section_10_2_18">10.2.18</a> </div>
26372 <a id="value-field-name-contains-invalid-character" href="#value-field-name-contains-invalid-character">'Value field name contains invalid character'</a>
26373 </h3>
26374 <p id="doc_section_10_2_18_p_1">The message "Value field name contains invalid character" can be caused by code like:</p>
26375 <div id="doc_figure_u.179"></div> <pre>
26376     xo_emit("{:cost-in-$$/%u}", 15);
26377             </pre> <p id="doc_section_10_2_18_p_3">This code should be replaced with code like:</p>
26378 <div id="doc_figure_u.180"></div> <pre>
26379     xo_emit("{:cost-in-dollars/%u}", 15);
26380             </pre> <p id="doc_section_10_2_18_p_5">An invalid character is often a sign of a typo, like "{:]}" instead of "{]:}". Field names are restricted to lower-case characters, digits, and hyphens.</p>
26381 </div>
26382 <div class="content">
26383 <h3 id="doc_section_10_2_19">
26384 <div class="self-section-number">
26385 <a href="#doc_section_10_2_19">10.2.19</a> </div>
26386 <a id="decoration-field-contains-invalid-character" href="#decoration-field-contains-invalid-character">'decoration field contains invalid character'</a>
26387 </h3>
26388 <p id="doc_section_10_2_19_p_1">The message "decoration field contains invalid character" can be caused by code like:</p>
26389 <div id="doc_figure_u.181"></div> <pre>
26390     xo_emit("{D:not good}");
26391             </pre> <p id="doc_section_10_2_19_p_3">This code should be replaced with code like:</p>
26392 <div id="doc_figure_u.182"></div> <pre>
26393     xo_emit("{D:((}{:good}{D:))}", "yes");
26394             </pre> <p id="doc_section_10_2_19_p_5">This is minor, but fields should use proper roles. Decoration fields are meant to hold punctuation and other characters used to decorate the content, typically to make it more readable to human readers.</p>
26395 </div>
26396 <div class="content">
26397 <h3 id="doc_section_10_2_20">
26398 <div class="self-section-number">
26399 <a href="#doc_section_10_2_20">10.2.20</a> </div>
26400 <a id="anchor-content-should-be-decimal-width" href="#anchor-content-should-be-decimal-width">'Anchor content should be decimal width'</a>
26401 </h3>
26402 <p id="doc_section_10_2_20_p_1">The message "Anchor content should be decimal width" can be caused by code like:</p>
26403 <div id="doc_figure_u.183"></div> <pre>
26404     xo_emit("{[:mumble}");
26405             </pre> <p id="doc_section_10_2_20_p_3">This code should be replaced with code like:</p>
26406 <div id="doc_figure_u.184"></div> <pre>
26407     xo_emit("{[:32}");
26408             </pre> <p id="doc_section_10_2_20_p_5">Anchors need an integer value to specify the width of the set of anchored fields. The value can be positive (for left padding/right justification) or negative (for right padding/left justification) and can appear in either the start or stop anchor field descriptor.</p>
26409 </div>
26410 <div class="content">
26411 <h3 id="doc_section_10_2_21">
26412 <div class="self-section-number">
26413 <a href="#doc_section_10_2_21">10.2.21</a> </div>
26414 <a id="anchor-format-should-be-d" href="#anchor-format-should-be-d">'Anchor format should be "%d"'</a>
26415 </h3>
26416 <p id="doc_section_10_2_21_p_1">The message "Anchor format should be "%d"" can be caused by code like:</p>
26417 <div id="doc_figure_u.185"></div> <pre>
26418     xo_emit("{[:/%s}");
26419             </pre> <p id="doc_section_10_2_21_p_3">This code should be replaced with code like:</p>
26420 <div id="doc_figure_u.186"></div> <pre>
26421     xo_emit("{[:/%d}");
26422             </pre> <p id="doc_section_10_2_21_p_5">Anchors only grok integer values, and if the value is not static, if must be in an 'int' argument, represented by the "%d" format. Anything else is an error.</p>
26423 </div>
26424 <div class="content">
26425 <h3 id="doc_section_10_2_22">
26426 <div class="self-section-number">
26427 <a href="#doc_section_10_2_22">10.2.22</a> </div>
26428 <a id="anchor-cannot-have-both-format-and-encoding-format" href="#anchor-cannot-have-both-format-and-encoding-format">'Anchor cannot have both format and encoding format")'</a>
26429 </h3>
26430 <p id="doc_section_10_2_22_p_1">The message "Anchor cannot have both format and encoding format")" can be caused by code like:</p>
26431 <div id="doc_figure_u.187"></div> <pre>
26432     xo_emit("{[:32/%d}");
26433             </pre> <p id="doc_section_10_2_22_p_3">This code should be replaced with code like:</p>
26434 <div id="doc_figure_u.188"></div> <pre>
26435     xo_emit("{[:32}");
26436             </pre> <p id="doc_section_10_2_22_p_5">Anchors can have a static value or argument for the width, but cannot have both.</p>
26437 </div>
26438 <div class="content">
26439 <h3 id="doc_section_10_2_23">
26440 <div class="self-section-number">
26441 <a href="#doc_section_10_2_23">10.2.23</a> </div>
26442 <a id="max-width-only-valid-for-strings" href="#max-width-only-valid-for-strings">'Max width only valid for strings'</a>
26443 </h3>
26444 <p id="doc_section_10_2_23_p_1">The message "Max width only valid for strings" can be caused by code like:</p>
26445 <div id="doc_figure_u.189"></div> <pre>
26446     xo_emit("{:tag/%2.4.6d}", 55);
26447             </pre> <p id="doc_section_10_2_23_p_3">This code should be replaced with code like:</p>
26448 <div id="doc_figure_u.190"></div> <pre>
26449     xo_emit("{:tag/%2.6d}", 55);
26450             </pre> <p id="doc_section_10_2_23_p_5">libxo allows a true 'max width' in addition to the traditional printf-style 'max number of bytes to use for input'. But this is supported only for string values, since it makes no sense for non-strings. This error may occur from a typo, like "{:tag/%6..6d}" where only one period should be used.</p>
26451 </div>
26452 </div>
26453 </div>
26454 <hr class="noprint">
26455 <div class="content">
26456 <h1 id="doc_section_11" class="np">
26457 <div class="self-section-number">
26458 <a href="#doc_section_11">11_</a> </div>
26459 <a id="howtos-focused-directions" href="#howtos-focused-directions">Howtos: Focused Directions</a>
26460 </h1>
26461 <p id="doc_section_11_p_1">This section provides task-oriented instructions for selected tasks. If you have a task that needs instructions, please open a request as an enhancement issue on github.</p>
26462 <p id="doc_section_11_p_2">Section Contents: </p>
26463 <ul>
26464 <li><a href="#howto-report-bugs" title="Howto: Report bugs">Section 11.1</a></li>
26465 <li><a href="#howto-install-libxo" title="Howto: Install libxo">Section 11.2</a></li>
26466 <li><a href="#howto-convert-command-line-applications" title="Howto: Convert command line applications">Section 11.3</a></li>
26467 <li><a href="#howto-use-xo-in-shell-scripts" title='Howto: Use "xo" in Shell Scripts'>Section 11.4</a></li>
26468 <li><a href="#howto-i18n" title="Howto: Internationalization (i18n)">Section 11.5</a></li>
26469 </ul>
26470 <div class="content">
26471 <h2 id="doc_section_11_1">
26472 <div class="self-section-number">
26473 <a href="#doc_section_11_1">11.1</a> </div>
26474 <a id="howto-report-bugs" href="#howto-report-bugs">Howto: Report bugs</a>
26475 </h2>
26476 <p id="doc_section_11_1_p_1">libxo uses github to track bugs or request enhancements. Please use the following URL:</p>
26477 <p id="doc_section_11_1_p_2"> <a href="https://github.com/Juniper/libxo/issues">https://github.com/Juniper/libxo/issues</a></p>
26478 </div>
26479 <div class="content">
26480 <h2 id="doc_section_11_2">
26481 <div class="self-section-number">
26482 <a href="#doc_section_11_2">11.2</a> </div>
26483 <a id="howto-install-libxo" href="#howto-install-libxo">Howto: Install libxo</a>
26484 </h2>
26485 <p id="doc_section_11_2_p_1">libxo is open source, under a new BSD license. Source code is available on github, as are recent releases. To get the most current release, please visit:</p>
26486 <p id="doc_section_11_2_p_2"> <a href="https://github.com/Juniper/libxo/releases">https://github.com/Juniper/libxo/releases</a></p>
26487 <p id="doc_section_11_2_p_3">After downloading and untarring the source code, building involves the following steps:</p>
26488 <div id="doc_figure_u.191"></div> <pre>
26489     sh bin/setup.sh
26490     cd build
26491     ../configure
26492     make
26493     make test
26494     sudo make install
26495             </pre> <p id="doc_section_11_2_p_5">libxo uses a distinct "build" directory to keep generated files separated from source files.</p>
26496 <p id="doc_section_11_2_p_6">Use "../configure --help" to display available configuration options, which include the following:</p>
26497 <div id="doc_figure_u.192"></div> <pre>
26498   --enable-warnings      Turn on compiler warnings
26499   --enable-debug         Turn on debugging
26500   --enable-text-only     Turn on text-only rendering
26501   --enable-printflike    Enable use of GCC __printflike attribute
26502   --disable-libxo-options  Turn off support for LIBXO_OPTIONS
26503   --with-gettext=PFX     Specify location of gettext installation
26504   --with-libslax-prefix=PFX  Specify location of libslax config
26505             </pre> <p id="doc_section_11_2_p_8">Compiler warnings are a very good thing, but recent compiler version have added some very pedantic checks. While every attempt is made to keep libxo code warning-free, warnings are now optional. If you are doing development work on libxo, it is required that you use --enable-warnings to keep the code warning free, but most users need not use this option.</p>
26506 <p id="doc_section_11_2_p_9">libxo provides the --enable-text-only option to reduce the footprint of the library for smaller installations. XML, JSON, and HTML rendering logic is removed.</p>
26507 <p id="doc_section_11_2_p_10">The gettext library does not provide a simple means of learning its location, but libxo will look for it in /usr and /opt/local. If installed elsewhere, the installer will need to provide this information using the --with-gettext=/dir/path option.</p>
26508 <p id="doc_section_11_2_p_11">libslax is not required by libxo; it contains the "oxtradoc" program used to format documentation.</p>
26509 <p id="doc_section_11_2_p_12">For additional information, see <a href="#building-libxo" title="Building libxo">Section 2.2</a>.</p>
26510 </div>
26511 <div class="content">
26512 <h2 id="doc_section_11_3">
26513 <div class="self-section-number">
26514 <a href="#doc_section_11_3">11.3</a> </div>
26515 <a id="howto-convert-command-line-applications" href="#howto-convert-command-line-applications">Howto: Convert command line applications</a>
26516 </h2>
26517 <div id="doc_figure_u.193"></div> <pre>
26518     How do I convert an existing command line application?
26519             </pre> <p id="doc_section_11_3_p_2">There are three basic steps for converting command line application to use libxo.</p>
26520 <p id="doc_section_11_3_p_3"> </p>
26521 <ul>
26522 <li>Setting up the context</li>
26523 <li>Converting printf calls</li>
26524 <li>Creating hierarchy</li>
26525 <li>Converting error functions</li>
26526 </ul>
26527 <p id="doc_section_11_3_p_4">Section Contents: </p>
26528 <ul>
26529 <li><a href="#setting-up-the-context" title="Setting up the context">Section 11.3.1</a></li>
26530 <li><a href="#converting-printf-calls" title="Converting printf Calls">Section 11.3.2</a></li>
26531 <li><a href="#creating-hierarchy" title="Creating Hierarchy">Section 11.3.3</a></li>
26532 <li><a href="#converting-error-functions" title="Converting Error Functions">Section 11.3.4</a></li>
26533 </ul>
26534 <div class="content">
26535 <h3 id="doc_section_11_3_1">
26536 <div class="self-section-number">
26537 <a href="#doc_section_11_3_1">11.3.1</a> </div>
26538 <a id="setting-up-the-context" href="#setting-up-the-context">Setting up the context</a>
26539 </h3>
26540 <p id="doc_section_11_3_1_p_1">To use libxo, you'll need to include the "xo.h" header file in your source code files:</p>
26541 <div id="doc_figure_u.194"></div> <pre>
26542     #include &lt;libxo/xo.h&gt;
26543             </pre> <p id="doc_section_11_3_1_p_3">In your main() function, you'll need to call xo_parse_args to handling argument parsing (<a href="#xo_parse_args" title="Parsing Command-line Arguments (xo_parse_args)">Section 5.4.1</a>). This function removes libxo-specific arguments the program's argv and returns either the number of remaining arguments or -1 to indicate an error.</p>
26544 <div id="doc_figure_u.195"></div> <pre>
26545     int main (int argc, char **argv)
26546     {
26547         argc = xo_parse_args(argc, argv);
26548         if (argc &lt; 0)
26549             return argc;
26550         ....
26551     }
26552             </pre> <p id="doc_section_11_3_1_p_5">At the bottom of your main(), you'll need to call xo_finish() to complete output processing for the default handle (<a href="#handles" title="Handles">Section 5.1</a>). libxo provides the xo_finish_atexit function that is suitable for use with the atexit(3) function.</p>
26553 <div id="doc_figure_u.196"></div> <pre>
26554     atexit(xo_finish_atexit);
26555             </pre> </div>
26556 <div class="content">
26557 <h3 id="doc_section_11_3_2">
26558 <div class="self-section-number">
26559 <a href="#doc_section_11_3_2">11.3.2</a> </div>
26560 <a id="converting-printf-calls" href="#converting-printf-calls">Converting printf Calls</a>
26561 </h3>
26562 <p id="doc_section_11_3_2_p_1">The second task is inspecting code for printf(3) calls and replacing them with xo_emit() calls. The format strings are similar in task, but libxo format strings wrap output fields in braces. The following two calls produce identical text output:</p>
26563 <div id="doc_figure_u.197"></div> <pre>
26564     printf("There are %d %s events\n", count, etype);
26565     xo_emit("There are {:count/%d} {:event} events\n", count, etype);
26566             </pre> <p id="doc_section_11_3_2_p_3">"count" and "event" are used as names for JSON and XML output. The "count" field uses the format "%d" and "event" uses the default "%s" format. Both are "value" roles, which is the default role.</p>
26567 <p id="doc_section_11_3_2_p_4">Since text outside of output fields is passed verbatim, other roles are less important, but their proper use can help make output more useful. The "note" and "label" roles allow HTML output to recognize the relationship between text and the associated values, allowing appropriate "hover" and "onclick" behavior. Using the "units" role allows the presentation layer to perform conversions when needed. The "warning" and "error" roles allows use of color and font to draw attention to warnings. The "padding" role makes the use of vital whitespace more clear (<a href="#padding-role" title="The Padding Role ({P:})">Section 3.2.1.6</a>).</p>
26568 <p id="doc_section_11_3_2_p_5">The "title" role indicates the headings of table and sections. This allows HTML output to use CSS to make this relationship more obvious.</p>
26569 <div id="doc_figure_u.198"></div> <pre>
26570     printf("Statistics:\n");
26571     xo_emit("{T:Statistics}:\n");
26572             </pre> <p id="doc_section_11_3_2_p_7">The "color" roles controls foreground and background colors, as well as effects like bold and underline (see <a href="#color-role" title="The Color Role ({C:})">Section 3.2.1.1</a>).</p>
26573 <div id="doc_figure_u.199"></div> <pre>
26574     xo_emit("{C:bold}required{C:}\n");
26575             </pre> <p id="doc_section_11_3_2_p_9">Finally, the start- and stop-anchor roles allow justification and padding over multiple fields (see <a href="#anchor-role" title="The Anchor Roles ({[:} and {]:})">Section 3.2.1.10</a>).</p>
26576 <div id="doc_figure_u.200"></div> <pre>
26577     snprintf(buf, sizeof(buf), "(%u/%u/%u)", min, ave, max);
26578     printf("%30s", buf);
26579
26580     xo_emit("{[:30}({:minimum/%u}/{:average/%u}/{:maximum/%u}{]:}",
26581             min, ave, max);
26582             </pre> </div>
26583 <div class="content">
26584 <h3 id="doc_section_11_3_3">
26585 <div class="self-section-number">
26586 <a href="#doc_section_11_3_3">11.3.3</a> </div>
26587 <a id="creating-hierarchy" href="#creating-hierarchy">Creating Hierarchy</a>
26588 </h3>
26589 <p id="doc_section_11_3_3_p_1">Text output doesn't have any sort of hierarchy, but XML and JSON require this. Typically applications use indentation to represent these relationship:</p>
26590 <div id="doc_figure_u.201"></div> <pre>
26591     printf("table %d\n", tnum);
26592     for (i = 0; i &lt; tmax; i++) {
26593         printf("    %s %d\n", table[i].name, table[i].size);
26594     }
26595
26596     xo_emit("{T:/table %d}\n", tnum);
26597     xo_open_list("table");
26598     for (i = 0; i &lt; tmax; i++) {
26599         xo_open_instance("table");
26600         xo_emit("{P:    }{k:name} {:size/%d}\n",
26601                 table[i].name, table[i].size);
26602         xo_close_instance("table");
26603     }
26604     xo_close_list("table");
26605             </pre> <p id="doc_section_11_3_3_p_3">The open and close list functions are used before and after the list, and the open and close instance functions are used before and after each instance with in the list.</p>
26606 <p id="doc_section_11_3_3_p_4">Typically these developer looks for a "for" loop as an indication of where to put these calls.</p>
26607 <p id="doc_section_11_3_3_p_5">In addition, the open and close container functions allow for organization levels of hierarchy.</p>
26608 <div id="doc_figure_u.202"></div> <pre>
26609     printf("Paging information:\n");
26610     printf("    Free:      %lu\n", free);
26611     printf("    Active:    %lu\n", active);
26612     printf("    Inactive:  %lu\n", inactive);
26613
26614     xo_open_container("paging-information");
26615     xo_emit("{P:    }{L:Free:      }{:free/%lu}\n", free);
26616     xo_emit("{P:    }{L:Active:    }{:active/%lu}\n", active);
26617     xo_emit("{P:    }{L:Inactive:  }{:inactive/%lu}\n", inactive);
26618     xo_close_container("paging-information");
26619             </pre> </div>
26620 <div class="content">
26621 <h3 id="doc_section_11_3_4">
26622 <div class="self-section-number">
26623 <a href="#doc_section_11_3_4">11.3.4</a> </div>
26624 <a id="converting-error-functions" href="#converting-error-functions">Converting Error Functions</a>
26625 </h3>
26626 <p id="doc_section_11_3_4_p_1">libxo provides variants of the standard error and warning functions, err(3) and warn(3). There are two variants, one for putting the errors on standard error, and the other writes the errors and warnings to the handle using the appropriate encoding style:</p>
26627 <div id="doc_figure_u.203"></div> <pre>
26628     err(1, "cannot open output file: %s", file);
26629
26630     xo_err(1, "cannot open output file: %s", file);
26631     xo_emit_err(1, "cannot open output file: {:filename}", file);
26632             </pre> </div>
26633 </div>
26634 <div class="content"><h2 id="doc_section_11_4">
26635 <div class="self-section-number">
26636 <a href="#doc_section_11_4">11.4</a> </div>
26637 <a id="howto-use-xo-in-shell-scripts" href="#howto-use-xo-in-shell-scripts">Howto: Use "xo" in Shell Scripts</a>
26638 </h2></div>
26639 <div class="content">
26640 <h2 id="doc_section_11_5">
26641 <div class="self-section-number">
26642 <a href="#doc_section_11_5">11.5</a> </div>
26643 <a id="howto-i18n" href="#howto-i18n">Howto: Internationalization (i18n)</a>
26644 </h2>
26645 <div id="doc_figure_u.204"></div> <pre>
26646     How do I use libxo to support internationalization?
26647             </pre> <p id="doc_section_11_5_p_2">libxo allows format and field strings to be used a keys into message catalogs to enable translation into a user's native language by invoking the standard gettext(3) functions.</p>
26648 <p id="doc_section_11_5_p_3">gettext setup is a bit complicated: text strings are extracted from source files into "portable object template" (.pot) files using the "xgettext" command. For each language, this template file is used as the source for a message catalog in the "portable object" (.po) format, which are translated by hand and compiled into "machine object" (.mo) files using the "msgfmt" command. The .mo files are then typically installed in the /usr/share/locale or /opt/local/share/locale directories. At run time, the user's language settings are used to select a .mo file which is searched for matching messages. Text strings in the source code are used as keys to look up the native language strings in the .mo file.</p>
26649 <p id="doc_section_11_5_p_4">Since the xo_emit format string is used as the key into the message catalog, libxo removes unimportant field formatting and modifiers from the format string before use so that minor formatting changes will not impact the expensive translation process. We don't want a developer change such as changing "/%06d" to "/%08d" to force hand inspection of all .po files. The simplified version can be generated for a single message using the "xopo -s &lt;text&gt;" command, or an entire .pot can be translated using the "xopo -f &lt;input&gt; -o &lt;output&gt;" command.</p>
26650 <div id="doc_figure_u.205"></div> <pre>
26651     EXAMPLE:
26652         % xopo -s "There are {:count/%u} {:event/%.6s} events\n"
26653         There are {:count} {:event} events\n
26654
26655     Recommended workflow:
26656         # Extract text messages
26657         xgettext --default-domain=foo --no-wrap \
26658             --add-comments --keyword=xo_emit --keyword=xo_emit_h \
26659             --keyword=xo_emit_warn -C -E -n --foreign-user \
26660             -o foo.pot.raw foo.c
26661
26662         # Simplify format strings for libxo
26663         xopo -f foo.pot.raw -o foo.pot
26664
26665         # For a new language, just copy the file
26666         cp foo.pot po/LC/my_lang/foo.po
26667
26668         # For an existing language:
26669         msgmerge --no-wrap po/LC/my_lang/foo.po \
26670                 foo.pot -o po/LC/my_lang/foo.po.new
26671
26672         # Now the hard part: translate foo.po using tools
26673         # like poedit or emacs' po-mode
26674
26675         # Compile the finished file; Use of msgfmt's "-v" option is
26676         # strongly encouraged, so that "fuzzy" entries are reported.
26677         msgfmt -v -o po/my_lang/LC_MESSAGES/foo.mo po/my_lang/foo.po
26678
26679         # Install the .mo file
26680         sudo cp po/my_lang/LC_MESSAGES/foo.mo \
26681                 /opt/local/share/locale/my_lang/LC_MESSAGE/
26682             </pre> <p id="doc_section_11_5_p_6">Once these steps are complete, you can use the "gettext" command to test the message catalog:</p>
26683 <div id="doc_figure_u.206"></div> <pre>
26684     gettext -d foo -e "some text"
26685             </pre> <p id="doc_section_11_5_p_8">Section Contents: </p>
26686 <ul><li><a href="#i18n-and-xo_emit" title="i18n and xo_emit">Section 11.5.1</a></li></ul>
26687 <div class="content">
26688 <h3 id="doc_section_11_5_1">
26689 <div class="self-section-number">
26690 <a href="#doc_section_11_5_1">11.5.1</a> </div>
26691 <a id="i18n-and-xo_emit" href="#i18n-and-xo_emit">i18n and xo_emit</a>
26692 </h3>
26693 <p id="doc_section_11_5_1_p_1">There are three features used in libxo used to support i18n:</p>
26694 <p id="doc_section_11_5_1_p_2"> </p>
26695 <ul>
26696 <li>The "{G:}" role looks for a translation of the format string.</li>
26697 <li>The "{g:}" modifier looks for a translation of the field.</li>
26698 <li>The "{p:}" modifier looks for a pluralized version of the field.</li>
26699 </ul>
26700 <p id="doc_section_11_5_1_p_3">Together these three flags allows a single function call to give native language support, as well as libxo's normal XML, JSON, and HTML support.</p>
26701 <div id="doc_figure_u.207"></div> <pre>
26702     printf(gettext("Received %zu %s from {g:server} server\n"),
26703            counter, ngettext("byte", "bytes", counter),
26704            gettext("web"));
26705
26706     xo_emit("{G:}Received {:received/%zu} {Ngp:byte,bytes} "
26707             "from {g:server} server\n", counter, "web");
26708             </pre> <p id="doc_section_11_5_1_p_5">libxo will see the "{G:}" role and will first simplify the format string, removing field formats and modifiers.</p>
26709 <div id="doc_figure_u.208"></div> <pre>
26710     "Received {:received} {N:byte,bytes} from {:server} server\n"
26711             </pre> <p id="doc_section_11_5_1_p_7">libxo calls gettext(3) with that string to get a localized version. If your language were Pig Latin, the result might look like:</p>
26712 <div id="doc_figure_u.209"></div> <pre>
26713     "Eceivedray {:received} {N:byte,bytes} omfray "
26714                "{:server} erversay\n"
26715             </pre> <p id="doc_section_11_5_1_p_9">Note the field names do not change and they should not be translated. The contents of the note ("byte,bytes") should also not be translated, since the "g" modifier will need the untranslated value as the key for the message catalog.</p>
26716 <p id="doc_section_11_5_1_p_10">The field "{g:server}" requests the rendered value of the field be translated using gettext(3). In this example, "web" would be used.</p>
26717 <p id="doc_section_11_5_1_p_11">The field "{Ngp:byte,bytes}" shows an example of plural form using the "p" modifier with the "g" modifier. The base singular and plural forms appear inside the field, separated by a comma. At run time, libxo uses the previous field's numeric value to decide which form to use by calling ngettext(3).</p>
26718 <p id="doc_section_11_5_1_p_12">If a domain name is needed, it can be supplied as the content of the {G:} role. Domain names remain in use throughout the format string until cleared with another domain name.</p>
26719 <div id="doc_figure_u.210"></div> <pre>
26720     printf(dgettext("dns", "Host %s not found: %d(%s)\n"),
26721         name, errno, dgettext("strerror", strerror(errno)));
26722
26723     xo_emit("{G:dns}Host {:hostname} not found: "
26724             "%d({G:strerror}{g:%m})\n", name, errno);
26725             </pre> </div>
26726 </div>
26727 </div>
26728 <hr class="noprint">
26729 <div class="content">
26730 <h1 id="doc_section_12" class="np">
26731 <div class="self-section-number">
26732 <a href="#doc_section_12">12_</a> </div>
26733 <a id="examples" href="#examples">Examples</a>
26734 </h1>
26735 <p id="doc_section_12_p_1">Section Contents: </p>
26736 <ul><li><a href="#unit-test" title="Unit Test">Section 12.1</a></li></ul>
26737 <div class="content">
26738 <h2 id="doc_section_12_1">
26739 <div class="self-section-number">
26740 <a href="#doc_section_12_1">12.1</a> </div>
26741 <a id="unit-test" href="#unit-test">Unit Test</a>
26742 </h2>
26743 <p id="doc_section_12_1_p_1">Here is the unit test example:</p>
26744 <div id="doc_figure_u.211"></div> <pre>
26745     int
26746     main (int argc, char **argv)
26747     {
26748         static char base_grocery[] = "GRO";
26749         static char base_hardware[] = "HRD";
26750         struct item {
26751             const char *i_title;
26752             int i_sold;
26753             int i_instock;
26754             int i_onorder;
26755             const char *i_sku_base;
26756             int i_sku_num;
26757         };
26758         struct item list[] = {
26759             { "gum", 1412, 54, 10, base_grocery, 415 },
26760             { "rope", 85, 4, 2, base_hardware, 212 },
26761             { "ladder", 0, 2, 1, base_hardware, 517 },
26762             { "bolt", 4123, 144, 42, base_hardware, 632 },
26763             { "water", 17, 14, 2, base_grocery, 2331 },
26764             { NULL, 0, 0, 0, NULL, 0 }
26765         };
26766         struct item list2[] = {
26767             { "fish", 1321, 45, 1, base_grocery, 533 },
26768         };
26769         struct item *ip;
26770         xo_info_t info[] = {
26771             { "in-stock", "number", "Number of items in stock" },
26772             { "name", "string", "Name of the item" },
26773             { "on-order", "number", "Number of items on order" },
26774             { "sku", "string", "Stock Keeping Unit" },
26775             { "sold", "number", "Number of items sold" },
26776             { NULL, NULL, NULL },
26777         };
26778         int info_count = (sizeof(info) / sizeof(info[0])) - 1;
26779
26780         argc = xo_parse_args(argc, argv);
26781         if (argc &lt; 0)
26782             exit(EXIT_FAILURE);
26783
26784         xo_set_info(NULL, info, info_count);
26785
26786         xo_open_container_h(NULL, "top");
26787
26788         xo_open_container("data");
26789         xo_open_list("item");
26790
26791         for (ip = list; ip-&gt;i_title; ip++) {
26792             xo_open_instance("item");
26793
26794             xo_emit("{L:Item} '{k:name/%s}':\n", ip-&gt;i_title);
26795             xo_emit("{P:   }{L:Total sold}: {n:sold/%u%s}\n",
26796                     ip-&gt;i_sold, ip-&gt;i_sold ? ".0" : "");
26797             xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\n", 
26798                     ip-&gt;i_instock);
26799             xo_emit("{P:   }{Lwc:On order}{:on-order/%u}\n", 
26800                     ip-&gt;i_onorder);
26801             xo_emit("{P:   }{L:SKU}: {q:sku/%s-000-%u}\n",
26802                     ip-&gt;i_sku_base, ip-&gt;i_sku_num);
26803
26804             xo_close_instance("item");
26805         }
26806
26807         xo_close_list("item");
26808         xo_close_container("data");
26809
26810         xo_open_container("data");
26811         xo_open_list("item");
26812
26813         for (ip = list2; ip-&gt;i_title; ip++) {
26814             xo_open_instance("item");
26815
26816             xo_emit("{L:Item} '{:name/%s}':\n", ip-&gt;i_title);
26817             xo_emit("{P:   }{L:Total sold}: {n:sold/%u%s}\n",
26818                     ip-&gt;i_sold, ip-&gt;i_sold ? ".0" : "");
26819             xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\n", 
26820                     ip-&gt;i_instock);
26821             xo_emit("{P:   }{Lwc:On order}{:on-order/%u}\n", 
26822                     ip-&gt;i_onorder);
26823             xo_emit("{P:   }{L:SKU}: {q:sku/%s-000-%u}\n",
26824                     ip-&gt;i_sku_base, ip-&gt;i_sku_num);
26825
26826             xo_close_instance("item");
26827         }
26828
26829         xo_close_list("item");
26830         xo_close_container("data");
26831
26832         xo_close_container_h(NULL, "top");
26833
26834         return 0;
26835     }
26836             </pre> <p id="doc_section_12_1_p_3">Text output:</p>
26837 <div id="doc_figure_u.212"></div> <pre>
26838     % ./testxo --libxo text
26839     Item 'gum':
26840        Total sold: 1412.0
26841        In stock: 54
26842        On order: 10
26843        SKU: GRO-000-415
26844     Item 'rope':
26845        Total sold: 85.0
26846        In stock: 4
26847        On order: 2
26848        SKU: HRD-000-212
26849     Item 'ladder':
26850        Total sold: 0
26851        In stock: 2
26852        On order: 1
26853        SKU: HRD-000-517
26854     Item 'bolt':
26855        Total sold: 4123.0
26856        In stock: 144
26857        On order: 42
26858        SKU: HRD-000-632
26859     Item 'water':
26860        Total sold: 17.0
26861        In stock: 14
26862        On order: 2
26863        SKU: GRO-000-2331
26864     Item 'fish':
26865        Total sold: 1321.0
26866        In stock: 45
26867        On order: 1
26868        SKU: GRO-000-533
26869             </pre> <p id="doc_section_12_1_p_5">JSON output:</p>
26870 <div id="doc_figure_u.213"></div> <pre>
26871     % ./testxo --libxo json,pretty
26872     "top": {
26873       "data": {
26874         "item": [
26875           {
26876             "name": "gum",
26877             "sold": 1412.0,
26878             "in-stock": 54,
26879             "on-order": 10,
26880             "sku": "GRO-000-415"
26881           },
26882           {
26883             "name": "rope",
26884             "sold": 85.0,
26885             "in-stock": 4,
26886             "on-order": 2,
26887             "sku": "HRD-000-212"
26888           },
26889           {
26890             "name": "ladder",
26891             "sold": 0,
26892             "in-stock": 2,
26893             "on-order": 1,
26894             "sku": "HRD-000-517"
26895           },
26896           {
26897             "name": "bolt",
26898             "sold": 4123.0,
26899             "in-stock": 144,
26900             "on-order": 42,
26901             "sku": "HRD-000-632"
26902           },
26903           {
26904             "name": "water",
26905             "sold": 17.0,
26906             "in-stock": 14,
26907             "on-order": 2,
26908             "sku": "GRO-000-2331"
26909           }
26910         ]
26911       },
26912       "data": {
26913         "item": [
26914           {
26915             "name": "fish",
26916             "sold": 1321.0,
26917             "in-stock": 45,
26918             "on-order": 1,
26919             "sku": "GRO-000-533"
26920           }
26921         ]
26922       }
26923     }
26924             </pre> <p id="doc_section_12_1_p_7">XML output:</p>
26925 <div id="doc_figure_u.214"></div> <pre>
26926     % ./testxo --libxo pretty,xml
26927     &lt;top&gt;
26928       &lt;data&gt;
26929         &lt;item&gt;
26930           &lt;name&gt;gum&lt;/name&gt;
26931           &lt;sold&gt;1412.0&lt;/sold&gt;
26932           &lt;in-stock&gt;54&lt;/in-stock&gt;
26933           &lt;on-order&gt;10&lt;/on-order&gt;
26934           &lt;sku&gt;GRO-000-415&lt;/sku&gt;
26935         &lt;/item&gt;
26936         &lt;item&gt;
26937           &lt;name&gt;rope&lt;/name&gt;
26938           &lt;sold&gt;85.0&lt;/sold&gt;
26939           &lt;in-stock&gt;4&lt;/in-stock&gt;
26940           &lt;on-order&gt;2&lt;/on-order&gt;
26941           &lt;sku&gt;HRD-000-212&lt;/sku&gt;
26942         &lt;/item&gt;
26943         &lt;item&gt;
26944           &lt;name&gt;ladder&lt;/name&gt;
26945           &lt;sold&gt;0&lt;/sold&gt;
26946           &lt;in-stock&gt;2&lt;/in-stock&gt;
26947           &lt;on-order&gt;1&lt;/on-order&gt;
26948           &lt;sku&gt;HRD-000-517&lt;/sku&gt;
26949         &lt;/item&gt;
26950         &lt;item&gt;
26951           &lt;name&gt;bolt&lt;/name&gt;
26952           &lt;sold&gt;4123.0&lt;/sold&gt;
26953           &lt;in-stock&gt;144&lt;/in-stock&gt;
26954           &lt;on-order&gt;42&lt;/on-order&gt;
26955           &lt;sku&gt;HRD-000-632&lt;/sku&gt;
26956         &lt;/item&gt;
26957         &lt;item&gt;
26958           &lt;name&gt;water&lt;/name&gt;
26959           &lt;sold&gt;17.0&lt;/sold&gt;
26960           &lt;in-stock&gt;14&lt;/in-stock&gt;
26961           &lt;on-order&gt;2&lt;/on-order&gt;
26962           &lt;sku&gt;GRO-000-2331&lt;/sku&gt;
26963         &lt;/item&gt;
26964       &lt;/data&gt;
26965       &lt;data&gt;
26966         &lt;item&gt;
26967           &lt;name&gt;fish&lt;/name&gt;
26968           &lt;sold&gt;1321.0&lt;/sold&gt;
26969           &lt;in-stock&gt;45&lt;/in-stock&gt;
26970           &lt;on-order&gt;1&lt;/on-order&gt;
26971           &lt;sku&gt;GRO-000-533&lt;/sku&gt;
26972         &lt;/item&gt;
26973       &lt;/data&gt;
26974     &lt;/top&gt;
26975             </pre> <p id="doc_section_12_1_p_9">HMTL output:</p>
26976 <div id="doc_figure_u.215"></div> <pre>
26977     % ./testxo --libxo pretty,html
26978     &lt;div class="line"&gt;
26979       &lt;div class="label"&gt;Item&lt;/div&gt;
26980       &lt;div class="text"&gt; '&lt;/div&gt;
26981       &lt;div class="data" data-tag="name"&gt;gum&lt;/div&gt;
26982       &lt;div class="text"&gt;':&lt;/div&gt;
26983     &lt;/div&gt;
26984     &lt;div class="line"&gt;
26985       &lt;div class="padding"&gt;   &lt;/div&gt;
26986       &lt;div class="label"&gt;Total sold&lt;/div&gt;
26987       &lt;div class="text"&gt;: &lt;/div&gt;
26988       &lt;div class="data" data-tag="sold"&gt;1412.0&lt;/div&gt;
26989     &lt;/div&gt;
26990     &lt;div class="line"&gt;
26991       &lt;div class="padding"&gt;   &lt;/div&gt;
26992       &lt;div class="label"&gt;In stock&lt;/div&gt;
26993       &lt;div class="decoration"&gt;:&lt;/div&gt;
26994       &lt;div class="padding"&gt; &lt;/div&gt;
26995       &lt;div class="data" data-tag="in-stock"&gt;54&lt;/div&gt;
26996     &lt;/div&gt;
26997     &lt;div class="line"&gt;
26998       &lt;div class="padding"&gt;   &lt;/div&gt;
26999       &lt;div class="label"&gt;On order&lt;/div&gt;
27000       &lt;div class="decoration"&gt;:&lt;/div&gt;
27001       &lt;div class="padding"&gt; &lt;/div&gt;
27002       &lt;div class="data" data-tag="on-order"&gt;10&lt;/div&gt;
27003     &lt;/div&gt;
27004     &lt;div class="line"&gt;
27005       &lt;div class="padding"&gt;   &lt;/div&gt;
27006       &lt;div class="label"&gt;SKU&lt;/div&gt;
27007       &lt;div class="text"&gt;: &lt;/div&gt;
27008       &lt;div class="data" data-tag="sku"&gt;GRO-000-415&lt;/div&gt;
27009     &lt;/div&gt;
27010     &lt;div class="line"&gt;
27011       &lt;div class="label"&gt;Item&lt;/div&gt;
27012       &lt;div class="text"&gt; '&lt;/div&gt;
27013       &lt;div class="data" data-tag="name"&gt;rope&lt;/div&gt;
27014       &lt;div class="text"&gt;':&lt;/div&gt;
27015     &lt;/div&gt;
27016     &lt;div class="line"&gt;
27017       &lt;div class="padding"&gt;   &lt;/div&gt;
27018       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27019       &lt;div class="text"&gt;: &lt;/div&gt;
27020       &lt;div class="data" data-tag="sold"&gt;85.0&lt;/div&gt;
27021     &lt;/div&gt;
27022     &lt;div class="line"&gt;
27023       &lt;div class="padding"&gt;   &lt;/div&gt;
27024       &lt;div class="label"&gt;In stock&lt;/div&gt;
27025       &lt;div class="decoration"&gt;:&lt;/div&gt;
27026       &lt;div class="padding"&gt; &lt;/div&gt;
27027       &lt;div class="data" data-tag="in-stock"&gt;4&lt;/div&gt;
27028     &lt;/div&gt;
27029     &lt;div class="line"&gt;
27030       &lt;div class="padding"&gt;   &lt;/div&gt;
27031       &lt;div class="label"&gt;On order&lt;/div&gt;
27032       &lt;div class="decoration"&gt;:&lt;/div&gt;
27033       &lt;div class="padding"&gt; &lt;/div&gt;
27034       &lt;div class="data" data-tag="on-order"&gt;2&lt;/div&gt;
27035     &lt;/div&gt;
27036     &lt;div class="line"&gt;
27037       &lt;div class="padding"&gt;   &lt;/div&gt;
27038       &lt;div class="label"&gt;SKU&lt;/div&gt;
27039       &lt;div class="text"&gt;: &lt;/div&gt;
27040       &lt;div class="data" data-tag="sku"&gt;HRD-000-212&lt;/div&gt;
27041     &lt;/div&gt;
27042     &lt;div class="line"&gt;
27043       &lt;div class="label"&gt;Item&lt;/div&gt;
27044       &lt;div class="text"&gt; '&lt;/div&gt;
27045       &lt;div class="data" data-tag="name"&gt;ladder&lt;/div&gt;
27046       &lt;div class="text"&gt;':&lt;/div&gt;
27047     &lt;/div&gt;
27048     &lt;div class="line"&gt;
27049       &lt;div class="padding"&gt;   &lt;/div&gt;
27050       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27051       &lt;div class="text"&gt;: &lt;/div&gt;
27052       &lt;div class="data" data-tag="sold"&gt;0&lt;/div&gt;
27053     &lt;/div&gt;
27054     &lt;div class="line"&gt;
27055       &lt;div class="padding"&gt;   &lt;/div&gt;
27056       &lt;div class="label"&gt;In stock&lt;/div&gt;
27057       &lt;div class="decoration"&gt;:&lt;/div&gt;
27058       &lt;div class="padding"&gt; &lt;/div&gt;
27059       &lt;div class="data" data-tag="in-stock"&gt;2&lt;/div&gt;
27060     &lt;/div&gt;
27061     &lt;div class="line"&gt;
27062       &lt;div class="padding"&gt;   &lt;/div&gt;
27063       &lt;div class="label"&gt;On order&lt;/div&gt;
27064       &lt;div class="decoration"&gt;:&lt;/div&gt;
27065       &lt;div class="padding"&gt; &lt;/div&gt;
27066       &lt;div class="data" data-tag="on-order"&gt;1&lt;/div&gt;
27067     &lt;/div&gt;
27068     &lt;div class="line"&gt;
27069       &lt;div class="padding"&gt;   &lt;/div&gt;
27070       &lt;div class="label"&gt;SKU&lt;/div&gt;
27071       &lt;div class="text"&gt;: &lt;/div&gt;
27072       &lt;div class="data" data-tag="sku"&gt;HRD-000-517&lt;/div&gt;
27073     &lt;/div&gt;
27074     &lt;div class="line"&gt;
27075       &lt;div class="label"&gt;Item&lt;/div&gt;
27076       &lt;div class="text"&gt; '&lt;/div&gt;
27077       &lt;div class="data" data-tag="name"&gt;bolt&lt;/div&gt;
27078       &lt;div class="text"&gt;':&lt;/div&gt;
27079     &lt;/div&gt;
27080     &lt;div class="line"&gt;
27081       &lt;div class="padding"&gt;   &lt;/div&gt;
27082       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27083       &lt;div class="text"&gt;: &lt;/div&gt;
27084       &lt;div class="data" data-tag="sold"&gt;4123.0&lt;/div&gt;
27085     &lt;/div&gt;
27086     &lt;div class="line"&gt;
27087       &lt;div class="padding"&gt;   &lt;/div&gt;
27088       &lt;div class="label"&gt;In stock&lt;/div&gt;
27089       &lt;div class="decoration"&gt;:&lt;/div&gt;
27090       &lt;div class="padding"&gt; &lt;/div&gt;
27091       &lt;div class="data" data-tag="in-stock"&gt;144&lt;/div&gt;
27092     &lt;/div&gt;
27093     &lt;div class="line"&gt;
27094       &lt;div class="padding"&gt;   &lt;/div&gt;
27095       &lt;div class="label"&gt;On order&lt;/div&gt;
27096       &lt;div class="decoration"&gt;:&lt;/div&gt;
27097       &lt;div class="padding"&gt; &lt;/div&gt;
27098       &lt;div class="data" data-tag="on-order"&gt;42&lt;/div&gt;
27099     &lt;/div&gt;
27100     &lt;div class="line"&gt;
27101       &lt;div class="padding"&gt;   &lt;/div&gt;
27102       &lt;div class="label"&gt;SKU&lt;/div&gt;
27103       &lt;div class="text"&gt;: &lt;/div&gt;
27104       &lt;div class="data" data-tag="sku"&gt;HRD-000-632&lt;/div&gt;
27105     &lt;/div&gt;
27106     &lt;div class="line"&gt;
27107       &lt;div class="label"&gt;Item&lt;/div&gt;
27108       &lt;div class="text"&gt; '&lt;/div&gt;
27109       &lt;div class="data" data-tag="name"&gt;water&lt;/div&gt;
27110       &lt;div class="text"&gt;':&lt;/div&gt;
27111     &lt;/div&gt;
27112     &lt;div class="line"&gt;
27113       &lt;div class="padding"&gt;   &lt;/div&gt;
27114       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27115       &lt;div class="text"&gt;: &lt;/div&gt;
27116       &lt;div class="data" data-tag="sold"&gt;17.0&lt;/div&gt;
27117     &lt;/div&gt;
27118     &lt;div class="line"&gt;
27119       &lt;div class="padding"&gt;   &lt;/div&gt;
27120       &lt;div class="label"&gt;In stock&lt;/div&gt;
27121       &lt;div class="decoration"&gt;:&lt;/div&gt;
27122       &lt;div class="padding"&gt; &lt;/div&gt;
27123       &lt;div class="data" data-tag="in-stock"&gt;14&lt;/div&gt;
27124     &lt;/div&gt;
27125     &lt;div class="line"&gt;
27126       &lt;div class="padding"&gt;   &lt;/div&gt;
27127       &lt;div class="label"&gt;On order&lt;/div&gt;
27128       &lt;div class="decoration"&gt;:&lt;/div&gt;
27129       &lt;div class="padding"&gt; &lt;/div&gt;
27130       &lt;div class="data" data-tag="on-order"&gt;2&lt;/div&gt;
27131     &lt;/div&gt;
27132     &lt;div class="line"&gt;
27133       &lt;div class="padding"&gt;   &lt;/div&gt;
27134       &lt;div class="label"&gt;SKU&lt;/div&gt;
27135       &lt;div class="text"&gt;: &lt;/div&gt;
27136       &lt;div class="data" data-tag="sku"&gt;GRO-000-2331&lt;/div&gt;
27137     &lt;/div&gt;
27138     &lt;div class="line"&gt;
27139       &lt;div class="label"&gt;Item&lt;/div&gt;
27140       &lt;div class="text"&gt; '&lt;/div&gt;
27141       &lt;div class="data" data-tag="name"&gt;fish&lt;/div&gt;
27142       &lt;div class="text"&gt;':&lt;/div&gt;
27143     &lt;/div&gt;
27144     &lt;div class="line"&gt;
27145       &lt;div class="padding"&gt;   &lt;/div&gt;
27146       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27147       &lt;div class="text"&gt;: &lt;/div&gt;
27148       &lt;div class="data" data-tag="sold"&gt;1321.0&lt;/div&gt;
27149     &lt;/div&gt;
27150     &lt;div class="line"&gt;
27151       &lt;div class="padding"&gt;   &lt;/div&gt;
27152       &lt;div class="label"&gt;In stock&lt;/div&gt;
27153       &lt;div class="decoration"&gt;:&lt;/div&gt;
27154       &lt;div class="padding"&gt; &lt;/div&gt;
27155       &lt;div class="data" data-tag="in-stock"&gt;45&lt;/div&gt;
27156     &lt;/div&gt;
27157     &lt;div class="line"&gt;
27158       &lt;div class="padding"&gt;   &lt;/div&gt;
27159       &lt;div class="label"&gt;On order&lt;/div&gt;
27160       &lt;div class="decoration"&gt;:&lt;/div&gt;
27161       &lt;div class="padding"&gt; &lt;/div&gt;
27162       &lt;div class="data" data-tag="on-order"&gt;1&lt;/div&gt;
27163     &lt;/div&gt;
27164     &lt;div class="line"&gt;
27165       &lt;div class="padding"&gt;   &lt;/div&gt;
27166       &lt;div class="label"&gt;SKU&lt;/div&gt;
27167       &lt;div class="text"&gt;: &lt;/div&gt;
27168       &lt;div class="data" data-tag="sku"&gt;GRO-000-533&lt;/div&gt;
27169     &lt;/div&gt;
27170             </pre> <p id="doc_section_12_1_p_11">HTML output with xpath and info flags:</p>
27171 <div id="doc_figure_u.216"></div> <pre>
27172     % ./testxo --libxo pretty,html,xpath,info
27173     &lt;div class="line"&gt;
27174       &lt;div class="label"&gt;Item&lt;/div&gt;
27175       &lt;div class="text"&gt; '&lt;/div&gt;
27176       &lt;div class="data" data-tag="name"
27177            data-xpath="/top/data/item/name" data-type="string"
27178            data-help="Name of the item"&gt;gum&lt;/div&gt;
27179       &lt;div class="text"&gt;':&lt;/div&gt;
27180     &lt;/div&gt;
27181     &lt;div class="line"&gt;
27182       &lt;div class="padding"&gt;   &lt;/div&gt;
27183       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27184       &lt;div class="text"&gt;: &lt;/div&gt;
27185       &lt;div class="data" data-tag="sold"
27186            data-xpath="/top/data/item/sold" data-type="number"
27187            data-help="Number of items sold"&gt;1412.0&lt;/div&gt;
27188     &lt;/div&gt;
27189     &lt;div class="line"&gt;
27190       &lt;div class="padding"&gt;   &lt;/div&gt;
27191       &lt;div class="label"&gt;In stock&lt;/div&gt;
27192       &lt;div class="decoration"&gt;:&lt;/div&gt;
27193       &lt;div class="padding"&gt; &lt;/div&gt;
27194       &lt;div class="data" data-tag="in-stock"
27195            data-xpath="/top/data/item/in-stock" data-type="number"
27196            data-help="Number of items in stock"&gt;54&lt;/div&gt;
27197     &lt;/div&gt;
27198     &lt;div class="line"&gt;
27199       &lt;div class="padding"&gt;   &lt;/div&gt;
27200       &lt;div class="label"&gt;On order&lt;/div&gt;
27201       &lt;div class="decoration"&gt;:&lt;/div&gt;
27202       &lt;div class="padding"&gt; &lt;/div&gt;
27203       &lt;div class="data" data-tag="on-order"
27204            data-xpath="/top/data/item/on-order" data-type="number"
27205            data-help="Number of items on order"&gt;10&lt;/div&gt;
27206     &lt;/div&gt;
27207     &lt;div class="line"&gt;
27208       &lt;div class="padding"&gt;   &lt;/div&gt;
27209       &lt;div class="label"&gt;SKU&lt;/div&gt;
27210       &lt;div class="text"&gt;: &lt;/div&gt;
27211       &lt;div class="data" data-tag="sku"
27212            data-xpath="/top/data/item/sku" data-type="string"
27213            data-help="Stock Keeping Unit"&gt;GRO-000-415&lt;/div&gt;
27214     &lt;/div&gt;
27215     &lt;div class="line"&gt;
27216       &lt;div class="label"&gt;Item&lt;/div&gt;
27217       &lt;div class="text"&gt; '&lt;/div&gt;
27218       &lt;div class="data" data-tag="name"
27219            data-xpath="/top/data/item/name" data-type="string"
27220            data-help="Name of the item"&gt;rope&lt;/div&gt;
27221       &lt;div class="text"&gt;':&lt;/div&gt;
27222     &lt;/div&gt;
27223     &lt;div class="line"&gt;
27224       &lt;div class="padding"&gt;   &lt;/div&gt;
27225       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27226       &lt;div class="text"&gt;: &lt;/div&gt;
27227       &lt;div class="data" data-tag="sold"
27228            data-xpath="/top/data/item/sold" data-type="number"
27229            data-help="Number of items sold"&gt;85.0&lt;/div&gt;
27230     &lt;/div&gt;
27231     &lt;div class="line"&gt;
27232       &lt;div class="padding"&gt;   &lt;/div&gt;
27233       &lt;div class="label"&gt;In stock&lt;/div&gt;
27234       &lt;div class="decoration"&gt;:&lt;/div&gt;
27235       &lt;div class="padding"&gt; &lt;/div&gt;
27236       &lt;div class="data" data-tag="in-stock"
27237            data-xpath="/top/data/item/in-stock" data-type="number"
27238            data-help="Number of items in stock"&gt;4&lt;/div&gt;
27239     &lt;/div&gt;
27240     &lt;div class="line"&gt;
27241       &lt;div class="padding"&gt;   &lt;/div&gt;
27242       &lt;div class="label"&gt;On order&lt;/div&gt;
27243       &lt;div class="decoration"&gt;:&lt;/div&gt;
27244       &lt;div class="padding"&gt; &lt;/div&gt;
27245       &lt;div class="data" data-tag="on-order"
27246            data-xpath="/top/data/item/on-order" data-type="number"
27247            data-help="Number of items on order"&gt;2&lt;/div&gt;
27248     &lt;/div&gt;
27249     &lt;div class="line"&gt;
27250       &lt;div class="padding"&gt;   &lt;/div&gt;
27251       &lt;div class="label"&gt;SKU&lt;/div&gt;
27252       &lt;div class="text"&gt;: &lt;/div&gt;
27253       &lt;div class="data" data-tag="sku"
27254            data-xpath="/top/data/item/sku" data-type="string"
27255            data-help="Stock Keeping Unit"&gt;HRD-000-212&lt;/div&gt;
27256     &lt;/div&gt;
27257     &lt;div class="line"&gt;
27258       &lt;div class="label"&gt;Item&lt;/div&gt;
27259       &lt;div class="text"&gt; '&lt;/div&gt;
27260       &lt;div class="data" data-tag="name"
27261            data-xpath="/top/data/item/name" data-type="string"
27262            data-help="Name of the item"&gt;ladder&lt;/div&gt;
27263       &lt;div class="text"&gt;':&lt;/div&gt;
27264     &lt;/div&gt;
27265     &lt;div class="line"&gt;
27266       &lt;div class="padding"&gt;   &lt;/div&gt;
27267       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27268       &lt;div class="text"&gt;: &lt;/div&gt;
27269       &lt;div class="data" data-tag="sold"
27270            data-xpath="/top/data/item/sold" data-type="number"
27271            data-help="Number of items sold"&gt;0&lt;/div&gt;
27272     &lt;/div&gt;
27273     &lt;div class="line"&gt;
27274       &lt;div class="padding"&gt;   &lt;/div&gt;
27275       &lt;div class="label"&gt;In stock&lt;/div&gt;
27276       &lt;div class="decoration"&gt;:&lt;/div&gt;
27277       &lt;div class="padding"&gt; &lt;/div&gt;
27278       &lt;div class="data" data-tag="in-stock"
27279            data-xpath="/top/data/item/in-stock" data-type="number"
27280            data-help="Number of items in stock"&gt;2&lt;/div&gt;
27281     &lt;/div&gt;
27282     &lt;div class="line"&gt;
27283       &lt;div class="padding"&gt;   &lt;/div&gt;
27284       &lt;div class="label"&gt;On order&lt;/div&gt;
27285       &lt;div class="decoration"&gt;:&lt;/div&gt;
27286       &lt;div class="padding"&gt; &lt;/div&gt;
27287       &lt;div class="data" data-tag="on-order"
27288            data-xpath="/top/data/item/on-order" data-type="number"
27289            data-help="Number of items on order"&gt;1&lt;/div&gt;
27290     &lt;/div&gt;
27291     &lt;div class="line"&gt;
27292       &lt;div class="padding"&gt;   &lt;/div&gt;
27293       &lt;div class="label"&gt;SKU&lt;/div&gt;
27294       &lt;div class="text"&gt;: &lt;/div&gt;
27295       &lt;div class="data" data-tag="sku"
27296            data-xpath="/top/data/item/sku" data-type="string"
27297            data-help="Stock Keeping Unit"&gt;HRD-000-517&lt;/div&gt;
27298     &lt;/div&gt;
27299     &lt;div class="line"&gt;
27300       &lt;div class="label"&gt;Item&lt;/div&gt;
27301       &lt;div class="text"&gt; '&lt;/div&gt;
27302       &lt;div class="data" data-tag="name"
27303            data-xpath="/top/data/item/name" data-type="string"
27304            data-help="Name of the item"&gt;bolt&lt;/div&gt;
27305       &lt;div class="text"&gt;':&lt;/div&gt;
27306     &lt;/div&gt;
27307     &lt;div class="line"&gt;
27308       &lt;div class="padding"&gt;   &lt;/div&gt;
27309       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27310       &lt;div class="text"&gt;: &lt;/div&gt;
27311       &lt;div class="data" data-tag="sold"
27312            data-xpath="/top/data/item/sold" data-type="number"
27313            data-help="Number of items sold"&gt;4123.0&lt;/div&gt;
27314     &lt;/div&gt;
27315     &lt;div class="line"&gt;
27316       &lt;div class="padding"&gt;   &lt;/div&gt;
27317       &lt;div class="label"&gt;In stock&lt;/div&gt;
27318       &lt;div class="decoration"&gt;:&lt;/div&gt;
27319       &lt;div class="padding"&gt; &lt;/div&gt;
27320       &lt;div class="data" data-tag="in-stock"
27321            data-xpath="/top/data/item/in-stock" data-type="number"
27322            data-help="Number of items in stock"&gt;144&lt;/div&gt;
27323     &lt;/div&gt;
27324     &lt;div class="line"&gt;
27325       &lt;div class="padding"&gt;   &lt;/div&gt;
27326       &lt;div class="label"&gt;On order&lt;/div&gt;
27327       &lt;div class="decoration"&gt;:&lt;/div&gt;
27328       &lt;div class="padding"&gt; &lt;/div&gt;
27329       &lt;div class="data" data-tag="on-order"
27330            data-xpath="/top/data/item/on-order" data-type="number"
27331            data-help="Number of items on order"&gt;42&lt;/div&gt;
27332     &lt;/div&gt;
27333     &lt;div class="line"&gt;
27334       &lt;div class="padding"&gt;   &lt;/div&gt;
27335       &lt;div class="label"&gt;SKU&lt;/div&gt;
27336       &lt;div class="text"&gt;: &lt;/div&gt;
27337       &lt;div class="data" data-tag="sku"
27338            data-xpath="/top/data/item/sku" data-type="string"
27339            data-help="Stock Keeping Unit"&gt;HRD-000-632&lt;/div&gt;
27340     &lt;/div&gt;
27341     &lt;div class="line"&gt;
27342       &lt;div class="label"&gt;Item&lt;/div&gt;
27343       &lt;div class="text"&gt; '&lt;/div&gt;
27344       &lt;div class="data" data-tag="name"
27345            data-xpath="/top/data/item/name" data-type="string"
27346            data-help="Name of the item"&gt;water&lt;/div&gt;
27347       &lt;div class="text"&gt;':&lt;/div&gt;
27348     &lt;/div&gt;
27349     &lt;div class="line"&gt;
27350       &lt;div class="padding"&gt;   &lt;/div&gt;
27351       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27352       &lt;div class="text"&gt;: &lt;/div&gt;
27353       &lt;div class="data" data-tag="sold"
27354            data-xpath="/top/data/item/sold" data-type="number"
27355            data-help="Number of items sold"&gt;17.0&lt;/div&gt;
27356     &lt;/div&gt;
27357     &lt;div class="line"&gt;
27358       &lt;div class="padding"&gt;   &lt;/div&gt;
27359       &lt;div class="label"&gt;In stock&lt;/div&gt;
27360       &lt;div class="decoration"&gt;:&lt;/div&gt;
27361       &lt;div class="padding"&gt; &lt;/div&gt;
27362       &lt;div class="data" data-tag="in-stock"
27363            data-xpath="/top/data/item/in-stock" data-type="number"
27364            data-help="Number of items in stock"&gt;14&lt;/div&gt;
27365     &lt;/div&gt;
27366     &lt;div class="line"&gt;
27367       &lt;div class="padding"&gt;   &lt;/div&gt;
27368       &lt;div class="label"&gt;On order&lt;/div&gt;
27369       &lt;div class="decoration"&gt;:&lt;/div&gt;
27370       &lt;div class="padding"&gt; &lt;/div&gt;
27371       &lt;div class="data" data-tag="on-order"
27372            data-xpath="/top/data/item/on-order" data-type="number"
27373            data-help="Number of items on order"&gt;2&lt;/div&gt;
27374     &lt;/div&gt;
27375     &lt;div class="line"&gt;
27376       &lt;div class="padding"&gt;   &lt;/div&gt;
27377       &lt;div class="label"&gt;SKU&lt;/div&gt;
27378       &lt;div class="text"&gt;: &lt;/div&gt;
27379       &lt;div class="data" data-tag="sku"
27380            data-xpath="/top/data/item/sku" data-type="string"
27381            data-help="Stock Keeping Unit"&gt;GRO-000-2331&lt;/div&gt;
27382     &lt;/div&gt;
27383     &lt;div class="line"&gt;
27384       &lt;div class="label"&gt;Item&lt;/div&gt;
27385       &lt;div class="text"&gt; '&lt;/div&gt;
27386       &lt;div class="data" data-tag="name"
27387            data-xpath="/top/data/item/name" data-type="string"
27388            data-help="Name of the item"&gt;fish&lt;/div&gt;
27389       &lt;div class="text"&gt;':&lt;/div&gt;
27390     &lt;/div&gt;
27391     &lt;div class="line"&gt;
27392       &lt;div class="padding"&gt;   &lt;/div&gt;
27393       &lt;div class="label"&gt;Total sold&lt;/div&gt;
27394       &lt;div class="text"&gt;: &lt;/div&gt;
27395       &lt;div class="data" data-tag="sold"
27396            data-xpath="/top/data/item/sold" data-type="number"
27397            data-help="Number of items sold"&gt;1321.0&lt;/div&gt;
27398     &lt;/div&gt;
27399     &lt;div class="line"&gt;
27400       &lt;div class="padding"&gt;   &lt;/div&gt;
27401       &lt;div class="label"&gt;In stock&lt;/div&gt;
27402       &lt;div class="decoration"&gt;:&lt;/div&gt;
27403       &lt;div class="padding"&gt; &lt;/div&gt;
27404       &lt;div class="data" data-tag="in-stock"
27405            data-xpath="/top/data/item/in-stock" data-type="number"
27406            data-help="Number of items in stock"&gt;45&lt;/div&gt;
27407     &lt;/div&gt;
27408     &lt;div class="line"&gt;
27409       &lt;div class="padding"&gt;   &lt;/div&gt;
27410       &lt;div class="label"&gt;On order&lt;/div&gt;
27411       &lt;div class="decoration"&gt;:&lt;/div&gt;
27412       &lt;div class="padding"&gt; &lt;/div&gt;
27413       &lt;div class="data" data-tag="on-order"
27414            data-xpath="/top/data/item/on-order" data-type="number"
27415            data-help="Number of items on order"&gt;1&lt;/div&gt;
27416     &lt;/div&gt;
27417     &lt;div class="line"&gt;
27418       &lt;div class="padding"&gt;   &lt;/div&gt;
27419       &lt;div class="label"&gt;SKU&lt;/div&gt;
27420       &lt;div class="text"&gt;: &lt;/div&gt;
27421       &lt;div class="data" data-tag="sku"
27422            data-xpath="/top/data/item/sku" data-type="string"
27423            data-help="Stock Keeping Unit"&gt;GRO-000-533&lt;/div&gt;
27424     &lt;/div&gt;
27425             </pre> </div>
27426 </div>
27427 <div class="content"></div>
27428 <hr class="noprint">
27429 <div class="content">
27430 <h1 id="doc.authors" class="np"><a href="#doc.authors">Author's Address</a></h1>
27431 <address class="vcard">
27432 <span class="vcardline"><span class="fn">Phil Shafer</span><span class="n hidden"><span class="family-name">Shafer</span><span class="given-name">Phil</span></span></span><span class="org vcardline">Juniper Networks</span><span class="vcardline">EMail: <a href="mailto:phil@juniper.net"><span class="email">phil@juniper.net</span></a></span>
27433 </address>
27434 </div>
27435 </body>
27436 </html>