1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
3 <head profile="http://www.w3.org/2006/03/hcard">
4 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
5 <title>libxo: The Easy Way to Generate text, XML, JSON, and HTML output</title>
6 <style type="text/css">/*
9 * Copyright (c) 2006-2011, Juniper Networks, Inc.
10 * All rights reserved.
11 * This SOFTWARE is licensed under the LICENSE provided in the
12 * ../Copyright file. By downloading, installing, copying, or otherwise
13 * using the SOFTWARE, you agree to be bound by the terms of that
21 #media-inspector { z-index: 1 }
24 #media-inspector { z-index: 2 }
28 font-family: Consolas, Menlo, Monaco,Lucida Console, Liberation Mono,
29 DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New,
45 h1 a, h2 a, h3 a, h4 a, h5 a {
57 border: 1px solid black;
64 border: 1px solid black;
73 background-color: #d0d0f0;
78 background-color: #f0d0d0;
82 display: inline-block;
86 div#nav-bar button#nav-next {
103 background-color: #dddddd;
106 div.self-section-number {
111 white-space: pre-wrap;
130 p#title span.filename {
153 div.self-section-number, div.section-number {
154 display: block-inline;
163 /* line-height: 21pt;*/
164 page-break-after: avoid;
167 page-break-before: always;
174 /* line-height: 15pt; */
175 page-break-after: avoid;
182 page-break-after: avoid;
189 page-break-after: avoid;
196 page-break-after: avoid;
203 p.section-contents, p.section-contents + ul {
204 background-color: #f8f8ff;
205 padding: 1em 0px 1em 3em;
206 border: 1px dotted #0000c0;
209 p.section-contents + ul {
210 margin: 0px 1em 0px 3em;
215 margin: 3em 1em 0px 3em;
221 <style type="text/css" title="Xml2Rfc (sans serif)">
223 text-decoration: none;
229 text-decoration: underline;
232 text-decoration: underline;
241 font-family: verdana, helvetica, arial, sans-serif;
283 background-color: lightyellow;
287 -moz-box-shadow: 0 0 4px #000000;
288 -webkit-box-shadow: 0 0 4px #000000;
289 box-shadow: 0 0 4px #000000;
292 border-style: dotted;
294 background-color: #f0f0f0;
298 background-color: white;
302 border-style: dotted;
304 background-color: #f8f8f8;
310 background-color: #f8f8f8;
320 border-style: outset;
323 background-color: lightyellow;
325 -moz-box-shadow: 0 0 4px #000000;
326 -webkit-box-shadow: 0 0 4px #000000;
327 box-shadow: 0 0 4px #000000;
330 border-style: outset;
348 border-style: none none inset none;
364 background-color: gray;
376 display:table-header-group;
424 background-color: yellow;
471 background-color: yellow;
482 text-decoration: none;
492 background-color: white;
498 content: leader('.') target-counter(attr(href), page);
502 content: target-counter(attr(href), page);
507 -moz-column-count: 2;
522 content: "LIBXO-MANUAL";
534 content: "[Page " counter(page) "]";
552 border: solid 1px #666666;
560 background-color: #ffffcc;
561 layer-background-color: #ffffcc;
564 div.fancy-tooltip-empty-header {
570 div.fancy-tooltip-header {
573 margin: 2px 2px 0px 2px;
574 border-bottom: 1px solid black;
577 div.fancy-tooltip-body {
582 div.fancy-tooltip-body ul, div.fancy-tooltip-body li {
583 padding: 1px 4px 1px 4px;
584 margin: 1px 2px 1px 8px;
588 background-color: #778899;
589 font: courier new, courier, monospace;
593 border: 1px solid #aaaaaa;
596 span.digress-anchor {
597 margin: 10pt 20pt 10pt 50pt;
600 a.digress-anchor:link, a.digress-anchor:visited,
601 a.digress-anchor-hover, a.digress-anchor,active {
602 text-decoration: none;
607 <script type="text/javascript">/*!
608 * jQuery JavaScript Library v1.7
611 * Copyright 2011, John Resig
612 * Dual licensed under the MIT or GPL Version 2 licenses.
613 * http://jquery.org/license
616 * http://sizzlejs.com/
617 * Copyright 2011, The Dojo Foundation
618 * Released under the MIT, BSD, and GPL Licenses.
620 * Date: Thu Nov 3 16:18:21 2011 -0400
622 (function( window, undefined ) {
624 // Use the correct document accordingly with window argument (sandbox)
625 var document = window.document,
626 navigator = window.navigator,
627 location = window.location;
628 var jQuery = (function() {
630 // Define a local copy of jQuery
631 var jQuery = function( selector, context ) {
632 // The jQuery object is actually just the init constructor 'enhanced'
633 return new jQuery.fn.init( selector, context, rootjQuery );
636 // Map over jQuery in case of overwrite
637 _jQuery = window.jQuery,
639 // Map over the $ in case of overwrite
642 // A central reference to the root jQuery(document)
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\-]*)$)/,
649 // Check if a string has a non-whitespace character in it
652 // Used for trimming whitespace
659 // Match a standalone tag
660 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
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,
669 rwebkit = /(webkit)[ \/]([\w.]+)/,
670 ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
671 rmsie = /(msie) ([\w.]+)/,
672 rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
674 // Matches dashed string for camelizing
675 rdashAlpha = /-([a-z]|[0-9])/ig,
678 // Used by jQuery.camelCase as callback to replace()
679 fcamelCase = function( all, letter ) {
680 return ( letter + "" ).toUpperCase();
683 // Keep a UserAgent string for use with jQuery.browser
684 userAgent = navigator.userAgent,
686 // For matching the engine and version of the browser
689 // The deferred used on DOM ready
692 // The ready event handler
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,
703 // [[Class]] -> type pairs
706 jQuery.fn = jQuery.prototype = {
708 init: function( selector, context, rootjQuery ) {
709 var match, elem, ret, doc;
711 // Handle $(""), $(null), or $(undefined)
716 // Handle $(DOMElement)
717 if ( selector.nodeType ) {
718 this.context = this[0] = selector;
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;
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 ];
740 match = quickExpr.exec( selector );
743 // Verify a match, and that no context was specified for #id
744 if ( match && (match[1] || !context) ) {
746 // HANDLE: $(html) -> $(array)
748 context = context instanceof jQuery ? context[0] : context;
749 doc = ( context ? context.ownerDocument || context : document );
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 );
756 if ( jQuery.isPlainObject( context ) ) {
757 selector = [ document.createElement( ret[1] ) ];
758 jQuery.fn.attr.call( selector, context, true );
761 selector = [ doc.createElement( ret[1] ) ];
765 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
766 selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
769 return jQuery.merge( this, selector );
773 elem = document.getElementById( match[2] );
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 );
784 // Otherwise, we inject the element directly into the jQuery object
789 this.context = document;
790 this.selector = selector;
794 // HANDLE: $(expr, $(...))
795 } else if ( !context || context.jquery ) {
796 return ( context || rootjQuery ).find( selector );
798 // HANDLE: $(expr, context)
799 // (which is just equivalent to: $(context).find(expr)
801 return this.constructor( context ).find( selector );
804 // HANDLE: $(function)
805 // Shortcut for document ready
806 } else if ( jQuery.isFunction( selector ) ) {
807 return rootjQuery.ready( selector );
810 if ( selector.selector !== undefined ) {
811 this.selector = selector.selector;
812 this.context = selector.context;
815 return jQuery.makeArray( selector, this );
818 // Start with an empty selector
821 // The current version of jQuery being used
824 // The default length of a jQuery object is 0
827 // The number of elements contained in the matched element set
832 toArray: function() {
833 return slice.call( this, 0 );
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 ) {
841 // Return a 'clean' array
844 // Return just the object
845 ( num < 0 ? this[ this.length + num ] : this[ num ] );
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();
854 if ( jQuery.isArray( elems ) ) {
855 push.apply( ret, elems );
858 jQuery.merge( ret, elems );
861 // Add the old object onto the stack (as a reference)
862 ret.prevObject = this;
864 ret.context = this.context;
866 if ( name === "find" ) {
867 ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
869 ret.selector = this.selector + "." + name + "(" + selector + ")";
872 // Return the newly-formed element set
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 );
883 ready: function( fn ) {
884 // Attach the listeners
896 this.slice( i, +i + 1 );
904 return this.eq( -1 );
908 return this.pushStack( slice.apply( this, arguments ),
909 "slice", slice.call(arguments).join(",") );
912 map: function( callback ) {
913 return this.pushStack( jQuery.map(this, function( elem, i ) {
914 return callback.call( elem, i, elem );
919 return this.prevObject || this.constructor(null);
922 // For internal use only.
923 // Behaves like an Array's method, not like a jQuery method.
929 // Give the init function the jQuery prototype for later instantiation
930 jQuery.fn.init.prototype = jQuery.fn;
932 jQuery.extend = jQuery.fn.extend = function() {
933 var options, name, src, copy, copyIsArray, clone,
934 target = arguments[0] || {},
936 length = arguments.length,
939 // Handle a deep copy situation
940 if ( typeof target === "boolean" ) {
942 target = arguments[1] || {};
943 // skip the boolean and the target
947 // Handle case when target is a string or something (possible in deep copy)
948 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
952 // extend jQuery itself if only one argument is passed
953 if ( length === i ) {
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 ];
966 // Prevent never-ending loop
967 if ( target === copy ) {
971 // Recurse if we're merging plain objects or arrays
972 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
975 clone = src && jQuery.isArray(src) ? src : [];
978 clone = src && jQuery.isPlainObject(src) ? src : {};
981 // Never move original objects, clone them
982 target[ name ] = jQuery.extend( deep, clone, copy );
984 // Don't bring in undefined values
985 } else if ( copy !== undefined ) {
986 target[ name ] = copy;
992 // Return the modified object
997 noConflict: function( deep ) {
998 if ( window.$ === jQuery ) {
1002 if ( deep && window.jQuery === jQuery ) {
1003 window.jQuery = _jQuery;
1009 // Is the DOM ready to be used? Set to true once it occurs.
1012 // A counter to track how many items to wait for before
1013 // the ready event fires. See #6781
1016 // Hold (or release) the ready event
1017 holdReady: function( hold ) {
1021 jQuery.ready( true );
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 );
1034 // Remember that the DOM is ready
1035 jQuery.isReady = true;
1037 // If a normal DOM Ready event fired, decrement, and wait if need be
1038 if ( wait !== true && --jQuery.readyWait > 0 ) {
1042 // If there are functions bound, to execute
1043 readyList.fireWith( document, [ jQuery ] );
1045 // Trigger any bound ready events
1046 if ( jQuery.fn.trigger ) {
1047 jQuery( document ).trigger( "ready" ).unbind( "ready" );
1052 bindReady: function() {
1057 readyList = jQuery.Callbacks( "once memory" );
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 );
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 );
1071 // A fallback to window.onload, that will always work
1072 window.addEventListener( "load", jQuery.ready, false );
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 );
1080 // A fallback to window.onload, that will always work
1081 window.attachEvent( "onload", jQuery.ready );
1083 // If IE and not a frame
1084 // continually check to see if the document is ready
1085 var toplevel = false;
1088 toplevel = window.frameElement == null;
1091 if ( document.documentElement.doScroll && toplevel ) {
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";
1104 isArray: Array.isArray || function( obj ) {
1105 return jQuery.type(obj) === "array";
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;
1113 isNumeric: function( obj ) {
1114 return obj != null && rdigit.test( obj ) && !isNaN( obj );
1117 type: function( obj ) {
1118 return obj == null ?
1120 class2type[ toString.call(obj) ] || "object";
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 ) ) {
1132 // Not own constructor property must be Object
1133 if ( obj.constructor &&
1134 !hasOwn.call(obj, "constructor") &&
1135 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
1139 // IE8,9 Will throw exceptions on certain host objects #9897
1143 // Own properties are enumerated firstly, so to speed up,
1144 // if last one is own, then all properties are own.
1147 for ( key in obj ) {}
1149 return key === undefined || hasOwn.call( obj, key );
1152 isEmptyObject: function( obj ) {
1153 for ( var name in obj ) {
1159 error: function( msg ) {
1163 parseJSON: function( data ) {
1164 if ( typeof data !== "string" || !data ) {
1168 // Make sure leading/trailing whitespace is removed (IE can't handle it)
1169 data = jQuery.trim( data );
1171 // Attempt to parse using the native JSON parser first
1172 if ( window.JSON && window.JSON.parse ) {
1173 return window.JSON.parse( data );
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, "")) ) {
1182 return ( new Function( "return " + data ) )();
1185 jQuery.error( "Invalid JSON: " + data );
1188 // Cross-browser xml parsing
1189 parseXML: function( data ) {
1192 if ( window.DOMParser ) { // Standard
1193 tmp = new DOMParser();
1194 xml = tmp.parseFromString( data , "text/xml" );
1196 xml = new ActiveXObject( "Microsoft.XMLDOM" );
1197 xml.async = "false";
1198 xml.loadXML( data );
1203 if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
1204 jQuery.error( "Invalid XML: " + data );
1209 noop: function() {},
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 );
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 );
1231 nodeName: function( elem, name ) {
1232 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
1235 // args is for internal usage only
1236 each: function( object, callback, args ) {
1238 length = object.length,
1239 isObj = length === undefined || jQuery.isFunction( object );
1243 for ( name in object ) {
1244 if ( callback.apply( object[ name ], args ) === false ) {
1249 for ( ; i < length; ) {
1250 if ( callback.apply( object[ i++ ], args ) === false ) {
1256 // A special, fast, case for the most common use of each
1259 for ( name in object ) {
1260 if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
1265 for ( ; i < length; ) {
1266 if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
1276 // Use native String.trim function wherever possible
1279 return text == null ?
1284 // Otherwise use our own trimming functionality
1286 return text == null ?
1288 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
1291 // results is for internal usage only
1292 makeArray: function( array, results ) {
1293 var ret = results || [];
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 );
1302 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
1303 push.call( ret, array );
1305 jQuery.merge( ret, array );
1312 inArray: function( elem, array, i ) {
1317 return indexOf.call( array, elem, i );
1321 i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
1323 for ( ; i < len; i++ ) {
1324 // Skip accessing in sparse arrays
1325 if ( i in array && array[ i ] === elem ) {
1334 merge: function( first, second ) {
1335 var i = first.length,
1338 if ( typeof second.length === "number" ) {
1339 for ( var l = second.length; j < l; j++ ) {
1340 first[ i++ ] = second[ j ];
1344 while ( second[j] !== undefined ) {
1345 first[ i++ ] = second[ j++ ];
1354 grep: function( elems, callback, inv ) {
1355 var ret = [], retVal;
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 ] );
1370 // arg is for internal usage only
1371 map: function( elems, callback, arg ) {
1372 var value, key, ret = [],
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 ) ) ;
1378 // Go through the array, translating each of the items to their
1380 for ( ; i < length; i++ ) {
1381 value = callback( elems[ i ], i, arg );
1383 if ( value != null ) {
1384 ret[ ret.length ] = value;
1388 // Go through every key on the object,
1390 for ( key in elems ) {
1391 value = callback( elems[ key ], key, arg );
1393 if ( value != null ) {
1394 ret[ ret.length ] = value;
1399 // Flatten any nested arrays
1400 return ret.concat.apply( [], ret );
1403 // A global GUID counter for objects
1406 // Bind a function to a context, optionally partially applying any
1408 proxy: function( fn, context ) {
1409 if ( typeof context === "string" ) {
1410 var tmp = fn[ context ];
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 ) ) {
1422 var args = slice.call( arguments, 2 ),
1423 proxy = function() {
1424 return fn.apply( context, args.concat( slice.call( arguments ) ) );
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++;
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;
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 );
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);
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 );
1458 // Getting an attribute
1459 return length ? fn( elems[0], key ) : undefined;
1463 return ( new Date() ).getTime();
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();
1471 var match = rwebkit.exec( ua ) ||
1472 ropera.exec( ua ) ||
1474 ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
1477 return { browser: match[1] || "", version: match[2] || "0" };
1481 function jQuerySub( selector, context ) {
1482 return new jQuerySub.fn.init( selector, context );
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 );
1494 return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
1496 jQuerySub.fn.init.prototype = jQuerySub.fn;
1497 var rootjQuerySub = jQuerySub(document);
1504 // Populate the class2type map
1505 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
1506 class2type[ "[object " + name + "]" ] = name.toLowerCase();
1509 browserMatch = jQuery.uaMatch( userAgent );
1510 if ( browserMatch.browser ) {
1511 jQuery.browser[ browserMatch.browser ] = true;
1512 jQuery.browser.version = browserMatch.version;
1515 // Deprecated, use jQuery.browser.webkit instead
1516 if ( jQuery.browser.webkit ) {
1517 jQuery.browser.safari = true;
1520 // IE doesn't match non-breaking spaces with \s
1521 if ( rnotwhite.test( "\xA0" ) ) {
1522 trimLeft = /^[\s\xA0]+/;
1523 trimRight = /[\s\xA0]+$/;
1526 // All jQuery objects should point back to these
1527 rootjQuery = jQuery(document);
1529 // Cleanup functions for the document ready method
1530 if ( document.addEventListener ) {
1531 DOMContentLoaded = function() {
1532 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
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 );
1546 // The DOM ready check for Internet Explorer
1547 function doScrollCheck() {
1548 if ( jQuery.isReady ) {
1553 // If IE is used, use the trick by Diego Perini
1554 // http://javascript.nwbox.com/IEContentLoaded/
1555 document.documentElement.doScroll("left");
1557 setTimeout( doScrollCheck, 1 );
1561 // and execute any waiting functions
1565 // Expose jQuery as an AMD module, but only for AMD loaders that
1566 // understand the issues with loading multiple versions of jQuery
1567 // in a page that all might call define(). The loader will indicate
1568 // they have special allowances for multiple jQuery versions by
1569 // specifying define.amd.jQuery = true. Register as a named module,
1570 // since jQuery can be concatenated with other files that may use define,
1571 // but not use a proper concatenation script that understands anonymous
1572 // AMD modules. A named AMD is safest and most robust way to register.
1573 // Lowercase jquery is used because AMD module names are derived from
1574 // file names, and jQuery is normally delivered in a lowercase file name.
1575 if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
1576 define( "jquery", [], function () { return jQuery; } );
1584 // String to Object flags format cache
1585 var flagsCache = {};
1587 // Convert String-formatted flags into Object-formatted ones and store in cache
1588 function createFlags( flags ) {
1589 var object = flagsCache[ flags ] = {},
1591 flags = flags.split( /\s+/ );
1592 for ( i = 0, length = flags.length; i < length; i++ ) {
1593 object[ flags[i] ] = true;
1599 * Create a callback list using the following parameters:
1601 * flags: an optional list of space-separated flags that will change how
1602 * the callback list behaves
1604 * By default a callback list will act like an event callback list and can be
1605 * "fired" multiple times.
1609 * once: will ensure the callback list can only be fired once (like a Deferred)
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)
1615 * unique: will ensure a callback can only be added once (no duplicate in the list)
1617 * stopOnFalse: interrupt callings when a callback returns false
1620 jQuery.Callbacks = function( flags ) {
1622 // Convert flags from String-formatted to Object-formatted
1623 // (we check in cache first)
1624 flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
1626 var // Actual callback list
1628 // Stack of fire calls for repeatable lists
1630 // Last fire value (for non-forgettable lists)
1632 // Flag to know if list is currently firing
1634 // First callback to fire (used internally by add and fireWith)
1636 // End of the loop when firing
1638 // Index of currently firing callback (modified by remove if needed)
1640 // Add one or several callbacks to the list
1641 add = function( args ) {
1647 for ( i = 0, length = args.length; i < length; i++ ) {
1649 type = jQuery.type( elem );
1650 if ( type === "array" ) {
1651 // Inspect recursively
1653 } else if ( type === "function" ) {
1654 // Add if not in unique mode and callback is not in
1655 if ( !flags.unique || !self.has( elem ) ) {
1662 fire = function( context, args ) {
1664 memory = !flags.memory || [ context, args ];
1666 firingIndex = 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
1677 if ( !flags.once ) {
1678 if ( stack && stack.length ) {
1679 memory = stack.shift();
1680 self.fireWith( memory[ 0 ], memory[ 1 ] );
1682 } else if ( memory === true ) {
1689 // Actual Callbacks object
1691 // Add a callback or a collection of callbacks to the list
1694 var length = list.length;
1696 // Do we need to add the callbacks to the
1697 // current firing batch?
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 ] );
1710 // Remove a callback from the list
1711 remove: function() {
1713 var args = arguments,
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
1721 if ( i <= firingLength ) {
1723 if ( i <= firingIndex ) {
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 ) {
1741 // Control if a given callback is in the list
1742 has: function( fn ) {
1745 length = list.length;
1746 for ( ; i < length; i++ ) {
1747 if ( fn === list[ i ] ) {
1754 // Remove all callbacks from the list
1759 // Have the list do nothing anymore
1760 disable: function() {
1761 list = stack = memory = undefined;
1765 disabled: function() {
1768 // Lock the list in its current state
1771 if ( !memory || memory === true ) {
1777 locked: function() {
1780 // Call all callbacks with the given context and arguments
1781 fireWith: function( context, args ) {
1784 if ( !flags.once ) {
1785 stack.push( [ context, args ] );
1787 } else if ( !( flags.once && memory ) ) {
1788 fire( context, args );
1793 // Call all the callbacks with the given arguments
1795 self.fireWith( this, arguments );
1798 // To know if the callbacks have already been called at least once
1810 var // Static reference to slice
1811 sliceDeferred = [].slice;
1815 Deferred: function( func ) {
1816 var doneList = jQuery.Callbacks( "once memory" ),
1817 failList = jQuery.Callbacks( "once memory" ),
1818 progressList = jQuery.Callbacks( "memory" ),
1823 notify: progressList
1828 progress: progressList.add,
1835 isResolved: doneList.fired,
1836 isRejected: failList.fired,
1838 then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
1839 deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
1842 always: function() {
1843 return deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
1845 pipe: function( fnDone, fnFail, fnProgress ) {
1846 return jQuery.Deferred(function( newDefer ) {
1848 done: [ fnDone, "resolve" ],
1849 fail: [ fnFail, "reject" ],
1850 progress: [ fnProgress, "notify" ]
1851 }, function( handler, data ) {
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 );
1861 newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
1865 deferred[ handler ]( newDefer[ action ] );
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 ) {
1876 for ( var key in promise ) {
1877 obj[ key ] = promise[ key ];
1883 deferred = promise.promise({}),
1886 for ( key in lists ) {
1887 deferred[ key ] = lists[ key ].fire;
1888 deferred[ key + "With" ] = lists[ key ].fireWith;
1892 deferred.done( function() {
1894 }, failList.disable, progressList.lock ).fail( function() {
1896 }, doneList.disable, progressList.lock );
1898 // Call given func if any
1900 func.call( deferred, deferred );
1908 when: function( firstParam ) {
1909 var args = sliceDeferred.call( arguments, 0 ),
1911 length = args.length,
1912 pValues = new Array( length ),
1915 deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
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 );
1927 function progressFunc( i ) {
1928 return function( value ) {
1929 pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
1930 deferred.notifyWith( promise, pValues );
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) );
1942 deferred.resolveWith( deferred, args );
1944 } else if ( deferred !== firstParam ) {
1945 deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
1954 jQuery.support = (function() {
1956 var div = document.createElement( "div" ),
1957 documentElement = document.documentElement,
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>";
1981 all = div.getElementsByTagName( "*" );
1982 a = div.getElementsByTagName( "a" )[ 0 ];
1984 // Can't get basic test support
1985 if ( !all || !all.length || !a ) {
1989 // First batch of supports tests
1990 select = document.createElement( "select" );
1991 opt = select.appendChild( document.createElement("option") );
1992 input = div.getElementsByTagName( "input" )[ 0 ];
1995 // IE strips leading whitespace when .innerHTML is used
1996 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1998 // Make sure that tbody elements aren't automatically inserted
1999 // IE will insert them into empty tables
2000 tbody: !div.getElementsByTagName( "tbody" ).length,
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,
2006 // Get the style information from getAttribute
2007 // (IE uses .cssText instead)
2008 style: /top/.test( a.getAttribute("style") ),
2010 // Make sure that URLs aren't manipulated
2011 // (IE normalizes it by default)
2012 hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
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 ),
2019 // Verify style float existence
2020 // (IE uses styleFloat instead of cssFloat)
2021 cssFloat: !!a.style.cssFloat,
2023 // Make sure unknown elements (like HTML5 elems) are handled appropriately
2024 unknownElems: !!div.getElementsByTagName( "nav" ).length,
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" ),
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,
2035 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
2036 getSetAttribute: div.className !== "t",
2038 // Tests for enctype support on a form(#6743)
2039 enctype: !!document.createElement("form").enctype,
2041 // Will be defined later
2042 submitBubbles: true,
2043 changeBubbles: true,
2044 focusinBubbles: false,
2045 deleteExpando: true,
2047 inlineBlockNeedsLayout: false,
2048 shrinkWrapBlocks: false,
2049 reliableMarginRight: true
2052 // Make sure checked status is properly cloned
2053 input.checked = true;
2054 support.noCloneChecked = input.cloneNode( true ).checked;
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;
2061 // Test to see if it's possible to delete an expando from an element
2062 // Fails in Internet Explorer
2066 support.deleteExpando = false;
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;
2075 div.cloneNode( true ).fireEvent( "onclick" );
2078 // Check if a radio maintains its value
2079 // after being appended to the DOM
2080 input = document.createElement("input");
2082 input.setAttribute("type", "radio");
2083 support.radioValue = input.value === "t";
2085 input.setAttribute("checked", "checked");
2086 div.appendChild( input );
2087 fragment = document.createDocumentFragment();
2088 fragment.appendChild( div.lastChild );
2090 // WebKit doesn't clone checked state correctly in fragments
2091 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
2095 // Figure out if the W3C box model works as expected
2096 div.style.width = div.style.paddingLeft = "1px";
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’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",
2115 jQuery.extend( testElementStyle, {
2116 position: "absolute",
2121 for ( i in testElementStyle ) {
2122 testElement.style[ i ] = testElementStyle[ i ];
2124 testElement.appendChild( div );
2125 testElementParent = body || documentElement;
2126 testElementParent.insertBefore( testElement, testElementParent.firstChild );
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;
2132 support.boxModel = div.offsetWidth === 2;
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
2138 // (IE < 8 does this)
2139 div.style.display = "inline";
2141 support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
2143 // Check if elements with layout shrink-wrap their children
2145 div.style.display = "";
2146 div.innerHTML = "<div style='width:4px;'></div>";
2147 support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
2150 div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
2151 tds = div.getElementsByTagName( "td" );
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 );
2162 tds[ 0 ].style.display = "";
2163 tds[ 1 ].style.display = "none";
2165 // Check if empty table cells still have offsetWidth/Height
2166 // (IE < 8 fail this test)
2167 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
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;
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 ) {
2196 eventName = "on" + i;
2197 isSupported = ( eventName in div );
2198 if ( !isSupported ) {
2199 div.setAttribute( eventName, "return;" );
2200 isSupported = ( typeof div[ eventName ] === "function" );
2202 support[ i + "Bubbles" ] = isSupported;
2206 // Run fixed position tests at doc ready to avoid a crash
2207 // related to the invisible body in IE8
2209 var container, outer, inner, table, td, offsetSupport,
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>";
2218 // Reconstruct a container
2219 body = document.getElementsByTagName("body")[0];
2221 // Return for frameset docs that don't have a body
2222 // These tests cannot be done
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 );
2230 // Construct a test element
2231 testElement = document.createElement("div");
2232 testElement.style.cssText = ptlm + vb;
2234 testElement.innerHTML = html;
2235 container.appendChild( testElement );
2236 outer = testElement.firstChild;
2237 inner = outer.firstChild;
2238 td = outer.nextSibling.firstChild.firstChild;
2241 doesNotAddBorder: ( inner.offsetTop !== 5 ),
2242 doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
2245 inner.style.position = "fixed";
2246 inner.style.top = "20px";
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 = "";
2252 outer.style.overflow = "hidden";
2253 outer.style.position = "relative";
2255 offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
2256 offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
2258 body.removeChild( container );
2259 testElement = container = null;
2261 jQuery.extend( support, offsetSupport );
2264 testElement.innerHTML = "";
2265 testElementParent.removeChild( testElement );
2267 // Null connected elements to avoid leaks in IE
2268 testElement = fragment = select = opt = body = marginDiv = div = input = null;
2273 // Keep track of boxModel
2274 jQuery.boxModel = jQuery.support.boxModel;
2279 var rbrace = /^(?:\{.*\}|\[.*\])$/,
2280 rmultiDash = /([A-Z])/g;
2285 // Please use with caution
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, "" ),
2292 // The following elements throw uncatchable exceptions if you
2293 // attempt to add expando properties to them.
2296 // Ban all objects except for Flash (which handle expandos)
2297 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
2301 hasData: function( elem ) {
2302 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
2303 return !!elem && !isEmptyDataObject( elem );
2306 data: function( elem, name, data, pvt /* Internal Use Only */ ) {
2307 if ( !jQuery.acceptData( elem ) ) {
2311 var privateCache, thisCache, ret,
2312 internalKey = jQuery.expando,
2313 getByName = typeof name === "string",
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,
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,
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";
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 ) {
2335 // Only DOM nodes need a new unique ID for each element since their data
2336 // ends up in the global cache
2338 elem[ jQuery.expando ] = id = ++jQuery.uuid;
2340 id = jQuery.expando;
2344 if ( !cache[ id ] ) {
2347 // Avoids exposing jQuery metadata on plain JS objects when the object
2348 // is serialized using JSON.stringify
2350 cache[ id ].toJSON = jQuery.noop;
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" ) {
2358 cache[ id ] = jQuery.extend( cache[ id ], name );
2360 cache[ id ].data = jQuery.extend( cache[ id ].data, name );
2364 privateCache = thisCache = cache[ id ];
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
2370 if ( !thisCache.data ) {
2371 thisCache.data = {};
2374 thisCache = thisCache.data;
2377 if ( data !== undefined ) {
2378 thisCache[ jQuery.camelCase( name ) ] = data;
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;
2387 // Check for both converted-to-camel and non-converted data property names
2388 // If a data property was specified
2391 // First Try to find as-is property data
2392 ret = thisCache[ name ];
2394 // Test for null|undefined property data
2395 if ( ret == null ) {
2397 // Try to find the camelCased property
2398 ret = thisCache[ jQuery.camelCase( name ) ];
2407 removeData: function( elem, name, pvt /* Internal Use Only */ ) {
2408 if ( !jQuery.acceptData( elem ) ) {
2412 var thisCache, i, l,
2414 // Reference to internal data cache key
2415 internalKey = jQuery.expando,
2417 isNode = elem.nodeType,
2419 // See jQuery.data for more information
2420 cache = isNode ? jQuery.cache : elem,
2422 // See jQuery.data for more information
2423 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
2425 // If there is already no cache entry for this object, there is no
2426 // purpose in continuing
2427 if ( !cache[ id ] ) {
2433 thisCache = pvt ? cache[ id ] : cache[ id ].data;
2437 // Support space separated names
2438 if ( jQuery.isArray( name ) ) {
2440 } else if ( name in thisCache ) {
2444 // split the camel cased version by spaces
2445 name = jQuery.camelCase( name );
2446 if ( name in thisCache ) {
2449 name = name.split( " " );
2453 for ( i = 0, l = name.length; i < l; i++ ) {
2454 delete thisCache[ name[i] ];
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 ) ) {
2465 // See jQuery.data for more information
2467 delete cache[ id ].data;
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 ]) ) {
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
2479 // Ensure that `cache` is not a window object #10080
2480 if ( jQuery.support.deleteExpando || !cache.setInterval ) {
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
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 );
2497 elem[ jQuery.expando ] = null;
2502 // For internal use only.
2503 _data: function( elem, name, data ) {
2504 return jQuery.data( elem, name, data, true );
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() ];
2513 return !(match === true || elem.getAttribute("classid") !== match);
2522 data: function( key, value ) {
2523 var parts, attr, name,
2526 if ( typeof key === "undefined" ) {
2527 if ( this.length ) {
2528 data = jQuery.data( this[0] );
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;
2535 if ( name.indexOf( "data-" ) === 0 ) {
2536 name = jQuery.camelCase( name.substring(5) );
2538 dataAttr( this[0], name, data[ name ] );
2541 jQuery._data( this[0], "parsedAttrs", true );
2547 } else if ( typeof key === "object" ) {
2548 return this.each(function() {
2549 jQuery.data( this, key );
2553 parts = key.split(".");
2554 parts[1] = parts[1] ? "." + parts[1] : "";
2556 if ( value === undefined ) {
2557 data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
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 );
2565 return data === undefined && parts[1] ?
2566 this.data( parts[0] ) :
2570 return this.each(function() {
2571 var $this = jQuery( this ),
2572 args = [ parts[0], value ];
2574 $this.triggerHandler( "setData" + parts[1] + "!", args );
2575 jQuery.data( this, key, value );
2576 $this.triggerHandler( "changeData" + parts[1] + "!", args );
2581 removeData: function( key ) {
2582 return this.each(function() {
2583 jQuery.removeData( this, key );
2588 function dataAttr( elem, key, data ) {
2589 // If nothing was found internally, try to fetch any
2590 // data from the HTML5 data-* attribute
2591 if ( data === undefined && elem.nodeType === 1 ) {
2593 var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
2595 data = elem.getAttribute( name );
2597 if ( typeof data === "string" ) {
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 ) :
2607 // Make sure we set the data so it isn't changed later
2608 jQuery.data( elem, key, data );
2618 // checks a cache object for emptiness
2619 function isEmptyDataObject( obj ) {
2620 for ( var name in obj ) {
2622 // if the public data object is empty, the private is still empty
2623 if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
2626 if ( name !== "toJSON" ) {
2637 function handleQueueMarkDefer( elem, type, src ) {
2638 var deferDataKey = type + "defer",
2639 queueDataKey = type + "queue",
2640 markDataKey = type + "mark",
2641 defer = jQuery._data( elem, deferDataKey );
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 );
2659 _mark: function( elem, type ) {
2661 type = ( type || "fx" ) + "mark";
2662 jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
2666 _unmark: function( force, elem, type ) {
2667 if ( force !== true ) {
2673 type = type || "fx";
2674 var key = type + "mark",
2675 count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
2677 jQuery._data( elem, key, count );
2679 jQuery.removeData( elem, key, true );
2680 handleQueueMarkDefer( elem, type, "mark" );
2685 queue: function( elem, type, data ) {
2688 type = ( type || "fx" ) + "queue";
2689 q = jQuery._data( elem, type );
2691 // Speed up dequeue by getting out quickly if this is just a lookup
2693 if ( !q || jQuery.isArray(data) ) {
2694 q = jQuery._data( elem, type, jQuery.makeArray(data) );
2703 dequeue: function( elem, type ) {
2704 type = type || "fx";
2706 var queue = jQuery.queue( elem, type ),
2710 // If the fx queue is dequeued, always remove the progress sentinel
2711 if ( fn === "inprogress" ) {
2716 // Add a progress sentinel to prevent the fx queue from being
2717 // automatically dequeued
2718 if ( type === "fx" ) {
2719 queue.unshift( "inprogress" );
2722 jQuery._data( elem, type + ".run", hooks );
2723 fn.call( elem, function() {
2724 jQuery.dequeue( elem, type );
2728 if ( !queue.length ) {
2729 jQuery.removeData( elem, type + "queue " + type + ".run", true );
2730 handleQueueMarkDefer( elem, type, "queue" );
2736 queue: function( type, data ) {
2737 if ( typeof type !== "string" ) {
2742 if ( data === undefined ) {
2743 return jQuery.queue( this[0], type );
2745 return this.each(function() {
2746 var queue = jQuery.queue( this, type, data );
2748 if ( type === "fx" && queue[0] !== "inprogress" ) {
2749 jQuery.dequeue( this, type );
2753 dequeue: function( type ) {
2754 return this.each(function() {
2755 jQuery.dequeue( this, type );
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";
2764 return this.queue( type, function( next, hooks ) {
2765 var timeout = setTimeout( next, time );
2766 hooks.stop = function() {
2767 clearTimeout( timeout );
2771 clearQueue: function( type ) {
2772 return this.queue( type || "fx", [] );
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" ) {
2781 type = type || "fx";
2782 var defer = jQuery.Deferred(),
2784 i = elements.length,
2786 deferDataKey = type + "defer",
2787 queueDataKey = type + "queue",
2788 markDataKey = type + "mark",
2790 function resolve() {
2791 if ( !( --count ) ) {
2792 defer.resolveWith( elements, [ elements ] );
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 ) )) {
2805 return defer.promise();
2812 var rclass = /[\n\t\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;
2823 attr: function( name, value ) {
2824 return jQuery.access( this, name, value, true, jQuery.attr );
2827 removeAttr: function( name ) {
2828 return this.each(function() {
2829 jQuery.removeAttr( this, name );
2833 prop: function( name, value ) {
2834 return jQuery.access( this, name, value, true, jQuery.prop );
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)
2842 this[ name ] = undefined;
2843 delete this[ name ];
2848 addClass: function( value ) {
2849 var classNames, i, l, elem,
2852 if ( jQuery.isFunction( value ) ) {
2853 return this.each(function( j ) {
2854 jQuery( this ).addClass( value.call(this, j, this.className) );
2858 if ( value && typeof value === "string" ) {
2859 classNames = value.split( rspace );
2861 for ( i = 0, l = this.length; i < l; i++ ) {
2864 if ( elem.nodeType === 1 ) {
2865 if ( !elem.className && classNames.length === 1 ) {
2866 elem.className = value;
2869 setClass = " " + elem.className + " ";
2871 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2872 if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
2873 setClass += classNames[ c ] + " ";
2876 elem.className = jQuery.trim( setClass );
2885 removeClass: function( value ) {
2886 var classNames, i, l, elem, className, c, cl;
2888 if ( jQuery.isFunction( value ) ) {
2889 return this.each(function( j ) {
2890 jQuery( this ).removeClass( value.call(this, j, this.className) );
2894 if ( (value && typeof value === "string") || value === undefined ) {
2895 classNames = ( value || "" ).split( rspace );
2897 for ( i = 0, l = this.length; i < l; i++ ) {
2900 if ( elem.nodeType === 1 && elem.className ) {
2902 className = (" " + elem.className + " ").replace( rclass, " " );
2903 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
2904 className = className.replace(" " + classNames[ c ] + " ", " ");
2906 elem.className = jQuery.trim( className );
2909 elem.className = "";
2918 toggleClass: function( value, stateVal ) {
2919 var type = typeof value,
2920 isBool = typeof stateVal === "boolean";
2922 if ( jQuery.isFunction( value ) ) {
2923 return this.each(function( i ) {
2924 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2928 return this.each(function() {
2929 if ( type === "string" ) {
2930 // toggle individual class names
2933 self = jQuery( this ),
2935 classNames = value.split( rspace );
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 );
2943 } else if ( type === "undefined" || type === "boolean" ) {
2944 if ( this.className ) {
2945 // store className if set
2946 jQuery._data( this, "__className__", this.className );
2949 // toggle whole className
2950 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2955 hasClass: function( selector ) {
2956 var className = " " + selector + " ",
2959 for ( ; i < l; i++ ) {
2960 if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2968 val: function( value ) {
2969 var hooks, ret, isFunction,
2972 if ( !arguments.length ) {
2974 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
2976 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
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;
2992 isFunction = jQuery.isFunction( value );
2994 return this.each(function( i ) {
2995 var self = jQuery(this), val;
2997 if ( this.nodeType !== 1 ) {
3002 val = value.call( this, i, self.val() );
3007 // Treat null/undefined as ""; convert numbers to string
3008 if ( val == null ) {
3010 } else if ( typeof val === "number" ) {
3012 } else if ( jQuery.isArray( val ) ) {
3013 val = jQuery.map(val, function ( value ) {
3014 return value == null ? "" : value + "";
3018 hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
3020 // If set returns undefined, fall back to normal setting
3021 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
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;
3039 get: function( elem ) {
3040 var value, i, max, option,
3041 index = elem.selectedIndex,
3043 options = elem.options,
3044 one = elem.type === "select-one";
3046 // Nothing was selected
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 ];
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" )) ) {
3061 // Get the specific value for the option
3062 value = jQuery( option ).val();
3064 // We don't need an array for one selects
3069 // Multi-Selects return an array
3070 values.push( value );
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();
3082 set: function( elem, value ) {
3083 var values = jQuery.makeArray( value );
3085 jQuery(elem).find("option").each(function() {
3086 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
3089 if ( !values.length ) {
3090 elem.selectedIndex = -1;
3108 attr: function( elem, name, value, pass ) {
3109 var ret, hooks, notxml,
3110 nType = elem.nodeType;
3112 // don't get/set attributes on text, comment and attribute nodes
3113 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
3117 if ( pass && name in jQuery.attrFn ) {
3118 return jQuery( elem )[ name ]( value );
3121 // Fallback to prop when attributes are not supported
3122 if ( !("getAttribute" in elem) ) {
3123 return jQuery.prop( elem, name, value );
3126 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
3128 // All attributes are lowercase
3129 // Grab necessary hook if one is defined
3131 name = name.toLowerCase();
3132 hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
3135 if ( value !== undefined ) {
3137 if ( value === null ) {
3138 jQuery.removeAttr( elem, name );
3141 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
3145 elem.setAttribute( name, "" + value );
3149 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
3154 ret = elem.getAttribute( name );
3156 // Non-existent attributes return null, we normalize to undefined
3157 return ret === null ?
3163 removeAttr: function( elem, value ) {
3164 var propName, attrNames, name, l,
3167 if ( elem.nodeType === 1 ) {
3168 attrNames = ( value || "" ).split( rspace );
3169 l = attrNames.length;
3171 for ( ; i < l; i++ ) {
3172 name = attrNames[ i ].toLowerCase();
3173 propName = jQuery.propFix[ name ] || name;
3175 // See #9699 for explanation of this approach (setting first, then removal)
3176 jQuery.attr( elem, name, "" );
3177 elem.removeAttribute( getSetAttribute ? name : propName );
3179 // Set corresponding property to false for boolean attributes
3180 if ( rboolean.test( name ) && propName in elem ) {
3181 elem[ propName ] = false;
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 );
3206 // Use the value property for back compat
3207 // Use the nodeHook for button elements in IE6/7 (#1954)
3209 get: function( elem, name ) {
3210 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
3211 return nodeHook.get( elem, name );
3213 return name in elem ?
3217 set: function( elem, value, name ) {
3218 if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
3219 return nodeHook.set( elem, value, name );
3221 // Does not return so that setAttribute is also used
3228 tabindex: "tabIndex",
3229 readonly: "readOnly",
3231 "class": "className",
3232 maxlength: "maxLength",
3233 cellspacing: "cellSpacing",
3234 cellpadding: "cellPadding",
3238 frameborder: "frameBorder",
3239 contenteditable: "contentEditable"
3242 prop: function( elem, name, value ) {
3243 var ret, hooks, notxml,
3244 nType = elem.nodeType;
3246 // don't get/set properties on text, comment and attribute nodes
3247 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
3251 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
3254 // Fix name and attach hooks
3255 name = jQuery.propFix[ name ] || name;
3256 hooks = jQuery.propHooks[ name ];
3259 if ( value !== undefined ) {
3260 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
3264 return ( elem[ name ] = value );
3268 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
3272 return elem[ name ];
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");
3284 return attributeNode && attributeNode.specified ?
3285 parseInt( attributeNode.value, 10 ) :
3286 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
3294 // Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
3295 jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
3297 // Hook for boolean attributes
3299 get: function( elem, name ) {
3300 // Align boolean attributes with corresponding properties
3301 // Fall back to attribute presence where some booleans are not supported
3303 property = jQuery.prop( elem, name );
3304 return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
3305 name.toLowerCase() :
3308 set: function( elem, value, name ) {
3310 if ( value === false ) {
3311 // Remove boolean attributes when set to false
3312 jQuery.removeAttr( elem, name );
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;
3322 elem.setAttribute( name, name.toLowerCase() );
3328 // IE6/7 do not support getting/setting some attributes with get/setAttribute
3329 if ( !getSetAttribute ) {
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 ) {
3341 ret = elem.getAttributeNode( name );
3342 return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
3346 set: function( elem, value, name ) {
3347 // Set the existing or create a new attribute node
3348 var ret = elem.getAttributeNode( name );
3350 ret = document.createAttribute( name );
3351 elem.setAttributeNode( ret );
3353 return ( ret.nodeValue = value + "" );
3357 // Apply the nodeHook to tabindex
3358 jQuery.attrHooks.tabindex.set = nodeHook.set;
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" );
3373 // Set contenteditable to false on removals(#10429)
3374 // Setting to empty string throws an error as an invalid value
3375 jQuery.attrHooks.contenteditable = {
3377 set: function( elem, value, name ) {
3378 if ( value === "" ) {
3381 nodeHook.set( elem, value, name );
3387 // Some attributes require a special call on IE
3388 if ( !jQuery.support.hrefNormalized ) {
3389 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
3390 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
3391 get: function( elem ) {
3392 var ret = elem.getAttribute( name, 2 );
3393 return ret === null ? undefined : ret;
3399 if ( !jQuery.support.style ) {
3400 jQuery.attrHooks.style = {
3401 get: function( elem ) {
3402 // Return undefined in the case of empty string
3403 // Normalize to lowercase since IE uppercases css property names
3404 return elem.style.cssText.toLowerCase() || undefined;
3406 set: function( elem, value ) {
3407 return ( elem.style.cssText = "" + value );
3412 // Safari mis-reports the default selected property of an option
3413 // Accessing the parent's selectedIndex property fixes it
3414 if ( !jQuery.support.optSelected ) {
3415 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
3416 get: function( elem ) {
3417 var parent = elem.parentNode;
3420 parent.selectedIndex;
3422 // Make sure that it also works with optgroups, see #5701
3423 if ( parent.parentNode ) {
3424 parent.parentNode.selectedIndex;
3432 // IE6/7 call enctype encoding
3433 if ( !jQuery.support.enctype ) {
3434 jQuery.propFix.enctype = "encoding";
3437 // Radios and checkboxes getter/setter
3438 if ( !jQuery.support.checkOn ) {
3439 jQuery.each([ "radio", "checkbox" ], function() {
3440 jQuery.valHooks[ this ] = {
3441 get: function( elem ) {
3442 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
3443 return elem.getAttribute("value") === null ? "on" : elem.value;
3448 jQuery.each([ "radio", "checkbox" ], function() {
3449 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
3450 set: function( elem, value ) {
3451 if ( jQuery.isArray( value ) ) {
3452 return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
3461 var rnamespaces = /\.(.*)$/,
3462 rformElems = /^(?:textarea|input|select)$/i,
3465 rescape = /[^\w\s.|`]/g,
3466 rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
3467 rhoverHack = /\bhover(\.\S+)?/,
3469 rmouseEvent = /^(?:mouse|contextmenu)|click/,
3470 rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
3471 quickParse = function( selector ) {
3472 var quick = rquickIs.exec( selector );
3475 // [ _, tag, id, class ]
3476 quick[1] = ( quick[1] || "" ).toLowerCase();
3477 quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
3481 quickIs = function( elem, m ) {
3483 (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
3484 (!m[2] || elem.id === m[2]) &&
3485 (!m[3] || m[3].test( elem.className ))
3488 hoverHack = function( events ) {
3489 return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
3493 * Helper functions for managing events -- not part of the public interface.
3494 * Props to Dean Edwards' addEvent library for many of the ideas.
3498 add: function( elem, types, handler, data, selector ) {
3500 var elemData, eventHandle, events,
3501 t, tns, type, namespaces, handleObj,
3502 handleObjIn, quick, handlers, special;
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 )) ) {
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;
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++;
3520 // Init the element's event structure and main handler, if this is the first
3521 events = elemData.events;
3523 elemData.events = events = {};
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 ) :
3534 // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
3535 eventHandle.elem = elem;
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++ ) {
3543 tns = rtypenamespace.exec( types[t] ) || [];
3545 namespaces = ( tns[2] || "" ).split( "." ).sort();
3547 // If event changes its type, use the special event handlers for the changed type
3548 special = jQuery.event.special[ type ] || {};
3550 // If selector defined, determine special event api type, otherwise given type
3551 type = ( selector ? special.delegateType : special.bindType ) || type;
3553 // Update special based on newly reset type
3554 special = jQuery.event.special[ type ] || {};
3556 // handleObj is passed to all event handlers
3557 handleObj = jQuery.extend({
3564 namespace: namespaces.join(".")
3567 // Delegated event; pre-analyze selector so it's processed quickly on event dispatch
3569 handleObj.quick = quickParse( selector );
3570 if ( !handleObj.quick && jQuery.expr.match.POS.test( selector ) ) {
3571 handleObj.isPositional = true;
3575 // Init the event handler queue if we're the first
3576 handlers = events[ type ];
3578 handlers = events[ type ] = [];
3579 handlers.delegateCount = 0;
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 );
3587 } else if ( elem.attachEvent ) {
3588 elem.attachEvent( "on" + type, eventHandle );
3593 if ( special.add ) {
3594 special.add.call( elem, handleObj );
3596 if ( !handleObj.handler.guid ) {
3597 handleObj.handler.guid = handler.guid;
3601 // Add to the element's handler list, delegates in front
3603 handlers.splice( handlers.delegateCount++, 0, handleObj );
3605 handlers.push( handleObj );
3608 // Keep track of which events have ever been used, for event optimization
3609 jQuery.event.global[ type ] = true;
3612 // Nullify elem to prevent memory leaks in IE
3618 // Detach an event or set of events from an element
3619 remove: function( elem, types, handler, selector ) {
3621 var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
3622 t, tns, type, namespaces, origCount,
3623 j, events, special, handle, eventType, handleObj;
3625 if ( !elemData || !(events = elemData.events) ) {
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] ) || [];
3634 namespaces = tns[2];
3636 // Unbind all events (on this namespace, if provided) for the element
3638 namespaces = namespaces? "." + namespaces : "";
3639 for ( j in events ) {
3640 jQuery.event.remove( elem, j + namespaces, handler, selector );
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;
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 ];
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 );
3661 if ( handleObj.selector ) {
3662 eventType.delegateCount--;
3664 if ( special.remove ) {
3665 special.remove.call( elem, handleObj );
3672 // Removing all events
3673 eventType.length = 0;
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 );
3683 delete events[ type ];
3687 // Remove the expando if it's no longer used
3688 if ( jQuery.isEmptyObject( events ) ) {
3689 handle = elemData.handle;
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 );
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.
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) ) {
3714 // Event object or event type
3715 var type = event.type || event,
3717 cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
3719 if ( type.indexOf( "!" ) >= 0 ) {
3720 // Exclusive events trigger only for the exact event (no namespaces)
3721 type = type.slice(0, -1);
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();
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
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 :
3742 new jQuery.Event( type, event ) :
3743 // Just the event type (string)
3744 new jQuery.Event( 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 : "";
3753 // triggerHandler() and global events don't bubble or run the default action
3754 if ( onlyHandlers || !elem ) {
3755 event.preventDefault();
3758 // Handle a global trigger
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 );
3771 // Clean up the event in case it is being reused
3772 event.result = undefined;
3773 if ( !event.target ) {
3774 event.target = elem;
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 );
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 ) {
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 ) ) {
3792 bubbleType = special.delegateType || type;
3794 for ( cur = elem.parentNode; cur; cur = cur.parentNode ) {
3795 eventPath.push([ cur, bubbleType ]);
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 ]);
3805 // Fire handlers on the event path
3806 for ( i = 0; i < eventPath.length; i++ ) {
3808 cur = eventPath[i][0];
3809 event.type = eventPath[i][1];
3811 handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
3813 handle.apply( cur, data );
3815 handle = ontype && cur[ ontype ];
3816 if ( handle && jQuery.acceptData( cur ) ) {
3817 handle.apply( cur, data );
3820 if ( event.isPropagationStopped() ) {
3826 // If nobody prevented the default action, do it now
3827 if ( !event.isDefaultPrevented() ) {
3829 if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
3830 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
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 ) ) {
3838 // Don't re-trigger an onFOO event when we call its FOO() method
3839 old = elem[ ontype ];
3842 elem[ ontype ] = null;
3845 // Prevent re-triggering of the same event, since we already bubbled it above
3846 jQuery.event.triggered = type;
3848 jQuery.event.triggered = undefined;
3851 elem[ ontype ] = old;
3857 return event.result;
3860 dispatch: function( event ) {
3862 // Make a writable jQuery.Event from the native event object
3863 event = jQuery.event.fix( event || window.event );
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,
3871 i, j, cur, ret, selMatch, matched, matches, handleObj, sel, hit, related;
3873 // Use the fix-ed jQuery.Event rather than the (read-only) native event
3875 event.delegateTarget = this;
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") ) {
3881 for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
3884 for ( i = 0; i < delegateCount; i++ ) {
3885 handleObj = handlers[ i ];
3886 sel = handleObj.selector;
3887 hit = selMatch[ sel ];
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 ) );
3896 matches.push( handleObj );
3899 if ( matches.length ) {
3900 handlerQueue.push({ elem: cur, matches: matches });
3905 // Add the remaining (directly-bound) handlers
3906 if ( handlers.length > delegateCount ) {
3907 handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
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;
3915 for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
3916 handleObj = matched.matches[ j ];
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 ) ) {
3922 event.data = handleObj.data;
3923 event.handleObj = handleObj;
3925 ret = ( specialHandle || handleObj.handler ).apply( matched.elem, args );
3927 if ( ret !== undefined ) {
3929 if ( ret === false ) {
3930 event.preventDefault();
3931 event.stopPropagation();
3938 return event.result;
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(" "),
3948 props: "char charCode key keyCode".split(" "),
3949 filter: function( event, original ) {
3951 // Add which for key events
3952 if ( event.which == null ) {
3953 event.which = original.charCode != null ? original.charCode : original.keyCode;
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;
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;
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 );
3977 // Add relatedTarget, if necessary
3978 if ( !event.relatedTarget && fromElement ) {
3979 event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
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 ) ) );
3992 fix: function( event ) {
3993 if ( event[ jQuery.expando ] ) {
3997 // Create a writable copy of the event object and normalize some properties
3999 originalEvent = event,
4000 fixHook = jQuery.event.fixHooks[ event.type ] || {},
4001 copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
4003 event = jQuery.Event( originalEvent );
4005 for ( i = copy.length; i; ) {
4007 event[ prop ] = originalEvent[ prop ];
4010 // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
4011 if ( !event.target ) {
4012 event.target = originalEvent.srcElement || document;
4015 // Target should not be a text node (#504, Safari)
4016 if ( event.target.nodeType === 3 ) {
4017 event.target = event.target.parentNode;
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;
4025 return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
4030 // Make sure the ready event is setup
4031 setup: jQuery.bindReady
4035 delegateType: "focusin",
4039 delegateType: "focusout",
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;
4051 teardown: function( namespaces, eventHandle ) {
4052 if ( this.onbeforeunload === eventHandle ) {
4053 this.onbeforeunload = null;
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(
4072 jQuery.event.trigger( e, null, elem );
4074 jQuery.event.dispatch.call( elem, e );
4076 if ( e.isDefaultPrevented() ) {
4077 event.preventDefault();
4082 // Some plugins are using, but it's undocumented/deprecated and will be removed.
4083 // The 1.7 special event interface should provide all the hooks needed now.
4084 jQuery.event.handle = jQuery.event.dispatch;
4086 jQuery.removeEvent = document.removeEventListener ?
4087 function( elem, type, handle ) {
4088 if ( elem.removeEventListener ) {
4089 elem.removeEventListener( type, handle, false );
4092 function( elem, type, handle ) {
4093 if ( elem.detachEvent ) {
4094 elem.detachEvent( "on" + type, handle );
4098 jQuery.Event = function( src, props ) {
4099 // Allow instantiation without the 'new' keyword
4100 if ( !(this instanceof jQuery.Event) ) {
4101 return new jQuery.Event( src, props );
4105 if ( src && src.type ) {
4106 this.originalEvent = src;
4107 this.type = src.type;
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;
4119 // Put explicitly provided properties onto the event object
4121 jQuery.extend( this, props );
4124 // Create a timestamp if incoming event doesn't have one
4125 this.timeStamp = src && src.timeStamp || jQuery.now();
4128 this[ jQuery.expando ] = true;
4131 function returnFalse() {
4134 function returnTrue() {
4138 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
4139 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
4140 jQuery.Event.prototype = {
4141 preventDefault: function() {
4142 this.isDefaultPrevented = returnTrue;
4144 var e = this.originalEvent;
4149 // if preventDefault exists run it on the original event
4150 if ( e.preventDefault ) {
4153 // otherwise set the returnValue property of the original event to false (IE)
4155 e.returnValue = false;
4158 stopPropagation: function() {
4159 this.isPropagationStopped = returnTrue;
4161 var e = this.originalEvent;
4165 // if stopPropagation exists run it on the original event
4166 if ( e.stopPropagation ) {
4167 e.stopPropagation();
4169 // otherwise set the cancelBubble property of the original event to true (IE)
4170 e.cancelBubble = true;
4172 stopImmediatePropagation: function() {
4173 this.isImmediatePropagationStopped = returnTrue;
4174 this.stopPropagation();
4176 isDefaultPrevented: returnFalse,
4177 isPropagationStopped: returnFalse,
4178 isImmediatePropagationStopped: returnFalse
4181 // Create mouseenter/leave events using mouseover/out and event-time checks
4183 mouseenter: "mouseover",
4184 mouseleave: "mouseout"
4185 }, function( orig, fix ) {
4186 jQuery.event.special[ orig ] = jQuery.event.special[ fix ] = {
4190 handle: function( event ) {
4192 related = event.relatedTarget,
4193 handleObj = event.handleObj,
4194 selector = handleObj.selector,
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;
4211 // IE submit delegation
4212 if ( !jQuery.support.submitBubbles ) {
4214 jQuery.event.special.submit = {
4216 // Only need this for delegated form submit events
4217 if ( jQuery.nodeName( this, "form" ) ) {
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 );
4233 form._submit_attached = true;
4236 // return undefined since we don't need an event listener
4239 teardown: function() {
4240 // Only need this for delegated form submit events
4241 if ( jQuery.nodeName( this, "form" ) ) {
4245 // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
4246 jQuery.event.remove( this, "._submit" );
4251 // IE change delegation and checkbox/radio fix
4252 if ( !jQuery.support.changeBubbles ) {
4254 jQuery.event.special.change = {
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;
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 );
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;
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 );
4287 elem._change_attached = true;
4292 handle: function( event ) {
4293 var elem = event.target;
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 );
4301 teardown: function() {
4302 jQuery.event.remove( this, "._change" );
4304 return rformElems.test( this.nodeName );
4309 // Create "bubbling" focus and blur events
4310 if ( !jQuery.support.focusinBubbles ) {
4311 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
4313 // Attach a single capturing handler while someone wants focusin/focusout
4315 handler = function( event ) {
4316 jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
4319 jQuery.event.special[ fix ] = {
4321 if ( attaches++ === 0 ) {
4322 document.addEventListener( orig, handler, true );
4325 teardown: function() {
4326 if ( --attaches === 0 ) {
4327 document.removeEventListener( orig, handler, true );
4336 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
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 )
4345 selector = undefined;
4347 for ( type in types ) {
4348 this.on( type, selector, data, types[ type ], one );
4353 if ( data == null && fn == null ) {
4356 data = selector = undefined;
4357 } else if ( fn == null ) {
4358 if ( typeof selector === "string" ) {
4359 // ( types, selector, fn )
4363 // ( types, data, fn )
4366 selector = undefined;
4369 if ( fn === false ) {
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 );
4382 // Use same guid so caller can remove using origFn
4383 fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
4385 return this.each( function() {
4386 jQuery.event.add( this, types, fn, data, selector );
4389 one: function( types, selector, data, fn ) {
4390 return this.on.call( this, types, selector, data, fn, 1 );
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,
4403 if ( typeof types === "object" ) {
4404 // ( types-object [, selector] )
4405 for ( var type in types ) {
4406 this.off( type, selector, types[ type ] );
4410 if ( selector === false || typeof selector === "function" ) {
4413 selector = undefined;
4415 if ( fn === false ) {
4418 return this.each(function() {
4419 jQuery.event.remove( this, types, fn, selector );
4423 bind: function( types, data, fn ) {
4424 return this.on( types, null, data, fn );
4426 unbind: function( types, fn ) {
4427 return this.off( types, null, fn );
4430 live: function( types, data, fn ) {
4431 jQuery( this.context ).on( types, this.selector, data, fn );
4434 die: function( types, fn ) {
4435 jQuery( this.context ).off( types, this.selector || "**", fn );
4439 delegate: function( selector, types, data, fn ) {
4440 return this.on( types, selector, data, fn );
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 );
4447 trigger: function( type, data ) {
4448 return this.each(function() {
4449 jQuery.event.trigger( type, data, this );
4452 triggerHandler: function( type, data ) {
4454 return jQuery.event.trigger( type, data, this[0], true );
4458 toggle: function( fn ) {
4459 // Save reference to arguments for access in closure
4460 var args = arguments,
4461 guid = fn.guid || jQuery.guid++,
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 );
4468 // Make sure that clicks stop
4469 event.preventDefault();
4471 // and execute the function
4472 return args[ lastToggle ].apply( this, arguments ) || false;
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;
4481 return this.click( toggler );
4484 hover: function( fnOver, fnOut ) {
4485 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
4489 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
4490 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
4491 "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
4493 // Handle event binding
4494 jQuery.fn[ name ] = function( data, fn ) {
4500 return arguments.length > 0 ?
4501 this.bind( name, data, fn ) :
4502 this.trigger( name );
4505 if ( jQuery.attrFn ) {
4506 jQuery.attrFn[ name ] = true;
4509 if ( rkeyEvent.test( name ) ) {
4510 jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
4513 if ( rmouseEvent.test( name ) ) {
4514 jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
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/
4528 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
4529 expando = "sizcache" + (Math.random() + '').replace('.', ''),
4531 toString = Object.prototype.toString,
4532 hasDuplicate = false,
4533 baseHasDuplicate = true,
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;
4547 var Sizzle = function( selector, context, results, seed ) {
4548 results = results || [];
4549 context = context || document;
4551 var origContext = context;
4553 if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
4557 if ( !selector || typeof selector !== "string" ) {
4561 var m, set, checkSet, extra, ret, cur, pop, i,
4563 contextXML = Sizzle.isXML( context ),
4567 // Reset the position of the chunker regexp (start from head)
4570 m = chunker.exec( soFar );
4584 if ( parts.length > 1 && origPOS.exec( selector ) ) {
4586 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
4587 set = posProcess( parts[0] + parts[1], context, seed );
4590 set = Expr.relative[ parts[0] ] ?
4592 Sizzle( parts.shift(), context );
4594 while ( parts.length ) {
4595 selector = parts.shift();
4597 if ( Expr.relative[ selector ] ) {
4598 selector += parts.shift();
4601 set = posProcess( selector, set, seed );
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]) ) {
4611 ret = Sizzle.find( parts.shift(), context, contextXML );
4612 context = ret.expr ?
4613 Sizzle.filter( ret.expr, ret.set )[0] :
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 );
4623 Sizzle.filter( ret.expr, ret.set ) :
4626 if ( parts.length > 0 ) {
4627 checkSet = makeArray( set );
4633 while ( parts.length ) {
4637 if ( !Expr.relative[ cur ] ) {
4643 if ( pop == null ) {
4647 Expr.relative[ cur ]( checkSet, pop, contextXML );
4651 checkSet = parts = [];
4660 Sizzle.error( cur || selector );
4663 if ( toString.call(checkSet) === "[object Array]" ) {
4665 results.push.apply( results, checkSet );
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] );
4675 for ( i = 0; checkSet[i] != null; i++ ) {
4676 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
4677 results.push( set[i] );
4683 makeArray( checkSet, results );
4687 Sizzle( extra, origContext, results, seed );
4688 Sizzle.uniqueSort( results );
4694 Sizzle.uniqueSort = function( results ) {
4696 hasDuplicate = baseHasDuplicate;
4697 results.sort( sortOrder );
4699 if ( hasDuplicate ) {
4700 for ( var i = 1; i < results.length; i++ ) {
4701 if ( results[i] === results[ i - 1 ] ) {
4702 results.splice( i--, 1 );
4711 Sizzle.matches = function( expr, set ) {
4712 return Sizzle( expr, null, null, set );
4715 Sizzle.matchesSelector = function( node, expr ) {
4716 return Sizzle( expr, null, null, [node] ).length > 0;
4719 Sizzle.find = function( expr, context, isXML ) {
4720 var set, i, len, match, type, left;
4726 for ( i = 0, len = Expr.order.length; i < len; i++ ) {
4727 type = Expr.order[i];
4729 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
4731 match.splice( 1, 1 );
4733 if ( left.substr( left.length - 1 ) !== "\\" ) {
4734 match[1] = (match[1] || "").replace( rBackslash, "" );
4735 set = Expr.find[ type ]( match, context, isXML );
4737 if ( set != null ) {
4738 expr = expr.replace( Expr.match[ type ], "" );
4746 set = typeof context.getElementsByTagName !== "undefined" ?
4747 context.getElementsByTagName( "*" ) :
4751 return { set: set, expr: expr };
4754 Sizzle.filter = function( expr, set, inplace, not ) {
4755 var match, anyFound,
4756 type, found, item, filter, left,
4761 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
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 ];
4773 if ( left.substr( left.length - 1 ) === "\\" ) {
4777 if ( curLoop === result ) {
4781 if ( Expr.preFilter[ type ] ) {
4782 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
4785 anyFound = found = true;
4787 } else if ( match === true ) {
4793 for ( i = 0; (item = curLoop[i]) != null; i++ ) {
4795 found = filter( item, match, i, curLoop );
4798 if ( inplace && found != null ) {
4806 } else if ( pass ) {
4807 result.push( item );
4814 if ( found !== undefined ) {
4819 expr = expr.replace( Expr.match[ type ], "" );
4830 // Improper expression
4831 if ( expr === old ) {
4832 if ( anyFound == null ) {
4833 Sizzle.error( expr );
4846 Sizzle.error = function( msg ) {
4847 throw "Syntax error, unrecognized expression: " + msg;
4851 * Utility function for retreiving the text value of an array of DOM nodes
4852 * @param {Array|Element} elem
4854 var getText = Sizzle.getText = function( elem ) {
4856 nodeType = elem.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, '' );
4868 // Traverse it's children
4869 for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
4870 ret += getText( elem );
4873 } else if ( nodeType === 3 || nodeType === 4 ) {
4874 return elem.nodeValue;
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 );
4889 var Expr = Sizzle.selectors = {
4890 order: [ "ID", "NAME", "TAG" ],
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\))?/
4906 "class": "className",
4911 href: function( elem ) {
4912 return elem.getAttribute( "href" );
4914 type: function( elem ) {
4915 return elem.getAttribute( "type" );
4920 "+": function(checkSet, part){
4921 var isPartStr = typeof part === "string",
4922 isTag = isPartStr && !rNonWord.test( part ),
4923 isPartStrNotTag = isPartStr && !isTag;
4926 part = part.toLowerCase();
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 ) {}
4933 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
4939 if ( isPartStrNotTag ) {
4940 Sizzle.filter( part, checkSet, true );
4944 ">": function( checkSet, part ) {
4946 isPartStr = typeof part === "string",
4948 l = checkSet.length;
4950 if ( isPartStr && !rNonWord.test( part ) ) {
4951 part = part.toLowerCase();
4953 for ( ; i < l; i++ ) {
4957 var parent = elem.parentNode;
4958 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
4963 for ( ; i < l; i++ ) {
4967 checkSet[i] = isPartStr ?
4969 elem.parentNode === part;
4974 Sizzle.filter( part, checkSet, true );
4979 "": function(checkSet, part, isXML){
4984 if ( typeof part === "string" && !rNonWord.test( part ) ) {
4985 part = part.toLowerCase();
4987 checkFn = dirNodeCheck;
4990 checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
4993 "~": function( checkSet, part, isXML ) {
4998 if ( typeof part === "string" && !rNonWord.test( part ) ) {
4999 part = part.toLowerCase();
5001 checkFn = dirNodeCheck;
5004 checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
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] : [];
5018 NAME: function( match, context ) {
5019 if ( typeof context.getElementsByName !== "undefined" ) {
5021 results = context.getElementsByName( match[1] );
5023 for ( var i = 0, l = results.length; i < l; i++ ) {
5024 if ( results[i].getAttribute("name") === match[1] ) {
5025 ret.push( results[i] );
5029 return ret.length === 0 ? null : ret;
5033 TAG: function( match, context ) {
5034 if ( typeof context.getElementsByTagName !== "undefined" ) {
5035 return context.getElementsByTagName( match[1] );
5040 CLASS: function( match, curLoop, inplace, result, not, isXML ) {
5041 match = " " + match[1].replace( rBackslash, "" ) + " ";
5047 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
5049 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
5051 result.push( elem );
5054 } else if ( inplace ) {
5063 ID: function( match ) {
5064 return match[1].replace( rBackslash, "" );
5067 TAG: function( match, curLoop ) {
5068 return match[1].replace( rBackslash, "" ).toLowerCase();
5071 CHILD: function( match ) {
5072 if ( match[1] === "nth" ) {
5074 Sizzle.error( match[0] );
5077 match[2] = match[2].replace(/^\+|\s*/g, '');
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]);
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;
5088 else if ( match[2] ) {
5089 Sizzle.error( match[0] );
5092 // TODO: Move to normal caching system
5098 ATTR: function( match, curLoop, inplace, result, not, isXML ) {
5099 var name = match[1] = match[1].replace( rBackslash, "" );
5101 if ( !isXML && Expr.attrMap[name] ) {
5102 match[1] = Expr.attrMap[name];
5105 // Handle if an un-quoted value was used
5106 match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
5108 if ( match[2] === "~=" ) {
5109 match[4] = " " + match[4] + " ";
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);
5122 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
5125 result.push.apply( result, ret );
5131 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
5138 POS: function( match ) {
5139 match.unshift( true );
5146 enabled: function( elem ) {
5147 return elem.disabled === false && elem.type !== "hidden";
5150 disabled: function( elem ) {
5151 return elem.disabled === true;
5154 checked: function( elem ) {
5155 return elem.checked === true;
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;
5165 return elem.selected === true;
5168 parent: function( elem ) {
5169 return !!elem.firstChild;
5172 empty: function( elem ) {
5173 return !elem.firstChild;
5176 has: function( elem, i, match ) {
5177 return !!Sizzle( match[3], elem ).length;
5180 header: function( elem ) {
5181 return (/h\d/i).test( elem.nodeName );
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 );
5191 radio: function( elem ) {
5192 return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
5195 checkbox: function( elem ) {
5196 return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
5199 file: function( elem ) {
5200 return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
5203 password: function( elem ) {
5204 return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
5207 submit: function( elem ) {
5208 var name = elem.nodeName.toLowerCase();
5209 return (name === "input" || name === "button") && "submit" === elem.type;
5212 image: function( elem ) {
5213 return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
5216 reset: function( elem ) {
5217 var name = elem.nodeName.toLowerCase();
5218 return (name === "input" || name === "button") && "reset" === elem.type;
5221 button: function( elem ) {
5222 var name = elem.nodeName.toLowerCase();
5223 return name === "input" && "button" === elem.type || name === "button";
5226 input: function( elem ) {
5227 return (/input|select|textarea|button/i).test( elem.nodeName );
5230 focus: function( elem ) {
5231 return elem === elem.ownerDocument.activeElement;
5235 first: function( elem, i ) {
5239 last: function( elem, i, match, array ) {
5240 return i === array.length - 1;
5243 even: function( elem, i ) {
5247 odd: function( elem, i ) {
5251 lt: function( elem, i, match ) {
5252 return i < match[3] - 0;
5255 gt: function( elem, i, match ) {
5256 return i > match[3] - 0;
5259 nth: function( elem, i, match ) {
5260 return match[3] - 0 === i;
5263 eq: function( elem, i, match ) {
5264 return match[3] - 0 === i;
5268 PSEUDO: function( elem, match, i, array ) {
5269 var name = match[1],
5270 filter = Expr.filters[ name ];
5273 return filter( elem, i, match, array );
5275 } else if ( name === "contains" ) {
5276 return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
5278 } else if ( name === "not" ) {
5281 for ( var j = 0, l = not.length; j < l; j++ ) {
5282 if ( not[j] === elem ) {
5290 Sizzle.error( name );
5294 CHILD: function( elem, match ) {
5296 doneName, parent, cache,
5304 while ( (node = node.previousSibling) ) {
5305 if ( node.nodeType === 1 ) {
5310 if ( type === "first" ) {
5317 while ( (node = node.nextSibling) ) {
5318 if ( node.nodeType === 1 ) {
5329 if ( first === 1 && last === 0 ) {
5333 doneName = match[0];
5334 parent = elem.parentNode;
5336 if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
5339 for ( node = parent.firstChild; node; node = node.nextSibling ) {
5340 if ( node.nodeType === 1 ) {
5341 node.nodeIndex = ++count;
5345 parent[ expando ] = doneName;
5348 diff = elem.nodeIndex - last;
5350 if ( first === 0 ) {
5354 return ( diff % first === 0 && diff / first >= 0 );
5359 ID: function( elem, match ) {
5360 return elem.nodeType === 1 && elem.getAttribute("id") === match;
5363 TAG: function( elem, match ) {
5364 return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
5367 CLASS: function( elem, match ) {
5368 return (" " + (elem.className || elem.getAttribute("class")) + " ")
5369 .indexOf( match ) > -1;
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 ?
5380 elem.getAttribute( name ),
5381 value = result + "",
5385 return result == null ?
5387 !type && Sizzle.attr ?
5392 value.indexOf(check) >= 0 :
5394 (" " + value + " ").indexOf(check) >= 0 :
5396 value && result !== false :
5400 value.indexOf(check) === 0 :
5402 value.substr(value.length - check.length) === check :
5404 value === check || value.substr(0, check.length + 1) === check + "-" :
5408 POS: function( elem, match, i, array ) {
5409 var name = match[2],
5410 filter = Expr.setFilters[ name ];
5413 return filter( elem, i, match, array );
5419 var origPOS = Expr.match.POS,
5420 fescape = function(all, num){
5421 return "\\" + (num - 0 + 1);
5424 for ( var type in Expr.match ) {
5425 Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
5426 Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
5429 var makeArray = function( array, results ) {
5430 array = Array.prototype.slice.call( array, 0 );
5433 results.push.apply( results, array );
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)
5445 Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
5447 // Provide a fallback method if it does not work
5449 makeArray = function( array, results ) {
5451 ret = results || [];
5453 if ( toString.call(array) === "[object Array]" ) {
5454 Array.prototype.push.apply( ret, array );
5457 if ( typeof array.length === "number" ) {
5458 for ( var l = array.length; i < l; i++ ) {
5459 ret.push( array[i] );
5463 for ( ; array[i]; i++ ) {
5464 ret.push( array[i] );
5473 var sortOrder, siblingCheck;
5475 if ( document.documentElement.compareDocumentPosition ) {
5476 sortOrder = function( a, b ) {
5478 hasDuplicate = true;
5482 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
5483 return a.compareDocumentPosition ? -1 : 1;
5486 return a.compareDocumentPosition(b) & 4 ? -1 : 1;
5490 sortOrder = function( a, b ) {
5491 // The nodes are identical, we can exit early
5493 hasDuplicate = true;
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;
5508 // If the nodes are siblings (or identical) we can do a quick check
5509 if ( aup === bup ) {
5510 return siblingCheck( a, b );
5512 // If no parents were found then the nodes are disconnected
5513 } else if ( !aup ) {
5516 } else if ( !bup ) {
5520 // Otherwise they're somewhere else in the tree so we need
5521 // to build up a full list of the parentNodes for comparison
5524 cur = cur.parentNode;
5531 cur = cur.parentNode;
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] );
5544 // We ended someplace up the tree so do a sibling check
5546 siblingCheck( a, bp[i], -1 ) :
5547 siblingCheck( ap[i], b, 1 );
5550 siblingCheck = function( a, b, ret ) {
5555 var cur = a.nextSibling;
5562 cur = cur.nextSibling;
5569 // Check to see if the browser returns elements by name when
5570 // querying by getElementById (and provide a workaround)
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;
5577 form.innerHTML = "<a name='" + id + "'/>";
5579 // Inject it into the root element, check its status, and remove it quickly
5580 root.insertBefore( form, root.firstChild );
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]);
5590 m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
5597 Expr.filter.ID = function( elem, match ) {
5598 var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
5600 return elem.nodeType === 1 && node && node.nodeValue === match;
5604 root.removeChild( form );
5606 // release memory in IE
5611 // Check to see if the browser returns only elements
5612 // when doing getElementsByTagName("*")
5614 // Create a fake element
5615 var div = document.createElement("div");
5616 div.appendChild( document.createComment("") );
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] );
5623 // Filter out possible comments
5624 if ( match[1] === "*" ) {
5627 for ( var i = 0; results[i]; i++ ) {
5628 if ( results[i].nodeType === 1 ) {
5629 tmp.push( results[i] );
5640 // Check to see if an attribute returns normalized href attributes
5641 div.innerHTML = "<a href='#'></a>";
5643 if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
5644 div.firstChild.getAttribute("href") !== "#" ) {
5646 Expr.attrHandle.href = function( elem ) {
5647 return elem.getAttribute( "href", 2 );
5651 // release memory in IE
5655 if ( document.querySelectorAll ) {
5657 var oldSizzle = Sizzle,
5658 div = document.createElement("div"),
5661 div.innerHTML = "<p class='TEST'></p>";
5663 // Safari can't handle uppercase or unicode characters when
5665 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
5669 Sizzle = function( query, context, extra, seed ) {
5670 context = context || document;
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 );
5678 if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
5679 // Speed-up: Sizzle("TAG")
5681 return makeArray( context.getElementsByTagName( query ), extra );
5683 // Speed-up: Sizzle(".CLASS")
5684 } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
5685 return makeArray( context.getElementsByClassName( match[2] ), extra );
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 );
5695 // Speed-up: Sizzle("#ID")
5696 } else if ( match && match[3] ) {
5697 var elem = context.getElementById( match[3] );
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 );
5709 return makeArray( [], extra );
5714 return makeArray( context.querySelectorAll(query), extra );
5715 } catch(qsaError) {}
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" ),
5725 hasParent = context.parentNode,
5726 relativeHierarchySelector = /^\s*[+~]/.test( query );
5729 context.setAttribute( "id", nid );
5731 nid = nid.replace( /'/g, "\\$&" );
5733 if ( relativeHierarchySelector && hasParent ) {
5734 context = context.parentNode;
5738 if ( !relativeHierarchySelector || hasParent ) {
5739 return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
5742 } catch(pseudoError) {
5745 oldContext.removeAttribute( "id" );
5751 return oldSizzle(query, context, extra, seed);
5754 for ( var prop in oldSizzle ) {
5755 Sizzle[ prop ] = oldSizzle[ prop ];
5758 // release memory in IE
5764 var html = document.documentElement,
5765 matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
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;
5774 // This should fail with an exception
5775 // Gecko does not error, returns false instead
5776 matches.call( document.documentElement, "[test!='']:sizzle" );
5778 } catch( pseudoError ) {
5782 Sizzle.matchesSelector = function( node, expr ) {
5783 // Make sure that attribute selectors are quoted
5784 expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
5786 if ( !Sizzle.isXML( node ) ) {
5788 if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
5789 var ret = matches.call( node, expr );
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 ) {
5802 return Sizzle(expr, null, null, [node]).length > 0;
5808 var div = document.createElement("div");
5810 div.innerHTML = "<div class='test e'></div><div class='test'></div>";
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 ) {
5818 // Safari caches class attributes, doesn't catch changes (in 3.2)
5819 div.lastChild.className = "e";
5821 if ( div.getElementsByClassName("e").length === 1 ) {
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]);
5832 // release memory in IE
5836 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5837 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5838 var elem = checkSet[i];
5846 if ( elem[ expando ] === doneName ) {
5847 match = checkSet[elem.sizset];
5851 if ( elem.nodeType === 1 && !isXML ){
5852 elem[ expando ] = doneName;
5856 if ( elem.nodeName.toLowerCase() === cur ) {
5864 checkSet[i] = match;
5869 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5870 for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5871 var elem = checkSet[i];
5879 if ( elem[ expando ] === doneName ) {
5880 match = checkSet[elem.sizset];
5884 if ( elem.nodeType === 1 ) {
5886 elem[ expando ] = doneName;
5890 if ( typeof cur !== "string" ) {
5891 if ( elem === cur ) {
5896 } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
5905 checkSet[i] = match;
5910 if ( document.documentElement.contains ) {
5911 Sizzle.contains = function( a, b ) {
5912 return a !== b && (a.contains ? a.contains(b) : true);
5915 } else if ( document.documentElement.compareDocumentPosition ) {
5916 Sizzle.contains = function( a, b ) {
5917 return !!(a.compareDocumentPosition(b) & 16);
5921 Sizzle.contains = function() {
5926 Sizzle.isXML = function( elem ) {
5927 // documentElement is verified for cases where it doesn't yet exist
5928 // (such as loading iframes in IE - #4833)
5929 var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
5931 return documentElement ? documentElement.nodeName !== "HTML" : false;
5934 var posProcess = function( selector, context, seed ) {
5938 root = context.nodeType ? [context] : context;
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 )) ) {
5944 selector = selector.replace( Expr.match.PSEUDO, "" );
5947 selector = Expr.relative[selector] ? selector + "*" : selector;
5949 for ( var i = 0, l = root.length; i < l; i++ ) {
5950 Sizzle( selector, root[i], tmpSet, seed );
5953 return Sizzle.filter( later, tmpSet );
5957 // Override sizzle attribute retrieval
5958 Sizzle.attr = jQuery.attr;
5959 Sizzle.selectors.attrMap = {};
5960 jQuery.find = Sizzle;
5961 jQuery.expr = Sizzle.selectors;
5962 jQuery.expr[":"] = jQuery.expr.filters;
5963 jQuery.unique = Sizzle.uniqueSort;
5964 jQuery.text = Sizzle.getText;
5965 jQuery.isXMLDoc = Sizzle.isXML;
5966 jQuery.contains = Sizzle.contains;
5972 var runtil = /Until$/,
5973 rparentsprev = /^(?:parents|prevUntil|prevAll)/,
5974 // Note: This RegExp should be improved, or likely pulled from Sizzle
5975 rmultiselector = /,/,
5976 isSimple = /^.[^:#\[\.,]*$/,
5977 slice = Array.prototype.slice,
5978 POS = jQuery.expr.match.POS,
5979 // methods guaranteed to produce a unique set when starting from a unique set
5980 guaranteedUnique = {
5988 find: function( selector ) {
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 ) ) {
6002 var ret = this.pushStack( "", "find", selector ),
6005 for ( i = 0, l = this.length; i < l; i++ ) {
6006 length = ret.length;
6007 jQuery.find( selector, this[i], ret );
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] ) {
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] ) ) {
6036 not: function( selector ) {
6037 return this.pushStack( winnow(this, selector, false), "not", selector);
6040 filter: function( selector ) {
6041 return this.pushStack( winnow(this, selector, true), "filter", selector );
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 );
6055 closest: function( selectors, context ) {
6056 var ret = [], i, l, cur = this[0];
6058 // Array (deprecated as of jQuery 1.7)
6059 if ( jQuery.isArray( selectors ) ) {
6062 while ( cur && cur.ownerDocument && cur !== context ) {
6063 for ( i = 0; i < selectors.length; i++ ) {
6065 if ( jQuery( cur ).is( selectors[ i ] ) ) {
6066 ret.push({ selector: selectors[ i ], elem: cur, level: level });
6070 cur = cur.parentNode;
6078 var pos = POS.test( selectors ) || typeof selectors !== "string" ?
6079 jQuery( selectors, context || this.context ) :
6082 for ( i = 0, l = this.length; i < l; i++ ) {
6086 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
6091 cur = cur.parentNode;
6092 if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
6099 ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
6101 return this.pushStack( ret, "closest", selectors );
6104 // Determine the position of an element within
6105 // the matched set of elements
6106 index: function( elem ) {
6108 // No argument, return index in parent
6110 return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
6113 // index in selector
6114 if ( typeof elem === "string" ) {
6115 return jQuery.inArray( this[0], jQuery( elem ) );
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 );
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 );
6130 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
6132 jQuery.unique( all ) );
6135 andSelf: function() {
6136 return this.add( this.prevObject );
6140 // A painfully simple check to see if an element is disconnected
6141 // from a document (should be improved, where feasible).
6142 function isDisconnected( node ) {
6143 return !node || !node.parentNode || node.parentNode.nodeType === 11;
6147 parent: function( elem ) {
6148 var parent = elem.parentNode;
6149 return parent && parent.nodeType !== 11 ? parent : null;
6151 parents: function( elem ) {
6152 return jQuery.dir( elem, "parentNode" );
6154 parentsUntil: function( elem, i, until ) {
6155 return jQuery.dir( elem, "parentNode", until );
6157 next: function( elem ) {
6158 return jQuery.nth( elem, 2, "nextSibling" );
6160 prev: function( elem ) {
6161 return jQuery.nth( elem, 2, "previousSibling" );
6163 nextAll: function( elem ) {
6164 return jQuery.dir( elem, "nextSibling" );
6166 prevAll: function( elem ) {
6167 return jQuery.dir( elem, "previousSibling" );
6169 nextUntil: function( elem, i, until ) {
6170 return jQuery.dir( elem, "nextSibling", until );
6172 prevUntil: function( elem, i, until ) {
6173 return jQuery.dir( elem, "previousSibling", until );
6175 siblings: function( elem ) {
6176 return jQuery.sibling( elem.parentNode.firstChild, elem );
6178 children: function( elem ) {
6179 return jQuery.sibling( elem.firstChild );
6181 contents: function( elem ) {
6182 return jQuery.nodeName( elem, "iframe" ) ?
6183 elem.contentDocument || elem.contentWindow.document :
6184 jQuery.makeArray( elem.childNodes );
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);
6195 if ( !runtil.test( name ) ) {
6199 if ( selector && typeof selector === "string" ) {
6200 ret = jQuery.filter( selector, ret );
6203 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
6205 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
6206 ret = ret.reverse();
6209 return this.pushStack( ret, name, args.join(",") );
6214 filter: function( expr, elems, not ) {
6216 expr = ":not(" + expr + ")";
6219 return elems.length === 1 ?
6220 jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
6221 jQuery.find.matches(expr, elems);
6224 dir: function( elem, dir, until ) {
6228 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
6229 if ( cur.nodeType === 1 ) {
6230 matched.push( cur );
6237 nth: function( cur, result, dir, elem ) {
6238 result = result || 1;
6241 for ( ; cur; cur = cur[dir] ) {
6242 if ( cur.nodeType === 1 && ++num === result ) {
6250 sibling: function( n, elem ) {
6253 for ( ; n; n = n.nextSibling ) {
6254 if ( n.nodeType === 1 && n !== elem ) {
6263 // Implement the identical functionality for filter and not
6264 function winnow( elements, qualifier, keep ) {
6266 // Can't pass null or undefined to indexOf in Firefox 4
6267 // Set to 0 to skip string check
6268 qualifier = qualifier || 0;
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;
6276 } else if ( qualifier.nodeType ) {
6277 return jQuery.grep(elements, function( elem, i ) {
6278 return ( elem === qualifier ) === keep;
6281 } else if ( typeof qualifier === "string" ) {
6282 var filtered = jQuery.grep(elements, function( elem ) {
6283 return elem.nodeType === 1;
6286 if ( isSimple.test( qualifier ) ) {
6287 return jQuery.filter(qualifier, filtered, !keep);
6289 qualifier = jQuery.filter( qualifier, filtered );
6293 return jQuery.grep(elements, function( elem, i ) {
6294 return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
6301 function createSafeFragment( document ) {
6302 var list = nodeNames.split( " " ),
6303 safeFrag = document.createDocumentFragment();
6305 if ( safeFrag.createElement ) {
6306 while ( list.length ) {
6307 safeFrag.createElement(
6315 var nodeNames = "abbr article aside audio canvas datalist details figcaption figure footer " +
6316 "header hgroup mark meter nav output progress section summary time video",
6317 rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
6318 rleadingWhitespace = /^\s+/,
6319 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
6320 rtagName = /<([\w:]+)/,
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\[|\-\-)/,
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, "", "" ]
6340 safeFragment = createSafeFragment( document );
6342 wrapMap.optgroup = wrapMap.option;
6343 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
6344 wrapMap.th = wrapMap.td;
6346 // IE can't serialize <link> and <script> tags normally
6347 if ( !jQuery.support.htmlSerialize ) {
6348 wrapMap._default = [ 1, "div<div>", "</div>" ];
6352 text: function( text ) {
6353 if ( jQuery.isFunction(text) ) {
6354 return this.each(function(i) {
6355 var self = jQuery( this );
6357 self.text( text.call(this, i, self.text()) );
6361 if ( typeof text !== "object" && text !== undefined ) {
6362 return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
6365 return jQuery.text( this );
6368 wrapAll: function( html ) {
6369 if ( jQuery.isFunction( html ) ) {
6370 return this.each(function(i) {
6371 jQuery(this).wrapAll( html.call(this, i) );
6376 // The elements to wrap the target around
6377 var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
6379 if ( this[0].parentNode ) {
6380 wrap.insertBefore( this[0] );
6383 wrap.map(function() {
6386 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
6387 elem = elem.firstChild;
6397 wrapInner: function( html ) {
6398 if ( jQuery.isFunction( html ) ) {
6399 return this.each(function(i) {
6400 jQuery(this).wrapInner( html.call(this, i) );
6404 return this.each(function() {
6405 var self = jQuery( this ),
6406 contents = self.contents();
6408 if ( contents.length ) {
6409 contents.wrapAll( html );
6412 self.append( html );
6417 wrap: function( html ) {
6418 return this.each(function() {
6419 jQuery( this ).wrapAll( html );
6423 unwrap: function() {
6424 return this.parent().each(function() {
6425 if ( !jQuery.nodeName( this, "body" ) ) {
6426 jQuery( this ).replaceWith( this.childNodes );
6431 append: function() {
6432 return this.domManip(arguments, true, function( elem ) {
6433 if ( this.nodeType === 1 ) {
6434 this.appendChild( elem );
6439 prepend: function() {
6440 return this.domManip(arguments, true, function( elem ) {
6441 if ( this.nodeType === 1 ) {
6442 this.insertBefore( elem, this.firstChild );
6447 before: function() {
6448 if ( this[0] && this[0].parentNode ) {
6449 return this.domManip(arguments, false, function( elem ) {
6450 this.parentNode.insertBefore( elem, this );
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 );
6460 if ( this[0] && this[0].parentNode ) {
6461 return this.domManip(arguments, false, function( elem ) {
6462 this.parentNode.insertBefore( elem, this.nextSibling );
6464 } else if ( arguments.length ) {
6465 var set = this.pushStack( this, "after", arguments );
6466 set.push.apply( set, jQuery(arguments[0]).toArray() );
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 ] );
6480 if ( elem.parentNode ) {
6481 elem.parentNode.removeChild( elem );
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("*") );
6496 // Remove any remaining nodes
6497 while ( elem.firstChild ) {
6498 elem.removeChild( elem.firstChild );
6505 clone: function( dataAndEvents, deepDataAndEvents ) {
6506 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6507 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6509 return this.map( function () {
6510 return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6514 html: function( value ) {
6515 if ( value === undefined ) {
6516 return this[0] && this[0].nodeType === 1 ?
6517 this[0].innerHTML.replace(rinlinejQuery, "") :
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() ] ) {
6525 value = value.replace(rxhtmlTag, "<$1></$2>");
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;
6536 // If using innerHTML throws an exception, use the fallback method
6538 this.empty().append( value );
6541 } else if ( jQuery.isFunction( value ) ) {
6542 this.each(function(i){
6543 var self = jQuery( this );
6545 self.html( value.call(this, i, self.html()) );
6549 this.empty().append( value );
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 ) );
6566 if ( typeof value !== "string" ) {
6567 value = jQuery( value ).detach();
6570 return this.each(function() {
6571 var next = this.nextSibling,
6572 parent = this.parentNode;
6574 jQuery( this ).remove();
6577 jQuery(next).before( value );
6579 jQuery(parent).append( value );
6583 return this.length ?
6584 this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
6589 detach: function( selector ) {
6590 return this.remove( selector, true );
6593 domManip: function( args, table, callback ) {
6594 var results, first, fragment, parent,
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 );
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 );
6614 parent = value && value.parentNode;
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 };
6621 results = jQuery.buildFragment( args, this, scripts );
6624 fragment = results.fragment;
6626 if ( fragment.childNodes.length === 1 ) {
6627 first = fragment = fragment.firstChild;
6629 first = fragment.firstChild;
6633 table = table && jQuery.nodeName( first, "tr" );
6635 for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
6638 root(this[i], first) :
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
6647 results.cacheable || ( l > 1 && i < lastIndex ) ?
6648 jQuery.clone( fragment, true, true ) :
6654 if ( scripts.length ) {
6655 jQuery.each( scripts, evalScript );
6663 function root( elem, cur ) {
6664 return jQuery.nodeName(elem, "table") ?
6665 (elem.getElementsByTagName("tbody")[0] ||
6666 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
6670 function cloneCopyEvent( src, dest ) {
6672 if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6677 oldData = jQuery._data( src ),
6678 curData = jQuery._data( dest, oldData ),
6679 events = oldData.events;
6682 delete curData.handle;
6683 curData.events = {};
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 );
6692 // make the cloned public data object a copy from the original
6693 if ( curData.data ) {
6694 curData.data = jQuery.extend( {}, curData.data );
6698 function cloneFixAttributes( src, dest ) {
6701 // We do not need to do anything for non-Elements
6702 if ( dest.nodeType !== 1 ) {
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();
6712 // mergeAttributes, in contrast, only merges back on the
6713 // original attributes, not the events
6714 if ( dest.mergeAttributes ) {
6715 dest.mergeAttributes( src );
6718 nodeName = dest.nodeName.toLowerCase();
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;
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;
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;
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;
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;
6751 // Event data gets referenced instead of copied if the expando
6753 dest.removeAttribute( jQuery.expando );
6756 jQuery.buildFragment = function( args, nodes, scripts ) {
6757 var fragment, cacheable, cacheresults, doc,
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];
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
6770 if ( !doc.createDocumentFragment ) {
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 )) ) {
6786 cacheresults = jQuery.fragments[ first ];
6787 if ( cacheresults && cacheresults !== 1 ) {
6788 fragment = cacheresults;
6793 fragment = doc.createDocumentFragment();
6794 jQuery.clean( args, doc, fragment, scripts );
6798 jQuery.fragments[ first ] = cacheresults ? fragment : 1;
6801 return { fragment: fragment, cacheable: cacheable };
6804 jQuery.fragments = {};
6808 prependTo: "prepend",
6809 insertBefore: "before",
6810 insertAfter: "after",
6811 replaceAll: "replaceWith"
6812 }, function( name, original ) {
6813 jQuery.fn[ name ] = function( selector ) {
6815 insert = jQuery( selector ),
6816 parent = this.length === 1 && this[0].parentNode;
6818 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
6819 insert[ original ]( this[0] );
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 );
6829 return this.pushStack( ret, name, insert.selector );
6834 function getAll( elem ) {
6835 if ( typeof elem.getElementsByTagName !== "undefined" ) {
6836 return elem.getElementsByTagName( "*" );
6838 } else if ( typeof elem.querySelectorAll !== "undefined" ) {
6839 return elem.querySelectorAll( "*" );
6846 // Used in clean, fixes the defaultChecked property
6847 function fixDefaultChecked( elem ) {
6848 if ( elem.type === "checkbox" || elem.type === "radio" ) {
6849 elem.defaultChecked = elem.checked;
6852 // Finds all inputs and passes them to fixDefaultChecked
6853 function findInputs( elem ) {
6854 var nodeName = ( elem.nodeName || "" ).toLowerCase();
6855 if ( nodeName === "input" ) {
6856 fixDefaultChecked( elem );
6857 // Skip scripts, get other children
6858 } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
6859 jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
6864 clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6865 var clone = elem.cloneNode(true),
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.
6878 cloneFixAttributes( elem, clone );
6880 // Using Sizzle here is crazy slow, so we use getElementsByTagName
6882 srcElements = getAll( elem );
6883 destElements = getAll( clone );
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] );
6896 // Copy the events from the original to the clone
6897 if ( dataAndEvents ) {
6898 cloneCopyEvent( elem, clone );
6900 if ( deepDataAndEvents ) {
6901 srcElements = getAll( elem );
6902 destElements = getAll( clone );
6904 for ( i = 0; srcElements[i]; ++i ) {
6905 cloneCopyEvent( srcElements[i], destElements[i] );
6910 srcElements = destElements = null;
6912 // Return the cloned set
6916 clean: function( elems, context, fragment, scripts ) {
6917 var checkScriptType;
6919 context = context || document;
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;
6928 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
6929 if ( typeof elem === "number" ) {
6937 // Convert html string into DOM nodes
6938 if ( typeof elem === "string" ) {
6939 if ( !rhtml.test( elem ) ) {
6940 elem = context.createTextNode( elem );
6942 // Fix "XHTML"-style tags in all browsers
6943 elem = elem.replace(rxhtmlTag, "<$1></$2>");
6945 // Trim whitespace, otherwise indexOf won't work as expected
6946 var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
6947 wrap = wrapMap[ tag ] || wrapMap._default,
6949 div = context.createElement("div");
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 );
6956 // Use a fragment created with the owner document
6957 createSafeFragment( context ).appendChild( div );
6960 // Go to html and back, then peel off extra wrappers
6961 div.innerHTML = wrap[1] + elem + wrap[2];
6963 // Move to the right depth
6965 div = div.lastChild;
6968 // Remove IE's autoinserted <tbody> from table fragments
6969 if ( !jQuery.support.tbody ) {
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 :
6976 // String was a bare <thead> or <tfoot>
6977 wrap[1] === "<table>" && !hasBody ?
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 ] );
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 );
6993 elem = div.childNodes;
6997 // Resets defaultChecked for any radios and checkboxes
6998 // about to be appended to the DOM in IE 6/7 (#8060)
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] );
7010 if ( elem.nodeType ) {
7013 ret = jQuery.merge( ret, elem );
7018 checkScriptType = function( elem ) {
7019 return !elem.type || rscriptType.test( elem.type );
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] );
7026 if ( ret[i].nodeType === 1 ) {
7027 var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
7029 ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
7031 fragment.appendChild( ret[i] );
7039 cleanData: function( elems ) {
7041 cache = jQuery.cache,
7042 special = jQuery.event.special,
7043 deleteExpando = jQuery.support.deleteExpando;
7045 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
7046 if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
7050 id = elem[ jQuery.expando ];
7055 if ( data && data.events ) {
7056 for ( var type in data.events ) {
7057 if ( special[ type ] ) {
7058 jQuery.event.remove( elem, type );
7060 // This is a shortcut to avoid jQuery.event.remove's overhead
7062 jQuery.removeEvent( elem, type, data.handle );
7066 // Null the DOM reference to avoid IE6/7/8 leak (#7054)
7067 if ( data.handle ) {
7068 data.handle.elem = null;
7072 if ( deleteExpando ) {
7073 delete elem[ jQuery.expando ];
7075 } else if ( elem.removeAttribute ) {
7076 elem.removeAttribute( jQuery.expando );
7085 function evalScript( i, elem ) {
7093 jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
7096 if ( elem.parentNode ) {
7097 elem.parentNode.removeChild( elem );
7104 var ralpha = /alpha\([^)]*\)/i,
7105 ropacity = /opacity=([^)]*)/,
7106 // fixed for IE9, see #8346
7107 rupper = /([A-Z]|^ms)/g,
7108 rnumpx = /^-?\d+(?:px)?$/i,
7110 rrelNum = /^([\-+])=([\-+.\de]+)/,
7112 cssShow = { position: "absolute", visibility: "hidden", display: "block" },
7113 cssWidth = [ "Left", "Right" ],
7114 cssHeight = [ "Top", "Bottom" ],
7120 jQuery.fn.css = function( name, value ) {
7121 // Setting 'undefined' is a no-op
7122 if ( arguments.length === 2 && value === undefined ) {
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 );
7134 // Add in style property hooks for overriding the default
7135 // behavior of getting and setting a style property
7138 get: function( elem, computed ) {
7140 // We should always get a number back from opacity
7141 var ret = curCSS( elem, "opacity", "opacity" );
7142 return ret === "" ? "1" : ret;
7145 return elem.style.opacity;
7151 // Exclude the following css properties to add px
7153 "fillOpacity": true,
7163 // Add in properties whose names you wish to fix before
7164 // setting or getting the value
7166 // normalize float css property
7167 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
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 ) {
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 ];
7181 name = jQuery.cssProps[ origName ] || origName;
7183 // Check if we're setting a value
7184 if ( value !== undefined ) {
7185 type = typeof value;
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 ) );
7194 // Make sure that NaN and null values aren't set. See: #7116
7195 if ( value == null || type === "number" && isNaN( value ) ) {
7199 // If a number was passed in, add 'px' to the (except for certain CSS properties)
7200 if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
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
7209 style[ name ] = value;
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 ) {
7219 // Otherwise just get the value from the style object
7220 return style[ name ];
7224 css: function( elem, name, extra ) {
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;
7232 // cssFloat needs a special treatment
7233 if ( name === "cssFloat" ) {
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 ) {
7241 // Otherwise, if a way to get the computed value exists, use that
7242 } else if ( curCSS ) {
7243 return curCSS( elem, name );
7247 // A method for quickly swapping in/out CSS properties to get correct calculations
7248 swap: function( elem, options, callback ) {
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 ];
7257 callback.call( elem );
7259 // Revert the old values
7260 for ( name in options ) {
7261 elem.style[ name ] = old[ name ];
7266 // DEPRECATED, Use jQuery.css() instead
7267 jQuery.curCSS = jQuery.css;
7269 jQuery.each(["height", "width"], function( i, name ) {
7270 jQuery.cssHooks[ name ] = {
7271 get: function( elem, computed, extra ) {
7275 if ( elem.offsetWidth !== 0 ) {
7276 return getWH( elem, name, extra );
7278 jQuery.swap( elem, cssShow, function() {
7279 val = getWH( elem, name, extra );
7287 set: function( elem, value ) {
7288 if ( rnumpx.test( value ) ) {
7289 // ignore negative width and height values #1599
7290 value = parseFloat( value );
7293 return value + "px";
7303 if ( !jQuery.support.opacity ) {
7304 jQuery.cssHooks.opacity = {
7305 get: function( elem, computed ) {
7306 // IE uses filters for opacity
7307 return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7308 ( parseFloat( RegExp.$1 ) / 100 ) + "" :
7309 computed ? "1" : "";
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 || "";
7318 // IE has trouble with opacity if it does not have layout
7319 // Force it by setting the zoom level
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, "" ) ) === "" ) {
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" );
7330 // if there there is no filter style applied in a css rule, we are done
7331 if ( currentStyle && !currentStyle.filter ) {
7336 // otherwise, set new filter values
7337 style.filter = ralpha.test( filter ) ?
7338 filter.replace( ralpha, opacity ) :
7339 filter + " " + opacity;
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
7353 jQuery.swap( elem, { "display": "inline-block" }, function() {
7355 ret = curCSS( elem, "margin-right", "marginRight" );
7357 ret = elem.style.marginRight;
7366 if ( document.defaultView && document.defaultView.getComputedStyle ) {
7367 getComputedStyle = function( elem, name ) {
7368 var ret, defaultView, computedStyle;
7370 name = name.replace( rupper, "-$1" ).toLowerCase();
7372 if ( !(defaultView = elem.ownerDocument.defaultView) ) {
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 );
7387 if ( document.documentElement.currentStyle ) {
7388 currentStyle = function( elem, name ) {
7389 var left, rsLeft, uncomputed,
7390 ret = elem.currentStyle && elem.currentStyle[ name ],
7393 // Avoid setting ret to empty string here
7394 // so we don't default to auto
7395 if ( ret === null && style && (uncomputed = style[ name ]) ) {
7399 // From the awesome hack by Dean Edwards
7400 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
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 ) ) {
7406 // Remember the original values
7408 rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
7410 // Put in the new values to get a computed value out
7412 elem.runtimeStyle.left = elem.currentStyle.left;
7414 style.left = name === "fontSize" ? "1em" : ( ret || 0 );
7415 ret = style.pixelLeft + "px";
7417 // Revert the changed values
7420 elem.runtimeStyle.left = rsLeft;
7424 return ret === "" ? "auto" : ret;
7428 curCSS = getComputedStyle || currentStyle;
7430 function getWH( elem, name, extra ) {
7432 // Start with offset property
7433 var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
7434 which = name === "width" ? cssWidth : cssHeight;
7437 if ( extra !== "border" ) {
7438 jQuery.each( which, function() {
7440 val -= parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
7442 if ( extra === "margin" ) {
7443 val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
7445 val -= parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
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;
7458 // Normalize "", auto, and prepare for extra
7459 val = parseFloat( val ) || 0;
7461 // Add padding, border, margin
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;
7468 if ( extra === "margin" ) {
7469 val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
7477 if ( jQuery.expr && jQuery.expr.filters ) {
7478 jQuery.expr.filters.hidden = function( elem ) {
7479 var width = elem.offsetWidth,
7480 height = elem.offsetHeight;
7482 return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
7485 jQuery.expr.filters.visible = function( elem ) {
7486 return !jQuery.expr.filters.hidden( elem );
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 = /^\/\//,
7504 rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
7505 rselectTextarea = /^(?:select|textarea)/i,
7506 rspacesAjax = /\s+/,
7507 rts = /([?&])_=[^&]*/,
7508 rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
7510 // Keep a copy of the old load method
7511 _load = jQuery.fn.load,
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
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
7531 // Document location
7534 // Document location segments
7537 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
7538 allTypes = ["*/"] + ["*"];
7540 // #8138, IE may throw an exception when accessing
7541 // a field from window.location if document.domain has been set
7543 ajaxLocation = location.href;
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;
7552 // Segment location into parts
7553 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7555 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7556 function addToPrefiltersOrTransports( structure ) {
7558 // dataTypeExpression is optional and defaults to "*"
7559 return function( dataTypeExpression, func ) {
7561 if ( typeof dataTypeExpression !== "string" ) {
7562 func = dataTypeExpression;
7563 dataTypeExpression = "*";
7566 if ( jQuery.isFunction( func ) ) {
7567 var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
7569 length = dataTypes.length,
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 ) || "*";
7583 list = structure[ dataType ] = structure[ dataType ] || [];
7584 // then we add to the structure accordingly
7585 list[ placeBefore ? "unshift" : "push" ]( func );
7591 // Base inspection function for prefilters and transports
7592 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
7593 dataType /* internal */, inspected /* internal */ ) {
7595 dataType = dataType || options.dataTypes[ 0 ];
7596 inspected = inspected || {};
7598 inspected[ dataType ] = true;
7600 var list = structure[ dataType ],
7602 length = list ? list.length : 0,
7603 executeOnly = ( structure === prefilters ),
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;
7614 options.dataTypes.unshift( selection );
7615 selection = inspectPrefiltersOrTransports(
7616 structure, options, originalOptions, jqXHR, selection, inspected );
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 );
7626 // unnecessary when only executing (prefilters)
7627 // but it'll be ignored by the caller in that case
7631 // A special extend for ajax options
7632 // that takes "flat" options (not to be deep extended)
7634 function ajaxExtend( target, src ) {
7636 flatOptions = jQuery.ajaxSettings.flatOptions || {};
7637 for ( key in src ) {
7638 if ( src[ key ] !== undefined ) {
7639 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
7643 jQuery.extend( true, target, deep );
7648 load: function( url, params, callback ) {
7649 if ( typeof url !== "string" && _load ) {
7650 return _load.apply( this, arguments );
7652 // Don't do a request if no elements are being requested
7653 } else if ( !this.length ) {
7657 var off = url.indexOf( " " );
7659 var selector = url.slice( off, url.length );
7660 url = url.slice( 0, off );
7663 // Default to a GET request
7666 // If the second parameter was provided
7668 // If it's a function
7669 if ( jQuery.isFunction( params ) ) {
7670 // We assume that it's the callback
7674 // Otherwise, build a param string
7675 } else if ( typeof params === "object" ) {
7676 params = jQuery.param( params, jQuery.ajaxSettings.traditional );
7683 // Request the remote document
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 ) {
7700 // See if a selector was specified
7701 self.html( selector ?
7702 // Create a dummy div to hold the results
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, ""))
7708 // Locate the specified elements
7711 // If not, just inject the full result
7716 self.each( callback, [ responseText, status, jqXHR ] );
7724 serialize: function() {
7725 return jQuery.param( this.serializeArray() );
7728 serializeArray: function() {
7729 return this.map(function(){
7730 return this.elements ? jQuery.makeArray( this.elements ) : this;
7733 return this.name && !this.disabled &&
7734 ( this.checked || rselectTextarea.test( this.nodeName ) ||
7735 rinput.test( this.type ) );
7737 .map(function( i, elem ){
7738 var val = jQuery( this ).val();
7740 return val == null ?
7742 jQuery.isArray( val ) ?
7743 jQuery.map( val, function( val, i ){
7744 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7746 { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7751 // Attach a bunch of functions for handling common AJAX events
7752 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
7753 jQuery.fn[ o ] = function( f ){
7754 return this.bind( o, f );
7758 jQuery.each( [ "get", "post" ], function( i, method ) {
7759 jQuery[ method ] = function( url, data, callback, type ) {
7760 // shift arguments if data argument was omitted
7761 if ( jQuery.isFunction( data ) ) {
7762 type = type || callback;
7767 return jQuery.ajax({
7779 getScript: function( url, callback ) {
7780 return jQuery.get( url, undefined, callback, "script" );
7783 getJSON: function( url, data, callback ) {
7784 return jQuery.get( url, data, callback, "json" );
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 ) {
7792 // Building a settings object
7793 ajaxExtend( target, jQuery.ajaxSettings );
7795 // Extending ajaxSettings
7797 target = jQuery.ajaxSettings;
7799 ajaxExtend( target, settings );
7805 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7808 contentType: "application/x-www-form-urlencoded",
7823 xml: "application/xml, text/xml",
7826 json: "application/json, text/javascript",
7838 text: "responseText"
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
7846 // Convert anything to text
7847 "* text": window.String,
7849 // Text to html (true = no transformation)
7852 // Evaluate text as a json expression
7853 "text json": jQuery.parseJSON,
7855 // Parse text as xml
7856 "text xml": jQuery.parseXML
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)
7869 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7870 ajaxTransport: addToPrefiltersOrTransports( transports ),
7873 ajax: function( url, options ) {
7875 // If url is an object, simulate pre-1.5 signature
7876 if ( typeof url === "object" ) {
7881 // Force options to be an object
7882 options = options || {};
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,
7895 deferred = jQuery.Deferred(),
7896 completeDeferred = jQuery.Callbacks( "once memory" ),
7897 // Status-dependent callbacks
7898 statusCode = s.statusCode || {},
7901 // Headers (they are sent all at once)
7902 requestHeaders = {},
7903 requestHeadersNames = {},
7905 responseHeadersString,
7911 // Cross-domain detection vars
7915 // To know if global events are to be dispatched
7924 // Caches the header
7925 setRequestHeader: function( name, value ) {
7927 var lname = name.toLowerCase();
7928 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7929 requestHeaders[ name ] = value;
7935 getAllResponseHeaders: function() {
7936 return state === 2 ? responseHeadersString : null;
7939 // Builds headers hashtable if needed
7940 getResponseHeader: function( key ) {
7942 if ( state === 2 ) {
7943 if ( !responseHeaders ) {
7944 responseHeaders = {};
7945 while( ( match = rheaders.exec( responseHeadersString ) ) ) {
7946 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7949 match = responseHeaders[ key.toLowerCase() ];
7951 return match === undefined ? null : match;
7954 // Overrides response content-type header
7955 overrideMimeType: function( type ) {
7962 // Cancel the request
7963 abort: function( statusText ) {
7964 statusText = statusText || "abort";
7966 transport.abort( statusText );
7968 done( 0, statusText );
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 ) {
7979 if ( state === 2 ) {
7983 // State is "done" now
7986 // Clear timeout if it exists
7987 if ( timeoutTimer ) {
7988 clearTimeout( timeoutTimer );
7991 // Dereference transport for early garbage collection
7992 // (no matter how long the jqXHR object will be used)
7993 transport = undefined;
7995 // Cache response headers
7996 responseHeadersString = headers || "";
7999 jqXHR.readyState = status > 0 ? 4 : 0;
8004 statusText = nativeStatusText,
8005 response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
8009 // If successful, handle type chaining
8010 if ( status >= 200 && status < 300 || status === 304 ) {
8012 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
8013 if ( s.ifModified ) {
8015 if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
8016 jQuery.lastModified[ ifModifiedKey ] = lastModified;
8018 if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
8019 jQuery.etag[ ifModifiedKey ] = etag;
8024 if ( status === 304 ) {
8026 statusText = "notmodified";
8033 success = ajaxConvert( s, response );
8034 statusText = "success";
8037 // We have a parsererror
8038 statusText = "parsererror";
8043 // We extract error from statusText
8044 // then normalize statusText and status for non-aborts
8046 if ( !statusText || status ) {
8047 statusText = "error";
8054 // Set data for the fake xhr object
8055 jqXHR.status = status;
8056 jqXHR.statusText = "" + ( nativeStatusText || statusText );
8060 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
8062 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
8065 // Status-dependent callbacks
8066 jqXHR.statusCode( statusCode );
8067 statusCode = undefined;
8069 if ( fireGlobals ) {
8070 globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
8071 [ jqXHR, s, isSuccess ? success : error ] );
8075 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
8077 if ( fireGlobals ) {
8078 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
8079 // Handle the global AJAX counter
8080 if ( !( --jQuery.active ) ) {
8081 jQuery.event.trigger( "ajaxStop" );
8087 deferred.promise( jqXHR );
8088 jqXHR.success = jqXHR.done;
8089 jqXHR.error = jqXHR.fail;
8090 jqXHR.complete = completeDeferred.add;
8092 // Status-dependent callbacks
8093 jqXHR.statusCode = function( map ) {
8097 for ( tmp in map ) {
8098 statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
8101 tmp = map[ jqXHR.status ];
8102 jqXHR.then( tmp, tmp );
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 ] + "//" );
8113 // Extract dataTypes list
8114 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
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 ) ) )
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 );
8132 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
8134 // If request was aborted inside a prefiler, stop there
8135 if ( state === 2 ) {
8139 // We can fire global events as of now if asked to
8140 fireGlobals = s.global;
8142 // Uppercase the type
8143 s.type = s.type.toUpperCase();
8145 // Determine if request has content
8146 s.hasContent = !rnoContent.test( s.type );
8148 // Watch for a new set of requests
8149 if ( fireGlobals && jQuery.active++ === 0 ) {
8150 jQuery.event.trigger( "ajaxStart" );
8153 // More options handling for requests with no content
8154 if ( !s.hasContent ) {
8156 // If data is available, append data to url
8158 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
8159 // #9682: remove data so that it's not used in an eventual retry
8163 // Get ifModifiedKey before adding the anti-cache parameter
8164 ifModifiedKey = s.url;
8166 // Add anti-cache in url if needed
8167 if ( s.cache === false ) {
8169 var ts = jQuery.now(),
8170 // try replacing _= if it is there
8171 ret = s.url.replace( rts, "$1_=" + ts );
8173 // if nothing was replaced, add timestamp to the end
8174 s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
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 );
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 ] );
8189 if ( jQuery.etag[ ifModifiedKey ] ) {
8190 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
8194 // Set the Accepts header for the server, depending on the dataType
8195 jqXHR.setRequestHeader(
8197 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
8198 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
8202 // Check for headers option
8203 for ( i in s.headers ) {
8204 jqXHR.setRequestHeader( i, s.headers[ i ] );
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
8215 // Install callbacks on deferreds
8216 for ( i in { success: 1, error: 1, complete: 1 } ) {
8217 jqXHR[ i ]( s[ i ] );
8221 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
8223 // If no transport, we auto-abort
8225 done( -1, "No Transport" );
8227 jqXHR.readyState = 1;
8228 // Send global event
8229 if ( fireGlobals ) {
8230 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
8233 if ( s.async && s.timeout > 0 ) {
8234 timeoutTimer = setTimeout( function(){
8235 jqXHR.abort( "timeout" );
8241 transport.send( requestHeaders, done );
8243 // Propagate exception as error if not done
8246 // Simply rethrow otherwise
8256 // Serialize an array of form elements or a set of
8257 // key/values into a query string
8258 param: function( a, traditional ) {
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 );
8266 // Set traditional to true for jQuery <= 1.3.2 behavior.
8267 if ( traditional === undefined ) {
8268 traditional = jQuery.ajaxSettings.traditional;
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 );
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 );
8286 // Return the resulting serialization
8287 return s.join( "&" ).replace( r20, "+" );
8291 function buildParams( prefix, obj, traditional, add ) {
8292 if ( jQuery.isArray( obj ) ) {
8293 // Serialize array item.
8294 jQuery.each( obj, function( i, v ) {
8295 if ( traditional || rbracket.test( prefix ) ) {
8296 // Treat each array item as a scalar.
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 );
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 );
8318 // Serialize scalar item.
8323 // This is still on the jQuery object... for now
8324 // Want to move this to jQuery.ajax some day
8327 // Counter for holding the number of active queries
8330 // Last-Modified header cache for next request
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
8341 function ajaxHandleResponses( s, jqXHR, responses ) {
8343 var contents = s.contents,
8344 dataTypes = s.dataTypes,
8345 responseFields = s.responseFields,
8351 // Fill responseXXX fields
8352 for ( type in responseFields ) {
8353 if ( type in responses ) {
8354 jqXHR[ responseFields[type] ] = responses[ type ];
8358 // Remove auto dataType and get content-type in the process
8359 while( dataTypes[ 0 ] === "*" ) {
8361 if ( ct === undefined ) {
8362 ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
8366 // Check if we're dealing with a known content-type
8368 for ( type in contents ) {
8369 if ( contents[ type ] && contents[ type ].test( ct ) ) {
8370 dataTypes.unshift( type );
8376 // Check to see if we have a response for the expected dataType
8377 if ( dataTypes[ 0 ] in responses ) {
8378 finalDataType = dataTypes[ 0 ];
8380 // Try convertible dataTypes
8381 for ( type in responses ) {
8382 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8383 finalDataType = type;
8386 if ( !firstDataType ) {
8387 firstDataType = type;
8390 // Or just use first one
8391 finalDataType = finalDataType || firstDataType;
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 );
8401 return responses[ finalDataType ];
8405 // Chain conversions given the request and the original response
8406 function ajaxConvert( s, response ) {
8408 // Apply the dataFilter if provided
8409 if ( s.dataFilter ) {
8410 response = s.dataFilter( response, s.dataType );
8413 var dataTypes = s.dataTypes,
8417 length = dataTypes.length,
8419 // Current and previous dataTypes
8420 current = dataTypes[ 0 ],
8422 // Conversion expression
8424 // Conversion function
8426 // Conversion functions (transitive conversion)
8430 // For each dataType in the chain
8431 for ( i = 1; i < length; i++ ) {
8433 // Create converters map
8434 // with lowercased keys
8436 for ( key in s.converters ) {
8437 if ( typeof key === "string" ) {
8438 converters[ key.toLowerCase() ] = s.converters[ key ];
8443 // Get the dataTypes
8445 current = dataTypes[ i ];
8447 // If current is auto dataType, update it to prev
8448 if ( current === "*" ) {
8450 // If no auto and dataTypes are actually different
8451 } else if ( prev !== "*" && prev !== current ) {
8453 // Get the converter
8454 conversion = prev + " " + current;
8455 conv = converters[ conversion ] || converters[ "* " + current ];
8457 // If there is no direct converter, search transitively
8460 for ( conv1 in converters ) {
8461 tmp = conv1.split( " " );
8462 if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
8463 conv2 = converters[ tmp[1] + " " + current ];
8465 conv1 = converters[ conv1 ];
8466 if ( conv1 === true ) {
8468 } else if ( conv2 === true ) {
8476 // If we found no converter, dispatch an error
8477 if ( !( conv || conv2 ) ) {
8478 jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
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) );
8493 var jsc = jQuery.now(),
8494 jsre = /(\=)\?(&|$)|\?\?/i;
8496 // Default jsonp settings
8499 jsonpCallback: function() {
8500 return jQuery.expando + "_" + ( jsc++ );
8504 // Detect, normalize options and install callbacks for jsonp requests
8505 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8507 var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
8508 ( typeof s.data === "string" );
8510 if ( s.dataTypes[ 0 ] === "jsonp" ||
8511 s.jsonp !== false && ( jsre.test( s.url ) ||
8512 inspectData && jsre.test( s.data ) ) ) {
8514 var responseContainer,
8515 jsonpCallback = s.jsonpCallback =
8516 jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
8517 previous = window[ jsonpCallback ],
8520 replace = "$1" + jsonpCallback + "$2";
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 );
8528 if ( s.data === data ) {
8529 // Add callback manually
8530 url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
8539 window[ jsonpCallback ] = function( response ) {
8540 responseContainer = [ response ];
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 ] );
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" );
8558 return responseContainer[ 0 ];
8561 // force json dataType
8562 s.dataTypes[ 0 ] = "json";
8564 // Delegate to script
8572 // Install script dataType
8575 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8578 script: /javascript|ecmascript/
8581 "text script": function( text ) {
8582 jQuery.globalEval( text );
8588 // Handle cache's special case and global
8589 jQuery.ajaxPrefilter( "script", function( s ) {
8590 if ( s.cache === undefined ) {
8593 if ( s.crossDomain ) {
8599 // Bind script tag hack transport
8600 jQuery.ajaxTransport( "script", function(s) {
8602 // This transport only deals with cross domain requests
8603 if ( s.crossDomain ) {
8606 head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
8610 send: function( _, callback ) {
8612 script = document.createElement( "script" );
8614 script.async = "async";
8616 if ( s.scriptCharset ) {
8617 script.charset = s.scriptCharset;
8622 // Attach handlers for all browsers
8623 script.onload = script.onreadystatechange = function( _, isAbort ) {
8625 if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8627 // Handle memory leak in IE
8628 script.onload = script.onreadystatechange = null;
8630 // Remove the script
8631 if ( head && script.parentNode ) {
8632 head.removeChild( script );
8635 // Dereference the script
8638 // Callback if not abort
8640 callback( 200, "success" );
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 );
8651 script.onload( 0, 1 );
8661 var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8662 xhrOnUnloadAbort = window.ActiveXObject ? function() {
8663 // Abort all pending requests
8664 for ( var key in xhrCallbacks ) {
8665 xhrCallbacks[ key ]( 0, 1 );
8671 // Functions to create xhrs
8672 function createStandardXHR() {
8674 return new window.XMLHttpRequest();
8678 function createActiveXHR() {
8680 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
8684 // Create the request object
8685 // (This is still attached to ajaxSettings for backward compatibility)
8686 jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8687 /* Microsoft failed to properly
8688 * implement the XMLHttpRequest in IE7 (can't request local files),
8689 * so we use the ActiveXObject when it is available
8690 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8691 * we need a fallback.
8694 return !this.isLocal && createStandardXHR() || createActiveXHR();
8696 // For all other browsers, use the standard XMLHttpRequest object
8699 // Determine support properties
8701 jQuery.extend( jQuery.support, {
8703 cors: !!xhr && ( "withCredentials" in xhr )
8705 })( jQuery.ajaxSettings.xhr() );
8707 // Create transport if the browser can provide an xhr
8708 if ( jQuery.support.ajax ) {
8710 jQuery.ajaxTransport(function( s ) {
8711 // Cross domain only allowed if supported through XMLHttpRequest
8712 if ( !s.crossDomain || jQuery.support.cors ) {
8717 send: function( headers, complete ) {
8725 // Passing null username, generates a login popup on Opera (#2865)
8727 xhr.open( s.type, s.url, s.async, s.username, s.password );
8729 xhr.open( s.type, s.url, s.async );
8732 // Apply custom fields if provided
8733 if ( s.xhrFields ) {
8734 for ( i in s.xhrFields ) {
8735 xhr[ i ] = s.xhrFields[ i ];
8739 // Override mime type if needed
8740 if ( s.mimeType && xhr.overrideMimeType ) {
8741 xhr.overrideMimeType( s.mimeType );
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";
8753 // Need an extra try/catch for cross domain requests in Firefox 3
8755 for ( i in headers ) {
8756 xhr.setRequestHeader( i, headers[ i ] );
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 );
8766 callback = function( _, isAbort ) {
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)
8779 // Was never called and is aborted or complete
8780 if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8783 callback = undefined;
8785 // Do not keep as active anymore
8787 xhr.onreadystatechange = jQuery.noop;
8788 if ( xhrOnUnloadAbort ) {
8789 delete xhrCallbacks[ handle ];
8795 // Abort it manually if needed
8796 if ( xhr.readyState !== 4 ) {
8800 status = xhr.status;
8801 responseHeaders = xhr.getAllResponseHeaders();
8803 xml = xhr.responseXML;
8805 // Construct response list
8806 if ( xml && xml.documentElement /* #4958 */ ) {
8807 responses.xml = xml;
8809 responses.text = xhr.responseText;
8811 // Firefox throws an exception when accessing
8812 // statusText for faulty cross-domain requests
8814 statusText = xhr.statusText;
8816 // We normalize with Webkit giving an empty statusText
8820 // Filter status for non standard behaviors
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 ) {
8833 } catch( firefoxAccessException ) {
8835 complete( -1, firefoxAccessException );
8839 // Call complete if needed
8841 complete( status, statusText, responses, responseHeaders );
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 ) {
8852 if ( xhrOnUnloadAbort ) {
8853 // Create the active xhrs callbacks list if needed
8854 // and attach the unload handler
8855 if ( !xhrCallbacks ) {
8857 jQuery( window ).unload( xhrOnUnloadAbort );
8859 // Add to list of active xhrs callbacks
8860 xhrCallbacks[ handle ] = callback;
8862 xhr.onreadystatechange = callback;
8879 var elemdisplay = {},
8881 rfxtypes = /^(?:toggle|show|hide)$/,
8882 rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
8885 // height animations
8886 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
8888 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
8889 // opacity animations
8895 show: function( speed, easing, callback ) {
8898 if ( speed || speed === 0 ) {
8899 return this.animate( genFx("show", 3), speed, easing, callback );
8902 for ( var i = 0, j = this.length; i < j; i++ ) {
8906 display = elem.style.display;
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 = "";
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) );
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++ ) {
8929 display = elem.style.display;
8931 if ( display === "" || display === "none" ) {
8932 elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
8941 hide: function( speed, easing, callback ) {
8942 if ( speed || speed === 0 ) {
8943 return this.animate( genFx("hide", 3), speed, easing, callback);
8950 for ( ; i < j; i++ ) {
8953 display = jQuery.css( elem, "display" );
8955 if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
8956 jQuery._data( elem, "olddisplay", display );
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";
8973 // Save the old toggle function
8974 _toggle: jQuery.fn.toggle,
8976 toggle: function( fn, fn2, callback ) {
8977 var bool = typeof fn === "boolean";
8979 if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
8980 this._toggle.apply( this, arguments );
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" ]();
8989 this.animate(genFx("toggle", 3), fn, fn2, callback);
8995 fadeTo: function( speed, to, easing, callback ) {
8996 return this.filter(":hidden").css("opacity", 0).show().end()
8997 .animate({opacity: to}, speed, easing, callback);
9000 animate: function( prop, speed, easing, callback ) {
9001 var optall = jQuery.speed( speed, easing, callback );
9003 if ( jQuery.isEmptyObject( prop ) ) {
9004 return this.each( optall.complete, [ false ] );
9007 // Do not change referenced properties as per-property easing will be lost
9008 prop = jQuery.extend( {}, prop );
9010 function doAnimation() {
9011 // XXX 'this' does not always have a nodeName when running the
9014 if ( optall.queue === false ) {
9015 jQuery._mark( this );
9018 var opt = jQuery.extend( {}, optall ),
9019 isElement = this.nodeType === 1,
9020 hidden = isElement && jQuery(this).is(":hidden"),
9022 parts, start, end, unit,
9025 // will store per property easing and be used to determine when an animation is complete
9026 opt.animatedProperties = {};
9030 // property name normalization
9031 name = jQuery.camelCase( p );
9033 prop[ name ] = prop[ p ];
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 ];
9044 opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
9047 if ( val === "hide" && hidden || val === "show" && !hidden ) {
9048 return opt.complete.call( this );
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 ];
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" ) {
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";
9069 this.style.zoom = 1;
9075 if ( opt.overflow != null ) {
9076 this.style.overflow = "hidden";
9080 e = new jQuery.fx( this, opt, p );
9083 if ( rfxtypes.test( val ) ) {
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 );
9089 jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
9096 parts = rfxnum.exec( val );
9100 end = parseFloat( parts[2] );
9101 unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
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);
9110 // If a +=/-= token was provided, we're doing a relative animation
9112 end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
9115 e.custom( start, end, unit );
9118 e.custom( start, val, "" );
9123 // For JS strict compliance
9127 return optall.queue === false ?
9128 this.each( doAnimation ) :
9129 this.queue( optall.queue, doAnimation );
9132 stop: function( type, clearQueue, gotoEnd ) {
9133 if ( typeof type !== "string" ) {
9134 gotoEnd = clearQueue;
9138 if ( clearQueue && type !== false ) {
9139 this.queue( type || "fx", [] );
9142 return this.each(function() {
9145 timers = jQuery.timers,
9146 data = jQuery._data( this );
9148 // clear marker counters if we know they won't be
9150 jQuery._unmark( true, this );
9153 function stopQueue( elem, data, i ) {
9154 var hooks = data[ i ];
9155 jQuery.removeData( elem, i, true );
9156 hooks.stop( gotoEnd );
9159 if ( type == null ) {
9161 if ( data[ i ].stop && i.indexOf(".run") === i.length - 4 ) {
9162 stopQueue( this, data, i );
9165 } else if ( data[ i = type + ".run" ] && data[ i ].stop ){
9166 stopQueue( this, data, i );
9169 for ( i = timers.length; i--; ) {
9170 if ( timers[ i ].elem === this && (type == null || timers[ i ].queue === type) ) {
9173 // force the next step to be the last
9174 timers[ i ]( true );
9176 timers[ i ].saveState();
9179 timers.splice( i, 1 );
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 );
9194 // Animations created synchronously will run synchronously
9195 function createFxNow() {
9196 setTimeout( clearFxNow, 0 );
9197 return ( fxNow = jQuery.now() );
9200 function clearFxNow() {
9204 // Generate parameters to create a standard animation
9205 function genFx( type, num ) {
9208 jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
9215 // Generate shortcuts for custom animations
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 );
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,
9235 easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
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;
9241 // normalize opt.queue - true/undefined/null -> "fx"
9242 if ( opt.queue == null || opt.queue === true ) {
9247 opt.old = opt.complete;
9249 opt.complete = function( noUnmark ) {
9250 if ( jQuery.isFunction( opt.old ) ) {
9251 opt.old.call( this );
9255 jQuery.dequeue( this, opt.queue );
9256 } else if ( noUnmark !== false ) {
9257 jQuery._unmark( this );
9265 linear: function( p, n, firstNum, diff ) {
9266 return firstNum + diff * p;
9268 swing: function( p, n, firstNum, diff ) {
9269 return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
9275 fx: function( elem, options, prop ) {
9276 this.options = options;
9280 options.orig = options.orig || {};
9285 jQuery.fx.prototype = {
9286 // Simple function for setting a style value
9287 update: function() {
9288 if ( this.options.step ) {
9289 this.options.step.call( this.elem, this.now, this );
9292 ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
9295 // Get the current size
9297 if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
9298 return this.elem[ this.prop ];
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;
9309 // Start an animation from one number to another
9310 custom: function( from, to, unit ) {
9314 this.startTime = fxNow || createFxNow();
9316 this.now = this.start = from;
9317 this.pos = this.state = 0;
9318 this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
9320 function t( gotoEnd ) {
9321 return self.step( gotoEnd );
9324 t.queue = this.options.queue;
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 );
9332 if ( t() && jQuery.timers.push(t) && !timerId ) {
9333 timerId = setInterval( fx.tick, fx.interval );
9337 // Simple 'show' function
9339 var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
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;
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 );
9351 this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
9354 // Start by showing the element
9355 jQuery( this.elem ).show();
9358 // Simple '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;
9364 // Begin the animation
9365 this.custom( this.cur(), 0 );
9368 // Each step of an animation
9369 step: function( gotoEnd ) {
9371 t = fxNow || createFxNow(),
9374 options = this.options;
9376 if ( gotoEnd || t >= options.duration + this.startTime ) {
9377 this.now = this.end;
9378 this.pos = this.state = 1;
9381 options.animatedProperties[ this.prop ] = true;
9383 for ( p in options.animatedProperties ) {
9384 if ( options.animatedProperties[ p ] !== true ) {
9390 // Reset the overflow
9391 if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
9393 jQuery.each( [ "", "X", "Y" ], function( index, value ) {
9394 elem.style[ "overflow" + value ] = options.overflow[ index ];
9398 // Hide the element if the "hide" operation was done
9399 if ( options.hide ) {
9400 jQuery( elem ).hide();
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 );
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
9417 complete = options.complete;
9420 options.complete = false;
9421 complete.call( elem );
9428 // classical easing cannot be used with an Infinity duration
9429 if ( options.duration == Infinity ) {
9432 n = t - this.startTime;
9433 this.state = n / options.duration;
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 );
9439 // Perform the next step of the animation
9447 jQuery.extend( jQuery.fx, {
9450 timers = jQuery.timers,
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 );
9461 if ( !timers.length ) {
9469 clearInterval( timerId );
9481 opacity: function( fx ) {
9482 jQuery.style( fx.elem, "opacity", fx.now );
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;
9489 fx.elem[ fx.prop ] = fx.now;
9495 // Adds width/height step functions
9496 // Do not set anything below 0
9497 jQuery.each([ "width", "height" ], function( i, prop ) {
9498 jQuery.fx.step[ prop ] = function( fx ) {
9499 jQuery.style( fx.elem, prop, Math.max(0, fx.now) );
9503 if ( jQuery.expr && jQuery.expr.filters ) {
9504 jQuery.expr.filters.animated = function( elem ) {
9505 return jQuery.grep(jQuery.timers, function( fn ) {
9506 return elem === fn.elem;
9511 // Try to restore the default display value of an element
9512 function defaultDisplay( nodeName ) {
9514 if ( !elemdisplay[ nodeName ] ) {
9516 var body = document.body,
9517 elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
9518 display = elem.css( "display" );
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
9526 iframe = document.createElement( "iframe" );
9527 iframe.frameBorder = iframe.width = iframe.height = 0;
9530 body.appendChild( iframe );
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>" );
9541 elem = iframeDoc.createElement( nodeName );
9543 iframeDoc.body.appendChild( elem );
9545 display = jQuery.css( elem, "display" );
9546 body.removeChild( iframe );
9549 // Store the correct default display
9550 elemdisplay[ nodeName ] = display;
9553 return elemdisplay[ nodeName ];
9559 var rtable = /^t(?:able|d|h)$/i,
9560 rroot = /^(?:body|html)$/i;
9562 if ( "getBoundingClientRect" in document.documentElement ) {
9563 jQuery.fn.offset = function( options ) {
9564 var elem = this[0], box;
9567 return this.each(function( i ) {
9568 jQuery.offset.setOffset( this, options, i );
9572 if ( !elem || !elem.ownerDocument ) {
9576 if ( elem === elem.ownerDocument.body ) {
9577 return jQuery.offset.bodyOffset( elem );
9581 box = elem.getBoundingClientRect();
9584 var doc = elem.ownerDocument,
9585 docElem = doc.documentElement;
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 };
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;
9601 return { top: top, left: left };
9605 jQuery.fn.offset = function( options ) {
9609 return this.each(function( i ) {
9610 jQuery.offset.setOffset( this, options, i );
9614 if ( !elem || !elem.ownerDocument ) {
9618 if ( elem === elem.ownerDocument.body ) {
9619 return jQuery.offset.bodyOffset( elem );
9623 offsetParent = elem.offsetParent,
9624 prevOffsetParent = elem,
9625 doc = elem.ownerDocument,
9626 docElem = doc.documentElement,
9628 defaultView = doc.defaultView,
9629 prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
9630 top = elem.offsetTop,
9631 left = elem.offsetLeft;
9633 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
9634 if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
9638 computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
9639 top -= elem.scrollTop;
9640 left -= elem.scrollLeft;
9642 if ( elem === offsetParent ) {
9643 top += elem.offsetTop;
9644 left += elem.offsetLeft;
9646 if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
9647 top += parseFloat( computedStyle.borderTopWidth ) || 0;
9648 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
9651 prevOffsetParent = offsetParent;
9652 offsetParent = elem.offsetParent;
9655 if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
9656 top += parseFloat( computedStyle.borderTopWidth ) || 0;
9657 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
9660 prevComputedStyle = computedStyle;
9663 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
9664 top += body.offsetTop;
9665 left += body.offsetLeft;
9668 if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
9669 top += Math.max( docElem.scrollTop, body.scrollTop );
9670 left += Math.max( docElem.scrollLeft, body.scrollLeft );
9673 return { top: top, left: left };
9679 bodyOffset: function( body ) {
9680 var top = body.offsetTop,
9681 left = body.offsetLeft;
9683 if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
9684 top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
9685 left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
9688 return { top: top, left: left };
9691 setOffset: function( elem, options, i ) {
9692 var position = jQuery.css( elem, "position" );
9694 // set position first, in-case top/left are set even on static elem
9695 if ( position === "static" ) {
9696 elem.style.position = "relative";
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;
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;
9712 curTop = parseFloat( curCSSTop ) || 0;
9713 curLeft = parseFloat( curCSSLeft ) || 0;
9716 if ( jQuery.isFunction( options ) ) {
9717 options = options.call( elem, i, curOffset );
9720 if ( options.top != null ) {
9721 props.top = ( options.top - curOffset.top ) + curTop;
9723 if ( options.left != null ) {
9724 props.left = ( options.left - curOffset.left ) + curLeft;
9727 if ( "using" in options ) {
9728 options.using.call( elem, props );
9730 curElem.css( props );
9738 position: function() {
9745 // Get *real* offsetParent
9746 offsetParent = this.offsetParent(),
9748 // Get correct offsets
9749 offset = this.offset(),
9750 parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
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;
9758 // Add offsetParent borders
9759 parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
9760 parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
9762 // Subtract the two offsets
9764 top: offset.top - parentOffset.top,
9765 left: offset.left - parentOffset.left
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;
9775 return offsetParent;
9781 // Create scrollLeft and scrollTop methods
9782 jQuery.each( ["Left", "Top"], function( i, name ) {
9783 var method = "scroll" + name;
9785 jQuery.fn[ method ] = function( val ) {
9788 if ( val === undefined ) {
9795 win = getWindow( elem );
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 ] :
9804 // Set the scroll offset
9805 return this.each(function() {
9806 win = getWindow( this );
9810 !i ? val : jQuery( win ).scrollLeft(),
9811 i ? val : jQuery( win ).scrollTop()
9815 this[ method ] = val;
9821 function getWindow( elem ) {
9822 return jQuery.isWindow( elem ) ?
9824 elem.nodeType === 9 ?
9825 elem.defaultView || elem.parentWindow :
9832 // Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
9833 jQuery.each([ "Height", "Width" ], function( i, name ) {
9835 var type = name.toLowerCase();
9837 // innerHeight and innerWidth
9838 jQuery.fn[ "inner" + name ] = function() {
9842 parseFloat( jQuery.css( elem, type, "padding" ) ) :
9847 // outerHeight and outerWidth
9848 jQuery.fn[ "outer" + name ] = function( margin ) {
9852 parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
9857 jQuery.fn[ type ] = function( size ) {
9858 // Get window width or height
9861 return size == null ? null : this;
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 ]() ) );
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;
9879 // Get document width or height
9880 } else if ( elem.nodeType === 9 ) {
9881 // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
9883 elem.documentElement["client" + name],
9884 elem.body["scroll" + name], elem.documentElement["scroll" + name],
9885 elem.body["offset" + name], elem.documentElement["offset" + name]
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 );
9893 return jQuery.isNumeric( ret ) ? ret : orig;
9895 // Set the width or height on the element (default to pixels if value is unitless)
9897 return this.css( type, typeof size === "string" ? size : size + "px" );
9904 // Expose jQuery to the global object
9905 window.jQuery = window.$ = jQuery;
9907 </script><script type="text/javascript">/*!
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
9914 * http://docs.jquery.com/UI
9916 (function( $, undefined ) {
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
9922 if ( $.ui.version ) {
9935 COMMAND_LEFT: 91, // COMMAND
9946 MENU: 93, // COMMAND_RIGHT
9948 NUMPAD_DECIMAL: 110,
9951 NUMPAD_MULTIPLY: 106,
9952 NUMPAD_SUBTRACT: 109,
9961 WINDOWS: 91 // COMMAND
9967 propAttr: $.fn.prop || $.fn.attr,
9970 focus: function( delay, fn ) {
9971 return typeof delay === "number" ?
9972 this.each(function() {
9974 setTimeout(function() {
9981 this._focus.apply( this, arguments );
9984 scrollParent: function() {
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));
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));
9996 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
9999 zIndex: function( zIndex ) {
10000 if ( zIndex !== undefined ) {
10001 return this.css( "zIndex", zIndex );
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 ) {
10021 elem = elem.parent();
10028 disableSelection: function() {
10029 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
10030 ".ui-disableSelection", function( event ) {
10031 event.preventDefault();
10035 enableSelection: function() {
10036 return this.unbind( ".ui-disableSelection" );
10040 $.each( [ "Width", "Height" ], function( i, name ) {
10041 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
10042 type = name.toLowerCase(),
10044 innerWidth: $.fn.innerWidth,
10045 innerHeight: $.fn.innerHeight,
10046 outerWidth: $.fn.outerWidth,
10047 outerHeight: $.fn.outerHeight
10050 function reduce( elem, size, border, margin ) {
10051 $.each( side, function() {
10052 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
10054 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
10057 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
10063 $.fn[ "inner" + name ] = function( size ) {
10064 if ( size === undefined ) {
10065 return orig[ "inner" + name ].call( this );
10068 return this.each(function() {
10069 $( this ).css( type, reduce( this, size ) + "px" );
10073 $.fn[ "outer" + name] = function( size, margin ) {
10074 if ( typeof size !== "number" ) {
10075 return orig[ "outer" + name ].call( this, size );
10078 return this.each(function() {
10079 $( this).css( type, reduce( this, size, true, margin ) + "px" );
10085 function focusable( element, isTabIndexNotNaN ) {
10086 var nodeName = element.nodeName.toLowerCase();
10087 if ( "area" === nodeName ) {
10088 var map = element.parentNode,
10089 mapName = map.name,
10091 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
10094 img = $( "img[usemap=#" + mapName + "]" )[0];
10095 return !!img && visible( img );
10097 return ( /input|select|textarea|button|object/.test( nodeName )
10098 ? !element.disabled
10100 ? element.href || isTabIndexNotNaN
10101 : isTabIndexNotNaN)
10102 // the element and all of its ancestors must be visible
10103 && visible( element );
10106 function visible( element ) {
10107 return !$( element ).parents().andSelf().filter(function() {
10108 return $.curCSS( this, "visibility" ) === "hidden" ||
10109 $.expr.filters.hidden( this );
10113 $.extend( $.expr[ ":" ], {
10114 data: function( elem, i, match ) {
10115 return !!$.data( elem, match[ 3 ] );
10118 focusable: function( element ) {
10119 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
10122 tabbable: function( element ) {
10123 var tabIndex = $.attr( element, "tabindex" ),
10124 isTabIndexNaN = isNaN( tabIndex );
10125 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
10131 var body = document.body,
10132 div = body.appendChild( div = document.createElement( "div" ) );
10134 $.extend( div.style, {
10135 minHeight: "100px",
10141 $.support.minHeight = div.offsetHeight === 100;
10142 $.support.selectstart = "onselectstart" in div;
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";
10155 // $.ui.plugin is deprecated. Use the proxy pattern instead.
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 ] ] );
10164 call: function( instance, name, args ) {
10165 var set = instance.plugins[ name ];
10166 if ( !set || !instance.element[ 0 ].parentNode ) {
10170 for ( var i = 0; i < set.length; i++ ) {
10171 if ( instance.options[ set[ i ][ 0 ] ] ) {
10172 set[ i ][ 1 ].apply( instance.element, args );
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 );
10185 // only used by resizable
10186 hasScroll: function( el, a ) {
10188 //If overflow is hidden, the element might have extra content, but the user wants to hide it
10189 if ( $( el ).css( "overflow" ) === "hidden") {
10193 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
10196 if ( el[ scroll ] > 0 ) {
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
10204 has = ( el[ scroll ] > 0 );
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 ) );
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 );
10222 * jQuery UI Widget 1.8.16
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
10228 * http://docs.jquery.com/UI/Widget
10230 (function( $, undefined ) {
10233 if ( $.cleanData ) {
10234 var _cleanData = $.cleanData;
10235 $.cleanData = function( elems ) {
10236 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
10238 $( elem ).triggerHandler( "remove" );
10239 // http://bugs.jquery.com/ticket/8235
10242 _cleanData( elems );
10245 var _remove = $.fn.remove;
10246 $.fn.remove = function( selector, keepData ) {
10247 return this.each(function() {
10249 if ( !selector || $.filter( selector, [ this ] ).length ) {
10250 $( "*", this ).add( [ this ] ).each(function() {
10252 $( this ).triggerHandler( "remove" );
10253 // http://bugs.jquery.com/ticket/8235
10258 return _remove.call( $(this), selector, keepData );
10263 $.widget = function( name, base, prototype ) {
10264 var namespace = name.split( "." )[ 0 ],
10266 name = name.split( "." )[ 1 ];
10267 fullName = namespace + "-" + name;
10269 if ( !prototype ) {
10274 // create selector for plugin
10275 $.expr[ ":" ][ fullName ] = function( elem ) {
10276 return !!$.data( elem, name );
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 );
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
10291 // $.each( basePrototype, function( key, val ) {
10292 // if ( $.isPlainObject(val) ) {
10293 // basePrototype[ key ] = $.extend( {}, val );
10296 basePrototype.options = $.extend( true, {}, basePrototype.options );
10297 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
10298 namespace: namespace,
10300 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
10301 widgetBaseClass: fullName
10304 $.widget.bridge( name, $[ namespace ][ name ] );
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;
10313 // allow multiple hashes to be passed on init
10314 options = !isMethodCall && args.length ?
10315 $.extend.apply( null, [ true, options ].concat(args) ) :
10318 // prevent calls to internal methods
10319 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
10320 return returnValue;
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 ) :
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 + "'";
10334 // if ( !$.isFunction( instance[options] ) ) {
10335 // throw "no such method '" + options + "' for " + name + " widget instance";
10337 // var methodValue = instance[ options ].apply( instance, args );
10338 if ( methodValue !== instance && methodValue !== undefined ) {
10339 returnValue = methodValue;
10344 this.each(function() {
10345 var instance = $.data( this, name );
10347 instance.option( options || {} )._init();
10349 $.data( this, name, new object( options, this ) );
10354 return returnValue;
10358 $.Widget = function( options, element ) {
10359 // allow instantiation without initializing for simple inheritance
10360 if ( arguments.length ) {
10361 this._createWidget( options, element );
10365 $.Widget.prototype = {
10366 widgetName: "widget",
10367 widgetEventPrefix: "",
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, {},
10378 this._getCreateOptions(),
10382 this.element.bind( "remove." + this.widgetName, function() {
10387 this._trigger( "create" );
10390 _getCreateOptions: function() {
10391 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
10393 _create: function() {},
10394 _init: function() {},
10396 destroy: function() {
10398 .unbind( "." + this.widgetName )
10399 .removeData( this.widgetName );
10401 .unbind( "." + this.widgetName )
10402 .removeAttr( "aria-disabled" )
10404 this.widgetBaseClass + "-disabled " +
10405 "ui-state-disabled" );
10408 widget: function() {
10409 return this.element;
10412 option: function( key, value ) {
10415 if ( arguments.length === 0 ) {
10416 // don't return a reference to the internal hash
10417 return $.extend( {}, this.options );
10420 if (typeof key === "string" ) {
10421 if ( value === undefined ) {
10422 return this.options[ key ];
10425 options[ key ] = value;
10428 this._setOptions( options );
10432 _setOptions: function( options ) {
10434 $.each( options, function( key, value ) {
10435 self._setOption( key, value );
10440 _setOption: function( key, value ) {
10441 this.options[ key ] = value;
10443 if ( key === "disabled" ) {
10445 [ value ? "addClass" : "removeClass"](
10446 this.widgetBaseClass + "-disabled" + " " +
10447 "ui-state-disabled" )
10448 .attr( "aria-disabled", value );
10454 enable: function() {
10455 return this._setOption( "disabled", false );
10457 disable: function() {
10458 return this._setOption( "disabled", true );
10461 _trigger: function( type, event, data ) {
10462 var callback = this.options[ type ];
10464 event = $.Event( event );
10465 event.type = ( type === this.widgetEventPrefix ?
10467 this.widgetEventPrefix + type ).toLowerCase();
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 ];
10480 this.element.trigger( event, data );
10482 return !( $.isFunction(callback) &&
10483 callback.call( this.element[0], event, data ) === false ||
10484 event.isDefaultPrevented() );
10490 * jQuery UI Mouse 1.8.16
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
10496 * http://docs.jquery.com/UI/Mouse
10499 * jquery.ui.widget.js
10501 (function( $, undefined ) {
10503 var mouseHandled = false;
10504 $( document ).mouseup( function( e ) {
10505 mouseHandled = false;
10508 $.widget("ui.mouse", {
10510 cancel: ':input,option',
10514 _mouseInit: function() {
10518 .bind('mousedown.'+this.widgetName, function(event) {
10519 return self._mouseDown(event);
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();
10529 this.started = false;
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);
10538 _mouseDown: function(event) {
10539 // don't let more than one widget handle mouseStart
10540 if( mouseHandled ) { return };
10542 // we may have missed mouseup (out of window)
10543 (this._mouseStarted && this._mouseUp(event));
10545 this._mouseDownEvent = event;
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)) {
10556 this.mouseDelayMet = !this.options.delay;
10557 if (!this.mouseDelayMet) {
10558 this._mouseDelayTimer = setTimeout(function() {
10559 self.mouseDelayMet = true;
10560 }, this.options.delay);
10563 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
10564 this._mouseStarted = (this._mouseStart(event) !== false);
10565 if (!this._mouseStarted) {
10566 event.preventDefault();
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');
10576 // these delegates are required to keep context
10577 this._mouseMoveDelegate = function(event) {
10578 return self._mouseMove(event);
10580 this._mouseUpDelegate = function(event) {
10581 return self._mouseUp(event);
10584 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
10585 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
10587 event.preventDefault();
10589 mouseHandled = true;
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);
10599 if (this._mouseStarted) {
10600 this._mouseDrag(event);
10601 return event.preventDefault();
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));
10610 return !this._mouseStarted;
10613 _mouseUp: function(event) {
10615 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
10616 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
10618 if (this._mouseStarted) {
10619 this._mouseStarted = false;
10621 if (event.target == this._mouseDownEvent.target) {
10622 $.data(event.target, this.widgetName + '.preventClickEvent', true);
10625 this._mouseStop(event);
10631 _mouseDistanceMet: function(event) {
10633 Math.abs(this._mouseDownEvent.pageX - event.pageX),
10634 Math.abs(this._mouseDownEvent.pageY - event.pageY)
10635 ) >= this.options.distance
10639 _mouseDelayMet: function(event) {
10640 return this.mouseDelayMet;
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; }
10652 * jQuery UI Draggable 1.8.16
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
10658 * http://docs.jquery.com/UI/Draggables
10661 * jquery.ui.core.js
10662 * jquery.ui.mouse.js
10663 * jquery.ui.widget.js
10665 (function( $, undefined ) {
10667 $.widget("ui.draggable", $.ui.mouse, {
10668 widgetEventPrefix: "drag",
10671 appendTo: "parent",
10673 connectToSortable: false,
10674 containment: false,
10679 helper: "original",
10682 refreshPositions: false,
10684 revertDuration: 500,
10687 scrollSensitivity: 20,
10695 _create: function() {
10697 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
10698 this.element[0].style.position = 'relative';
10700 (this.options.addClasses && this.element.addClass("ui-draggable"));
10701 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
10707 destroy: function() {
10708 if(!this.element.data('draggable')) return;
10710 .removeData("draggable")
10711 .unbind(".draggable")
10712 .removeClass("ui-draggable"
10713 + " ui-draggable-dragging"
10714 + " ui-draggable-disabled");
10715 this._mouseDestroy();
10720 _mouseCapture: function(event) {
10722 var o = this.options;
10724 // among others, prevent a drag on a resizable-handle
10725 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
10728 //Quit if we're not on a valid handle
10729 this.handle = this._getHandle(event);
10733 if ( o.iframeFix ) {
10734 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
10735 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
10737 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
10738 position: "absolute", opacity: "0.001", zIndex: 1000
10740 .css($(this).offset())
10749 _mouseStart: function(event) {
10751 var o = this.options;
10753 //Create and append the visible helper
10754 this.helper = this._createHelper(event);
10756 //Cache the helper size
10757 this._cacheHelperProportions();
10759 //If ddmanager is used for droppables, set the global draggable
10761 $.ui.ddmanager.current = this;
10764 * - Position generation -
10765 * This block generates everything position related - it's the core of draggables.
10768 //Cache the margins of the original element
10769 this._cacheMargins();
10771 //Store the helper's css position
10772 this.cssPosition = this.helper.css("position");
10773 this.scrollParent = this.helper.scrollParent();
10775 //The element's absolute position on the page minus margins
10776 this.offset = this.positionAbs = this.element.offset();
10778 top: this.offset.top - this.margins.top,
10779 left: this.offset.left - this.margins.left
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
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
10791 //Generate the original position
10792 this.originalPosition = this.position = this._generatePosition(event);
10793 this.originalPageX = event.pageX;
10794 this.originalPageY = event.pageY;
10796 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
10797 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
10799 //Set a containment if given in the options
10801 this._setContainment();
10803 //Trigger event + callbacks
10804 if(this._trigger("start", event) === false) {
10809 //Recache the helper size
10810 this._cacheHelperProportions();
10812 //Prepare the droppable offsets
10813 if ($.ui.ddmanager && !o.dropBehaviour)
10814 $.ui.ddmanager.prepareOffsets(this, event);
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
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);
10825 _mouseDrag: function(event, noPropagation) {
10827 //Compute the helpers position
10828 this.position = this._generatePosition(event);
10829 this.positionAbs = this._convertPositionTo("absolute");
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) {
10838 this.position = ui.position;
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);
10848 _mouseStop: function(event) {
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);
10855 //if a drop comes from outside (a sortable)
10857 dropped = this.dropped;
10858 this.dropped = false;
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")
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))) {
10867 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
10868 if(self._trigger("stop", event) !== false) {
10873 if(this._trigger("stop", event) !== false) {
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
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);
10891 return $.ui.mouse.prototype._mouseUp.call(this, event);
10894 cancel: function() {
10896 if(this.helper.is(".ui-draggable-dragging")) {
10906 _getHandle: function(event) {
10908 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
10909 $(this.options.handle, this.element)
10913 if(this == event.target) handle = true;
10920 _createHelper: function(event) {
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);
10925 if(!helper.parents('body').length)
10926 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
10928 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
10929 helper.css("position", "absolute");
10935 _adjustOffsetFromHelper: function(obj) {
10936 if (typeof obj == 'string') {
10937 obj = obj.split(' ');
10939 if ($.isArray(obj)) {
10940 obj = {left: +obj[0], top: +obj[1] || 0};
10942 if ('left' in obj) {
10943 this.offset.click.left = obj.left + this.margins.left;
10945 if ('right' in obj) {
10946 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
10948 if ('top' in obj) {
10949 this.offset.click.top = obj.top + this.margins.top;
10951 if ('bottom' in obj) {
10952 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
10956 _getParentOffset: function() {
10958 //Get the offsetParent and cache its position
10959 this.offsetParent = this.helper.offsetParent();
10960 var po = this.offsetParent.offset();
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();
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 };
10976 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
10977 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
10982 _getRelativeOffset: function() {
10984 if(this.cssPosition == "relative") {
10985 var p = this.element.position();
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()
10991 return { top: 0, left: 0 };
10996 _cacheMargins: function() {
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)
11005 _cacheHelperProportions: function() {
11006 this.helperProportions = {
11007 width: this.helper.outerWidth(),
11008 height: this.helper.outerHeight()
11012 _setContainment: function() {
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
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');
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
11035 this.relative_container = c;
11037 } else if(o.containment.constructor == Array) {
11038 this.containment = o.containment;
11043 _convertPositionTo: function(d, pos) {
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);
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)
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)
11066 _generatePosition: function(event) {
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;
11073 * - Position constraining -
11074 * Constrain the position to a mix of grid, containment.
11077 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
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 ];
11088 containment = this.containment;
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;
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;
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;
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() ) ))
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() ))
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;
11135 // From now on bulk stuff - mainly helpers
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);
11146 _uiHash: function(event) {
11148 helper: this.helper,
11149 position: this.position,
11150 originalPosition: this.originalPosition,
11151 offset: this.positionAbs
11157 $.extend($.ui.draggable, {
11161 $.ui.plugin.add("draggable", "connectToSortable", {
11162 start: function(event, ui) {
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
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);
11180 stop: function(event, ui) {
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 });
11186 $.each(inst.sortables, function() {
11187 if(this.instance.isOver) {
11189 this.instance.isOver = 0;
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)
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;
11197 //Trigger the stop of the sortable
11198 this.instance._mouseStop(event);
11200 this.instance.options.helper = this.instance.options._helper;
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' });
11207 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
11208 this.instance._trigger("deactivate", event, uiSortable);
11214 drag: function(event, ui) {
11216 var inst = $(this).data("draggable"), self = this;
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;
11224 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
11227 $.each(inst.sortables, function(i) {
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;
11234 if(this.instance._intersectsWith(this.instance.containerCache)) {
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) {
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]; };
11247 event.target = this.instance.currentItem[0];
11248 this.instance._mouseCapture(event, true);
11249 this.instance._mouseStart(event, true, true);
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;
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;
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);
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) {
11274 this.instance.isOver = 0;
11275 this.instance.cancelHelperRemoval = true;
11277 //Prevent reverting on this forced stop
11278 this.instance.options.revert = false;
11280 // The out event needs to be triggered independently
11281 this.instance._trigger('out', event, this.instance._uiHash(this.instance));
11283 this.instance._mouseStop(event, true);
11284 this.instance.options.helper = this.instance.options._helper;
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();
11290 inst._trigger("fromSortable", event);
11291 inst.dropped = false; //draggable revert needs that
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);
11307 stop: function(event, ui) {
11308 var o = $(this).data('draggable').options;
11309 if (o._cursor) $('body').css("cursor", o._cursor);
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);
11319 stop: function(event, ui) {
11320 var o = $(this).data('draggable').options;
11321 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
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();
11330 drag: function(event, ui) {
11332 var i = $(this).data("draggable"), o = i.options, scrolled = false;
11334 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
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;
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;
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);
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);
11368 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
11369 $.ui.ddmanager.prepareOffsets(i, event);
11374 $.ui.plugin.add("draggable", "snap", {
11375 start: function(event, ui) {
11377 var i = $(this).data("draggable"), o = i.options;
11378 i.snapElements = [];
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({
11384 width: $t.outerWidth(), height: $t.outerHeight(),
11385 top: $o.top, left: $o.left
11390 drag: function(event, ui) {
11392 var inst = $(this).data("draggable"), o = inst.options;
11393 var d = o.snapTolerance;
11395 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
11396 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
11398 for (var i = inst.snapElements.length - 1; i >= 0; i--){
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;
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;
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;
11421 var first = (ts || bs || ls || rs);
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;
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);
11443 $.ui.plugin.add("draggable", "stack", {
11444 start: function(event, ui) {
11446 var o = $(this).data("draggable").options;
11448 var group = $.makeArray($(o.stack)).sort(function(a,b) {
11449 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
11451 if (!group.length) { return; }
11453 var min = parseInt(group[0].style.zIndex) || 0;
11454 $(group).each(function(i) {
11455 this.style.zIndex = min + i;
11458 this[0].style.zIndex = min + group.length;
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);
11469 stop: function(event, ui) {
11470 var o = $(this).data("draggable").options;
11471 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
11477 * jQuery UI Droppable 1.8.16
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
11483 * http://docs.jquery.com/UI/Droppables
11486 * jquery.ui.core.js
11487 * jquery.ui.widget.js
11488 * jquery.ui.mouse.js
11489 * jquery.ui.draggable.js
11491 (function( $, undefined ) {
11493 $.widget("ui.droppable", {
11494 widgetEventPrefix: "drop",
11497 activeClass: false,
11502 tolerance: 'intersect'
11504 _create: function() {
11506 var o = this.options, accept = o.accept;
11507 this.isover = 0; this.isout = 1;
11509 this.accept = $.isFunction(accept) ? accept : function(d) {
11510 return d.is(accept);
11513 //Store the droppable's proportions
11514 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
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);
11520 (o.addClasses && this.element.addClass("ui-droppable"));
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 )
11531 .removeClass("ui-droppable ui-droppable-disabled")
11532 .removeData("droppable")
11533 .unbind(".droppable");
11538 _setOption: function(key, value) {
11540 if(key == 'accept') {
11541 this.accept = $.isFunction(value) ? value : function(d) {
11542 return d.is(value);
11545 $.Widget.prototype._setOption.apply(this, arguments);
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)));
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)));
11560 _over: function(event) {
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
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));
11572 _out: function(event) {
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
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));
11584 _drop: function(event,custom) {
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
11589 var childrenIntersection = false;
11590 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
11591 var inst = $.data(this, 'droppable');
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; }
11600 if(childrenIntersection) return false;
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;
11615 draggable: (c.currentItem || c.element),
11617 position: c.position,
11618 offset: c.positionAbs
11624 $.extend($.ui.droppable, {
11628 $.ui.intersect = function(draggable, droppable, toleranceMode) {
11630 if (!droppable.offset) return false;
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;
11637 switch (toleranceMode) {
11639 return (l <= x1 && x2 <= r
11640 && t <= y1 && y2 <= b);
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
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);
11656 (y1 >= t && y1 <= b) || // Top edge touching
11657 (y2 >= t && y2 <= b) || // Bottom edge touching
11658 (y1 < t && y2 > b) // Surrounded vertically
11660 (x1 >= l && x1 <= r) || // Left edge touching
11661 (x2 >= l && x2 <= r) || // Right edge touching
11662 (x1 < l && x2 > r) // Surrounded horizontally
11673 This manager tracks offsets of draggables and droppables
11677 droppables: { 'default': [] },
11678 prepareOffsets: function(t, event) {
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();
11684 droppablesLoop: for (var i = 0; i < m.length; i++) {
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
11690 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
11692 m[i].offset = m[i].element.offset();
11693 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
11698 drop: function(draggable, event) {
11700 var dropped = false;
11701 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
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);
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);
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 );
11722 drag: function(draggable, event) {
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);
11727 //Run through all droppables and check their positions based on specific tolerance options
11728 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
11730 if(this.options.disabled || this.greedyChild || !this.visible) return;
11731 var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
11733 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
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);
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);
11752 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
11753 this[c == "isover" ? "_over" : "_out"].call(this, event);
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);
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 );
11773 * jQuery UI Resizable 1.8.16
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
11779 * http://docs.jquery.com/UI/Resizables
11782 * jquery.ui.core.js
11783 * jquery.ui.mouse.js
11784 * jquery.ui.widget.js
11786 (function( $, undefined ) {
11788 $.widget("ui.resizable", $.ui.mouse, {
11789 widgetEventPrefix: "resize",
11793 animateDuration: "slow",
11794 animateEasing: "swing",
11795 aspectRatio: false,
11797 containment: false,
11808 _create: function() {
11810 var self = this, o = this.options;
11811 this.element.addClass("ui-resizable");
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
11821 //Wrap the element if it cannot hold child nodes
11822 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
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' });
11828 //Create a wrapper element and set the wrapper to the new current internal element
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')
11839 //Overwrite the original this.element
11840 this.element = this.element.parent().data(
11841 "resizable", this.element.data('resizable')
11844 this.elementIsWrapper = true;
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});
11850 //Prevent Safari textarea resize
11851 this.originalResizeStyle = this.originalElement.css('resize');
11852 this.originalElement.css('resize', 'none');
11854 //Push the actual element to our proportionallyResize internal array
11855 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
11857 // avoid IE jump (hard set the margin)
11858 this.originalElement.css({ margin: this.originalElement.css('margin') });
11860 // fix handlers offset
11861 this._proportionallyResize();
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) {
11868 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
11869 var n = this.handles.split(","); this.handles = {};
11871 for(var i = 0; i < n.length; i++) {
11873 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
11874 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
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 });
11880 //TODO : What's going on here?
11881 if ('se' == handle) {
11882 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
11885 //Insert into internal handles object and append to element
11886 this.handles[handle] = '.ui-resizable-'+handle;
11887 this.element.append(axis);
11892 this._renderAxis = function(target) {
11894 target = target || this.element;
11896 for(var i in this.handles) {
11898 if(this.handles[i].constructor == String)
11899 this.handles[i] = $(this.handles[i], this.element).show();
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)) {
11904 var axis = $(this.handles[i], this.element), padWrapper = 0;
11906 //Checking the correct pad and border
11907 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
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("");
11915 target.css(padPos, padWrapper);
11917 this._proportionallyResize();
11921 //TODO: What's that good for? There's not anything to be executed left
11922 if(!$(this.handles[i]).length)
11928 //TODO: make renderAxis a prototype function
11929 this._renderAxis(this.element);
11931 this._handles = $('.ui-resizable-handle', this.element)
11932 .disableSelection();
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';
11944 //If we want to auto hide the elements
11946 this._handles.hide();
11948 .addClass("ui-resizable-autohide")
11949 .hover(function() {
11950 if (o.disabled) return;
11951 $(this).removeClass("ui-resizable-autohide");
11952 self._handles.show();
11955 if (o.disabled) return;
11956 if (!self.resizing) {
11957 $(this).addClass("ui-resizable-autohide");
11958 self._handles.hide();
11963 //Initialize the mouse interaction
11968 destroy: function() {
11970 this._mouseDestroy();
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();
11977 //TODO: Unwrap at same DOM position
11978 if (this.elementIsWrapper) {
11979 _destroy(this.element);
11980 var wrapper = this.element;
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')
11992 this.originalElement.css('resize', this.originalResizeStyle);
11993 _destroy(this.originalElement);
11998 _mouseCapture: function(event) {
11999 var handle = false;
12000 for (var i in this.handles) {
12001 if ($(this.handles[i])[0] == event.target) {
12006 return !this.options.disabled && handle;
12009 _mouseStart: function(event) {
12011 var o = this.options, iniPos = this.element.position(), el = this.element;
12013 this.resizing = true;
12014 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
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 });
12021 //Opera fixing relative position
12022 if ($.browser.opera && (/relative/).test(el.css('position')))
12023 el.css({ position: 'relative', top: 'auto', left: 'auto' });
12025 this._renderProxy();
12027 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
12029 if (o.containment) {
12030 curleft += $(o.containment).scrollLeft() || 0;
12031 curtop += $(o.containment).scrollTop() || 0;
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 };
12044 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
12046 var cursor = $('.ui-resizable-' + this.axis).css('cursor');
12047 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
12049 el.addClass("ui-resizable-resizing");
12050 this._propagate("start", event);
12054 _mouseDrag: function(event) {
12056 //Increase performance, avoid regex
12057 var el = this.helper, o = this.options, props = {},
12058 self = this, smp = this.originalMousePosition, a = this.axis;
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;
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;
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);
12072 data = this._respectSize(data, event);
12074 // plugins callbacks need to be called first
12075 this._propagate("resize", event);
12078 top: this.position.top + "px", left: this.position.left + "px",
12079 width: this.size.width + "px", height: this.size.height + "px"
12082 if (!this._helper && this._proportionallyResizeElements.length)
12083 this._proportionallyResize();
12085 this._updateCache(data);
12087 // calling the user callback at the end
12088 this._trigger('resize', event, this.ui());
12093 _mouseStop: function(event) {
12095 this.resizing = false;
12096 var o = this.options, self = this;
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;
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;
12108 this.element.css($.extend(s, { top: top, left: left }));
12110 self.helper.height(self.size.height);
12111 self.helper.width(self.size.width);
12113 if (this._helper && !o.animate) this._proportionallyResize();
12116 $('body').css('cursor', 'auto');
12118 this.element.removeClass("ui-resizable-resizing");
12120 this._propagate("stop", event);
12122 if (this._helper) this.helper.remove();
12127 _updateVirtualBoundaries: function(forceAspectRatio) {
12128 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, 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
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;
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;
12150 this._vBoundaries = b;
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;
12162 _updateRatio: function(data, event) {
12164 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
12166 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
12167 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
12170 data.left = cpos.left + (csize.width - data.width);
12174 data.top = cpos.top + (csize.height - data.height);
12175 data.left = cpos.left + (csize.width - data.width);
12181 _respectSize: function(data, event) {
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);
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;
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);
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;
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;
12208 _proportionallyResize: function() {
12210 var o = this.options;
12211 if (!this._proportionallyResizeElements.length) return;
12212 var element = this.helper || this.element;
12214 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
12216 var prel = this._proportionallyResizeElements[i];
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')];
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;
12228 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
12232 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
12233 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
12240 _renderProxy: function() {
12242 var el = this.element, o = this.options;
12243 this.elementOffset = el.offset();
12247 this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
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 );
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
12264 .disableSelection();
12267 this.helper = this.element;
12273 e: function(event, dx, dy) {
12274 return { width: this.originalSize.width + dx };
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 };
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 };
12284 s: function(event, dx, dy) {
12285 return { height: this.originalSize.height + dy };
12287 se: function(event, dx, dy) {
12288 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
12290 sw: function(event, dx, dy) {
12291 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
12293 ne: function(event, dx, dy) {
12294 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
12296 nw: function(event, dx, dy) {
12297 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
12301 _propagate: function(n, event) {
12302 $.ui.plugin.call(this, n, [event, this.ui()]);
12303 (n != "resize" && this._trigger(n, event, this.ui()));
12310 originalElement: this.originalElement,
12311 element: this.element,
12312 helper: this.helper,
12313 position: this.position,
12315 originalSize: this.originalSize,
12316 originalPosition: this.originalPosition
12322 $.extend($.ui.resizable, {
12327 * Resizable Extensions
12330 $.ui.plugin.add("resizable", "alsoResize", {
12332 start: function (event, ui) {
12333 var self = $(this).data("resizable"), o = self.options;
12335 var _store = function (exp) {
12336 $(exp).each(function() {
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()
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); }); }
12350 _store(o.alsoResize);
12354 resize: function (event, ui) {
12355 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
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
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'];
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;
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' });
12383 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
12384 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
12386 _alsoResize(o.alsoResize);
12390 stop: function (event, ui) {
12391 var self = $(this).data("resizable"), o = self.options;
12393 var _reset = function (exp) {
12394 $(exp).each(function() {
12396 // reset position for Opera - no need to verify it was changed
12397 el.css({ position: el.data("resizable-alsoresize").position });
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); });
12406 _reset(o.alsoResize);
12410 $(this).removeData("resizable-alsoresize");
12414 $.ui.plugin.add("resizable", "animate", {
12416 stop: function(event, ui) {
12417 var self = $(this).data("resizable"), o = self.options;
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;
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;
12427 self.element.animate(
12428 $.extend(style, top && left ? { top: top, left: left } : {}), {
12429 duration: o.animateDuration,
12430 easing: o.animateEasing,
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)
12440 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
12442 // propagating resize, and updating values for each animation step
12443 self._updateCache(data);
12444 self._propagate("resize", event);
12453 $.ui.plugin.add("resizable", "containment", {
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;
12460 self.containerElement = $(ce);
12462 if (/document/.test(oc) || oc == document) {
12463 self.containerOffset = { left: 0, top: 0 };
12464 self.containerPosition = { left: 0, top: 0 };
12466 self.parentData = {
12467 element: $(document), left: 0, top: 0,
12468 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
12472 // i'm a node, so compute top, left, right, bottom
12474 var element = $(ce), p = [];
12475 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
12477 self.containerOffset = element.offset();
12478 self.containerPosition = element.position();
12479 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
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);
12484 self.parentData = {
12485 element: ce, left: co.left, top: co.top, width: width, height: height
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;
12495 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
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;
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;
12509 self.offset.left = self.parentData.left+self.position.left;
12510 self.offset.top = self.parentData.top+self.position.top;
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 );
12515 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
12516 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
12518 if(isParent && isOffsetRelative) woset -= self.parentData.left;
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;
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;
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;
12535 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
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 });
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 });
12546 $.ui.plugin.add("resizable", "ghost", {
12548 start: function(event, ui) {
12550 var self = $(this).data("resizable"), o = self.options, cs = self.size;
12552 self.ghost = self.originalElement.clone();
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 : '');
12558 self.ghost.appendTo(self.helper);
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 });
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));
12574 $.ui.plugin.add("resizable", "grid", {
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);
12581 if (/^(se|s|e)$/.test(a)) {
12582 self.size.width = os.width + ox;
12583 self.size.height = os.height + oy;
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;
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;
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;
12605 var num = function(v) {
12606 return parseInt(v, 10) || 0;
12609 var isNumber = function(value) {
12610 return !isNaN(parseInt(value, 10));
12615 * jQuery UI Selectable 1.8.16
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
12621 * http://docs.jquery.com/UI/Selectables
12624 * jquery.ui.core.js
12625 * jquery.ui.mouse.js
12626 * jquery.ui.widget.js
12628 (function( $, undefined ) {
12630 $.widget("ui.selectable", $.ui.mouse, {
12638 _create: function() {
12641 this.element.addClass("ui-selectable");
12643 this.dragged = false;
12645 // cache selectee children based on filter
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", {
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')
12668 this.selectees = selectees.addClass("ui-selectee");
12672 this.helper = $("<div class='ui-selectable-helper'></div>");
12675 destroy: function() {
12677 .removeClass("ui-selectee")
12678 .removeData("selectable-item");
12680 .removeClass("ui-selectable ui-selectable-disabled")
12681 .removeData("selectable")
12682 .unbind(".selectable");
12683 this._mouseDestroy();
12688 _mouseStart: function(event) {
12691 this.opos = [event.pageX, event.pageY];
12693 if (this.options.disabled)
12696 var options = this.options;
12698 this.selectees = $(options.filter, this.element[0]);
12700 this._trigger("start", event);
12702 $(options.appendTo).append(this.helper);
12703 // position helper (lasso)
12705 "left": event.clientX,
12706 "top": event.clientY,
12711 if (options.autoRefresh) {
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
12730 $(event.target).parents().andSelf().each(function() {
12731 var selectee = $.data(this, "selectable-item");
12733 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
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
12742 self._trigger("selecting", event, {
12743 selecting: selectee.element
12746 self._trigger("unselecting", event, {
12747 unselecting: selectee.element
12756 _mouseDrag: function(event) {
12758 this.dragged = true;
12760 if (this.options.disabled)
12763 var options = this.options;
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});
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])
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);
12784 if (selectee.selected) {
12785 selectee.$element.removeClass('ui-selected');
12786 selectee.selected = false;
12788 if (selectee.unselecting) {
12789 selectee.$element.removeClass('ui-unselecting');
12790 selectee.unselecting = false;
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
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;
12809 selectee.$element.removeClass('ui-selecting');
12810 selectee.selecting = false;
12811 if (selectee.startselected) {
12812 selectee.$element.addClass('ui-unselecting');
12813 selectee.unselecting = true;
12815 // selectable UNSELECTING callback
12816 self._trigger("unselecting", event, {
12817 unselecting: selectee.element
12821 if (selectee.selected) {
12822 if (!event.metaKey && !selectee.startselected) {
12823 selectee.$element.removeClass('ui-selected');
12824 selectee.selected = false;
12826 selectee.$element.addClass('ui-unselecting');
12827 selectee.unselecting = true;
12828 // selectable UNSELECTING callback
12829 self._trigger("unselecting", event, {
12830 unselecting: selectee.element
12840 _mouseStop: function(event) {
12843 this.dragged = false;
12845 var options = this.options;
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
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
12866 this._trigger("stop", event);
12868 this.helper.remove();
12875 $.extend($.ui.selectable, {
12881 * jQuery UI Sortable 1.8.16
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
12887 * http://docs.jquery.com/UI/Sortables
12890 * jquery.ui.core.js
12891 * jquery.ui.mouse.js
12892 * jquery.ui.widget.js
12894 (function( $, undefined ) {
12896 $.widget("ui.sortable", $.ui.mouse, {
12897 widgetEventPrefix: "sort",
12899 appendTo: "parent",
12901 connectWith: false,
12902 containment: false,
12906 forcePlaceholderSize: false,
12907 forceHelperSize: false,
12910 helper: "original",
12913 placeholder: false,
12916 scrollSensitivity: 20,
12919 tolerance: "intersect",
12922 _create: function() {
12924 var o = this.options;
12925 this.containerCache = {};
12926 this.element.addClass("ui-sortable");
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;
12934 //Let's determine the parent's offset
12935 this.offset = this.element.offset();
12937 //Initialize mouse events for interaction
12942 destroy: function() {
12944 .removeClass("ui-sortable ui-sortable-disabled")
12945 .removeData("sortable")
12946 .unbind(".sortable");
12947 this._mouseDestroy();
12949 for ( var i = this.items.length - 1; i >= 0; i-- )
12950 this.items[i].item.removeData("sortable-item");
12955 _setOption: function(key, value){
12956 if ( key === "disabled" ) {
12957 this.options[ key ] = value;
12960 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
12962 // Don't call widget base _setOption for disable as it adds ui-state-disabled class
12963 $.Widget.prototype._setOption.apply(this, arguments);
12967 _mouseCapture: function(event, overrideHandle) {
12969 if (this.reverting) {
12973 if(this.options.disabled || this.options.type == 'static') return false;
12975 //We have to refresh the items data once first
12976 this._refreshItems(event);
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);
12985 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
12987 if(!currentItem) return false;
12988 if(this.options.handle && !overrideHandle) {
12989 var validHandle = false;
12991 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
12992 if(!validHandle) return false;
12995 this.currentItem = currentItem;
12996 this._removeCurrentsFromItems();
13001 _mouseStart: function(event, overrideHandle, noActivation) {
13003 var o = this.options, self = this;
13004 this.currentContainer = this;
13006 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
13007 this.refreshPositions();
13009 //Create and append the visible helper
13010 this.helper = this._createHelper(event);
13012 //Cache the helper size
13013 this._cacheHelperProportions();
13016 * - Position generation -
13017 * This block generates everything position related - it's the core of draggables.
13020 //Cache the margins of the original element
13021 this._cacheMargins();
13023 //Get the next scrolling parent
13024 this.scrollParent = this.helper.scrollParent();
13026 //The element's absolute position on the page minus margins
13027 this.offset = this.currentItem.offset();
13029 top: this.offset.top - this.margins.top,
13030 left: this.offset.left - this.margins.left
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");
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
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
13047 //Generate the original position
13048 this.originalPosition = this._generatePosition(event);
13049 this.originalPageX = event.pageX;
13050 this.originalPageY = event.pageY;
13052 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
13053 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
13055 //Cache the former DOM position
13056 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
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();
13063 //Create the placeholder
13064 this._createPlaceholder();
13066 //Set a containment if given in the options
13068 this._setContainment();
13070 if(o.cursor) { // cursor option
13071 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
13072 $('body').css("cursor", o.cursor);
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);
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);
13085 //Prepare scrolling
13086 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
13087 this.overflowOffset = this.scrollParent.offset();
13090 this._trigger("start", event, this._uiHash());
13092 //Recache the helper size
13093 if(!this._preserveHelperProportions)
13094 this._cacheHelperProportions();
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)); }
13102 //Prepare possible droppables
13104 $.ui.ddmanager.current = this;
13106 if ($.ui.ddmanager && !o.dropBehaviour)
13107 $.ui.ddmanager.prepareOffsets(this, event);
13109 this.dragging = true;
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
13117 _mouseDrag: function(event) {
13119 //Compute the helpers position
13120 this.position = this._generatePosition(event);
13121 this.positionAbs = this._convertPositionTo("absolute");
13123 if (!this.lastPositionAbs) {
13124 this.lastPositionAbs = this.positionAbs;
13128 if(this.options.scroll) {
13129 var o = this.options, scrolled = false;
13130 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
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;
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;
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);
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);
13156 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
13157 $.ui.ddmanager.prepareOffsets(this, event);
13160 //Regenerate the absolute position used for position checks
13161 this.positionAbs = this._convertPositionTo("absolute");
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';
13168 for (var i = this.items.length - 1; i >= 0; i--) {
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;
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
13181 this.direction = intersection == 1 ? "down" : "up";
13183 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
13184 this._rearrange(event, item);
13189 this._trigger("change", event, this._uiHash());
13194 //Post events to containers
13195 this._contactContainers(event);
13197 //Interconnect with droppables
13198 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
13201 this._trigger('sort', event, this._uiHash());
13203 this.lastPositionAbs = this.positionAbs;
13208 _mouseStop: function(event, noPropagation) {
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);
13216 if(this.options.revert) {
13218 var cur = self.placeholder.offset();
13220 self.reverting = true;
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);
13229 this._clear(event, noPropagation);
13236 cancel: function() {
13240 if(this.dragging) {
13242 this._mouseUp({ target: null });
13244 if(this.options.helper == "original")
13245 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13247 this.currentItem.show();
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;
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();
13272 if(this.domPosition.prev) {
13273 $(this.domPosition.prev).after(this.currentItem);
13275 $(this.domPosition.parent).prepend(this.currentItem);
13283 serialize: function(o) {
13285 var items = this._getItemsAsjQuery(o && o.connected);
13286 var str = []; o = o || {};
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]));
13293 if(!str.length && o.key) {
13294 str.push(o.key + '=');
13297 return str.join('&');
13301 toArray: function(o) {
13303 var items = this._getItemsAsjQuery(o && o.connected);
13304 var ret = []; o = o || {};
13306 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
13311 /* Be careful with the following core functions */
13312 _intersectsWith: function(item) {
13314 var x1 = this.positionAbs.left,
13315 x2 = x1 + this.helperProportions.width,
13316 y1 = this.positionAbs.top,
13317 y2 = y1 + this.helperProportions.height;
13320 r = l + item.width,
13322 b = t + item.height;
13324 var dyClick = this.offset.click.top,
13325 dxClick = this.offset.click.left;
13327 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
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'])
13333 return isOverElement;
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
13344 _intersectsWithPointer: function(item) {
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();
13352 if (!isOverElement)
13355 return this.floating ?
13356 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
13357 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
13361 _intersectsWithSides: function(item) {
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();
13368 if (this.floating && horizontalDirection) {
13369 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
13371 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
13376 _getDragVerticalDirection: function() {
13377 var delta = this.positionAbs.top - this.lastPositionAbs.top;
13378 return delta != 0 && (delta > 0 ? "down" : "up");
13381 _getDragHorizontalDirection: function() {
13382 var delta = this.positionAbs.left - this.lastPositionAbs.left;
13383 return delta != 0 && (delta > 0 ? "right" : "left");
13386 refresh: function(event) {
13387 this._refreshItems(event);
13388 this.refreshPositions();
13392 _connectWith: function() {
13393 var options = this.options;
13394 return options.connectWith.constructor == String
13395 ? [options.connectWith]
13396 : options.connectWith;
13399 _getItemsAsjQuery: function(connected) {
13404 var connectWith = this._connectWith();
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]);
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]);
13420 for (var i = queries.length - 1; i >= 0; i--){
13421 queries[i][0].each(function() {
13430 _removeCurrentsFromItems: function() {
13432 var list = this.currentItem.find(":data(sortable-item)");
13434 for (var i=0; i < this.items.length; i++) {
13436 for (var j=0; j < list.length; j++) {
13437 if(list[j] == this.items[i].item[0])
13438 this.items.splice(i,1);
13445 _refreshItems: function(event) {
13448 this.containers = [this];
13449 var items = this.items;
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();
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);
13467 for (var i = queries.length - 1; i >= 0; i--) {
13468 var targetData = queries[i][1];
13469 var _queries = queries[i][0];
13471 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
13472 var item = $(_queries[j]);
13474 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
13478 instance: targetData,
13479 width: 0, height: 0,
13487 refreshPositions: function(fast) {
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();
13494 for (var i = this.items.length - 1; i >= 0; i--){
13495 var item = this.items[i];
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])
13501 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
13504 item.width = t.outerWidth();
13505 item.height = t.outerHeight();
13508 var p = t.offset();
13509 item.left = p.left;
13513 if(this.options.custom && this.options.custom.refreshContainers) {
13514 this.options.custom.refreshContainers.call(this);
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();
13528 _createPlaceholder: function(that) {
13530 var self = that || this, o = self.options;
13532 if(!o.placeholder || o.placeholder.constructor == String) {
13533 var className = o.placeholder;
13535 element: function() {
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];
13542 el.style.visibility = "hidden";
13546 update: function(container, p) {
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;
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)); };
13559 //Create the placeholder
13560 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
13562 //Append it after the actual current item
13563 self.currentItem.after(self.placeholder);
13565 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
13566 o.placeholder.update(self, self.placeholder);
13570 _contactContainers: function(event) {
13572 // get innermost container that intersects with item
13573 var innermostContainer = null, innermostIndex = null;
13576 for (var i = this.containers.length - 1; i >= 0; i--){
13578 // never consider a container that's located within the item itself
13579 if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
13582 if(this._intersectsWith(this.containers[i].containerCache)) {
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]))
13588 innermostContainer = this.containers[i];
13589 innermostIndex = i;
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;
13601 // if no intersecting containers found, return
13602 if(!innermostContainer) return;
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]) {
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];
13620 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
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));
13628 //Update the placeholder
13629 this.options.placeholder.update(this.currentContainer, this.placeholder);
13631 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
13632 this.containers[innermostIndex].containerCache.over = 1;
13638 _createHelper: function(event) {
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);
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]);
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") };
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());
13656 _adjustOffsetFromHelper: function(obj) {
13657 if (typeof obj == 'string') {
13658 obj = obj.split(' ');
13660 if ($.isArray(obj)) {
13661 obj = {left: +obj[0], top: +obj[1] || 0};
13663 if ('left' in obj) {
13664 this.offset.click.left = obj.left + this.margins.left;
13666 if ('right' in obj) {
13667 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
13669 if ('top' in obj) {
13670 this.offset.click.top = obj.top + this.margins.top;
13672 if ('bottom' in obj) {
13673 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
13677 _getParentOffset: function() {
13680 //Get the offsetParent and cache its position
13681 this.offsetParent = this.helper.offsetParent();
13682 var po = this.offsetParent.offset();
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();
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 };
13698 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
13699 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
13704 _getRelativeOffset: function() {
13706 if(this.cssPosition == "relative") {
13707 var p = this.currentItem.position();
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()
13713 return { top: 0, left: 0 };
13718 _cacheMargins: function() {
13720 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
13721 top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
13725 _cacheHelperProportions: function() {
13726 this.helperProportions = {
13727 width: this.helper.outerWidth(),
13728 height: this.helper.outerHeight()
13732 _setContainment: function() {
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
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');
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
13758 _convertPositionTo: function(d, pos) {
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);
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)
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)
13781 _generatePosition: function(event) {
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);
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();
13793 var pageX = event.pageX;
13794 var pageY = event.pageY;
13797 * - Position constraining -
13798 * Constrain the position to a mix of grid, containment.
13801 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
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;
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;
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;
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() ) ))
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() ))
13839 _rearrange: function(event, i, a, hardRefresh) {
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));
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;
13851 window.setTimeout(function() {
13852 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
13857 _clear: function(event, noPropagation) {
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;
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;
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] = '';
13873 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13875 this.currentItem.show();
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]));
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;
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
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());
13914 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
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]);
13919 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
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());
13926 this.fromOutside = false;
13931 _trigger: function() {
13932 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
13937 _uiHash: function(inst) {
13938 var self = inst || this;
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
13952 $.extend($.ui.sortable, {
13958 * jQuery UI Effects 1.8.16
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
13964 * http://docs.jquery.com/UI/Effects/
13966 ;jQuery.effects || (function($, undefined) {
13972 /******************************************************************************/
13973 /****************************** COLOR ANIMATIONS ******************************/
13974 /******************************************************************************/
13976 // override the animation for color styles
13977 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
13978 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
13979 function(i, attr) {
13980 $.fx.step[attr] = function(fx) {
13981 if (!fx.colorInit) {
13982 fx.start = getColor(fx.elem, attr);
13983 fx.end = getRGB(fx.end);
13984 fx.colorInit = true;
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) + ')';
13994 // Color Conversion functions from highlightFade
13995 // By Blair Mitchelmore
13996 // http://jquery.offput.ca/highlightFade/
13998 // Parse strings looking for color tuples [255,255,255]
13999 function getRGB(color) {
14002 // Check if we're already dealing with an array of colors
14003 if ( color && color.constructor == Array && color.length == 3 )
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)];
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];
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)];
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)];
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'];
14026 // Otherwise, we're most likely dealing with a named color
14027 return colors[$.trim(color).toLowerCase()];
14030 function getColor(elem, attr) {
14034 color = $.curCSS(elem, attr);
14036 // Keep going until we find an element that has color, or we hit the body
14037 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
14040 attr = "backgroundColor";
14041 } while ( elem = elem.parentNode );
14043 return getRGB(color);
14046 // Some named colors to work with
14047 // From Interface by Stefan Petre
14048 // http://interface.eyecon.ro/
14052 azure:[240,255,255],
14053 beige:[245,245,220],
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],
14068 darksalmon:[233,150,122],
14069 darkviolet:[148,0,211],
14070 fuchsia:[255,0,255],
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],
14082 magenta:[255,0,255],
14086 orange:[255,165,0],
14087 pink:[255,192,203],
14088 purple:[128,0,128],
14089 violet:[128,0,128],
14091 silver:[192,192,192],
14092 white:[255,255,255],
14093 yellow:[255,255,0],
14094 transparent: [255,255,255]
14099 /******************************************************************************/
14100 /****************************** CLASS ANIMATIONS ******************************/
14101 /******************************************************************************/
14103 var classAnimationActions = ['add', 'remove', 'toggle'],
14104 shorthandStyles = {
14116 function getElementStyles() {
14117 var style = document.defaultView
14118 ? document.defaultView.getComputedStyle(this, null)
14119 : this.currentStyle,
14124 // webkit enumerates style porperties
14125 if (style && style.length && style[0] && style[style[0]]) {
14126 var len = style.length;
14129 if (typeof style[key] == 'string') {
14130 camelCase = key.replace(/\-(\w)/g, function(all, letter){
14131 return letter.toUpperCase();
14133 newStyle[camelCase] = style[key];
14137 for (key in style) {
14138 if (typeof style[key] === 'string') {
14139 newStyle[key] = style[key];
14147 function filterStyles(styles) {
14149 for (name in styles) {
14150 value = styles[name];
14152 // ignore null and undefined values
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) ||
14161 // only colors or values that can be converted to numbers
14162 (!(/color/i).test(name) && isNaN(parseFloat(value)))
14164 delete styles[name];
14171 function styleDifference(oldStyle, newStyle) {
14172 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
14175 for (name in newStyle) {
14176 if (oldStyle[name] != newStyle[name]) {
14177 diff[name] = newStyle[name];
14184 $.effects.animateClass = function(value, duration, easing, callback) {
14185 if ($.isFunction(easing)) {
14190 return this.queue(function() {
14191 var that = $(this),
14192 originalStyleAttr = that.attr('style') || ' ',
14193 originalStyle = filterStyles(getElementStyles.call(this)),
14195 className = that.attr('class');
14197 $.each(classAnimationActions, function(i, action) {
14198 if (value[action]) {
14199 that[action + 'Class'](value[action]);
14202 newStyle = filterStyles(getElementStyles.call(this));
14203 that.attr('class', className);
14205 that.animate(styleDifference(originalStyle, newStyle), {
14207 duration: duration,
14209 complete: function() {
14210 $.each(classAnimationActions, function(i, action) {
14211 if (value[action]) { that[action + 'Class'](value[action]); }
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;
14218 that.attr('style', originalStyleAttr);
14220 if (callback) { callback.apply(this, arguments); }
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);
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);
14238 _toggleClass: $.fn.toggleClass,
14239 toggleClass: function(classNames, force, speed, easing, callback) {
14240 if ( typeof force == "boolean" || force === undefined ) {
14242 // without speed parameter;
14243 return this._toggleClass(classNames, force);
14245 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
14248 // without switch parameter;
14249 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
14253 switchClass: function(remove,add,speed,easing,callback) {
14254 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
14260 /******************************************************************************/
14261 /*********************************** EFFECTS **********************************/
14262 /******************************************************************************/
14264 $.extend($.effects, {
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]]);
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]));
14281 setMode: function(el, mode) {
14282 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
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
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;
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;
14301 return {x: x, y: y};
14304 // Wraps the element around a wrapper that copies position properties
14305 createWrapper: function(element) {
14307 // if the element is already wrapped, return it
14308 if (element.parent().is('.ui-effects-wrapper')) {
14309 return element.parent();
14312 // wrap the element
14314 width: element.outerWidth(true),
14315 height: element.outerHeight(true),
14316 'float': element.css('float')
14318 wrapper = $('<div></div>')
14319 .addClass('ui-effects-wrapper')
14322 background: 'transparent',
14327 active = document.activeElement;
14329 element.wrap(wrapper);
14331 // Fixes #7595 - Elements lose focus when wrapped.
14332 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
14333 $( active ).focus();
14336 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
14338 // transfer positioning properties to the wrapper
14339 if (element.css('position') == 'static') {
14340 wrapper.css({ position: 'relative' });
14341 element.css({ position: 'relative' });
14344 position: element.css('position'),
14345 zIndex: element.css('z-index')
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';
14353 element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
14356 return wrapper.css(props).show();
14359 removeWrapper: function(element) {
14361 active = document.activeElement;
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();
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];
14386 function _normalizeArguments(effect, options, speed, callback) {
14387 // shift params for method overloading
14388 if (typeof effect == 'object') {
14389 callback = options;
14392 effect = options.effect;
14394 if ($.isFunction(options)) {
14395 callback = options;
14399 if (typeof options == 'number' || $.fx.speeds[options]) {
14404 if ($.isFunction(speed)) {
14409 options = options || {};
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;
14415 callback = callback || options.complete;
14417 return [effect, options, speed, callback];
14420 function standardSpeed( speed ) {
14421 // valid standard speeds
14422 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
14426 // invalid strings - treat as "normal" speed
14427 if ( typeof speed === "string" && !$.effects[ speed ] ) {
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
14443 mode = args2.options.mode,
14444 effectMethod = $.effects[effect];
14446 if ( $.fx.off || !effectMethod ) {
14447 // delegate to the original method (e.g., .show()) if possible
14449 return this[ mode ]( args2.duration, args2.callback );
14451 return this.each(function() {
14452 if ( args2.callback ) {
14453 args2.callback.call( this );
14459 return effectMethod.call(this, args2);
14463 show: function(speed) {
14464 if ( standardSpeed( speed ) ) {
14465 return this._show.apply(this, arguments);
14467 var args = _normalizeArguments.apply(this, arguments);
14468 args[1].mode = 'show';
14469 return this.effect.apply(this, args);
14474 hide: function(speed) {
14475 if ( standardSpeed( speed ) ) {
14476 return this._hide.apply(this, arguments);
14478 var args = _normalizeArguments.apply(this, arguments);
14479 args[1].mode = 'hide';
14480 return this.effect.apply(this, args);
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);
14490 var args = _normalizeArguments.apply(this, arguments);
14491 args[1].mode = 'toggle';
14492 return this.effect.apply(this, args);
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];
14509 /******************************************************************************/
14510 /*********************************** EASING ***********************************/
14511 /******************************************************************************/
14514 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
14516 * Uses the built in easing capabilities added In jQuery 1.1
14517 * to offer multiple easing options
14519 * TERMS OF USE - jQuery Easing
14521 * Open source under the BSD License.
14523 * Copyright 2008 George McGinley Smith
14524 * All rights reserved.
14526 * Redistribution and use in source and binary forms, with or without modification,
14527 * are permitted provided that the following conditions are met:
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.
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.
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.
14550 // t: current time, b: begInnIng value, c: change In value, d: duration
14551 $.easing.jswing = $.easing.swing;
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);
14560 easeInQuad: function (x, t, b, c, d) {
14561 return c*(t/=d)*t + b;
14563 easeOutQuad: function (x, t, b, c, d) {
14564 return -c *(t/=d)*(t-2) + b;
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;
14570 easeInCubic: function (x, t, b, c, d) {
14571 return c*(t/=d)*t*t + b;
14573 easeOutCubic: function (x, t, b, c, d) {
14574 return c*((t=t/d-1)*t*t + 1) + b;
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;
14580 easeInQuart: function (x, t, b, c, d) {
14581 return c*(t/=d)*t*t*t + b;
14583 easeOutQuart: function (x, t, b, c, d) {
14584 return -c * ((t=t/d-1)*t*t*t - 1) + b;
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;
14590 easeInQuint: function (x, t, b, c, d) {
14591 return c*(t/=d)*t*t*t*t + b;
14593 easeOutQuint: function (x, t, b, c, d) {
14594 return c*((t=t/d-1)*t*t*t*t + 1) + b;
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;
14600 easeInSine: function (x, t, b, c, d) {
14601 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
14603 easeOutSine: function (x, t, b, c, d) {
14604 return c * Math.sin(t/d * (Math.PI/2)) + b;
14606 easeInOutSine: function (x, t, b, c, d) {
14607 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
14609 easeInExpo: function (x, t, b, c, d) {
14610 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
14612 easeOutExpo: function (x, t, b, c, d) {
14613 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
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;
14621 easeInCirc: function (x, t, b, c, d) {
14622 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
14624 easeOutCirc: function (x, t, b, c, d) {
14625 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
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;
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;
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;
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;
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;
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;
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;
14666 easeInBounce: function (x, t, b, c, d) {
14667 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
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;
14677 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
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;
14688 * TERMS OF USE - EASING EQUATIONS
14690 * Open source under the BSD License.
14692 * Copyright 2001 Robert Penner
14693 * All rights reserved.
14695 * Redistribution and use in source and binary forms, with or without modification,
14696 * are permitted provided that the following conditions are met:
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.
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.
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.
14721 * jQuery UI Effects Blind 1.8.16
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
14727 * http://docs.jquery.com/UI/Effects/Blind
14730 * jquery.effects.core.js
14732 (function( $, undefined ) {
14734 $.effects.blind = function(o) {
14736 return this.queue(function() {
14739 var el = $(this), props = ['position','top','bottom','left','right'];
14742 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14743 var direction = o.options.direction || 'vertical'; // Default direction
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
14753 var animation = {};
14754 animation[ref] = mode == 'show' ? distance : 0;
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
14770 * jQuery UI Effects Bounce 1.8.16
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
14776 * http://docs.jquery.com/UI/Effects/Bounce
14779 * jquery.effects.core.js
14781 (function( $, undefined ) {
14783 $.effects.bounce = function(o) {
14785 return this.queue(function() {
14788 var el = $(this), props = ['position','top','bottom','left','right'];
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
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--;
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;
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;
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(){
14828 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14829 if(o.callback) o.callback.apply(this, arguments); // Callback
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
14840 el.queue('fx', function() { el.dequeue(); });
14848 * jQuery UI Effects Clip 1.8.16
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
14854 * http://docs.jquery.com/UI/Effects/Clip
14857 * jquery.effects.core.js
14859 (function( $, undefined ) {
14861 $.effects.clip = function(o) {
14863 return this.queue(function() {
14866 var el = $(this), props = ['position','top','bottom','left','right','height','width'];
14869 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14870 var direction = o.options.direction || 'vertical'; // Default direction
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;
14877 size: (direction == 'vertical') ? 'height' : 'width',
14878 position: (direction == 'vertical') ? 'top' : 'left'
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
14884 var animation = {};
14885 animation[ref.size] = mode == 'show' ? distance : 0;
14886 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
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
14902 * jQuery UI Effects Drop 1.8.16
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
14908 * http://docs.jquery.com/UI/Effects/Drop
14911 * jquery.effects.core.js
14913 (function( $, undefined ) {
14915 $.effects.drop = function(o) {
14917 return this.queue(function() {
14920 var el = $(this), props = ['position','top','bottom','left','right','opacity'];
14923 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14924 var direction = o.options.direction || 'left'; // Default Direction
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
14935 var animation = {opacity: mode == 'show' ? 1 : 0};
14936 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
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
14952 * jQuery UI Effects Explode 1.8.16
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
14958 * http://docs.jquery.com/UI/Effects/Explode
14961 * jquery.effects.core.js
14963 (function( $, undefined ) {
14965 $.effects.explode = function(o) {
14967 return this.queue(function() {
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;
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();
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;
14980 var width = el.outerWidth(true);
14981 var height = el.outerHeight(true);
14983 for(var i=0;i<rows;i++) { // =
14984 for(var j=0;j<cells;j++) { // ||
14988 .wrap('<div></div>')
14990 position: 'absolute',
14991 visibility: 'visible',
14992 left: -j*(width/cells),
14993 top: -i*(height/rows)
14996 .addClass('ui-effects-explode')
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
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);
15013 // Set a timeout, to call the callback approx. when the other animations have finished
15014 setTimeout(function() {
15016 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
15017 if(o.callback) o.callback.apply(el[0]); // Callback
15020 $('div.ui-effects-explode').remove();
15022 }, o.duration || 500);
15031 * jQuery UI Effects Fade 1.8.16
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
15037 * http://docs.jquery.com/UI/Effects/Fade
15040 * jquery.effects.core.js
15042 (function( $, undefined ) {
15044 $.effects.fade = function(o) {
15045 return this.queue(function() {
15046 var elem = $(this),
15047 mode = $.effects.setMode(elem, o.options.mode || 'hide');
15049 elem.animate({ opacity: mode }, {
15051 duration: o.duration,
15052 easing: o.options.easing,
15053 complete: function() {
15054 (o.callback && o.callback.apply(this, arguments));
15063 * jQuery UI Effects Fold 1.8.16
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
15069 * http://docs.jquery.com/UI/Effects/Fold
15072 * jquery.effects.core.js
15074 (function( $, undefined ) {
15076 $.effects.fold = function(o) {
15078 return this.queue(function() {
15081 var el = $(this), props = ['position','top','bottom','left','right'];
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;
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
15100 var animation1 = {}, animation2 = {};
15101 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
15102 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
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
15119 * jQuery UI Effects Highlight 1.8.16
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
15125 * http://docs.jquery.com/UI/Effects/Highlight
15128 * jquery.effects.core.js
15130 (function( $, undefined ) {
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'),
15138 backgroundColor: elem.css('backgroundColor')
15141 if (mode == 'hide') {
15142 animation.opacity = 0;
15145 $.effects.save(elem, props);
15149 backgroundImage: 'none',
15150 backgroundColor: o.options.color || '#ffff99'
15152 .animate(animation, {
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));
15169 * jQuery UI Effects Pulsate 1.8.16
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
15175 * http://docs.jquery.com/UI/Effects/Pulsate
15178 * jquery.effects.core.js
15180 (function( $, undefined ) {
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'),
15192 elem.css('opacity', 0).show();
15196 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
15200 for (var i = 0; i < times; i++) {
15201 elem.animate({ opacity: animateTo }, duration, o.options.easing);
15202 animateTo = (animateTo + 1) % 2;
15205 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
15206 if (animateTo == 0) {
15209 (o.callback && o.callback.apply(this, arguments));
15213 .queue('fx', function() { elem.dequeue(); })
15220 * jQuery UI Effects Scale 1.8.16
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
15226 * http://docs.jquery.com/UI/Effects/Scale
15229 * jquery.effects.core.js
15231 (function( $, undefined ) {
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() };
15241 $.extend(o.options, {
15244 percent: mode == 'hide' ? percent : 100,
15245 from: mode == 'hide'
15248 height: original.height * factor,
15249 width: original.width * factor
15253 elem.effect('scale', o.options, o.duration, o.callback);
15258 $.effects.scale = function(o) {
15260 return this.queue(function() {
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;
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
15279 var factor = { // Set scaling factor
15280 y: direction != 'horizontal' ? (percent / 100) : 1,
15281 x: direction != 'vertical' ? (percent / 100) : 1
15283 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
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;};
15291 options.from = el.from; options.to = el.to; options.mode = mode;
15294 el.effect('size', options, o.duration, o.callback);
15300 $.effects.size = function(o) {
15302 return this.queue(function() {
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'];
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
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;
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}
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);
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);
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);
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
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(){
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);
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);
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
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);
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
15398 * jQuery UI Effects Shake 1.8.16
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
15404 * http://docs.jquery.com/UI/Effects/Shake
15407 * jquery.effects.core.js
15409 (function( $, undefined ) {
15411 $.effects.shake = function(o) {
15413 return this.queue(function() {
15416 var el = $(this), props = ['position','top','bottom','left','right'];
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
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';
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;
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);
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
15447 el.queue('fx', function() { el.dequeue(); });
15455 * jQuery UI Effects Slide 1.8.16
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
15461 * http://docs.jquery.com/UI/Effects/Slide
15464 * jquery.effects.core.js
15466 (function( $, undefined ) {
15468 $.effects.slide = function(o) {
15470 return this.queue(function() {
15473 var el = $(this), props = ['position','top','bottom','left','right'];
15476 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
15477 var direction = o.options.direction || 'left'; // Default Direction
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
15488 var animation = {};
15489 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
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
15505 * jQuery UI Effects Transfer 1.8.16
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
15511 * http://docs.jquery.com/UI/Effects/Transfer
15514 * jquery.effects.core.js
15516 (function( $, undefined ) {
15518 $.effects.transfer = function(o) {
15519 return this.queue(function() {
15520 var elem = $(this),
15521 target = $(o.options.to),
15522 endPosition = target.offset(),
15524 top: endPosition.top,
15525 left: endPosition.left,
15526 height: target.innerHeight(),
15527 width: target.innerWidth()
15529 startPosition = elem.offset(),
15530 transfer = $('<div class="ui-effects-transfer"></div>')
15531 .appendTo(document.body)
15532 .addClass(o.options.className)
15534 top: startPosition.top,
15535 left: startPosition.left,
15536 height: elem.innerHeight(),
15537 width: elem.innerWidth(),
15538 position: 'absolute'
15540 .animate(animation, o.duration, o.options.easing, function() {
15542 (o.callback && o.callback.apply(elem[0], arguments));
15550 * jQuery UI Accordion 1.8.16
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
15556 * http://docs.jquery.com/UI/Accordion
15559 * jquery.ui.core.js
15560 * jquery.ui.widget.js
15562 (function( $, undefined ) {
15564 $.widget( "ui.accordion", {
15570 collapsible: false,
15573 header: "> li > :first-child,> :not(li):even",
15575 header: "ui-icon-triangle-1-e",
15576 headerSelected: "ui-icon-triangle-1-s"
15579 navigationFilter: function() {
15580 return this.href.toLowerCase() === location.href.toLowerCase();
15584 _create: function() {
15586 options = self.options;
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
15595 .addClass( "ui-accordion-li-fix" );
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 ) {
15603 $( this ).addClass( "ui-state-hover" );
15605 .bind( "mouseleave.accordion", function() {
15606 if ( options.disabled ) {
15609 $( this ).removeClass( "ui-state-hover" );
15611 .bind( "focus.accordion", function() {
15612 if ( options.disabled ) {
15615 $( this ).addClass( "ui-state-focus" );
15617 .bind( "blur.accordion", function() {
15618 if ( options.disabled ) {
15621 $( this ).removeClass( "ui-state-focus" );
15624 self.headers.next()
15625 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
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;
15635 // anchor within content
15636 self.active = current.closest( ".ui-accordion-content" ).prev();
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" );
15647 self._createIcons();
15651 self.element.attr( "role", "tablist" );
15654 .attr( "role", "tab" )
15655 .bind( "keydown.accordion", function( event ) {
15656 return self._keydown( event );
15659 .attr( "role", "tabpanel" );
15662 .not( self.active || "" )
15664 "aria-expanded": "false",
15665 "aria-selected": "false",
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 );
15677 "aria-expanded": "true",
15678 "aria-selected": "true",
15683 // only need links in tab order for Safari
15684 if ( !$.browser.safari ) {
15685 self.headers.find( "a" ).attr( "tabIndex", -1 );
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();
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" );
15709 _destroyIcons: function() {
15710 this.headers.children( ".ui-icon" ).remove();
15711 this.element.removeClass( "ui-accordion-icons" );
15714 destroy: function() {
15715 var options = this.options;
15718 .removeClass( "ui-accordion ui-widget ui-helper-reset" )
15719 .removeAttr( "role" );
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" );
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", "" );
15739 return $.Widget.prototype.destroy.call( this );
15742 _setOption: function( key, value ) {
15743 $.Widget.prototype._setOption.apply( this, arguments );
15745 if ( key == "active" ) {
15746 this.activate( value );
15748 if ( key == "icons" ) {
15749 this._destroyIcons();
15751 this._createIcons();
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" );
15763 _keydown: function( event ) {
15764 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
15768 var keyCode = $.ui.keyCode,
15769 length = this.headers.length,
15770 currentIndex = this.headers.index( event.target ),
15773 switch ( event.keyCode ) {
15774 case keyCode.RIGHT:
15776 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
15780 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
15782 case keyCode.SPACE:
15783 case keyCode.ENTER:
15784 this._clickHandler( { target: event.target }, event.target );
15785 event.preventDefault();
15789 $( event.target ).attr( "tabIndex", -1 );
15790 $( toFocus ).attr( "tabIndex", 0 );
15798 resize: function() {
15799 var options = this.options,
15802 if ( options.fillSpace ) {
15803 if ( $.browser.msie ) {
15804 var defOverflow = this.element.parent().css( "overflow" );
15805 this.element.parent().css( "overflow", "hidden");
15807 maxHeight = this.element.parent().height();
15808 if ($.browser.msie) {
15809 this.element.parent().css( "overflow", defOverflow );
15812 this.headers.each(function() {
15813 maxHeight -= $( this ).outerHeight( true );
15816 this.headers.next()
15818 $( this ).height( Math.max( 0, maxHeight -
15819 $( this ).innerHeight() + $( this ).height() ) );
15821 .css( "overflow", "auto" );
15822 } else if ( options.autoHeight ) {
15824 this.headers.next()
15826 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15828 .height( maxHeight );
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 );
15844 _findActive: function( selector ) {
15846 ? typeof selector === "number"
15847 ? this.headers.filter( ":eq(" + selector + ")" )
15848 : this.headers.not( this.headers.not( selector ) )
15849 : selector === false
15851 : this.headers.filter( ":eq(0)" );
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 ) {
15861 // called only when using activate(false) to close all parts programmatically
15862 if ( !event.target ) {
15863 if ( !options.collapsible ) {
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(),
15876 newHeader: $( [] ),
15877 oldHeader: options.active,
15878 newContent: $( [] ),
15881 toShow = ( this.active = $( [] ) );
15882 this._toggle( toShow, toHide, data );
15886 // get the click target
15887 var clicked = $( event.currentTarget || target ),
15888 clickedIsActive = clicked[0] === this.active[0];
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 ?
15894 this.headers.index( clicked );
15896 // if animations are still active, or the active header is the target, ignore click
15897 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
15901 // find elements to show and hide
15902 var active = this.active,
15903 toShow = clicked.next(),
15904 toHide = this.active.next(),
15907 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
15908 oldHeader: this.active,
15909 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
15912 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
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 );
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 ) {
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 );
15935 .addClass( "ui-accordion-content-active" );
15941 _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
15943 options = self.options;
15945 self.toShow = toShow;
15946 self.toHide = toHide;
15949 var complete = function() {
15953 return self._completed.apply( self, arguments );
15956 // trigger changestart event
15957 self._trigger( "changestart", null, self.data );
15959 // count elements to animate
15960 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
15962 if ( options.animated ) {
15963 var animOptions = {};
15965 if ( options.collapsible && clickedIsActive ) {
15969 complete: complete,
15971 autoHeight: options.autoHeight || options.fillSpace
15977 complete: complete,
15979 autoHeight: options.autoHeight || options.fillSpace
15983 if ( !options.proxied ) {
15984 options.proxied = options.animated;
15987 if ( !options.proxiedDuration ) {
15988 options.proxiedDuration = options.duration;
15991 options.animated = $.isFunction( options.proxied ) ?
15992 options.proxied( animOptions ) :
15995 options.duration = $.isFunction( options.proxiedDuration ) ?
15996 options.proxiedDuration( animOptions ) :
15997 options.proxiedDuration;
15999 var animations = $.ui.accordion.animations,
16000 duration = options.duration,
16001 easing = options.animated;
16003 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
16006 if ( !animations[ easing ] ) {
16007 animations[ easing ] = function( options ) {
16008 this.slide( options, {
16010 duration: duration || 700
16015 animations[ easing ]( animOptions );
16017 if ( options.collapsible && clickedIsActive ) {
16027 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
16030 "aria-expanded": "false",
16031 "aria-selected": "false",
16037 "aria-expanded": "true",
16038 "aria-selected": "true",
16044 _completed: function( cancel ) {
16045 this.running = cancel ? 0 : --this.running;
16046 if ( this.running ) {
16050 if ( this.options.clearStyle ) {
16051 this.toShow.add( this.toHide ).css({
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;
16064 this._trigger( "change", null, this.data );
16068 $.extend( $.ui.accordion, {
16071 slide: function( options, additions ) {
16072 options = $.extend({
16075 }, options, additions );
16076 if ( !options.toHide.size() ) {
16077 options.toShow.animate({
16079 paddingTop: "show",
16080 paddingBottom: "show"
16084 if ( !options.toShow.size() ) {
16085 options.toHide.animate({
16087 paddingTop: "hide",
16088 paddingBottom: "hide"
16092 var overflow = options.toShow.css( "overflow" ),
16096 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
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 ) );
16107 $.each( fxAttrs, function( i, prop ) {
16108 hideProps[ prop ] = "hide";
16110 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
16111 showProps[ prop ] = {
16113 unit: parts[ 2 ] || "px"
16116 options.toShow.css({ height: 0, overflow: "hidden" }).show();
16118 .filter( ":hidden" )
16119 .each( options.complete )
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 );
16132 options.toShow[ 0 ].style[ settings.prop ] =
16133 ( percentDone * showProps[ settings.prop ].value )
16134 + showProps[ settings.prop ].unit;
16136 duration: options.duration,
16137 easing: options.easing,
16138 complete: function() {
16139 if ( !options.autoHeight ) {
16140 options.toShow.css( "height", "" );
16142 options.toShow.css({
16143 width: originalWidth,
16146 options.complete();
16150 bounceslide: function( options ) {
16151 this.slide( options, {
16152 easing: options.down ? "easeOutBounce" : "swing",
16153 duration: options.down ? 1000 : 200
16161 * jQuery UI Autocomplete 1.8.16
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
16167 * http://docs.jquery.com/UI/Autocomplete
16170 * jquery.ui.core.js
16171 * jquery.ui.widget.js
16172 * jquery.ui.position.js
16174 (function( $, undefined ) {
16176 // used to prevent race conditions with remote data sources
16177 var requestIndex = 0;
16179 $.widget( "ui.autocomplete", {
16195 _create: function() {
16197 doc = this.element[ 0 ].ownerDocument,
16201 .addClass( "ui-autocomplete-input" )
16202 .attr( "autocomplete", "off" )
16203 // TODO verify these actually work as intended
16206 "aria-autocomplete": "list",
16207 "aria-haspopup": "true"
16209 .bind( "keydown.autocomplete", function( event ) {
16210 if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) {
16214 suppressKeyPress = false;
16215 var keyCode = $.ui.keyCode;
16216 switch( event.keyCode ) {
16217 case keyCode.PAGE_UP:
16218 self._move( "previousPage", event );
16220 case keyCode.PAGE_DOWN:
16221 self._move( "nextPage", event );
16224 self._move( "previous", event );
16225 // prevent moving cursor to beginning of text field in some browsers
16226 event.preventDefault();
16229 self._move( "next", event );
16230 // prevent moving cursor to end of text field in some browsers
16231 event.preventDefault();
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();
16242 //passthrough - ENTER and TAB both select the current element
16244 if ( !self.menu.active ) {
16247 self.menu.select( event );
16249 case keyCode.ESCAPE:
16250 self.element.val( self.term );
16251 self.close( event );
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 );
16262 }, self.options.delay );
16266 .bind( "keypress.autocomplete", function( event ) {
16267 if ( suppressKeyPress ) {
16268 suppressKeyPress = false;
16269 event.preventDefault();
16272 .bind( "focus.autocomplete", function() {
16273 if ( self.options.disabled ) {
16277 self.selectedItem = null;
16278 self.previous = self.element.val();
16280 .bind( "blur.autocomplete", function( event ) {
16281 if ( self.options.disabled ) {
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 );
16292 this._initSource();
16293 this.response = function() {
16294 return self._response.apply( self, arguments );
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 ) ) {
16318 // use another timeout to make sure the blur-event-handler on the input was already triggered
16319 setTimeout(function() {
16320 clearTimeout( self.closing );
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 );
16333 selected: function( event, ui ) {
16334 var item = ui.item.data( "item.autocomplete" ),
16335 previous = self.previous;
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;
16350 if ( false !== self._trigger( "select", event, { item: item } ) ) {
16351 self.element.val( item.value );
16353 // reset the term after the select event
16354 // this allows custom select handling to work properly
16355 self.term = self.element.val();
16357 self.close( event );
16358 self.selectedItem = item;
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 );
16369 .zIndex( this.element.zIndex() + 1 )
16370 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
16371 .css({ top: 0, left: 0 })
16374 if ( $.fn.bgiframe ) {
16375 this.menu.element.bgiframe();
16379 destroy: function() {
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 );
16390 _setOption: function( key, value ) {
16391 $.Widget.prototype._setOption.apply( this, arguments );
16392 if ( key === "source" ) {
16393 this._initSource();
16395 if ( key === "appendTo" ) {
16396 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
16398 if ( key === "disabled" && value && this.xhr ) {
16403 _initSource: function() {
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) );
16412 } else if ( typeof this.options.source === "string" ) {
16413 url = this.options.source;
16414 this.source = function( request, response ) {
16418 self.xhr = $.ajax({
16422 autocompleteRequest: ++requestIndex,
16423 success: function( data, status ) {
16424 if ( this.autocompleteRequest === requestIndex ) {
16428 error: function() {
16429 if ( this.autocompleteRequest === requestIndex ) {
16436 this.source = this.options.source;
16440 search: function( value, event ) {
16441 value = value != null ? value : this.element.val();
16443 // always save the actual value, not the one passed as an argument
16444 this.term = this.element.val();
16446 if ( value.length < this.options.minLength ) {
16447 return this.close( event );
16450 clearTimeout( this.closing );
16451 if ( this._trigger( "search", event ) === false ) {
16455 return this._search( value );
16458 _search: function( value ) {
16460 this.element.addClass( "ui-autocomplete-loading" );
16462 this.source( { term: value }, this.response );
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" );
16474 if ( !this.pending ) {
16475 this.element.removeClass( "ui-autocomplete-loading" );
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 );
16488 _change: function( event ) {
16489 if ( this.previous !== this.element.val() ) {
16490 this._trigger( "change", event, { item: this.selectedItem } );
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 ) {
16499 return $.map( items, function(item) {
16500 if ( typeof item === "string" ) {
16507 label: item.label || item.value,
16508 value: item.value || item.label
16513 _suggest: function( items ) {
16514 var ul = this.menu.element
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();
16522 // size and position menu
16524 this._resizeMenu();
16525 ul.position( $.extend({
16527 }, this.options.position ));
16529 if ( this.options.autoFocus ) {
16530 this.menu.next( new $.Event("mouseover") );
16534 _resizeMenu: function() {
16535 var ul = this.menu.element;
16536 ul.outerWidth( Math.max(
16537 ul.width( "" ).outerWidth(),
16538 this.element.outerWidth()
16542 _renderMenu: function( ul, items ) {
16544 $.each( items, function( index, item ) {
16545 self._renderItem( ul, item );
16549 _renderItem: function( ul, item) {
16550 return $( "<li></li>" )
16551 .data( "item.autocomplete", item )
16552 .append( $( "<a></a>" ).text( item.label ) )
16556 _move: function( direction, event ) {
16557 if ( !this.menu.element.is(":visible") ) {
16558 this.search( null, event );
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();
16567 this.menu[ direction ]( event );
16570 widget: function() {
16571 return this.menu.element;
16575 $.extend( $.ui.autocomplete, {
16576 escapeRegex: function( value ) {
16577 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
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 );
16590 * jQuery UI Menu (not officially released)
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.
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
16600 * http://docs.jquery.com/UI/Menu
16603 * jquery.ui.core.js
16604 * jquery.ui.widget.js
16608 $.widget("ui.menu", {
16609 _create: function() {
16612 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
16615 "aria-activedescendant": "ui-active-menuitem"
16617 .click(function( event ) {
16618 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
16622 event.preventDefault();
16623 self.select( event );
16628 refresh: function() {
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");
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() );
16643 .mouseleave(function() {
16648 activate: function( event, item ) {
16650 if (this.hasScroll()) {
16651 var offset = item.offset().top - this.element.offset().top,
16652 scroll = this.element.scrollTop(),
16653 elementHeight = this.element.height();
16655 this.element.scrollTop( scroll + offset);
16656 } else if (offset >= elementHeight) {
16657 this.element.scrollTop( scroll + offset - elementHeight + item.height());
16660 this.active = item.eq(0)
16662 .addClass("ui-state-hover")
16663 .attr("id", "ui-active-menuitem")
16665 this._trigger("focus", event, { item: item });
16668 deactivate: function() {
16669 if (!this.active) { return; }
16671 this.active.children("a")
16672 .removeClass("ui-state-hover")
16674 this._trigger("blur");
16675 this.active = null;
16678 next: function(event) {
16679 this.move("next", ".ui-menu-item:first", event);
16682 previous: function(event) {
16683 this.move("prev", ".ui-menu-item:last", event);
16686 first: function() {
16687 return this.active && !this.active.prevAll(".ui-menu-item").length;
16691 return this.active && !this.active.nextAll(".ui-menu-item").length;
16694 move: function(direction, edge, event) {
16695 if (!this.active) {
16696 this.activate(event, this.element.children(edge));
16699 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
16701 this.activate(event, next);
16703 this.activate(event, this.element.children(edge));
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"));
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;
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");
16727 this.activate(event, result);
16729 this.activate(event, this.element.children(".ui-menu-item")
16730 .filter(!this.active || this.last() ? ":first" : ":last"));
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"));
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;
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");
16755 this.activate(event, result);
16757 this.activate(event, this.element.children(".ui-menu-item")
16758 .filter(!this.active || this.first() ? ":last" : ":first"));
16762 hasScroll: function() {
16763 return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight");
16766 select: function( event ) {
16767 this._trigger("selected", event, { item: this.active });
16773 * jQuery UI Button 1.8.16
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
16779 * http://docs.jquery.com/UI/Button
16782 * jquery.ui.core.js
16783 * jquery.ui.widget.js
16785 (function( $, undefined ) {
16787 var lastActive, startXPos, startYPos, clickDragged,
16788 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
16789 stateClasses = "ui-state-hover ui-state-active ",
16790 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
16791 formResetHandler = function() {
16792 var buttons = $( this ).find( ":ui-button" );
16793 setTimeout(function() {
16794 buttons.button( "refresh" );
16797 radioGroup = function( radio ) {
16798 var name = radio.name,
16803 radios = $( form ).find( "[name='" + name + "']" );
16805 radios = $( "[name='" + name + "']", radio.ownerDocument )
16806 .filter(function() {
16814 $.widget( "ui.button", {
16824 _create: function() {
16825 this.element.closest( "form" )
16826 .unbind( "reset.button" )
16827 .bind( "reset.button", formResetHandler );
16829 if ( typeof this.options.disabled !== "boolean" ) {
16830 this.options.disabled = this.element.propAttr( "disabled" );
16833 this._determineButtonType();
16834 this.hasTitle = !!this.buttonElement.attr( "title" );
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";
16842 if ( options.label === null ) {
16843 options.label = this.buttonElement.html();
16846 if ( this.element.is( ":disabled" ) ) {
16847 options.disabled = true;
16851 .addClass( baseClasses )
16852 .attr( "role", "button" )
16853 .bind( "mouseenter.button", function() {
16854 if ( options.disabled ) {
16857 $( this ).addClass( "ui-state-hover" );
16858 if ( this === lastActive ) {
16859 $( this ).addClass( "ui-state-active" );
16862 .bind( "mouseleave.button", function() {
16863 if ( options.disabled ) {
16866 $( this ).removeClass( hoverClass );
16868 .bind( "click.button", function( event ) {
16869 if ( options.disabled ) {
16870 event.preventDefault();
16871 event.stopImmediatePropagation();
16876 .bind( "focus.button", function() {
16877 // no need to check disabled, focus won't be triggered anyway
16878 self.buttonElement.addClass( focusClass );
16880 .bind( "blur.button", function() {
16881 self.buttonElement.removeClass( focusClass );
16884 if ( toggleButton ) {
16885 this.element.bind( "change.button", function() {
16886 if ( clickDragged ) {
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)
16895 .bind( "mousedown.button", function( event ) {
16896 if ( options.disabled ) {
16899 clickDragged = false;
16900 startXPos = event.pageX;
16901 startYPos = event.pageY;
16903 .bind( "mouseup.button", function( event ) {
16904 if ( options.disabled ) {
16907 if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
16908 clickDragged = true;
16913 if ( this.type === "checkbox" ) {
16914 this.buttonElement.bind( "click.button", function() {
16915 if ( options.disabled || clickDragged ) {
16918 $( this ).toggleClass( "ui-state-active" );
16919 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
16921 } else if ( this.type === "radio" ) {
16922 this.buttonElement.bind( "click.button", function() {
16923 if ( options.disabled || clickDragged ) {
16926 $( this ).addClass( "ui-state-active" );
16927 self.buttonElement.attr( "aria-pressed", "true" );
16929 var radio = self.element[ 0 ];
16930 radioGroup( radio )
16933 return $( this ).button( "widget" )[ 0 ];
16935 .removeClass( "ui-state-active" )
16936 .attr( "aria-pressed", "false" );
16940 .bind( "mousedown.button", function() {
16941 if ( options.disabled ) {
16944 $( this ).addClass( "ui-state-active" );
16946 $( document ).one( "mouseup", function() {
16950 .bind( "mouseup.button", function() {
16951 if ( options.disabled ) {
16954 $( this ).removeClass( "ui-state-active" );
16956 .bind( "keydown.button", function(event) {
16957 if ( options.disabled ) {
16960 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
16961 $( this ).addClass( "ui-state-active" );
16964 .bind( "keyup.button", function() {
16965 $( this ).removeClass( "ui-state-active" );
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)
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();
16985 _determineButtonType: function() {
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";
16994 this.type = "button";
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 );
17010 this.element.addClass( "ui-helper-hidden-accessible" );
17012 var checked = this.element.is( ":checked" );
17014 this.buttonElement.addClass( "ui-state-active" );
17016 this.buttonElement.attr( "aria-pressed", checked );
17018 this.buttonElement = this.element;
17022 widget: function() {
17023 return this.buttonElement;
17026 destroy: function() {
17028 .removeClass( "ui-helper-hidden-accessible" );
17030 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
17031 .removeAttr( "role" )
17032 .removeAttr( "aria-pressed" )
17033 .html( this.buttonElement.find(".ui-button-text").html() );
17035 if ( !this.hasTitle ) {
17036 this.buttonElement.removeAttr( "title" );
17039 $.Widget.prototype.destroy.call( this );
17042 _setOption: function( key, value ) {
17043 $.Widget.prototype._setOption.apply( this, arguments );
17044 if ( key === "disabled" ) {
17046 this.element.propAttr( "disabled", true );
17048 this.element.propAttr( "disabled", false );
17052 this._resetButton();
17055 refresh: function() {
17056 var isDisabled = this.element.is( ":disabled" );
17057 if ( isDisabled !== this.options.disabled ) {
17058 this._setOption( "disabled", isDisabled );
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" );
17067 $( this ).button( "widget" )
17068 .removeClass( "ui-state-active" )
17069 .attr( "aria-pressed", "false" );
17072 } else if ( this.type === "checkbox" ) {
17073 if ( this.element.is( ":checked" ) ) {
17075 .addClass( "ui-state-active" )
17076 .attr( "aria-pressed", "true" );
17079 .removeClass( "ui-state-active" )
17080 .attr( "aria-pressed", "false" );
17085 _resetButton: function() {
17086 if ( this.type === "input" ) {
17087 if ( this.options.label ) {
17088 this.element.val( this.options.label );
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() )
17098 icons = this.options.icons,
17099 multipleIcons = icons.primary && icons.secondary,
17100 buttonClasses = [];
17102 if ( icons.primary || icons.secondary ) {
17103 if ( this.options.text ) {
17104 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
17107 if ( icons.primary ) {
17108 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
17111 if ( icons.secondary ) {
17112 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
17115 if ( !this.options.text ) {
17116 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
17118 if ( !this.hasTitle ) {
17119 buttonElement.attr( "title", buttonText );
17123 buttonClasses.push( "ui-button-text-only" );
17125 buttonElement.addClass( buttonClasses.join( " " ) );
17129 $.widget( "ui.buttonset", {
17131 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
17134 _create: function() {
17135 this.element.addClass( "ui-buttonset" );
17138 _init: function() {
17142 _setOption: function( key, value ) {
17143 if ( key === "disabled" ) {
17144 this.buttons.button( "option", key, value );
17147 $.Widget.prototype._setOption.apply( this, arguments );
17150 refresh: function() {
17151 var ltr = this.element.css( "direction" ) === "ltr";
17153 this.buttons = this.element.find( this.options.items )
17154 .filter( ":ui-button" )
17155 .button( "refresh" )
17157 .not( ":ui-button" )
17161 return $( this ).button( "widget" )[ 0 ];
17163 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
17164 .filter( ":first" )
17165 .addClass( ltr ? "ui-corner-left" : "ui-corner-right" )
17168 .addClass( ltr ? "ui-corner-right" : "ui-corner-left" )
17173 destroy: function() {
17174 this.element.removeClass( "ui-buttonset" );
17177 return $( this ).button( "widget" )[ 0 ];
17179 .removeClass( "ui-corner-left ui-corner-right" )
17181 .button( "destroy" );
17183 $.Widget.prototype.destroy.call( this );
17189 * jQuery UI Datepicker 1.8.16
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
17195 * http://docs.jquery.com/UI/Datepicker
17198 * jquery.ui.core.js
17200 (function( $, undefined ) {
17202 $.extend($.ui, { datepicker: { version: "1.8.16" } });
17204 var PROP_NAME = 'datepicker';
17205 var dpuuid = new Date().getTime();
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. */
17213 function Datepicker() {
17214 this.debug = false; // Change this to true to start debugging
17215 this._curInst = null; // The current instance in use
17216 this._keyEvent = false; // If the last event was a key event
17217 this._disabledInputs = []; // List of date picker inputs that have been disabled
17218 this._datepickerShowing = false; // True if the popup picker is showing , false if not
17219 this._inDialog = false; // True if showing within a "dialog", false if not
17220 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
17221 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
17222 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
17223 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
17224 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
17225 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
17226 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
17227 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
17228 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
17229 this.regional = []; // Available regional settings, indexed by language code
17230 this.regional[''] = { // Default regional settings
17231 closeText: 'Done', // Display text for close link
17232 prevText: 'Prev', // Display text for previous month link
17233 nextText: 'Next', // Display text for next month link
17234 currentText: 'Today', // Display text for current month link
17235 monthNames: ['January','February','March','April','May','June',
17236 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
17237 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
17238 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
17239 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
17240 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
17241 weekHeader: 'Wk', // Column header for week of the year
17242 dateFormat: 'mm/dd/yy', // See format options on parseDate
17243 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
17244 isRTL: false, // True if right-to-left language, false if left-to-right
17245 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
17246 yearSuffix: '' // Additional text to append to the year in the month headers
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
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>'));
17302 $.extend(Datepicker.prototype, {
17303 /* Class name added to elements to indicate already configured with a date picker. */
17304 markerClassName: 'hasDatepicker',
17306 //Keep track of the maximum number of rows displayed (see #7043)
17309 /* Debug logging (if enabled). */
17312 console.log.apply('', arguments);
17315 // TODO rename to "widget" when switching to widget factory
17316 _widgetDatepicker: function() {
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 || {});
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);
17337 inlineSettings = inlineSettings || {};
17339 inlineSettings[attrName] = eval(attrValue);
17341 inlineSettings[attrName] = attrValue;
17345 var nodeName = target.nodeName.toLowerCase();
17346 var inline = (nodeName == 'div' || nodeName == 'span');
17349 target.id = 'dp' + this.uuid;
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);
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>')))};
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))
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);
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 );
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');
17399 inst.append.remove();
17401 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
17402 input[isRTL ? 'before' : 'after'](inst.append);
17404 input.unbind('focus', this._showDatepicker);
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();
17424 $.datepicker._showDatepicker(input[0]);
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) {
17439 for (var i = 0; i < names.length; i++) {
17440 if (names[i].length > max) {
17441 max = names[i].length;
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());
17452 inst.input.attr('size', this._formatDate(inst, date).length);
17456 /* Attach an inline date picker to a div. */
17457 _inlineDatepicker: function(target, inst) {
17458 var divSpan = $(target);
17459 if (divSpan.hasClass(this.markerClassName))
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);
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 );
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" );
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
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);
17502 extendRemove(inst.settings, settings || {});
17503 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
17504 this._dialogInput.val(date);
17506 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
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];
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]);
17523 $.blockUI(this.dpDiv);
17524 $.data(this._dialogInput[0], PROP_NAME, inst);
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)) {
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();
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)) {
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: ''});
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");
17571 this._disabledInputs = $.map(this._disabledInputs,
17572 function(value) { return (value == target ? null : value); }); // delete entry
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)) {
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'});
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");
17596 this._disabledInputs = $.map(this._disabledInputs,
17597 function(value) { return (value == target ? null : value); }); // delete entry
17598 this._disabledInputs[this._disabledInputs.length] = target;
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) {
17608 for (var i = 0; i < this._disabledInputs.length; i++) {
17609 if (this._disabledInputs[i] == target)
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) {
17621 return $.data(target, PROP_NAME);
17624 throw 'Missing instance data for this datepicker';
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));
17643 var settings = name || {};
17644 if (typeof name == 'string') {
17646 settings[name] = value;
17649 if (this._curInst == inst) {
17650 this._hideDatepicker();
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);
17669 // change method deprecated
17670 _changeDatepicker: function(target, name, value) {
17671 this._optionDatepicker(target, name, value);
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);
17679 this._updateDatepicker(inst);
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);
17689 this._setDate(inst, date);
17690 this._updateDatepicker(inst);
17691 this._updateAlternate(inst);
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);
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();
17716 break; // hide on tab out
17717 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
17718 $.datepicker._currentClass + ')', inst.dpDiv);
17720 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
17721 var onSelect = $.datepicker._get(inst, 'onSelect');
17723 var dateStr = $.datepicker._formatDate(inst);
17725 // trigger custom callback
17726 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
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
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
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;
17772 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
17773 $.datepicker._showDatepicker(this);
17778 event.preventDefault();
17779 event.stopPropagation();
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);
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) {
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);
17808 $.datepicker.log(event);
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
17824 var inst = $.datepicker._getInst(input);
17825 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
17826 if ( $.datepicker._datepickerShowing ) {
17827 $.datepicker._triggerOnClose($.datepicker._curInst);
17829 $.datepicker._curInst.dpDiv.stop(true, true);
17831 var beforeShow = $.datepicker._get(inst, 'beforeShow');
17832 var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
17833 if(beforeShowSettings === false){
17837 extendRemove(inst.settings, beforeShowSettings);
17838 inst.lastVal = null;
17839 $.datepicker._lastInput = input;
17840 $.datepicker._setDateFromField(inst);
17841 if ($.datepicker._inDialog) // hide cursor
17843 if (!$.datepicker._pos) { // position below input
17844 $.datepicker._pos = $.datepicker._findPos(input);
17845 $.datepicker._pos[1] += input.offsetHeight; // add the height
17847 var isFixed = false;
17848 $(input).parents().each(function() {
17849 isFixed |= $(this).css('position') == 'fixed';
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;
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()});
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);
17885 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
17886 if (!showAnim || !duration)
17888 if (inst.input.is(':visible') && !inst.input.is(':disabled'))
17889 inst.input.focus();
17890 $.datepicker._curInst = inst;
17894 /* Generate the date picker content. */
17895 _updateDatepicker: function(inst) {
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()})
17905 inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
17906 var numMonths = this._getNumberOfMonths(inst);
17907 var cols = numMonths[1];
17909 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
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);
17929 origyearshtml = inst.yearshtml = null;
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;
17941 return [parseFloat(convert(elem.css('border-left-width'))),
17942 parseFloat(convert(elem.css('border-top-width')))];
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();
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;
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);
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'];
17974 var position = $(obj).offset();
17975 return [position.left, position.top];
17978 /* Trigger custom callback of onClose. */
17979 _triggerOnClose: function(inst) {
17980 var onClose = this._get(inst, 'onClose');
17982 onClose.apply((inst.input ? inst.input[0] : null),
17983 [(inst.input ? inst.input.val() : ''), inst]);
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)))
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;
17999 if ($.effects && $.effects[showAnim])
18000 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
18002 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
18003 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), 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' });
18013 $('body').append(this.dpDiv);
18016 this._inDialog = false;
18020 /* Tidy up after a dialog display. */
18021 _tidyDialog: function(inst) {
18022 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
18025 /* Close date picker if clicked elsewhere. */
18026 _checkExternalClick: function(event) {
18027 if (!$.datepicker._curInst)
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();
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])) {
18045 this._adjustInstDate(inst, offset +
18046 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
18048 this._updateDatepicker(inst);
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;
18061 var date = new Date();
18062 inst.selectedDay = date.getDate();
18063 inst.drawMonth = inst.selectedMonth = date.getMonth();
18064 inst.drawYear = inst.selectedYear = date.getFullYear();
18066 this._notifyChange(inst);
18067 this._adjustDate(target);
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);
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])) {
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));
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, '');
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));
18108 inst.input.val(dateStr);
18109 this._updateAlternate(inst);
18110 var onSelect = this._get(inst, '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
18116 this._updateDatepicker(inst);
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;
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); });
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), ''];
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;
18158 /* Parse a string value into a date object.
18159 See formatDate below for the possible formats.
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 + '');
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;
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);
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);
18203 throw 'Missing number at position ' + iValue;
18204 iValue += num[0].length;
18205 return parseInt(num[0], 10);
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) {
18211 }).sort(function (a, b) {
18212 return -(a[1].length - b[1].length);
18215 $.each(names, function (i, pair) {
18216 var name = pair[1];
18217 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
18219 iValue += name.length;
18226 throw 'Unknown name at position ' + iValue;
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;
18235 for (var iFormat = 0; iFormat < format.length; iFormat++) {
18237 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
18242 switch (format.charAt(iFormat)) {
18244 day = getNumber('d');
18247 getName('D', dayNamesShort, dayNames);
18250 doy = getNumber('o');
18253 month = getNumber('m');
18256 month = getName('M', monthNamesShort, monthNames);
18259 year = getNumber('y');
18262 var date = new Date(getNumber('@'));
18263 year = date.getFullYear();
18264 month = date.getMonth() + 1;
18265 day = date.getDate();
18268 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
18269 year = date.getFullYear();
18270 month = date.getMonth() + 1;
18271 day = date.getDate();
18274 if (lookAhead("'"))
18283 if (iValue < value.length){
18284 throw "Extra/unparsed characters found in date: " + value.substring(iValue);
18287 year = new Date().getFullYear();
18288 else if (year < 100)
18289 year += new Date().getFullYear() - new Date().getFullYear() % 100 +
18290 (year <= shortYearCutoff ? 0 : -100);
18295 var dim = this._getDaysInMonth(year, month - 1);
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
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
18320 W3C: 'yy-mm-dd', // ISO 8601
18322 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
18323 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
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)
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
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) {
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);
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)
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]);
18379 var literal = false;
18381 for (var iFormat = 0; iFormat < format.length; iFormat++) {
18383 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
18386 output += format.charAt(iFormat);
18388 switch (format.charAt(iFormat)) {
18390 output += formatNumber('d', date.getDate(), 2);
18393 output += formatName('D', date.getDay(), dayNamesShort, dayNames);
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);
18400 output += formatNumber('m', date.getMonth() + 1, 2);
18403 output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
18406 output += (lookAhead('y') ? date.getFullYear() :
18407 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
18410 output += date.getTime();
18413 output += date.getTime() * 10000 + this._ticksTo1970;
18416 if (lookAhead("'"))
18422 output += format.charAt(iFormat);
18428 /* Extract all possible characters from the date format. */
18429 _possibleChars: function (format) {
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);
18439 for (var iFormat = 0; iFormat < format.length; iFormat++)
18441 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
18444 chars += format.charAt(iFormat);
18446 switch (format.charAt(iFormat)) {
18447 case 'd': case 'm': case 'y': case '@':
18448 chars += '0123456789';
18450 case 'D': case 'M':
18451 return null; // Accept anything
18453 if (lookAhead("'"))
18459 chars += format.charAt(iFormat);
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];
18470 /* Parse existing date and initialise date picker. */
18471 _setDateFromField: function(inst, noDefault) {
18472 if (inst.input.val() == inst.lastVal) {
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);
18481 date = this.parseDate(dateFormat, dates, settings) || defaultDate;
18484 dates = (noDefault ? '' : dates);
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);
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()));
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);
18508 var offsetString = function(offset) {
18510 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
18511 offset, $.datepicker._getFormatConfig(inst));
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);
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));
18533 case 'y': case 'Y' :
18534 year += parseInt(matches[1],10);
18535 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
18538 matches = pattern.exec(offset);
18540 return new Date(year, month, day);
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);
18546 newDate.setHours(0);
18547 newDate.setMinutes(0);
18548 newDate.setSeconds(0);
18549 newDate.setMilliseconds(0);
18551 return this._daylightSavingAdjust(newDate);
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);
18566 /* Set the date(s) directly. */
18567 _setDate: function(inst, date, noChange) {
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);
18579 inst.input.val(clear ? '' : this._formatDate(inst));
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)));
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) {
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) {
18620 if (drawMonth < 0) {
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);
18670 for (var row = 0; row < numMonths[0]; row++) {
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';
18677 if (isMultiMonth) {
18678 calender += '<div class="ui-datepicker-group';
18679 if (numMonths[1] > 1)
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;
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>' +
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>';
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 ? ' ' : // 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);
18744 calender += tbody + '</tr>';
18747 if (drawMonth > 11) {
18751 calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
18752 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
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;
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 = '';
18772 if (secondary || !changeMonth)
18773 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
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\');" ' +
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>';
18787 monthHtml += '</select>';
18789 if (!showMonthAfterYear)
18790 html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : '');
18792 if ( !inst.yearshtml ) {
18793 inst.yearshtml = '';
18794 if (secondary || !changeYear)
18795 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
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);
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\');" ' +
18813 for (; year <= endYear; year++) {
18814 inst.yearshtml += '<option value="' + year + '"' +
18815 (year == drawYear ? ' selected="selected"' : '') +
18816 '>' + year + '</option>';
18818 inst.yearshtml += '</select>';
18820 html += inst.yearshtml;
18821 inst.yearshtml = null;
18824 html += this._get(inst, 'yearSuffix');
18825 if (showMonthAfterYear)
18826 html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml;
18827 html += '</div>'; // Close datepicker_header
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);
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);
18855 /* Notify change of month/year. */
18856 _notifyChange: function(inst) {
18857 var onChange = this._get(inst, 'onChangeMonthYear');
18859 onChange.apply((inst.input ? inst.input[0] : null),
18860 [inst.selectedYear, inst.selectedMonth + 1, inst]);
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));
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);
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();
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();
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));
18890 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
18891 return this._isInRange(inst, date);
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()));
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')};
18912 /* Format the given date for display. */
18913 _formatDate: function(inst, day, month, year) {
18915 inst.currentDay = inst.selectedDay;
18916 inst.currentMonth = inst.selectedMonth;
18917 inst.currentYear = inst.selectedYear;
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));
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.
18931 function bindHover(dpDiv) {
18932 var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
18933 return dpDiv.bind('mouseout', function(event) {
18934 var elem = $( event.target ).closest( selector );
18935 if ( !elem.length ) {
18938 elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" );
18940 .bind('mouseover', function(event) {
18941 var elem = $( event.target ).closest( selector );
18942 if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) ||
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');
18953 /* jQuery extend now ignores nulls! */
18954 function extendRemove(target, props) {
18955 $.extend(target, props);
18956 for (var name in props)
18957 if (props[name] == null || props[name] == undefined)
18958 target[name] = props[name];
18962 /* Determine whether an object is an array. */
18963 function isArray(a) {
18964 return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
18965 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
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){
18974 /* Verify an empty collection wasn't passed - Fixes #6976 */
18975 if ( !this.length ) {
18979 /* Initialise the date picker. */
18980 if (!$.datepicker.initialized) {
18981 $(document).mousedown($.datepicker._checkExternalClick).
18982 find('body').append($.datepicker.dpDiv);
18983 $.datepicker.initialized = true;
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);
19001 $.datepicker = new Datepicker(); // singleton instance
19002 $.datepicker.initialized = false;
19003 $.datepicker.uuid = new Date().getTime();
19004 $.datepicker.version = "1.8.16";
19006 // Workaround for #4055
19007 // Add another global to avoid noConflict issues with inline event handlers
19008 window['DP_jQuery_' + dpuuid] = $;
19012 * jQuery UI Dialog 1.8.16
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
19018 * http://docs.jquery.com/UI/Dialog
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
19029 (function( $, undefined ) {
19031 var uiDialogClasses =
19034 'ui-widget-content ' +
19036 sizeRelatedOptions = {
19045 resizableRelatedOptions = {
19051 // support for jQuery 1.3.2 - handle common attrFn methods for dialog
19052 attrFn = $.attrFn || {
19064 $.widget("ui.dialog", {
19068 closeOnEscape: true,
19069 closeText: 'close',
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);
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 = "";
19106 this.options.title = this.options.title || this.originalTitle;
19108 options = self.options,
19110 title = options.title || ' ',
19111 titleId = $.ui.dialog.getTitleId(self.element),
19113 uiDialog = (self.uiDialog = $('<div></div>'))
19114 .appendTo(document.body)
19116 .addClass(uiDialogClasses + options.dialogClass)
19118 zIndex: options.zIndex
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) {
19127 event.preventDefault();
19132 'aria-labelledby': titleId
19134 .mousedown(function(event) {
19135 self.moveToTop(false, event);
19138 uiDialogContent = self.element
19140 .removeAttr('title')
19142 'ui-dialog-content ' +
19143 'ui-widget-content')
19144 .appendTo(uiDialog),
19146 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
19148 'ui-dialog-titlebar ' +
19149 'ui-widget-header ' +
19151 'ui-helper-clearfix'
19153 .prependTo(uiDialog),
19155 uiDialogTitlebarClose = $('<a href="#"></a>')
19157 'ui-dialog-titlebar-close ' +
19160 .attr('role', 'button')
19163 uiDialogTitlebarClose.addClass('ui-state-hover');
19166 uiDialogTitlebarClose.removeClass('ui-state-hover');
19169 .focus(function() {
19170 uiDialogTitlebarClose.addClass('ui-state-focus');
19173 uiDialogTitlebarClose.removeClass('ui-state-focus');
19175 .click(function(event) {
19179 .appendTo(uiDialogTitlebar),
19181 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
19184 'ui-icon-closethick'
19186 .text(options.closeText)
19187 .appendTo(uiDialogTitlebarClose),
19189 uiDialogTitle = $('<span></span>')
19190 .addClass('ui-dialog-title')
19191 .attr('id', titleId)
19193 .prependTo(uiDialogTitlebar);
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;
19202 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
19204 if (options.draggable && $.fn.draggable) {
19205 self._makeDraggable();
19207 if (options.resizable && $.fn.resizable) {
19208 self._makeResizable();
19211 self._createButtons(options.buttons);
19212 self._isOpen = false;
19214 if ($.fn.bgiframe) {
19215 uiDialog.bgiframe();
19219 _init: function() {
19220 if ( this.options.autoOpen ) {
19225 destroy: function() {
19228 if (self.overlay) {
19229 self.overlay.destroy();
19231 self.uiDialog.hide();
19234 .removeData('dialog')
19235 .removeClass('ui-dialog-content ui-widget-content')
19236 .hide().appendTo('body');
19237 self.uiDialog.remove();
19239 if (self.originalTitle) {
19240 self.element.attr('title', self.originalTitle);
19246 widget: function() {
19247 return this.uiDialog;
19250 close: function(event) {
19254 if (false === self._trigger('beforeClose', event)) {
19258 if (self.overlay) {
19259 self.overlay.destroy();
19261 self.uiDialog.unbind('keypress.ui-dialog');
19263 self._isOpen = false;
19265 if (self.options.hide) {
19266 self.uiDialog.hide(self.options.hide, function() {
19267 self._trigger('close', event);
19270 self.uiDialog.hide();
19271 self._trigger('close', event);
19274 $.ui.dialog.overlay.resize();
19276 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
19277 if (self.options.modal) {
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);
19287 $.ui.dialog.maxZ = maxZ;
19293 isOpen: function() {
19294 return this._isOpen;
19297 // the force parameter allows us to move modal dialogs to their correct
19298 // position on open
19299 moveToTop: function(force, event) {
19301 options = self.options,
19304 if ((options.modal && !force) ||
19305 (!options.stack && !options.modal)) {
19306 return self._trigger('focus', event);
19309 if (options.zIndex > $.ui.dialog.maxZ) {
19310 $.ui.dialog.maxZ = options.zIndex;
19312 if (self.overlay) {
19313 $.ui.dialog.maxZ += 1;
19314 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
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);
19329 if (this._isOpen) { return; }
19332 options = self.options,
19333 uiDialog = self.uiDialog;
19335 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
19337 self._position(options.position);
19338 uiDialog.show(options.show);
19339 self.moveToTop(true);
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) {
19348 var tabbables = $(':tabbable', this),
19349 first = tabbables.filter(':first'),
19350 last = tabbables.filter(':last');
19352 if (event.target === last[0] && !event.shiftKey) {
19355 } else if (event.target === first[0] && event.shiftKey) {
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();
19368 self._isOpen = true;
19369 self._trigger('open');
19374 _createButtons: function(buttons) {
19376 hasButtons = false,
19377 uiDialogButtonPane = $('<div></div>')
19379 'ui-dialog-buttonpane ' +
19380 'ui-widget-content ' +
19381 'ui-helper-clearfix'
19383 uiButtonSet = $( "<div></div>" )
19384 .addClass( "ui-dialog-buttonset" )
19385 .appendTo( uiDialogButtonPane );
19387 // if we already have a button pane, remove it
19388 self.uiDialog.find('.ui-dialog-buttonpane').remove();
19390 if (typeof buttons === 'object' && buttons !== null) {
19391 $.each(buttons, function() {
19392 return !(hasButtons = true);
19396 $.each(buttons, function(name, props) {
19397 props = $.isFunction( props ) ?
19398 { click: props, text: name } :
19400 var button = $('<button type="button"></button>')
19401 .click(function() {
19402 props.click.apply(self.element[0], arguments);
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" ) {
19410 if ( key in attrFn ) {
19411 button[ key ]( value );
19413 button.attr( key, value );
19420 uiDialogButtonPane.appendTo(self.uiDialog);
19424 _makeDraggable: function() {
19426 options = self.options,
19430 function filteredUi(ui) {
19432 position: ui.position,
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));
19446 drag: function(event, ui) {
19447 self._trigger('drag', event, filteredUi(ui));
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();
19459 _makeResizable: function(handles) {
19460 handles = (handles === undefined ? this.options.resizable : handles);
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' ?
19468 'n,e,s,w,se,sw,ne,nw'
19471 function filteredUi(ui) {
19473 originalPosition: ui.originalPosition,
19474 originalSize: ui.originalSize,
19475 position: ui.position,
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));
19493 resize: function(event, ui) {
19494 self._trigger('resize', event, filteredUi(ui));
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();
19504 .css('position', position)
19505 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
19508 _minHeight: function() {
19509 var options = this.options;
19511 if (options.height === 'auto') {
19512 return options.minHeight;
19514 return Math.min(options.minHeight, options.height);
19518 _position: function(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(' ');
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) {
19534 $.each(['left', 'top'], function(i, offsetPosition) {
19535 if (+myAt[i] === myAt[i]) {
19536 offset[i] = myAt[i];
19537 myAt[i] = offsetPosition;
19542 my: myAt.join(" "),
19543 at: myAt.join(" "),
19544 offset: offset.join(" ")
19548 position = $.extend({}, $.ui.dialog.prototype.options.position, position);
19550 position = $.ui.dialog.prototype.options.position;
19553 // need to show the dialog to get the actual offset in the position plugin
19554 isVisible = this.uiDialog.is(':visible');
19556 this.uiDialog.show();
19559 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
19560 .css({ top: 0, left: 0 })
19561 .position($.extend({ of: window }, position));
19563 this.uiDialog.hide();
19567 _setOptions: function( options ) {
19569 resizableOptions = {},
19572 $.each( options, function( key, value ) {
19573 self._setOption( key, value );
19575 if ( key in sizeRelatedOptions ) {
19578 if ( key in resizableRelatedOptions ) {
19579 resizableOptions[ key ] = value;
19586 if ( this.uiDialog.is( ":data(resizable)" ) ) {
19587 this.uiDialog.resizable( "option", resizableOptions );
19591 _setOption: function(key, value){
19593 uiDialog = self.uiDialog;
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";
19603 self._createButtons(value);
19606 // ensure that we always pass a string
19607 self.uiDialogTitlebarCloseText.text("" + value);
19609 case "dialogClass":
19611 .removeClass(self.options.dialogClass)
19612 .addClass(uiDialogClasses + value);
19616 uiDialog.addClass('ui-dialog-disabled');
19618 uiDialog.removeClass('ui-dialog-disabled');
19622 var isDraggable = uiDialog.is( ":data(draggable)" );
19623 if ( isDraggable && !value ) {
19624 uiDialog.draggable( "destroy" );
19627 if ( !isDraggable && value ) {
19628 self._makeDraggable();
19632 self._position(value);
19635 // currently resizable, becoming non-resizable
19636 var isResizable = uiDialog.is( ":data(resizable)" );
19637 if (isResizable && !value) {
19638 uiDialog.resizable('destroy');
19641 // currently resizable, changing handles
19642 if (isResizable && typeof value === 'string') {
19643 uiDialog.resizable('option', 'handles', value);
19646 // currently non-resizable, becoming resizable
19647 if (!isResizable && value !== false) {
19648 self._makeResizable(value);
19652 // convert whatever was passed in o a string, for html() to not throw up
19653 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' '));
19657 $.Widget.prototype._setOption.apply(self, arguments);
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
19664 var options = this.options,
19667 isVisible = this.uiDialog.is( ":visible" );
19669 // reset content sizing
19670 this.element.show().css({
19676 if (options.minWidth > options.width) {
19677 options.width = options.minWidth;
19680 // reset wrapper sizing
19681 // determine the height of all the non-content elements
19682 nonContentHeight = this.uiDialog.css({
19684 width: options.width
19687 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
19689 if ( options.height === "auto" ) {
19690 // only needed for IE6 support
19691 if ( $.support.minHeight ) {
19693 minHeight: minContentHeight,
19697 this.uiDialog.show();
19698 var autoHeight = this.element.css( "height", "auto" ).height();
19699 if ( !isVisible ) {
19700 this.uiDialog.hide();
19702 this.element.height( Math.max( autoHeight, minContentHeight ) );
19705 this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
19708 if (this.uiDialog.is(':data(resizable)')) {
19709 this.uiDialog.resizable('option', 'minHeight', this._minHeight());
19714 $.extend($.ui.dialog, {
19720 getTitleId: function($el) {
19721 var id = $el.attr('id');
19726 return 'ui-dialog-title-' + id;
19729 overlay: function(dialog) {
19730 this.$el = $.ui.dialog.overlay.create(dialog);
19734 $.extend($.ui.dialog.overlay, {
19736 // reuse old instances due to IE memory leak with alpha transparency (see #5185)
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) {
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) {
19764 dialog.close(event);
19765 event.preventDefault();
19769 // handle window resize
19770 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
19773 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
19774 .appendTo(document.body)
19776 width: this.width(),
19777 height: this.height()
19780 if ($.fn.bgiframe) {
19784 this.instances.push($el);
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]);
19794 if (this.instances.length === 0) {
19795 $([document, window]).unbind('.dialog-overlay');
19800 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
19802 $.each(this.instances, function() {
19803 maxZ = Math.max(maxZ, this.css('z-index'));
19808 height: function() {
19812 if ($.browser.msie && $.browser.version < 7) {
19813 scrollHeight = Math.max(
19814 document.documentElement.scrollHeight,
19815 document.body.scrollHeight
19817 offsetHeight = Math.max(
19818 document.documentElement.offsetHeight,
19819 document.body.offsetHeight
19822 if (scrollHeight < offsetHeight) {
19823 return $(window).height() + 'px';
19825 return scrollHeight + 'px';
19827 // handle "good" browsers
19829 return $(document).height() + 'px';
19833 width: function() {
19837 if ( $.browser.msie ) {
19838 scrollWidth = Math.max(
19839 document.documentElement.scrollWidth,
19840 document.body.scrollWidth
19842 offsetWidth = Math.max(
19843 document.documentElement.offsetWidth,
19844 document.body.offsetWidth
19847 if (scrollWidth < offsetWidth) {
19848 return $(window).width() + 'px';
19850 return scrollWidth + 'px';
19852 // handle "good" browsers
19854 return $(document).width() + 'px';
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.
19867 var $overlays = $([]);
19868 $.each($.ui.dialog.overlay.instances, function() {
19869 $overlays = $overlays.add(this);
19876 width: $.ui.dialog.overlay.width(),
19877 height: $.ui.dialog.overlay.height()
19882 $.extend($.ui.dialog.overlay.prototype, {
19883 destroy: function() {
19884 $.ui.dialog.overlay.destroy(this.$el);
19890 * jQuery UI Position 1.8.16
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
19896 * http://docs.jquery.com/UI/Position
19898 (function( $, undefined ) {
19902 var horizontalPositions = /left|center|right/,
19903 verticalPositions = /top|center|bottom/,
19905 _position = $.fn.position,
19906 _offset = $.fn.offset;
19908 $.fn.position = function( options ) {
19909 if ( !options || !options.of ) {
19910 return _position.apply( this, arguments );
19913 // make a copy, we don't want to modify arguments
19914 options = $.extend( {}, options );
19916 var target = $( options.of ),
19917 targetElem = target[0],
19918 collision = ( options.collision || "flip" ).split( " " ),
19919 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
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 };
19939 targetWidth = target.outerWidth();
19940 targetHeight = target.outerHeight();
19941 basePosition = target.offset();
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 ];
19955 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
19956 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
19957 options[ this ] = pos;
19960 // normalize collision option
19961 if ( collision.length === 1 ) {
19962 collision[ 1 ] = collision[ 0 ];
19965 // normalize offset option
19966 offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
19967 if ( offset.length === 1 ) {
19968 offset[ 1 ] = offset[ 0 ];
19970 offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
19972 if ( options.at[0] === "right" ) {
19973 basePosition.left += targetWidth;
19974 } else if ( options.at[0] === center ) {
19975 basePosition.left += targetWidth / 2;
19978 if ( options.at[1] === "bottom" ) {
19979 basePosition.top += targetHeight;
19980 } else if ( options.at[1] === center ) {
19981 basePosition.top += targetHeight / 2;
19984 basePosition.left += offset[ 0 ];
19985 basePosition.top += offset[ 1 ];
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 ),
20000 if ( options.my[0] === "right" ) {
20001 position.left -= elemWidth;
20002 } else if ( options.my[0] === center ) {
20003 position.left -= elemWidth / 2;
20006 if ( options.my[1] === "bottom" ) {
20007 position.top -= elemHeight;
20008 } else if ( options.my[1] === center ) {
20009 position.top -= elemHeight / 2;
20012 // prevent fractions (see #5280)
20013 position.left = Math.round( position.left );
20014 position.top = Math.round( position.top );
20016 collisionPosition = {
20017 left: position.left - marginLeft,
20018 top: position.top - marginTop
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,
20038 if ( $.fn.bgiframe ) {
20041 elem.offset( $.extend( position, { using: options.using } ) );
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 );
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 );
20060 left: function( position, data ) {
20061 if ( data.at[0] === center ) {
20064 var win = $( window ),
20065 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
20066 myOffset = data.my[ 0 ] === "left" ?
20068 data.my[ 0 ] === "right" ?
20071 atOffset = data.at[ 0 ] === "left" ?
20074 offset = -2 * data.offset[ 0 ];
20075 position.left += data.collisionPosition.left < 0 ?
20076 myOffset + atOffset + offset :
20078 myOffset + atOffset + offset :
20081 top: function( position, data ) {
20082 if ( data.at[1] === center ) {
20085 var win = $( window ),
20086 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
20087 myOffset = data.my[ 1 ] === "top" ?
20089 data.my[ 1 ] === "bottom" ?
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 :
20099 myOffset + atOffset + offset :
20105 // offset setter from jQuery 1.4
20106 if ( !$.offset.setOffset ) {
20107 $.offset.setOffset = function( elem, options ) {
20108 // set position first, in-case top/left are set even on static elem
20109 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
20110 elem.style.position = "relative";
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,
20117 top: (options.top - curOffset.top) + curTop,
20118 left: (options.left - curOffset.left) + curLeft
20121 if ( 'using' in options ) {
20122 options.using.call( elem, props );
20124 curElem.css( props );
20128 $.fn.offset = function( options ) {
20129 var elem = this[ 0 ];
20130 if ( !elem || !elem.ownerDocument ) { return null; }
20132 return this.each(function() {
20133 $.offset.setOffset( this, options );
20136 return _offset.call( this );
20142 * jQuery UI Progressbar 1.8.16
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
20148 * http://docs.jquery.com/UI/Progressbar
20151 * jquery.ui.core.js
20152 * jquery.ui.widget.js
20154 (function( $, undefined ) {
20156 $.widget( "ui.progressbar", {
20164 _create: function() {
20166 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
20168 role: "progressbar",
20169 "aria-valuemin": this.min,
20170 "aria-valuemax": this.options.max,
20171 "aria-valuenow": this._value()
20174 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
20175 .appendTo( this.element );
20177 this.oldValue = this._value();
20178 this._refreshValue();
20181 destroy: function() {
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" );
20189 this.valueDiv.remove();
20191 $.Widget.prototype.destroy.apply( this, arguments );
20194 value: function( newValue ) {
20195 if ( newValue === undefined ) {
20196 return this._value();
20199 this._setOption( "value", newValue );
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" );
20212 $.Widget.prototype._setOption.apply( this, arguments );
20215 _value: function() {
20216 var val = this.options.value;
20217 // normalize invalid value
20218 if ( typeof val !== "number" ) {
20221 return Math.min( this.options.max, Math.max( this.min, val ) );
20224 _percentage: function() {
20225 return 100 * this._value() / this.options.max;
20228 _refreshValue: function() {
20229 var value = this.value();
20230 var percentage = this._percentage();
20232 if ( this.oldValue !== value ) {
20233 this.oldValue = value;
20234 this._trigger( "change" );
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 );
20245 $.extend( $.ui.progressbar, {
20251 * jQuery UI Slider 1.8.16
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
20257 * http://docs.jquery.com/UI/Slider
20260 * jquery.ui.core.js
20261 * jquery.ui.mouse.js
20262 * jquery.ui.widget.js
20264 (function( $, undefined ) {
20266 // number of pages in a slider
20267 // (how many times can you page up/down to go through the whole range)
20270 $.widget( "ui.slider", $.ui.mouse, {
20272 widgetEventPrefix: "slide",
20279 orientation: "horizontal",
20286 _create: function() {
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,
20294 this._keySliding = false;
20295 this._mouseSliding = false;
20296 this._animateOff = true;
20297 this._handleIndex = null;
20298 this._detectOrientation();
20302 .addClass( "ui-slider" +
20303 " ui-slider-" + this.orientation +
20305 " ui-widget-content" +
20307 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
20309 this.range = $([]);
20312 if ( o.range === true ) {
20314 o.values = [ this._valueMin(), this._valueMin() ];
20316 if ( o.values.length && o.values.length !== 2 ) {
20317 o.values = [ o.values[0], o.values[0] ];
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 : "" ) );
20330 for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
20331 handles.push( handle );
20334 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
20336 this.handle = this.handles.eq( 0 );
20338 this.handles.add( this.range ).filter( "a" )
20339 .click(function( event ) {
20340 event.preventDefault();
20342 .hover(function() {
20343 if ( !o.disabled ) {
20344 $( this ).addClass( "ui-state-hover" );
20347 $( this ).removeClass( "ui-state-hover" );
20349 .focus(function() {
20350 if ( !o.disabled ) {
20351 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
20352 $( this ).addClass( "ui-state-focus" );
20358 $( this ).removeClass( "ui-state-focus" );
20361 this.handles.each(function( i ) {
20362 $( this ).data( "index.ui-slider-handle", i );
20366 .keydown(function( event ) {
20368 index = $( this ).data( "index.ui-slider-handle" ),
20374 if ( self.options.disabled ) {
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:
20388 if ( !self._keySliding ) {
20389 self._keySliding = true;
20390 $( this ).addClass( "ui-state-active" );
20391 allowed = self._start( event, index );
20392 if ( allowed === false ) {
20399 step = self.options.step;
20400 if ( self.options.values && self.options.values.length ) {
20401 curVal = newVal = self.values( index );
20403 curVal = newVal = self.value();
20406 switch ( event.keyCode ) {
20407 case $.ui.keyCode.HOME:
20408 newVal = self._valueMin();
20410 case $.ui.keyCode.END:
20411 newVal = self._valueMax();
20413 case $.ui.keyCode.PAGE_UP:
20414 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
20416 case $.ui.keyCode.PAGE_DOWN:
20417 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
20419 case $.ui.keyCode.UP:
20420 case $.ui.keyCode.RIGHT:
20421 if ( curVal === self._valueMax() ) {
20424 newVal = self._trimAlignValue( curVal + step );
20426 case $.ui.keyCode.DOWN:
20427 case $.ui.keyCode.LEFT:
20428 if ( curVal === self._valueMin() ) {
20431 newVal = self._trimAlignValue( curVal - step );
20435 self._slide( event, index, newVal );
20440 .keyup(function( event ) {
20441 var index = $( this ).data( "index.ui-slider-handle" );
20443 if ( self._keySliding ) {
20444 self._keySliding = false;
20445 self._stop( event, index );
20446 self._change( event, index );
20447 $( this ).removeClass( "ui-state-active" );
20452 this._refreshValue();
20454 this._animateOff = false;
20457 destroy: function() {
20458 this.handles.remove();
20459 this.range.remove();
20462 .removeClass( "ui-slider" +
20463 " ui-slider-horizontal" +
20464 " ui-slider-vertical" +
20465 " ui-slider-disabled" +
20467 " ui-widget-content" +
20469 .removeData( "slider" )
20470 .unbind( ".slider" );
20472 this._mouseDestroy();
20477 _mouseCapture: function( event ) {
20478 var o = this.options,
20489 if ( o.disabled ) {
20493 this.elementSize = {
20494 width: this.element.outerWidth(),
20495 height: this.element.outerHeight()
20497 this.elementOffset = this.element.offset();
20499 position = { x: event.pageX, y: event.pageY };
20500 normValue = this._normValueFromMouse( position );
20501 distance = this._valueMax() - this._valueMin() + 1;
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 );
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 ) {
20517 closestHandle = $( this.handles[index] );
20520 allowed = this._start( event, index );
20521 if ( allowed === false ) {
20524 this._mouseSliding = true;
20526 self._handleIndex = index;
20529 .addClass( "ui-state-active" )
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)
20543 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
20544 this._slide( event, index, normValue );
20546 this._animateOff = true;
20550 _mouseStart: function( event ) {
20554 _mouseDrag: function( event ) {
20555 var position = { x: event.pageX, y: event.pageY },
20556 normValue = this._normValueFromMouse( position );
20558 this._slide( event, this._handleIndex, normValue );
20563 _mouseStop: function( event ) {
20564 this.handles.removeClass( "ui-state-active" );
20565 this._mouseSliding = false;
20567 this._stop( event, this._handleIndex );
20568 this._change( event, this._handleIndex );
20570 this._handleIndex = null;
20571 this._clickOffset = null;
20572 this._animateOff = false;
20577 _detectOrientation: function() {
20578 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
20581 _normValueFromMouse: function( position ) {
20588 if ( this.orientation === "horizontal" ) {
20589 pixelTotal = this.elementSize.width;
20590 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
20592 pixelTotal = this.elementSize.height;
20593 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
20596 percentMouse = ( pixelMouse / pixelTotal );
20597 if ( percentMouse > 1 ) {
20600 if ( percentMouse < 0 ) {
20603 if ( this.orientation === "vertical" ) {
20604 percentMouse = 1 - percentMouse;
20607 valueTotal = this._valueMax() - this._valueMin();
20608 valueMouse = this._valueMin() + percentMouse * valueTotal;
20610 return this._trimAlignValue( valueMouse );
20613 _start: function( event, index ) {
20615 handle: this.handles[ index ],
20616 value: this.value()
20618 if ( this.options.values && this.options.values.length ) {
20619 uiHash.value = this.values( index );
20620 uiHash.values = this.values();
20622 return this._trigger( "start", event, uiHash );
20625 _slide: function( event, index, newVal ) {
20630 if ( this.options.values && this.options.values.length ) {
20631 otherVal = this.values( index ? 0 : 1 );
20633 if ( ( this.options.values.length === 2 && this.options.range === true ) &&
20634 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
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 ],
20648 otherVal = this.values( index ? 0 : 1 );
20649 if ( allowed !== false ) {
20650 this.values( index, newVal, true );
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 ],
20660 if ( allowed !== false ) {
20661 this.value( newVal );
20667 _stop: function( event, index ) {
20669 handle: this.handles[ index ],
20670 value: this.value()
20672 if ( this.options.values && this.options.values.length ) {
20673 uiHash.value = this.values( index );
20674 uiHash.values = this.values();
20677 this._trigger( "stop", event, uiHash );
20680 _change: function( event, index ) {
20681 if ( !this._keySliding && !this._mouseSliding ) {
20683 handle: this.handles[ index ],
20684 value: this.value()
20686 if ( this.options.values && this.options.values.length ) {
20687 uiHash.value = this.values( index );
20688 uiHash.values = this.values();
20691 this._trigger( "change", event, uiHash );
20695 value: function( newValue ) {
20696 if ( arguments.length ) {
20697 this.options.value = this._trimAlignValue( newValue );
20698 this._refreshValue();
20699 this._change( null, 0 );
20703 return this._value();
20706 values: function( index, newValue ) {
20711 if ( arguments.length > 1 ) {
20712 this.options.values[ index ] = this._trimAlignValue( newValue );
20713 this._refreshValue();
20714 this._change( null, index );
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 );
20726 this._refreshValue();
20728 if ( this.options.values && this.options.values.length ) {
20729 return this._values( index );
20731 return this.value();
20735 return this._values();
20739 _setOption: function( key, value ) {
20743 if ( $.isArray( this.options.values ) ) {
20744 valsLength = this.options.values.length;
20747 $.Widget.prototype._setOption.apply( this, arguments );
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" );
20757 this.handles.propAttr( "disabled", false );
20758 this.element.removeClass( "ui-disabled" );
20761 case "orientation":
20762 this._detectOrientation();
20764 .removeClass( "ui-slider-horizontal ui-slider-vertical" )
20765 .addClass( "ui-slider-" + this.orientation );
20766 this._refreshValue();
20769 this._animateOff = true;
20770 this._refreshValue();
20771 this._change( null, 0 );
20772 this._animateOff = false;
20775 this._animateOff = true;
20776 this._refreshValue();
20777 for ( i = 0; i < valsLength; i += 1 ) {
20778 this._change( null, i );
20780 this._animateOff = false;
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 );
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 ) {
20802 if ( arguments.length ) {
20803 val = this.options.values[ index ];
20804 val = this._trimAlignValue( val );
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 ] );
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();
20824 if ( val >= this._valueMax() ) {
20825 return this._valueMax();
20827 var step = ( this.options.step > 0 ) ? this.options.step : 1,
20828 valModStep = (val - this._valueMin()) % step,
20829 alignValue = val - valModStep;
20831 if ( Math.abs(valModStep) * 2 >= step ) {
20832 alignValue += ( valModStep > 0 ) ? step : ( -step );
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) );
20840 _valueMin: function() {
20841 return this.options.min;
20844 _valueMax: function() {
20845 return this.options.max;
20848 _refreshValue: function() {
20849 var oRange = this.options.range,
20852 animate = ( !this._animateOff ) ? o.animate : false,
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" ) {
20868 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
20871 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
20875 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
20878 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
20882 lastValPercent = valPercent;
20885 value = this.value();
20886 valueMin = this._valueMin();
20887 valueMax = this._valueMax();
20888 valPercent = ( valueMax !== valueMin ) ?
20889 ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
20891 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
20892 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
20894 if ( oRange === "min" && this.orientation === "horizontal" ) {
20895 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
20897 if ( oRange === "max" && this.orientation === "horizontal" ) {
20898 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
20900 if ( oRange === "min" && this.orientation === "vertical" ) {
20901 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
20903 if ( oRange === "max" && this.orientation === "vertical" ) {
20904 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
20911 $.extend( $.ui.slider, {
20917 * jQuery UI Tabs 1.8.16
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
20923 * http://docs.jquery.com/UI/Tabs
20926 * jquery.ui.core.js
20927 * jquery.ui.widget.js
20929 (function( $, undefined ) {
20934 function getNextTabId() {
20938 function getNextListId() {
20942 $.widget( "ui.tabs", {
20947 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
20948 collapsible: false,
20953 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
20954 idPrefix: "ui-tabs-",
20956 panelTemplate: "<div></div>",
20960 spinner: "<em>Loading…</em>",
20961 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
20964 _create: function() {
20965 this._tabify( true );
20968 _setOption: function( key, value ) {
20969 if ( key == "selected" ) {
20970 if (this.options.collapsible && value == this.options.selected ) {
20973 this.select( value );
20975 this.options[ key ] = value;
20980 _tabId: function( a ) {
20981 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
20982 this.options.idPrefix + getNextTabId();
20985 _sanitizeSelector: function( hash ) {
20986 // we need this because an id may contain a ":"
20987 return hash.replace( /:/g, "\\:" );
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 ) ) );
20996 _ui: function( tab, panel ) {
21000 index: this.anchors.index( tab )
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)" )
21010 var el = $( this );
21011 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
21015 _tabify: function( init ) {
21018 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
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 ];
21025 this.panels = $( [] );
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 ],
21036 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
21037 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
21043 if ( fragmentId.test( href ) ) {
21044 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
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 );
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( /#.*$/, "" ) );
21055 var id = self._tabId( a );
21057 var $panel = self.element.find( "#" + id );
21058 if ( !$panel.length ) {
21059 $panel = $( o.panelTemplate )
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 );
21065 self.panels = self.panels.add( $panel );
21066 // invalid tab href
21068 o.disabled.push( i );
21072 // initialization from scratch
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" );
21081 // use "selected" option or try to retrieve:
21082 // 1. from fragment identifier in url
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 ) {
21094 if ( typeof o.selected !== "number" && o.cookie ) {
21095 o.selected = parseInt( self._cookie(), 10 );
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" ) );
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
21105 // sanity check - default to first tab...
21106 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
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 );
21119 if ( $.inArray( o.selected, o.disabled ) != -1 ) {
21120 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
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" );
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 ] ) );
21137 this.load( o.selected );
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;
21146 // update selected after add/remove
21148 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
21151 // update collapsible
21152 // TODO: use .toggleClass()
21153 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
21155 // set or update cookie after init and add/remove respectively
21157 this._cookie( o.selected, o.cookie );
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" );
21167 // reset cache if switching from cached to not cached
21168 if ( o.cache === false ) {
21169 this.anchors.removeData( "cache.tabs" );
21172 // remove all handlers before, tabify may run on existing tabs after add or option change
21173 this.lis.add( this.anchors ).unbind( ".tabs" );
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 );
21181 var removeState = function( state, el ) {
21182 el.removeClass( "ui-state-" + state );
21184 this.lis.bind( "mouseover.tabs" , function() {
21185 addState( "hover", $( this ) );
21187 this.lis.bind( "mouseout.tabs", function() {
21188 removeState( "hover", $( this ) );
21190 this.anchors.bind( "focus.tabs", function() {
21191 addState( "focus", $( this ).closest( "li" ) );
21193 this.anchors.bind( "blur.tabs", function() {
21194 removeState( "focus", $( this ).closest( "li" ) );
21198 // set up animations
21199 var hideFx, showFx;
21201 if ( $.isArray( o.fx ) ) {
21202 hideFx = o.fx[ 0 ];
21203 showFx = o.fx[ 1 ];
21205 hideFx = showFx = o.fx;
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" );
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 ] ) );
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 ] ) );
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" );
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" );
21250 // attach tab event handler, unbind to avoid duplicates from former tabifying...
21251 this.anchors.bind( o.event + ".tabs", function() {
21253 $li = $(el).closest( "li" ),
21254 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
21255 $show = self.element.find( self._sanitizeSelector( el.hash ) );
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 ) {
21270 o.selected = self.anchors.index( this );
21274 // if tab may be closed
21275 if ( o.collapsible ) {
21276 if ( $li.hasClass( "ui-tabs-selected" ) ) {
21280 self._cookie( o.selected, o.cookie );
21283 self.element.queue( "tabs", function() {
21284 hideTab( el, $hide );
21285 }).dequeue( "tabs" );
21289 } else if ( !$hide.length ) {
21291 self._cookie( o.selected, o.cookie );
21294 self.element.queue( "tabs", function() {
21295 showTab( el, $show );
21298 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
21299 self.load( self.anchors.index( this ) );
21307 self._cookie( o.selected, o.cookie );
21311 if ( $show.length ) {
21312 if ( $hide.length ) {
21313 self.element.queue( "tabs", function() {
21314 hideTab( el, $hide );
21317 self.element.queue( "tabs", function() {
21318 showTab( el, $show );
21321 self.load( self.anchors.index( this ) );
21323 throw "jQuery UI Tabs: Mismatching fragment identifier.";
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 ) {
21335 // disable click in any case
21336 this.anchors.bind( "click.tabs", function(){
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 + "]" ) );
21351 destroy: function() {
21352 var o = this.options;
21358 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
21359 .removeData( "tabs" );
21361 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
21363 this.anchors.each(function() {
21364 var href = $.data( this, "href.tabs" );
21368 var $this = $( this ).unbind( ".tabs" );
21369 $.each( [ "href", "load", "cache" ], function( i, prefix ) {
21370 $this.removeData( prefix + ".tabs" );
21374 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
21375 if ( $.data( this, "destroy.tabs" ) ) {
21376 $( this ).remove();
21378 $( this ).removeClass([
21379 "ui-state-default",
21381 "ui-tabs-selected",
21385 "ui-state-disabled",
21387 "ui-widget-content",
21388 "ui-corner-bottom",
21395 this._cookie( null, o.cookie );
21401 add: function( url, label, index ) {
21402 if ( index === undefined ) {
21403 index = this.anchors.length;
21408 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
21409 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
21411 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
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 )
21418 .data( "destroy.tabs", true );
21420 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
21422 if ( index >= this.lis.length ) {
21423 $li.appendTo( this.list );
21424 $panel.appendTo( this.list[ 0 ].parentNode );
21426 $li.insertBefore( this.lis[ index ] );
21427 $panel.insertBefore( this.panels[ index ] );
21430 o.disabled = $.map( o.disabled, function( n, i ) {
21431 return n >= index ? ++n : n;
21436 if ( this.anchors.length == 1 ) {
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 ] ) );
21447 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
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();
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 ) );
21463 o.disabled = $.map(
21464 $.grep( o.disabled, function(n, i) {
21468 return n >= index ? --n : n;
21473 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
21477 enable: function( index ) {
21478 index = this._getIndex( index );
21479 var o = this.options;
21480 if ( $.inArray( index, o.disabled ) == -1 ) {
21484 this.lis.eq( index ).removeClass( "ui-state-disabled" );
21485 o.disabled = $.grep( o.disabled, function( n, i ) {
21489 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
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" );
21500 o.disabled.push( index );
21503 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
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;
21518 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
21522 load: function( index ) {
21523 index = this._getIndex( index );
21526 a = this.anchors.eq( index )[ 0 ],
21527 url = $.data( a, "load.tabs" );
21531 // not remote or from cache
21532 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
21533 this.element.dequeue( "tabs" );
21537 // load remote from here on
21538 this.lis.eq( index ).addClass( "ui-state-processing" );
21541 var span = $( "span", a );
21542 span.data( "label.tabs", span.html() ).html( o.spinner );
21545 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
21547 success: function( r, s ) {
21548 self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
21550 // take care of tab labels
21554 $.data( a, "cache.tabs", true );
21557 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
21559 o.ajaxOptions.success( r, s );
21563 error: function( xhr, s, e ) {
21564 // take care of tab labels
21567 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
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 );
21579 // last, so that load event is fired before show...
21580 self.element.dequeue( "tabs" );
21585 abort: function() {
21586 // stop possibly running animations
21587 this.element.queue( [] );
21588 this.panels.stop( false, true );
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 ) );
21594 // terminate pending requests from other tabs
21600 // take care of tab labels
21605 url: function( index, url ) {
21606 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
21610 length: function() {
21611 return this.anchors.length;
21615 $.extend( $.ui.tabs, {
21626 $.extend( $.ui.tabs.prototype, {
21628 rotate: function( ms, continuing ) {
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 );
21640 e.stopPropagation();
21644 var stop = self._unrotate || ( self._unrotate = !continuing
21646 if (e.clientX) { // in case of a true click
21657 this.element.bind( "tabsshow", rotate );
21658 this.anchors.bind( o.event + ".tabs", stop );
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;
21674 </script><script type="text/javascript">/*
21677 * Copyright 2011, Juniper Network Inc, All rights reserved
21678 * See ../Copyright for more information.
21681 jQuery(function ($) {
21683 * dbgpr() is our old-and-trusted debug print function
21685 $.dbgpr = function () {
21686 /* The actual work is pretty trivial */
21687 $('#debug-log').prepend(Array.prototype.slice
21688 .call(arguments).join(" ") + "\n");
21691 </script><script type="text/javascript">/*
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
21702 function popClick(event, objectId) {
21703 var sc = window["stickyClick"];
21704 if (sc && sc[objectId]) {
21705 popDown(event, objectId);
21706 sc[objectId] = false;
21708 popUp(event, objectId);
21710 window["stickyClick"] = sc = [];
21712 sc[objectId] = true;
21717 function popUp(event, objectId) {
21718 var sc = window["stickyClick"];
21719 if (sc && sc[objectId]) {
21723 if (document.getElementById == null)
21725 var ie = document.all ? 1 : 0; /* Is this Internet Explorer? */
21726 var dm = document.getElementById(objectId);
21731 var widthPage = window.innerWidth ? window.innerWidth
21732 : document.body.clientWidth;
21734 var elementWidth = dm.offsetWidth;
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;
21748 if (left + elementWidth > widthPage)
21749 left = widthPage - elementWidth - 25;
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;
21758 ds.width = cw + "px";
21762 ds.top = top + "px";
21763 ds.width = widthPage / 2 + "px";
21764 ds.display = "block";
21766 var tm = document.getElementById("table-" + objectId);
21770 elementWidth = tm.offsetWidth;
21771 if (left + elementWidth > widthPage)
21772 left = widthPage - elementWidth - 25;
21774 ds.left = left + "px";
21777 function popDown(event, objectId) {
21778 var sc = window["stickyClick"];
21779 if (sc && sc[objectId]) {
21783 if (document.getElementById == null)
21785 var dm = document.getElementById(objectId);
21787 dm.style.display = "none";
21790 </script><script type="text/javascript">/*
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
21801 jQuery(function ($) {
21802 var $body = $("body");
21803 var $newp = $("<div id='top'><div id='top-left'/>"
21804 + "<div id='top-right'/></div");
21805 var $left = $("div#top-left", $newp);
21806 var $right = $("div#top-right", $newp);
21808 $right.append($("<div id='nav-bar'><button id='nav-prev'/>"
21809 + "<button id='nav-next'/></div>"));
21811 $body.append($newp);
21812 $left.append($("div#toc"));
21814 $("div.content, div.index, div.note", $body).each(function (i, elt) {
21815 $(elt).appendTo($right);
21818 $("body > ul.toc").remove();
21819 $("#rfc.toc").remove();
21820 $("div.note").remove();
21821 $("h1", $left).remove();
21823 /* $body.append($("<div id='debug-log'/>")); */
21824 $left.append($("<div class='padding'/>"));
21830 var $active = $($right.children("div.content").get(0));
21832 var last = this.URL.lastIndexOf("#");
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();
21841 setActive($active);
21844 function setActive ($elt, toggle) {
21845 if ($elt && $elt.length > 0 && $elt.hasClass("content")) {
21846 /* Mark a new element "active" */
21848 active.removeClass("active");
21850 active.addClass("active");
21852 /* Now we want to find the matching TOC entry and mark it */
21854 tocactive.removeClass("toc-active");
21856 var id = $elt.get(0).children[0].id
21857 $.dbgpr("sa:", 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");
21866 var $tt = tocactive.parents("li.tocline0");
21867 $.dbgpr("tt:", $tt.length);
21869 $("ul.top-toc", $tt).toggleClass("top-toc-open");
21871 $("ul.top-toc", $tt).addClass("top-toc-open");
21875 var szr = $("div#top-right div.active").innerHeight();
21876 var sz = $("p#title").innerHeight();
21877 sz = window.innerHeight - sz;
21883 $("div#toc > ul.toc").innerHeight(sz);
21888 function findParent ($elt, className) {
21890 if ($elt.hasClass(className))
21892 $elt = $elt.parent();
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];
21903 var toggle = $(this).parent().hasClass("tocline0");
21905 var $target = $(document.getElementById(id));
21906 $.dbgpr("id: ", id, " + ", $target, " + ", $target.length);
21908 var $parent = findParent($target, "content");
21909 $.dbgpr("pr: ", $parent);
21910 setActive($parent, toggle);
21913 $("html").animate({ scrollTop: 0 }, 500);
21917 $("a", $right).each(function (idx, elt) {
21918 /* Put the @title as the link value */
21920 var href = $elt.attr("href");
21924 var len = href.indexOf(":");
21926 proto = href.substr(0, len);
21929 if (proto != "http" && proto != "https") {
21930 var t = $elt.attr("title");
21931 if (t !== undefined && href !== undefined)
21933 $elt.click(function (event) {
21934 event.preventDefault();
21935 var id = this.href.split("#");
21936 id = id[id.length - 1];
21938 var $target = $(document.getElementById(id));
21939 setActive($target.parents("div.content"));
21941 $("html").animate({ scrollTop: 0 }, 500);
21946 $("button#nav-prev").button({
21947 label: "<< Previous",
21948 }).click(function (event) {
21949 setActive(active.prev());
21952 $("button#nav-next").button({
21954 }).click(function (event) {
21955 setActive(active.next());
21958 $("p", $right).each(function (idx, elt) {
21960 var val = $elt.get(0);
21961 if (val && val.textContent && val.textContent.startsWith("Section Contents")) {
21962 $elt.addClass("section-contents");
21967 function getMedia () {
21968 var mediaInspector = document.getElementById('media-inspector');
21971 if (mediaInspector === null)
21974 if (mediaInspector.currentStyle) {
21975 zIndex = mediaInspector.currentStyle['zIndex'];
21976 } else if (window.getComputedStyle) {
21977 zIndex = window.getComputedStyle(mediaInspector, '')
21978 .getPropertyValue("z-index");
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 Formatting with libxo" href="#doc_section_2">
21987 <link rel="Chapter" title="3 The libxo API" href="#doc_section_3">
21988 <link rel="Chapter" title='4 The "xo" Utility' href="#doc_section_4">
21989 <link rel="Chapter" title="5 xolint" href="#doc_section_5">
21990 <link rel="Chapter" title="6 xohtml" href="#doc_section_6">
21991 <link rel="Chapter" title="7 xopo" href="#doc_section_7">
21992 <link rel="Chapter" title="8 FAQs" href="#doc_section_8">
21993 <link rel="Chapter" title="9 Howtos: Focused Directions" href="#doc_section_9">
21994 <link rel="Chapter" title="10 Examples" href="#doc_section_10">
21995 <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/">
21996 <link rel="schema.DC" href="http://purl.org/dc/elements/1.1/">
21997 <meta name="DC.Creator" content="Shafer, P.">
21999 <body style="font-size: 80%">
22000 <div id="media-inspector"></div>
22001 <div id="header"><table summary="header information" class="header" border="0" cellpadding="1" cellspacing="1">
22003 <td class="header left">The libxo Project</td>
22004 <td class="header right">P. Shafer</td>
22007 <td class="header left"></td>
22008 <td class="header right">Juniper Networks</td>
22011 <td class="header left"></td>
22012 <td class="header right">May 28, 2016</td>
22015 <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>
22017 <h1 class="np" id="doc.toc"><a href="#doc.toc">Table of Contents</a></h1>
22019 <li class="tocline0">
22020 <div class="section-number" id="toc_doc_section_1">1Â Â Â </div>
22021 <a href="#overview">Overview</a><ul class="toc top-toc"><li class="tocline1">
22022 <div class="section-number" id="toc_doc_section_1_1">1.1Â Â Â </div>
22023 <a href="#getting-libxo">Getting libxo</a><ul class="toc">
22024 <li class="tocline1">
22025 <div class="section-number" id="toc_doc_section_1_1_1">1.1.1Â Â Â </div>
22026 <a href="#downloading-libxo-source-code">Downloading libxo Source Code</a>
22028 <li class="tocline1">
22029 <div class="section-number" id="toc_doc_section_1_1_2">1.1.2Â Â Â </div>
22030 <a href="#building-libxo">Building libxo</a><ul class="toc">
22031 <li class="tocline1">
22032 <div class="section-number" id="toc_doc_section_1_1_2_1">1.1.2.1Â Â Â </div>
22033 <a href="#setting-up-the-build">Setting up the build</a>
22035 <li class="tocline1">
22036 <div class="section-number" id="toc_doc_section_1_1_2_2">1.1.2.2Â Â Â </div>
22037 <a href="#running-the-configure-script">Running the "configure" Script</a>
22039 <li class="tocline1">
22040 <div class="section-number" id="toc_doc_section_1_1_2_3">1.1.2.3Â Â Â </div>
22041 <a href="#running-the-make-command">Running the "make" command</a>
22043 <li class="tocline1">
22044 <div class="section-number" id="toc_doc_section_1_1_2_4">1.1.2.4Â Â Â </div>
22045 <a href="#running-the-regression-tests">Running the Regression Tests</a>
22047 <li class="tocline1">
22048 <div class="section-number" id="toc_doc_section_1_1_2_5">1.1.2.5Â Â Â </div>
22049 <a href="#installing-libxo">Installing libxo</a>
22056 <li class="tocline0">
22057 <div class="section-number" id="toc_doc_section_2">2Â Â Â </div>
22058 <a href="#formatting-with-libxo">Formatting with libxo</a><ul class="toc top-toc">
22059 <li class="tocline1">
22060 <div class="section-number" id="toc_doc_section_2_1">2.1Â Â Â </div>
22061 <a href="#encoding-styles">Encoding Styles</a><ul class="toc">
22062 <li class="tocline1">
22063 <div class="section-number" id="toc_doc_section_2_1_1">2.1.1Â Â Â </div>
22064 <a href="#text-output">Text Output</a>
22066 <li class="tocline1">
22067 <div class="section-number" id="toc_doc_section_2_1_2">2.1.2Â Â Â </div>
22068 <a href="#xml-output">XML Output</a>
22070 <li class="tocline1">
22071 <div class="section-number" id="toc_doc_section_2_1_3">2.1.3Â Â Â </div>
22072 <a href="#json-output">JSON Output</a>
22074 <li class="tocline1">
22075 <div class="section-number" id="toc_doc_section_2_1_4">2.1.4Â Â Â </div>
22076 <a href="#html-output">HTML Output</a>
22080 <li class="tocline1">
22081 <div class="section-number" id="toc_doc_section_2_2">2.2Â Â Â </div>
22082 <a href="#format-strings">Format Strings</a><ul class="toc">
22083 <li class="tocline1">
22084 <div class="section-number" id="toc_doc_section_2_2_1">2.2.1Â Â Â </div>
22085 <a href="#field-roles">Field Roles</a><ul class="toc">
22086 <li class="tocline1">
22087 <div class="section-number" id="toc_doc_section_2_2_1_1">2.2.1.1Â Â Â </div>
22088 <a href="#color-role">The Color Role ({C:})</a>
22090 <li class="tocline1">
22091 <div class="section-number" id="toc_doc_section_2_2_1_2">2.2.1.2Â Â Â </div>
22092 <a href="#the-decoration-role-d">The Decoration Role ({D:})</a>
22094 <li class="tocline1">
22095 <div class="section-number" id="toc_doc_section_2_2_1_3">2.2.1.3Â Â Â </div>
22096 <a href="#gettext-role">The Gettext Role ({G:})</a>
22098 <li class="tocline1">
22099 <div class="section-number" id="toc_doc_section_2_2_1_4">2.2.1.4Â Â Â </div>
22100 <a href="#the-label-role-l">The Label Role ({L:})</a>
22102 <li class="tocline1">
22103 <div class="section-number" id="toc_doc_section_2_2_1_5">2.2.1.5Â Â Â </div>
22104 <a href="#the-note-role-n">The Note Role ({N:})</a>
22106 <li class="tocline1">
22107 <div class="section-number" id="toc_doc_section_2_2_1_6">2.2.1.6Â Â Â </div>
22108 <a href="#padding-role">The Padding Role ({P:})</a>
22110 <li class="tocline1">
22111 <div class="section-number" id="toc_doc_section_2_2_1_7">2.2.1.7Â Â Â </div>
22112 <a href="#the-title-role-t">The Title Role ({T:})</a>
22114 <li class="tocline1">
22115 <div class="section-number" id="toc_doc_section_2_2_1_8">2.2.1.8Â Â Â </div>
22116 <a href="#the-units-role-u">The Units Role ({U:})</a>
22118 <li class="tocline1">
22119 <div class="section-number" id="toc_doc_section_2_2_1_9">2.2.1.9Â Â Â </div>
22120 <a href="#the-value-role-v-and-">The Value Role ({V:} and {:})</a>
22122 <li class="tocline1">
22123 <div class="section-number" id="toc_doc_section_2_2_1_10">2.2.1.10Â Â Â </div>
22124 <a href="#anchor-role">The Anchor Roles ({[:} and {]:})</a>
22128 <li class="tocline1">
22129 <div class="section-number" id="toc_doc_section_2_2_2">2.2.2Â Â Â </div>
22130 <a href="#field-modifiers">Field Modifiers</a><ul class="toc">
22131 <li class="tocline1">
22132 <div class="section-number" id="toc_doc_section_2_2_2_1">2.2.2.1Â Â Â </div>
22133 <a href="#the-argument-modifier-a">The Argument Modifier ({a:})</a>
22135 <li class="tocline1">
22136 <div class="section-number" id="toc_doc_section_2_2_2_2">2.2.2.2Â Â Â </div>
22137 <a href="#the-colon-modifier-c">The Colon Modifier ({c:})</a>
22139 <li class="tocline1">
22140 <div class="section-number" id="toc_doc_section_2_2_2_3">2.2.2.3Â Â Â </div>
22141 <a href="#the-display-modifier-d">The Display Modifier ({d:})</a>
22143 <li class="tocline1">
22144 <div class="section-number" id="toc_doc_section_2_2_2_4">2.2.2.4Â Â Â </div>
22145 <a href="#e-modifier">The Encoding Modifier ({e:})</a>
22147 <li class="tocline1">
22148 <div class="section-number" id="toc_doc_section_2_2_2_5">2.2.2.5Â Â Â </div>
22149 <a href="#gettext-modifier">The Gettext Modifier ({g:})</a>
22151 <li class="tocline1">
22152 <div class="section-number" id="toc_doc_section_2_2_2_6">2.2.2.6Â Â Â </div>
22153 <a href="#the-humanize-modifier-h">The Humanize Modifier ({h:})</a>
22155 <li class="tocline1">
22156 <div class="section-number" id="toc_doc_section_2_2_2_7">2.2.2.7Â Â Â </div>
22157 <a href="#the-key-modifier-k">The Key Modifier ({k:})</a>
22159 <li class="tocline1">
22160 <div class="section-number" id="toc_doc_section_2_2_2_8">2.2.2.8Â Â Â </div>
22161 <a href="#the-leaf-list-modifier-l">The Leaf-List Modifier ({l:})</a>
22163 <li class="tocline1">
22164 <div class="section-number" id="toc_doc_section_2_2_2_9">2.2.2.9Â Â Â </div>
22165 <a href="#the-no-quotes-modifier-n">The No-Quotes Modifier ({n:})</a>
22167 <li class="tocline1">
22168 <div class="section-number" id="toc_doc_section_2_2_2_10">2.2.2.10Â Â Â </div>
22169 <a href="#plural-modifier">The Plural Modifier ({p:})</a>
22171 <li class="tocline1">
22172 <div class="section-number" id="toc_doc_section_2_2_2_11">2.2.2.11Â Â Â </div>
22173 <a href="#the-quotes-modifier-q">The Quotes Modifier ({q:})</a>
22175 <li class="tocline1">
22176 <div class="section-number" id="toc_doc_section_2_2_2_12">2.2.2.12Â Â Â </div>
22177 <a href="#the-trim-modifier-t">The Trim Modifier ({t:})</a>
22179 <li class="tocline1">
22180 <div class="section-number" id="toc_doc_section_2_2_2_13">2.2.2.13Â Â Â </div>
22181 <a href="#the-white-space-modifier-w">The White Space Modifier ({w:})</a>
22185 <li class="tocline1">
22186 <div class="section-number" id="toc_doc_section_2_2_3">2.2.3Â Â Â </div>
22187 <a href="#field-formatting">Field Formatting</a>
22189 <li class="tocline1">
22190 <div class="section-number" id="toc_doc_section_2_2_4">2.2.4Â Â Â </div>
22191 <a href="#utf-8-and-locale-strings">UTF-8 and Locale Strings</a>
22193 <li class="tocline1">
22194 <div class="section-number" id="toc_doc_section_2_2_5">2.2.5Â Â Â </div>
22195 <a href="#characters-outside-of-field-definitions">Characters Outside of Field Definitions</a>
22197 <li class="tocline1">
22198 <div class="section-number" id="toc_doc_section_2_2_6">2.2.6Â Â Â </div>
22199 <a href="#m-is-supported">"%m" Is Supported</a>
22201 <li class="tocline1">
22202 <div class="section-number" id="toc_doc_section_2_2_7">2.2.7Â Â Â </div>
22203 <a href="#n-is-not-supported">"%n" Is Not Supported</a>
22205 <li class="tocline1">
22206 <div class="section-number" id="toc_doc_section_2_2_8">2.2.8Â Â Â </div>
22207 <a href="#the-encoding-format-eformat">The Encoding Format (eformat)</a>
22209 <li class="tocline1">
22210 <div class="section-number" id="toc_doc_section_2_2_9">2.2.9Â Â Â </div>
22211 <a href="#content-strings">Content Strings</a>
22213 <li class="tocline1">
22214 <div class="section-number" id="toc_doc_section_2_2_10">2.2.10Â Â Â </div>
22215 <a href="#printf-like">Argument Validation</a>
22217 <li class="tocline1">
22218 <div class="section-number" id="toc_doc_section_2_2_11">2.2.11Â Â Â </div>
22219 <a href="#retain">Retaining Parsed Format Information</a>
22221 <li class="tocline1">
22222 <div class="section-number" id="toc_doc_section_2_2_12">2.2.12Â Â Â </div>
22223 <a href="#example">Example</a>
22227 <li class="tocline1">
22228 <div class="section-number" id="toc_doc_section_2_3">2.3Â Â Â </div>
22229 <a href="#representing-hierarchy">Representing Hierarchy</a><ul class="toc">
22230 <li class="tocline1">
22231 <div class="section-number" id="toc_doc_section_2_3_1">2.3.1Â Â Â </div>
22232 <a href="#containers">Containers</a>
22234 <li class="tocline1">
22235 <div class="section-number" id="toc_doc_section_2_3_2">2.3.2Â Â Â </div>
22236 <a href="#lists-and-instances">Lists and Instances</a>
22238 <li class="tocline1">
22239 <div class="section-number" id="toc_doc_section_2_3_3">2.3.3Â Â Â </div>
22240 <a href="#dtrt-mode">DTRT Mode</a>
22242 <li class="tocline1">
22243 <div class="section-number" id="toc_doc_section_2_3_4">2.3.4Â Â Â </div>
22244 <a href="#markers">Markers</a>
22248 <li class="tocline1">
22249 <div class="section-number" id="toc_doc_section_2_4">2.4Â Â Â </div>
22250 <a href="#command-line-arguments">Command-line Arguments</a>
22254 <li class="tocline0">
22255 <div class="section-number" id="toc_doc_section_3">3Â Â Â </div>
22256 <a href="#the-libxo-api">The libxo API</a><ul class="toc top-toc">
22257 <li class="tocline1">
22258 <div class="section-number" id="toc_doc_section_3_1">3.1Â Â Â </div>
22259 <a href="#handles">Handles</a><ul class="toc">
22260 <li class="tocline1">
22261 <div class="section-number" id="toc_doc_section_3_1_1">3.1.1Â Â Â </div>
22262 <a href="#xo_create">xo_create</a>
22264 <li class="tocline1">
22265 <div class="section-number" id="toc_doc_section_3_1_2">3.1.2Â Â Â </div>
22266 <a href="#xo_create_to_file">xo_create_to_file</a>
22268 <li class="tocline1">
22269 <div class="section-number" id="toc_doc_section_3_1_3">3.1.3Â Â Â </div>
22270 <a href="#xo_set_writer">xo_set_writer</a>
22272 <li class="tocline1">
22273 <div class="section-number" id="toc_doc_section_3_1_4">3.1.4Â Â Â </div>
22274 <a href="#xo_set_style">xo_set_style</a><ul class="toc">
22275 <li class="tocline1">
22276 <div class="section-number" id="toc_doc_section_3_1_4_1">3.1.4.1Â Â Â </div>
22277 <a href="#styles">Output Styles (XO_STYLE_*)</a>
22279 <li class="tocline1">
22280 <div class="section-number" id="toc_doc_section_3_1_4_2">3.1.4.2Â Â Â </div>
22281 <a href="#xo_set_style_name">xo_set_style_name</a>
22285 <li class="tocline1">
22286 <div class="section-number" id="toc_doc_section_3_1_5">3.1.5Â Â Â </div>
22287 <a href="#xo_set_flags">xo_set_flags</a><ul class="toc">
22288 <li class="tocline1">
22289 <div class="section-number" id="toc_doc_section_3_1_5_1">3.1.5.1Â Â Â </div>
22290 <a href="#flags">Flags (XOF_*)</a>
22292 <li class="tocline1">
22293 <div class="section-number" id="toc_doc_section_3_1_5_2">3.1.5.2Â Â Â </div>
22294 <a href="#xo_clear_flags">xo_clear_flags</a>
22296 <li class="tocline1">
22297 <div class="section-number" id="toc_doc_section_3_1_5_3">3.1.5.3Â Â Â </div>
22298 <a href="#xo_set_options">xo_set_options</a>
22302 <li class="tocline1">
22303 <div class="section-number" id="toc_doc_section_3_1_6">3.1.6Â Â Â </div>
22304 <a href="#xo_destroy">xo_destroy</a>
22308 <li class="tocline1">
22309 <div class="section-number" id="toc_doc_section_3_2">3.2Â Â Â </div>
22310 <a href="#emitting-content-xo_emit">Emitting Content (xo_emit)</a><ul class="toc">
22311 <li class="tocline1">
22312 <div class="section-number" id="toc_doc_section_3_2_1">3.2.1Â Â Â </div>
22313 <a href="#xo_emit_field">Single Field Emitting Functions (xo_emit_field)</a>
22315 <li class="tocline1">
22316 <div class="section-number" id="toc_doc_section_3_2_2">3.2.2Â Â Â </div>
22317 <a href="#xo_attr">Attributes (xo_attr)</a>
22319 <li class="tocline1">
22320 <div class="section-number" id="toc_doc_section_3_2_3">3.2.3Â Â Â </div>
22321 <a href="#flushing-output-xo_flush">Flushing Output (xo_flush)</a>
22323 <li class="tocline1">
22324 <div class="section-number" id="toc_doc_section_3_2_4">3.2.4Â Â Â </div>
22325 <a href="#finishing-output-xo_finish">Finishing Output (xo_finish)</a>
22329 <li class="tocline1">
22330 <div class="section-number" id="toc_doc_section_3_3">3.3Â Â Â </div>
22331 <a href="#emitting-hierarchy">Emitting Hierarchy</a><ul class="toc"><li class="tocline1">
22332 <div class="section-number" id="toc_doc_section_3_3_1">3.3.1Â Â Â </div>
22333 <a href="#lists-and-instances-2">Lists and Instances</a>
22336 <li class="tocline1">
22337 <div class="section-number" id="toc_doc_section_3_4">3.4Â Â Â </div>
22338 <a href="#support-functions">Support Functions</a><ul class="toc">
22339 <li class="tocline1">
22340 <div class="section-number" id="toc_doc_section_3_4_1">3.4.1Â Â Â </div>
22341 <a href="#xo_parse_args">Parsing Command-line Arguments (xo_parse_args)</a>
22343 <li class="tocline1">
22344 <div class="section-number" id="toc_doc_section_3_4_2">3.4.2Â Â Â </div>
22345 <a href="#xo_set_program">xo_set_program</a>
22347 <li class="tocline1">
22348 <div class="section-number" id="toc_doc_section_3_4_3">3.4.3Â Â Â </div>
22349 <a href="#xo_set_version">xo_set_version</a>
22351 <li class="tocline1">
22352 <div class="section-number" id="toc_doc_section_3_4_4">3.4.4Â Â Â </div>
22353 <a href="#info">Field Information (xo_info_t)</a>
22355 <li class="tocline1">
22356 <div class="section-number" id="toc_doc_section_3_4_5">3.4.5Â Â Â </div>
22357 <a href="#memory-allocation">Memory Allocation</a>
22359 <li class="tocline1">
22360 <div class="section-number" id="toc_doc_section_3_4_6">3.4.6Â Â Â </div>
22361 <a href="#LIBXO_OPTIONS">LIBXO_OPTIONS</a>
22363 <li class="tocline1">
22364 <div class="section-number" id="toc_doc_section_3_4_7">3.4.7Â Â Â </div>
22365 <a href="#errors-warnings-and-messages">Errors, Warnings, and Messages</a>
22367 <li class="tocline1">
22368 <div class="section-number" id="toc_doc_section_3_4_8">3.4.8Â Â Â </div>
22369 <a href="#xo_error">xo_error</a>
22371 <li class="tocline1">
22372 <div class="section-number" id="toc_doc_section_3_4_9">3.4.9Â Â Â </div>
22373 <a href="#xo_no_setlocale">xo_no_setlocale</a>
22377 <li class="tocline1">
22378 <div class="section-number" id="toc_doc_section_3_5">3.5Â Â Â </div>
22379 <a href="#emitting-syslog-messages">Emitting syslog Messages</a><ul class="toc">
22380 <li class="tocline1">
22381 <div class="section-number" id="toc_doc_section_3_5_1">3.5.1Â Â Â </div>
22382 <a href="#priority">Priority, Facility, and Flags</a>
22384 <li class="tocline1">
22385 <div class="section-number" id="toc_doc_section_3_5_2">3.5.2Â Â Â </div>
22386 <a href="#xo_syslog">xo_syslog</a>
22388 <li class="tocline1">
22389 <div class="section-number" id="toc_doc_section_3_5_3">3.5.3Â Â Â </div>
22390 <a href="#support-functions-2">Support functions</a><ul class="toc">
22391 <li class="tocline1">
22392 <div class="section-number" id="toc_doc_section_3_5_3_1">3.5.3.1Â Â Â </div>
22393 <a href="#xo_vsyslog">xo_vsyslog</a>
22395 <li class="tocline1">
22396 <div class="section-number" id="toc_doc_section_3_5_3_2">3.5.3.2Â Â Â </div>
22397 <a href="#xo_open_log">xo_open_log</a>
22399 <li class="tocline1">
22400 <div class="section-number" id="toc_doc_section_3_5_3_3">3.5.3.3Â Â Â </div>
22401 <a href="#xo_close_log">xo_close_log</a>
22403 <li class="tocline1">
22404 <div class="section-number" id="toc_doc_section_3_5_3_4">3.5.3.4Â Â Â </div>
22405 <a href="#xo_set_logmask">xo_set_logmask</a>
22407 <li class="tocline1">
22408 <div class="section-number" id="toc_doc_section_3_5_3_5">3.5.3.5Â Â Â </div>
22409 <a href="#xo_set_syslog_enterprise_id">xo_set_syslog_enterprise_id</a>
22415 <li class="tocline1">
22416 <div class="section-number" id="toc_doc_section_3_6">3.6Â Â Â </div>
22417 <a href="#creating-custom-encoders">Creating Custom Encoders</a><ul class="toc">
22418 <li class="tocline1">
22419 <div class="section-number" id="toc_doc_section_3_6_1">3.6.1Â Â Â </div>
22420 <a href="#loading-encoders">Loading Encoders</a>
22422 <li class="tocline1">
22423 <div class="section-number" id="toc_doc_section_3_6_2">3.6.2Â Â Â </div>
22424 <a href="#encoder-initialization">Encoder Initialization</a>
22426 <li class="tocline1">
22427 <div class="section-number" id="toc_doc_section_3_6_3">3.6.3Â Â Â </div>
22428 <a href="#operations">Operations</a>
22434 <li class="tocline0">
22435 <div class="section-number" id="toc_doc_section_4">4Â Â Â </div>
22436 <a href="#the-xo-utility">The "xo" Utility</a><ul class="toc top-toc">
22437 <li class="tocline1">
22438 <div class="section-number" id="toc_doc_section_4_1">4.1Â Â Â </div>
22439 <a href="#command-line-options">Command Line Options</a>
22441 <li class="tocline1">
22442 <div class="section-number" id="toc_doc_section_4_2">4.2Â Â Â </div>
22443 <a href="#example-2">Example</a>
22447 <li class="tocline0">
22448 <div class="section-number" id="toc_doc_section_5">5Â Â Â </div>
22449 <a href="#xolint">xolint</a>
22451 <li class="tocline0">
22452 <div class="section-number" id="toc_doc_section_6">6Â Â Â </div>
22453 <a href="#xohtml">xohtml</a>
22455 <li class="tocline0">
22456 <div class="section-number" id="toc_doc_section_7">7Â Â Â </div>
22457 <a href="#xopo">xopo</a>
22459 <li class="tocline0">
22460 <div class="section-number" id="toc_doc_section_8">8Â Â Â </div>
22461 <a href="#faqs">FAQs</a><ul class="toc top-toc">
22462 <li class="tocline1">
22463 <div class="section-number" id="toc_doc_section_8_1">8.1Â Â Â </div>
22464 <a href="#general">General</a><ul class="toc">
22465 <li class="tocline1">
22466 <div class="section-number" id="toc_doc_section_8_1_1">8.1.1Â Â Â </div>
22467 <a href="#can-you-share-the-history-of-libxo">Can you share the history of libxo?</a>
22469 <li class="tocline1">
22470 <div class="section-number" id="toc_doc_section_8_1_2">8.1.2Â Â Â </div>
22471 <a href="#did-the-complex-semantics-of-format-strings-evolve-over-time">Did the complex semantics of format strings evolve over time?</a>
22473 <li class="tocline1">
22474 <div class="section-number" id="toc_doc_section_8_1_3">8.1.3Â Â Â </div>
22475 <a href="#good-field-names">What makes a good field name?</a>
22479 <li class="tocline1">
22480 <div class="section-number" id="toc_doc_section_8_2">8.2Â Â Â </div>
22481 <a href="#what-does-this-message-mean">What does this message mean?</a><ul class="toc">
22482 <li class="tocline1">
22483 <div class="section-number" id="toc_doc_section_8_2_1">8.2.1Â Â Â </div>
22484 <a href="#a-percent-sign-appearing-in-text-is-a-literal">'A percent sign appearing in text is a literal'</a>
22486 <li class="tocline1">
22487 <div class="section-number" id="toc_doc_section_8_2_2">8.2.2Â Â Â </div>
22488 <a href="#unknown-long-name-for-rolemodifier">'Unknown long name for role/modifier'</a>
22490 <li class="tocline1">
22491 <div class="section-number" id="toc_doc_section_8_2_3">8.2.3Â Â Â </div>
22492 <a href="#last-character-before-field-definition-is-a-field-type">'Last character before field definition is a field type'</a>
22494 <li class="tocline1">
22495 <div class="section-number" id="toc_doc_section_8_2_4">8.2.4Â Â Â </div>
22496 <a href="#encoding-format-uses-different-number-of-arguments">'Encoding format uses different number of arguments'</a>
22498 <li class="tocline1">
22499 <div class="section-number" id="toc_doc_section_8_2_5">8.2.5Â Â Â </div>
22500 <a href="#only-one-field-role-can-be-used">'Only one field role can be used'</a>
22502 <li class="tocline1">
22503 <div class="section-number" id="toc_doc_section_8_2_6">8.2.6Â Â Â </div>
22504 <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>
22506 <li class="tocline1">
22507 <div class="section-number" id="toc_doc_section_8_2_7">8.2.7Â Â Â </div>
22508 <a href="#an-encoding-format-cannot-be-given-roles-dnlt">'An encoding format cannot be given (roles: DNLT)'</a>
22510 <li class="tocline1">
22511 <div class="section-number" id="toc_doc_section_8_2_8">8.2.8Â Â Â </div>
22512 <a href="#format-cannot-be-given-when-content-is-present-roles-cdln">'Format cannot be given when content is present (roles: CDLN)'</a>
22514 <li class="tocline1">
22515 <div class="section-number" id="toc_doc_section_8_2_9">8.2.9Â Â Â </div>
22516 <a href="#field-has-color-without-fg--or-bg--role-c">'Field has color without fg- or bg- (role: C)'</a>
22518 <li class="tocline1">
22519 <div class="section-number" id="toc_doc_section_8_2_10">8.2.10Â Â Â </div>
22520 <a href="#field-has-invalid-color-or-effect-role-c">'Field has invalid color or effect (role: C)'</a>
22522 <li class="tocline1">
22523 <div class="section-number" id="toc_doc_section_8_2_11">8.2.11Â Â Â </div>
22524 <a href="#field-has-humanize-modifier-but-no-format-string">'Field has humanize modifier but no format string'</a>
22526 <li class="tocline1">
22527 <div class="section-number" id="toc_doc_section_8_2_12">8.2.12Â Â Â </div>
22528 <a href="#field-has-hn--modifier-but-not-h-modifier">'Field has hn-* modifier but not 'h' modifier'</a>
22530 <li class="tocline1">
22531 <div class="section-number" id="toc_doc_section_8_2_13">8.2.13Â Â Â </div>
22532 <a href="#value-field-must-have-a-name-as-content">'Value field must have a name (as content)")'</a>
22534 <li class="tocline1">
22535 <div class="section-number" id="toc_doc_section_8_2_14">8.2.14Â Â Â </div>
22536 <a href="#use-hyphens-not-underscores-for-value-field-name">'Use hyphens, not underscores, for value field name'</a>
22538 <li class="tocline1">
22539 <div class="section-number" id="toc_doc_section_8_2_15">8.2.15Â Â Â </div>
22540 <a href="#value-field-name-cannot-start-with-digit">'Value field name cannot start with digit'</a>
22542 <li class="tocline1">
22543 <div class="section-number" id="toc_doc_section_8_2_16">8.2.16Â Â Â </div>
22544 <a href="#value-field-name-should-be-lower-case">'Value field name should be lower case'</a>
22546 <li class="tocline1">
22547 <div class="section-number" id="toc_doc_section_8_2_17">8.2.17Â Â Â </div>
22548 <a href="#value-field-name-should-be-longer-than-two-characters">'Value field name should be longer than two characters'</a>
22550 <li class="tocline1">
22551 <div class="section-number" id="toc_doc_section_8_2_18">8.2.18Â Â Â </div>
22552 <a href="#value-field-name-contains-invalid-character">'Value field name contains invalid character'</a>
22554 <li class="tocline1">
22555 <div class="section-number" id="toc_doc_section_8_2_19">8.2.19Â Â Â </div>
22556 <a href="#decoration-field-contains-invalid-character">'decoration field contains invalid character'</a>
22558 <li class="tocline1">
22559 <div class="section-number" id="toc_doc_section_8_2_20">8.2.20Â Â Â </div>
22560 <a href="#anchor-content-should-be-decimal-width">'Anchor content should be decimal width'</a>
22562 <li class="tocline1">
22563 <div class="section-number" id="toc_doc_section_8_2_21">8.2.21Â Â Â </div>
22564 <a href="#anchor-format-should-be-d">'Anchor format should be "%d"'</a>
22566 <li class="tocline1">
22567 <div class="section-number" id="toc_doc_section_8_2_22">8.2.22Â Â Â </div>
22568 <a href="#anchor-cannot-have-both-format-and-encoding-format">'Anchor cannot have both format and encoding format")'</a>
22570 <li class="tocline1">
22571 <div class="section-number" id="toc_doc_section_8_2_23">8.2.23Â Â Â </div>
22572 <a href="#max-width-only-valid-for-strings">'Max width only valid for strings'</a>
22578 <li class="tocline0">
22579 <div class="section-number" id="toc_doc_section_9">9Â Â Â </div>
22580 <a href="#howtos-focused-directions">Howtos: Focused Directions</a><ul class="toc top-toc">
22581 <li class="tocline1">
22582 <div class="section-number" id="toc_doc_section_9_1">9.1Â Â Â </div>
22583 <a href="#howto-report-bugs">Howto: Report bugs</a>
22585 <li class="tocline1">
22586 <div class="section-number" id="toc_doc_section_9_2">9.2Â Â Â </div>
22587 <a href="#howto-install-libxo">Howto: Install libxo</a>
22589 <li class="tocline1">
22590 <div class="section-number" id="toc_doc_section_9_3">9.3Â Â Â </div>
22591 <a href="#howto-convert-command-line-applications">Howto: Convert command line applications</a><ul class="toc">
22592 <li class="tocline1">
22593 <div class="section-number" id="toc_doc_section_9_3_1">9.3.1Â Â Â </div>
22594 <a href="#setting-up-the-context">Setting up the context</a>
22596 <li class="tocline1">
22597 <div class="section-number" id="toc_doc_section_9_3_2">9.3.2Â Â Â </div>
22598 <a href="#converting-printf-calls">Converting printf Calls</a>
22600 <li class="tocline1">
22601 <div class="section-number" id="toc_doc_section_9_3_3">9.3.3Â Â Â </div>
22602 <a href="#creating-hierarchy">Creating Hierarchy</a>
22604 <li class="tocline1">
22605 <div class="section-number" id="toc_doc_section_9_3_4">9.3.4Â Â Â </div>
22606 <a href="#converting-error-functions">Converting Error Functions</a>
22610 <li class="tocline1">
22611 <div class="section-number" id="toc_doc_section_9_4">9.4Â Â Â </div>
22612 <a href="#howto-use-xo-in-shell-scripts">Howto: Use "xo" in Shell Scripts</a>
22614 <li class="tocline1">
22615 <div class="section-number" id="toc_doc_section_9_5">9.5Â Â Â </div>
22616 <a href="#howto-i18n">Howto: Internationalization (i18n)</a><ul class="toc"><li class="tocline1">
22617 <div class="section-number" id="toc_doc_section_9_5_1">9.5.1Â Â Â </div>
22618 <a href="#i18n-and-xo_emit">i18n and xo_emit</a>
22623 <li class="tocline0">
22624 <div class="section-number" id="toc_doc_section_10">10Â Â Â </div>
22625 <a href="#examples">Examples</a><ul class="toc top-toc"><li class="tocline1">
22626 <div class="section-number" id="toc_doc_section_10_1">10.1Â Â Â </div>
22627 <a href="#unit-test">Unit Test</a>
22630 <li class="tocline0"><a href="#doc.authors">Author's Address</a></li>
22633 <hr class="noprint">
22634 <div class="content">
22635 <h1 id="doc_section_1" class="np">
22636 <div class="self-section-number">
22637 <a href="#doc_section_1">1_</a>Â </div>
22638 <a id="overview" href="#overview">Overview</a>
22640 <p id="doc_section_1_p_1">libxo - A Library for Generating Text, XML, JSON, and HTML Output</p>
22641 <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. And you don't want multiple code paths that can't help but get out of sync. None of this "if (xml) {... } else {...}" logic. And ifdefs are right out. But you'd really, really like all the fancy features that modern encoding formats can provide. libxo can help.</p>
22642 <p id="doc_section_1_p_3">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 2.2</a>):</p>
22643 <div id="doc_figure_u.1"></div> <pre>
22644 xo_emit(" {:lines/%7ju} {:words/%7ju} "
22645 "{:characters/%7ju} {d:filename/%s}\n",
22646 linect, wordct, charct, file);
22647 </pre> <p id="doc_section_1_p_5">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. Output can then be generated in various style, using the "‑‑libxo" option:</p>
22648 <div id="doc_figure_u.2"></div> <pre>
22650 25 165 1140 /etc/motd
22651 % wc --libxo xml,pretty,warn /etc/motd
22654 <lines>25</lines>
22655 <words>165</words>
22656 <characters>1140</characters>
22657 <filename>/etc/motd</filename>
22660 % wc --libxo json,pretty,warn /etc/motd
22667 "characters": 1140,
22668 "filename": "/etc/motd"
22673 % wc --libxo html,pretty,warn /etc/motd
22674 <div class="line">
22675 <div class="text"> </div>
22676 <div class="data" data-tag="lines"> 25</div>
22677 <div class="text"> </div>
22678 <div class="data" data-tag="words"> 165</div>
22679 <div class="text"> </div>
22680 <div class="data" data-tag="characters"> 1140</div>
22681 <div class="text"> </div>
22682 <div class="data" data-tag="filename">/etc/motd</div>
22684 </pre> <p id="doc_section_1_p_7">Section Contents: </p>
22685 <ul><li><a href="#getting-libxo" title="Getting libxo">Section 1.1</a></li></ul>
22686 <div class="content">
22687 <h2 id="doc_section_1_1">
22688 <div class="self-section-number">
22689 <a href="#doc_section_1_1">1.1</a>Â </div>
22690 <a id="getting-libxo" href="#getting-libxo">Getting libxo</a>
22692 <p id="doc_section_1_1_p_1">libxo lives on github as:</p>
22693 <p id="doc_section_1_1_p_2"> <a href="https://github.com/Juniper/libxo">https://github.com/Juniper/libxo</a></p>
22694 <p id="doc_section_1_1_p_3">The latest release of libxo is available at:</p>
22695 <p id="doc_section_1_1_p_4"> <a href="https://github.com/Juniper/libxo/releases">https://github.com/Juniper/libxo/releases</a></p>
22696 <p id="doc_section_1_1_p_5">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>
22697 <div id="doc_figure_u.3"></div> <pre>
22698 git clone https://github.com/Juniper/libxo.git -b develop
22699 </pre> <p id="doc_section_1_1_p_7">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>
22700 <p id="doc_section_1_1_p_8">libxo is open source, distributed under the BSD license. It shipped as part of the FreeBSD operating system starting with release 11.0.</p>
22701 <p id="doc_section_1_1_p_9">Issues, problems, and bugs should be directly to the issues page on our github site.</p>
22702 <p id="doc_section_1_1_p_10">Section Contents: </p>
22704 <li><a href="#downloading-libxo-source-code" title="Downloading libxo Source Code">Section 1.1.1</a></li>
22705 <li><a href="#building-libxo" title="Building libxo">Section 1.1.2</a></li>
22707 <div class="content">
22708 <h3 id="doc_section_1_1_1">
22709 <div class="self-section-number">
22710 <a href="#doc_section_1_1_1">1.1.1</a>Â </div>
22711 <a id="downloading-libxo-source-code" href="#downloading-libxo-source-code">Downloading libxo Source Code</a>
22713 <p id="doc_section_1_1_1_p_1">You can retrieve the source for libxo in two ways:</p>
22714 <p id="doc_section_1_1_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‑RELEASE.tar.gz" button under that section.</p>
22715 <p id="doc_section_1_1_1_p_3">After downloading that release's distfile, untar it as follows:</p>
22716 <div id="doc_figure_u.4"></div> <pre>
22717 tar -zxf libxo-RELEASE.tar.gz
22719 </pre> <p id="doc_section_1_1_1_p_5">[Note: for Solaris users, your "tar" command lacks the "‑z" flag, so you'll need to substitute "gzip -dc "file" | tar xf -" instead of "tar -zxf "file"".]</p>
22720 <p id="doc_section_1_1_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>
22721 <div id="doc_figure_u.5"></div> <pre>
22722 git clone https://github.com/Juniper/libxo.git
22724 </pre> <p id="doc_section_1_1_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>
22725 <p id="doc_section_1_1_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>
22727 <div class="content">
22728 <h3 id="doc_section_1_1_2">
22729 <div class="self-section-number">
22730 <a href="#doc_section_1_1_2">1.1.2</a>Â </div>
22731 <a id="building-libxo" href="#building-libxo">Building libxo</a>
22733 <p id="doc_section_1_1_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>
22734 <p id="doc_section_1_1_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>
22735 <div id="doc_figure_u.6"></div> <pre>
22742 </pre> <p id="doc_section_1_1_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>
22743 <p id="doc_section_1_1_2_p_5">Section Contents: </p>
22745 <li><a href="#setting-up-the-build" title="Setting up the build">Section 1.1.2.1</a></li>
22746 <li><a href="#running-the-configure-script" title='Running the "configure" Script'>Section 1.1.2.2</a></li>
22747 <li><a href="#running-the-make-command" title='Running the "make" command'>Section 1.1.2.3</a></li>
22748 <li><a href="#running-the-regression-tests" title="Running the Regression Tests">Section 1.1.2.4</a></li>
22749 <li><a href="#installing-libxo" title="Installing libxo">Section 1.1.2.5</a></li>
22751 <div class="content">
22752 <h4 id="doc_section_1_1_2_1">
22753 <div class="self-section-number">
22754 <a href="#doc_section_1_1_2_1">1.1.2.1</a>Â </div>
22755 <a id="setting-up-the-build" href="#setting-up-the-build">Setting up the build</a>
22757 <p id="doc_section_1_1_2_1_p_1">[If you downloaded a distfile, you can skip this step.]</p>
22758 <p id="doc_section_1_1_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>
22759 <div id="doc_figure_u.7"></div> <pre>
22761 </pre> <p id="doc_section_1_1_2_1_p_4">Note: We're are currently using autoreconf version 2.69.</p>
22763 <div class="content">
22764 <h4 id="doc_section_1_1_2_2">
22765 <div class="self-section-number">
22766 <a href="#doc_section_1_1_2_2">1.1.2.2</a>Â </div>
22767 <a id="running-the-configure-script" href="#running-the-configure-script">Running the "configure" Script</a>
22769 <p id="doc_section_1_1_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>
22770 <p id="doc_section_1_1_2_2_p_2">We use the "build" directory to keep object files and generated files away from the source tree.</p>
22771 <p id="doc_section_1_1_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>
22772 <div id="doc_figure_u.8"></div> <pre>
22775 </pre> <p id="doc_section_1_1_2_2_p_5">Expect to see the "configure" script generate the following error:</p>
22776 <div id="doc_figure_u.9"></div> <pre>
22777 /usr/bin/rm: cannot remove `libtoolT': No such file or directory
22778 </pre> <p id="doc_section_1_1_2_2_p_7">This error is harmless and can be safely ignored.</p>
22779 <p id="doc_section_1_1_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>
22780 <div id="doc_figure_u.10"></div> <pre>
22782 ../configure [OPTION]... [VAR=VALUE]...
22784 <div class="content">
22785 <h4 id="doc_section_1_1_2_3">
22786 <div class="self-section-number">
22787 <a href="#doc_section_1_1_2_3">1.1.2.3</a>Â </div>
22788 <a id="running-the-make-command" href="#running-the-make-command">Running the "make" command</a>
22790 <p id="doc_section_1_1_2_3_p_1">Once the "configure" script is run, build the images using the "make" command:</p>
22791 <div id="doc_figure_u.11"></div> <pre>
22794 <div class="content">
22795 <h4 id="doc_section_1_1_2_4">
22796 <div class="self-section-number">
22797 <a href="#doc_section_1_1_2_4">1.1.2.4</a>Â </div>
22798 <a id="running-the-regression-tests" href="#running-the-regression-tests">Running the Regression Tests</a>
22800 <p id="doc_section_1_1_2_4_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>
22801 <div id="doc_figure_u.12"></div> <pre>
22804 <div class="content">
22805 <h4 id="doc_section_1_1_2_5">
22806 <div class="self-section-number">
22807 <a href="#doc_section_1_1_2_5">1.1.2.5</a>Â </div>
22808 <a id="installing-libxo" href="#installing-libxo">Installing libxo</a>
22810 <p id="doc_section_1_1_2_5_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>
22811 <div id="doc_figure_u.13"></div> <pre>
22813 </pre> <p id="doc_section_1_1_2_5_p_3">If you are not the "root" user and are using the "sudo" package, use:</p>
22814 <div id="doc_figure_u.14"></div> <pre>
22816 </pre> <p id="doc_section_1_1_2_5_p_5">Verify the installation by viewing the output of "xo --version":</p>
22817 <div id="doc_figure_u.15"></div> <pre>
22819 libxo version 0.3.5-git-develop
22820 xo version 0.3.5-git-develop
22825 <hr class="noprint">
22826 <div class="content">
22827 <h1 id="doc_section_2" class="np">
22828 <div class="self-section-number">
22829 <a href="#doc_section_2">2_</a>Â </div>
22830 <a id="formatting-with-libxo" href="#formatting-with-libxo">Formatting with libxo</a>
22832 <p id="doc_section_2_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>
22833 <p id="doc_section_2_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>
22834 <p id="doc_section_2_p_3">In addition, modern reality means that more output ends up in web browsers than in terminals, making HTML output valuable.</p>
22835 <p id="doc_section_2_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; "<div>" elements surround the traditional text output, with attributes that detail how to render the data.</p>
22836 <p id="doc_section_2_p_5">A single libxo function call in source code is all that's required:</p>
22837 <div id="doc_figure_u.16"></div> <pre>
22838 xo_emit("Connecting to {:host}.{:domain}...\n", host, domain);
22841 Connecting to my-box.example.com...
22843 <host>my-box</host>
22844 <domain>example.com</domain>
22847 "domain": "example.com"
22849 <div class="line">
22850 <div class="text">Connecting to </div>
22851 <div class="data" data-tag="host"
22852 data-xpath="/top/host">my-box</div>
22853 <div class="text">.</div>
22854 <div class="data" data-tag="domain"
22855 data-xpath="/top/domain">example.com</div>
22856 <div class="text">...</div>
22858 </pre> <p id="doc_section_2_p_7">Section Contents: </p>
22860 <li><a href="#encoding-styles" title="Encoding Styles">Section 2.1</a></li>
22861 <li><a href="#format-strings" title="Format Strings">Section 2.2</a></li>
22862 <li><a href="#representing-hierarchy" title="Representing Hierarchy">Section 2.3</a></li>
22863 <li><a href="#command-line-arguments" title="Command-line Arguments">Section 2.4</a></li>
22865 <div class="content">
22866 <h2 id="doc_section_2_1">
22867 <div class="self-section-number">
22868 <a href="#doc_section_2_1">2.1</a>Â </div>
22869 <a id="encoding-styles" href="#encoding-styles">Encoding Styles</a>
22871 <p id="doc_section_2_1_p_1">There are four encoding styles supported by libxo:</p>
22872 <p id="doc_section_2_1_p_2"> </p>
22874 <li>TEXT output can be display on a terminal session, allowing compatibility with traditional command line usage.</li>
22875 <li>XML output is suitable for tools like XPath and protocols like NETCONF.</li>
22876 <li>JSON output can be used for RESTful APIs and integration with languages like Javascript and Python.</li>
22877 <li>HTML can be matched with a small CSS file to permit rendering in any HTML5 browser.</li>
22879 <p id="doc_section_2_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 6</a>).</p>
22880 <p id="doc_section_2_1_p_4">Section Contents: </p>
22882 <li><a href="#text-output" title="Text Output">Section 2.1.1</a></li>
22883 <li><a href="#xml-output" title="XML Output">Section 2.1.2</a></li>
22884 <li><a href="#json-output" title="JSON Output">Section 2.1.3</a></li>
22885 <li><a href="#html-output" title="HTML Output">Section 2.1.4</a></li>
22887 <div class="content">
22888 <h3 id="doc_section_2_1_1">
22889 <div class="self-section-number">
22890 <a href="#doc_section_2_1_1">2.1.1</a>Â </div>
22891 <a id="text-output" href="#text-output">Text Output</a>
22893 <p id="doc_section_2_1_1_p_1">Most traditional programs generate text output on standard output, with contents like:</p>
22894 <div id="doc_figure_u.17"></div> <pre>
22898 </pre> <p id="doc_section_2_1_1_p_3">In this example (taken from du source code), the code to generate this data might look like:</p>
22899 <div id="doc_figure_u.18"></div> <pre>
22900 printf("%d\t%s\n", num_blocks, path);
22901 </pre> <p id="doc_section_2_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>
22902 <p id="doc_section_2_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>
22903 <div id="doc_figure_u.19"></div> <pre>
22904 xo_emit("{:blocks/%d}\t{:path/%s}\n", num_blocks, path);
22905 </pre> <p id="doc_section_2_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>
22906 <p id="doc_section_2_1_1_p_9">The following sections introduce the other formats.</p>
22908 <div class="content">
22909 <h3 id="doc_section_2_1_2">
22910 <div class="self-section-number">
22911 <a href="#doc_section_2_1_2">2.1.2</a>Â </div>
22912 <a id="xml-output" href="#xml-output">XML Output</a>
22914 <p id="doc_section_2_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>
22915 <div id="doc_figure_u.20"></div> <pre>
22917 <blocks>36</blocks>
22918 <path>./src</path>
22921 <blocks>40</blocks>
22922 <path>./bin</path>
22925 <blocks>90</blocks>
22926 <path>.</path>
22928 </pre> <p id="doc_section_2_1_2_p_3">XML is a W3C standard for encoding data. See w3c.org/TR/xml for additional information.</p>
22930 <div class="content">
22931 <h3 id="doc_section_2_1_3">
22932 <div class="self-section-number">
22933 <a href="#doc_section_2_1_3">2.1.3</a>Â </div>
22934 <a id="json-output" href="#json-output">JSON Output</a>
22936 <p id="doc_section_2_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>
22937 <div id="doc_figure_u.21"></div> <pre>
22939 { "blocks": 36, "path" : "./src" },
22940 { "blocks": 40, "path" : "./bin" },
22941 { "blocks": 90, "path" : "./" }
22944 <div class="content">
22945 <h3 id="doc_section_2_1_4">
22946 <div class="self-section-number">
22947 <a href="#doc_section_2_1_4">2.1.4</a>Â </div>
22948 <a id="html-output" href="#html-output">HTML Output</a>
22950 <p id="doc_section_2_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 <div> 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>
22951 <p id="doc_section_2_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>
22952 <div id="doc_figure_u.22"></div> <pre>
22953 <div class="line">
22954 <div class="data" data-tag="blocks">36</div>
22955 <div class="padding"> </div>
22956 <div class="data" data-tag="path">./src</div>
22958 <div class="line">
22959 <div class="data" data-tag="blocks">40</div>
22960 <div class="padding"> </div>
22961 <div class="data" data-tag="path">./bin</div>
22963 <div class="line">
22964 <div class="data" data-tag="blocks">90</div>
22965 <div class="padding"> </div>
22966 <div class="data" data-tag="path">./</div>
22970 <div class="content">
22971 <h2 id="doc_section_2_2">
22972 <div class="self-section-number">
22973 <a href="#doc_section_2_2">2.2</a>Â </div>
22974 <a id="format-strings" href="#format-strings">Format Strings</a>
22976 <p id="doc_section_2_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>
22977 <p id="doc_section_2_2_p_2">The field description is given as follows:</p>
22978 <div id="doc_figure_u.23"></div> <pre>
22979 '{' [ role | modifier ]* [',' long-names ]* ':' [ content ]
22980 [ '/' field-format [ '/' encoding-format ]] '}'
22981 </pre> <p id="doc_section_2_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>
22982 <p id="doc_section_2_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‑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>
22983 <div id="doc_figure_u.24"></div> <pre>
22984 xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\n", 65);
22985 </pre> <p id="doc_section_2_2_p_7">This single line of code can generate text (" In stock: 65\n"), XML ("<in‑stock>65</in‑stock>"), JSON ('"in‑stock": 6'), or HTML (too lengthy to be listed here).</p>
22986 <p id="doc_section_2_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>
22987 <div id="doc_figure_u.25"></div> <pre>
22988 xo_emit("{L,white,colon:In stock}{,key:in-stock/%u}\n", 65);
22989 </pre> <p id="doc_section_2_2_p_10">Section Contents: </p>
22991 <li><a href="#field-roles" title="Field Roles">Section 2.2.1</a></li>
22992 <li><a href="#field-modifiers" title="Field Modifiers">Section 2.2.2</a></li>
22993 <li><a href="#field-formatting" title="Field Formatting">Section 2.2.3</a></li>
22994 <li><a href="#utf-8-and-locale-strings" title="UTF-8 and Locale Strings">Section 2.2.4</a></li>
22995 <li><a href="#characters-outside-of-field-definitions" title="Characters Outside of Field Definitions">Section 2.2.5</a></li>
22996 <li><a href="#m-is-supported" title='"%m" Is Supported'>Section 2.2.6</a></li>
22997 <li><a href="#n-is-not-supported" title='"%n" Is Not Supported'>Section 2.2.7</a></li>
22998 <li><a href="#the-encoding-format-eformat" title="The Encoding Format (eformat)">Section 2.2.8</a></li>
22999 <li><a href="#content-strings" title="Content Strings">Section 2.2.9</a></li>
23000 <li><a href="#printf-like" title="Argument Validation">Section 2.2.10</a></li>
23001 <li><a href="#retain" title="Retaining Parsed Format Information">Section 2.2.11</a></li>
23002 <li><a href="#example" title="Example">Section 2.2.12</a></li>
23004 <div class="content">
23005 <h3 id="doc_section_2_2_1">
23006 <div class="self-section-number">
23007 <a href="#doc_section_2_2_1">2.2.1</a>Â </div>
23008 <a id="field-roles" href="#field-roles">Field Roles</a>
23010 <p id="doc_section_2_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>
23011 <div id="doc_table_u.1"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23013 <th class="left">R</th>
23014 <th class="left">Name</th>
23015 <th class="left">Description</th>
23021 <td>Field has color and effect controls</td>
23025 <td>decoration</td>
23026 <td>Field is non-text (e.g., colon, comma)</td>
23031 <td>Field is an error message</td>
23036 <td>Call gettext(3) on the format string</td>
23041 <td>Field is text that prefixes a value</td>
23046 <td>Field is text that follows a value</td>
23051 <td>Field is spaces needed for vertical alignment</td>
23056 <td>Field is a title value for headings</td>
23061 <td>Field is the units for the previous value field</td>
23066 <td>Field is the name of field (the default)</td>
23071 <td>Field is a warning message</td>
23075 <td>start-anchor</td>
23076 <td>Begin a section of anchored variable-width text</td>
23080 <td>stop-anchor</td>
23081 <td>End a section of anchored variable-width text</td>
23085 <div id="doc_figure_u.26"></div> <pre>
23087 xo_emit("{L:Free}{D::}{P: }{:free/%u} {U:Blocks}\n",
23089 </pre> <p id="doc_section_2_2_1_p_3">When a role is not provided, the "value" role is used as the default.</p>
23090 <p id="doc_section_2_2_1_p_4">Roles and modifiers can also use more verbose names, when preceded by a comma:</p>
23091 <div id="doc_figure_u.27"></div> <pre>
23093 xo_emit("{,label:Free}{,decoration::}{,padding: }"
23094 "{,value:free/%u} {,units:Blocks}\n",
23096 </pre> <p id="doc_section_2_2_1_p_6">Section Contents: </p>
23098 <li><a href="#color-role" title="The Color Role ({C:})">Section 2.2.1.1</a></li>
23099 <li><a href="#the-decoration-role-d" title="The Decoration Role ({D:})">Section 2.2.1.2</a></li>
23100 <li><a href="#gettext-role" title="The Gettext Role ({G:})">Section 2.2.1.3</a></li>
23101 <li><a href="#the-label-role-l" title="The Label Role ({L:})">Section 2.2.1.4</a></li>
23102 <li><a href="#the-note-role-n" title="The Note Role ({N:})">Section 2.2.1.5</a></li>
23103 <li><a href="#padding-role" title="The Padding Role ({P:})">Section 2.2.1.6</a></li>
23104 <li><a href="#the-title-role-t" title="The Title Role ({T:})">Section 2.2.1.7</a></li>
23105 <li><a href="#the-units-role-u" title="The Units Role ({U:})">Section 2.2.1.8</a></li>
23106 <li><a href="#the-value-role-v-and-" title="The Value Role ({V:} and {:})">Section 2.2.1.9</a></li>
23107 <li><a href="#anchor-role" title="The Anchor Roles ({[:} and {]:})">Section 2.2.1.10</a></li>
23109 <div class="content">
23110 <h4 id="doc_section_2_2_1_1">
23111 <div class="self-section-number">
23112 <a href="#doc_section_2_2_1_1">2.2.1.1</a>Â </div>
23113 <a id="color-role" href="#color-role">The Color Role ({C:})</a>
23115 <p id="doc_section_2_2_1_1_p_1">Colors and effects control how text values are displayed; they are used for display styles (TEXT and HTML).</p>
23116 <div id="doc_figure_u.28"></div> <pre>
23117 xo_emit("{C:bold}{:value}{C:no-bold}\n", value);
23118 </pre> <p id="doc_section_2_2_1_1_p_3">Colors and effects remain in effect until modified by other "C"-role fields.</p>
23119 <div id="doc_figure_u.29"></div> <pre>
23120 xo_emit("{C:bold}{C:inverse}both{C:no-bold}only inverse\n");
23121 </pre> <p id="doc_section_2_2_1_1_p_5">If the content is empty, the "reset" action is performed.</p>
23122 <div id="doc_figure_u.30"></div> <pre>
23123 xo_emit("{C:both,underline}{:value}{C:}\n", value);
23124 </pre> <p id="doc_section_2_2_1_1_p_7">The content should be a comma-separated list of zero or more colors or display effects.</p>
23125 <div id="doc_figure_u.31"></div> <pre>
23126 xo_emit("{C:bold,inverse}Ugly{C:no-bold,no-inverse}\n");
23127 </pre> <p id="doc_section_2_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>
23128 <div id="doc_figure_u.32"></div> <pre>
23129 xo_emit("{C:/%s%s}{:value}{C:}", need_bold ? "bold" : "",
23130 need_underline ? "underline" : "", value);
23131 </pre> <p id="doc_section_2_2_1_1_p_11">Color names are prefixed with either "fg‑" or "bg‑" to change the foreground and background colors, respectively.</p>
23132 <div id="doc_figure_u.33"></div> <pre>
23133 xo_emit("{C:/fg-%s,bg-%s}{Lwc:Cost}{:cost/%u}{C:reset}\n",
23134 fg_color, bg_color, cost);
23135 </pre> <p id="doc_section_2_2_1_1_p_13">The following table lists the supported effects:</p>
23136 <div id="doc_table_u.2"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23138 <th class="left">Name</th>
23139 <th class="left">Description</th>
23144 <td>Change background color</td>
23148 <td>Start bold text effect</td>
23152 <td>Change foreground color</td>
23156 <td>Start inverse (aka reverse) text effect</td>
23160 <td>Stop bold text effect</td>
23163 <td>no-inverse</td>
23164 <td>Stop inverse (aka reverse) text effect</td>
23167 <td>no-underline</td>
23168 <td>Stop underline text effect</td>
23172 <td>Reset effects (only)</td>
23176 <td>Reset colors and effects (restore defaults)</td>
23180 <td>Start underline text effect</td>
23184 <p id="doc_section_2_2_1_1_p_14">The following color names are supported:</p>
23185 <div id="doc_table_u.3"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23187 <th class="left">Name</th>
23188 <th class="left">Description</th>
23205 <td>Default color for foreground or background</td>
23230 <div class="content">
23231 <h4 id="doc_section_2_2_1_2">
23232 <div class="self-section-number">
23233 <a href="#doc_section_2_2_1_2">2.2.1.2</a>Â </div>
23234 <a id="the-decoration-role-d" href="#the-decoration-role-d">The Decoration Role ({D:})</a>
23236 <p id="doc_section_2_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>
23237 <div id="doc_figure_u.34"></div> <pre>
23238 xo_emit("{D:((}{:name}{D:))}\n", name);
23240 <div class="content">
23241 <h4 id="doc_section_2_2_1_3">
23242 <div class="self-section-number">
23243 <a href="#doc_section_2_2_1_3">2.2.1.3</a>Â </div>
23244 <a id="gettext-role" href="#gettext-role">The Gettext Role ({G:})</a>
23246 <p id="doc_section_2_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>
23247 <p id="doc_section_2_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>
23248 <p id="doc_section_2_2_1_3_p_3">The simplified version can be generated for a single message using the "xopo -s <text>" command, or an entire .pot can be translated using the "xopo -f <input> -o <output>" command.</p>
23249 <div id="doc_figure_u.35"></div> <pre>
23250 xo_emit("{G:}Invalid token\n");
23251 </pre> <p id="doc_section_2_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>
23252 <div id="doc_figure_u.36"></div> <pre>
23253 xo_emit("{G:libc}Service unavailable in restricted mode\n");
23254 </pre> <p id="doc_section_2_2_1_3_p_7">See <a href="#howto-i18n" title="Howto: Internationalization (i18n)">Section 9.5</a> for additional details.</p>
23256 <div class="content">
23257 <h4 id="doc_section_2_2_1_4">
23258 <div class="self-section-number">
23259 <a href="#doc_section_2_2_1_4">2.2.1.4</a>Â </div>
23260 <a id="the-label-role-l" href="#the-label-role-l">The Label Role ({L:})</a>
23262 <p id="doc_section_2_2_1_4_p_1">Labels are text that appears before a value.</p>
23263 <div id="doc_figure_u.37"></div> <pre>
23264 xo_emit("{Lwc:Cost}{:cost/%u}\n", cost);
23266 <div class="content">
23267 <h4 id="doc_section_2_2_1_5">
23268 <div class="self-section-number">
23269 <a href="#doc_section_2_2_1_5">2.2.1.5</a>Â </div>
23270 <a id="the-note-role-n" href="#the-note-role-n">The Note Role ({N:})</a>
23272 <p id="doc_section_2_2_1_5_p_1">Notes are text that appears after a value.</p>
23273 <div id="doc_figure_u.38"></div> <pre>
23274 xo_emit("{:cost/%u} {N:per year}\n", cost);
23276 <div class="content">
23277 <h4 id="doc_section_2_2_1_6">
23278 <div class="self-section-number">
23279 <a href="#doc_section_2_2_1_6">2.2.1.6</a>Â </div>
23280 <a id="padding-role" href="#padding-role">The Padding Role ({P:})</a>
23282 <p id="doc_section_2_2_1_6_p_1">Padding represents whitespace used before and between fields.</p>
23283 <p id="doc_section_2_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>
23284 <div id="doc_figure_u.39"></div> <pre>
23285 xo_emit("{P: }{Lwc:Cost}{:cost/%u}\n", cost);
23286 xo_emit("{P:/%30s}{Lwc:Cost}{:cost/%u}\n", "", cost);
23288 <div class="content">
23289 <h4 id="doc_section_2_2_1_7">
23290 <div class="self-section-number">
23291 <a href="#doc_section_2_2_1_7">2.2.1.7</a>Â </div>
23292 <a id="the-title-role-t" href="#the-title-role-t">The Title Role ({T:})</a>
23294 <p id="doc_section_2_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>
23295 <div id="doc_figure_u.40"></div> <pre>
23296 xo_emit("{T:Interface Statistics}\n");
23297 xo_emit("{T:/%20.20s}{T:/%6.6s}\n", "Item Name", "Cost");
23298 </pre> <p id="doc_section_2_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>
23299 <div id="doc_figure_u.41"></div> <pre>
23300 xo_emit("{T:Name/%20s}{T:Count/%6s}\n");
23301 </pre> <p id="doc_section_2_2_1_7_p_5">Since the incoming argument is a string, the format must be "%s" or something suitable.</p>
23303 <div class="content">
23304 <h4 id="doc_section_2_2_1_8">
23305 <div class="self-section-number">
23306 <a href="#doc_section_2_2_1_8">2.2.1.8</a>Â </div>
23307 <a id="the-units-role-u" href="#the-units-role-u">The Units Role ({U:})</a>
23309 <p id="doc_section_2_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>
23310 <div id="doc_figure_u.42"></div> <pre>
23311 xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\n", miles);
23312 </pre> <p id="doc_section_2_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>
23313 <p id="doc_section_2_2_1_8_p_4">When the XOF_UNITS flag is set, units are rendered in XML as the "units" attribute:</p>
23314 <div id="doc_figure_u.43"></div> <pre>
23315 <distance units="miles">50</distance>
23316 </pre> <p id="doc_section_2_2_1_8_p_6">Units can also be rendered in HTML as the "data‑units" attribute:</p>
23317 <div id="doc_figure_u.44"></div> <pre>
23318 <div class="data" data-tag="distance" data-units="miles"
23319 data-xpath="/top/data/distance">50</div>
23321 <div class="content">
23322 <h4 id="doc_section_2_2_1_9">
23323 <div class="self-section-number">
23324 <a href="#doc_section_2_2_1_9">2.2.1.9</a>Â </div>
23325 <a id="the-value-role-v-and-" href="#the-value-role-v-and-">The Value Role ({V:} and {:})</a>
23327 <p id="doc_section_2_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>
23328 <div id="doc_figure_u.45"></div> <pre>
23329 xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\n",
23330 length, width, height);
23331 xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\n,
23332 author, poem, year);
23334 <div class="content">
23335 <h4 id="doc_section_2_2_1_10">
23336 <div class="self-section-number">
23337 <a href="#doc_section_2_2_1_10">2.2.1.10</a>Â </div>
23338 <a id="anchor-role" href="#anchor-role">The Anchor Roles ({[:} and {]:})</a>
23340 <p id="doc_section_2_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>
23341 <p id="doc_section_2_2_1_10_p_2">To give a width directly, encode it as the content of the anchor tag:</p>
23342 <div id="doc_figure_u.46"></div> <pre>
23343 xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\n", min, max);
23344 </pre> <p id="doc_section_2_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>
23345 <div id="doc_figure_u.47"></div> <pre>
23346 xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\n", width, min, max);
23347 </pre> <p id="doc_section_2_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>
23348 <p id="doc_section_2_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>
23351 <div class="content">
23352 <h3 id="doc_section_2_2_2">
23353 <div class="self-section-number">
23354 <a href="#doc_section_2_2_2">2.2.2</a>Â </div>
23355 <a id="field-modifiers" href="#field-modifiers">Field Modifiers</a>
23357 <p id="doc_section_2_2_2_p_1">Field modifiers are flags which modify the way content emitted for particular output styles:</p>
23358 <div id="doc_table_u.4"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23360 <th class="left">M</th>
23361 <th class="left">Name</th>
23362 <th class="left">Description</th>
23368 <td>The content appears as a 'const char *' argument</td>
23373 <td>A colon (":") is appended after the label</td>
23378 <td>Only emit field for display styles (text/HTML)</td>
23383 <td>Only emit for encoding styles (XML/JSON)</td>
23388 <td>Call gettext on field's render content</td>
23392 <td>humanize (hn)</td>
23393 <td>Format large numbers in human-readable style</td>
23398 <td>Humanize: Place space between numeric and unit</td>
23402 <td>hn-decimal</td>
23403 <td>Humanize: Add a decimal digit, if number < 10</td>
23408 <td>Humanize: Use 1000 as divisor instead of 1024</td>
23413 <td>Field is a key, suitable for XPath predicates</td>
23418 <td>Field is a leaf-list</td>
23423 <td>Do not quote the field when using JSON style</td>
23428 <td>Gettext: Use comma-separated plural form</td>
23433 <td>Quote the field when using JSON style</td>
23438 <td>Trim leading and trailing whitespace</td>
23443 <td>A blank (" ") is appended after the label</td>
23447 <p id="doc_section_2_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>
23448 <p id="doc_section_2_2_2_p_3">Section Contents: </p>
23450 <li><a href="#the-argument-modifier-a" title="The Argument Modifier ({a:})">Section 2.2.2.1</a></li>
23451 <li><a href="#the-colon-modifier-c" title="The Colon Modifier ({c:})">Section 2.2.2.2</a></li>
23452 <li><a href="#the-display-modifier-d" title="The Display Modifier ({d:})">Section 2.2.2.3</a></li>
23453 <li><a href="#e-modifier" title="The Encoding Modifier ({e:})">Section 2.2.2.4</a></li>
23454 <li><a href="#gettext-modifier" title="The Gettext Modifier ({g:})">Section 2.2.2.5</a></li>
23455 <li><a href="#the-humanize-modifier-h" title="The Humanize Modifier ({h:})">Section 2.2.2.6</a></li>
23456 <li><a href="#the-key-modifier-k" title="The Key Modifier ({k:})">Section 2.2.2.7</a></li>
23457 <li><a href="#the-leaf-list-modifier-l" title="The Leaf-List Modifier ({l:})">Section 2.2.2.8</a></li>
23458 <li><a href="#the-no-quotes-modifier-n" title="The No-Quotes Modifier ({n:})">Section 2.2.2.9</a></li>
23459 <li><a href="#plural-modifier" title="The Plural Modifier ({p:})">Section 2.2.2.10</a></li>
23460 <li><a href="#the-quotes-modifier-q" title="The Quotes Modifier ({q:})">Section 2.2.2.11</a></li>
23461 <li><a href="#the-trim-modifier-t" title="The Trim Modifier ({t:})">Section 2.2.2.12</a></li>
23462 <li><a href="#the-white-space-modifier-w" title="The White Space Modifier ({w:})">Section 2.2.2.13</a></li>
23464 <div class="content">
23465 <h4 id="doc_section_2_2_2_1">
23466 <div class="self-section-number">
23467 <a href="#doc_section_2_2_2_1">2.2.2.1</a>Â </div>
23468 <a id="the-argument-modifier-a" href="#the-argument-modifier-a">The Argument Modifier ({a:})</a>
23470 <p id="doc_section_2_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>
23471 <div id="doc_figure_u.48"></div> <pre>
23473 xo_emit("{La:} {a:}\n", "Label text", "label", "value");
23479 <label>value</label>
23480 </pre> <p id="doc_section_2_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‑%s}".</p>
23482 <div class="content">
23483 <h4 id="doc_section_2_2_2_2">
23484 <div class="self-section-number">
23485 <a href="#doc_section_2_2_2_2">2.2.2.2</a>Â </div>
23486 <a id="the-colon-modifier-c" href="#the-colon-modifier-c">The Colon Modifier ({c:})</a>
23488 <p id="doc_section_2_2_2_2_p_1">The colon modifier appends a single colon to the data value:</p>
23489 <div id="doc_figure_u.49"></div> <pre>
23491 xo_emit("{Lc:Name}{:name}\n", "phil");
23494 </pre> <p id="doc_section_2_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>
23496 <div class="content">
23497 <h4 id="doc_section_2_2_2_3">
23498 <div class="self-section-number">
23499 <a href="#doc_section_2_2_2_3">2.2.2.3</a>Â </div>
23500 <a id="the-display-modifier-d" href="#the-display-modifier-d">The Display Modifier ({d:})</a>
23502 <p id="doc_section_2_2_2_3_p_1">The display modifier indicated the field should only be generated for the display output styles, TEXT and HTML.</p>
23503 <div id="doc_figure_u.50"></div> <pre>
23505 xo_emit("{Lcw:Name}{d:name} {:id/%d}\n", "phil", 1);
23509 <id>1</id>
23510 </pre> <p id="doc_section_2_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>
23512 <div class="content">
23513 <h4 id="doc_section_2_2_2_4">
23514 <div class="self-section-number">
23515 <a href="#doc_section_2_2_2_4">2.2.2.4</a>Â </div>
23516 <a id="e-modifier" href="#e-modifier">The Encoding Modifier ({e:})</a>
23518 <p id="doc_section_2_2_2_4_p_1">The display modifier indicated the field should only be generated for the display output styles, TEXT and HTML.</p>
23519 <div id="doc_figure_u.51"></div> <pre>
23521 xo_emit("{Lcw:Name}{:name} {e:id/%d}\n", "phil", 1);
23525 <name>phil</name><id>1</id>
23526 </pre> <p id="doc_section_2_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>
23528 <div class="content">
23529 <h4 id="doc_section_2_2_2_5">
23530 <div class="self-section-number">
23531 <a href="#doc_section_2_2_2_5">2.2.2.5</a>Â </div>
23532 <a id="gettext-modifier" href="#gettext-modifier">The Gettext Modifier ({g:})</a>
23534 <p id="doc_section_2_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>
23535 <p id="doc_section_2_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>
23536 <div id="doc_figure_u.52"></div> <pre>
23537 xo_emit("{Lgwc:State}{g:state}\n", "full");
23538 </pre> <p id="doc_section_2_2_2_5_p_4">See <a href="#gettext-role" title="The Gettext Role ({G:})">Section 2.2.1.3</a>, <a href="#plural-modifier" title="The Plural Modifier ({p:})">Section 2.2.2.10</a>, and <a href="#howto-i18n" title="Howto: Internationalization (i18n)">Section 9.5</a> for additional details.</p>
23540 <div class="content">
23541 <h4 id="doc_section_2_2_2_6">
23542 <div class="self-section-number">
23543 <a href="#doc_section_2_2_2_6">2.2.2.6</a>Â </div>
23544 <a id="the-humanize-modifier-h" href="#the-humanize-modifier-h">The Humanize Modifier ({h:})</a>
23546 <p id="doc_section_2_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>
23547 <p id="doc_section_2_2_2_6_p_2">"hn" can be used as an alias for "humanize".</p>
23548 <p id="doc_section_2_2_2_6_p_3">The humanize modifier only affects display styles (TEXT and HMTL). The "no‑humanize" option (See <a href="#LIBXO_OPTIONS" title="LIBXO_OPTIONS">Section 3.4.6</a>) will block the function of the humanize modifier.</p>
23549 <p id="doc_section_2_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‑space" modifier places a space between the number and any multiplier symbol, such as "M" or "K" (ex: "44 K"). The "hn‑decimal" modifier will add a decimal point and a single tenths digit when the number is less than 10 (ex: "4.4K"). The "hn‑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>
23550 <div id="doc_figure_u.53"></div> <pre>
23552 xo_emit("{h:input/%u}, {h,hn-space:output/%u}, "
23553 "{h,hn-decimal:errors/%u}, {h,hn-1000:capacity/%u}, "
23554 "{h,hn-decimal:remaining/%u}\n",
23555 input, output, errors, capacity, remaining);
23557 21, 57 K, 96M, 44M, 1.2G
23558 </pre> <p id="doc_section_2_2_2_6_p_6">In the HTML style, the original numeric value is rendered in the "data‑number" attribute on the <div> element:</p>
23559 <div id="doc_figure_u.54"></div> <pre>
23560 <div class="data" data-tag="errors"
23561 data-number="100663296">96M</div>
23563 <div class="content">
23564 <h4 id="doc_section_2_2_2_7">
23565 <div class="self-section-number">
23566 <a href="#doc_section_2_2_2_7">2.2.2.7</a>Â </div>
23567 <a id="the-key-modifier-k" href="#the-key-modifier-k">The Key Modifier ({k:})</a>
23569 <p id="doc_section_2_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>
23570 <div id="doc_figure_u.55"></div> <pre>
23572 xo_open_list("user");
23573 for (i = 0; i < num_users; i++) {
23574 xo_open_instance("user");
23575 xo_emit("User {k:name} has {:count} tickets\n",
23576 user[i].u_name, user[i].u_tickets);
23577 xo_close_instance("user");
23579 xo_close_list("user");
23580 </pre> <p id="doc_section_2_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>
23582 <div class="content">
23583 <h4 id="doc_section_2_2_2_8">
23584 <div class="self-section-number">
23585 <a href="#doc_section_2_2_2_8">2.2.2.8</a>Â </div>
23586 <a id="the-leaf-list-modifier-l" href="#the-leaf-list-modifier-l">The Leaf-List Modifier ({l:})</a>
23588 <p id="doc_section_2_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>
23589 <div id="doc_figure_u.56"></div> <pre>
23591 for (i = 0; i < num_users; i++) {
23592 xo_emit("Member {l:user}\n", user[i].u_name);
23595 <user>phil</user>
23596 <user>pallavi</user>
23598 "user": [ "phil", "pallavi" ]
23599 </pre> <p id="doc_section_2_2_2_8_p_3">The name of the field must match the name of the leaf list.</p>
23601 <div class="content">
23602 <h4 id="doc_section_2_2_2_9">
23603 <div class="self-section-number">
23604 <a href="#doc_section_2_2_2_9">2.2.2.9</a>Â </div>
23605 <a id="the-no-quotes-modifier-n" href="#the-no-quotes-modifier-n">The No-Quotes Modifier ({n:})</a>
23607 <p id="doc_section_2_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>
23608 <div id="doc_figure_u.57"></div> <pre>
23610 const char *bool = is_true ? "true" : "false";
23611 xo_emit("{n:fancy/%s}", bool);
23615 <div class="content">
23616 <h4 id="doc_section_2_2_2_10">
23617 <div class="self-section-number">
23618 <a href="#doc_section_2_2_2_10">2.2.2.10</a>Â </div>
23619 <a id="plural-modifier" href="#plural-modifier">The Plural Modifier ({p:})</a>
23621 <p id="doc_section_2_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>
23622 <div id="doc_figure_u.58"></div> <pre>
23623 xo_emit("{:bytes} {Ngp:byte,bytes}\n", bytes);
23624 </pre> <p id="doc_section_2_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 2.2.2.5</a>.</p>
23625 <p id="doc_section_2_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>
23626 <p id="doc_section_2_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>
23628 <div class="content">
23629 <h4 id="doc_section_2_2_2_11">
23630 <div class="self-section-number">
23631 <a href="#doc_section_2_2_2_11">2.2.2.11</a>Â </div>
23632 <a id="the-quotes-modifier-q" href="#the-quotes-modifier-q">The Quotes Modifier ({q:})</a>
23634 <p id="doc_section_2_2_2_11_p_1">The quotes modifier (and its twin, the 'no‑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>
23635 <div id="doc_figure_u.59"></div> <pre>
23637 xo_emit("{q:time/%d}", 2014);
23640 </pre> <p id="doc_section_2_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>
23641 <div id="doc_figure_u.60"></div> <pre>
23642 d i o u x X D O U e E f F g G a A c C p
23644 <div class="content">
23645 <h4 id="doc_section_2_2_2_12">
23646 <div class="self-section-number">
23647 <a href="#doc_section_2_2_2_12">2.2.2.12</a>Â </div>
23648 <a id="the-trim-modifier-t" href="#the-trim-modifier-t">The Trim Modifier ({t:})</a>
23650 <p id="doc_section_2_2_2_12_p_1">The trim modifier removes any leading or trailing whitespace from the value.</p>
23651 <div id="doc_figure_u.61"></div> <pre>
23653 xo_emit("{t:description}", " some input ");
23655 "description": "some input"
23657 <div class="content">
23658 <h4 id="doc_section_2_2_2_13">
23659 <div class="self-section-number">
23660 <a href="#doc_section_2_2_2_13">2.2.2.13</a>Â </div>
23661 <a id="the-white-space-modifier-w" href="#the-white-space-modifier-w">The White Space Modifier ({w:})</a>
23663 <p id="doc_section_2_2_2_13_p_1">The white space modifier appends a single space to the data value:</p>
23664 <div id="doc_figure_u.62"></div> <pre>
23666 xo_emit("{Lw:Name}{:name}\n", "phil");
23669 </pre> <p id="doc_section_2_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>
23670 <p id="doc_section_2_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>
23673 <div class="content">
23674 <h3 id="doc_section_2_2_3">
23675 <div class="self-section-number">
23676 <a href="#doc_section_2_2_3">2.2.3</a>Â </div>
23677 <a id="field-formatting" href="#field-formatting">Field Formatting</a>
23679 <p id="doc_section_2_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>
23680 <p id="doc_section_2_2_3_p_2">If the format string is not provided for a value field, it defaults to "%s".</p>
23681 <p id="doc_section_2_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>
23682 <p id="doc_section_2_2_3_p_4">The format string has the form:</p>
23683 <div id="doc_figure_u.63"></div> <pre>
23684 '%' format-modifier * format-character
23685 </pre> <p id="doc_section_2_2_3_p_6">The format- modifier can be:</p>
23686 <p id="doc_section_2_2_3_p_7"> </p>
23688 <li>a '#' character, indicating the output value should be prefixed with '0x', typically to indicate a base 16 (hex) value.</li>
23689 <li>a minus sign ('‑'), indicating the output value should be padded on the right instead of the left.</li>
23690 <li>a leading zero ('0') indicating the output value should be padded on the left with zeroes instead of spaces (' ').</li>
23691 <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>
23692 <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>
23693 <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>
23694 <li>one or more 'h' characters, indicating shorter input data.</li>
23695 <li>one or more 'l' characters, indicating longer input data.</li>
23696 <li>a 'z' character, indicating a 'size_t' argument.</li>
23697 <li>a 't' character, indicating a 'ptrdiff_t' argument.</li>
23698 <li>a ' ' character, indicating a space should be emitted before positive numbers.</li>
23699 <li>a '+' character, indicating sign should emitted before any number.</li>
23701 <p id="doc_section_2_2_3_p_8">Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be removed eventually.</p>
23702 <p id="doc_section_2_2_3_p_9">The format character is described in the following table:</p>
23703 <div id="doc_table_u.5"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23705 <th class="left">Ltr</th>
23706 <th class="left">Argument Type</th>
23707 <th class="left">Format</th>
23713 <td>base 10 (decimal)</td>
23718 <td>base 10 (decimal)</td>
23723 <td>base 8 (octal)</td>
23728 <td>base 10 (decimal)</td>
23733 <td>base 16 (hex)</td>
23737 <td>unsigned long</td>
23738 <td>base 16 (hex)</td>
23743 <td>base 10 (decimal)</td>
23747 <td>unsigned long</td>
23748 <td>base 8 (octal)</td>
23752 <td>unsigned long</td>
23753 <td>base 10 (decimal)</td>
23758 <td>[-]d.ddde+-dd</td>
23763 <td>[-]d.dddE+-dd</td>
23768 <td>[-]ddd.ddd</td>
23773 <td>[-]ddd.ddd</td>
23778 <td>as 'e' or 'f'</td>
23783 <td>as 'E' or 'F'</td>
23788 <td>[-]0xh.hhhp[+-]d</td>
23793 <td>[-]0Xh.hhhp[+-]d</td>
23797 <td>unsigned char</td>
23798 <td>a character</td>
23803 <td>a character</td>
23808 <td>a UTF-8 string</td>
23813 <td>a unicode/WCS string</td>
23822 <p id="doc_section_2_2_3_p_10">The 'h' and 'l' modifiers affect the size and treatment of the argument:</p>
23823 <div id="doc_table_u.6"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23825 <th class="left">Mod</th>
23826 <th class="left">d, i</th>
23827 <th class="left">o, u, x, X</th>
23832 <td>signed char</td>
23833 <td>unsigned char</td>
23838 <td>unsigned short</td>
23843 <td>unsigned long</td>
23848 <td>unsigned long long</td>
23873 <div class="content">
23874 <h3 id="doc_section_2_2_4">
23875 <div class="self-section-number">
23876 <a href="#doc_section_2_2_4">2.2.4</a>Â </div>
23877 <a id="utf-8-and-locale-strings" href="#utf-8-and-locale-strings">UTF-8 and Locale Strings</a>
23879 <p id="doc_section_2_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‑8".</p>
23880 <p id="doc_section_2_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>
23881 <div id="doc_figure_u.64"></div> <pre>
23882 xo_emit("Alll strings are utf-8 content {:tag/%ls}",
23883 L"except for wide strings");
23884 </pre> <p id="doc_section_2_2_4_p_4">"%S" is equivalent to "%ls".</p>
23885 <div id="doc_table_u.7"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
23887 <th class="left">Format</th>
23888 <th class="left">Argument Type</th>
23889 <th class="left">Argument Contents</th>
23894 <td>const char *</td>
23895 <td>UTF-8 string</td>
23899 <td>const char *</td>
23900 <td>UTF-8 string (alias for '%s')</td>
23904 <td>const wchar_t *</td>
23905 <td>Wide character UNICODE string</td>
23909 <td>const char *</td>
23910 <td>locale-based string</td>
23914 <p id="doc_section_2_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>
23915 <div id="doc_figure_u.65"></div> <pre>
23916 void print_order (const char *name, int size,
23917 struct tm *timep) {
23919 const char *size_val = "unknown";
23922 snprintf(buf, sizeof(buf), "%d", size);
23927 wcsftime(when, sizeof(when), L"%d%b%y", timep);
23929 xo_emit("The hat for {:name/%hs} is {:size/%s}.\n",
23931 xo_emit("It was ordered on {:order-time/%ls}.\n",
23934 </pre> <p id="doc_section_2_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>
23935 <p id="doc_section_2_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‑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>
23936 <p id="doc_section_2_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>
23937 <div id="doc_figure_u.66"></div> <pre>
23938 xo_emit("{:name/%3.10.6s}", name);
23940 <div class="content">
23941 <h3 id="doc_section_2_2_5">
23942 <div class="self-section-number">
23943 <a href="#doc_section_2_2_5">2.2.5</a>Â </div>
23944 <a id="characters-outside-of-field-definitions" href="#characters-outside-of-field-definitions">Characters Outside of Field Definitions</a>
23946 <p id="doc_section_2_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 <div> with class "text".</p>
23947 <div id="doc_figure_u.67"></div> <pre>
23949 xo_emit("The hat is {:size/%s}.\n", size_val);
23951 The hat is extra small.
23953 <size>extra small</size>
23955 "size": "extra small"
23957 <div class="text">The hat is </div>
23958 <div class="data" data-tag="size">extra small</div>
23959 <div class="text">.</div>
23961 <div class="content">
23962 <h3 id="doc_section_2_2_6">
23963 <div class="self-section-number">
23964 <a href="#doc_section_2_2_6">2.2.6</a>Â </div>
23965 <a id="m-is-supported" href="#m-is-supported">"%m" Is Supported</a>
23967 <p id="doc_section_2_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>
23968 <div id="doc_figure_u.68"></div> <pre>
23969 xo_emit("{:filename} cannot be opened: {:error/%m}", filename);
23970 xo_emit("{:filename} cannot be opened: {:error/%s}",
23971 filename, strerror(errno));
23973 <div class="content">
23974 <h3 id="doc_section_2_2_7">
23975 <div class="self-section-number">
23976 <a href="#doc_section_2_2_7">2.2.7</a>Â </div>
23977 <a id="n-is-not-supported" href="#n-is-not-supported">"%n" Is Not Supported</a>
23979 <p id="doc_section_2_2_7_p_1">libxo does not support the '%n' directive. It's a bad idea and we just don't do it.</p>
23981 <div class="content">
23982 <h3 id="doc_section_2_2_8">
23983 <div class="self-section-number">
23984 <a href="#doc_section_2_2_8">2.2.8</a>Â </div>
23985 <a id="the-encoding-format-eformat" href="#the-encoding-format-eformat">The Encoding Format (eformat)</a>
23987 <p id="doc_section_2_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>
23989 <div class="content">
23990 <h3 id="doc_section_2_2_9">
23991 <div class="self-section-number">
23992 <a href="#doc_section_2_2_9">2.2.9</a>Â </div>
23993 <a id="content-strings" href="#content-strings">Content Strings</a>
23995 <p id="doc_section_2_2_9_p_1">For padding and labels, the content string is considered the content, unless a format is given.</p>
23997 <div class="content">
23998 <h3 id="doc_section_2_2_10">
23999 <div class="self-section-number">
24000 <a href="#doc_section_2_2_10">2.2.10</a>Â </div>
24001 <a id="printf-like" href="#printf-like">Argument Validation</a>
24003 <p id="doc_section_2_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>
24004 <p id="doc_section_2_2_10_p_2">libxo provide variants of functions that provide this ability, if the "‑‑enable‑printflike" option is passed to the "configure" script. These functions use the "_p" suffix, like "xo_emit_p()", xo_emit_hp()", etc.</p>
24005 <p id="doc_section_2_2_10_p_3">The following are features of libxo formatting strings that are incompatible with printf-like testing:</p>
24006 <p id="doc_section_2_2_10_p_4"> </p>
24008 <li>implicit formats, where "{:tag}" has an implicit "%s";</li>
24009 <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>
24010 <li>percent signs in strings, where "{:filled}%" makes a single, trailing percent sign;</li>
24011 <li>the "l" and "h" modifiers for strings, where "{:tag/%hs}" means locale-based string and "{:tag/%ls}" means a wide character string;</li>
24012 <li>distinct encoding formats, where "{:tag/#%s/%s}" means the display styles (text and HTML) will use "#%s" where other styles use "%s";</li>
24014 <p id="doc_section_2_2_10_p_5">If none of these features are in use by your code, then using the "_p" variants might be wise.</p>
24015 <div id="doc_table_u.8"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24017 <th class="left">Function</th>
24018 <th class="left">printf-like Equivalent</th>
24022 <td>xo_emit_hv</td>
24023 <td>xo_emit_hvp</td>
24027 <td>xo_emit_hp</td>
24034 <td>xo_emit_warn_hcv</td>
24035 <td>xo_emit_warn_hcvp</td>
24038 <td>xo_emit_warn_hc</td>
24039 <td>xo_emit_warn_hcp</td>
24042 <td>xo_emit_warn_c</td>
24043 <td>xo_emit_warn_cp</td>
24046 <td>xo_emit_warn</td>
24047 <td>xo_emit_warn_p</td>
24050 <td>xo_emit_warnx_</td>
24051 <td>xo_emit_warnx_p</td>
24054 <td>xo_emit_err</td>
24055 <td>xo_emit_err_p</td>
24058 <td>xo_emit_errx</td>
24059 <td>xo_emit_errx_p</td>
24062 <td>xo_emit_errc</td>
24063 <td>xo_emit_errc_p</td>
24068 <div class="content">
24069 <h3 id="doc_section_2_2_11">
24070 <div class="self-section-number">
24071 <a href="#doc_section_2_2_11">2.2.11</a>Â </div>
24072 <a id="retain" href="#retain">Retaining Parsed Format Information</a>
24074 <p id="doc_section_2_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>
24075 <div id="doc_figure_u.69"></div> <pre>
24077 int xo_emit_f(xo_emit_flags_t flags, const char fmt, ...);
24079 xo_emit_f(XOEF_RETAIN, "{:some/%02d}{:thing/%-6s}{:fancy}\n",
24080 some, thing, fancy);
24081 </pre> <p id="doc_section_2_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>
24082 <div id="doc_table_u.9"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24084 <th class="left">Function</th>
24085 <th class="left">Flags Equivalent</th>
24089 <td>xo_emit_hv</td>
24090 <td>xo_emit_hvf</td>
24094 <td>xo_emit_hf</td>
24101 <td>xo_emit_hvp</td>
24102 <td>xo_emit_hvfp</td>
24105 <td>xo_emit_hp</td>
24106 <td>xo_emit_hfp</td>
24110 <td>xo_emit_fp</td>
24114 <p id="doc_section_2_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>
24115 <p id="doc_section_2_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>
24116 <div id="doc_figure_u.70"></div> <pre>
24117 const char *fmt = "{:name} {:count/%d}\n";
24118 for (i = 0; i < 1000; i++) {
24119 xo_open_instance("item");
24120 xo_emit_f(XOEF_RETAIN, fmt, name[i], count[i]);
24122 xo_retain_clear(fmt);
24123 </pre> <p id="doc_section_2_2_11_p_7">The retained information is kept as thread-specific data.</p>
24125 <div class="content">
24126 <h3 id="doc_section_2_2_12">
24127 <div class="self-section-number">
24128 <a href="#doc_section_2_2_12">2.2.12</a>Â </div>
24129 <a id="example" href="#example">Example</a>
24131 <p id="doc_section_2_2_12_p_1">In this example, the value for the number of items in stock is emitted:</p>
24132 <div id="doc_figure_u.71"></div> <pre>
24133 xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\n",
24135 </pre> <p id="doc_section_2_2_12_p_3">This call will generate the following output:</p>
24136 <div id="doc_figure_u.72"></div> <pre>
24140 <in-stock>144</in-stock>
24144 <div class="line">
24145 <div class="padding"> </div>
24146 <div class="label">In stock</div>
24147 <div class="decoration">:</div>
24148 <div class="padding"> </div>
24149 <div class="data" data-tag="in-stock">144</div>
24151 </pre> <p id="doc_section_2_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>
24152 <div id="doc_figure_u.73"></div> <pre>
24153 <div class="data" data-tag="in-stock"
24154 data-xpath="/top/data/item/in-stock"
24156 data-help="Number of items in stock">144</div>
24159 <div class="content">
24160 <h2 id="doc_section_2_3">
24161 <div class="self-section-number">
24162 <a href="#doc_section_2_3">2.3</a>Â </div>
24163 <a id="representing-hierarchy" href="#representing-hierarchy">Representing Hierarchy</a>
24165 <p id="doc_section_2_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>
24166 <p id="doc_section_2_3_p_2">XML encodes lists as set of sequential elements:</p>
24167 <div id="doc_figure_u.74"></div> <pre>
24168 <user>phil</user>
24169 <user>pallavi</user>
24170 <user>sjg</user>
24171 </pre> <p id="doc_section_2_3_p_4">JSON encodes lists using a single name and square brackets:</p>
24172 <div id="doc_figure_u.75"></div> <pre>
24173 "user": [ "phil", "pallavi", "sjg" ]
24174 </pre> <p id="doc_section_2_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>
24175 <p id="doc_section_2_3_p_7">Section Contents: </p>
24177 <li><a href="#containers" title="Containers">Section 2.3.1</a></li>
24178 <li><a href="#lists-and-instances" title="Lists and Instances">Section 2.3.2</a></li>
24179 <li><a href="#dtrt-mode" title="DTRT Mode">Section 2.3.3</a></li>
24180 <li><a href="#markers" title="Markers">Section 2.3.4</a></li>
24182 <div class="content">
24183 <h3 id="doc_section_2_3_1">
24184 <div class="self-section-number">
24185 <a href="#doc_section_2_3_1">2.3.1</a>Â </div>
24186 <a id="containers" href="#containers">Containers</a>
24188 <p id="doc_section_2_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>
24189 <p id="doc_section_2_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>
24190 <div id="doc_figure_u.76"></div> <pre>
24191 int xo_open_container_h (xo_handle_t *xop, const char *name);
24192 int xo_open_container (const char *name);
24193 </pre> <p id="doc_section_2_3_1_p_4">To close a level, use the xo_close_container() or xo_close_container_h() functions:</p>
24194 <div id="doc_figure_u.77"></div> <pre>
24195 int xo_close_container_h (xo_handle_t *xop, const char *name);
24196 int xo_close_container (const char *name);
24197 </pre> <p id="doc_section_2_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>
24198 <div id="doc_figure_u.78"></div> <pre>
24201 xo_open_container("top");
24202 xo_open_container("system");
24203 xo_emit("{:host-name/%s%s%s", hostname,
24204 domainname ? "." : "", domainname ?: "");
24205 xo_close_container("system");
24206 xo_close_container("top");
24210 my-host.example.org
24214 <host-name>my-host.example.org</host-name>
24220 "host-name": "my-host.example.org"
24224 <div class="data"
24225 data-tag="host-name">my-host.example.org</div>
24227 <div class="content">
24228 <h3 id="doc_section_2_3_2">
24229 <div class="self-section-number">
24230 <a href="#doc_section_2_3_2">2.3.2</a>Â </div>
24231 <a id="lists-and-instances" href="#lists-and-instances">Lists and Instances</a>
24233 <p id="doc_section_2_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>
24234 <div id="doc_figure_u.79"></div> <pre>
24235 xo_open_list("item");
24237 for (ip = list; ip->i_title; ip++) {
24238 xo_open_instance("item");
24239 xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
24240 xo_close_instance("item");
24243 xo_close_list("item");
24244 </pre> <p id="doc_section_2_3_2_p_3">Getting the list and instance calls correct is critical to the proper generation of XML and JSON data.</p>
24246 <div class="content">
24247 <h3 id="doc_section_2_3_3">
24248 <div class="self-section-number">
24249 <a href="#doc_section_2_3_3">2.3.3</a>Â </div>
24250 <a id="dtrt-mode" href="#dtrt-mode">DTRT Mode</a>
24252 <p id="doc_section_2_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>
24253 <div id="doc_figure_u.80"></div> <pre>
24254 xo_set_flags(NULL, XOF_DTRT);
24255 </pre> <p id="doc_section_2_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>
24256 <div id="doc_figure_u.81"></div> <pre>
24257 xo_open_container("top");
24259 xo_close_container_d();
24260 </pre> <p id="doc_section_2_3_3_p_5">This also works for lists and instances:</p>
24261 <div id="doc_figure_u.82"></div> <pre>
24262 xo_open_list("item");
24264 xo_open_instance("item");
24266 xo_close_instance_d();
24269 </pre> <p id="doc_section_2_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>
24271 <div class="content">
24272 <h3 id="doc_section_2_3_4">
24273 <div class="self-section-number">
24274 <a href="#doc_section_2_3_4">2.3.4</a>Â </div>
24275 <a id="markers" href="#markers">Markers</a>
24277 <p id="doc_section_2_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>
24278 <p id="doc_section_2_3_4_p_2">Markers use names which are not user-visible, allowing the caller to choose appropriate internal names.</p>
24279 <p id="doc_section_2_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‑guts" is used to ensure that any constructs opened by the function are closed properly.</p>
24280 <div id="doc_figure_u.83"></div> <pre>
24281 for (i = 0; fish[i]; i++) {
24282 xo_open_instance("fish");
24283 xo_open_marker("fish-guts");
24284 dump_fish_details(i);
24285 xo_close_marker("fish-guts");
24289 <div class="content">
24290 <h2 id="doc_section_2_4">
24291 <div class="self-section-number">
24292 <a href="#doc_section_2_4">2.4</a>Â </div>
24293 <a id="command-line-arguments" href="#command-line-arguments">Command-line Arguments</a>
24295 <p id="doc_section_2_4_p_1">libxo uses command line options to trigger rendering behavior. The following options are recognised:</p>
24296 <p id="doc_section_2_4_p_2"> </p>
24298 <li>--libxo <options></li>
24299 <li>--libxo=<options></li>
24300 <li>--libxo:<brief‑options></li>
24302 <p id="doc_section_2_4_p_3">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 3.4.1</a> for details.</p>
24303 <p id="doc_section_2_4_p_4">Options is a comma-separated list of tokens that correspond to output styles, flags, or features:</p>
24304 <div id="doc_table_u.10"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24306 <th class="left">Token</th>
24307 <th class="left">Action</th>
24312 <td>Enable colors/effects for display styles (TEXT, HTML)</td>
24316 <td>Enable "Do The Right Thing" mode</td>
24320 <td>Emit HTML output</td>
24324 <td>Set the indentation level</td>
24328 <td>Add info attributes (HTML)</td>
24332 <td>Emit JSON output</td>
24336 <td>Emit the key attribute for keys (XML)</td>
24339 <td>log-gettext</td>
24340 <td>Log (via stderr) each gettext(3) string lookup</td>
24343 <td>log-syslog</td>
24344 <td>Log (via stderr) each syslog message (via xo_syslog)</td>
24347 <td>no-humanize</td>
24348 <td>Ignore the {h:} modifier (TEXT, HTML)</td>
24352 <td>Do not initialize the locale setting</td>
24356 <td>Prevent retaining formatting information</td>
24360 <td>Do not emit a top set of braces (JSON)</td>
24364 <td>Pretend the 1st output item was not 1st (JSON)</td>
24368 <td>Emit pretty-printed output</td>
24372 <td>Force retaining formatting information</td>
24376 <td>Emit TEXT output</td>
24379 <td>underscores</td>
24380 <td>Replace XML-friendly "-"s with JSON friendly "_"s e</td>
24384 <td>Add the 'units' (XML) or 'data-units (HTML) attribute</td>
24388 <td>Emit warnings when libxo detects bad calls</td>
24392 <td>Emit warnings in XML</td>
24396 <td>Emit XML output</td>
24400 <td>Add XPath expressions (HTML)</td>
24404 <p id="doc_section_2_4_p_5">The brief options are detailed in <a href="#LIBXO_OPTIONS" title="LIBXO_OPTIONS">Section 3.4.6</a>.</p>
24407 <hr class="noprint">
24408 <div class="content">
24409 <h1 id="doc_section_3" class="np">
24410 <div class="self-section-number">
24411 <a href="#doc_section_3">3_</a>Â </div>
24412 <a id="the-libxo-api" href="#the-libxo-api">The libxo API</a>
24414 <p id="doc_section_3_p_1">This section gives details about the functions in libxo, how to call them, and the actions they perform.</p>
24415 <p id="doc_section_3_p_2">Section Contents: </p>
24417 <li><a href="#handles" title="Handles">Section 3.1</a></li>
24418 <li><a href="#emitting-content-xo_emit" title="Emitting Content (xo_emit)">Section 3.2</a></li>
24419 <li><a href="#emitting-hierarchy" title="Emitting Hierarchy">Section 3.3</a></li>
24420 <li><a href="#support-functions" title="Support Functions">Section 3.4</a></li>
24421 <li><a href="#emitting-syslog-messages" title="Emitting syslog Messages">Section 3.5</a></li>
24422 <li><a href="#creating-custom-encoders" title="Creating Custom Encoders">Section 3.6</a></li>
24424 <div class="content">
24425 <h2 id="doc_section_3_1">
24426 <div class="self-section-number">
24427 <a href="#doc_section_3_1">3.1</a>Â </div>
24428 <a id="handles" href="#handles">Handles</a>
24430 <p id="doc_section_3_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>
24431 <p id="doc_section_3_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>
24432 <p id="doc_section_3_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>
24433 <p id="doc_section_3_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>
24434 <p id="doc_section_3_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>
24435 <p id="doc_section_3_1_p_6">For example, the following are equivalent:</p>
24436 <div id="doc_figure_u.84"></div> <pre>
24438 xo_emit_h(NULL, "test");
24439 </pre> <p id="doc_section_3_1_p_8">Handles are created using xo_create() and destroy using xo_destroy().</p>
24440 <p id="doc_section_3_1_p_9">Section Contents: </p>
24442 <li><a href="#xo_create" title="xo_create">Section 3.1.1</a></li>
24443 <li><a href="#xo_create_to_file" title="xo_create_to_file">Section 3.1.2</a></li>
24444 <li><a href="#xo_set_writer" title="xo_set_writer">Section 3.1.3</a></li>
24445 <li><a href="#xo_set_style" title="xo_set_style">Section 3.1.4</a></li>
24446 <li><a href="#xo_set_flags" title="xo_set_flags">Section 3.1.5</a></li>
24447 <li><a href="#xo_destroy" title="xo_destroy">Section 3.1.6</a></li>
24449 <div class="content">
24450 <h3 id="doc_section_3_1_1">
24451 <div class="self-section-number">
24452 <a href="#doc_section_3_1_1">3.1.1</a>Â </div>
24453 <a id="xo_create" href="#xo_create">xo_create</a>
24455 <p id="doc_section_3_1_1_p_1">A handle can be allocated using the xo_create() function:</p>
24456 <div id="doc_figure_u.85"></div> <pre>
24457 xo_handle_t *xo_create (unsigned style, unsigned flags);
24460 xo_handle_t *xop = xo_create(XO_STYLE_JSON, XOF_WARN);
24462 xo_emit_h(xop, "testing\n");
24463 </pre> <p id="doc_section_3_1_1_p_3">See also <a href="#styles" title="Output Styles (XO_STYLE_*)">Section 3.1.4.1</a> and <a href="#flags" title="Flags (XOF_*)">Section 3.1.5.1</a>.</p>
24465 <div class="content">
24466 <h3 id="doc_section_3_1_2">
24467 <div class="self-section-number">
24468 <a href="#doc_section_3_1_2">3.1.2</a>Â </div>
24469 <a id="xo_create_to_file" href="#xo_create_to_file">xo_create_to_file</a>
24471 <p id="doc_section_3_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>
24472 <div id="doc_figure_u.86"></div> <pre>
24473 xo_handle_t *xo_create_to_file (FILE *fp, unsigned style,
24475 </pre> <p id="doc_section_3_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>
24477 <div class="content">
24478 <h3 id="doc_section_3_1_3">
24479 <div class="self-section-number">
24480 <a href="#doc_section_3_1_3">3.1.3</a>Â </div>
24481 <a id="xo_set_writer" href="#xo_set_writer">xo_set_writer</a>
24483 <p id="doc_section_3_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>
24484 <div id="doc_figure_u.87"></div> <pre>
24485 void xo_set_writer (xo_handle_t *xop, void *opaque,
24486 xo_write_func_t write_func,
24487 xo_close_func_t close_func);
24488 xo_flush_func_t flush_func);
24490 <div class="content">
24491 <h3 id="doc_section_3_1_4">
24492 <div class="self-section-number">
24493 <a href="#doc_section_3_1_4">3.1.4</a>Â </div>
24494 <a id="xo_set_style" href="#xo_set_style">xo_set_style</a>
24496 <p id="doc_section_3_1_4_p_1">To set the style, use the xo_set_style() function:</p>
24497 <div id="doc_figure_u.88"></div> <pre>
24498 void xo_set_style(xo_handle_t *xop, unsigned style);
24499 </pre> <p id="doc_section_3_1_4_p_3">To use the default handle, pass a NULL handle:</p>
24500 <div id="doc_figure_u.89"></div> <pre>
24501 xo_set_style(NULL, XO_STYLE_XML);
24502 </pre> <p id="doc_section_3_1_4_p_5">Section Contents: </p>
24504 <li><a href="#styles" title="Output Styles (XO_STYLE_*)">Section 3.1.4.1</a></li>
24505 <li><a href="#xo_set_style_name" title="xo_set_style_name">Section 3.1.4.2</a></li>
24507 <div class="content">
24508 <h4 id="doc_section_3_1_4_1">
24509 <div class="self-section-number">
24510 <a href="#doc_section_3_1_4_1">3.1.4.1</a>Â </div>
24511 <a id="styles" href="#styles">Output Styles (XO_STYLE_*)</a>
24513 <p id="doc_section_3_1_4_1_p_1">The libxo functions accept a set of output styles:</p>
24514 <div id="doc_table_u.11"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24516 <th class="left">Flag</th>
24517 <th class="left">Description</th>
24521 <td>XO_STYLE_TEXT</td>
24522 <td>Traditional text output</td>
24525 <td>XO_STYLE_XML</td>
24526 <td>XML encoded data</td>
24529 <td>XO_STYLE_JSON</td>
24530 <td>JSON encoded data</td>
24533 <td>XO_STYLE_HTML</td>
24534 <td>HTML encoded data</td>
24539 <div class="content">
24540 <h4 id="doc_section_3_1_4_2">
24541 <div class="self-section-number">
24542 <a href="#doc_section_3_1_4_2">3.1.4.2</a>Â </div>
24543 <a id="xo_set_style_name" href="#xo_set_style_name">xo_set_style_name</a>
24545 <p id="doc_section_3_1_4_2_p_1">The xo_set_style_name() can be used to set the style based on a name encoded as a string:</p>
24546 <div id="doc_figure_u.90"></div> <pre>
24547 int xo_set_style_name (xo_handle_t *xop, const char *style);
24548 </pre> <p id="doc_section_3_1_4_2_p_3">The name can be any of the styles: "text", "xml", "json", or "html".</p>
24549 <div id="doc_figure_u.91"></div> <pre>
24551 xo_set_style_name(NULL, "html");
24554 <div class="content">
24555 <h3 id="doc_section_3_1_5">
24556 <div class="self-section-number">
24557 <a href="#doc_section_3_1_5">3.1.5</a>Â </div>
24558 <a id="xo_set_flags" href="#xo_set_flags">xo_set_flags</a>
24560 <p id="doc_section_3_1_5_p_1">To set the flags, use the xo_set_flags() function:</p>
24561 <div id="doc_figure_u.92"></div> <pre>
24562 void xo_set_flags(xo_handle_t *xop, unsigned flags);
24563 </pre> <p id="doc_section_3_1_5_p_3">To use the default handle, pass a NULL handle:</p>
24564 <div id="doc_figure_u.93"></div> <pre>
24565 xo_set_style(NULL, XO_STYLE_XML);
24566 </pre> <p id="doc_section_3_1_5_p_5">Section Contents: </p>
24568 <li><a href="#flags" title="Flags (XOF_*)">Section 3.1.5.1</a></li>
24569 <li><a href="#xo_clear_flags" title="xo_clear_flags">Section 3.1.5.2</a></li>
24570 <li><a href="#xo_set_options" title="xo_set_options">Section 3.1.5.3</a></li>
24572 <div class="content">
24573 <h4 id="doc_section_3_1_5_1">
24574 <div class="self-section-number">
24575 <a href="#doc_section_3_1_5_1">3.1.5.1</a>Â </div>
24576 <a id="flags" href="#flags">Flags (XOF_*)</a>
24578 <p id="doc_section_3_1_5_1_p_1">The set of valid flags include:</p>
24579 <div id="doc_table_u.12"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24581 <th class="left">Flag</th>
24582 <th class="left">Description</th>
24586 <td>XOF_CLOSE_FP</td>
24587 <td>Close file pointer on xo_destroy()</td>
24591 <td>Enable color and effects in output</td>
24594 <td>XOF_COLOR_ALLOWED</td>
24595 <td>Allow color/effect for terminal output</td>
24599 <td>Enable "do the right thing" mode</td>
24603 <td>Display info data attributes (HTML)</td>
24607 <td>Emit the key attribute (XML)</td>
24610 <td>XOF_NO_ENV</td>
24611 <td>Do not use the LIBXO_OPTIONS env var</td>
24614 <td>XOF_NO_HUMANIZE</td>
24615 <td>Display humanization (TEXT, HTML)</td>
24618 <td>XOF_PRETTY</td>
24619 <td>Make 'pretty printed' output</td>
24622 <td>XOF_UNDERSCORES</td>
24623 <td>Replaces hyphens with underscores</td>
24627 <td>Display units (XML, HMTL)</td>
24631 <td>Generate warnings for broken calls</td>
24634 <td>XOF_WARN_XML</td>
24635 <td>Generate warnings in XML on stdout</td>
24639 <td>Emit XPath expressions (HTML)</td>
24642 <td>XOF_COLUMNS</td>
24643 <td>Force xo_emit to return columns used</td>
24647 <td>Flush output after each xo_emit call</td>
24651 <p id="doc_section_3_1_5_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>
24652 <p id="doc_section_3_1_5_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>
24653 <p id="doc_section_3_1_5_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>
24654 <p id="doc_section_3_1_5_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>
24655 <p id="doc_section_3_1_5_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>
24656 <p id="doc_section_3_1_5_1_p_7">If the style is XO_STYLE_HTML, the following additional flags can be used:</p>
24657 <div id="doc_table_u.13"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24659 <th class="left">Flag</th>
24660 <th class="left">Description</th>
24665 <td>Emit "data-xpath" attributes</td>
24669 <td>Emit additional info fields</td>
24673 <p id="doc_section_3_1_5_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>
24674 <p id="doc_section_3_1_5_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 3.4.4</a> for details.</p>
24675 <p id="doc_section_3_1_5_1_p_10">If the style is XO_STYLE_XML, the following additional flags can be used:</p>
24676 <div id="doc_table_u.14"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
24678 <th class="left">Flag</th>
24679 <th class="left">Description</th>
24683 <td>Flag 'key' fields for xml</td>
24686 <p id="doc_section_3_1_5_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>
24687 <div id="doc_figure_u.94"></div> <pre>
24688 xo_emit("{k:name}", item);
24691 <name key="key">truck</name>
24693 <div class="content">
24694 <h4 id="doc_section_3_1_5_2">
24695 <div class="self-section-number">
24696 <a href="#doc_section_3_1_5_2">3.1.5.2</a>Â </div>
24697 <a id="xo_clear_flags" href="#xo_clear_flags">xo_clear_flags</a>
24699 <p id="doc_section_3_1_5_2_p_1">The xo_clear_flags() function turns off the given flags in a specific handle.</p>
24700 <div id="doc_figure_u.95"></div> <pre>
24701 void xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags);
24703 <div class="content">
24704 <h4 id="doc_section_3_1_5_3">
24705 <div class="self-section-number">
24706 <a href="#doc_section_3_1_5_3">3.1.5.3</a>Â </div>
24707 <a id="xo_set_options" href="#xo_set_options">xo_set_options</a>
24709 <p id="doc_section_3_1_5_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>
24710 <div id="doc_figure_u.96"></div> <pre>
24711 int xo_set_options (xo_handle_t *xop, const char *input);
24712 </pre> <p id="doc_section_3_1_5_3_p_3">The options are identical to those listed in <a href="#command-line-arguments" title="Command-line Arguments">Section 2.4</a>.</p>
24715 <div class="content">
24716 <h3 id="doc_section_3_1_6">
24717 <div class="self-section-number">
24718 <a href="#doc_section_3_1_6">3.1.6</a>Â </div>
24719 <a id="xo_destroy" href="#xo_destroy">xo_destroy</a>
24721 <p id="doc_section_3_1_6_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>
24722 <div id="doc_figure_u.97"></div> <pre>
24723 void xo_destroy(xo_handle_t *xop);
24726 <div class="content">
24727 <h2 id="doc_section_3_2">
24728 <div class="self-section-number">
24729 <a href="#doc_section_3_2">3.2</a>Â </div>
24730 <a id="emitting-content-xo_emit" href="#emitting-content-xo_emit">Emitting Content (xo_emit)</a>
24732 <p id="doc_section_3_2_p_1">The following functions are used to emit output:</p>
24733 <div id="doc_figure_u.98"></div> <pre>
24734 int xo_emit (const char *fmt, ...);
24735 int xo_emit_h (xo_handle_t *xop, const char *fmt, ...);
24736 int xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap);
24737 </pre> <p id="doc_section_3_2_p_3">The "fmt" argument is a string containing field descriptors as specified in <a href="#format-strings" title="Format Strings">Section 2.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 3.1</a>.</p>
24738 <p id="doc_section_3_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>
24739 <p id="doc_section_3_2_p_5">Section Contents: </p>
24741 <li><a href="#xo_emit_field" title="Single Field Emitting Functions (xo_emit_field)">Section 3.2.1</a></li>
24742 <li><a href="#xo_attr" title="Attributes (xo_attr)">Section 3.2.2</a></li>
24743 <li><a href="#flushing-output-xo_flush" title="Flushing Output (xo_flush)">Section 3.2.3</a></li>
24744 <li><a href="#finishing-output-xo_finish" title="Finishing Output (xo_finish)">Section 3.2.4</a></li>
24746 <div class="content">
24747 <h3 id="doc_section_3_2_1">
24748 <div class="self-section-number">
24749 <a href="#doc_section_3_2_1">3.2.1</a>Â </div>
24750 <a id="xo_emit_field" href="#xo_emit_field">Single Field Emitting Functions (xo_emit_field)</a>
24752 <p id="doc_section_3_2_1_p_1">The following functions can also make output, but only make a single field at a time:</p>
24753 <div id="doc_figure_u.99"></div> <pre>
24754 int xo_emit_field_hv (xo_handle_t *xop, const char *rolmod,
24755 const char *contents, const char *fmt,
24756 const char *efmt, va_list vap);
24758 int xo_emit_field_h (xo_handle_t *xop, const char *rolmod,
24759 const char *contents, const char *fmt,
24760 const char *efmt, ...);
24762 int xo_emit_field (const char *rolmod, const char *contents,
24763 const char *fmt, const char *efmt, ...);
24764 </pre> <p id="doc_section_3_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>
24765 <div id="doc_figure_u.100"></div> <pre>
24766 xo_emit("T", "Host name is ", NULL, NULL);
24767 xo_emit("V", "host-name", NULL, NULL, host-name);
24769 <div class="content">
24770 <h3 id="doc_section_3_2_2">
24771 <div class="self-section-number">
24772 <a href="#doc_section_3_2_2">3.2.2</a>Â </div>
24773 <a id="xo_attr" href="#xo_attr">Attributes (xo_attr)</a>
24775 <p id="doc_section_3_2_2_p_1">The xo_attr() function emits attributes for the XML output style.</p>
24776 <div id="doc_figure_u.101"></div> <pre>
24777 int xo_attr (const char *name, const char *fmt, ...);
24778 int xo_attr_h (xo_handle_t *xop, const char *name,
24779 const char *fmt, ...);
24780 int xo_attr_hv (xo_handle_t *xop, const char *name,
24781 const char *fmt, va_list vap);
24782 </pre> <p id="doc_section_3_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>
24783 <div id="doc_figure_u.102"></div> <pre>
24785 xo_attr("seconds", "%ld", (unsigned long) login_time);
24786 struct tm *tmp = localtime(login_time);
24787 strftime(buf, sizeof(buf), "%R", tmp);
24788 xo_emit("Logged in at {:login-time}\n", buf);
24790 <login-time seconds="1408336270">00:14</login-time>
24791 </pre> <p id="doc_section_3_2_2_p_5">xo_attr is placed on the next container, instance, leaf, or leaf list that is emitted.</p>
24792 <p id="doc_section_3_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>
24794 <div class="content">
24795 <h3 id="doc_section_3_2_3">
24796 <div class="self-section-number">
24797 <a href="#doc_section_3_2_3">3.2.3</a>Â </div>
24798 <a id="flushing-output-xo_flush" href="#flushing-output-xo_flush">Flushing Output (xo_flush)</a>
24800 <p id="doc_section_3_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>
24801 <div id="doc_figure_u.103"></div> <pre>
24802 void xo_flush (void);
24803 void xo_flush_h (xo_handle_t *xop);
24804 </pre> <p id="doc_section_3_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>
24806 <div class="content">
24807 <h3 id="doc_section_3_2_4">
24808 <div class="self-section-number">
24809 <a href="#doc_section_3_2_4">3.2.4</a>Â </div>
24810 <a id="finishing-output-xo_finish" href="#finishing-output-xo_finish">Finishing Output (xo_finish)</a>
24812 <p id="doc_section_3_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>
24813 <div id="doc_figure_u.104"></div> <pre>
24814 int xo_finish (void);
24815 int xo_finish_h (xo_handle_t *xop);
24816 void xo_finish_atexit (void);
24817 </pre> <p id="doc_section_3_2_4_p_3">Calling this function is vital to the proper operation of libxo, especially for the non-TEXT output styles.</p>
24818 <p id="doc_section_3_2_4_p_4">xo_finish_atexit is suitable for use with atexit(3).</p>
24821 <div class="content">
24822 <h2 id="doc_section_3_3">
24823 <div class="self-section-number">
24824 <a href="#doc_section_3_3">3.3</a>Â </div>
24825 <a id="emitting-hierarchy" href="#emitting-hierarchy">Emitting Hierarchy</a>
24827 <p id="doc_section_3_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>
24828 <p id="doc_section_3_3_p_2">To create a container, use the xo_open_container and xo_close_container functions:</p>
24829 <div id="doc_figure_u.105"></div> <pre>
24830 int xo_open_container (const char *name);
24831 int xo_open_container_h (xo_handle_t *xop, const char *name);
24832 int xo_open_container_hd (xo_handle_t *xop, const char *name);
24833 int xo_open_container_d (const char *name);
24835 int xo_close_container (const char *name);
24836 int xo_close_container_h (xo_handle_t *xop, const char *name);
24837 int xo_close_container_hd (xo_handle_t *xop);
24838 int xo_close_container_d (void);
24839 </pre> <p id="doc_section_3_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>
24840 <p id="doc_section_3_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>
24841 <p id="doc_section_3_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>
24842 <p id="doc_section_3_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>
24843 <div id="doc_figure_u.106"></div> <pre>
24845 xo_open_container("system");
24846 xo_emit("The host name is {:host-name}\n", hn);
24847 xo_close_container("system");
24849 <system><host-name>foo</host-name></system>
24850 </pre> <p id="doc_section_3_3_p_9">Section Contents: </p>
24851 <ul><li><a href="#lists-and-instances-2" title="Lists and Instances">Section 3.3.1</a></li></ul>
24852 <div class="content">
24853 <h3 id="doc_section_3_3_1">
24854 <div class="self-section-number">
24855 <a href="#doc_section_3_3_1">3.3.1</a>Â </div>
24856 <a id="lists-and-instances-2" href="#lists-and-instances-2">Lists and Instances</a>
24858 <p id="doc_section_3_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>
24859 <p id="doc_section_3_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>
24860 <div id="doc_figure_u.107"></div> <pre>
24862 xo_open_list("user");
24863 for (i = 0; i < num_users; i++) {
24864 xo_open_instance("user");
24865 xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\n",
24866 pw[i].pw_name, pw[i].pw_uid,
24867 pw[i].pw_gid, pw[i].pw_dir);
24868 xo_close_instance("user");
24870 xo_close_list("user");
24872 phil:1001:1001:/home/phil
24873 pallavi:1002:1002:/home/pallavi
24876 <name>phil</name>
24877 <uid>1001</uid>
24878 <gid>1001</gid>
24879 <home>/home/phil</home>
24882 <name>pallavi</name>
24883 <uid>1002</uid>
24884 <gid>1002</gid>
24885 <home>/home/pallavi</home>
24893 "home": "/home/phil",
24899 "home": "/home/pallavi",
24904 <div class="content">
24905 <h2 id="doc_section_3_4">
24906 <div class="self-section-number">
24907 <a href="#doc_section_3_4">3.4</a>Â </div>
24908 <a id="support-functions" href="#support-functions">Support Functions</a>
24910 <p id="doc_section_3_4_p_1">Section Contents: </p>
24912 <li><a href="#xo_parse_args" title="Parsing Command-line Arguments (xo_parse_args)">Section 3.4.1</a></li>
24913 <li><a href="#xo_set_program" title="xo_set_program">Section 3.4.2</a></li>
24914 <li><a href="#xo_set_version" title="xo_set_version">Section 3.4.3</a></li>
24915 <li><a href="#info" title="Field Information (xo_info_t)">Section 3.4.4</a></li>
24916 <li><a href="#memory-allocation" title="Memory Allocation">Section 3.4.5</a></li>
24917 <li><a href="#LIBXO_OPTIONS" title="LIBXO_OPTIONS">Section 3.4.6</a></li>
24918 <li><a href="#errors-warnings-and-messages" title="Errors, Warnings, and Messages">Section 3.4.7</a></li>
24919 <li><a href="#xo_error" title="xo_error">Section 3.4.8</a></li>
24920 <li><a href="#xo_no_setlocale" title="xo_no_setlocale">Section 3.4.9</a></li>
24922 <div class="content">
24923 <h3 id="doc_section_3_4_1">
24924 <div class="self-section-number">
24925 <a href="#doc_section_3_4_1">3.4.1</a>Â </div>
24926 <a id="xo_parse_args" href="#xo_parse_args">Parsing Command-line Arguments (xo_parse_args)</a>
24928 <p id="doc_section_3_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>
24929 <div id="doc_figure_u.108"></div> <pre>
24930 argc = xo_parse_args(argc, argv);
24932 exit(EXIT_FAILURE);
24933 </pre> <p id="doc_section_3_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="#command-line-arguments" title="Command-line Arguments">Section 2.4</a> for a description of valid arguments.</p>
24935 <div class="content">
24936 <h3 id="doc_section_3_4_2">
24937 <div class="self-section-number">
24938 <a href="#doc_section_3_4_2">3.4.2</a>Â </div>
24939 <a id="xo_set_program" href="#xo_set_program">xo_set_program</a>
24941 <p id="doc_section_3_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>
24942 <div id="doc_figure_u.109"></div> <pre>
24943 xo_set_program(argv[0]);
24944 </pre> <p id="doc_section_3_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>
24946 <div class="content">
24947 <h3 id="doc_section_3_4_3">
24948 <div class="self-section-number">
24949 <a href="#doc_section_3_4_3">3.4.3</a>Â </div>
24950 <a id="xo_set_version" href="#xo_set_version">xo_set_version</a>
24952 <p id="doc_section_3_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>
24953 <div id="doc_figure_u.110"></div> <pre>
24954 void xo_set_version (const char *version);
24955 void xo_set_version_h (xo_handle_t *xop, const char *version);
24957 <div class="content">
24958 <h3 id="doc_section_3_4_4">
24959 <div class="self-section-number">
24960 <a href="#doc_section_3_4_4">3.4.4</a>Â </div>
24961 <a id="info" href="#info">Field Information (xo_info_t)</a>
24963 <p id="doc_section_3_4_4_p_1">HTML data can include additional information in attributes that begin with "data‑". To enable this, three things must occur:</p>
24964 <p id="doc_section_3_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>
24965 <p id="doc_section_3_4_4_p_3">Second, the application must inform libxo about this information using the xo_set_info() call:</p>
24966 <div id="doc_figure_u.111"></div> <pre>
24967 typedef struct xo_info_s {
24968 const char *xi_name; /* Name of the element */
24969 const char *xi_type; /* Type of field */
24970 const char *xi_help; /* Description of field */
24973 void xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count);
24974 </pre> <p id="doc_section_3_4_4_p_5">Like other libxo calls, passing NULL for the handle tells libxo to use the default handle.</p>
24975 <p id="doc_section_3_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>
24976 <div id="doc_figure_u.112"></div> <pre>
24977 xo_info_t info[] = {
24978 { "in-stock", "number", "Number of items in stock" },
24979 { "name", "string", "Name of the item" },
24980 { "on-order", "number", "Number of items on order" },
24981 { "sku", "string", "Stock Keeping Unit" },
24982 { "sold", "number", "Number of items sold" },
24984 int info_count = (sizeof(info) / sizeof(info[0]));
24986 xo_set_info(NULL, info, info_count);
24987 </pre> <p id="doc_section_3_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 "‑‑libxo=info" command line argument.</p>
24988 <p id="doc_section_3_4_4_p_9">The type and help values, if present, are emitted as the "data‑type" and "data‑help" attributes:</p>
24989 <div id="doc_figure_u.113"></div> <pre>
24990 <div class="data" data-tag="sku" data-type="string"
24991 data-help="Stock Keeping Unit">GRO-000-533</div>
24993 <div class="content">
24994 <h3 id="doc_section_3_4_5">
24995 <div class="self-section-number">
24996 <a href="#doc_section_3_4_5">3.4.5</a>Â </div>
24997 <a id="memory-allocation" href="#memory-allocation">Memory Allocation</a>
24999 <p id="doc_section_3_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>
25000 <div id="doc_figure_u.114"></div> <pre>
25001 void xo_set_allocator (xo_realloc_func_t realloc_func,
25002 xo_free_func_t free_func);
25003 </pre> <p id="doc_section_3_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>
25004 <p id="doc_section_3_4_5_p_4">By default, the standard realloc() and free() functions are used.</p>
25006 <div class="content">
25007 <h3 id="doc_section_3_4_6">
25008 <div class="self-section-number">
25009 <a href="#doc_section_3_4_6">3.4.6</a>Â </div>
25010 <a id="LIBXO_OPTIONS" href="#LIBXO_OPTIONS">LIBXO_OPTIONS</a>
25012 <p id="doc_section_3_4_6_p_1">The environment variable "LIBXO_OPTIONS" can be set to a string of options:</p>
25013 <div id="doc_table_u.15"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25015 <th class="left">Option</th>
25016 <th class="left">Action</th>
25021 <td>Enable color/effects for TEXT/HTML</td>
25025 <td>Force line-buffered flushing</td>
25029 <td>Enable HTML output (XO_STYLE_HTML)</td>
25033 <td>Enable info output (XOF_INFO)</td>
25036 <td>i<num></td>
25037 <td>Indent by <number></td>
25041 <td>Enable JSON output (XO_STYLE_JSON)</td>
25045 <td>Add keys to XPATH expressions in HTML</td>
25049 <td>Disable humanization (TEXT, HTML)</td>
25053 <td>Enable pretty-printed output (XOF_PRETTY)</td>
25057 <td>Enable text output (XO_STYLE_TEXT)</td>
25061 <td>Add units to HTML output</td>
25065 <td>Change "-"s to "_"s in element names (JSON)</td>
25069 <td>Enable warnings (XOF_WARN)</td>
25073 <td>Enable XML output (XO_STYLE_XML)</td>
25077 <td>Enable XPath data (XOF_XPATH)</td>
25081 <p id="doc_section_3_4_6_p_2">For example, warnings can be enabled by:</p>
25082 <div id="doc_figure_u.115"></div> <pre>
25083 % env LIBXO_OPTIONS=W my-app
25084 </pre> <p id="doc_section_3_4_6_p_4">Complete HTML output can be generated with:</p>
25085 <div id="doc_figure_u.116"></div> <pre>
25086 % env LIBXO_OPTIONS=HXI my-app
25087 </pre> <p id="doc_section_3_4_6_p_6">Since environment variables are inherited, child processes will have the same options, which may be undesirable, making the use of the "‑‑libxo" option is preferable in most situations.</p>
25089 <div class="content">
25090 <h3 id="doc_section_3_4_7">
25091 <div class="self-section-number">
25092 <a href="#doc_section_3_4_7">3.4.7</a>Â </div>
25093 <a id="errors-warnings-and-messages" href="#errors-warnings-and-messages">Errors, Warnings, and Messages</a>
25095 <p id="doc_section_3_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>
25096 <div id="doc_figure_u.117"></div> <pre>
25097 void xo_warn (const char *fmt, ...);
25098 void xo_warnx (const char *fmt, ...);
25099 void xo_warn_c (int code, const char *fmt, ...);
25100 void xo_warn_hc (xo_handle_t *xop, int code,
25101 const char *fmt, ...);
25102 void xo_err (int eval, const char *fmt, ...);
25103 void xo_errc (int eval, int code, const char *fmt, ...);
25104 void xo_errx (int eval, const char *fmt, ...);
25105 void xo_message (const char *fmt, ...);
25106 void xo_message_c (int code, const char *fmt, ...);
25107 void xo_message_hc (xo_handle_t *xop, int code,
25108 const char *fmt, ...);
25109 void xo_message_hcv (xo_handle_t *xop, int code,
25110 const char *fmt, va_list vap);
25111 </pre> <p id="doc_section_3_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>
25112 <div id="doc_figure_u.118"></div> <pre>
25114 if (open(filename, O_RDONLY) < 0)
25115 xo_err(1, "cannot open file '%s'", filename);
25117 <div class="content">
25118 <h3 id="doc_section_3_4_8">
25119 <div class="self-section-number">
25120 <a href="#doc_section_3_4_8">3.4.8</a>Â </div>
25121 <a id="xo_error" href="#xo_error">xo_error</a>
25123 <p id="doc_section_3_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>
25124 <div id="doc_figure_u.119"></div> <pre>
25126 xo_error("Does not %s", "compute");
25128 <error><message>Does not compute</message></error>
25130 "error": { "message": "Does not compute" }
25132 <div class="content">
25133 <h3 id="doc_section_3_4_9">
25134 <div class="self-section-number">
25135 <a href="#doc_section_3_4_9">3.4.9</a>Â </div>
25136 <a id="xo_no_setlocale" href="#xo_no_setlocale">xo_no_setlocale</a>
25138 <p id="doc_section_3_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‑8". The caller may wish to avoid this behavior, and can do so by calling the xo_no_setlocale() function.</p>
25139 <div id="doc_figure_u.120"></div> <pre>
25140 void xo_no_setlocale (void);
25143 <div class="content">
25144 <h2 id="doc_section_3_5">
25145 <div class="self-section-number">
25146 <a href="#doc_section_3_5">3.5</a>Â </div>
25147 <a id="emitting-syslog-messages" href="#emitting-syslog-messages">Emitting syslog Messages</a>
25149 <p id="doc_section_3_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>
25150 <p id="doc_section_3_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 "<pri>" 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>
25151 <p id="doc_section_3_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>
25152 <p id="doc_section_3_5_p_4">https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers</p>
25153 <p id="doc_section_3_5_p_5">Use the <a href="#xo_set_syslog_enterprise_id" title="xo_set_syslog_enterprise_id">Section 3.5.3.5</a>() function to set the Enterprise ID, as needed.</p>
25154 <p id="doc_section_3_5_p_6">The message name should follow the conventions in <a href="#good-field-names" title="What makes a good field name?">Section 8.1.3</a>, as should the fields within the message.</p>
25155 <div id="doc_figure_u.121"></div> <pre>
25156 /* Both of these calls are optional */
25157 xo_set_syslog_enterprise_id(32473);
25158 xo_open_log("my-program", 0, LOG_DAEMON);
25160 /* Generate a syslog message */
25161 xo_syslog(LOG_ERR, "upload-failed",
25162 "error <%d> uploading file '{:filename}' "
25163 "as '{:target/%s:%s}'",
25164 code, filename, protocol, remote);
25166 xo_syslog(LOG_INFO, "poofd-invalid-state",
25167 "state {:current/%u} is invalid {:connection/%u}",
25169 </pre> <p id="doc_section_3_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>
25170 <p id="doc_section_3_5_p_9">Section Contents: </p>
25172 <li><a href="#priority" title="Priority, Facility, and Flags">Section 3.5.1</a></li>
25173 <li><a href="#xo_syslog" title="xo_syslog">Section 3.5.2</a></li>
25174 <li><a href="#support-functions-2" title="Support functions">Section 3.5.3</a></li>
25176 <div class="content">
25177 <h3 id="doc_section_3_5_1">
25178 <div class="self-section-number">
25179 <a href="#doc_section_3_5_1">3.5.1</a>Â </div>
25180 <a id="priority" href="#priority">Priority, Facility, and Flags</a>
25182 <p id="doc_section_3_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>
25183 <div id="doc_figure_u.122"></div> <pre>
25184 xo_syslog(LOG_ERR | LOG_AUTH, "login-failed",
25185 "Login failed; user '{:user}' from host '{:address}'",
25187 </pre> <p id="doc_section_3_5_1_p_3">These values are defined in <syslog.h>.</p>
25188 <p id="doc_section_3_5_1_p_4">The priority value indicates the importance and potential impact of each message.</p>
25189 <div id="doc_table_u.16"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25191 <th class="left">Priority</th>
25192 <th class="left">Description</th>
25197 <td>A panic condition, normally broadcast to all users</td>
25201 <td>A condition that should be corrected immediately</td>
25205 <td>Critical conditions</td>
25209 <td>Generic errors</td>
25212 <td>LOG_WARNING</td>
25213 <td>Warning messages</td>
25216 <td>LOG_NOTICE</td>
25217 <td>Non-error conditions that might need special handling</td>
25221 <td>Informational messages</td>
25225 <td>Developer-oriented messages</td>
25229 <p id="doc_section_3_5_1_p_5">The facility value indicates the source of message, in fairly generic terms.</p>
25230 <div id="doc_table_u.17"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25232 <th class="left">Facility</th>
25233 <th class="left">Description</th>
25238 <td>The authorization system (e.g. login(1))</td>
25241 <td>LOG_AUTHPRIV</td>
25242 <td>As LOG_AUTH, but logged to a privileged file</td>
25246 <td>The cron daemon: cron(8)</td>
25249 <td>LOG_DAEMON</td>
25250 <td>System daemons, not otherwise explicitly listed</td>
25254 <td>The file transfer protocol daemons</td>
25258 <td>Messages generated by the kernel</td>
25262 <td>The line printer spooling system</td>
25266 <td>The mail system</td>
25270 <td>The network news system</td>
25273 <td>LOG_SECURITY</td>
25274 <td>Security subsystems, such as ipfw(4)</td>
25277 <td>LOG_SYSLOG</td>
25278 <td>Messages generated internally by syslogd(8)</td>
25282 <td>Messages generated by user processes (default)</td>
25286 <td>The uucp system</td>
25289 <td>LOG_LOCAL0..7</td>
25290 <td>Reserved for local use</td>
25294 <p id="doc_section_3_5_1_p_6">In addition to the values listed above, xo_open_log accepts a set of addition flags requesting specific behaviors.</p>
25295 <div id="doc_table_u.18"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25297 <th class="left">Flag</th>
25298 <th class="left">Description</th>
25303 <td>If syslogd fails, attempt to write to /dev/console</td>
25306 <td>LOG_NDELAY</td>
25307 <td>Open the connection to syslogd(8) immediately</td>
25310 <td>LOG_PERROR</td>
25311 <td>Write the message also to standard error output</td>
25315 <td>Log the process id with each message</td>
25320 <div class="content">
25321 <h3 id="doc_section_3_5_2">
25322 <div class="self-section-number">
25323 <a href="#doc_section_3_5_2">3.5.2</a>Â </div>
25324 <a id="xo_syslog" href="#xo_syslog">xo_syslog</a>
25326 <p id="doc_section_3_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>
25327 <p id="doc_section_3_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>
25328 <div id="doc_figure_u.123"></div> <pre>
25329 xo_syslog(LOG_ERR, "poofd-missing-file",
25330 "'{:filename}' not found: {:error/%m}", filename);
25332 ... [poofd-missing-file@32473 filename="/etc/poofd.conf"
25333 error="Permission denied"] '/etc/poofd.conf' not
25334 found: Permission denied
25336 <div class="content">
25337 <h3 id="doc_section_3_5_3">
25338 <div class="self-section-number">
25339 <a href="#doc_section_3_5_3">3.5.3</a>Â </div>
25340 <a id="support-functions-2" href="#support-functions-2">Support functions</a>
25342 <p id="doc_section_3_5_3_p_1">Section Contents: </p>
25344 <li><a href="#xo_vsyslog" title="xo_vsyslog">Section 3.5.3.1</a></li>
25345 <li><a href="#xo_open_log" title="xo_open_log">Section 3.5.3.2</a></li>
25346 <li><a href="#xo_close_log" title="xo_close_log">Section 3.5.3.3</a></li>
25347 <li><a href="#xo_set_logmask" title="xo_set_logmask">Section 3.5.3.4</a></li>
25348 <li><a href="#xo_set_syslog_enterprise_id" title="xo_set_syslog_enterprise_id">Section 3.5.3.5</a></li>
25350 <div class="content">
25351 <h4 id="doc_section_3_5_3_1">
25352 <div class="self-section-number">
25353 <a href="#doc_section_3_5_3_1">3.5.3.1</a>Â </div>
25354 <a id="xo_vsyslog" href="#xo_vsyslog">xo_vsyslog</a>
25356 <p id="doc_section_3_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>
25357 <div id="doc_figure_u.124"></div> <pre>
25358 void my_log (const char *name, const char *fmt, ...)
25361 va_start(vap, fmt);
25362 xo_vsyslog(LOG_ERR, name, fmt, vap);
25366 <div class="content">
25367 <h4 id="doc_section_3_5_3_2">
25368 <div class="self-section-number">
25369 <a href="#doc_section_3_5_3_2">3.5.3.2</a>Â </div>
25370 <a id="xo_open_log" href="#xo_open_log">xo_open_log</a>
25372 <p id="doc_section_3_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 3.5.1</a>.</p>
25373 <div id="doc_figure_u.125"></div> <pre>
25375 xo_open_log (const char *ident, int logopt, int facility);
25377 <div class="content">
25378 <h4 id="doc_section_3_5_3_3">
25379 <div class="self-section-number">
25380 <a href="#doc_section_3_5_3_3">3.5.3.3</a>Â </div>
25381 <a id="xo_close_log" href="#xo_close_log">xo_close_log</a>
25383 <p id="doc_section_3_5_3_3_p_1">xo_close_log functions similar to closelog(3), closing the log file and releasing any associated resources.</p>
25384 <div id="doc_figure_u.126"></div> <pre>
25386 xo_close_log (void);
25388 <div class="content">
25389 <h4 id="doc_section_3_5_3_4">
25390 <div class="self-section-number">
25391 <a href="#doc_section_3_5_3_4">3.5.3.4</a>Â </div>
25392 <a id="xo_set_logmask" href="#xo_set_logmask">xo_set_logmask</a>
25394 <p id="doc_section_3_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>
25395 <div id="doc_figure_u.127"></div> <pre>
25397 xo_set_logmask (int maskpri);
25400 setlogmask(LOG_UPTO(LOG_WARN));
25402 <div class="content">
25403 <h4 id="doc_section_3_5_3_5">
25404 <div class="self-section-number">
25405 <a href="#doc_section_3_5_3_5">3.5.3.5</a>Â </div>
25406 <a id="xo_set_syslog_enterprise_id" href="#xo_set_syslog_enterprise_id">xo_set_syslog_enterprise_id</a>
25408 <p id="doc_section_3_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>
25409 <p id="doc_section_3_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>
25410 <div id="doc_figure_u.128"></div> <pre>
25412 xo_set_syslog_enterprise_id (unsigned short eid);
25413 </pre> <p id="doc_section_3_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>
25414 <p id="doc_section_3_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>
25415 <p id="doc_section_3_5_3_5_p_6">New EIDs can be requested from IANA using the following page:</p>
25416 <p id="doc_section_3_5_3_5_p_7"> <a href="http://pen.iana.org/pen/PenApplication.page">http://pen.iana.org/pen/PenApplication.page</a></p>
25417 <p id="doc_section_3_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>
25421 <div class="content">
25422 <h2 id="doc_section_3_6">
25423 <div class="self-section-number">
25424 <a href="#doc_section_3_6">3.6</a>Â </div>
25425 <a id="creating-custom-encoders" href="#creating-custom-encoders">Creating Custom Encoders</a>
25427 <p id="doc_section_3_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>
25428 <p id="doc_section_3_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>
25429 <p id="doc_section_3_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>
25430 <p id="doc_section_3_6_p_4">The three elements of the API are:</p>
25431 <p id="doc_section_3_6_p_5"> </p>
25434 <li>initialization</li>
25435 <li>operations</li>
25437 <p id="doc_section_3_6_p_6">The following sections provide details about these topics.</p>
25438 <p id="doc_section_3_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>
25439 <p id="doc_section_3_6_p_8">Section Contents: </p>
25441 <li><a href="#loading-encoders" title="Loading Encoders">Section 3.6.1</a></li>
25442 <li><a href="#encoder-initialization" title="Encoder Initialization">Section 3.6.2</a></li>
25443 <li><a href="#operations" title="Operations">Section 3.6.3</a></li>
25445 <div class="content">
25446 <h3 id="doc_section_3_6_1">
25447 <div class="self-section-number">
25448 <a href="#doc_section_3_6_1">3.6.1</a>Â </div>
25449 <a id="loading-encoders" href="#loading-encoders">Loading Encoders</a>
25451 <p id="doc_section_3_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>
25452 <div id="doc_figure_u.129"></div> <pre>
25453 % ls -1 lib/libxo/extensions/*.enc
25454 lib/libxo/extensions/cbor.enc
25455 lib/libxo/extensions/test.enc
25457 <div class="content">
25458 <h3 id="doc_section_3_6_2">
25459 <div class="self-section-number">
25460 <a href="#doc_section_3_6_2">3.6.2</a>Â </div>
25461 <a id="encoder-initialization" href="#encoder-initialization">Encoder Initialization</a>
25463 <p id="doc_section_3_6_2_p_1">Each encoder must export a symbol used to access the library, which must have the following signature:</p>
25464 <div id="doc_figure_u.130"></div> <pre>
25465 int xo_encoder_library_init (XO_ENCODER_INIT_ARGS);
25466 </pre> <p id="doc_section_3_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>
25467 <p id="doc_section_3_6_2_p_4"> </p>
25469 <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>
25470 <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>
25472 <p id="doc_section_3_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>
25473 <p id="doc_section_3_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>
25475 <div class="content">
25476 <h3 id="doc_section_3_6_3">
25477 <div class="self-section-number">
25478 <a href="#doc_section_3_6_3">3.6.3</a>Â </div>
25479 <a id="operations" href="#operations">Operations</a>
25481 <p id="doc_section_3_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>
25482 <div id="doc_table_u.19"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25484 <th class="left">Operation</th>
25485 <th class="left">Meaning (Base function)</th>
25489 <td>XO_OP_CREATE</td>
25490 <td>Called when the handle is created</td>
25493 <td>XO_OP_OPEN_CONTAINER</td>
25494 <td>Container opened (xo_open_container)</td>
25497 <td>XO_OP_CLOSE_CONTAINER</td>
25498 <td>Container closed (xo_close_container)</td>
25501 <td>XO_OP_OPEN_LIST</td>
25502 <td>List opened (xo_open_list)</td>
25505 <td>XO_OP_CLOSE_LIST</td>
25506 <td>List closed (xo_close_list)</td>
25509 <td>XO_OP_OPEN_LEAF_LIST</td>
25510 <td>Leaf list opened (xo_open_leaf_list)</td>
25513 <td>XO_OP_CLOSE_LEAF_LIST</td>
25514 <td>Leaf list closed (xo_close_leaf_list)</td>
25517 <td>XO_OP_OPEN_INSTANCE</td>
25518 <td>Instance opened (xo_open_instance)</td>
25521 <td>XO_OP_CLOSE_INSTANCE</td>
25522 <td>Instance closed (xo_close_instance)</td>
25525 <td>XO_OP_STRING</td>
25526 <td>Field with Quoted UTF-8 string</td>
25529 <td>XO_OP_CONTENT</td>
25530 <td>Field with content</td>
25533 <td>XO_OP_FINISH</td>
25534 <td>Finish any pending output</td>
25537 <td>XO_OP_FLUSH</td>
25538 <td>Flush any buffered output</td>
25541 <td>XO_OP_DESTROY</td>
25542 <td>Clean up resources</td>
25545 <td>XO_OP_ATTRIBUTE</td>
25546 <td>An attribute name/value pair</td>
25549 <td>XO_OP_VERSION</td>
25550 <td>A version string</td>
25554 <p id="doc_section_3_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>
25555 <p id="doc_section_3_6_3_p_3">All strings are encoded in UTF-8.</p>
25559 <hr class="noprint">
25560 <div class="content">
25561 <h1 id="doc_section_4" class="np">
25562 <div class="self-section-number">
25563 <a href="#doc_section_4">4_</a>Â </div>
25564 <a id="the-xo-utility" href="#the-xo-utility">The "xo" Utility</a>
25566 <p id="doc_section_4_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>
25567 <p id="doc_section_4_p_2">The style of output can be selected using a specific option: "‑X" for XML, "‑J" for JSON, "‑H" for HTML, or "‑T" for TEXT, which is the default. The "--style <style>" option can also be used. The LIBXO_OPTIONS environment variable can also be used to set the style, as well as other flags.</p>
25568 <p id="doc_section_4_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>
25569 <div id="doc_figure_u.131"></div> <pre>
25570 xo "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
25573 The fish weighs 6 pounds.
25575 <name>fish</name>
25576 <weight>6</weight>
25581 <div class="line">
25582 <div class="text">The </div>
25583 <div class="data" data-tag="name">fish</div>
25584 <div class="text"> weighs </div>
25585 <div class="data" data-tag="weight">6</div>
25586 <div class="text"> pounds.</div>
25588 </pre> <p id="doc_section_4_p_5">The "--wrap <path>" 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>
25589 <div id="doc_figure_u.132"></div> <pre>
25590 xo --wrap top/a/b/c '{:tag}' value
25597 <tag>value</tag>
25612 </pre> <p id="doc_section_4_p_7">The "--open <path>" and "--close <path>" 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 "‑‑depth" option may be used to set the depth for indentation. The "‑‑leading‑xpath" may be used to prepend data to the XPath values used for HTML output style.</p>
25613 <div id="doc_figure_u.133"></div> <pre>
25616 xo --depth 2 '{tag}' value
25617 xo --close top/data
25621 <tag>value</tag>
25630 </pre> <p id="doc_section_4_p_9">Section Contents: </p>
25632 <li><a href="#command-line-options" title="Command Line Options">Section 4.1</a></li>
25633 <li><a href="#example-2" title="Example">Section 4.2</a></li>
25635 <div class="content">
25636 <h2 id="doc_section_4_1">
25637 <div class="self-section-number">
25638 <a href="#doc_section_4_1">4.1</a>Â </div>
25639 <a id="command-line-options" href="#command-line-options">Command Line Options</a>
25641 <p id="doc_section_4_1_p_1">Usage: xo [options] format [fields]</p>
25642 <div id="doc_figure_u.134"></div> <pre>
25643 --close <path> Close tags for the given path
25644 --depth <num> Set the depth for pretty printing
25645 --help Display this help text
25646 --html OR -H Generate HTML output
25647 --json OR -J Generate JSON output
25648 --leading-xpath <path> Add a prefix to generated XPaths (HTML)
25649 --open <path> Open tags for the given path
25650 --pretty OR -p Make 'pretty' output (add indent, newlines)
25651 --style <style> Generate given style (xml, json, text, html)
25652 --text OR -T Generate text output (the default style)
25653 --version Display version information
25654 --warn OR -W Display warnings in text on stderr
25655 --warn-xml Display warnings in xml on stdout
25656 --wrap <path> Wrap output in a set of containers
25657 --xml OR -X Generate XML output
25658 --xpath Add XPath data to HTML output);
25660 <div class="content">
25661 <h2 id="doc_section_4_2">
25662 <div class="self-section-number">
25663 <a href="#doc_section_4_2">4.2</a>Â </div>
25664 <a id="example-2" href="#example-2">Example</a>
25666 <div id="doc_figure_u.135"></div> <pre>
25667 % xo 'The {:product} is {:status}\n' stereo "in route"
25668 The stereo is in route
25669 % ./xo/xo -p -X 'The {:product} is {:status}\n' stereo "in route"
25670 <product>stereo</product>
25671 <status>in route</status>
25674 <hr class="noprint">
25675 <div class="content">
25676 <h1 id="doc_section_5" class="np">
25677 <div class="self-section-number">
25678 <a href="#doc_section_5">5_</a>Â </div>
25679 <a id="xolint" href="#xolint">xolint</a>
25681 <p id="doc_section_5_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>
25682 <p id="doc_section_5_p_2">xolint takes the one or more C files as arguments, and reports and errors, warning, or informational messages as needed.</p>
25683 <div id="doc_table_u.20"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25685 <th class="left">Option</th>
25686 <th class="left">Meaning</th>
25691 <td>Invoke 'cpp' against the input file</td>
25694 <td>-C <flags></td>
25695 <td>Flags that are passed to 'cpp</td>
25699 <td>Enable debug output</td>
25703 <td>Generate documentation for all xolint messages</td>
25707 <td>Generate info table code</td>
25711 <td>Print the offending lines after the message</td>
25715 <td>Print vocabulary of all field names</td>
25719 <td>Extract samples from xolint, suitable for testing</td>
25723 <p id="doc_section_5_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>
25724 <div id="doc_figure_u.136"></div> <pre>
25725 % xolint.pl -t xolint.c
25726 xolint.c: 16: error: anchor format should be "%d"
25727 16 xo_emit("{[:/%s}");
25728 </pre> <p id="doc_section_5_p_5">The "‑I" option will generate a table of xo_info_t structures ,</p>
25729 <p id="doc_section_5_p_6">The "‑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>
25731 <hr class="noprint">
25732 <div class="content">
25733 <h1 id="doc_section_6" class="np">
25734 <div class="self-section-number">
25735 <a href="#doc_section_6">6_</a>Â </div>
25736 <a id="xohtml" href="#xohtml">xohtml</a>
25738 <p id="doc_section_6_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>
25739 <p id="doc_section_6_p_2">xohtml is given a command, either on the command line or via the "‑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 "‑f" option. The "‑b" option can be used to provide an alternative base path for the support files.</p>
25740 <div id="doc_table_u.21"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25742 <th class="left">Option</th>
25743 <th class="left">Meaning</th>
25747 <td>-b <base></td>
25748 <td>Base path for finding css/javascript files</td>
25751 <td>-c <command></td>
25752 <td>Command to execute</td>
25755 <td>-f <file></td>
25756 <td>Output file name</td>
25760 <p id="doc_section_6_p_3">The "‑c" option takes a full command with arguments, including any libxo options needed to generate html ("‑‑libxo=html"). This value must be quoted if it consists of multiple tokens.</p>
25762 <hr class="noprint">
25763 <div class="content">
25764 <h1 id="doc_section_7" class="np">
25765 <div class="self-section-number">
25766 <a href="#doc_section_7">7_</a>Â </div>
25767 <a id="xopo" href="#xopo">xopo</a>
25769 <p id="doc_section_7_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>
25770 <p id="doc_section_7_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 "‑f" option, and the output is either standard output or a file given by the "‑o" option.</p>
25771 <p id="doc_section_7_p_3">In the second mode, a simple message given using the "‑s" option on the command, and the simplified version of that message is printed on stdout.</p>
25772 <div id="doc_table_u.22"><table summary="" class="tt full" cellpadding="3" cellspacing="0">
25774 <th class="left">Option</th>
25775 <th class="left">Meaning</th>
25779 <td>-o <file></td>
25780 <td>Output file name</td>
25783 <td>-f <file></td>
25784 <td>Use the given .po file as input</td>
25787 <td>-s <text></td>
25788 <td>Simplify a format string</td>
25792 <div id="doc_figure_u.137"></div> <pre>
25794 % xopo -s "There are {:count/%u} {:event/%.6s} events\n"
25795 There are {:count} {:event} events\n
25797 % xgettext --default-domain=foo --no-wrap \
25798 --add-comments --keyword=xo_emit --keyword=xo_emit_h \
25799 --keyword=xo_emit_warn -C -E -n --foreign-user \
25800 -o foo.pot.raw foo.c
25801 % xopo -f foo.pot.raw -o foo.pot
25802 </pre> <p id="doc_section_7_p_5">Use of the "‑‑no‑wrap" option for xgettext is required to ensure that incoming msgid strings are not wrapped across multiple lines.</p>
25804 <hr class="noprint">
25805 <div class="content">
25806 <h1 id="doc_section_8" class="np">
25807 <div class="self-section-number">
25808 <a href="#doc_section_8">8_</a>Â </div>
25809 <a id="faqs" href="#faqs">FAQs</a>
25811 <p id="doc_section_8_p_1">This section contains the set of questions that users typically ask, along with answers that might be helpful.</p>
25812 <p id="doc_section_8_p_2">Section Contents: </p>
25814 <li><a href="#general" title="General">Section 8.1</a></li>
25815 <li><a href="#what-does-this-message-mean" title="What does this message mean?">Section 8.2</a></li>
25817 <p id="doc_section_8_p_3">Section Contents: </p>
25819 <li><a href="#general" title="General">Section 8.1</a></li>
25820 <li><a href="#what-does-this-message-mean" title="What does this message mean?">Section 8.2</a></li>
25822 <div class="content">
25823 <h2 id="doc_section_8_1">
25824 <div class="self-section-number">
25825 <a href="#doc_section_8_1">8.1</a>Â </div>
25826 <a id="general" href="#general">General</a>
25828 <p id="doc_section_8_1_p_1">Section Contents: </p>
25830 <li><a href="#can-you-share-the-history-of-libxo" title="Can you share the history of libxo?">Section 8.1.1</a></li>
25831 <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 8.1.2</a></li>
25832 <li><a href="#good-field-names" title="What makes a good field name?">Section 8.1.3</a></li>
25834 <div class="content">
25835 <h3 id="doc_section_8_1_1">
25836 <div class="self-section-number">
25837 <a href="#doc_section_8_1_1">8.1.1</a>Â </div>
25838 <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>
25840 <p id="doc_section_8_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 "‑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>
25841 <p id="doc_section_8_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>
25842 <p id="doc_section_8_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>
25844 <div class="content">
25845 <h3 id="doc_section_8_1_2">
25846 <div class="self-section-number">
25847 <a href="#doc_section_8_1_2">8.1.2</a>Â </div>
25848 <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>
25850 <p id="doc_section_8_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>
25851 <div id="doc_figure_u.138"></div> <pre>
25853 help "State of the DOCSIS interface";
25858 help "DOCSIS mode (2.0/3.0) of the DOCSIS interface";
25862 tag docsis-upstream-speed {
25863 help "Operational upstream speed of the interface";
25867 tag downstream-scanning {
25868 help "Result of scanning in downstream direction";
25873 help "Result of ranging action";
25877 tag signal-to-noise-ratio {
25878 help "Signal to noise ratio for all channels";
25883 help "Operational power of the signal on all channels";
25887 format docsis-status-format {
25889 State : @, Mode: @, Upstream speed: @
25890 Downstream scanning: @, Ranging: @
25891 Signal to noise ratio: @
25895 field docsis-state;
25897 field docsis-upstream-speed;
25898 field downstream-scanning;
25900 field signal-to-noise-ratio;
25904 </pre> <p id="doc_section_8_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>
25905 <p id="doc_section_8_1_2_p_4">The roles and modifiers describe these details.</p>
25906 <p id="doc_section_8_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>
25907 <p id="doc_section_8_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>
25908 <p id="doc_section_8_1_2_p_7">libxo is a new implementation of these ideas and is distinct from the previous implementation in JUNOS.</p>
25910 <div class="content">
25911 <h3 id="doc_section_8_1_3">
25912 <div class="self-section-number">
25913 <a href="#doc_section_8_1_3">8.1.3</a>Â </div>
25914 <a id="good-field-names" href="#good-field-names">What makes a good field name?</a>
25916 <p id="doc_section_8_1_3_p_1">To make useful, consistent field names, follow these guidelines:</p>
25917 <p id="doc_section_8_1_3_p_2"> </p>
25919 <dt>Use lower case, even for TLAs</dt>
25920 <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>
25921 <dt>Use hyphens, not underscores</dt>
25922 <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>
25923 <dt>Use full words</dt>
25924 <dd>Don't abbreviate especially when the abbreviation is not obvious or not widely used. Use "data‑size", not "dsz" or "dsize". Use "interface" instead of "ifname", "if‑name", "iface", "if", or "intf".</dd>
25925 <dt>Use <verb>-<units></dt>
25926 <dd>Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in making consistent, useful names, avoiding the situation where one app uses "sent‑packet" and another "packets‑sent" and another "packets‑we‑have‑sent". The <units> can be dropped when it is obvious, as can obvious words in the classification. Use "receive‑after‑window‑packets" instead of "received‑packets‑of‑data‑after‑window".</dd>
25927 <dt>Reuse existing field names</dt>
25928 <dd>Nothing's worse than writing expressions like:</dd>
25930 <div id="doc_figure_u.139"></div> <pre>
25931 if ($src1/process[pid == $pid]/name ==
25932 $src2/proc-table/proc-list
25933 /proc-entry[process-id == $pid]/proc-name) {
25936 </pre> <p id="doc_section_8_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>
25937 <p id="doc_section_8_1_3_p_5"> </p>
25939 <dt>Use containment as scoping</dt>
25940 <dd>In the previous example, all the names are prefixed with "proc‑", which is redundant given that they are nested under the process table.</dd>
25941 <dt>Think about your users</dt>
25942 <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 3.2.2</a>) or "{e:}" fields (<a href="#e-modifier" title="The Encoding Modifier ({e:})">Section 2.2.2.4</a>) to make the data useful.</dd>
25943 <dt>Don't use an arbitrary number postfix</dt>
25944 <dd>What does "errors2" mean? No one will know. "errors‑after‑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>
25945 <dt>Be consistent, uniform, unsurprising, and predictable</dt>
25946 <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>
25948 <p id="doc_section_8_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>
25949 <p id="doc_section_8_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‑short" and "dropped‑too‑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>
25952 <div class="content">
25953 <h2 id="doc_section_8_2">
25954 <div class="self-section-number">
25955 <a href="#doc_section_8_2">8.2</a>Â </div>
25956 <a id="what-does-this-message-mean" href="#what-does-this-message-mean">What does this message mean?</a>
25958 <p id="doc_section_8_2_p_1">Section Contents: </p>
25960 <li><a href="#a-percent-sign-appearing-in-text-is-a-literal" title="'A percent sign appearing in text is a literal'">Section 8.2.1</a></li>
25961 <li><a href="#unknown-long-name-for-rolemodifier" title="'Unknown long name for role/modifier'">Section 8.2.2</a></li>
25962 <li><a href="#last-character-before-field-definition-is-a-field-type" title="'Last character before field definition is a field type'">Section 8.2.3</a></li>
25963 <li><a href="#encoding-format-uses-different-number-of-arguments" title="'Encoding format uses different number of arguments'">Section 8.2.4</a></li>
25964 <li><a href="#only-one-field-role-can-be-used" title="'Only one field role can be used'">Section 8.2.5</a></li>
25965 <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 8.2.6</a></li>
25966 <li><a href="#an-encoding-format-cannot-be-given-roles-dnlt" title="'An encoding format cannot be given (roles: DNLT)'">Section 8.2.7</a></li>
25967 <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 8.2.8</a></li>
25968 <li><a href="#field-has-color-without-fg--or-bg--role-c" title="'Field has color without fg- or bg- (role: C)'">Section 8.2.9</a></li>
25969 <li><a href="#field-has-invalid-color-or-effect-role-c" title="'Field has invalid color or effect (role: C)'">Section 8.2.10</a></li>
25970 <li><a href="#field-has-humanize-modifier-but-no-format-string" title="'Field has humanize modifier but no format string'">Section 8.2.11</a></li>
25971 <li><a href="#field-has-hn--modifier-but-not-h-modifier" title="'Field has hn-* modifier but not 'h' modifier'">Section 8.2.12</a></li>
25972 <li><a href="#value-field-must-have-a-name-as-content" title="'Value field must have a name (as content)")'">Section 8.2.13</a></li>
25973 <li><a href="#use-hyphens-not-underscores-for-value-field-name" title="'Use hyphens, not underscores, for value field name'">Section 8.2.14</a></li>
25974 <li><a href="#value-field-name-cannot-start-with-digit" title="'Value field name cannot start with digit'">Section 8.2.15</a></li>
25975 <li><a href="#value-field-name-should-be-lower-case" title="'Value field name should be lower case'">Section 8.2.16</a></li>
25976 <li><a href="#value-field-name-should-be-longer-than-two-characters" title="'Value field name should be longer than two characters'">Section 8.2.17</a></li>
25977 <li><a href="#value-field-name-contains-invalid-character" title="'Value field name contains invalid character'">Section 8.2.18</a></li>
25978 <li><a href="#decoration-field-contains-invalid-character" title="'decoration field contains invalid character'">Section 8.2.19</a></li>
25979 <li><a href="#anchor-content-should-be-decimal-width" title="'Anchor content should be decimal width'">Section 8.2.20</a></li>
25980 <li><a href="#anchor-format-should-be-d" title="'Anchor format should be "%d"'">Section 8.2.21</a></li>
25981 <li><a href="#anchor-cannot-have-both-format-and-encoding-format" title="'Anchor cannot have both format and encoding format")'">Section 8.2.22</a></li>
25982 <li><a href="#max-width-only-valid-for-strings" title="'Max width only valid for strings'">Section 8.2.23</a></li>
25984 <div class="content">
25985 <h3 id="doc_section_8_2_1">
25986 <div class="self-section-number">
25987 <a href="#doc_section_8_2_1">8.2.1</a>Â </div>
25988 <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>
25990 <p id="doc_section_8_2_1_p_1">The message "A percent sign appearing in text is a literal" can be caused by code like:</p>
25991 <div id="doc_figure_u.140"></div> <pre>
25992 xo_emit("cost: %d", cost);
25993 </pre> <p id="doc_section_8_2_1_p_3">This code should be replaced with code like:</p>
25994 <div id="doc_figure_u.141"></div> <pre>
25995 xo_emit("{L:cost}: {:cost/%d}", cost);
25996 </pre> <p id="doc_section_8_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>
25998 <div class="content">
25999 <h3 id="doc_section_8_2_2">
26000 <div class="self-section-number">
26001 <a href="#doc_section_8_2_2">8.2.2</a>Â </div>
26002 <a id="unknown-long-name-for-rolemodifier" href="#unknown-long-name-for-rolemodifier">'Unknown long name for role/modifier'</a>
26004 <p id="doc_section_8_2_2_p_1">The message "Unknown long name for role/modifier" can be caused by code like:</p>
26005 <div id="doc_figure_u.142"></div> <pre>
26006 xo_emit("{,humanization:value}", value);
26007 </pre> <p id="doc_section_8_2_2_p_3">This code should be replaced with code like:</p>
26008 <div id="doc_figure_u.143"></div> <pre>
26009 xo_emit("{,humanize:value}", value);
26010 </pre> <p id="doc_section_8_2_2_p_5">The hn-* modifiers (hn-decimal, hn-space, hn-1000) are only valid for fields with the {h:} modifier.</p>
26012 <div class="content">
26013 <h3 id="doc_section_8_2_3">
26014 <div class="self-section-number">
26015 <a href="#doc_section_8_2_3">8.2.3</a>Â </div>
26016 <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>
26018 <p id="doc_section_8_2_3_p_1">The message "Last character before field definition is a field type" can be caused by code like:</p>
26019 <p id="doc_section_8_2_3_p_2">A common typo:</p>
26020 <div id="doc_figure_u.144"></div> <pre>
26021 xo_emit("{T:Min} T{:Max}");
26022 </pre> <p id="doc_section_8_2_3_p_4">This code should be replaced with code like:</p>
26023 <div id="doc_figure_u.145"></div> <pre>
26024 xo_emit("{T:Min} {T:Max}");
26025 </pre> <p id="doc_section_8_2_3_p_6">Twiddling the "{" and the field role is a common typo.</p>
26027 <div class="content">
26028 <h3 id="doc_section_8_2_4">
26029 <div class="self-section-number">
26030 <a href="#doc_section_8_2_4">8.2.4</a>Â </div>
26031 <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>
26033 <p id="doc_section_8_2_4_p_1">The message "Encoding format uses different number of arguments" can be caused by code like:</p>
26034 <div id="doc_figure_u.146"></div> <pre>
26035 xo_emit("{:name/%6.6s %%04d/%s}", name, number);
26036 </pre> <p id="doc_section_8_2_4_p_3">This code should be replaced with code like:</p>
26037 <div id="doc_figure_u.147"></div> <pre>
26038 xo_emit("{:name/%6.6s %04d/%s-%d}", name, number);
26039 </pre> <p id="doc_section_8_2_4_p_5">Both format should consume the same number of arguments off the stack</p>
26041 <div class="content">
26042 <h3 id="doc_section_8_2_5">
26043 <div class="self-section-number">
26044 <a href="#doc_section_8_2_5">8.2.5</a>Â </div>
26045 <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>
26047 <p id="doc_section_8_2_5_p_1">The message "Only one field role can be used" can be caused by code like:</p>
26048 <div id="doc_figure_u.148"></div> <pre>
26049 xo_emit("{LT:Max}");
26050 </pre> <p id="doc_section_8_2_5_p_3">This code should be replaced with code like:</p>
26051 <div id="doc_figure_u.149"></div> <pre>
26052 xo_emit("{T:Max}");
26054 <div class="content">
26055 <h3 id="doc_section_8_2_6">
26056 <div class="self-section-number">
26057 <a href="#doc_section_8_2_6">8.2.6</a>Â </div>
26058 <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>
26060 <p id="doc_section_8_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>
26061 <div id="doc_figure_u.150"></div> <pre>
26062 xo_emit("{T:%6.6s}\n", "Max");
26063 </pre> <p id="doc_section_8_2_6_p_3">This code should be replaced with code like:</p>
26064 <div id="doc_figure_u.151"></div> <pre>
26065 xo_emit("{T:/%6.6s}\n", "Max");
26066 </pre> <p id="doc_section_8_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>
26068 <div class="content">
26069 <h3 id="doc_section_8_2_7">
26070 <div class="self-section-number">
26071 <a href="#doc_section_8_2_7">8.2.7</a>Â </div>
26072 <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>
26074 <p id="doc_section_8_2_7_p_1">The message "An encoding format cannot be given (roles: DNLT)" can be caused by code like:</p>
26075 <div id="doc_figure_u.152"></div> <pre>
26076 xo_emit("{T:Max//%s}", "Max");
26077 </pre> <p id="doc_section_8_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>
26079 <div class="content">
26080 <h3 id="doc_section_8_2_8">
26081 <div class="self-section-number">
26082 <a href="#doc_section_8_2_8">8.2.8</a>Â </div>
26083 <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>
26085 <p id="doc_section_8_2_8_p_1">The message "Format cannot be given when content is present (roles: CDLN)" can be caused by code like:</p>
26086 <div id="doc_figure_u.153"></div> <pre>
26087 xo_emit("{N:Max/%6.6s}", "Max");
26088 </pre> <p id="doc_section_8_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>
26090 <div class="content">
26091 <h3 id="doc_section_8_2_9">
26092 <div class="self-section-number">
26093 <a href="#doc_section_8_2_9">8.2.9</a>Â </div>
26094 <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>
26096 <p id="doc_section_8_2_9_p_1">The message "Field has color without fg- or bg- (role: C)" can be caused by code like:</p>
26097 <div id="doc_figure_u.154"></div> <pre>
26098 xo_emit("{C:green}{:foo}{C:}", x);
26099 </pre> <p id="doc_section_8_2_9_p_3">This code should be replaced with code like:</p>
26100 <div id="doc_figure_u.155"></div> <pre>
26101 xo_emit("{C:fg-green}{:foo}{C:}", x);
26102 </pre> <p id="doc_section_8_2_9_p_5">Colors must be prefixed by either "fg‑" or "bg‑".</p>
26104 <div class="content">
26105 <h3 id="doc_section_8_2_10">
26106 <div class="self-section-number">
26107 <a href="#doc_section_8_2_10">8.2.10</a>Â </div>
26108 <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>
26110 <p id="doc_section_8_2_10_p_1">The message "Field has invalid color or effect (role: C)" can be caused by code like:</p>
26111 <div id="doc_figure_u.156"></div> <pre>
26112 xo_emit("{C:fg-purple,bold}{:foo}{C:gween}", x);
26113 </pre> <p id="doc_section_8_2_10_p_3">This code should be replaced with code like:</p>
26114 <div id="doc_figure_u.157"></div> <pre>
26115 xo_emit("{C:fg-red,bold}{:foo}{C:fg-green}", x);
26116 </pre> <p id="doc_section_8_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‑" or "bg‑". Effects are limited to bold, no-bold, underline, no-underline, inverse, no-inverse, normal, and reset. Values must be separated by commas.</p>
26118 <div class="content">
26119 <h3 id="doc_section_8_2_11">
26120 <div class="self-section-number">
26121 <a href="#doc_section_8_2_11">8.2.11</a>Â </div>
26122 <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>
26124 <p id="doc_section_8_2_11_p_1">The message "Field has humanize modifier but no format string" can be caused by code like:</p>
26125 <div id="doc_figure_u.158"></div> <pre>
26126 xo_emit("{h:value}", value);
26127 </pre> <p id="doc_section_8_2_11_p_3">This code should be replaced with code like:</p>
26128 <div id="doc_figure_u.159"></div> <pre>
26129 xo_emit("{h:value/%d}", value);
26130 </pre> <p id="doc_section_8_2_11_p_5">Humanization is only value for numbers, which are not likely to use the default format ("%s").</p>
26132 <div class="content">
26133 <h3 id="doc_section_8_2_12">
26134 <div class="self-section-number">
26135 <a href="#doc_section_8_2_12">8.2.12</a>Â </div>
26136 <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>
26138 <p id="doc_section_8_2_12_p_1">The message "Field has hn-* modifier but not 'h' modifier" can be caused by code like:</p>
26139 <div id="doc_figure_u.160"></div> <pre>
26140 xo_emit("{,hn-1000:value}", value);
26141 </pre> <p id="doc_section_8_2_12_p_3">This code should be replaced with code like:</p>
26142 <div id="doc_figure_u.161"></div> <pre>
26143 xo_emit("{h,hn-1000:value}", value);
26144 </pre> <p id="doc_section_8_2_12_p_5">The hn-* modifiers (hn-decimal, hn-space, hn-1000) are only valid for fields with the {h:} modifier.</p>
26146 <div class="content">
26147 <h3 id="doc_section_8_2_13">
26148 <div class="self-section-number">
26149 <a href="#doc_section_8_2_13">8.2.13</a>Â </div>
26150 <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>
26152 <p id="doc_section_8_2_13_p_1">The message "Value field must have a name (as content)")" can be caused by code like:</p>
26153 <div id="doc_figure_u.162"></div> <pre>
26154 xo_emit("{:/%s}", "value");
26155 </pre> <p id="doc_section_8_2_13_p_3">This code should be replaced with code like:</p>
26156 <div id="doc_figure_u.163"></div> <pre>
26157 xo_emit("{:tag-name/%s}", "value");
26158 </pre> <p id="doc_section_8_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>
26160 <div class="content">
26161 <h3 id="doc_section_8_2_14">
26162 <div class="self-section-number">
26163 <a href="#doc_section_8_2_14">8.2.14</a>Â </div>
26164 <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>
26166 <p id="doc_section_8_2_14_p_1">The message "Use hyphens, not underscores, for value field name" can be caused by code like:</p>
26167 <div id="doc_figure_u.164"></div> <pre>
26168 xo_emit("{:no_under_scores}", "bad");
26169 </pre> <p id="doc_section_8_2_14_p_3">This code should be replaced with code like:</p>
26170 <div id="doc_figure_u.165"></div> <pre>
26171 xo_emit("{:no-under-scores}", "bad");
26172 </pre> <p id="doc_section_8_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>
26174 <div class="content">
26175 <h3 id="doc_section_8_2_15">
26176 <div class="self-section-number">
26177 <a href="#doc_section_8_2_15">8.2.15</a>Â </div>
26178 <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>
26180 <p id="doc_section_8_2_15_p_1">The message "Value field name cannot start with digit" can be caused by code like:</p>
26181 <div id="doc_figure_u.166"></div> <pre>
26182 xo_emit("{:10-gig/}");
26183 </pre> <p id="doc_section_8_2_15_p_3">This code should be replaced with code like:</p>
26184 <div id="doc_figure_u.167"></div> <pre>
26185 xo_emit("{:ten-gig/}");
26186 </pre> <p id="doc_section_8_2_15_p_5">XML element names cannot start with a digit.</p>
26188 <div class="content">
26189 <h3 id="doc_section_8_2_16">
26190 <div class="self-section-number">
26191 <a href="#doc_section_8_2_16">8.2.16</a>Â </div>
26192 <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>
26194 <p id="doc_section_8_2_16_p_1">The message "Value field name should be lower case" can be caused by code like:</p>
26195 <div id="doc_figure_u.168"></div> <pre>
26196 xo_emit("{:WHY-ARE-YOU-SHOUTING}", "NO REASON");
26197 </pre> <p id="doc_section_8_2_16_p_3">This code should be replaced with code like:</p>
26198 <div id="doc_figure_u.169"></div> <pre>
26199 xo_emit("{:why-are-you-shouting}", "no reason");
26200 </pre> <p id="doc_section_8_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>
26202 <div class="content">
26203 <h3 id="doc_section_8_2_17">
26204 <div class="self-section-number">
26205 <a href="#doc_section_8_2_17">8.2.17</a>Â </div>
26206 <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>
26208 <p id="doc_section_8_2_17_p_1">The message "Value field name should be longer than two characters" can be caused by code like:</p>
26209 <div id="doc_figure_u.170"></div> <pre>
26210 xo_emit("{:x}", "mumble");
26211 </pre> <p id="doc_section_8_2_17_p_3">This code should be replaced with code like:</p>
26212 <div id="doc_figure_u.171"></div> <pre>
26213 xo_emit("{:something-meaningful}", "mumble");
26214 </pre> <p id="doc_section_8_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>
26216 <div class="content">
26217 <h3 id="doc_section_8_2_18">
26218 <div class="self-section-number">
26219 <a href="#doc_section_8_2_18">8.2.18</a>Â </div>
26220 <a id="value-field-name-contains-invalid-character" href="#value-field-name-contains-invalid-character">'Value field name contains invalid character'</a>
26222 <p id="doc_section_8_2_18_p_1">The message "Value field name contains invalid character" can be caused by code like:</p>
26223 <div id="doc_figure_u.172"></div> <pre>
26224 xo_emit("{:cost-in-$$/%u}", 15);
26225 </pre> <p id="doc_section_8_2_18_p_3">This code should be replaced with code like:</p>
26226 <div id="doc_figure_u.173"></div> <pre>
26227 xo_emit("{:cost-in-dollars/%u}", 15);
26228 </pre> <p id="doc_section_8_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>
26230 <div class="content">
26231 <h3 id="doc_section_8_2_19">
26232 <div class="self-section-number">
26233 <a href="#doc_section_8_2_19">8.2.19</a>Â </div>
26234 <a id="decoration-field-contains-invalid-character" href="#decoration-field-contains-invalid-character">'decoration field contains invalid character'</a>
26236 <p id="doc_section_8_2_19_p_1">The message "decoration field contains invalid character" can be caused by code like:</p>
26237 <div id="doc_figure_u.174"></div> <pre>
26238 xo_emit("{D:not good}");
26239 </pre> <p id="doc_section_8_2_19_p_3">This code should be replaced with code like:</p>
26240 <div id="doc_figure_u.175"></div> <pre>
26241 xo_emit("{D:((}{:good}{D:))}", "yes");
26242 </pre> <p id="doc_section_8_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>
26244 <div class="content">
26245 <h3 id="doc_section_8_2_20">
26246 <div class="self-section-number">
26247 <a href="#doc_section_8_2_20">8.2.20</a>Â </div>
26248 <a id="anchor-content-should-be-decimal-width" href="#anchor-content-should-be-decimal-width">'Anchor content should be decimal width'</a>
26250 <p id="doc_section_8_2_20_p_1">The message "Anchor content should be decimal width" can be caused by code like:</p>
26251 <div id="doc_figure_u.176"></div> <pre>
26252 xo_emit("{[:mumble}");
26253 </pre> <p id="doc_section_8_2_20_p_3">This code should be replaced with code like:</p>
26254 <div id="doc_figure_u.177"></div> <pre>
26256 </pre> <p id="doc_section_8_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>
26258 <div class="content">
26259 <h3 id="doc_section_8_2_21">
26260 <div class="self-section-number">
26261 <a href="#doc_section_8_2_21">8.2.21</a>Â </div>
26262 <a id="anchor-format-should-be-d" href="#anchor-format-should-be-d">'Anchor format should be "%d"'</a>
26264 <p id="doc_section_8_2_21_p_1">The message "Anchor format should be "%d"" can be caused by code like:</p>
26265 <div id="doc_figure_u.178"></div> <pre>
26266 xo_emit("{[:/%s}");
26267 </pre> <p id="doc_section_8_2_21_p_3">This code should be replaced with code like:</p>
26268 <div id="doc_figure_u.179"></div> <pre>
26269 xo_emit("{[:/%d}");
26270 </pre> <p id="doc_section_8_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>
26272 <div class="content">
26273 <h3 id="doc_section_8_2_22">
26274 <div class="self-section-number">
26275 <a href="#doc_section_8_2_22">8.2.22</a>Â </div>
26276 <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>
26278 <p id="doc_section_8_2_22_p_1">The message "Anchor cannot have both format and encoding format")" can be caused by code like:</p>
26279 <div id="doc_figure_u.180"></div> <pre>
26280 xo_emit("{[:32/%d}");
26281 </pre> <p id="doc_section_8_2_22_p_3">This code should be replaced with code like:</p>
26282 <div id="doc_figure_u.181"></div> <pre>
26284 </pre> <p id="doc_section_8_2_22_p_5">Anchors can have a static value or argument for the width, but cannot have both.</p>
26286 <div class="content">
26287 <h3 id="doc_section_8_2_23">
26288 <div class="self-section-number">
26289 <a href="#doc_section_8_2_23">8.2.23</a>Â </div>
26290 <a id="max-width-only-valid-for-strings" href="#max-width-only-valid-for-strings">'Max width only valid for strings'</a>
26292 <p id="doc_section_8_2_23_p_1">The message "Max width only valid for strings" can be caused by code like:</p>
26293 <div id="doc_figure_u.182"></div> <pre>
26294 xo_emit("{:tag/%2.4.6d}", 55);
26295 </pre> <p id="doc_section_8_2_23_p_3">This code should be replaced with code like:</p>
26296 <div id="doc_figure_u.183"></div> <pre>
26297 xo_emit("{:tag/%2.6d}", 55);
26298 </pre> <p id="doc_section_8_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>
26302 <hr class="noprint">
26303 <div class="content">
26304 <h1 id="doc_section_9" class="np">
26305 <div class="self-section-number">
26306 <a href="#doc_section_9">9_</a>Â </div>
26307 <a id="howtos-focused-directions" href="#howtos-focused-directions">Howtos: Focused Directions</a>
26309 <p id="doc_section_9_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>
26310 <p id="doc_section_9_p_2">Section Contents: </p>
26312 <li><a href="#howto-report-bugs" title="Howto: Report bugs">Section 9.1</a></li>
26313 <li><a href="#howto-install-libxo" title="Howto: Install libxo">Section 9.2</a></li>
26314 <li><a href="#howto-convert-command-line-applications" title="Howto: Convert command line applications">Section 9.3</a></li>
26315 <li><a href="#howto-use-xo-in-shell-scripts" title='Howto: Use "xo" in Shell Scripts'>Section 9.4</a></li>
26316 <li><a href="#howto-i18n" title="Howto: Internationalization (i18n)">Section 9.5</a></li>
26318 <div class="content">
26319 <h2 id="doc_section_9_1">
26320 <div class="self-section-number">
26321 <a href="#doc_section_9_1">9.1</a>Â </div>
26322 <a id="howto-report-bugs" href="#howto-report-bugs">Howto: Report bugs</a>
26324 <p id="doc_section_9_1_p_1">libxo uses github to track bugs or request enhancements. Please use the following URL:</p>
26325 <p id="doc_section_9_1_p_2"> <a href="https://github.com/Juniper/libxo/issues">https://github.com/Juniper/libxo/issues</a></p>
26327 <div class="content">
26328 <h2 id="doc_section_9_2">
26329 <div class="self-section-number">
26330 <a href="#doc_section_9_2">9.2</a>Â </div>
26331 <a id="howto-install-libxo" href="#howto-install-libxo">Howto: Install libxo</a>
26333 <p id="doc_section_9_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>
26334 <p id="doc_section_9_2_p_2"> <a href="https://github.com/Juniper/libxo/releases">https://github.com/Juniper/libxo/releases</a></p>
26335 <p id="doc_section_9_2_p_3">After downloading and untarring the source code, building involves the following steps:</p>
26336 <div id="doc_figure_u.184"></div> <pre>
26343 </pre> <p id="doc_section_9_2_p_5">libxo uses a distinct "build" directory to keep generated files separated from source files.</p>
26344 <p id="doc_section_9_2_p_6">Use "../configure --help" to display available configuration options, which include the following:</p>
26345 <div id="doc_figure_u.185"></div> <pre>
26346 --enable-warnings Turn on compiler warnings
26347 --enable-debug Turn on debugging
26348 --enable-text-only Turn on text-only rendering
26349 --enable-printflike Enable use of GCC __printflike attribute
26350 --disable-libxo-options Turn off support for LIBXO_OPTIONS
26351 --with-gettext=PFX Specify location of gettext installation
26352 --with-libslax-prefix=PFX Specify location of libslax config
26353 </pre> <p id="doc_section_9_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>
26354 <p id="doc_section_9_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>
26355 <p id="doc_section_9_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>
26356 <p id="doc_section_9_2_p_11">libslax is not required by libxo; it contains the "oxtradoc" program used to format documentation.</p>
26357 <p id="doc_section_9_2_p_12">For additional information, see <a href="#building-libxo" title="Building libxo">Section 1.1.2</a>.</p>
26359 <div class="content">
26360 <h2 id="doc_section_9_3">
26361 <div class="self-section-number">
26362 <a href="#doc_section_9_3">9.3</a>Â </div>
26363 <a id="howto-convert-command-line-applications" href="#howto-convert-command-line-applications">Howto: Convert command line applications</a>
26365 <div id="doc_figure_u.186"></div> <pre>
26366 How do I convert an existing command line application?
26367 </pre> <p id="doc_section_9_3_p_2">There are three basic steps for converting command line application to use libxo.</p>
26368 <p id="doc_section_9_3_p_3"> </p>
26370 <li>Setting up the context</li>
26371 <li>Converting printf calls</li>
26372 <li>Creating hierarchy</li>
26373 <li>Converting error functions</li>
26375 <p id="doc_section_9_3_p_4">Section Contents: </p>
26377 <li><a href="#setting-up-the-context" title="Setting up the context">Section 9.3.1</a></li>
26378 <li><a href="#converting-printf-calls" title="Converting printf Calls">Section 9.3.2</a></li>
26379 <li><a href="#creating-hierarchy" title="Creating Hierarchy">Section 9.3.3</a></li>
26380 <li><a href="#converting-error-functions" title="Converting Error Functions">Section 9.3.4</a></li>
26382 <div class="content">
26383 <h3 id="doc_section_9_3_1">
26384 <div class="self-section-number">
26385 <a href="#doc_section_9_3_1">9.3.1</a>Â </div>
26386 <a id="setting-up-the-context" href="#setting-up-the-context">Setting up the context</a>
26388 <p id="doc_section_9_3_1_p_1">To use libxo, you'll need to include the "xo.h" header file in your source code files:</p>
26389 <div id="doc_figure_u.187"></div> <pre>
26390 #include <libxo/xo.h>
26391 </pre> <p id="doc_section_9_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 3.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>
26392 <div id="doc_figure_u.188"></div> <pre>
26393 int main (int argc, char **argv)
26395 argc = xo_parse_args(argc, argv);
26400 </pre> <p id="doc_section_9_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 3.1</a>). libxo provides the xo_finish_atexit function that is suitable for use with the atexit(3) function.</p>
26401 <div id="doc_figure_u.189"></div> <pre>
26402 atexit(xo_finish_atexit);
26404 <div class="content">
26405 <h3 id="doc_section_9_3_2">
26406 <div class="self-section-number">
26407 <a href="#doc_section_9_3_2">9.3.2</a>Â </div>
26408 <a id="converting-printf-calls" href="#converting-printf-calls">Converting printf Calls</a>
26410 <p id="doc_section_9_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>
26411 <div id="doc_figure_u.190"></div> <pre>
26412 printf("There are %d %s events\n", count, etype);
26413 xo_emit("There are {:count/%d} {:event} events\n", count, etype);
26414 </pre> <p id="doc_section_9_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>
26415 <p id="doc_section_9_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 2.2.1.6</a>).</p>
26416 <p id="doc_section_9_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>
26417 <div id="doc_figure_u.191"></div> <pre>
26418 printf("Statistics:\n");
26419 xo_emit("{T:Statistics}:\n");
26420 </pre> <p id="doc_section_9_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 2.2.1.1</a>).</p>
26421 <div id="doc_figure_u.192"></div> <pre>
26422 xo_emit("{C:bold}required{C:}\n");
26423 </pre> <p id="doc_section_9_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 2.2.1.10</a>).</p>
26424 <div id="doc_figure_u.193"></div> <pre>
26425 snprintf(buf, sizeof(buf), "(%u/%u/%u)", min, ave, max);
26426 printf("%30s", buf);
26428 xo_emit("{[:30}({:minimum/%u}/{:average/%u}/{:maximum/%u}{]:}",
26431 <div class="content">
26432 <h3 id="doc_section_9_3_3">
26433 <div class="self-section-number">
26434 <a href="#doc_section_9_3_3">9.3.3</a>Â </div>
26435 <a id="creating-hierarchy" href="#creating-hierarchy">Creating Hierarchy</a>
26437 <p id="doc_section_9_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>
26438 <div id="doc_figure_u.194"></div> <pre>
26439 printf("table %d\n", tnum);
26440 for (i = 0; i < tmax; i++) {
26441 printf(" %s %d\n", table[i].name, table[i].size);
26444 xo_emit("{T:/table %d}\n", tnum);
26445 xo_open_list("table");
26446 for (i = 0; i < tmax; i++) {
26447 xo_open_instance("table");
26448 xo_emit("{P: }{k:name} {:size/%d}\n",
26449 table[i].name, table[i].size);
26450 xo_close_instance("table");
26452 xo_close_list("table");
26453 </pre> <p id="doc_section_9_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>
26454 <p id="doc_section_9_3_3_p_4">Typically these developer looks for a "for" loop as an indication of where to put these calls.</p>
26455 <p id="doc_section_9_3_3_p_5">In addition, the open and close container functions allow for organization levels of hierarchy.</p>
26456 <div id="doc_figure_u.195"></div> <pre>
26457 printf("Paging information:\n");
26458 printf(" Free: %lu\n", free);
26459 printf(" Active: %lu\n", active);
26460 printf(" Inactive: %lu\n", inactive);
26462 xo_open_container("paging-information");
26463 xo_emit("{P: }{L:Free: }{:free/%lu}\n", free);
26464 xo_emit("{P: }{L:Active: }{:active/%lu}\n", active);
26465 xo_emit("{P: }{L:Inactive: }{:inactive/%lu}\n", inactive);
26466 xo_close_container("paging-information");
26468 <div class="content">
26469 <h3 id="doc_section_9_3_4">
26470 <div class="self-section-number">
26471 <a href="#doc_section_9_3_4">9.3.4</a>Â </div>
26472 <a id="converting-error-functions" href="#converting-error-functions">Converting Error Functions</a>
26474 <p id="doc_section_9_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>
26475 <div id="doc_figure_u.196"></div> <pre>
26476 err(1, "cannot open output file: %s", file);
26478 xo_err(1, "cannot open output file: %s", file);
26479 xo_emit_err(1, "cannot open output file: {:filename}", file);
26482 <div class="content"><h2 id="doc_section_9_4">
26483 <div class="self-section-number">
26484 <a href="#doc_section_9_4">9.4</a>Â </div>
26485 <a id="howto-use-xo-in-shell-scripts" href="#howto-use-xo-in-shell-scripts">Howto: Use "xo" in Shell Scripts</a>
26487 <div class="content">
26488 <h2 id="doc_section_9_5">
26489 <div class="self-section-number">
26490 <a href="#doc_section_9_5">9.5</a>Â </div>
26491 <a id="howto-i18n" href="#howto-i18n">Howto: Internationalization (i18n)</a>
26493 <div id="doc_figure_u.197"></div> <pre>
26494 How do I use libxo to support internationalization?
26495 </pre> <p id="doc_section_9_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>
26496 <p id="doc_section_9_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>
26497 <p id="doc_section_9_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 <text>" command, or an entire .pot can be translated using the "xopo -f <input> -o <output>" command.</p>
26498 <div id="doc_figure_u.198"></div> <pre>
26500 % xopo -s "There are {:count/%u} {:event/%.6s} events\n"
26501 There are {:count} {:event} events\n
26503 Recommended workflow:
26504 # Extract text messages
26505 xgettext --default-domain=foo --no-wrap \
26506 --add-comments --keyword=xo_emit --keyword=xo_emit_h \
26507 --keyword=xo_emit_warn -C -E -n --foreign-user \
26508 -o foo.pot.raw foo.c
26510 # Simplify format strings for libxo
26511 xopo -f foo.pot.raw -o foo.pot
26513 # For a new language, just copy the file
26514 cp foo.pot po/LC/my_lang/foo.po
26516 # For an existing language:
26517 msgmerge --no-wrap po/LC/my_lang/foo.po \
26518 foo.pot -o po/LC/my_lang/foo.po.new
26520 # Now the hard part: translate foo.po using tools
26521 # like poedit or emacs' po-mode
26523 # Compile the finished file; Use of msgfmt's "-v" option is
26524 # strongly encouraged, so that "fuzzy" entries are reported.
26525 msgfmt -v -o po/my_lang/LC_MESSAGES/foo.mo po/my_lang/foo.po
26527 # Install the .mo file
26528 sudo cp po/my_lang/LC_MESSAGES/foo.mo \
26529 /opt/local/share/locale/my_lang/LC_MESSAGE/
26530 </pre> <p id="doc_section_9_5_p_6">Once these steps are complete, you can use the "gettext" command to test the message catalog:</p>
26531 <div id="doc_figure_u.199"></div> <pre>
26532 gettext -d foo -e "some text"
26533 </pre> <p id="doc_section_9_5_p_8">Section Contents: </p>
26534 <ul><li><a href="#i18n-and-xo_emit" title="i18n and xo_emit">Section 9.5.1</a></li></ul>
26535 <div class="content">
26536 <h3 id="doc_section_9_5_1">
26537 <div class="self-section-number">
26538 <a href="#doc_section_9_5_1">9.5.1</a>Â </div>
26539 <a id="i18n-and-xo_emit" href="#i18n-and-xo_emit">i18n and xo_emit</a>
26541 <p id="doc_section_9_5_1_p_1">There are three features used in libxo used to support i18n:</p>
26542 <p id="doc_section_9_5_1_p_2"> </p>
26544 <li>The "{G:}" role looks for a translation of the format string.</li>
26545 <li>The "{g:}" modifier looks for a translation of the field.</li>
26546 <li>The "{p:}" modifier looks for a pluralized version of the field.</li>
26548 <p id="doc_section_9_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>
26549 <div id="doc_figure_u.200"></div> <pre>
26550 printf(gettext("Received %zu %s from {g:server} server\n"),
26551 counter, ngettext("byte", "bytes", counter),
26554 xo_emit("{G:}Received {:received/%zu} {Ngp:byte,bytes} "
26555 "from {g:server} server\n", counter, "web");
26556 </pre> <p id="doc_section_9_5_1_p_5">libxo will see the "{G:}" role and will first simplify the format string, removing field formats and modifiers.</p>
26557 <div id="doc_figure_u.201"></div> <pre>
26558 "Received {:received} {N:byte,bytes} from {:server} server\n"
26559 </pre> <p id="doc_section_9_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>
26560 <div id="doc_figure_u.202"></div> <pre>
26561 "Eceivedray {:received} {N:byte,bytes} omfray "
26562 "{:server} erversay\n"
26563 </pre> <p id="doc_section_9_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>
26564 <p id="doc_section_9_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>
26565 <p id="doc_section_9_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>
26566 <p id="doc_section_9_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>
26567 <div id="doc_figure_u.203"></div> <pre>
26568 printf(dgettext("dns", "Host %s not found: %d(%s)\n"),
26569 name, errno, dgettext("strerror", strerror(errno)));
26571 xo_emit("{G:dns}Host {:hostname} not found: "
26572 "%d({G:strerror}{g:%m})\n", name, errno);
26576 <hr class="noprint">
26577 <div class="content">
26578 <h1 id="doc_section_10" class="np">
26579 <div class="self-section-number">
26580 <a href="#doc_section_10">10_</a>Â </div>
26581 <a id="examples" href="#examples">Examples</a>
26583 <p id="doc_section_10_p_1">Section Contents: </p>
26584 <ul><li><a href="#unit-test" title="Unit Test">Section 10.1</a></li></ul>
26585 <div class="content">
26586 <h2 id="doc_section_10_1">
26587 <div class="self-section-number">
26588 <a href="#doc_section_10_1">10.1</a>Â </div>
26589 <a id="unit-test" href="#unit-test">Unit Test</a>
26591 <p id="doc_section_10_1_p_1">Here is the unit test example:</p>
26592 <div id="doc_figure_u.204"></div> <pre>
26594 main (int argc, char **argv)
26596 static char base_grocery[] = "GRO";
26597 static char base_hardware[] = "HRD";
26599 const char *i_title;
26603 const char *i_sku_base;
26606 struct item list[] = {
26607 { "gum", 1412, 54, 10, base_grocery, 415 },
26608 { "rope", 85, 4, 2, base_hardware, 212 },
26609 { "ladder", 0, 2, 1, base_hardware, 517 },
26610 { "bolt", 4123, 144, 42, base_hardware, 632 },
26611 { "water", 17, 14, 2, base_grocery, 2331 },
26612 { NULL, 0, 0, 0, NULL, 0 }
26614 struct item list2[] = {
26615 { "fish", 1321, 45, 1, base_grocery, 533 },
26618 xo_info_t info[] = {
26619 { "in-stock", "number", "Number of items in stock" },
26620 { "name", "string", "Name of the item" },
26621 { "on-order", "number", "Number of items on order" },
26622 { "sku", "string", "Stock Keeping Unit" },
26623 { "sold", "number", "Number of items sold" },
26624 { NULL, NULL, NULL },
26626 int info_count = (sizeof(info) / sizeof(info[0])) - 1;
26628 argc = xo_parse_args(argc, argv);
26630 exit(EXIT_FAILURE);
26632 xo_set_info(NULL, info, info_count);
26634 xo_open_container_h(NULL, "top");
26636 xo_open_container("data");
26637 xo_open_list("item");
26639 for (ip = list; ip->i_title; ip++) {
26640 xo_open_instance("item");
26642 xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title);
26643 xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n",
26644 ip->i_sold, ip->i_sold ? ".0" : "");
26645 xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\n",
26647 xo_emit("{P: }{Lwc:On order}{:on-order/%u}\n",
26649 xo_emit("{P: }{L:SKU}: {q:sku/%s-000-%u}\n",
26650 ip->i_sku_base, ip->i_sku_num);
26652 xo_close_instance("item");
26655 xo_close_list("item");
26656 xo_close_container("data");
26658 xo_open_container("data");
26659 xo_open_list("item");
26661 for (ip = list2; ip->i_title; ip++) {
26662 xo_open_instance("item");
26664 xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
26665 xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n",
26666 ip->i_sold, ip->i_sold ? ".0" : "");
26667 xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\n",
26669 xo_emit("{P: }{Lwc:On order}{:on-order/%u}\n",
26671 xo_emit("{P: }{L:SKU}: {q:sku/%s-000-%u}\n",
26672 ip->i_sku_base, ip->i_sku_num);
26674 xo_close_instance("item");
26677 xo_close_list("item");
26678 xo_close_container("data");
26680 xo_close_container_h(NULL, "top");
26684 </pre> <p id="doc_section_10_1_p_3">Text output:</p>
26685 <div id="doc_figure_u.205"></div> <pre>
26686 % ./testxo --libxo text
26717 </pre> <p id="doc_section_10_1_p_5">JSON output:</p>
26718 <div id="doc_figure_u.206"></div> <pre>
26719 % ./testxo --libxo json,pretty
26728 "sku": "GRO-000-415"
26735 "sku": "HRD-000-212"
26742 "sku": "HRD-000-517"
26749 "sku": "HRD-000-632"
26756 "sku": "GRO-000-2331"
26767 "sku": "GRO-000-533"
26772 </pre> <p id="doc_section_10_1_p_7">XML output:</p>
26773 <div id="doc_figure_u.207"></div> <pre>
26774 % ./testxo --libxo pretty,xml
26778 <name>gum</name>
26779 <sold>1412.0</sold>
26780 <in-stock>54</in-stock>
26781 <on-order>10</on-order>
26782 <sku>GRO-000-415</sku>
26785 <name>rope</name>
26786 <sold>85.0</sold>
26787 <in-stock>4</in-stock>
26788 <on-order>2</on-order>
26789 <sku>HRD-000-212</sku>
26792 <name>ladder</name>
26793 <sold>0</sold>
26794 <in-stock>2</in-stock>
26795 <on-order>1</on-order>
26796 <sku>HRD-000-517</sku>
26799 <name>bolt</name>
26800 <sold>4123.0</sold>
26801 <in-stock>144</in-stock>
26802 <on-order>42</on-order>
26803 <sku>HRD-000-632</sku>
26806 <name>water</name>
26807 <sold>17.0</sold>
26808 <in-stock>14</in-stock>
26809 <on-order>2</on-order>
26810 <sku>GRO-000-2331</sku>
26815 <name>fish</name>
26816 <sold>1321.0</sold>
26817 <in-stock>45</in-stock>
26818 <on-order>1</on-order>
26819 <sku>GRO-000-533</sku>
26823 </pre> <p id="doc_section_10_1_p_9">HMTL output:</p>
26824 <div id="doc_figure_u.208"></div> <pre>
26825 % ./testxo --libxo pretty,html
26826 <div class="line">
26827 <div class="label">Item</div>
26828 <div class="text"> '</div>
26829 <div class="data" data-tag="name">gum</div>
26830 <div class="text">':</div>
26832 <div class="line">
26833 <div class="padding"> </div>
26834 <div class="label">Total sold</div>
26835 <div class="text">: </div>
26836 <div class="data" data-tag="sold">1412.0</div>
26838 <div class="line">
26839 <div class="padding"> </div>
26840 <div class="label">In stock</div>
26841 <div class="decoration">:</div>
26842 <div class="padding"> </div>
26843 <div class="data" data-tag="in-stock">54</div>
26845 <div class="line">
26846 <div class="padding"> </div>
26847 <div class="label">On order</div>
26848 <div class="decoration">:</div>
26849 <div class="padding"> </div>
26850 <div class="data" data-tag="on-order">10</div>
26852 <div class="line">
26853 <div class="padding"> </div>
26854 <div class="label">SKU</div>
26855 <div class="text">: </div>
26856 <div class="data" data-tag="sku">GRO-000-415</div>
26858 <div class="line">
26859 <div class="label">Item</div>
26860 <div class="text"> '</div>
26861 <div class="data" data-tag="name">rope</div>
26862 <div class="text">':</div>
26864 <div class="line">
26865 <div class="padding"> </div>
26866 <div class="label">Total sold</div>
26867 <div class="text">: </div>
26868 <div class="data" data-tag="sold">85.0</div>
26870 <div class="line">
26871 <div class="padding"> </div>
26872 <div class="label">In stock</div>
26873 <div class="decoration">:</div>
26874 <div class="padding"> </div>
26875 <div class="data" data-tag="in-stock">4</div>
26877 <div class="line">
26878 <div class="padding"> </div>
26879 <div class="label">On order</div>
26880 <div class="decoration">:</div>
26881 <div class="padding"> </div>
26882 <div class="data" data-tag="on-order">2</div>
26884 <div class="line">
26885 <div class="padding"> </div>
26886 <div class="label">SKU</div>
26887 <div class="text">: </div>
26888 <div class="data" data-tag="sku">HRD-000-212</div>
26890 <div class="line">
26891 <div class="label">Item</div>
26892 <div class="text"> '</div>
26893 <div class="data" data-tag="name">ladder</div>
26894 <div class="text">':</div>
26896 <div class="line">
26897 <div class="padding"> </div>
26898 <div class="label">Total sold</div>
26899 <div class="text">: </div>
26900 <div class="data" data-tag="sold">0</div>
26902 <div class="line">
26903 <div class="padding"> </div>
26904 <div class="label">In stock</div>
26905 <div class="decoration">:</div>
26906 <div class="padding"> </div>
26907 <div class="data" data-tag="in-stock">2</div>
26909 <div class="line">
26910 <div class="padding"> </div>
26911 <div class="label">On order</div>
26912 <div class="decoration">:</div>
26913 <div class="padding"> </div>
26914 <div class="data" data-tag="on-order">1</div>
26916 <div class="line">
26917 <div class="padding"> </div>
26918 <div class="label">SKU</div>
26919 <div class="text">: </div>
26920 <div class="data" data-tag="sku">HRD-000-517</div>
26922 <div class="line">
26923 <div class="label">Item</div>
26924 <div class="text"> '</div>
26925 <div class="data" data-tag="name">bolt</div>
26926 <div class="text">':</div>
26928 <div class="line">
26929 <div class="padding"> </div>
26930 <div class="label">Total sold</div>
26931 <div class="text">: </div>
26932 <div class="data" data-tag="sold">4123.0</div>
26934 <div class="line">
26935 <div class="padding"> </div>
26936 <div class="label">In stock</div>
26937 <div class="decoration">:</div>
26938 <div class="padding"> </div>
26939 <div class="data" data-tag="in-stock">144</div>
26941 <div class="line">
26942 <div class="padding"> </div>
26943 <div class="label">On order</div>
26944 <div class="decoration">:</div>
26945 <div class="padding"> </div>
26946 <div class="data" data-tag="on-order">42</div>
26948 <div class="line">
26949 <div class="padding"> </div>
26950 <div class="label">SKU</div>
26951 <div class="text">: </div>
26952 <div class="data" data-tag="sku">HRD-000-632</div>
26954 <div class="line">
26955 <div class="label">Item</div>
26956 <div class="text"> '</div>
26957 <div class="data" data-tag="name">water</div>
26958 <div class="text">':</div>
26960 <div class="line">
26961 <div class="padding"> </div>
26962 <div class="label">Total sold</div>
26963 <div class="text">: </div>
26964 <div class="data" data-tag="sold">17.0</div>
26966 <div class="line">
26967 <div class="padding"> </div>
26968 <div class="label">In stock</div>
26969 <div class="decoration">:</div>
26970 <div class="padding"> </div>
26971 <div class="data" data-tag="in-stock">14</div>
26973 <div class="line">
26974 <div class="padding"> </div>
26975 <div class="label">On order</div>
26976 <div class="decoration">:</div>
26977 <div class="padding"> </div>
26978 <div class="data" data-tag="on-order">2</div>
26980 <div class="line">
26981 <div class="padding"> </div>
26982 <div class="label">SKU</div>
26983 <div class="text">: </div>
26984 <div class="data" data-tag="sku">GRO-000-2331</div>
26986 <div class="line">
26987 <div class="label">Item</div>
26988 <div class="text"> '</div>
26989 <div class="data" data-tag="name">fish</div>
26990 <div class="text">':</div>
26992 <div class="line">
26993 <div class="padding"> </div>
26994 <div class="label">Total sold</div>
26995 <div class="text">: </div>
26996 <div class="data" data-tag="sold">1321.0</div>
26998 <div class="line">
26999 <div class="padding"> </div>
27000 <div class="label">In stock</div>
27001 <div class="decoration">:</div>
27002 <div class="padding"> </div>
27003 <div class="data" data-tag="in-stock">45</div>
27005 <div class="line">
27006 <div class="padding"> </div>
27007 <div class="label">On order</div>
27008 <div class="decoration">:</div>
27009 <div class="padding"> </div>
27010 <div class="data" data-tag="on-order">1</div>
27012 <div class="line">
27013 <div class="padding"> </div>
27014 <div class="label">SKU</div>
27015 <div class="text">: </div>
27016 <div class="data" data-tag="sku">GRO-000-533</div>
27018 </pre> <p id="doc_section_10_1_p_11">HTML output with xpath and info flags:</p>
27019 <div id="doc_figure_u.209"></div> <pre>
27020 % ./testxo --libxo pretty,html,xpath,info
27021 <div class="line">
27022 <div class="label">Item</div>
27023 <div class="text"> '</div>
27024 <div class="data" data-tag="name"
27025 data-xpath="/top/data/item/name" data-type="string"
27026 data-help="Name of the item">gum</div>
27027 <div class="text">':</div>
27029 <div class="line">
27030 <div class="padding"> </div>
27031 <div class="label">Total sold</div>
27032 <div class="text">: </div>
27033 <div class="data" data-tag="sold"
27034 data-xpath="/top/data/item/sold" data-type="number"
27035 data-help="Number of items sold">1412.0</div>
27037 <div class="line">
27038 <div class="padding"> </div>
27039 <div class="label">In stock</div>
27040 <div class="decoration">:</div>
27041 <div class="padding"> </div>
27042 <div class="data" data-tag="in-stock"
27043 data-xpath="/top/data/item/in-stock" data-type="number"
27044 data-help="Number of items in stock">54</div>
27046 <div class="line">
27047 <div class="padding"> </div>
27048 <div class="label">On order</div>
27049 <div class="decoration">:</div>
27050 <div class="padding"> </div>
27051 <div class="data" data-tag="on-order"
27052 data-xpath="/top/data/item/on-order" data-type="number"
27053 data-help="Number of items on order">10</div>
27055 <div class="line">
27056 <div class="padding"> </div>
27057 <div class="label">SKU</div>
27058 <div class="text">: </div>
27059 <div class="data" data-tag="sku"
27060 data-xpath="/top/data/item/sku" data-type="string"
27061 data-help="Stock Keeping Unit">GRO-000-415</div>
27063 <div class="line">
27064 <div class="label">Item</div>
27065 <div class="text"> '</div>
27066 <div class="data" data-tag="name"
27067 data-xpath="/top/data/item/name" data-type="string"
27068 data-help="Name of the item">rope</div>
27069 <div class="text">':</div>
27071 <div class="line">
27072 <div class="padding"> </div>
27073 <div class="label">Total sold</div>
27074 <div class="text">: </div>
27075 <div class="data" data-tag="sold"
27076 data-xpath="/top/data/item/sold" data-type="number"
27077 data-help="Number of items sold">85.0</div>
27079 <div class="line">
27080 <div class="padding"> </div>
27081 <div class="label">In stock</div>
27082 <div class="decoration">:</div>
27083 <div class="padding"> </div>
27084 <div class="data" data-tag="in-stock"
27085 data-xpath="/top/data/item/in-stock" data-type="number"
27086 data-help="Number of items in stock">4</div>
27088 <div class="line">
27089 <div class="padding"> </div>
27090 <div class="label">On order</div>
27091 <div class="decoration">:</div>
27092 <div class="padding"> </div>
27093 <div class="data" data-tag="on-order"
27094 data-xpath="/top/data/item/on-order" data-type="number"
27095 data-help="Number of items on order">2</div>
27097 <div class="line">
27098 <div class="padding"> </div>
27099 <div class="label">SKU</div>
27100 <div class="text">: </div>
27101 <div class="data" data-tag="sku"
27102 data-xpath="/top/data/item/sku" data-type="string"
27103 data-help="Stock Keeping Unit">HRD-000-212</div>
27105 <div class="line">
27106 <div class="label">Item</div>
27107 <div class="text"> '</div>
27108 <div class="data" data-tag="name"
27109 data-xpath="/top/data/item/name" data-type="string"
27110 data-help="Name of the item">ladder</div>
27111 <div class="text">':</div>
27113 <div class="line">
27114 <div class="padding"> </div>
27115 <div class="label">Total sold</div>
27116 <div class="text">: </div>
27117 <div class="data" data-tag="sold"
27118 data-xpath="/top/data/item/sold" data-type="number"
27119 data-help="Number of items sold">0</div>
27121 <div class="line">
27122 <div class="padding"> </div>
27123 <div class="label">In stock</div>
27124 <div class="decoration">:</div>
27125 <div class="padding"> </div>
27126 <div class="data" data-tag="in-stock"
27127 data-xpath="/top/data/item/in-stock" data-type="number"
27128 data-help="Number of items in stock">2</div>
27130 <div class="line">
27131 <div class="padding"> </div>
27132 <div class="label">On order</div>
27133 <div class="decoration">:</div>
27134 <div class="padding"> </div>
27135 <div class="data" data-tag="on-order"
27136 data-xpath="/top/data/item/on-order" data-type="number"
27137 data-help="Number of items on order">1</div>
27139 <div class="line">
27140 <div class="padding"> </div>
27141 <div class="label">SKU</div>
27142 <div class="text">: </div>
27143 <div class="data" data-tag="sku"
27144 data-xpath="/top/data/item/sku" data-type="string"
27145 data-help="Stock Keeping Unit">HRD-000-517</div>
27147 <div class="line">
27148 <div class="label">Item</div>
27149 <div class="text"> '</div>
27150 <div class="data" data-tag="name"
27151 data-xpath="/top/data/item/name" data-type="string"
27152 data-help="Name of the item">bolt</div>
27153 <div class="text">':</div>
27155 <div class="line">
27156 <div class="padding"> </div>
27157 <div class="label">Total sold</div>
27158 <div class="text">: </div>
27159 <div class="data" data-tag="sold"
27160 data-xpath="/top/data/item/sold" data-type="number"
27161 data-help="Number of items sold">4123.0</div>
27163 <div class="line">
27164 <div class="padding"> </div>
27165 <div class="label">In stock</div>
27166 <div class="decoration">:</div>
27167 <div class="padding"> </div>
27168 <div class="data" data-tag="in-stock"
27169 data-xpath="/top/data/item/in-stock" data-type="number"
27170 data-help="Number of items in stock">144</div>
27172 <div class="line">
27173 <div class="padding"> </div>
27174 <div class="label">On order</div>
27175 <div class="decoration">:</div>
27176 <div class="padding"> </div>
27177 <div class="data" data-tag="on-order"
27178 data-xpath="/top/data/item/on-order" data-type="number"
27179 data-help="Number of items on order">42</div>
27181 <div class="line">
27182 <div class="padding"> </div>
27183 <div class="label">SKU</div>
27184 <div class="text">: </div>
27185 <div class="data" data-tag="sku"
27186 data-xpath="/top/data/item/sku" data-type="string"
27187 data-help="Stock Keeping Unit">HRD-000-632</div>
27189 <div class="line">
27190 <div class="label">Item</div>
27191 <div class="text"> '</div>
27192 <div class="data" data-tag="name"
27193 data-xpath="/top/data/item/name" data-type="string"
27194 data-help="Name of the item">water</div>
27195 <div class="text">':</div>
27197 <div class="line">
27198 <div class="padding"> </div>
27199 <div class="label">Total sold</div>
27200 <div class="text">: </div>
27201 <div class="data" data-tag="sold"
27202 data-xpath="/top/data/item/sold" data-type="number"
27203 data-help="Number of items sold">17.0</div>
27205 <div class="line">
27206 <div class="padding"> </div>
27207 <div class="label">In stock</div>
27208 <div class="decoration">:</div>
27209 <div class="padding"> </div>
27210 <div class="data" data-tag="in-stock"
27211 data-xpath="/top/data/item/in-stock" data-type="number"
27212 data-help="Number of items in stock">14</div>
27214 <div class="line">
27215 <div class="padding"> </div>
27216 <div class="label">On order</div>
27217 <div class="decoration">:</div>
27218 <div class="padding"> </div>
27219 <div class="data" data-tag="on-order"
27220 data-xpath="/top/data/item/on-order" data-type="number"
27221 data-help="Number of items on order">2</div>
27223 <div class="line">
27224 <div class="padding"> </div>
27225 <div class="label">SKU</div>
27226 <div class="text">: </div>
27227 <div class="data" data-tag="sku"
27228 data-xpath="/top/data/item/sku" data-type="string"
27229 data-help="Stock Keeping Unit">GRO-000-2331</div>
27231 <div class="line">
27232 <div class="label">Item</div>
27233 <div class="text"> '</div>
27234 <div class="data" data-tag="name"
27235 data-xpath="/top/data/item/name" data-type="string"
27236 data-help="Name of the item">fish</div>
27237 <div class="text">':</div>
27239 <div class="line">
27240 <div class="padding"> </div>
27241 <div class="label">Total sold</div>
27242 <div class="text">: </div>
27243 <div class="data" data-tag="sold"
27244 data-xpath="/top/data/item/sold" data-type="number"
27245 data-help="Number of items sold">1321.0</div>
27247 <div class="line">
27248 <div class="padding"> </div>
27249 <div class="label">In stock</div>
27250 <div class="decoration">:</div>
27251 <div class="padding"> </div>
27252 <div class="data" data-tag="in-stock"
27253 data-xpath="/top/data/item/in-stock" data-type="number"
27254 data-help="Number of items in stock">45</div>
27256 <div class="line">
27257 <div class="padding"> </div>
27258 <div class="label">On order</div>
27259 <div class="decoration">:</div>
27260 <div class="padding"> </div>
27261 <div class="data" data-tag="on-order"
27262 data-xpath="/top/data/item/on-order" data-type="number"
27263 data-help="Number of items on order">1</div>
27265 <div class="line">
27266 <div class="padding"> </div>
27267 <div class="label">SKU</div>
27268 <div class="text">: </div>
27269 <div class="data" data-tag="sku"
27270 data-xpath="/top/data/item/sku" data-type="string"
27271 data-help="Stock Keeping Unit">GRO-000-533</div>
27275 <div class="content"></div>
27276 <hr class="noprint">
27277 <div class="content">
27278 <h1 id="doc.authors" class="np"><a href="#doc.authors">Author's Address</a></h1>
27279 <address class="vcard">
27280 <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>