12061Sjkh<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
250479Speter<html lang="en">
32061Sjkh<head profile="http://www.w3.org/2006/03/hcard">
438666Sjb<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
532427Sjb<title>libxo: The Easy Way to Generate text, XML, JSON, and HTML output</title>
6111131Sru<style type="text/css">/*
7111131Sru * $Id$
838666Sjb *
938666Sjb * Copyright (c) 2006-2011, Juniper Networks, Inc.
1038666Sjb * All rights reserved.
1138666Sjb * This SOFTWARE is licensed under the LICENSE provided in the
1264049Salex * ../Copyright file. By downloading, installing, copying, or otherwise
1364049Salex * using the SOFTWARE, you agree to be bound by the terms of that
14116679Ssimokawa * LICENSE.
1566071Smarkm */
16116679Ssimokawa
1773504Sobrien#media-inspector {
1838666Sjb    display:none
1932427Sjb}
2038666Sjb@media screen {
21108451Sschweikh    #media-inspector { z-index: 1 }
2238666Sjb}
2338666Sjb@media print {
2438666Sjb    #media-inspector { z-index: 2 }
2538666Sjb}
2617308Speter
2791606Skeramidapre {
2819175Sbde    font-family: Consolas, Menlo, Monaco,Lucida Console, Liberation Mono,
2996205Sjwd                 DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New,
3096205Sjwd                 monospace, serif;
3138042Sbde    margin-bottom: 10px;
3296205Sjwd}
3396205Sjwd
3438042Sbde@media screen {
3596205Sjwd    hr.noprint {
3696205Sjwd	display: none;
3717308Speter    }
3896205Sjwd
3996205Sjwd    h1, h2, h3, h4, h5 {
4017308Speter	font-size: 14pt;
4196205Sjwd	color: black;
4296205Sjwd	margin: 0;
4396205Sjwd	padding: 0;
4496205Sjwd    }
4596205Sjwd    h1 a, h2 a, h3 a, h4 a, h5 a {
4696205Sjwd	font-size: 12pt;
4796205Sjwd	color: black;
4896205Sjwd    }
4996205Sjwd
5096205Sjwd    div#top {
5196205Sjwd	display: table;
5296205Sjwd    }
5398775Sdillon
5498723Sdillon    div#top-left {
5598723Sdillon	display: table-cell;
5698723Sdillon	width: 400px;
5798723Sdillon	border: 1px solid black;
5838666Sjb	border-right: 0px;
5938666Sjb    }
6017308Speter
6195509Sru    div#top-right {
6295793Sru	display: table-cell;
63116679Ssimokawa	width: 100%;
64120760Sru	border: 1px solid black;
65116679Ssimokawa    }
66120760Sru
672061Sjkh    div.section-number {
6897769Sru	display: none;
6997252Sru    }
70119579Sru
7197252Sru    div.fake-content {
7295730Sru	display: block;
7395793Sru	background-color: #d0d0f0;
74111617Sru    }
7595730Sru
76116679Ssimokawa    div.fake-active {
7795730Sru	display: block;
78116679Ssimokawa	background-color: #f0d0d0;
7995730Sru    }
80110035Sru
81107516Sru    div#nav-bar {
82110035Sru	display: inline-block;
83117234Sru	float: right;
84110035Sru    }
85117229Sru
86117234Sru    div#nav-bar button#nav-next {
8754324Smarcel        margin-right: 1em;
8817308Speter    }
89119519Smarcel
90119519Smarcel    div#nav-bar button {
91119519Smarcel        border-radius: 4px;
92119519Smarcel    }
93119519Smarcel
94119519Smarcel    div.content {
95119579Sru	display: none;
96119519Smarcel    }
97119519Smarcel
98119519Smarcel    div.active {
99119519Smarcel	display: block;
100119519Smarcel    }
10138666Sjb
10217308Speter    a.toc-active {
103119519Smarcel	background-color: #dddddd;
104119579Sru    }
10538666Sjb
106110035Sru    div.self-section-number {
1072302Spaul	display: none;
10839206Sjkh    }
10939206Sjkh
11039206Sjkh    div#debug-log {
11173349Sru	white-space: pre-wrap;
11217308Speter    }
11354324Smarcel
11454324Smarcel    h1, h2, h3, h4, h5 {
11554324Smarcel	margin: 0;
11654324Smarcel    }
11754324Smarcel
11854324Smarcel    div#toc {
11954324Smarcel	overflow-y: scroll;
120118531Sru    }
12154324Smarcel
12254324Smarcel    div#toc > ul.toc {
12354324Smarcel	margin-left: 2px;
12454324Smarcel    }
12554324Smarcel
12654324Smarcel    table.header {
127110035Sru	display: none;
12854324Smarcel    }
129110035Sru
130110035Sru    p#title span.filename {
13154324Smarcel	display: none;
13254324Smarcel    }
13354324Smarcel
13454324Smarcel    p#title {
13554324Smarcel	margin-top: 20px;
136110035Sru    }
13754324Smarcel
13854324Smarcel    ul.top-toc {
13954324Smarcel	display: none;
140118531Sru    }
141118531Sru
14254324Smarcel    ul.top-toc-open {
14354324Smarcel	display: block;
14454324Smarcel    }
14595730Sru
14695730Sru    div.padding {
14795730Sru	width: 300px;
14895730Sru    }
14995730Sru
15095730Sru}
15195730Sru
15238666Sjb@media print {
153107374Sru    div.self-section-number, div.section-number {
15417308Speter	display: block-inline;
15555678Smarcel    }
156110035Sru
157117793Sru    button {
158110035Sru	display: none;
159110035Sru    }
160110035Sru
1612061Sjkh    h1 {
16217308Speter	font-size: 14pt;
163107516Sru	/*  line-height: 21pt;*/
164107374Sru	page-break-after: avoid;
16555678Smarcel    }
166107516Sru    h1.np {
167107516Sru	page-break-before: always;
168107516Sru    }
169107516Sru    h1 a {
170107516Sru	color: #333333;
171107516Sru    }
172107516Sru    h2 {
173107516Sru	font-size: 12pt;
174122204Skris	/*  line-height: 15pt; */
17555678Smarcel	page-break-after: avoid;
17655678Smarcel    }
177116696Sru    h2 a {
17855678Smarcel	color: black;
17955678Smarcel    }
180107516Sru    h3 {
181107516Sru	font-size: 10pt;
182107516Sru	page-break-after: avoid;
183107516Sru    }
18455678Smarcel    h3 a {
18555678Smarcel	color: black;
186111131Sru    }
187111131Sru    h4 {
188111131Sru	font-size: 10pt;
189111131Sru	page-break-after: avoid;
190111131Sru    }
191111131Sru    h4 a {
192111131Sru	color: black;
193103985Sphk    }
194103985Sphk    h5 {
195103985Sphk	font-size: 10pt;
196103985Sphk	page-break-after: avoid;
197111089Sphk    }
198111131Sru    h5 a {
199111131Sru	color: black;
200111131Sru    }
201111131Sru}
202111131Sru
203111131Srup.section-contents, p.section-contents + ul {
204111131Sru    background-color: #f8f8ff;
205111131Sru    padding: 1em 0px 1em 3em;
206111131Sru    border: 1px dotted #0000c0;
207111133Sru}
208103985Sphk
209111131Srup.section-contents + ul {
210111131Sru    margin: 0px 1em 0px 3em;
211103985Sphk    border-top: 0px;
212111131Sru}
213103985Sphk
214118531Srup.section-contents {
215118531Sru    margin: 3em 1em 0px 3em;
216103985Sphk    font-weight: bold;
217103985Sphk    border-bottom: 0px;
218111131Sru    padding-bottom: 0px;
219111131Sru}
220103985Sphk</style>
221103985Sphk<style type="text/css" title="Xml2Rfc (sans serif)">
222111131Srua {
223111131Sru  text-decoration: none;
224111131Sru}
225111131Srua.smpl {
226111131Sru  color: black;
227103985Sphk}
228a:hover {
229  text-decoration: underline;
230}
231a:active {
232  text-decoration: underline;
233}
234address {
235  margin-top: 1em;
236  margin-left: 2em;
237  font-style: normal;
238}
239body {
240  color: black;
241  font-family: verdana, helvetica, arial, sans-serif;
242  font-size: 10pt;
243}
244cite {
245  font-style: normal;
246}
247dd {
248  margin-right: 2em;
249}
250dl {
251  margin-left: 2em;
252}
253
254dl.empty dd {
255  margin-top: .5em;
256}
257dl p {
258  margin-left: 0em;
259}
260dt {
261  margin-top: .5em;
262}
263img {
264  margin-left: 3em;
265}
266li {
267  margin-left: 2em;
268  margin-right: 2em;
269}
270ol {
271  margin-left: 2em;
272  margin-right: 2em;
273}
274ol p {
275  margin-left: 0em;
276}
277p {
278  margin-left: 2em;
279  margin-right: 2em;
280}
281pre {
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}
291pre.text2 {
292  border-style: dotted;
293  border-width: 1px;
294  background-color: #f0f0f0;
295  width: 69em;
296}
297pre.inline {
298  background-color: white;
299  padding: 0em;
300}
301pre.text {
302  border-style: dotted;
303  border-width: 1px;
304  background-color: #f8f8f8;
305  width: 69em;
306}
307pre.drawing {
308  border-style: solid;
309  border-width: 1px;
310  background-color: #f8f8f8;
311  padding: 2em;
312}
313table {
314  margin-left: 2em;
315}
316table.tt {
317  vertical-align: top;
318}
319table.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}
329table.headers {
330  border-style: outset;
331  border-width: 1px;
332}
333table.tt td {
334  vertical-align: top;
335}
336table.full td {
337  border-style: inset;
338  border-width: 1px;
339}
340table.tt th {
341  vertical-align: top;
342}
343table.full th {
344  border-style: inset;
345  border-width: 1px;
346}
347table.headers th {
348  border-style: none none inset none;
349  border-width: 1px;
350}
351table.header {
352  width: 95%;
353  font-size: 10pt;
354  color: white;
355}
356td.top {
357  vertical-align: top;
358}
359td.topnowrap {
360  vertical-align: top;
361  white-space: nowrap; 
362}
363td.header {
364  background-color: gray;
365  width: 50%;
366}
367td.header a {
368  color: white;
369}
370td.reference {
371  vertical-align: top;
372  white-space: nowrap;
373  padding-right: 1em;
374}
375thead {
376  display:table-header-group;
377}
378ul.toc {
379  list-style: none;
380  margin-left: 1.5em;
381  margin-right: 0em;
382  padding-left: 0em;
383}
384li.tocline0 {
385  line-height: 150%;
386  font-weight: bold;
387  font-size: 10pt;
388  margin-left: 0em;
389  margin-right: 0em;
390}
391li.tocline1 {
392  line-height: normal;
393  font-weight: normal;
394  font-size: 9pt;
395  margin-left: 0em;
396  margin-right: 0em;
397}
398li.tocline2 {
399  font-size: 0pt;
400}
401ul p {
402  margin-left: 0em;
403}
404ul.ind {
405  list-style: none;
406  margin-left: 1.5em;
407  margin-right: 0em;
408  padding-left: 0em;
409}
410li.indline0 {
411  font-weight: bold;
412  line-height: 200%;
413  margin-left: 0em;
414  margin-right: 0em;
415}
416li.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
551div.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
564div.fancy-tooltip-empty-header {
565  text-align: left;
566  font-weight: bold;
567  margin: 2px;
568}
569
570div.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
577div.fancy-tooltip-body {
578  font-weight: normal;
579  margin: 4px;
580}
581
582div.fancy-tooltip-body ul, div.fancy-tooltip-body li  {
583  padding: 1px 4px 1px 4px;
584  margin: 1px 2px 1px 8px;
585}
586
587span.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
596span.digress-anchor {
597  margin: 10pt 20pt 10pt 50pt;
598}
599
600a.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)
625var document = window.document,
626	navigator = window.navigator,
627	location = window.location;
628var jQuery = (function() {
629
630// Define a local copy of jQuery
631var 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
706jQuery.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
930jQuery.fn.init.prototype = jQuery.fn;
931
932jQuery.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
996jQuery.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
1505jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
1506	class2type[ "[object " + name + "]" ] = name.toLowerCase();
1507});
1508
1509browserMatch = jQuery.uaMatch( userAgent );
1510if ( browserMatch.browser ) {
1511	jQuery.browser[ browserMatch.browser ] = true;
1512	jQuery.browser.version = browserMatch.version;
1513}
1514
1515// Deprecated, use jQuery.browser.webkit instead
1516if ( jQuery.browser.webkit ) {
1517	jQuery.browser.safari = true;
1518}
1519
1520// IE doesn't match non-breaking spaces with \s
1521if ( rnotwhite.test( "\xA0" ) ) {
1522	trimLeft = /^[\s\xA0]+/;
1523	trimRight = /[\s\xA0]+$/;
1524}
1525
1526// All jQuery objects should point back to these
1527rootjQuery = jQuery(document);
1528
1529// Cleanup functions for the document ready method
1530if ( 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
1547function 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.
1575if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
1576	define( "jquery", [], function () { return jQuery; } );
1577}
1578
1579return jQuery;
1580
1581})();
1582
1583
1584// String to Object flags format cache
1585var flagsCache = {};
1586
1587// Convert String-formatted flags into Object-formatted ones and store in cache
1588function 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 */
1620jQuery.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
1810var // Static reference to slice
1811	sliceDeferred = [].slice;
1812
1813jQuery.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
1954jQuery.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
2274jQuery.boxModel = jQuery.support.boxModel;
2275
2276
2277
2278
2279var rbrace = /^(?:\{.*\}|\[.*\])$/,
2280	rmultiDash = /([A-Z])/g;
2281
2282jQuery.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
2521jQuery.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
2588function 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
2619function 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
2637function 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
2657jQuery.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
2735jQuery.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
2812var 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
2822jQuery.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
3028jQuery.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)
3295jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
3296
3297// Hook for boolean attributes
3298boolHook = {
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
3329if ( !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
3388if ( !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
3399if ( !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
3414if ( !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
3433if ( !jQuery.support.enctype ) {
3434	jQuery.propFix.enctype = "encoding";
3435}
3436
3437// Radios and checkboxes getter/setter
3438if ( !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}
3448jQuery.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
3461var 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 */
3496jQuery.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.
4084jQuery.event.handle = jQuery.event.dispatch;
4085
4086jQuery.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
4098jQuery.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
4131function returnFalse() {
4132	return false;
4133}
4134function 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
4140jQuery.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
4182jQuery.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
4212if ( !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
4252if ( !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
4310if ( !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
4334jQuery.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
4489jQuery.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
4528var 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
4547var 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
4694Sizzle.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
4711Sizzle.matches = function( expr, set ) {
4712	return Sizzle( expr, null, null, set );
4713};
4714
4715Sizzle.matchesSelector = function( node, expr ) {
4716	return Sizzle( expr, null, null, [node] ).length > 0;
4717};
4718
4719Sizzle.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
4754Sizzle.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
4846Sizzle.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 */
4854var 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
4889var 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
5419var origPOS = Expr.match.POS,
5420	fescape = function(all, num){
5421		return "\\" + (num - 0 + 1);
5422	};
5423
5424for ( 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
5429var 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)
5444try {
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
5473var sortOrder, siblingCheck;
5474
5475if ( 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
5655if ( 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
5836function 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
5869function 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
5910if ( 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
5926Sizzle.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
5934var 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
5958Sizzle.attr = jQuery.attr;
5959Sizzle.selectors.attrMap = {};
5960jQuery.find = Sizzle;
5961jQuery.expr = Sizzle.selectors;
5962jQuery.expr[":"] = jQuery.expr.filters;
5963jQuery.unique = Sizzle.uniqueSort;
5964jQuery.text = Sizzle.getText;
5965jQuery.isXMLDoc = Sizzle.isXML;
5966jQuery.contains = Sizzle.contains;
5967
5968
5969})();
5970
5971
5972var 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
5987jQuery.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).
6142function isDisconnected( node ) {
6143	return !node || !node.parentNode || node.parentNode.nodeType === 11;
6144}
6145
6146jQuery.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
6213jQuery.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
6264function 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
6301function 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
6315var 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
6342wrapMap.optgroup = wrapMap.option;
6343wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
6344wrapMap.th = wrapMap.td;
6345
6346// IE can't serialize <link> and <script> tags normally
6347if ( !jQuery.support.htmlSerialize ) {
6348	wrapMap._default = [ 1, "div<div>", "</div>" ];
6349}
6350
6351jQuery.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
6663function 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
6670function 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
6698function 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
6756jQuery.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
6804jQuery.fragments = {};
6805
6806jQuery.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
6834function 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
6847function 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
6853function 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
6863jQuery.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
7085function 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
7104var 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
7120jQuery.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
7133jQuery.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
7267jQuery.curCSS = jQuery.css;
7268
7269jQuery.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
7303if ( !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
7344jQuery(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
7366if ( 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
7387if ( 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
7428curCSS = getComputedStyle || currentStyle;
7429
7430function 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
7477if ( 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
7493var 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
7542try {
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
7553ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7554
7555// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7556function 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
7592function 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
7634function 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
7647jQuery.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
7752jQuery.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
7758jQuery.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
7777jQuery.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
8291function 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
8325jQuery.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 */
8341function 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
8406function 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
8493var jsc = jQuery.now(),
8494	jsre = /(\=)\?(&|$)|\?\?/i;
8495
8496// Default jsonp settings
8497jQuery.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
8505jQuery.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
8573jQuery.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
8589jQuery.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
8600jQuery.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
8661var // #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
8672function createStandardXHR() {
8673	try {
8674		return new window.XMLHttpRequest();
8675	} catch( e ) {}
8676}
8677
8678function 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)
8686jQuery.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
8708if ( 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
8879var 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
8894jQuery.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
9195function createFxNow() {
9196	setTimeout( clearFxNow, 0 );
9197	return ( fxNow = jQuery.now() );
9198}
9199
9200function clearFxNow() {
9201	fxNow = undefined;
9202}
9203
9204// Generate parameters to create a standard animation
9205function 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
9216jQuery.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
9229jQuery.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
9285jQuery.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
9447jQuery.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
9497jQuery.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
9503if ( 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
9512function 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
9559var rtable = /^t(?:able|d|h)$/i,
9560	rroot = /^(?:body|html)$/i;
9561
9562if ( "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
9677jQuery.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
9736jQuery.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
9782jQuery.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
9821function 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
9833jQuery.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
9905window.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 || {};
9922if ( $.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
10085function 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
10106function 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+
10233if ( $.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
10503var 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
12605var num = function(v) {
12606	return parseInt(v, 10) || 0;
12607};
12608
12609var 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'],
13979function(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]
13999function 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
14030function 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
14050var 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
14103var 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
14116function 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
14147function 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
14171function 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
14386function _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
14420function 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
16177var 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
16787var 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
17204var PROP_NAME = 'datepicker';
17205var dpuuid = new Date().getTime();
17206var 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
17213function 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 */ 
18931function 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! */
18954function 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. */
18963function 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
19008window['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
19031var 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
19902var 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
20106if ( !$.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)
20268var 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
20931var tabId = 0,
20932	listId = 0;
20933
20934function getNextTabId() {
20935	return ++tabId;
20936}
20937
20938function 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
21681jQuery(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
21702function 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
21717function 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
21777function 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
21801jQuery(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>
27437