From a1eb34f420663e354e736b94caf82bf04e30d6e6 Mon Sep 17 00:00:00 2001 From: Than Ngo Date: Fri, 7 Feb 2025 09:18:49 +0100 Subject: [PATCH] Resolves: RHEL-78141, CVE-2020-11023, CVE-2020-11022 --- ...jquery-CVE-2020-11023-CVE-2020-11022.patch | 15773 ++++++++++++++++ doxygen.spec | 15 +- 2 files changed, 15783 insertions(+), 5 deletions(-) create mode 100644 doxygen-1.8.14-jquery-CVE-2020-11023-CVE-2020-11022.patch diff --git a/doxygen-1.8.14-jquery-CVE-2020-11023-CVE-2020-11022.patch b/doxygen-1.8.14-jquery-CVE-2020-11023-CVE-2020-11022.patch new file mode 100644 index 0000000..e1ccebd --- /dev/null +++ b/doxygen-1.8.14-jquery-CVE-2020-11023-CVE-2020-11022.patch @@ -0,0 +1,15773 @@ +Binary files doxygen-1.8.14.orig/jquery/._jquery-3.6.0.min.js and doxygen-1.8.14/jquery/._jquery-3.6.0.min.js differ +diff -Nur doxygen-1.8.14.orig/jquery/Makefile doxygen-1.8.14/jquery/Makefile +--- doxygen-1.8.14.orig/jquery/Makefile 2017-10-31 20:36:00.000000000 +0100 ++++ doxygen-1.8.14/jquery/Makefile 2021-06-27 13:30:43.000000000 +0200 +@@ -1,34 +1,27 @@ +-JQUERY_VERSION = 1.7.1 +-JQUERY_UI_VERSION = 1.8.18 +-HASHCHANGE_VERSION = 1.3 +-SCROLL_VERSION = 1.4.2 +-POWERTIP_VERSION = 1.2.0 ++JQUERY_VERSION = 3.6.0 ++JQUERY_UI_VERSION = 1.12.1 ++SCROLL_VERSION = 2.1.2 ++POWERTIP_VERSION = 1.3.1 + TOUCHPUNCH_VERSION = 0.2.3 +-SMARTMENUS_VERSION = 1.0.0 ++SMARTMENUS_VERSION = 1.1.0 + +-MINIFIER ?= /usr/local/bin/yuicompressor-2.4.7 +-SCRIPTS = jquery-$(JQUERY_VERSION).js \ +- jquery.ui-$(JQUERY_UI_VERSION).core.js \ +- jquery.ui-$(JQUERY_UI_VERSION).widget.js \ +- jquery.ui-$(JQUERY_UI_VERSION).mouse.js \ +- jquery.ui-$(JQUERY_UI_VERSION).resizable.js \ +- jquery.ba-$(HASHCHANGE_VERSION)-hashchange.js \ +- jquery.scrollTo-$(SCROLL_VERSION).js \ +- jquery.powertip-$(POWERTIP_VERSION).js \ +- jquery.ui-$(TOUCHPUNCH_VERSION).touch-punch.js \ +- jquery.smartmenus-$(SMARTMENUS_VERSION).js ++MINIFIER ?= /usr/local/bin/yuicompressor-2.4.8 ++SCRIPTS = jquery-$(JQUERY_VERSION).min.js \ ++ jquery.ui-$(JQUERY_UI_VERSION).min.js \ ++ jquery.scrollTo-$(SCROLL_VERSION).min.js \ ++ jquery.powertip-$(POWERTIP_VERSION).mod.min.js \ ++ jquery.ui.touch-punch-$(TOUCHPUNCH_VERSION).min.js \ ++ jquery.smartmenus-$(SMARTMENUS_VERSION).min.js + RESULTS = jquery.js doxmenu-min.css + +-SCRIPTS_MIN = $(SCRIPTS:%.js=%-min.js) +- + all: $(RESULTS) + + install: $(RESULTS) + cp jquery.js ../templates/html/jquery.js + cp doxmenu-min.css ../templates/html/tabs.css + +-jquery.js: $(SCRIPTS_MIN) +- cat $(SCRIPTS_MIN) > jquery.js ++jquery.js: $(SCRIPTS) ++ cat $(SCRIPTS) > jquery.js + + doxmenu-min.css: sm-core-css.css \ + sass/sm-dox.scss \ +@@ -40,11 +33,6 @@ + java -jar $(MINIFIER).jar doxmenu.css > doxmenu-min.css + rm -f sm-dox.css doxmenu.css + +-scripts: $(SCRIPTS_MIN) +- + clean: +- rm -rf $(SCRIPTS_MIN) $(RESULTS) doxmenu.css .sass-cache jquery.js +- +-%-min.js: %.js +- java -jar $(MINIFIER).jar $^ > $@ ++ rm -rf $(RESULTS) doxmenu.css .sass-cache + +diff -Nur doxygen-1.8.14.orig/jquery/README doxygen-1.8.14/jquery/README +--- doxygen-1.8.14.orig/jquery/README 2017-10-31 20:36:00.000000000 +0100 ++++ doxygen-1.8.14/jquery/README 2021-06-27 13:30:36.000000000 +0200 +@@ -1,16 +1,20 @@ + Doxygen's jquery.js script is composed of minified versions of the following + packages: +-- jquery 1.7.1: http://jquery.com/download/ +-- jquery.ui 1.8.18: https://code.google.com/p/jquery-ui/downloads/list ++- jquery 3.6.0: https://jquery.com/download/ ++- jquery.ui 1.12.1: https://github.com/jquery/jquery-ui + modules required: +- - jquery.ui.core +- - jquery.ui.widget +- - jquery.ui.mouse +- - jquery.ui.resizable +-- jquery.hashchange: 1.3: http://benalman.com/projects/jquery-hashchange-plugin/ +-- jquery.scrollTo: 1.4.2: https://github.com/flesler/jquery.scrollTo +-- jquery.powertip: 1.2.0: http://stevenbenner.github.io/jquery-powertip/ +-- jquery.touchpunch: 0.2.3: http://touchpunch.furf.com/ +-- jquery.smartmenus: 1.0.0: http://www.smartmenus.org/ ++ - jquery.ui.core all ++ - jquery.ui.interactions resizable ++ - jquery.ui.widgets mouse ++- jquery.scrollTo: 2.1.2: https://github.com/flesler/jquery.scrollTo ++- jquery.powertip: 1.3.1: https://stevenbenner.github.io/jquery-powertip/ ++- jquery.touchpunch: 0.2.3: http://touchpunch.furf.com/ + fix for issue 303 ++- jquery.smartmenus: 1.1.0: https://www.smartmenus.org/ + + The Makefile will built the jquery.js files used by doxygen. ++ ++Note that there is a performance issue in the default powertip version. ++See https://github.com/stevenbenner/jquery-powertip/issues/178 ++Until that is fixed a modified version is shipped with doxygen. This version ++removes the "destroy" functionality which was not used by doxygen anyway. ++ +diff -Nur doxygen-1.8.14.orig/jquery/jquery-1.7.1.js doxygen-1.8.14/jquery/jquery-1.7.1.js +--- doxygen-1.8.14.orig/jquery/jquery-1.7.1.js 2017-10-31 20:36:00.000000000 +0100 ++++ doxygen-1.8.14/jquery/jquery-1.7.1.js 1970-01-01 01:00:00.000000000 +0100 +@@ -1,9266 +0,0 @@ +-/*! +- * jQuery JavaScript Library v1.7.1 +- * http://jquery.com/ +- * +- * Copyright 2011, John Resig +- * Dual licensed under the MIT or GPL Version 2 licenses. +- * http://jquery.org/license +- * +- * Includes Sizzle.js +- * http://sizzlejs.com/ +- * Copyright 2011, The Dojo Foundation +- * Released under the MIT, BSD, and GPL Licenses. +- * +- * Date: Mon Nov 21 21:11:03 2011 -0500 +- */ +-(function( window, undefined ) { +- +-// Use the correct document accordingly with window argument (sandbox) +-var document = window.document, +- navigator = window.navigator, +- location = window.location; +-var jQuery = (function() { +- +-// Define a local copy of jQuery +-var jQuery = function( selector, context ) { +- // The jQuery object is actually just the init constructor 'enhanced' +- return new jQuery.fn.init( selector, context, rootjQuery ); +- }, +- +- // Map over jQuery in case of overwrite +- _jQuery = window.jQuery, +- +- // Map over the $ in case of overwrite +- _$ = window.$, +- +- // A central reference to the root jQuery(document) +- rootjQuery, +- +- // A simple way to check for HTML strings or ID strings +- // Prioritize #id over to avoid XSS via location.hash (#9521) +- quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, +- +- // Check if a string has a non-whitespace character in it +- rnotwhite = /\S/, +- +- // Used for trimming whitespace +- trimLeft = /^\s+/, +- trimRight = /\s+$/, +- +- // Match a standalone tag +- rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, +- +- // JSON RegExp +- rvalidchars = /^[\],:{}\s]*$/, +- rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, +- rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, +- rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, +- +- // Useragent RegExp +- rwebkit = /(webkit)[ \/]([\w.]+)/, +- ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, +- rmsie = /(msie) ([\w.]+)/, +- rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, +- +- // Matches dashed string for camelizing +- rdashAlpha = /-([a-z]|[0-9])/ig, +- rmsPrefix = /^-ms-/, +- +- // Used by jQuery.camelCase as callback to replace() +- fcamelCase = function( all, letter ) { +- return ( letter + "" ).toUpperCase(); +- }, +- +- // Keep a UserAgent string for use with jQuery.browser +- userAgent = navigator.userAgent, +- +- // For matching the engine and version of the browser +- browserMatch, +- +- // The deferred used on DOM ready +- readyList, +- +- // The ready event handler +- DOMContentLoaded, +- +- // Save a reference to some core methods +- toString = Object.prototype.toString, +- hasOwn = Object.prototype.hasOwnProperty, +- push = Array.prototype.push, +- slice = Array.prototype.slice, +- trim = String.prototype.trim, +- indexOf = Array.prototype.indexOf, +- +- // [[Class]] -> type pairs +- class2type = {}; +- +-jQuery.fn = jQuery.prototype = { +- constructor: jQuery, +- init: function( selector, context, rootjQuery ) { +- var match, elem, ret, doc; +- +- // Handle $(""), $(null), or $(undefined) +- if ( !selector ) { +- return this; +- } +- +- // Handle $(DOMElement) +- if ( selector.nodeType ) { +- this.context = this[0] = selector; +- this.length = 1; +- return this; +- } +- +- // The body element only exists once, optimize finding it +- if ( selector === "body" && !context && document.body ) { +- this.context = document; +- this[0] = document.body; +- this.selector = selector; +- this.length = 1; +- return this; +- } +- +- // Handle HTML strings +- if ( typeof selector === "string" ) { +- // Are we dealing with HTML string or an ID? +- if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { +- // Assume that strings that start and end with <> are HTML and skip the regex check +- match = [ null, selector, null ]; +- +- } else { +- match = quickExpr.exec( selector ); +- } +- +- // Verify a match, and that no context was specified for #id +- if ( match && (match[1] || !context) ) { +- +- // HANDLE: $(html) -> $(array) +- if ( match[1] ) { +- context = context instanceof jQuery ? context[0] : context; +- doc = ( context ? context.ownerDocument || context : document ); +- +- // If a single string is passed in and it's a single tag +- // just do a createElement and skip the rest +- ret = rsingleTag.exec( selector ); +- +- if ( ret ) { +- if ( jQuery.isPlainObject( context ) ) { +- selector = [ document.createElement( ret[1] ) ]; +- jQuery.fn.attr.call( selector, context, true ); +- +- } else { +- selector = [ doc.createElement( ret[1] ) ]; +- } +- +- } else { +- ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); +- selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; +- } +- +- return jQuery.merge( this, selector ); +- +- // HANDLE: $("#id") +- } else { +- elem = document.getElementById( match[2] ); +- +- // Check parentNode to catch when Blackberry 4.6 returns +- // nodes that are no longer in the document #6963 +- if ( elem && elem.parentNode ) { +- // Handle the case where IE and Opera return items +- // by name instead of ID +- if ( elem.id !== match[2] ) { +- return rootjQuery.find( selector ); +- } +- +- // Otherwise, we inject the element directly into the jQuery object +- this.length = 1; +- this[0] = elem; +- } +- +- this.context = document; +- this.selector = selector; +- return this; +- } +- +- // HANDLE: $(expr, $(...)) +- } else if ( !context || context.jquery ) { +- return ( context || rootjQuery ).find( selector ); +- +- // HANDLE: $(expr, context) +- // (which is just equivalent to: $(context).find(expr) +- } else { +- return this.constructor( context ).find( selector ); +- } +- +- // HANDLE: $(function) +- // Shortcut for document ready +- } else if ( jQuery.isFunction( selector ) ) { +- return rootjQuery.ready( selector ); +- } +- +- if ( selector.selector !== undefined ) { +- this.selector = selector.selector; +- this.context = selector.context; +- } +- +- return jQuery.makeArray( selector, this ); +- }, +- +- // Start with an empty selector +- selector: "", +- +- // The current version of jQuery being used +- jquery: "1.7.1", +- +- // The default length of a jQuery object is 0 +- length: 0, +- +- // The number of elements contained in the matched element set +- size: function() { +- return this.length; +- }, +- +- toArray: function() { +- return slice.call( this, 0 ); +- }, +- +- // Get the Nth element in the matched element set OR +- // Get the whole matched element set as a clean array +- get: function( num ) { +- return num == null ? +- +- // Return a 'clean' array +- this.toArray() : +- +- // Return just the object +- ( num < 0 ? this[ this.length + num ] : this[ num ] ); +- }, +- +- // Take an array of elements and push it onto the stack +- // (returning the new matched element set) +- pushStack: function( elems, name, selector ) { +- // Build a new jQuery matched element set +- var ret = this.constructor(); +- +- if ( jQuery.isArray( elems ) ) { +- push.apply( ret, elems ); +- +- } else { +- jQuery.merge( ret, elems ); +- } +- +- // Add the old object onto the stack (as a reference) +- ret.prevObject = this; +- +- ret.context = this.context; +- +- if ( name === "find" ) { +- ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; +- } else if ( name ) { +- ret.selector = this.selector + "." + name + "(" + selector + ")"; +- } +- +- // Return the newly-formed element set +- return ret; +- }, +- +- // Execute a callback for every element in the matched set. +- // (You can seed the arguments with an array of args, but this is +- // only used internally.) +- each: function( callback, args ) { +- return jQuery.each( this, callback, args ); +- }, +- +- ready: function( fn ) { +- // Attach the listeners +- jQuery.bindReady(); +- +- // Add the callback +- readyList.add( fn ); +- +- return this; +- }, +- +- eq: function( i ) { +- i = +i; +- return i === -1 ? +- this.slice( i ) : +- this.slice( i, i + 1 ); +- }, +- +- first: function() { +- return this.eq( 0 ); +- }, +- +- last: function() { +- return this.eq( -1 ); +- }, +- +- slice: function() { +- return this.pushStack( slice.apply( this, arguments ), +- "slice", slice.call(arguments).join(",") ); +- }, +- +- map: function( callback ) { +- return this.pushStack( jQuery.map(this, function( elem, i ) { +- return callback.call( elem, i, elem ); +- })); +- }, +- +- end: function() { +- return this.prevObject || this.constructor(null); +- }, +- +- // For internal use only. +- // Behaves like an Array's method, not like a jQuery method. +- push: push, +- sort: [].sort, +- splice: [].splice +-}; +- +-// Give the init function the jQuery prototype for later instantiation +-jQuery.fn.init.prototype = jQuery.fn; +- +-jQuery.extend = jQuery.fn.extend = function() { +- var options, name, src, copy, copyIsArray, clone, +- target = arguments[0] || {}, +- i = 1, +- length = arguments.length, +- deep = false; +- +- // Handle a deep copy situation +- if ( typeof target === "boolean" ) { +- deep = target; +- target = arguments[1] || {}; +- // skip the boolean and the target +- i = 2; +- } +- +- // Handle case when target is a string or something (possible in deep copy) +- if ( typeof target !== "object" && !jQuery.isFunction(target) ) { +- target = {}; +- } +- +- // extend jQuery itself if only one argument is passed +- if ( length === i ) { +- target = this; +- --i; +- } +- +- for ( ; i < length; i++ ) { +- // Only deal with non-null/undefined values +- if ( (options = arguments[ i ]) != null ) { +- // Extend the base object +- for ( name in options ) { +- src = target[ name ]; +- copy = options[ name ]; +- +- // Prevent never-ending loop +- if ( target === copy ) { +- continue; +- } +- +- // Recurse if we're merging plain objects or arrays +- if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { +- if ( copyIsArray ) { +- copyIsArray = false; +- clone = src && jQuery.isArray(src) ? src : []; +- +- } else { +- clone = src && jQuery.isPlainObject(src) ? src : {}; +- } +- +- // Never move original objects, clone them +- target[ name ] = jQuery.extend( deep, clone, copy ); +- +- // Don't bring in undefined values +- } else if ( copy !== undefined ) { +- target[ name ] = copy; +- } +- } +- } +- } +- +- // Return the modified object +- return target; +-}; +- +-jQuery.extend({ +- noConflict: function( deep ) { +- if ( window.$ === jQuery ) { +- window.$ = _$; +- } +- +- if ( deep && window.jQuery === jQuery ) { +- window.jQuery = _jQuery; +- } +- +- return jQuery; +- }, +- +- // Is the DOM ready to be used? Set to true once it occurs. +- isReady: false, +- +- // A counter to track how many items to wait for before +- // the ready event fires. See #6781 +- readyWait: 1, +- +- // Hold (or release) the ready event +- holdReady: function( hold ) { +- if ( hold ) { +- jQuery.readyWait++; +- } else { +- jQuery.ready( true ); +- } +- }, +- +- // Handle when the DOM is ready +- ready: function( wait ) { +- // Either a released hold or an DOMready/load event and not yet ready +- if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { +- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). +- if ( !document.body ) { +- return setTimeout( jQuery.ready, 1 ); +- } +- +- // Remember that the DOM is ready +- jQuery.isReady = true; +- +- // If a normal DOM Ready event fired, decrement, and wait if need be +- if ( wait !== true && --jQuery.readyWait > 0 ) { +- return; +- } +- +- // If there are functions bound, to execute +- readyList.fireWith( document, [ jQuery ] ); +- +- // Trigger any bound ready events +- if ( jQuery.fn.trigger ) { +- jQuery( document ).trigger( "ready" ).off( "ready" ); +- } +- } +- }, +- +- bindReady: function() { +- if ( readyList ) { +- return; +- } +- +- readyList = jQuery.Callbacks( "once memory" ); +- +- // Catch cases where $(document).ready() is called after the +- // browser event has already occurred. +- if ( document.readyState === "complete" ) { +- // Handle it asynchronously to allow scripts the opportunity to delay ready +- return setTimeout( jQuery.ready, 1 ); +- } +- +- // Mozilla, Opera and webkit nightlies currently support this event +- if ( document.addEventListener ) { +- // Use the handy event callback +- document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); +- +- // A fallback to window.onload, that will always work +- window.addEventListener( "load", jQuery.ready, false ); +- +- // If IE event model is used +- } else if ( document.attachEvent ) { +- // ensure firing before onload, +- // maybe late but safe also for iframes +- document.attachEvent( "onreadystatechange", DOMContentLoaded ); +- +- // A fallback to window.onload, that will always work +- window.attachEvent( "onload", jQuery.ready ); +- +- // If IE and not a frame +- // continually check to see if the document is ready +- var toplevel = false; +- +- try { +- toplevel = window.frameElement == null; +- } catch(e) {} +- +- if ( document.documentElement.doScroll && toplevel ) { +- doScrollCheck(); +- } +- } +- }, +- +- // See test/unit/core.js for details concerning isFunction. +- // Since version 1.3, DOM methods and functions like alert +- // aren't supported. They return false on IE (#2968). +- isFunction: function( obj ) { +- return jQuery.type(obj) === "function"; +- }, +- +- isArray: Array.isArray || function( obj ) { +- return jQuery.type(obj) === "array"; +- }, +- +- // A crude way of determining if an object is a window +- isWindow: function( obj ) { +- return obj && typeof obj === "object" && "setInterval" in obj; +- }, +- +- isNumeric: function( obj ) { +- return !isNaN( parseFloat(obj) ) && isFinite( obj ); +- }, +- +- type: function( obj ) { +- return obj == null ? +- String( obj ) : +- class2type[ toString.call(obj) ] || "object"; +- }, +- +- isPlainObject: function( obj ) { +- // Must be an Object. +- // Because of IE, we also have to check the presence of the constructor property. +- // Make sure that DOM nodes and window objects don't pass through, as well +- if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { +- return false; +- } +- +- try { +- // Not own constructor property must be Object +- if ( obj.constructor && +- !hasOwn.call(obj, "constructor") && +- !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { +- return false; +- } +- } catch ( e ) { +- // IE8,9 Will throw exceptions on certain host objects #9897 +- return false; +- } +- +- // Own properties are enumerated firstly, so to speed up, +- // if last one is own, then all properties are own. +- +- var key; +- for ( key in obj ) {} +- +- return key === undefined || hasOwn.call( obj, key ); +- }, +- +- isEmptyObject: function( obj ) { +- for ( var name in obj ) { +- return false; +- } +- return true; +- }, +- +- error: function( msg ) { +- throw new Error( msg ); +- }, +- +- parseJSON: function( data ) { +- if ( typeof data !== "string" || !data ) { +- return null; +- } +- +- // Make sure leading/trailing whitespace is removed (IE can't handle it) +- data = jQuery.trim( data ); +- +- // Attempt to parse using the native JSON parser first +- if ( window.JSON && window.JSON.parse ) { +- return window.JSON.parse( data ); +- } +- +- // Make sure the incoming data is actual JSON +- // Logic borrowed from http://json.org/json2.js +- if ( rvalidchars.test( data.replace( rvalidescape, "@" ) +- .replace( rvalidtokens, "]" ) +- .replace( rvalidbraces, "")) ) { +- +- return ( new Function( "return " + data ) )(); +- +- } +- jQuery.error( "Invalid JSON: " + data ); +- }, +- +- // Cross-browser xml parsing +- parseXML: function( data ) { +- var xml, tmp; +- try { +- if ( window.DOMParser ) { // Standard +- tmp = new DOMParser(); +- xml = tmp.parseFromString( data , "text/xml" ); +- } else { // IE +- xml = new ActiveXObject( "Microsoft.XMLDOM" ); +- xml.async = "false"; +- xml.loadXML( data ); +- } +- } catch( e ) { +- xml = undefined; +- } +- if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { +- jQuery.error( "Invalid XML: " + data ); +- } +- return xml; +- }, +- +- noop: function() {}, +- +- // Evaluates a script in a global context +- // Workarounds based on findings by Jim Driscoll +- // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context +- globalEval: function( data ) { +- if ( data && rnotwhite.test( data ) ) { +- // We use execScript on Internet Explorer +- // We use an anonymous function so that context is window +- // rather than jQuery in Firefox +- ( window.execScript || function( data ) { +- window[ "eval" ].call( window, data ); +- } )( data ); +- } +- }, +- +- // Convert dashed to camelCase; used by the css and data modules +- // Microsoft forgot to hump their vendor prefix (#9572) +- camelCase: function( string ) { +- return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +- }, +- +- nodeName: function( elem, name ) { +- return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); +- }, +- +- // args is for internal usage only +- each: function( object, callback, args ) { +- var name, i = 0, +- length = object.length, +- isObj = length === undefined || jQuery.isFunction( object ); +- +- if ( args ) { +- if ( isObj ) { +- for ( name in object ) { +- if ( callback.apply( object[ name ], args ) === false ) { +- break; +- } +- } +- } else { +- for ( ; i < length; ) { +- if ( callback.apply( object[ i++ ], args ) === false ) { +- break; +- } +- } +- } +- +- // A special, fast, case for the most common use of each +- } else { +- if ( isObj ) { +- for ( name in object ) { +- if ( callback.call( object[ name ], name, object[ name ] ) === false ) { +- break; +- } +- } +- } else { +- for ( ; i < length; ) { +- if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { +- break; +- } +- } +- } +- } +- +- return object; +- }, +- +- // Use native String.trim function wherever possible +- trim: trim ? +- function( text ) { +- return text == null ? +- "" : +- trim.call( text ); +- } : +- +- // Otherwise use our own trimming functionality +- function( text ) { +- return text == null ? +- "" : +- text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); +- }, +- +- // results is for internal usage only +- makeArray: function( array, results ) { +- var ret = results || []; +- +- if ( array != null ) { +- // The window, strings (and functions) also have 'length' +- // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 +- var type = jQuery.type( array ); +- +- if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { +- push.call( ret, array ); +- } else { +- jQuery.merge( ret, array ); +- } +- } +- +- return ret; +- }, +- +- inArray: function( elem, array, i ) { +- var len; +- +- if ( array ) { +- if ( indexOf ) { +- return indexOf.call( array, elem, i ); +- } +- +- len = array.length; +- i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; +- +- for ( ; i < len; i++ ) { +- // Skip accessing in sparse arrays +- if ( i in array && array[ i ] === elem ) { +- return i; +- } +- } +- } +- +- return -1; +- }, +- +- merge: function( first, second ) { +- var i = first.length, +- j = 0; +- +- if ( typeof second.length === "number" ) { +- for ( var l = second.length; j < l; j++ ) { +- first[ i++ ] = second[ j ]; +- } +- +- } else { +- while ( second[j] !== undefined ) { +- first[ i++ ] = second[ j++ ]; +- } +- } +- +- first.length = i; +- +- return first; +- }, +- +- grep: function( elems, callback, inv ) { +- var ret = [], retVal; +- inv = !!inv; +- +- // Go through the array, only saving the items +- // that pass the validator function +- for ( var i = 0, length = elems.length; i < length; i++ ) { +- retVal = !!callback( elems[ i ], i ); +- if ( inv !== retVal ) { +- ret.push( elems[ i ] ); +- } +- } +- +- return ret; +- }, +- +- // arg is for internal usage only +- map: function( elems, callback, arg ) { +- var value, key, ret = [], +- i = 0, +- length = elems.length, +- // jquery objects are treated as arrays +- isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; +- +- // Go through the array, translating each of the items to their +- if ( isArray ) { +- for ( ; i < length; i++ ) { +- value = callback( elems[ i ], i, arg ); +- +- if ( value != null ) { +- ret[ ret.length ] = value; +- } +- } +- +- // Go through every key on the object, +- } else { +- for ( key in elems ) { +- value = callback( elems[ key ], key, arg ); +- +- if ( value != null ) { +- ret[ ret.length ] = value; +- } +- } +- } +- +- // Flatten any nested arrays +- return ret.concat.apply( [], ret ); +- }, +- +- // A global GUID counter for objects +- guid: 1, +- +- // Bind a function to a context, optionally partially applying any +- // arguments. +- proxy: function( fn, context ) { +- if ( typeof context === "string" ) { +- var tmp = fn[ context ]; +- context = fn; +- fn = tmp; +- } +- +- // Quick check to determine if target is callable, in the spec +- // this throws a TypeError, but we will just return undefined. +- if ( !jQuery.isFunction( fn ) ) { +- return undefined; +- } +- +- // Simulated bind +- var args = slice.call( arguments, 2 ), +- proxy = function() { +- return fn.apply( context, args.concat( slice.call( arguments ) ) ); +- }; +- +- // Set the guid of unique handler to the same of original handler, so it can be removed +- proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; +- +- return proxy; +- }, +- +- // Mutifunctional method to get and set values to a collection +- // The value/s can optionally be executed if it's a function +- access: function( elems, key, value, exec, fn, pass ) { +- var length = elems.length; +- +- // Setting many attributes +- if ( typeof key === "object" ) { +- for ( var k in key ) { +- jQuery.access( elems, k, key[k], exec, fn, value ); +- } +- return elems; +- } +- +- // Setting one attribute +- if ( value !== undefined ) { +- // Optionally, function values get executed if exec is true +- exec = !pass && exec && jQuery.isFunction(value); +- +- for ( var i = 0; i < length; i++ ) { +- fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); +- } +- +- return elems; +- } +- +- // Getting an attribute +- return length ? fn( elems[0], key ) : undefined; +- }, +- +- now: function() { +- return ( new Date() ).getTime(); +- }, +- +- // Use of jQuery.browser is frowned upon. +- // More details: http://docs.jquery.com/Utilities/jQuery.browser +- uaMatch: function( ua ) { +- ua = ua.toLowerCase(); +- +- var match = rwebkit.exec( ua ) || +- ropera.exec( ua ) || +- rmsie.exec( ua ) || +- ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || +- []; +- +- return { browser: match[1] || "", version: match[2] || "0" }; +- }, +- +- sub: function() { +- function jQuerySub( selector, context ) { +- return new jQuerySub.fn.init( selector, context ); +- } +- jQuery.extend( true, jQuerySub, this ); +- jQuerySub.superclass = this; +- jQuerySub.fn = jQuerySub.prototype = this(); +- jQuerySub.fn.constructor = jQuerySub; +- jQuerySub.sub = this.sub; +- jQuerySub.fn.init = function init( selector, context ) { +- if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { +- context = jQuerySub( context ); +- } +- +- return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); +- }; +- jQuerySub.fn.init.prototype = jQuerySub.fn; +- var rootjQuerySub = jQuerySub(document); +- return jQuerySub; +- }, +- +- browser: {} +-}); +- +-// Populate the class2type map +-jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { +- class2type[ "[object " + name + "]" ] = name.toLowerCase(); +-}); +- +-browserMatch = jQuery.uaMatch( userAgent ); +-if ( browserMatch.browser ) { +- jQuery.browser[ browserMatch.browser ] = true; +- jQuery.browser.version = browserMatch.version; +-} +- +-// Deprecated, use jQuery.browser.webkit instead +-if ( jQuery.browser.webkit ) { +- jQuery.browser.safari = true; +-} +- +-// IE doesn't match non-breaking spaces with \s +-if ( rnotwhite.test( "\xA0" ) ) { +- trimLeft = /^[\s\xA0]+/; +- trimRight = /[\s\xA0]+$/; +-} +- +-// All jQuery objects should point back to these +-rootjQuery = jQuery(document); +- +-// Cleanup functions for the document ready method +-if ( document.addEventListener ) { +- DOMContentLoaded = function() { +- document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); +- jQuery.ready(); +- }; +- +-} else if ( document.attachEvent ) { +- DOMContentLoaded = function() { +- // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). +- if ( document.readyState === "complete" ) { +- document.detachEvent( "onreadystatechange", DOMContentLoaded ); +- jQuery.ready(); +- } +- }; +-} +- +-// The DOM ready check for Internet Explorer +-function doScrollCheck() { +- if ( jQuery.isReady ) { +- return; +- } +- +- try { +- // If IE is used, use the trick by Diego Perini +- // http://javascript.nwbox.com/IEContentLoaded/ +- document.documentElement.doScroll("left"); +- } catch(e) { +- setTimeout( doScrollCheck, 1 ); +- return; +- } +- +- // and execute any waiting functions +- jQuery.ready(); +-} +- +-return jQuery; +- +-})(); +- +- +-// String to Object flags format cache +-var flagsCache = {}; +- +-// Convert String-formatted flags into Object-formatted ones and store in cache +-function createFlags( flags ) { +- var object = flagsCache[ flags ] = {}, +- i, length; +- flags = flags.split( /\s+/ ); +- for ( i = 0, length = flags.length; i < length; i++ ) { +- object[ flags[i] ] = true; +- } +- return object; +-} +- +-/* +- * Create a callback list using the following parameters: +- * +- * flags: an optional list of space-separated flags that will change how +- * the callback list behaves +- * +- * By default a callback list will act like an event callback list and can be +- * "fired" multiple times. +- * +- * Possible flags: +- * +- * once: will ensure the callback list can only be fired once (like a Deferred) +- * +- * memory: will keep track of previous values and will call any callback added +- * after the list has been fired right away with the latest "memorized" +- * values (like a Deferred) +- * +- * unique: will ensure a callback can only be added once (no duplicate in the list) +- * +- * stopOnFalse: interrupt callings when a callback returns false +- * +- */ +-jQuery.Callbacks = function( flags ) { +- +- // Convert flags from String-formatted to Object-formatted +- // (we check in cache first) +- flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; +- +- var // Actual callback list +- list = [], +- // Stack of fire calls for repeatable lists +- stack = [], +- // Last fire value (for non-forgettable lists) +- memory, +- // Flag to know if list is currently firing +- firing, +- // First callback to fire (used internally by add and fireWith) +- firingStart, +- // End of the loop when firing +- firingLength, +- // Index of currently firing callback (modified by remove if needed) +- firingIndex, +- // Add one or several callbacks to the list +- add = function( args ) { +- var i, +- length, +- elem, +- type, +- actual; +- for ( i = 0, length = args.length; i < length; i++ ) { +- elem = args[ i ]; +- type = jQuery.type( elem ); +- if ( type === "array" ) { +- // Inspect recursively +- add( elem ); +- } else if ( type === "function" ) { +- // Add if not in unique mode and callback is not in +- if ( !flags.unique || !self.has( elem ) ) { +- list.push( elem ); +- } +- } +- } +- }, +- // Fire callbacks +- fire = function( context, args ) { +- args = args || []; +- memory = !flags.memory || [ context, args ]; +- firing = true; +- firingIndex = firingStart || 0; +- firingStart = 0; +- firingLength = list.length; +- for ( ; list && firingIndex < firingLength; firingIndex++ ) { +- if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { +- memory = true; // Mark as halted +- break; +- } +- } +- firing = false; +- if ( list ) { +- if ( !flags.once ) { +- if ( stack && stack.length ) { +- memory = stack.shift(); +- self.fireWith( memory[ 0 ], memory[ 1 ] ); +- } +- } else if ( memory === true ) { +- self.disable(); +- } else { +- list = []; +- } +- } +- }, +- // Actual Callbacks object +- self = { +- // Add a callback or a collection of callbacks to the list +- add: function() { +- if ( list ) { +- var length = list.length; +- add( arguments ); +- // Do we need to add the callbacks to the +- // current firing batch? +- if ( firing ) { +- firingLength = list.length; +- // With memory, if we're not firing then +- // we should call right away, unless previous +- // firing was halted (stopOnFalse) +- } else if ( memory && memory !== true ) { +- firingStart = length; +- fire( memory[ 0 ], memory[ 1 ] ); +- } +- } +- return this; +- }, +- // Remove a callback from the list +- remove: function() { +- if ( list ) { +- var args = arguments, +- argIndex = 0, +- argLength = args.length; +- for ( ; argIndex < argLength ; argIndex++ ) { +- for ( var i = 0; i < list.length; i++ ) { +- if ( args[ argIndex ] === list[ i ] ) { +- // Handle firingIndex and firingLength +- if ( firing ) { +- if ( i <= firingLength ) { +- firingLength--; +- if ( i <= firingIndex ) { +- firingIndex--; +- } +- } +- } +- // Remove the element +- list.splice( i--, 1 ); +- // If we have some unicity property then +- // we only need to do this once +- if ( flags.unique ) { +- break; +- } +- } +- } +- } +- } +- return this; +- }, +- // Control if a given callback is in the list +- has: function( fn ) { +- if ( list ) { +- var i = 0, +- length = list.length; +- for ( ; i < length; i++ ) { +- if ( fn === list[ i ] ) { +- return true; +- } +- } +- } +- return false; +- }, +- // Remove all callbacks from the list +- empty: function() { +- list = []; +- return this; +- }, +- // Have the list do nothing anymore +- disable: function() { +- list = stack = memory = undefined; +- return this; +- }, +- // Is it disabled? +- disabled: function() { +- return !list; +- }, +- // Lock the list in its current state +- lock: function() { +- stack = undefined; +- if ( !memory || memory === true ) { +- self.disable(); +- } +- return this; +- }, +- // Is it locked? +- locked: function() { +- return !stack; +- }, +- // Call all callbacks with the given context and arguments +- fireWith: function( context, args ) { +- if ( stack ) { +- if ( firing ) { +- if ( !flags.once ) { +- stack.push( [ context, args ] ); +- } +- } else if ( !( flags.once && memory ) ) { +- fire( context, args ); +- } +- } +- return this; +- }, +- // Call all the callbacks with the given arguments +- fire: function() { +- self.fireWith( this, arguments ); +- return this; +- }, +- // To know if the callbacks have already been called at least once +- fired: function() { +- return !!memory; +- } +- }; +- +- return self; +-}; +- +- +- +- +-var // Static reference to slice +- sliceDeferred = [].slice; +- +-jQuery.extend({ +- +- Deferred: function( func ) { +- var doneList = jQuery.Callbacks( "once memory" ), +- failList = jQuery.Callbacks( "once memory" ), +- progressList = jQuery.Callbacks( "memory" ), +- state = "pending", +- lists = { +- resolve: doneList, +- reject: failList, +- notify: progressList +- }, +- promise = { +- done: doneList.add, +- fail: failList.add, +- progress: progressList.add, +- +- state: function() { +- return state; +- }, +- +- // Deprecated +- isResolved: doneList.fired, +- isRejected: failList.fired, +- +- then: function( doneCallbacks, failCallbacks, progressCallbacks ) { +- deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); +- return this; +- }, +- always: function() { +- deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); +- return this; +- }, +- pipe: function( fnDone, fnFail, fnProgress ) { +- return jQuery.Deferred(function( newDefer ) { +- jQuery.each( { +- done: [ fnDone, "resolve" ], +- fail: [ fnFail, "reject" ], +- progress: [ fnProgress, "notify" ] +- }, function( handler, data ) { +- var fn = data[ 0 ], +- action = data[ 1 ], +- returned; +- if ( jQuery.isFunction( fn ) ) { +- deferred[ handler ](function() { +- returned = fn.apply( this, arguments ); +- if ( returned && jQuery.isFunction( returned.promise ) ) { +- returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); +- } else { +- newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); +- } +- }); +- } else { +- deferred[ handler ]( newDefer[ action ] ); +- } +- }); +- }).promise(); +- }, +- // Get a promise for this deferred +- // If obj is provided, the promise aspect is added to the object +- promise: function( obj ) { +- if ( obj == null ) { +- obj = promise; +- } else { +- for ( var key in promise ) { +- obj[ key ] = promise[ key ]; +- } +- } +- return obj; +- } +- }, +- deferred = promise.promise({}), +- key; +- +- for ( key in lists ) { +- deferred[ key ] = lists[ key ].fire; +- deferred[ key + "With" ] = lists[ key ].fireWith; +- } +- +- // Handle state +- deferred.done( function() { +- state = "resolved"; +- }, failList.disable, progressList.lock ).fail( function() { +- state = "rejected"; +- }, doneList.disable, progressList.lock ); +- +- // Call given func if any +- if ( func ) { +- func.call( deferred, deferred ); +- } +- +- // All done! +- return deferred; +- }, +- +- // Deferred helper +- when: function( firstParam ) { +- var args = sliceDeferred.call( arguments, 0 ), +- i = 0, +- length = args.length, +- pValues = new Array( length ), +- count = length, +- pCount = length, +- deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? +- firstParam : +- jQuery.Deferred(), +- promise = deferred.promise(); +- function resolveFunc( i ) { +- return function( value ) { +- args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; +- if ( !( --count ) ) { +- deferred.resolveWith( deferred, args ); +- } +- }; +- } +- function progressFunc( i ) { +- return function( value ) { +- pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; +- deferred.notifyWith( promise, pValues ); +- }; +- } +- if ( length > 1 ) { +- for ( ; i < length; i++ ) { +- if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { +- args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); +- } else { +- --count; +- } +- } +- if ( !count ) { +- deferred.resolveWith( deferred, args ); +- } +- } else if ( deferred !== firstParam ) { +- deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); +- } +- return promise; +- } +-}); +- +- +- +- +-jQuery.support = (function() { +- +- var support, +- all, +- a, +- select, +- opt, +- input, +- marginDiv, +- fragment, +- tds, +- events, +- eventName, +- i, +- isSupported, +- div = document.createElement( "div" ), +- documentElement = document.documentElement; +- +- // Preliminary tests +- div.setAttribute("className", "t"); +- div.innerHTML = "
a"; +- +- all = div.getElementsByTagName( "*" ); +- a = div.getElementsByTagName( "a" )[ 0 ]; +- +- // Can't get basic test support +- if ( !all || !all.length || !a ) { +- return {}; +- } +- +- // First batch of supports tests +- select = document.createElement( "select" ); +- opt = select.appendChild( document.createElement("option") ); +- input = div.getElementsByTagName( "input" )[ 0 ]; +- +- support = { +- // IE strips leading whitespace when .innerHTML is used +- leadingWhitespace: ( div.firstChild.nodeType === 3 ), +- +- // Make sure that tbody elements aren't automatically inserted +- // IE will insert them into empty tables +- tbody: !div.getElementsByTagName("tbody").length, +- +- // Make sure that link elements get serialized correctly by innerHTML +- // This requires a wrapper element in IE +- htmlSerialize: !!div.getElementsByTagName("link").length, +- +- // Get the style information from getAttribute +- // (IE uses .cssText instead) +- style: /top/.test( a.getAttribute("style") ), +- +- // Make sure that URLs aren't manipulated +- // (IE normalizes it by default) +- hrefNormalized: ( a.getAttribute("href") === "/a" ), +- +- // Make sure that element opacity exists +- // (IE uses filter instead) +- // Use a regex to work around a WebKit issue. See #5145 +- opacity: /^0.55/.test( a.style.opacity ), +- +- // Verify style float existence +- // (IE uses styleFloat instead of cssFloat) +- cssFloat: !!a.style.cssFloat, +- +- // Make sure that if no value is specified for a checkbox +- // that it defaults to "on". +- // (WebKit defaults to "" instead) +- checkOn: ( input.value === "on" ), +- +- // Make sure that a selected-by-default option has a working selected property. +- // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) +- optSelected: opt.selected, +- +- // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) +- getSetAttribute: div.className !== "t", +- +- // Tests for enctype support on a form(#6743) +- enctype: !!document.createElement("form").enctype, +- +- // Makes sure cloning an html5 element does not cause problems +- // Where outerHTML is undefined, this still works +- html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", +- +- // Will be defined later +- submitBubbles: true, +- changeBubbles: true, +- focusinBubbles: false, +- deleteExpando: true, +- noCloneEvent: true, +- inlineBlockNeedsLayout: false, +- shrinkWrapBlocks: false, +- reliableMarginRight: true +- }; +- +- // Make sure checked status is properly cloned +- input.checked = true; +- support.noCloneChecked = input.cloneNode( true ).checked; +- +- // Make sure that the options inside disabled selects aren't marked as disabled +- // (WebKit marks them as disabled) +- select.disabled = true; +- support.optDisabled = !opt.disabled; +- +- // Test to see if it's possible to delete an expando from an element +- // Fails in Internet Explorer +- try { +- delete div.test; +- } catch( e ) { +- support.deleteExpando = false; +- } +- +- if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { +- div.attachEvent( "onclick", function() { +- // Cloning a node shouldn't copy over any +- // bound event handlers (IE does this) +- support.noCloneEvent = false; +- }); +- div.cloneNode( true ).fireEvent( "onclick" ); +- } +- +- // Check if a radio maintains its value +- // after being appended to the DOM +- input = document.createElement("input"); +- input.value = "t"; +- input.setAttribute("type", "radio"); +- support.radioValue = input.value === "t"; +- +- input.setAttribute("checked", "checked"); +- div.appendChild( input ); +- fragment = document.createDocumentFragment(); +- fragment.appendChild( div.lastChild ); +- +- // WebKit doesn't clone checked state correctly in fragments +- support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; +- +- // Check if a disconnected checkbox will retain its checked +- // value of true after appended to the DOM (IE6/7) +- support.appendChecked = input.checked; +- +- fragment.removeChild( input ); +- fragment.appendChild( div ); +- +- div.innerHTML = ""; +- +- // Check if div with explicit width and no margin-right incorrectly +- // gets computed margin-right based on width of container. For more +- // info see bug #3333 +- // Fails in WebKit before Feb 2011 nightlies +- // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right +- if ( window.getComputedStyle ) { +- marginDiv = document.createElement( "div" ); +- marginDiv.style.width = "0"; +- marginDiv.style.marginRight = "0"; +- div.style.width = "2px"; +- div.appendChild( marginDiv ); +- support.reliableMarginRight = +- ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; +- } +- +- // Technique from Juriy Zaytsev +- // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ +- // We only care about the case where non-standard event systems +- // are used, namely in IE. Short-circuiting here helps us to +- // avoid an eval call (in setAttribute) which can cause CSP +- // to go haywire. See: https://developer.mozilla.org/en/Security/CSP +- if ( div.attachEvent ) { +- for( i in { +- submit: 1, +- change: 1, +- focusin: 1 +- }) { +- eventName = "on" + i; +- isSupported = ( eventName in div ); +- if ( !isSupported ) { +- div.setAttribute( eventName, "return;" ); +- isSupported = ( typeof div[ eventName ] === "function" ); +- } +- support[ i + "Bubbles" ] = isSupported; +- } +- } +- +- fragment.removeChild( div ); +- +- // Null elements to avoid leaks in IE +- fragment = select = opt = marginDiv = div = input = null; +- +- // Run tests that need a body at doc ready +- jQuery(function() { +- var container, outer, inner, table, td, offsetSupport, +- conMarginTop, ptlm, vb, style, html, +- body = document.getElementsByTagName("body")[0]; +- +- if ( !body ) { +- // Return for frameset docs that don't have a body +- return; +- } +- +- conMarginTop = 1; +- ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;"; +- vb = "visibility:hidden;border:0;"; +- style = "style='" + ptlm + "border:5px solid #000;padding:0;'"; +- html = "
" + +- "" + +- "
"; +- +- container = document.createElement("div"); +- container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; +- body.insertBefore( container, body.firstChild ); +- +- // Construct the test element +- div = document.createElement("div"); +- container.appendChild( div ); +- +- // Check if table cells still have offsetWidth/Height when they are set +- // to display:none and there are still other visible table cells in a +- // table row; if so, offsetWidth/Height are not reliable for use when +- // determining if an element has been hidden directly using +- // display:none (it is still safe to use offsets if a parent element is +- // hidden; don safety goggles and see bug #4512 for more information). +- // (only IE 8 fails this test) +- div.innerHTML = "
t
"; +- tds = div.getElementsByTagName( "td" ); +- isSupported = ( tds[ 0 ].offsetHeight === 0 ); +- +- tds[ 0 ].style.display = ""; +- tds[ 1 ].style.display = "none"; +- +- // Check if empty table cells still have offsetWidth/Height +- // (IE <= 8 fail this test) +- support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); +- +- // Figure out if the W3C box model works as expected +- div.innerHTML = ""; +- div.style.width = div.style.paddingLeft = "1px"; +- jQuery.boxModel = support.boxModel = div.offsetWidth === 2; +- +- if ( typeof div.style.zoom !== "undefined" ) { +- // Check if natively block-level elements act like inline-block +- // elements when setting their display to 'inline' and giving +- // them layout +- // (IE < 8 does this) +- div.style.display = "inline"; +- div.style.zoom = 1; +- support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); +- +- // Check if elements with layout shrink-wrap their children +- // (IE 6 does this) +- div.style.display = ""; +- div.innerHTML = "
"; +- support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); +- } +- +- div.style.cssText = ptlm + vb; +- div.innerHTML = html; +- +- outer = div.firstChild; +- inner = outer.firstChild; +- td = outer.nextSibling.firstChild.firstChild; +- +- offsetSupport = { +- doesNotAddBorder: ( inner.offsetTop !== 5 ), +- doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) +- }; +- +- inner.style.position = "fixed"; +- inner.style.top = "20px"; +- +- // safari subtracts parent border width here which is 5px +- offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); +- inner.style.position = inner.style.top = ""; +- +- outer.style.overflow = "hidden"; +- outer.style.position = "relative"; +- +- offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); +- offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); +- +- body.removeChild( container ); +- div = container = null; +- +- jQuery.extend( support, offsetSupport ); +- }); +- +- return support; +-})(); +- +- +- +- +-var rbrace = /^(?:\{.*\}|\[.*\])$/, +- rmultiDash = /([A-Z])/g; +- +-jQuery.extend({ +- cache: {}, +- +- // Please use with caution +- uuid: 0, +- +- // Unique for each copy of jQuery on the page +- // Non-digits removed to match rinlinejQuery +- expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), +- +- // The following elements throw uncatchable exceptions if you +- // attempt to add expando properties to them. +- noData: { +- "embed": true, +- // Ban all objects except for Flash (which handle expandos) +- "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", +- "applet": true +- }, +- +- hasData: function( elem ) { +- elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; +- return !!elem && !isEmptyDataObject( elem ); +- }, +- +- data: function( elem, name, data, pvt /* Internal Use Only */ ) { +- if ( !jQuery.acceptData( elem ) ) { +- return; +- } +- +- var privateCache, thisCache, ret, +- internalKey = jQuery.expando, +- getByName = typeof name === "string", +- +- // We have to handle DOM nodes and JS objects differently because IE6-7 +- // can't GC object references properly across the DOM-JS boundary +- isNode = elem.nodeType, +- +- // Only DOM nodes need the global jQuery cache; JS object data is +- // attached directly to the object so GC can occur automatically +- cache = isNode ? jQuery.cache : elem, +- +- // Only defining an ID for JS objects if its cache already exists allows +- // the code to shortcut on the same path as a DOM node with no cache +- id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, +- isEvents = name === "events"; +- +- // Avoid doing any more work than we need to when trying to get data on an +- // object that has no data at all +- if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { +- return; +- } +- +- if ( !id ) { +- // Only DOM nodes need a new unique ID for each element since their data +- // ends up in the global cache +- if ( isNode ) { +- elem[ internalKey ] = id = ++jQuery.uuid; +- } else { +- id = internalKey; +- } +- } +- +- if ( !cache[ id ] ) { +- cache[ id ] = {}; +- +- // Avoids exposing jQuery metadata on plain JS objects when the object +- // is serialized using JSON.stringify +- if ( !isNode ) { +- cache[ id ].toJSON = jQuery.noop; +- } +- } +- +- // An object can be passed to jQuery.data instead of a key/value pair; this gets +- // shallow copied over onto the existing cache +- if ( typeof name === "object" || typeof name === "function" ) { +- if ( pvt ) { +- cache[ id ] = jQuery.extend( cache[ id ], name ); +- } else { +- cache[ id ].data = jQuery.extend( cache[ id ].data, name ); +- } +- } +- +- privateCache = thisCache = cache[ id ]; +- +- // jQuery data() is stored in a separate object inside the object's internal data +- // cache in order to avoid key collisions between internal data and user-defined +- // data. +- if ( !pvt ) { +- if ( !thisCache.data ) { +- thisCache.data = {}; +- } +- +- thisCache = thisCache.data; +- } +- +- if ( data !== undefined ) { +- thisCache[ jQuery.camelCase( name ) ] = data; +- } +- +- // Users should not attempt to inspect the internal events object using jQuery.data, +- // it is undocumented and subject to change. But does anyone listen? No. +- if ( isEvents && !thisCache[ name ] ) { +- return privateCache.events; +- } +- +- // Check for both converted-to-camel and non-converted data property names +- // If a data property was specified +- if ( getByName ) { +- +- // First Try to find as-is property data +- ret = thisCache[ name ]; +- +- // Test for null|undefined property data +- if ( ret == null ) { +- +- // Try to find the camelCased property +- ret = thisCache[ jQuery.camelCase( name ) ]; +- } +- } else { +- ret = thisCache; +- } +- +- return ret; +- }, +- +- removeData: function( elem, name, pvt /* Internal Use Only */ ) { +- if ( !jQuery.acceptData( elem ) ) { +- return; +- } +- +- var thisCache, i, l, +- +- // Reference to internal data cache key +- internalKey = jQuery.expando, +- +- isNode = elem.nodeType, +- +- // See jQuery.data for more information +- cache = isNode ? jQuery.cache : elem, +- +- // See jQuery.data for more information +- id = isNode ? elem[ internalKey ] : internalKey; +- +- // If there is already no cache entry for this object, there is no +- // purpose in continuing +- if ( !cache[ id ] ) { +- return; +- } +- +- if ( name ) { +- +- thisCache = pvt ? cache[ id ] : cache[ id ].data; +- +- if ( thisCache ) { +- +- // Support array or space separated string names for data keys +- if ( !jQuery.isArray( name ) ) { +- +- // try the string as a key before any manipulation +- if ( name in thisCache ) { +- name = [ name ]; +- } else { +- +- // split the camel cased version by spaces unless a key with the spaces exists +- name = jQuery.camelCase( name ); +- if ( name in thisCache ) { +- name = [ name ]; +- } else { +- name = name.split( " " ); +- } +- } +- } +- +- for ( i = 0, l = name.length; i < l; i++ ) { +- delete thisCache[ name[i] ]; +- } +- +- // If there is no data left in the cache, we want to continue +- // and let the cache object itself get destroyed +- if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { +- return; +- } +- } +- } +- +- // See jQuery.data for more information +- if ( !pvt ) { +- delete cache[ id ].data; +- +- // Don't destroy the parent cache unless the internal data object +- // had been the only thing left in it +- if ( !isEmptyDataObject(cache[ id ]) ) { +- return; +- } +- } +- +- // Browsers that fail expando deletion also refuse to delete expandos on +- // the window, but it will allow it on all other JS objects; other browsers +- // don't care +- // Ensure that `cache` is not a window object #10080 +- if ( jQuery.support.deleteExpando || !cache.setInterval ) { +- delete cache[ id ]; +- } else { +- cache[ id ] = null; +- } +- +- // We destroyed the cache and need to eliminate the expando on the node to avoid +- // false lookups in the cache for entries that no longer exist +- if ( isNode ) { +- // IE does not allow us to delete expando properties from nodes, +- // nor does it have a removeAttribute function on Document nodes; +- // we must handle all of these cases +- if ( jQuery.support.deleteExpando ) { +- delete elem[ internalKey ]; +- } else if ( elem.removeAttribute ) { +- elem.removeAttribute( internalKey ); +- } else { +- elem[ internalKey ] = null; +- } +- } +- }, +- +- // For internal use only. +- _data: function( elem, name, data ) { +- return jQuery.data( elem, name, data, true ); +- }, +- +- // A method for determining if a DOM node can handle the data expando +- acceptData: function( elem ) { +- if ( elem.nodeName ) { +- var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; +- +- if ( match ) { +- return !(match === true || elem.getAttribute("classid") !== match); +- } +- } +- +- return true; +- } +-}); +- +-jQuery.fn.extend({ +- data: function( key, value ) { +- var parts, attr, name, +- data = null; +- +- if ( typeof key === "undefined" ) { +- if ( this.length ) { +- data = jQuery.data( this[0] ); +- +- if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) { +- attr = this[0].attributes; +- for ( var i = 0, l = attr.length; i < l; i++ ) { +- name = attr[i].name; +- +- if ( name.indexOf( "data-" ) === 0 ) { +- name = jQuery.camelCase( name.substring(5) ); +- +- dataAttr( this[0], name, data[ name ] ); +- } +- } +- jQuery._data( this[0], "parsedAttrs", true ); +- } +- } +- +- return data; +- +- } else if ( typeof key === "object" ) { +- return this.each(function() { +- jQuery.data( this, key ); +- }); +- } +- +- parts = key.split("."); +- parts[1] = parts[1] ? "." + parts[1] : ""; +- +- if ( value === undefined ) { +- data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); +- +- // Try to fetch any internally stored data first +- if ( data === undefined && this.length ) { +- data = jQuery.data( this[0], key ); +- data = dataAttr( this[0], key, data ); +- } +- +- return data === undefined && parts[1] ? +- this.data( parts[0] ) : +- data; +- +- } else { +- return this.each(function() { +- var self = jQuery( this ), +- args = [ parts[0], value ]; +- +- self.triggerHandler( "setData" + parts[1] + "!", args ); +- jQuery.data( this, key, value ); +- self.triggerHandler( "changeData" + parts[1] + "!", args ); +- }); +- } +- }, +- +- removeData: function( key ) { +- return this.each(function() { +- jQuery.removeData( this, key ); +- }); +- } +-}); +- +-function dataAttr( elem, key, data ) { +- // If nothing was found internally, try to fetch any +- // data from the HTML5 data-* attribute +- if ( data === undefined && elem.nodeType === 1 ) { +- +- var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); +- +- data = elem.getAttribute( name ); +- +- if ( typeof data === "string" ) { +- try { +- data = data === "true" ? true : +- data === "false" ? false : +- data === "null" ? null : +- jQuery.isNumeric( data ) ? parseFloat( data ) : +- rbrace.test( data ) ? jQuery.parseJSON( data ) : +- data; +- } catch( e ) {} +- +- // Make sure we set the data so it isn't changed later +- jQuery.data( elem, key, data ); +- +- } else { +- data = undefined; +- } +- } +- +- return data; +-} +- +-// checks a cache object for emptiness +-function isEmptyDataObject( obj ) { +- for ( var name in obj ) { +- +- // if the public data object is empty, the private is still empty +- if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { +- continue; +- } +- if ( name !== "toJSON" ) { +- return false; +- } +- } +- +- return true; +-} +- +- +- +- +-function handleQueueMarkDefer( elem, type, src ) { +- var deferDataKey = type + "defer", +- queueDataKey = type + "queue", +- markDataKey = type + "mark", +- defer = jQuery._data( elem, deferDataKey ); +- if ( defer && +- ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && +- ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { +- // Give room for hard-coded callbacks to fire first +- // and eventually mark/queue something else on the element +- setTimeout( function() { +- if ( !jQuery._data( elem, queueDataKey ) && +- !jQuery._data( elem, markDataKey ) ) { +- jQuery.removeData( elem, deferDataKey, true ); +- defer.fire(); +- } +- }, 0 ); +- } +-} +- +-jQuery.extend({ +- +- _mark: function( elem, type ) { +- if ( elem ) { +- type = ( type || "fx" ) + "mark"; +- jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); +- } +- }, +- +- _unmark: function( force, elem, type ) { +- if ( force !== true ) { +- type = elem; +- elem = force; +- force = false; +- } +- if ( elem ) { +- type = type || "fx"; +- var key = type + "mark", +- count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); +- if ( count ) { +- jQuery._data( elem, key, count ); +- } else { +- jQuery.removeData( elem, key, true ); +- handleQueueMarkDefer( elem, type, "mark" ); +- } +- } +- }, +- +- queue: function( elem, type, data ) { +- var q; +- if ( elem ) { +- type = ( type || "fx" ) + "queue"; +- q = jQuery._data( elem, type ); +- +- // Speed up dequeue by getting out quickly if this is just a lookup +- if ( data ) { +- if ( !q || jQuery.isArray(data) ) { +- q = jQuery._data( elem, type, jQuery.makeArray(data) ); +- } else { +- q.push( data ); +- } +- } +- return q || []; +- } +- }, +- +- dequeue: function( elem, type ) { +- type = type || "fx"; +- +- var queue = jQuery.queue( elem, type ), +- fn = queue.shift(), +- hooks = {}; +- +- // If the fx queue is dequeued, always remove the progress sentinel +- if ( fn === "inprogress" ) { +- fn = queue.shift(); +- } +- +- if ( fn ) { +- // Add a progress sentinel to prevent the fx queue from being +- // automatically dequeued +- if ( type === "fx" ) { +- queue.unshift( "inprogress" ); +- } +- +- jQuery._data( elem, type + ".run", hooks ); +- fn.call( elem, function() { +- jQuery.dequeue( elem, type ); +- }, hooks ); +- } +- +- if ( !queue.length ) { +- jQuery.removeData( elem, type + "queue " + type + ".run", true ); +- handleQueueMarkDefer( elem, type, "queue" ); +- } +- } +-}); +- +-jQuery.fn.extend({ +- queue: function( type, data ) { +- if ( typeof type !== "string" ) { +- data = type; +- type = "fx"; +- } +- +- if ( data === undefined ) { +- return jQuery.queue( this[0], type ); +- } +- return this.each(function() { +- var queue = jQuery.queue( this, type, data ); +- +- if ( type === "fx" && queue[0] !== "inprogress" ) { +- jQuery.dequeue( this, type ); +- } +- }); +- }, +- dequeue: function( type ) { +- return this.each(function() { +- jQuery.dequeue( this, type ); +- }); +- }, +- // Based off of the plugin by Clint Helfers, with permission. +- // http://blindsignals.com/index.php/2009/07/jquery-delay/ +- delay: function( time, type ) { +- time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; +- type = type || "fx"; +- +- return this.queue( type, function( next, hooks ) { +- var timeout = setTimeout( next, time ); +- hooks.stop = function() { +- clearTimeout( timeout ); +- }; +- }); +- }, +- clearQueue: function( type ) { +- return this.queue( type || "fx", [] ); +- }, +- // Get a promise resolved when queues of a certain type +- // are emptied (fx is the type by default) +- promise: function( type, object ) { +- if ( typeof type !== "string" ) { +- object = type; +- type = undefined; +- } +- type = type || "fx"; +- var defer = jQuery.Deferred(), +- elements = this, +- i = elements.length, +- count = 1, +- deferDataKey = type + "defer", +- queueDataKey = type + "queue", +- markDataKey = type + "mark", +- tmp; +- function resolve() { +- if ( !( --count ) ) { +- defer.resolveWith( elements, [ elements ] ); +- } +- } +- while( i-- ) { +- if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || +- ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || +- jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && +- jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { +- count++; +- tmp.add( resolve ); +- } +- } +- resolve(); +- return defer.promise(); +- } +-}); +- +- +- +- +-var rclass = /[\n\t\r]/g, +- rspace = /\s+/, +- rreturn = /\r/g, +- rtype = /^(?:button|input)$/i, +- rfocusable = /^(?:button|input|object|select|textarea)$/i, +- rclickable = /^a(?:rea)?$/i, +- rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, +- getSetAttribute = jQuery.support.getSetAttribute, +- nodeHook, boolHook, fixSpecified; +- +-jQuery.fn.extend({ +- attr: function( name, value ) { +- return jQuery.access( this, name, value, true, jQuery.attr ); +- }, +- +- removeAttr: function( name ) { +- return this.each(function() { +- jQuery.removeAttr( this, name ); +- }); +- }, +- +- prop: function( name, value ) { +- return jQuery.access( this, name, value, true, jQuery.prop ); +- }, +- +- removeProp: function( name ) { +- name = jQuery.propFix[ name ] || name; +- return this.each(function() { +- // try/catch handles cases where IE balks (such as removing a property on window) +- try { +- this[ name ] = undefined; +- delete this[ name ]; +- } catch( e ) {} +- }); +- }, +- +- addClass: function( value ) { +- var classNames, i, l, elem, +- setClass, c, cl; +- +- if ( jQuery.isFunction( value ) ) { +- return this.each(function( j ) { +- jQuery( this ).addClass( value.call(this, j, this.className) ); +- }); +- } +- +- if ( value && typeof value === "string" ) { +- classNames = value.split( rspace ); +- +- for ( i = 0, l = this.length; i < l; i++ ) { +- elem = this[ i ]; +- +- if ( elem.nodeType === 1 ) { +- if ( !elem.className && classNames.length === 1 ) { +- elem.className = value; +- +- } else { +- setClass = " " + elem.className + " "; +- +- for ( c = 0, cl = classNames.length; c < cl; c++ ) { +- if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { +- setClass += classNames[ c ] + " "; +- } +- } +- elem.className = jQuery.trim( setClass ); +- } +- } +- } +- } +- +- return this; +- }, +- +- removeClass: function( value ) { +- var classNames, i, l, elem, className, c, cl; +- +- if ( jQuery.isFunction( value ) ) { +- return this.each(function( j ) { +- jQuery( this ).removeClass( value.call(this, j, this.className) ); +- }); +- } +- +- if ( (value && typeof value === "string") || value === undefined ) { +- classNames = ( value || "" ).split( rspace ); +- +- for ( i = 0, l = this.length; i < l; i++ ) { +- elem = this[ i ]; +- +- if ( elem.nodeType === 1 && elem.className ) { +- if ( value ) { +- className = (" " + elem.className + " ").replace( rclass, " " ); +- for ( c = 0, cl = classNames.length; c < cl; c++ ) { +- className = className.replace(" " + classNames[ c ] + " ", " "); +- } +- elem.className = jQuery.trim( className ); +- +- } else { +- elem.className = ""; +- } +- } +- } +- } +- +- return this; +- }, +- +- toggleClass: function( value, stateVal ) { +- var type = typeof value, +- isBool = typeof stateVal === "boolean"; +- +- if ( jQuery.isFunction( value ) ) { +- return this.each(function( i ) { +- jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); +- }); +- } +- +- return this.each(function() { +- if ( type === "string" ) { +- // toggle individual class names +- var className, +- i = 0, +- self = jQuery( this ), +- state = stateVal, +- classNames = value.split( rspace ); +- +- while ( (className = classNames[ i++ ]) ) { +- // check each className given, space seperated list +- state = isBool ? state : !self.hasClass( className ); +- self[ state ? "addClass" : "removeClass" ]( className ); +- } +- +- } else if ( type === "undefined" || type === "boolean" ) { +- if ( this.className ) { +- // store className if set +- jQuery._data( this, "__className__", this.className ); +- } +- +- // toggle whole className +- this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; +- } +- }); +- }, +- +- hasClass: function( selector ) { +- var className = " " + selector + " ", +- i = 0, +- l = this.length; +- for ( ; i < l; i++ ) { +- if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { +- return true; +- } +- } +- +- return false; +- }, +- +- val: function( value ) { +- var hooks, ret, isFunction, +- elem = this[0]; +- +- if ( !arguments.length ) { +- if ( elem ) { +- hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; +- +- if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { +- return ret; +- } +- +- ret = elem.value; +- +- return typeof ret === "string" ? +- // handle most common string cases +- ret.replace(rreturn, "") : +- // handle cases where value is null/undef or number +- ret == null ? "" : ret; +- } +- +- return; +- } +- +- isFunction = jQuery.isFunction( value ); +- +- return this.each(function( i ) { +- var self = jQuery(this), val; +- +- if ( this.nodeType !== 1 ) { +- return; +- } +- +- if ( isFunction ) { +- val = value.call( this, i, self.val() ); +- } else { +- val = value; +- } +- +- // Treat null/undefined as ""; convert numbers to string +- if ( val == null ) { +- val = ""; +- } else if ( typeof val === "number" ) { +- val += ""; +- } else if ( jQuery.isArray( val ) ) { +- val = jQuery.map(val, function ( value ) { +- return value == null ? "" : value + ""; +- }); +- } +- +- hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; +- +- // If set returns undefined, fall back to normal setting +- if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { +- this.value = val; +- } +- }); +- } +-}); +- +-jQuery.extend({ +- valHooks: { +- option: { +- get: function( elem ) { +- // attributes.value is undefined in Blackberry 4.7 but +- // uses .value. See #6932 +- var val = elem.attributes.value; +- return !val || val.specified ? elem.value : elem.text; +- } +- }, +- select: { +- get: function( elem ) { +- var value, i, max, option, +- index = elem.selectedIndex, +- values = [], +- options = elem.options, +- one = elem.type === "select-one"; +- +- // Nothing was selected +- if ( index < 0 ) { +- return null; +- } +- +- // Loop through all the selected options +- i = one ? index : 0; +- max = one ? index + 1 : options.length; +- for ( ; i < max; i++ ) { +- option = options[ i ]; +- +- // Don't return options that are disabled or in a disabled optgroup +- if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && +- (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { +- +- // Get the specific value for the option +- value = jQuery( option ).val(); +- +- // We don't need an array for one selects +- if ( one ) { +- return value; +- } +- +- // Multi-Selects return an array +- values.push( value ); +- } +- } +- +- // Fixes Bug #2551 -- select.val() broken in IE after form.reset() +- if ( one && !values.length && options.length ) { +- return jQuery( options[ index ] ).val(); +- } +- +- return values; +- }, +- +- set: function( elem, value ) { +- var values = jQuery.makeArray( value ); +- +- jQuery(elem).find("option").each(function() { +- this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; +- }); +- +- if ( !values.length ) { +- elem.selectedIndex = -1; +- } +- return values; +- } +- } +- }, +- +- attrFn: { +- val: true, +- css: true, +- html: true, +- text: true, +- data: true, +- width: true, +- height: true, +- offset: true +- }, +- +- attr: function( elem, name, value, pass ) { +- var ret, hooks, notxml, +- nType = elem.nodeType; +- +- // don't get/set attributes on text, comment and attribute nodes +- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { +- return; +- } +- +- if ( pass && name in jQuery.attrFn ) { +- return jQuery( elem )[ name ]( value ); +- } +- +- // Fallback to prop when attributes are not supported +- if ( typeof elem.getAttribute === "undefined" ) { +- return jQuery.prop( elem, name, value ); +- } +- +- notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); +- +- // All attributes are lowercase +- // Grab necessary hook if one is defined +- if ( notxml ) { +- name = name.toLowerCase(); +- hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); +- } +- +- if ( value !== undefined ) { +- +- if ( value === null ) { +- jQuery.removeAttr( elem, name ); +- return; +- +- } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { +- return ret; +- +- } else { +- elem.setAttribute( name, "" + value ); +- return value; +- } +- +- } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { +- return ret; +- +- } else { +- +- ret = elem.getAttribute( name ); +- +- // Non-existent attributes return null, we normalize to undefined +- return ret === null ? +- undefined : +- ret; +- } +- }, +- +- removeAttr: function( elem, value ) { +- var propName, attrNames, name, l, +- i = 0; +- +- if ( value && elem.nodeType === 1 ) { +- attrNames = value.toLowerCase().split( rspace ); +- l = attrNames.length; +- +- for ( ; i < l; i++ ) { +- name = attrNames[ i ]; +- +- if ( name ) { +- propName = jQuery.propFix[ name ] || name; +- +- // See #9699 for explanation of this approach (setting first, then removal) +- jQuery.attr( elem, name, "" ); +- elem.removeAttribute( getSetAttribute ? name : propName ); +- +- // Set corresponding property to false for boolean attributes +- if ( rboolean.test( name ) && propName in elem ) { +- elem[ propName ] = false; +- } +- } +- } +- } +- }, +- +- attrHooks: { +- type: { +- set: function( elem, value ) { +- // We can't allow the type property to be changed (since it causes problems in IE) +- if ( rtype.test( elem.nodeName ) && elem.parentNode ) { +- jQuery.error( "type property can't be changed" ); +- } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { +- // Setting the type on a radio button after the value resets the value in IE6-9 +- // Reset value to it's default in case type is set after value +- // This is for element creation +- var val = elem.value; +- elem.setAttribute( "type", value ); +- if ( val ) { +- elem.value = val; +- } +- return value; +- } +- } +- }, +- // Use the value property for back compat +- // Use the nodeHook for button elements in IE6/7 (#1954) +- value: { +- get: function( elem, name ) { +- if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { +- return nodeHook.get( elem, name ); +- } +- return name in elem ? +- elem.value : +- null; +- }, +- set: function( elem, value, name ) { +- if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { +- return nodeHook.set( elem, value, name ); +- } +- // Does not return so that setAttribute is also used +- elem.value = value; +- } +- } +- }, +- +- propFix: { +- tabindex: "tabIndex", +- readonly: "readOnly", +- "for": "htmlFor", +- "class": "className", +- maxlength: "maxLength", +- cellspacing: "cellSpacing", +- cellpadding: "cellPadding", +- rowspan: "rowSpan", +- colspan: "colSpan", +- usemap: "useMap", +- frameborder: "frameBorder", +- contenteditable: "contentEditable" +- }, +- +- prop: function( elem, name, value ) { +- var ret, hooks, notxml, +- nType = elem.nodeType; +- +- // don't get/set properties on text, comment and attribute nodes +- if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { +- return; +- } +- +- notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); +- +- if ( notxml ) { +- // Fix name and attach hooks +- name = jQuery.propFix[ name ] || name; +- hooks = jQuery.propHooks[ name ]; +- } +- +- if ( value !== undefined ) { +- if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { +- return ret; +- +- } else { +- return ( elem[ name ] = value ); +- } +- +- } else { +- if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { +- return ret; +- +- } else { +- return elem[ name ]; +- } +- } +- }, +- +- propHooks: { +- tabIndex: { +- get: function( elem ) { +- // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set +- // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ +- var attributeNode = elem.getAttributeNode("tabindex"); +- +- return attributeNode && attributeNode.specified ? +- parseInt( attributeNode.value, 10 ) : +- rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? +- 0 : +- undefined; +- } +- } +- } +-}); +- +-// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) +-jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; +- +-// Hook for boolean attributes +-boolHook = { +- get: function( elem, name ) { +- // Align boolean attributes with corresponding properties +- // Fall back to attribute presence where some booleans are not supported +- var attrNode, +- property = jQuery.prop( elem, name ); +- return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? +- name.toLowerCase() : +- undefined; +- }, +- set: function( elem, value, name ) { +- var propName; +- if ( value === false ) { +- // Remove boolean attributes when set to false +- jQuery.removeAttr( elem, name ); +- } else { +- // value is true since we know at this point it's type boolean and not false +- // Set boolean attributes to the same name and set the DOM property +- propName = jQuery.propFix[ name ] || name; +- if ( propName in elem ) { +- // Only set the IDL specifically if it already exists on the element +- elem[ propName ] = true; +- } +- +- elem.setAttribute( name, name.toLowerCase() ); +- } +- return name; +- } +-}; +- +-// IE6/7 do not support getting/setting some attributes with get/setAttribute +-if ( !getSetAttribute ) { +- +- fixSpecified = { +- name: true, +- id: true +- }; +- +- // Use this for any attribute in IE6/7 +- // This fixes almost every IE6/7 issue +- nodeHook = jQuery.valHooks.button = { +- get: function( elem, name ) { +- var ret; +- ret = elem.getAttributeNode( name ); +- return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? +- ret.nodeValue : +- undefined; +- }, +- set: function( elem, value, name ) { +- // Set the existing or create a new attribute node +- var ret = elem.getAttributeNode( name ); +- if ( !ret ) { +- ret = document.createAttribute( name ); +- elem.setAttributeNode( ret ); +- } +- return ( ret.nodeValue = value + "" ); +- } +- }; +- +- // Apply the nodeHook to tabindex +- jQuery.attrHooks.tabindex.set = nodeHook.set; +- +- // Set width and height to auto instead of 0 on empty string( Bug #8150 ) +- // This is for removals +- jQuery.each([ "width", "height" ], function( i, name ) { +- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { +- set: function( elem, value ) { +- if ( value === "" ) { +- elem.setAttribute( name, "auto" ); +- return value; +- } +- } +- }); +- }); +- +- // Set contenteditable to false on removals(#10429) +- // Setting to empty string throws an error as an invalid value +- jQuery.attrHooks.contenteditable = { +- get: nodeHook.get, +- set: function( elem, value, name ) { +- if ( value === "" ) { +- value = "false"; +- } +- nodeHook.set( elem, value, name ); +- } +- }; +-} +- +- +-// Some attributes require a special call on IE +-if ( !jQuery.support.hrefNormalized ) { +- jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { +- jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { +- get: function( elem ) { +- var ret = elem.getAttribute( name, 2 ); +- return ret === null ? undefined : ret; +- } +- }); +- }); +-} +- +-if ( !jQuery.support.style ) { +- jQuery.attrHooks.style = { +- get: function( elem ) { +- // Return undefined in the case of empty string +- // Normalize to lowercase since IE uppercases css property names +- return elem.style.cssText.toLowerCase() || undefined; +- }, +- set: function( elem, value ) { +- return ( elem.style.cssText = "" + value ); +- } +- }; +-} +- +-// Safari mis-reports the default selected property of an option +-// Accessing the parent's selectedIndex property fixes it +-if ( !jQuery.support.optSelected ) { +- jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { +- get: function( elem ) { +- var parent = elem.parentNode; +- +- if ( parent ) { +- parent.selectedIndex; +- +- // Make sure that it also works with optgroups, see #5701 +- if ( parent.parentNode ) { +- parent.parentNode.selectedIndex; +- } +- } +- return null; +- } +- }); +-} +- +-// IE6/7 call enctype encoding +-if ( !jQuery.support.enctype ) { +- jQuery.propFix.enctype = "encoding"; +-} +- +-// Radios and checkboxes getter/setter +-if ( !jQuery.support.checkOn ) { +- jQuery.each([ "radio", "checkbox" ], function() { +- jQuery.valHooks[ this ] = { +- get: function( elem ) { +- // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified +- return elem.getAttribute("value") === null ? "on" : elem.value; +- } +- }; +- }); +-} +-jQuery.each([ "radio", "checkbox" ], function() { +- jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { +- set: function( elem, value ) { +- if ( jQuery.isArray( value ) ) { +- return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); +- } +- } +- }); +-}); +- +- +- +- +-var rformElems = /^(?:textarea|input|select)$/i, +- rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, +- rhoverHack = /\bhover(\.\S+)?\b/, +- rkeyEvent = /^key/, +- rmouseEvent = /^(?:mouse|contextmenu)|click/, +- rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, +- rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, +- quickParse = function( selector ) { +- var quick = rquickIs.exec( selector ); +- if ( quick ) { +- // 0 1 2 3 +- // [ _, tag, id, class ] +- quick[1] = ( quick[1] || "" ).toLowerCase(); +- quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); +- } +- return quick; +- }, +- quickIs = function( elem, m ) { +- var attrs = elem.attributes || {}; +- return ( +- (!m[1] || elem.nodeName.toLowerCase() === m[1]) && +- (!m[2] || (attrs.id || {}).value === m[2]) && +- (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) +- ); +- }, +- hoverHack = function( events ) { +- return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); +- }; +- +-/* +- * Helper functions for managing events -- not part of the public interface. +- * Props to Dean Edwards' addEvent library for many of the ideas. +- */ +-jQuery.event = { +- +- add: function( elem, types, handler, data, selector ) { +- +- var elemData, eventHandle, events, +- t, tns, type, namespaces, handleObj, +- handleObjIn, quick, handlers, special; +- +- // Don't attach events to noData or text/comment nodes (allow plain objects tho) +- if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { +- return; +- } +- +- // Caller can pass in an object of custom data in lieu of the handler +- if ( handler.handler ) { +- handleObjIn = handler; +- handler = handleObjIn.handler; +- } +- +- // Make sure that the handler has a unique ID, used to find/remove it later +- if ( !handler.guid ) { +- handler.guid = jQuery.guid++; +- } +- +- // Init the element's event structure and main handler, if this is the first +- events = elemData.events; +- if ( !events ) { +- elemData.events = events = {}; +- } +- eventHandle = elemData.handle; +- if ( !eventHandle ) { +- elemData.handle = eventHandle = function( e ) { +- // Discard the second event of a jQuery.event.trigger() and +- // when an event is called after a page has unloaded +- return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? +- jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : +- undefined; +- }; +- // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events +- eventHandle.elem = elem; +- } +- +- // Handle multiple events separated by a space +- // jQuery(...).bind("mouseover mouseout", fn); +- types = jQuery.trim( hoverHack(types) ).split( " " ); +- for ( t = 0; t < types.length; t++ ) { +- +- tns = rtypenamespace.exec( types[t] ) || []; +- type = tns[1]; +- namespaces = ( tns[2] || "" ).split( "." ).sort(); +- +- // If event changes its type, use the special event handlers for the changed type +- special = jQuery.event.special[ type ] || {}; +- +- // If selector defined, determine special event api type, otherwise given type +- type = ( selector ? special.delegateType : special.bindType ) || type; +- +- // Update special based on newly reset type +- special = jQuery.event.special[ type ] || {}; +- +- // handleObj is passed to all event handlers +- handleObj = jQuery.extend({ +- type: type, +- origType: tns[1], +- data: data, +- handler: handler, +- guid: handler.guid, +- selector: selector, +- quick: quickParse( selector ), +- namespace: namespaces.join(".") +- }, handleObjIn ); +- +- // Init the event handler queue if we're the first +- handlers = events[ type ]; +- if ( !handlers ) { +- handlers = events[ type ] = []; +- handlers.delegateCount = 0; +- +- // Only use addEventListener/attachEvent if the special events handler returns false +- if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { +- // Bind the global event handler to the element +- if ( elem.addEventListener ) { +- elem.addEventListener( type, eventHandle, false ); +- +- } else if ( elem.attachEvent ) { +- elem.attachEvent( "on" + type, eventHandle ); +- } +- } +- } +- +- if ( special.add ) { +- special.add.call( elem, handleObj ); +- +- if ( !handleObj.handler.guid ) { +- handleObj.handler.guid = handler.guid; +- } +- } +- +- // Add to the element's handler list, delegates in front +- if ( selector ) { +- handlers.splice( handlers.delegateCount++, 0, handleObj ); +- } else { +- handlers.push( handleObj ); +- } +- +- // Keep track of which events have ever been used, for event optimization +- jQuery.event.global[ type ] = true; +- } +- +- // Nullify elem to prevent memory leaks in IE +- elem = null; +- }, +- +- global: {}, +- +- // Detach an event or set of events from an element +- remove: function( elem, types, handler, selector, mappedTypes ) { +- +- var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), +- t, tns, type, origType, namespaces, origCount, +- j, events, special, handle, eventType, handleObj; +- +- if ( !elemData || !(events = elemData.events) ) { +- return; +- } +- +- // Once for each type.namespace in types; type may be omitted +- types = jQuery.trim( hoverHack( types || "" ) ).split(" "); +- for ( t = 0; t < types.length; t++ ) { +- tns = rtypenamespace.exec( types[t] ) || []; +- type = origType = tns[1]; +- namespaces = tns[2]; +- +- // Unbind all events (on this namespace, if provided) for the element +- if ( !type ) { +- for ( type in events ) { +- jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); +- } +- continue; +- } +- +- special = jQuery.event.special[ type ] || {}; +- type = ( selector? special.delegateType : special.bindType ) || type; +- eventType = events[ type ] || []; +- origCount = eventType.length; +- namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; +- +- // Remove matching events +- for ( j = 0; j < eventType.length; j++ ) { +- handleObj = eventType[ j ]; +- +- if ( ( mappedTypes || origType === handleObj.origType ) && +- ( !handler || handler.guid === handleObj.guid ) && +- ( !namespaces || namespaces.test( handleObj.namespace ) ) && +- ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { +- eventType.splice( j--, 1 ); +- +- if ( handleObj.selector ) { +- eventType.delegateCount--; +- } +- if ( special.remove ) { +- special.remove.call( elem, handleObj ); +- } +- } +- } +- +- // Remove generic event handler if we removed something and no more handlers exist +- // (avoids potential for endless recursion during removal of special event handlers) +- if ( eventType.length === 0 && origCount !== eventType.length ) { +- if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { +- jQuery.removeEvent( elem, type, elemData.handle ); +- } +- +- delete events[ type ]; +- } +- } +- +- // Remove the expando if it's no longer used +- if ( jQuery.isEmptyObject( events ) ) { +- handle = elemData.handle; +- if ( handle ) { +- handle.elem = null; +- } +- +- // removeData also checks for emptiness and clears the expando if empty +- // so use it instead of delete +- jQuery.removeData( elem, [ "events", "handle" ], true ); +- } +- }, +- +- // Events that are safe to short-circuit if no handlers are attached. +- // Native DOM events should not be added, they may have inline handlers. +- customEvent: { +- "getData": true, +- "setData": true, +- "changeData": true +- }, +- +- trigger: function( event, data, elem, onlyHandlers ) { +- // Don't do events on text and comment nodes +- if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { +- return; +- } +- +- // Event object or event type +- var type = event.type || event, +- namespaces = [], +- cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; +- +- // focus/blur morphs to focusin/out; ensure we're not firing them right now +- if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { +- return; +- } +- +- if ( type.indexOf( "!" ) >= 0 ) { +- // Exclusive events trigger only for the exact event (no namespaces) +- type = type.slice(0, -1); +- exclusive = true; +- } +- +- if ( type.indexOf( "." ) >= 0 ) { +- // Namespaced trigger; create a regexp to match event type in handle() +- namespaces = type.split("."); +- type = namespaces.shift(); +- namespaces.sort(); +- } +- +- if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { +- // No jQuery handlers for this event type, and it can't have inline handlers +- return; +- } +- +- // Caller can pass in an Event, Object, or just an event type string +- event = typeof event === "object" ? +- // jQuery.Event object +- event[ jQuery.expando ] ? event : +- // Object literal +- new jQuery.Event( type, event ) : +- // Just the event type (string) +- new jQuery.Event( type ); +- +- event.type = type; +- event.isTrigger = true; +- event.exclusive = exclusive; +- event.namespace = namespaces.join( "." ); +- event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; +- ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; +- +- // Handle a global trigger +- if ( !elem ) { +- +- // TODO: Stop taunting the data cache; remove global events and always attach to document +- cache = jQuery.cache; +- for ( i in cache ) { +- if ( cache[ i ].events && cache[ i ].events[ type ] ) { +- jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); +- } +- } +- return; +- } +- +- // Clean up the event in case it is being reused +- event.result = undefined; +- if ( !event.target ) { +- event.target = elem; +- } +- +- // Clone any incoming data and prepend the event, creating the handler arg list +- data = data != null ? jQuery.makeArray( data ) : []; +- data.unshift( event ); +- +- // Allow special events to draw outside the lines +- special = jQuery.event.special[ type ] || {}; +- if ( special.trigger && special.trigger.apply( elem, data ) === false ) { +- return; +- } +- +- // Determine event propagation path in advance, per W3C events spec (#9951) +- // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) +- eventPath = [[ elem, special.bindType || type ]]; +- if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { +- +- bubbleType = special.delegateType || type; +- cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; +- old = null; +- for ( ; cur; cur = cur.parentNode ) { +- eventPath.push([ cur, bubbleType ]); +- old = cur; +- } +- +- // Only add window if we got to document (e.g., not plain obj or detached DOM) +- if ( old && old === elem.ownerDocument ) { +- eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); +- } +- } +- +- // Fire handlers on the event path +- for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { +- +- cur = eventPath[i][0]; +- event.type = eventPath[i][1]; +- +- handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); +- if ( handle ) { +- handle.apply( cur, data ); +- } +- // Note that this is a bare JS function and not a jQuery handler +- handle = ontype && cur[ ontype ]; +- if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { +- event.preventDefault(); +- } +- } +- event.type = type; +- +- // If nobody prevented the default action, do it now +- if ( !onlyHandlers && !event.isDefaultPrevented() ) { +- +- if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && +- !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { +- +- // Call a native DOM method on the target with the same name name as the event. +- // Can't use an .isFunction() check here because IE6/7 fails that test. +- // Don't do default actions on window, that's where global variables be (#6170) +- // IE<9 dies on focus/blur to hidden element (#1486) +- if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { +- +- // Don't re-trigger an onFOO event when we call its FOO() method +- old = elem[ ontype ]; +- +- if ( old ) { +- elem[ ontype ] = null; +- } +- +- // Prevent re-triggering of the same event, since we already bubbled it above +- jQuery.event.triggered = type; +- elem[ type ](); +- jQuery.event.triggered = undefined; +- +- if ( old ) { +- elem[ ontype ] = old; +- } +- } +- } +- } +- +- return event.result; +- }, +- +- dispatch: function( event ) { +- +- // Make a writable jQuery.Event from the native event object +- event = jQuery.event.fix( event || window.event ); +- +- var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), +- delegateCount = handlers.delegateCount, +- args = [].slice.call( arguments, 0 ), +- run_all = !event.exclusive && !event.namespace, +- handlerQueue = [], +- i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; +- +- // Use the fix-ed jQuery.Event rather than the (read-only) native event +- args[0] = event; +- event.delegateTarget = this; +- +- // Determine handlers that should run if there are delegated events +- // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861) +- if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) { +- +- // Pregenerate a single jQuery object for reuse with .is() +- jqcur = jQuery(this); +- jqcur.context = this.ownerDocument || this; +- +- for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { +- selMatch = {}; +- matches = []; +- jqcur[0] = cur; +- for ( i = 0; i < delegateCount; i++ ) { +- handleObj = handlers[ i ]; +- sel = handleObj.selector; +- +- if ( selMatch[ sel ] === undefined ) { +- selMatch[ sel ] = ( +- handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) +- ); +- } +- if ( selMatch[ sel ] ) { +- matches.push( handleObj ); +- } +- } +- if ( matches.length ) { +- handlerQueue.push({ elem: cur, matches: matches }); +- } +- } +- } +- +- // Add the remaining (directly-bound) handlers +- if ( handlers.length > delegateCount ) { +- handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); +- } +- +- // Run delegates first; they may want to stop propagation beneath us +- for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { +- matched = handlerQueue[ i ]; +- event.currentTarget = matched.elem; +- +- for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { +- handleObj = matched.matches[ j ]; +- +- // Triggered event must either 1) be non-exclusive and have no namespace, or +- // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). +- if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { +- +- event.data = handleObj.data; +- event.handleObj = handleObj; +- +- ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) +- .apply( matched.elem, args ); +- +- if ( ret !== undefined ) { +- event.result = ret; +- if ( ret === false ) { +- event.preventDefault(); +- event.stopPropagation(); +- } +- } +- } +- } +- } +- +- return event.result; +- }, +- +- // Includes some event props shared by KeyEvent and MouseEvent +- // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** +- props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), +- +- fixHooks: {}, +- +- keyHooks: { +- props: "char charCode key keyCode".split(" "), +- filter: function( event, original ) { +- +- // Add which for key events +- if ( event.which == null ) { +- event.which = original.charCode != null ? original.charCode : original.keyCode; +- } +- +- return event; +- } +- }, +- +- mouseHooks: { +- props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), +- filter: function( event, original ) { +- var eventDoc, doc, body, +- button = original.button, +- fromElement = original.fromElement; +- +- // Calculate pageX/Y if missing and clientX/Y available +- if ( event.pageX == null && original.clientX != null ) { +- eventDoc = event.target.ownerDocument || document; +- doc = eventDoc.documentElement; +- body = eventDoc.body; +- +- event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); +- event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); +- } +- +- // Add relatedTarget, if necessary +- if ( !event.relatedTarget && fromElement ) { +- event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; +- } +- +- // Add which for click: 1 === left; 2 === middle; 3 === right +- // Note: button is not normalized, so don't use it +- if ( !event.which && button !== undefined ) { +- event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); +- } +- +- return event; +- } +- }, +- +- fix: function( event ) { +- if ( event[ jQuery.expando ] ) { +- return event; +- } +- +- // Create a writable copy of the event object and normalize some properties +- var i, prop, +- originalEvent = event, +- fixHook = jQuery.event.fixHooks[ event.type ] || {}, +- copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; +- +- event = jQuery.Event( originalEvent ); +- +- for ( i = copy.length; i; ) { +- prop = copy[ --i ]; +- event[ prop ] = originalEvent[ prop ]; +- } +- +- // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) +- if ( !event.target ) { +- event.target = originalEvent.srcElement || document; +- } +- +- // Target should not be a text node (#504, Safari) +- if ( event.target.nodeType === 3 ) { +- event.target = event.target.parentNode; +- } +- +- // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) +- if ( event.metaKey === undefined ) { +- event.metaKey = event.ctrlKey; +- } +- +- return fixHook.filter? fixHook.filter( event, originalEvent ) : event; +- }, +- +- special: { +- ready: { +- // Make sure the ready event is setup +- setup: jQuery.bindReady +- }, +- +- load: { +- // Prevent triggered image.load events from bubbling to window.load +- noBubble: true +- }, +- +- focus: { +- delegateType: "focusin" +- }, +- blur: { +- delegateType: "focusout" +- }, +- +- beforeunload: { +- setup: function( data, namespaces, eventHandle ) { +- // We only want to do this special case on windows +- if ( jQuery.isWindow( this ) ) { +- this.onbeforeunload = eventHandle; +- } +- }, +- +- teardown: function( namespaces, eventHandle ) { +- if ( this.onbeforeunload === eventHandle ) { +- this.onbeforeunload = null; +- } +- } +- } +- }, +- +- simulate: function( type, elem, event, bubble ) { +- // Piggyback on a donor event to simulate a different one. +- // Fake originalEvent to avoid donor's stopPropagation, but if the +- // simulated event prevents default then we do the same on the donor. +- var e = jQuery.extend( +- new jQuery.Event(), +- event, +- { type: type, +- isSimulated: true, +- originalEvent: {} +- } +- ); +- if ( bubble ) { +- jQuery.event.trigger( e, null, elem ); +- } else { +- jQuery.event.dispatch.call( elem, e ); +- } +- if ( e.isDefaultPrevented() ) { +- event.preventDefault(); +- } +- } +-}; +- +-// Some plugins are using, but it's undocumented/deprecated and will be removed. +-// The 1.7 special event interface should provide all the hooks needed now. +-jQuery.event.handle = jQuery.event.dispatch; +- +-jQuery.removeEvent = document.removeEventListener ? +- function( elem, type, handle ) { +- if ( elem.removeEventListener ) { +- elem.removeEventListener( type, handle, false ); +- } +- } : +- function( elem, type, handle ) { +- if ( elem.detachEvent ) { +- elem.detachEvent( "on" + type, handle ); +- } +- }; +- +-jQuery.Event = function( src, props ) { +- // Allow instantiation without the 'new' keyword +- if ( !(this instanceof jQuery.Event) ) { +- return new jQuery.Event( src, props ); +- } +- +- // Event object +- if ( src && src.type ) { +- this.originalEvent = src; +- this.type = src.type; +- +- // Events bubbling up the document may have been marked as prevented +- // by a handler lower down the tree; reflect the correct value. +- this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || +- src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; +- +- // Event type +- } else { +- this.type = src; +- } +- +- // Put explicitly provided properties onto the event object +- if ( props ) { +- jQuery.extend( this, props ); +- } +- +- // Create a timestamp if incoming event doesn't have one +- this.timeStamp = src && src.timeStamp || jQuery.now(); +- +- // Mark it as fixed +- this[ jQuery.expando ] = true; +-}; +- +-function returnFalse() { +- return false; +-} +-function returnTrue() { +- return true; +-} +- +-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +-jQuery.Event.prototype = { +- preventDefault: function() { +- this.isDefaultPrevented = returnTrue; +- +- var e = this.originalEvent; +- if ( !e ) { +- return; +- } +- +- // if preventDefault exists run it on the original event +- if ( e.preventDefault ) { +- e.preventDefault(); +- +- // otherwise set the returnValue property of the original event to false (IE) +- } else { +- e.returnValue = false; +- } +- }, +- stopPropagation: function() { +- this.isPropagationStopped = returnTrue; +- +- var e = this.originalEvent; +- if ( !e ) { +- return; +- } +- // if stopPropagation exists run it on the original event +- if ( e.stopPropagation ) { +- e.stopPropagation(); +- } +- // otherwise set the cancelBubble property of the original event to true (IE) +- e.cancelBubble = true; +- }, +- stopImmediatePropagation: function() { +- this.isImmediatePropagationStopped = returnTrue; +- this.stopPropagation(); +- }, +- isDefaultPrevented: returnFalse, +- isPropagationStopped: returnFalse, +- isImmediatePropagationStopped: returnFalse +-}; +- +-// Create mouseenter/leave events using mouseover/out and event-time checks +-jQuery.each({ +- mouseenter: "mouseover", +- mouseleave: "mouseout" +-}, function( orig, fix ) { +- jQuery.event.special[ orig ] = { +- delegateType: fix, +- bindType: fix, +- +- handle: function( event ) { +- var target = this, +- related = event.relatedTarget, +- handleObj = event.handleObj, +- selector = handleObj.selector, +- ret; +- +- // For mousenter/leave call the handler if related is outside the target. +- // NB: No relatedTarget if the mouse left/entered the browser window +- if ( !related || (related !== target && !jQuery.contains( target, related )) ) { +- event.type = handleObj.origType; +- ret = handleObj.handler.apply( this, arguments ); +- event.type = fix; +- } +- return ret; +- } +- }; +-}); +- +-// IE submit delegation +-if ( !jQuery.support.submitBubbles ) { +- +- jQuery.event.special.submit = { +- setup: function() { +- // Only need this for delegated form submit events +- if ( jQuery.nodeName( this, "form" ) ) { +- return false; +- } +- +- // Lazy-add a submit handler when a descendant form may potentially be submitted +- jQuery.event.add( this, "click._submit keypress._submit", function( e ) { +- // Node name check avoids a VML-related crash in IE (#9807) +- var elem = e.target, +- form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; +- if ( form && !form._submit_attached ) { +- jQuery.event.add( form, "submit._submit", function( event ) { +- // If form was submitted by the user, bubble the event up the tree +- if ( this.parentNode && !event.isTrigger ) { +- jQuery.event.simulate( "submit", this.parentNode, event, true ); +- } +- }); +- form._submit_attached = true; +- } +- }); +- // return undefined since we don't need an event listener +- }, +- +- teardown: function() { +- // Only need this for delegated form submit events +- if ( jQuery.nodeName( this, "form" ) ) { +- return false; +- } +- +- // Remove delegated handlers; cleanData eventually reaps submit handlers attached above +- jQuery.event.remove( this, "._submit" ); +- } +- }; +-} +- +-// IE change delegation and checkbox/radio fix +-if ( !jQuery.support.changeBubbles ) { +- +- jQuery.event.special.change = { +- +- setup: function() { +- +- if ( rformElems.test( this.nodeName ) ) { +- // IE doesn't fire change on a check/radio until blur; trigger it on click +- // after a propertychange. Eat the blur-change in special.change.handle. +- // This still fires onchange a second time for check/radio after blur. +- if ( this.type === "checkbox" || this.type === "radio" ) { +- jQuery.event.add( this, "propertychange._change", function( event ) { +- if ( event.originalEvent.propertyName === "checked" ) { +- this._just_changed = true; +- } +- }); +- jQuery.event.add( this, "click._change", function( event ) { +- if ( this._just_changed && !event.isTrigger ) { +- this._just_changed = false; +- jQuery.event.simulate( "change", this, event, true ); +- } +- }); +- } +- return false; +- } +- // Delegated event; lazy-add a change handler on descendant inputs +- jQuery.event.add( this, "beforeactivate._change", function( e ) { +- var elem = e.target; +- +- if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { +- jQuery.event.add( elem, "change._change", function( event ) { +- if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { +- jQuery.event.simulate( "change", this.parentNode, event, true ); +- } +- }); +- elem._change_attached = true; +- } +- }); +- }, +- +- handle: function( event ) { +- var elem = event.target; +- +- // Swallow native change events from checkbox/radio, we already triggered them above +- if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { +- return event.handleObj.handler.apply( this, arguments ); +- } +- }, +- +- teardown: function() { +- jQuery.event.remove( this, "._change" ); +- +- return rformElems.test( this.nodeName ); +- } +- }; +-} +- +-// Create "bubbling" focus and blur events +-if ( !jQuery.support.focusinBubbles ) { +- jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { +- +- // Attach a single capturing handler while someone wants focusin/focusout +- var attaches = 0, +- handler = function( event ) { +- jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); +- }; +- +- jQuery.event.special[ fix ] = { +- setup: function() { +- if ( attaches++ === 0 ) { +- document.addEventListener( orig, handler, true ); +- } +- }, +- teardown: function() { +- if ( --attaches === 0 ) { +- document.removeEventListener( orig, handler, true ); +- } +- } +- }; +- }); +-} +- +-jQuery.fn.extend({ +- +- on: function( types, selector, data, fn, /*INTERNAL*/ one ) { +- var origFn, type; +- +- // Types can be a map of types/handlers +- if ( typeof types === "object" ) { +- // ( types-Object, selector, data ) +- if ( typeof selector !== "string" ) { +- // ( types-Object, data ) +- data = selector; +- selector = undefined; +- } +- for ( type in types ) { +- this.on( type, selector, data, types[ type ], one ); +- } +- return this; +- } +- +- if ( data == null && fn == null ) { +- // ( types, fn ) +- fn = selector; +- data = selector = undefined; +- } else if ( fn == null ) { +- if ( typeof selector === "string" ) { +- // ( types, selector, fn ) +- fn = data; +- data = undefined; +- } else { +- // ( types, data, fn ) +- fn = data; +- data = selector; +- selector = undefined; +- } +- } +- if ( fn === false ) { +- fn = returnFalse; +- } else if ( !fn ) { +- return this; +- } +- +- if ( one === 1 ) { +- origFn = fn; +- fn = function( event ) { +- // Can use an empty set, since event contains the info +- jQuery().off( event ); +- return origFn.apply( this, arguments ); +- }; +- // Use same guid so caller can remove using origFn +- fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); +- } +- return this.each( function() { +- jQuery.event.add( this, types, fn, data, selector ); +- }); +- }, +- one: function( types, selector, data, fn ) { +- return this.on.call( this, types, selector, data, fn, 1 ); +- }, +- off: function( types, selector, fn ) { +- if ( types && types.preventDefault && types.handleObj ) { +- // ( event ) dispatched jQuery.Event +- var handleObj = types.handleObj; +- jQuery( types.delegateTarget ).off( +- handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type, +- handleObj.selector, +- handleObj.handler +- ); +- return this; +- } +- if ( typeof types === "object" ) { +- // ( types-object [, selector] ) +- for ( var type in types ) { +- this.off( type, selector, types[ type ] ); +- } +- return this; +- } +- if ( selector === false || typeof selector === "function" ) { +- // ( types [, fn] ) +- fn = selector; +- selector = undefined; +- } +- if ( fn === false ) { +- fn = returnFalse; +- } +- return this.each(function() { +- jQuery.event.remove( this, types, fn, selector ); +- }); +- }, +- +- bind: function( types, data, fn ) { +- return this.on( types, null, data, fn ); +- }, +- unbind: function( types, fn ) { +- return this.off( types, null, fn ); +- }, +- +- live: function( types, data, fn ) { +- jQuery( this.context ).on( types, this.selector, data, fn ); +- return this; +- }, +- die: function( types, fn ) { +- jQuery( this.context ).off( types, this.selector || "**", fn ); +- return this; +- }, +- +- delegate: function( selector, types, data, fn ) { +- return this.on( types, selector, data, fn ); +- }, +- undelegate: function( selector, types, fn ) { +- // ( namespace ) or ( selector, types [, fn] ) +- return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); +- }, +- +- trigger: function( type, data ) { +- return this.each(function() { +- jQuery.event.trigger( type, data, this ); +- }); +- }, +- triggerHandler: function( type, data ) { +- if ( this[0] ) { +- return jQuery.event.trigger( type, data, this[0], true ); +- } +- }, +- +- toggle: function( fn ) { +- // Save reference to arguments for access in closure +- var args = arguments, +- guid = fn.guid || jQuery.guid++, +- i = 0, +- toggler = function( event ) { +- // Figure out which function to execute +- var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; +- jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); +- +- // Make sure that clicks stop +- event.preventDefault(); +- +- // and execute the function +- return args[ lastToggle ].apply( this, arguments ) || false; +- }; +- +- // link all the functions, so any of them can unbind this click handler +- toggler.guid = guid; +- while ( i < args.length ) { +- args[ i++ ].guid = guid; +- } +- +- return this.click( toggler ); +- }, +- +- hover: function( fnOver, fnOut ) { +- return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); +- } +-}); +- +-jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + +- "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + +- "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { +- +- // Handle event binding +- jQuery.fn[ name ] = function( data, fn ) { +- if ( fn == null ) { +- fn = data; +- data = null; +- } +- +- return arguments.length > 0 ? +- this.on( name, null, data, fn ) : +- this.trigger( name ); +- }; +- +- if ( jQuery.attrFn ) { +- jQuery.attrFn[ name ] = true; +- } +- +- if ( rkeyEvent.test( name ) ) { +- jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; +- } +- +- if ( rmouseEvent.test( name ) ) { +- jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; +- } +-}); +- +- +- +-/*! +- * Sizzle CSS Selector Engine +- * Copyright 2011, The Dojo Foundation +- * Released under the MIT, BSD, and GPL Licenses. +- * More information: http://sizzlejs.com/ +- */ +-(function(){ +- +-var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +- expando = "sizcache" + (Math.random() + '').replace('.', ''), +- done = 0, +- toString = Object.prototype.toString, +- hasDuplicate = false, +- baseHasDuplicate = true, +- rBackslash = /\\/g, +- rReturn = /\r\n/g, +- rNonWord = /\W/; +- +-// Here we check if the JavaScript engine is using some sort of +-// optimization where it does not always call our comparision +-// function. If that is the case, discard the hasDuplicate value. +-// Thus far that includes Google Chrome. +-[0, 0].sort(function() { +- baseHasDuplicate = false; +- return 0; +-}); +- +-var Sizzle = function( selector, context, results, seed ) { +- results = results || []; +- context = context || document; +- +- var origContext = context; +- +- if ( context.nodeType !== 1 && context.nodeType !== 9 ) { +- return []; +- } +- +- if ( !selector || typeof selector !== "string" ) { +- return results; +- } +- +- var m, set, checkSet, extra, ret, cur, pop, i, +- prune = true, +- contextXML = Sizzle.isXML( context ), +- parts = [], +- soFar = selector; +- +- // Reset the position of the chunker regexp (start from head) +- do { +- chunker.exec( "" ); +- m = chunker.exec( soFar ); +- +- if ( m ) { +- soFar = m[3]; +- +- parts.push( m[1] ); +- +- if ( m[2] ) { +- extra = m[3]; +- break; +- } +- } +- } while ( m ); +- +- if ( parts.length > 1 && origPOS.exec( selector ) ) { +- +- if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { +- set = posProcess( parts[0] + parts[1], context, seed ); +- +- } else { +- set = Expr.relative[ parts[0] ] ? +- [ context ] : +- Sizzle( parts.shift(), context ); +- +- while ( parts.length ) { +- selector = parts.shift(); +- +- if ( Expr.relative[ selector ] ) { +- selector += parts.shift(); +- } +- +- set = posProcess( selector, set, seed ); +- } +- } +- +- } else { +- // Take a shortcut and set the context if the root selector is an ID +- // (but not if it'll be faster if the inner selector is an ID) +- if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && +- Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { +- +- ret = Sizzle.find( parts.shift(), context, contextXML ); +- context = ret.expr ? +- Sizzle.filter( ret.expr, ret.set )[0] : +- ret.set[0]; +- } +- +- if ( context ) { +- ret = seed ? +- { expr: parts.pop(), set: makeArray(seed) } : +- Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); +- +- set = ret.expr ? +- Sizzle.filter( ret.expr, ret.set ) : +- ret.set; +- +- if ( parts.length > 0 ) { +- checkSet = makeArray( set ); +- +- } else { +- prune = false; +- } +- +- while ( parts.length ) { +- cur = parts.pop(); +- pop = cur; +- +- if ( !Expr.relative[ cur ] ) { +- cur = ""; +- } else { +- pop = parts.pop(); +- } +- +- if ( pop == null ) { +- pop = context; +- } +- +- Expr.relative[ cur ]( checkSet, pop, contextXML ); +- } +- +- } else { +- checkSet = parts = []; +- } +- } +- +- if ( !checkSet ) { +- checkSet = set; +- } +- +- if ( !checkSet ) { +- Sizzle.error( cur || selector ); +- } +- +- if ( toString.call(checkSet) === "[object Array]" ) { +- if ( !prune ) { +- results.push.apply( results, checkSet ); +- +- } else if ( context && context.nodeType === 1 ) { +- for ( i = 0; checkSet[i] != null; i++ ) { +- if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { +- results.push( set[i] ); +- } +- } +- +- } else { +- for ( i = 0; checkSet[i] != null; i++ ) { +- if ( checkSet[i] && checkSet[i].nodeType === 1 ) { +- results.push( set[i] ); +- } +- } +- } +- +- } else { +- makeArray( checkSet, results ); +- } +- +- if ( extra ) { +- Sizzle( extra, origContext, results, seed ); +- Sizzle.uniqueSort( results ); +- } +- +- return results; +-}; +- +-Sizzle.uniqueSort = function( results ) { +- if ( sortOrder ) { +- hasDuplicate = baseHasDuplicate; +- results.sort( sortOrder ); +- +- if ( hasDuplicate ) { +- for ( var i = 1; i < results.length; i++ ) { +- if ( results[i] === results[ i - 1 ] ) { +- results.splice( i--, 1 ); +- } +- } +- } +- } +- +- return results; +-}; +- +-Sizzle.matches = function( expr, set ) { +- return Sizzle( expr, null, null, set ); +-}; +- +-Sizzle.matchesSelector = function( node, expr ) { +- return Sizzle( expr, null, null, [node] ).length > 0; +-}; +- +-Sizzle.find = function( expr, context, isXML ) { +- var set, i, len, match, type, left; +- +- if ( !expr ) { +- return []; +- } +- +- for ( i = 0, len = Expr.order.length; i < len; i++ ) { +- type = Expr.order[i]; +- +- if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { +- left = match[1]; +- match.splice( 1, 1 ); +- +- if ( left.substr( left.length - 1 ) !== "\\" ) { +- match[1] = (match[1] || "").replace( rBackslash, "" ); +- set = Expr.find[ type ]( match, context, isXML ); +- +- if ( set != null ) { +- expr = expr.replace( Expr.match[ type ], "" ); +- break; +- } +- } +- } +- } +- +- if ( !set ) { +- set = typeof context.getElementsByTagName !== "undefined" ? +- context.getElementsByTagName( "*" ) : +- []; +- } +- +- return { set: set, expr: expr }; +-}; +- +-Sizzle.filter = function( expr, set, inplace, not ) { +- var match, anyFound, +- type, found, item, filter, left, +- i, pass, +- old = expr, +- result = [], +- curLoop = set, +- isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); +- +- while ( expr && set.length ) { +- for ( type in Expr.filter ) { +- if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { +- filter = Expr.filter[ type ]; +- left = match[1]; +- +- anyFound = false; +- +- match.splice(1,1); +- +- if ( left.substr( left.length - 1 ) === "\\" ) { +- continue; +- } +- +- if ( curLoop === result ) { +- result = []; +- } +- +- if ( Expr.preFilter[ type ] ) { +- match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); +- +- if ( !match ) { +- anyFound = found = true; +- +- } else if ( match === true ) { +- continue; +- } +- } +- +- if ( match ) { +- for ( i = 0; (item = curLoop[i]) != null; i++ ) { +- if ( item ) { +- found = filter( item, match, i, curLoop ); +- pass = not ^ found; +- +- if ( inplace && found != null ) { +- if ( pass ) { +- anyFound = true; +- +- } else { +- curLoop[i] = false; +- } +- +- } else if ( pass ) { +- result.push( item ); +- anyFound = true; +- } +- } +- } +- } +- +- if ( found !== undefined ) { +- if ( !inplace ) { +- curLoop = result; +- } +- +- expr = expr.replace( Expr.match[ type ], "" ); +- +- if ( !anyFound ) { +- return []; +- } +- +- break; +- } +- } +- } +- +- // Improper expression +- if ( expr === old ) { +- if ( anyFound == null ) { +- Sizzle.error( expr ); +- +- } else { +- break; +- } +- } +- +- old = expr; +- } +- +- return curLoop; +-}; +- +-Sizzle.error = function( msg ) { +- throw new Error( "Syntax error, unrecognized expression: " + msg ); +-}; +- +-/** +- * Utility function for retreiving the text value of an array of DOM nodes +- * @param {Array|Element} elem +- */ +-var getText = Sizzle.getText = function( elem ) { +- var i, node, +- nodeType = elem.nodeType, +- ret = ""; +- +- if ( nodeType ) { +- if ( nodeType === 1 || nodeType === 9 ) { +- // Use textContent || innerText for elements +- if ( typeof elem.textContent === 'string' ) { +- return elem.textContent; +- } else if ( typeof elem.innerText === 'string' ) { +- // Replace IE's carriage returns +- return elem.innerText.replace( rReturn, '' ); +- } else { +- // Traverse it's children +- for ( elem = elem.firstChild; elem; elem = elem.nextSibling) { +- ret += getText( elem ); +- } +- } +- } else if ( nodeType === 3 || nodeType === 4 ) { +- return elem.nodeValue; +- } +- } else { +- +- // If no nodeType, this is expected to be an array +- for ( i = 0; (node = elem[i]); i++ ) { +- // Do not traverse comment nodes +- if ( node.nodeType !== 8 ) { +- ret += getText( node ); +- } +- } +- } +- return ret; +-}; +- +-var Expr = Sizzle.selectors = { +- order: [ "ID", "NAME", "TAG" ], +- +- match: { +- ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, +- CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, +- NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, +- ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, +- TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, +- CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, +- POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, +- PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ +- }, +- +- leftMatch: {}, +- +- attrMap: { +- "class": "className", +- "for": "htmlFor" +- }, +- +- attrHandle: { +- href: function( elem ) { +- return elem.getAttribute( "href" ); +- }, +- type: function( elem ) { +- return elem.getAttribute( "type" ); +- } +- }, +- +- relative: { +- "+": function(checkSet, part){ +- var isPartStr = typeof part === "string", +- isTag = isPartStr && !rNonWord.test( part ), +- isPartStrNotTag = isPartStr && !isTag; +- +- if ( isTag ) { +- part = part.toLowerCase(); +- } +- +- for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { +- if ( (elem = checkSet[i]) ) { +- while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} +- +- checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? +- elem || false : +- elem === part; +- } +- } +- +- if ( isPartStrNotTag ) { +- Sizzle.filter( part, checkSet, true ); +- } +- }, +- +- ">": function( checkSet, part ) { +- var elem, +- isPartStr = typeof part === "string", +- i = 0, +- l = checkSet.length; +- +- if ( isPartStr && !rNonWord.test( part ) ) { +- part = part.toLowerCase(); +- +- for ( ; i < l; i++ ) { +- elem = checkSet[i]; +- +- if ( elem ) { +- var parent = elem.parentNode; +- checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; +- } +- } +- +- } else { +- for ( ; i < l; i++ ) { +- elem = checkSet[i]; +- +- if ( elem ) { +- checkSet[i] = isPartStr ? +- elem.parentNode : +- elem.parentNode === part; +- } +- } +- +- if ( isPartStr ) { +- Sizzle.filter( part, checkSet, true ); +- } +- } +- }, +- +- "": function(checkSet, part, isXML){ +- var nodeCheck, +- doneName = done++, +- checkFn = dirCheck; +- +- if ( typeof part === "string" && !rNonWord.test( part ) ) { +- part = part.toLowerCase(); +- nodeCheck = part; +- checkFn = dirNodeCheck; +- } +- +- checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); +- }, +- +- "~": function( checkSet, part, isXML ) { +- var nodeCheck, +- doneName = done++, +- checkFn = dirCheck; +- +- if ( typeof part === "string" && !rNonWord.test( part ) ) { +- part = part.toLowerCase(); +- nodeCheck = part; +- checkFn = dirNodeCheck; +- } +- +- checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); +- } +- }, +- +- find: { +- ID: function( match, context, isXML ) { +- if ( typeof context.getElementById !== "undefined" && !isXML ) { +- var m = context.getElementById(match[1]); +- // Check parentNode to catch when Blackberry 4.6 returns +- // nodes that are no longer in the document #6963 +- return m && m.parentNode ? [m] : []; +- } +- }, +- +- NAME: function( match, context ) { +- if ( typeof context.getElementsByName !== "undefined" ) { +- var ret = [], +- results = context.getElementsByName( match[1] ); +- +- for ( var i = 0, l = results.length; i < l; i++ ) { +- if ( results[i].getAttribute("name") === match[1] ) { +- ret.push( results[i] ); +- } +- } +- +- return ret.length === 0 ? null : ret; +- } +- }, +- +- TAG: function( match, context ) { +- if ( typeof context.getElementsByTagName !== "undefined" ) { +- return context.getElementsByTagName( match[1] ); +- } +- } +- }, +- preFilter: { +- CLASS: function( match, curLoop, inplace, result, not, isXML ) { +- match = " " + match[1].replace( rBackslash, "" ) + " "; +- +- if ( isXML ) { +- return match; +- } +- +- for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { +- if ( elem ) { +- if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { +- if ( !inplace ) { +- result.push( elem ); +- } +- +- } else if ( inplace ) { +- curLoop[i] = false; +- } +- } +- } +- +- return false; +- }, +- +- ID: function( match ) { +- return match[1].replace( rBackslash, "" ); +- }, +- +- TAG: function( match, curLoop ) { +- return match[1].replace( rBackslash, "" ).toLowerCase(); +- }, +- +- CHILD: function( match ) { +- if ( match[1] === "nth" ) { +- if ( !match[2] ) { +- Sizzle.error( match[0] ); +- } +- +- match[2] = match[2].replace(/^\+|\s*/g, ''); +- +- // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' +- var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( +- match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || +- !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); +- +- // calculate the numbers (first)n+(last) including if they are negative +- match[2] = (test[1] + (test[2] || 1)) - 0; +- match[3] = test[3] - 0; +- } +- else if ( match[2] ) { +- Sizzle.error( match[0] ); +- } +- +- // TODO: Move to normal caching system +- match[0] = done++; +- +- return match; +- }, +- +- ATTR: function( match, curLoop, inplace, result, not, isXML ) { +- var name = match[1] = match[1].replace( rBackslash, "" ); +- +- if ( !isXML && Expr.attrMap[name] ) { +- match[1] = Expr.attrMap[name]; +- } +- +- // Handle if an un-quoted value was used +- match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); +- +- if ( match[2] === "~=" ) { +- match[4] = " " + match[4] + " "; +- } +- +- return match; +- }, +- +- PSEUDO: function( match, curLoop, inplace, result, not ) { +- if ( match[1] === "not" ) { +- // If we're dealing with a complex expression, or a simple one +- if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { +- match[3] = Sizzle(match[3], null, null, curLoop); +- +- } else { +- var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); +- +- if ( !inplace ) { +- result.push.apply( result, ret ); +- } +- +- return false; +- } +- +- } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { +- return true; +- } +- +- return match; +- }, +- +- POS: function( match ) { +- match.unshift( true ); +- +- return match; +- } +- }, +- +- filters: { +- enabled: function( elem ) { +- return elem.disabled === false && elem.type !== "hidden"; +- }, +- +- disabled: function( elem ) { +- return elem.disabled === true; +- }, +- +- checked: function( elem ) { +- return elem.checked === true; +- }, +- +- selected: function( elem ) { +- // Accessing this property makes selected-by-default +- // options in Safari work properly +- if ( elem.parentNode ) { +- elem.parentNode.selectedIndex; +- } +- +- return elem.selected === true; +- }, +- +- parent: function( elem ) { +- return !!elem.firstChild; +- }, +- +- empty: function( elem ) { +- return !elem.firstChild; +- }, +- +- has: function( elem, i, match ) { +- return !!Sizzle( match[3], elem ).length; +- }, +- +- header: function( elem ) { +- return (/h\d/i).test( elem.nodeName ); +- }, +- +- text: function( elem ) { +- var attr = elem.getAttribute( "type" ), type = elem.type; +- // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) +- // use getAttribute instead to test this case +- return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); +- }, +- +- radio: function( elem ) { +- return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; +- }, +- +- checkbox: function( elem ) { +- return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; +- }, +- +- file: function( elem ) { +- return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; +- }, +- +- password: function( elem ) { +- return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; +- }, +- +- submit: function( elem ) { +- var name = elem.nodeName.toLowerCase(); +- return (name === "input" || name === "button") && "submit" === elem.type; +- }, +- +- image: function( elem ) { +- return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; +- }, +- +- reset: function( elem ) { +- var name = elem.nodeName.toLowerCase(); +- return (name === "input" || name === "button") && "reset" === elem.type; +- }, +- +- button: function( elem ) { +- var name = elem.nodeName.toLowerCase(); +- return name === "input" && "button" === elem.type || name === "button"; +- }, +- +- input: function( elem ) { +- return (/input|select|textarea|button/i).test( elem.nodeName ); +- }, +- +- focus: function( elem ) { +- return elem === elem.ownerDocument.activeElement; +- } +- }, +- setFilters: { +- first: function( elem, i ) { +- return i === 0; +- }, +- +- last: function( elem, i, match, array ) { +- return i === array.length - 1; +- }, +- +- even: function( elem, i ) { +- return i % 2 === 0; +- }, +- +- odd: function( elem, i ) { +- return i % 2 === 1; +- }, +- +- lt: function( elem, i, match ) { +- return i < match[3] - 0; +- }, +- +- gt: function( elem, i, match ) { +- return i > match[3] - 0; +- }, +- +- nth: function( elem, i, match ) { +- return match[3] - 0 === i; +- }, +- +- eq: function( elem, i, match ) { +- return match[3] - 0 === i; +- } +- }, +- filter: { +- PSEUDO: function( elem, match, i, array ) { +- var name = match[1], +- filter = Expr.filters[ name ]; +- +- if ( filter ) { +- return filter( elem, i, match, array ); +- +- } else if ( name === "contains" ) { +- return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; +- +- } else if ( name === "not" ) { +- var not = match[3]; +- +- for ( var j = 0, l = not.length; j < l; j++ ) { +- if ( not[j] === elem ) { +- return false; +- } +- } +- +- return true; +- +- } else { +- Sizzle.error( name ); +- } +- }, +- +- CHILD: function( elem, match ) { +- var first, last, +- doneName, parent, cache, +- count, diff, +- type = match[1], +- node = elem; +- +- switch ( type ) { +- case "only": +- case "first": +- while ( (node = node.previousSibling) ) { +- if ( node.nodeType === 1 ) { +- return false; +- } +- } +- +- if ( type === "first" ) { +- return true; +- } +- +- node = elem; +- +- case "last": +- while ( (node = node.nextSibling) ) { +- if ( node.nodeType === 1 ) { +- return false; +- } +- } +- +- return true; +- +- case "nth": +- first = match[2]; +- last = match[3]; +- +- if ( first === 1 && last === 0 ) { +- return true; +- } +- +- doneName = match[0]; +- parent = elem.parentNode; +- +- if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { +- count = 0; +- +- for ( node = parent.firstChild; node; node = node.nextSibling ) { +- if ( node.nodeType === 1 ) { +- node.nodeIndex = ++count; +- } +- } +- +- parent[ expando ] = doneName; +- } +- +- diff = elem.nodeIndex - last; +- +- if ( first === 0 ) { +- return diff === 0; +- +- } else { +- return ( diff % first === 0 && diff / first >= 0 ); +- } +- } +- }, +- +- ID: function( elem, match ) { +- return elem.nodeType === 1 && elem.getAttribute("id") === match; +- }, +- +- TAG: function( elem, match ) { +- return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; +- }, +- +- CLASS: function( elem, match ) { +- return (" " + (elem.className || elem.getAttribute("class")) + " ") +- .indexOf( match ) > -1; +- }, +- +- ATTR: function( elem, match ) { +- var name = match[1], +- result = Sizzle.attr ? +- Sizzle.attr( elem, name ) : +- Expr.attrHandle[ name ] ? +- Expr.attrHandle[ name ]( elem ) : +- elem[ name ] != null ? +- elem[ name ] : +- elem.getAttribute( name ), +- value = result + "", +- type = match[2], +- check = match[4]; +- +- return result == null ? +- type === "!=" : +- !type && Sizzle.attr ? +- result != null : +- type === "=" ? +- value === check : +- type === "*=" ? +- value.indexOf(check) >= 0 : +- type === "~=" ? +- (" " + value + " ").indexOf(check) >= 0 : +- !check ? +- value && result !== false : +- type === "!=" ? +- value !== check : +- type === "^=" ? +- value.indexOf(check) === 0 : +- type === "$=" ? +- value.substr(value.length - check.length) === check : +- type === "|=" ? +- value === check || value.substr(0, check.length + 1) === check + "-" : +- false; +- }, +- +- POS: function( elem, match, i, array ) { +- var name = match[2], +- filter = Expr.setFilters[ name ]; +- +- if ( filter ) { +- return filter( elem, i, match, array ); +- } +- } +- } +-}; +- +-var origPOS = Expr.match.POS, +- fescape = function(all, num){ +- return "\\" + (num - 0 + 1); +- }; +- +-for ( var type in Expr.match ) { +- Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); +- Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +-} +- +-var makeArray = function( array, results ) { +- array = Array.prototype.slice.call( array, 0 ); +- +- if ( results ) { +- results.push.apply( results, array ); +- return results; +- } +- +- return array; +-}; +- +-// Perform a simple check to determine if the browser is capable of +-// converting a NodeList to an array using builtin methods. +-// Also verifies that the returned array holds DOM nodes +-// (which is not the case in the Blackberry browser) +-try { +- Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; +- +-// Provide a fallback method if it does not work +-} catch( e ) { +- makeArray = function( array, results ) { +- var i = 0, +- ret = results || []; +- +- if ( toString.call(array) === "[object Array]" ) { +- Array.prototype.push.apply( ret, array ); +- +- } else { +- if ( typeof array.length === "number" ) { +- for ( var l = array.length; i < l; i++ ) { +- ret.push( array[i] ); +- } +- +- } else { +- for ( ; array[i]; i++ ) { +- ret.push( array[i] ); +- } +- } +- } +- +- return ret; +- }; +-} +- +-var sortOrder, siblingCheck; +- +-if ( document.documentElement.compareDocumentPosition ) { +- sortOrder = function( a, b ) { +- if ( a === b ) { +- hasDuplicate = true; +- return 0; +- } +- +- if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { +- return a.compareDocumentPosition ? -1 : 1; +- } +- +- return a.compareDocumentPosition(b) & 4 ? -1 : 1; +- }; +- +-} else { +- sortOrder = function( a, b ) { +- // The nodes are identical, we can exit early +- if ( a === b ) { +- hasDuplicate = true; +- return 0; +- +- // Fallback to using sourceIndex (in IE) if it's available on both nodes +- } else if ( a.sourceIndex && b.sourceIndex ) { +- return a.sourceIndex - b.sourceIndex; +- } +- +- var al, bl, +- ap = [], +- bp = [], +- aup = a.parentNode, +- bup = b.parentNode, +- cur = aup; +- +- // If the nodes are siblings (or identical) we can do a quick check +- if ( aup === bup ) { +- return siblingCheck( a, b ); +- +- // If no parents were found then the nodes are disconnected +- } else if ( !aup ) { +- return -1; +- +- } else if ( !bup ) { +- return 1; +- } +- +- // Otherwise they're somewhere else in the tree so we need +- // to build up a full list of the parentNodes for comparison +- while ( cur ) { +- ap.unshift( cur ); +- cur = cur.parentNode; +- } +- +- cur = bup; +- +- while ( cur ) { +- bp.unshift( cur ); +- cur = cur.parentNode; +- } +- +- al = ap.length; +- bl = bp.length; +- +- // Start walking down the tree looking for a discrepancy +- for ( var i = 0; i < al && i < bl; i++ ) { +- if ( ap[i] !== bp[i] ) { +- return siblingCheck( ap[i], bp[i] ); +- } +- } +- +- // We ended someplace up the tree so do a sibling check +- return i === al ? +- siblingCheck( a, bp[i], -1 ) : +- siblingCheck( ap[i], b, 1 ); +- }; +- +- siblingCheck = function( a, b, ret ) { +- if ( a === b ) { +- return ret; +- } +- +- var cur = a.nextSibling; +- +- while ( cur ) { +- if ( cur === b ) { +- return -1; +- } +- +- cur = cur.nextSibling; +- } +- +- return 1; +- }; +-} +- +-// Check to see if the browser returns elements by name when +-// querying by getElementById (and provide a workaround) +-(function(){ +- // We're going to inject a fake input element with a specified name +- var form = document.createElement("div"), +- id = "script" + (new Date()).getTime(), +- root = document.documentElement; +- +- form.innerHTML = ""; +- +- // Inject it into the root element, check its status, and remove it quickly +- root.insertBefore( form, root.firstChild ); +- +- // The workaround has to do additional checks after a getElementById +- // Which slows things down for other browsers (hence the branching) +- if ( document.getElementById( id ) ) { +- Expr.find.ID = function( match, context, isXML ) { +- if ( typeof context.getElementById !== "undefined" && !isXML ) { +- var m = context.getElementById(match[1]); +- +- return m ? +- m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? +- [m] : +- undefined : +- []; +- } +- }; +- +- Expr.filter.ID = function( elem, match ) { +- var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); +- +- return elem.nodeType === 1 && node && node.nodeValue === match; +- }; +- } +- +- root.removeChild( form ); +- +- // release memory in IE +- root = form = null; +-})(); +- +-(function(){ +- // Check to see if the browser returns only elements +- // when doing getElementsByTagName("*") +- +- // Create a fake element +- var div = document.createElement("div"); +- div.appendChild( document.createComment("") ); +- +- // Make sure no comments are found +- if ( div.getElementsByTagName("*").length > 0 ) { +- Expr.find.TAG = function( match, context ) { +- var results = context.getElementsByTagName( match[1] ); +- +- // Filter out possible comments +- if ( match[1] === "*" ) { +- var tmp = []; +- +- for ( var i = 0; results[i]; i++ ) { +- if ( results[i].nodeType === 1 ) { +- tmp.push( results[i] ); +- } +- } +- +- results = tmp; +- } +- +- return results; +- }; +- } +- +- // Check to see if an attribute returns normalized href attributes +- div.innerHTML = ""; +- +- if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && +- div.firstChild.getAttribute("href") !== "#" ) { +- +- Expr.attrHandle.href = function( elem ) { +- return elem.getAttribute( "href", 2 ); +- }; +- } +- +- // release memory in IE +- div = null; +-})(); +- +-if ( document.querySelectorAll ) { +- (function(){ +- var oldSizzle = Sizzle, +- div = document.createElement("div"), +- id = "__sizzle__"; +- +- div.innerHTML = "

"; +- +- // Safari can't handle uppercase or unicode characters when +- // in quirks mode. +- if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { +- return; +- } +- +- Sizzle = function( query, context, extra, seed ) { +- context = context || document; +- +- // Only use querySelectorAll on non-XML documents +- // (ID selectors don't work in non-HTML documents) +- if ( !seed && !Sizzle.isXML(context) ) { +- // See if we find a selector to speed up +- var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); +- +- if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { +- // Speed-up: Sizzle("TAG") +- if ( match[1] ) { +- return makeArray( context.getElementsByTagName( query ), extra ); +- +- // Speed-up: Sizzle(".CLASS") +- } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { +- return makeArray( context.getElementsByClassName( match[2] ), extra ); +- } +- } +- +- if ( context.nodeType === 9 ) { +- // Speed-up: Sizzle("body") +- // The body element only exists once, optimize finding it +- if ( query === "body" && context.body ) { +- return makeArray( [ context.body ], extra ); +- +- // Speed-up: Sizzle("#ID") +- } else if ( match && match[3] ) { +- var elem = context.getElementById( match[3] ); +- +- // Check parentNode to catch when Blackberry 4.6 returns +- // nodes that are no longer in the document #6963 +- if ( elem && elem.parentNode ) { +- // Handle the case where IE and Opera return items +- // by name instead of ID +- if ( elem.id === match[3] ) { +- return makeArray( [ elem ], extra ); +- } +- +- } else { +- return makeArray( [], extra ); +- } +- } +- +- try { +- return makeArray( context.querySelectorAll(query), extra ); +- } catch(qsaError) {} +- +- // qSA works strangely on Element-rooted queries +- // We can work around this by specifying an extra ID on the root +- // and working up from there (Thanks to Andrew Dupont for the technique) +- // IE 8 doesn't work on object elements +- } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { +- var oldContext = context, +- old = context.getAttribute( "id" ), +- nid = old || id, +- hasParent = context.parentNode, +- relativeHierarchySelector = /^\s*[+~]/.test( query ); +- +- if ( !old ) { +- context.setAttribute( "id", nid ); +- } else { +- nid = nid.replace( /'/g, "\\$&" ); +- } +- if ( relativeHierarchySelector && hasParent ) { +- context = context.parentNode; +- } +- +- try { +- if ( !relativeHierarchySelector || hasParent ) { +- return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); +- } +- +- } catch(pseudoError) { +- } finally { +- if ( !old ) { +- oldContext.removeAttribute( "id" ); +- } +- } +- } +- } +- +- return oldSizzle(query, context, extra, seed); +- }; +- +- for ( var prop in oldSizzle ) { +- Sizzle[ prop ] = oldSizzle[ prop ]; +- } +- +- // release memory in IE +- div = null; +- })(); +-} +- +-(function(){ +- var html = document.documentElement, +- matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; +- +- if ( matches ) { +- // Check to see if it's possible to do matchesSelector +- // on a disconnected node (IE 9 fails this) +- var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), +- pseudoWorks = false; +- +- try { +- // This should fail with an exception +- // Gecko does not error, returns false instead +- matches.call( document.documentElement, "[test!='']:sizzle" ); +- +- } catch( pseudoError ) { +- pseudoWorks = true; +- } +- +- Sizzle.matchesSelector = function( node, expr ) { +- // Make sure that attribute selectors are quoted +- expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); +- +- if ( !Sizzle.isXML( node ) ) { +- try { +- if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { +- var ret = matches.call( node, expr ); +- +- // IE 9's matchesSelector returns false on disconnected nodes +- if ( ret || !disconnectedMatch || +- // As well, disconnected nodes are said to be in a document +- // fragment in IE 9, so check for that +- node.document && node.document.nodeType !== 11 ) { +- return ret; +- } +- } +- } catch(e) {} +- } +- +- return Sizzle(expr, null, null, [node]).length > 0; +- }; +- } +-})(); +- +-(function(){ +- var div = document.createElement("div"); +- +- div.innerHTML = "
"; +- +- // Opera can't find a second classname (in 9.6) +- // Also, make sure that getElementsByClassName actually exists +- if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { +- return; +- } +- +- // Safari caches class attributes, doesn't catch changes (in 3.2) +- div.lastChild.className = "e"; +- +- if ( div.getElementsByClassName("e").length === 1 ) { +- return; +- } +- +- Expr.order.splice(1, 0, "CLASS"); +- Expr.find.CLASS = function( match, context, isXML ) { +- if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { +- return context.getElementsByClassName(match[1]); +- } +- }; +- +- // release memory in IE +- div = null; +-})(); +- +-function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { +- for ( var i = 0, l = checkSet.length; i < l; i++ ) { +- var elem = checkSet[i]; +- +- if ( elem ) { +- var match = false; +- +- elem = elem[dir]; +- +- while ( elem ) { +- if ( elem[ expando ] === doneName ) { +- match = checkSet[elem.sizset]; +- break; +- } +- +- if ( elem.nodeType === 1 && !isXML ){ +- elem[ expando ] = doneName; +- elem.sizset = i; +- } +- +- if ( elem.nodeName.toLowerCase() === cur ) { +- match = elem; +- break; +- } +- +- elem = elem[dir]; +- } +- +- checkSet[i] = match; +- } +- } +-} +- +-function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { +- for ( var i = 0, l = checkSet.length; i < l; i++ ) { +- var elem = checkSet[i]; +- +- if ( elem ) { +- var match = false; +- +- elem = elem[dir]; +- +- while ( elem ) { +- if ( elem[ expando ] === doneName ) { +- match = checkSet[elem.sizset]; +- break; +- } +- +- if ( elem.nodeType === 1 ) { +- if ( !isXML ) { +- elem[ expando ] = doneName; +- elem.sizset = i; +- } +- +- if ( typeof cur !== "string" ) { +- if ( elem === cur ) { +- match = true; +- break; +- } +- +- } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { +- match = elem; +- break; +- } +- } +- +- elem = elem[dir]; +- } +- +- checkSet[i] = match; +- } +- } +-} +- +-if ( document.documentElement.contains ) { +- Sizzle.contains = function( a, b ) { +- return a !== b && (a.contains ? a.contains(b) : true); +- }; +- +-} else if ( document.documentElement.compareDocumentPosition ) { +- Sizzle.contains = function( a, b ) { +- return !!(a.compareDocumentPosition(b) & 16); +- }; +- +-} else { +- Sizzle.contains = function() { +- return false; +- }; +-} +- +-Sizzle.isXML = function( elem ) { +- // documentElement is verified for cases where it doesn't yet exist +- // (such as loading iframes in IE - #4833) +- var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; +- +- return documentElement ? documentElement.nodeName !== "HTML" : false; +-}; +- +-var posProcess = function( selector, context, seed ) { +- var match, +- tmpSet = [], +- later = "", +- root = context.nodeType ? [context] : context; +- +- // Position selectors must be done after the filter +- // And so must :not(positional) so we move all PSEUDOs to the end +- while ( (match = Expr.match.PSEUDO.exec( selector )) ) { +- later += match[0]; +- selector = selector.replace( Expr.match.PSEUDO, "" ); +- } +- +- selector = Expr.relative[selector] ? selector + "*" : selector; +- +- for ( var i = 0, l = root.length; i < l; i++ ) { +- Sizzle( selector, root[i], tmpSet, seed ); +- } +- +- return Sizzle.filter( later, tmpSet ); +-}; +- +-// EXPOSE +-// Override sizzle attribute retrieval +-Sizzle.attr = jQuery.attr; +-Sizzle.selectors.attrMap = {}; +-jQuery.find = Sizzle; +-jQuery.expr = Sizzle.selectors; +-jQuery.expr[":"] = jQuery.expr.filters; +-jQuery.unique = Sizzle.uniqueSort; +-jQuery.text = Sizzle.getText; +-jQuery.isXMLDoc = Sizzle.isXML; +-jQuery.contains = Sizzle.contains; +- +- +-})(); +- +- +-var runtil = /Until$/, +- rparentsprev = /^(?:parents|prevUntil|prevAll)/, +- // Note: This RegExp should be improved, or likely pulled from Sizzle +- rmultiselector = /,/, +- isSimple = /^.[^:#\[\.,]*$/, +- slice = Array.prototype.slice, +- POS = jQuery.expr.match.POS, +- // methods guaranteed to produce a unique set when starting from a unique set +- guaranteedUnique = { +- children: true, +- contents: true, +- next: true, +- prev: true +- }; +- +-jQuery.fn.extend({ +- find: function( selector ) { +- var self = this, +- i, l; +- +- if ( typeof selector !== "string" ) { +- return jQuery( selector ).filter(function() { +- for ( i = 0, l = self.length; i < l; i++ ) { +- if ( jQuery.contains( self[ i ], this ) ) { +- return true; +- } +- } +- }); +- } +- +- var ret = this.pushStack( "", "find", selector ), +- length, n, r; +- +- for ( i = 0, l = this.length; i < l; i++ ) { +- length = ret.length; +- jQuery.find( selector, this[i], ret ); +- +- if ( i > 0 ) { +- // Make sure that the results are unique +- for ( n = length; n < ret.length; n++ ) { +- for ( r = 0; r < length; r++ ) { +- if ( ret[r] === ret[n] ) { +- ret.splice(n--, 1); +- break; +- } +- } +- } +- } +- } +- +- return ret; +- }, +- +- has: function( target ) { +- var targets = jQuery( target ); +- return this.filter(function() { +- for ( var i = 0, l = targets.length; i < l; i++ ) { +- if ( jQuery.contains( this, targets[i] ) ) { +- return true; +- } +- } +- }); +- }, +- +- not: function( selector ) { +- return this.pushStack( winnow(this, selector, false), "not", selector); +- }, +- +- filter: function( selector ) { +- return this.pushStack( winnow(this, selector, true), "filter", selector ); +- }, +- +- is: function( selector ) { +- return !!selector && ( +- typeof selector === "string" ? +- // If this is a positional selector, check membership in the returned set +- // so $("p:first").is("p:last") won't return true for a doc with two "p". +- POS.test( selector ) ? +- jQuery( selector, this.context ).index( this[0] ) >= 0 : +- jQuery.filter( selector, this ).length > 0 : +- this.filter( selector ).length > 0 ); +- }, +- +- closest: function( selectors, context ) { +- var ret = [], i, l, cur = this[0]; +- +- // Array (deprecated as of jQuery 1.7) +- if ( jQuery.isArray( selectors ) ) { +- var level = 1; +- +- while ( cur && cur.ownerDocument && cur !== context ) { +- for ( i = 0; i < selectors.length; i++ ) { +- +- if ( jQuery( cur ).is( selectors[ i ] ) ) { +- ret.push({ selector: selectors[ i ], elem: cur, level: level }); +- } +- } +- +- cur = cur.parentNode; +- level++; +- } +- +- return ret; +- } +- +- // String +- var pos = POS.test( selectors ) || typeof selectors !== "string" ? +- jQuery( selectors, context || this.context ) : +- 0; +- +- for ( i = 0, l = this.length; i < l; i++ ) { +- cur = this[i]; +- +- while ( cur ) { +- if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { +- ret.push( cur ); +- break; +- +- } else { +- cur = cur.parentNode; +- if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { +- break; +- } +- } +- } +- } +- +- ret = ret.length > 1 ? jQuery.unique( ret ) : ret; +- +- return this.pushStack( ret, "closest", selectors ); +- }, +- +- // Determine the position of an element within +- // the matched set of elements +- index: function( elem ) { +- +- // No argument, return index in parent +- if ( !elem ) { +- return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; +- } +- +- // index in selector +- if ( typeof elem === "string" ) { +- return jQuery.inArray( this[0], jQuery( elem ) ); +- } +- +- // Locate the position of the desired element +- return jQuery.inArray( +- // If it receives a jQuery object, the first element is used +- elem.jquery ? elem[0] : elem, this ); +- }, +- +- add: function( selector, context ) { +- var set = typeof selector === "string" ? +- jQuery( selector, context ) : +- jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), +- all = jQuery.merge( this.get(), set ); +- +- return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? +- all : +- jQuery.unique( all ) ); +- }, +- +- andSelf: function() { +- return this.add( this.prevObject ); +- } +-}); +- +-// A painfully simple check to see if an element is disconnected +-// from a document (should be improved, where feasible). +-function isDisconnected( node ) { +- return !node || !node.parentNode || node.parentNode.nodeType === 11; +-} +- +-jQuery.each({ +- parent: function( elem ) { +- var parent = elem.parentNode; +- return parent && parent.nodeType !== 11 ? parent : null; +- }, +- parents: function( elem ) { +- return jQuery.dir( elem, "parentNode" ); +- }, +- parentsUntil: function( elem, i, until ) { +- return jQuery.dir( elem, "parentNode", until ); +- }, +- next: function( elem ) { +- return jQuery.nth( elem, 2, "nextSibling" ); +- }, +- prev: function( elem ) { +- return jQuery.nth( elem, 2, "previousSibling" ); +- }, +- nextAll: function( elem ) { +- return jQuery.dir( elem, "nextSibling" ); +- }, +- prevAll: function( elem ) { +- return jQuery.dir( elem, "previousSibling" ); +- }, +- nextUntil: function( elem, i, until ) { +- return jQuery.dir( elem, "nextSibling", until ); +- }, +- prevUntil: function( elem, i, until ) { +- return jQuery.dir( elem, "previousSibling", until ); +- }, +- siblings: function( elem ) { +- return jQuery.sibling( elem.parentNode.firstChild, elem ); +- }, +- children: function( elem ) { +- return jQuery.sibling( elem.firstChild ); +- }, +- contents: function( elem ) { +- return jQuery.nodeName( elem, "iframe" ) ? +- elem.contentDocument || elem.contentWindow.document : +- jQuery.makeArray( elem.childNodes ); +- } +-}, function( name, fn ) { +- jQuery.fn[ name ] = function( until, selector ) { +- var ret = jQuery.map( this, fn, until ); +- +- if ( !runtil.test( name ) ) { +- selector = until; +- } +- +- if ( selector && typeof selector === "string" ) { +- ret = jQuery.filter( selector, ret ); +- } +- +- ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; +- +- if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { +- ret = ret.reverse(); +- } +- +- return this.pushStack( ret, name, slice.call( arguments ).join(",") ); +- }; +-}); +- +-jQuery.extend({ +- filter: function( expr, elems, not ) { +- if ( not ) { +- expr = ":not(" + expr + ")"; +- } +- +- return elems.length === 1 ? +- jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : +- jQuery.find.matches(expr, elems); +- }, +- +- dir: function( elem, dir, until ) { +- var matched = [], +- cur = elem[ dir ]; +- +- while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { +- if ( cur.nodeType === 1 ) { +- matched.push( cur ); +- } +- cur = cur[dir]; +- } +- return matched; +- }, +- +- nth: function( cur, result, dir, elem ) { +- result = result || 1; +- var num = 0; +- +- for ( ; cur; cur = cur[dir] ) { +- if ( cur.nodeType === 1 && ++num === result ) { +- break; +- } +- } +- +- return cur; +- }, +- +- sibling: function( n, elem ) { +- var r = []; +- +- for ( ; n; n = n.nextSibling ) { +- if ( n.nodeType === 1 && n !== elem ) { +- r.push( n ); +- } +- } +- +- return r; +- } +-}); +- +-// Implement the identical functionality for filter and not +-function winnow( elements, qualifier, keep ) { +- +- // Can't pass null or undefined to indexOf in Firefox 4 +- // Set to 0 to skip string check +- qualifier = qualifier || 0; +- +- if ( jQuery.isFunction( qualifier ) ) { +- return jQuery.grep(elements, function( elem, i ) { +- var retVal = !!qualifier.call( elem, i, elem ); +- return retVal === keep; +- }); +- +- } else if ( qualifier.nodeType ) { +- return jQuery.grep(elements, function( elem, i ) { +- return ( elem === qualifier ) === keep; +- }); +- +- } else if ( typeof qualifier === "string" ) { +- var filtered = jQuery.grep(elements, function( elem ) { +- return elem.nodeType === 1; +- }); +- +- if ( isSimple.test( qualifier ) ) { +- return jQuery.filter(qualifier, filtered, !keep); +- } else { +- qualifier = jQuery.filter( qualifier, filtered ); +- } +- } +- +- return jQuery.grep(elements, function( elem, i ) { +- return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; +- }); +-} +- +- +- +- +-function createSafeFragment( document ) { +- var list = nodeNames.split( "|" ), +- safeFrag = document.createDocumentFragment(); +- +- if ( safeFrag.createElement ) { +- while ( list.length ) { +- safeFrag.createElement( +- list.pop() +- ); +- } +- } +- return safeFrag; +-} +- +-var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" + +- "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", +- rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, +- rleadingWhitespace = /^\s+/, +- rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, +- rtagName = /<([\w:]+)/, +- rtbody = /", "" ], +- legend: [ 1, "
", "
" ], +- thead: [ 1, "", "
" ], +- tr: [ 2, "", "
" ], +- td: [ 3, "", "
" ], +- col: [ 2, "", "
" ], +- area: [ 1, "", "" ], +- _default: [ 0, "", "" ] +- }, +- safeFragment = createSafeFragment( document ); +- +-wrapMap.optgroup = wrapMap.option; +-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +-wrapMap.th = wrapMap.td; +- +-// IE can't serialize and ' ); +- +- iframe_doc.close(); +- +- // Update the Iframe's hash, for great justice. +- iframe.location.hash = hash; +- } +- }; +- +- })(); +- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^ +- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- +- return self; +- })(); +- +-})(jQuery,this); +diff -Nur doxygen-1.8.14.orig/jquery/jquery.powertip-1.2.0.js doxygen-1.8.14/jquery/jquery.powertip-1.2.0.js +--- doxygen-1.8.14.orig/jquery/jquery.powertip-1.2.0.js 2017-10-31 20:36:00.000000000 +0100 ++++ doxygen-1.8.14/jquery/jquery.powertip-1.2.0.js 1970-01-01 01:00:00.000000000 +0100 +@@ -1,1166 +0,0 @@ +-/*! +- PowerTip - v1.2.0 - 2013-04-03 +- http://stevenbenner.github.com/jquery-powertip/ +- Copyright (c) 2013 Steven Benner (http://stevenbenner.com/). +- Released under MIT license. +- https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt +-*/ +-(function(factory) { +- if (typeof define === 'function' && define.amd) { +- // AMD. Register as an anonymous module. +- define(['jquery'], factory); +- } else { +- // Browser globals +- factory(jQuery); +- } +-}(function($) { +- +- // useful private variables +- var $document = $(document), +- $window = $(window), +- $body = $('body'); +- +- // constants +- var DATA_DISPLAYCONTROLLER = 'displayController', +- DATA_HASACTIVEHOVER = 'hasActiveHover', +- DATA_FORCEDOPEN = 'forcedOpen', +- DATA_HASMOUSEMOVE = 'hasMouseMove', +- DATA_MOUSEONTOTIP = 'mouseOnToPopup', +- DATA_ORIGINALTITLE = 'originalTitle', +- DATA_POWERTIP = 'powertip', +- DATA_POWERTIPJQ = 'powertipjq', +- DATA_POWERTIPTARGET = 'powertiptarget', +- RAD2DEG = 180 / Math.PI; +- +- /** +- * Session data +- * Private properties global to all powerTip instances +- */ +- var session = { +- isTipOpen: false, +- isFixedTipOpen: false, +- isClosing: false, +- tipOpenImminent: false, +- activeHover: null, +- currentX: 0, +- currentY: 0, +- previousX: 0, +- previousY: 0, +- desyncTimeout: null, +- mouseTrackingActive: false, +- delayInProgress: false, +- windowWidth: 0, +- windowHeight: 0, +- scrollTop: 0, +- scrollLeft: 0 +- }; +- +- /** +- * Collision enumeration +- * @enum {number} +- */ +- var Collision = { +- none: 0, +- top: 1, +- bottom: 2, +- left: 4, +- right: 8 +- }; +- +- /** +- * Display hover tooltips on the matched elements. +- * @param {(Object|string)} opts The options object to use for the plugin, or +- * the name of a method to invoke on the first matched element. +- * @param {*=} [arg] Argument for an invoked method (optional). +- * @return {jQuery} jQuery object for the matched selectors. +- */ +- $.fn.powerTip = function(opts, arg) { +- // don't do any work if there were no matched elements +- if (!this.length) { +- return this; +- } +- +- // handle api method calls on the plugin, e.g. powerTip('hide') +- if ($.type(opts) === 'string' && $.powerTip[opts]) { +- return $.powerTip[opts].call(this, this, arg); +- } +- +- // extend options and instantiate TooltipController +- var options = $.extend({}, $.fn.powerTip.defaults, opts), +- tipController = new TooltipController(options); +- +- // hook mouse and viewport dimension tracking +- initTracking(); +- +- // setup the elements +- this.each(function elementSetup() { +- var $this = $(this), +- dataPowertip = $this.data(DATA_POWERTIP), +- dataElem = $this.data(DATA_POWERTIPJQ), +- dataTarget = $this.data(DATA_POWERTIPTARGET), +- title; +- +- // handle repeated powerTip calls on the same element by destroying the +- // original instance hooked to it and replacing it with this call +- if ($this.data(DATA_DISPLAYCONTROLLER)) { +- $.powerTip.destroy($this); +- } +- +- // attempt to use title attribute text if there is no data-powertip, +- // data-powertipjq or data-powertiptarget. If we do use the title +- // attribute, delete the attribute so the browser will not show it +- title = $this.attr('title'); +- if (!dataPowertip && !dataTarget && !dataElem && title) { +- $this.data(DATA_POWERTIP, title); +- $this.data(DATA_ORIGINALTITLE, title); +- $this.removeAttr('title'); +- } +- +- // create hover controllers for each element +- $this.data( +- DATA_DISPLAYCONTROLLER, +- new DisplayController($this, options, tipController) +- ); +- }); +- +- // attach events to matched elements if the manual options is not enabled +- if (!options.manual) { +- this.on({ +- // mouse events +- 'mouseenter.powertip': function elementMouseEnter(event) { +- $.powerTip.show(this, event); +- }, +- 'mouseleave.powertip': function elementMouseLeave() { +- $.powerTip.hide(this); +- }, +- // keyboard events +- 'focus.powertip': function elementFocus() { +- $.powerTip.show(this); +- }, +- 'blur.powertip': function elementBlur() { +- $.powerTip.hide(this, true); +- }, +- 'keydown.powertip': function elementKeyDown(event) { +- // close tooltip when the escape key is pressed +- if (event.keyCode === 27) { +- $.powerTip.hide(this, true); +- } +- } +- }); +- } +- +- return this; +- }; +- +- /** +- * Default options for the powerTip plugin. +- */ +- $.fn.powerTip.defaults = { +- fadeInTime: 200, +- fadeOutTime: 100, +- followMouse: false, +- popupId: 'powerTip', +- intentSensitivity: 7, +- intentPollInterval: 100, +- closeDelay: 100, +- placement: 'n', +- smartPlacement: false, +- offset: 10, +- mouseOnToPopup: false, +- manual: false +- }; +- +- /** +- * Default smart placement priority lists. +- * The first item in the array is the highest priority, the last is the lowest. +- * The last item is also the default, which will be used if all previous options +- * do not fit. +- */ +- $.fn.powerTip.smartPlacementLists = { +- n: ['n', 'ne', 'nw', 's'], +- e: ['e', 'ne', 'se', 'w', 'nw', 'sw', 'n', 's', 'e'], +- s: ['s', 'se', 'sw', 'n'], +- w: ['w', 'nw', 'sw', 'e', 'ne', 'se', 'n', 's', 'w'], +- nw: ['nw', 'w', 'sw', 'n', 's', 'se', 'nw'], +- ne: ['ne', 'e', 'se', 'n', 's', 'sw', 'ne'], +- sw: ['sw', 'w', 'nw', 's', 'n', 'ne', 'sw'], +- se: ['se', 'e', 'ne', 's', 'n', 'nw', 'se'], +- 'nw-alt': ['nw-alt', 'n', 'ne-alt', 'sw-alt', 's', 'se-alt', 'w', 'e'], +- 'ne-alt': ['ne-alt', 'n', 'nw-alt', 'se-alt', 's', 'sw-alt', 'e', 'w'], +- 'sw-alt': ['sw-alt', 's', 'se-alt', 'nw-alt', 'n', 'ne-alt', 'w', 'e'], +- 'se-alt': ['se-alt', 's', 'sw-alt', 'ne-alt', 'n', 'nw-alt', 'e', 'w'] +- }; +- +- /** +- * Public API +- */ +- $.powerTip = { +- /** +- * Attempts to show the tooltip for the specified element. +- * @param {jQuery|Element} element The element to open the tooltip for. +- * @param {jQuery.Event=} event jQuery event for hover intent and mouse +- * tracking (optional). +- */ +- show: function apiShowTip(element, event) { +- if (event) { +- trackMouse(event); +- session.previousX = event.pageX; +- session.previousY = event.pageY; +- $(element).data(DATA_DISPLAYCONTROLLER).show(); +- } else { +- $(element).first().data(DATA_DISPLAYCONTROLLER).show(true, true); +- } +- return element; +- }, +- +- /** +- * Repositions the tooltip on the element. +- * @param {jQuery|Element} element The element the tooltip is shown for. +- */ +- reposition: function apiResetPosition(element) { +- $(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition(); +- return element; +- }, +- +- /** +- * Attempts to close any open tooltips. +- * @param {(jQuery|Element)=} element The element with the tooltip that +- * should be closed (optional). +- * @param {boolean=} immediate Disable close delay (optional). +- */ +- hide: function apiCloseTip(element, immediate) { +- if (element) { +- $(element).first().data(DATA_DISPLAYCONTROLLER).hide(immediate); +- } else { +- if (session.activeHover) { +- session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true); +- } +- } +- return element; +- }, +- +- /** +- * Destroy and roll back any powerTip() instance on the specified element. +- * @param {jQuery|Element} element The element with the powerTip instance. +- */ +- destroy: function apiDestroy(element) { +- $(element).off('.powertip').each(function destroy() { +- var $this = $(this), +- dataAttributes = [ +- DATA_ORIGINALTITLE, +- DATA_DISPLAYCONTROLLER, +- DATA_HASACTIVEHOVER, +- DATA_FORCEDOPEN +- ]; +- +- if ($this.data(DATA_ORIGINALTITLE)) { +- $this.attr('title', $this.data(DATA_ORIGINALTITLE)); +- dataAttributes.push(DATA_POWERTIP); +- } +- +- $this.removeData(dataAttributes); +- }); +- return element; +- } +- }; +- +- // API aliasing +- $.powerTip.showTip = $.powerTip.show; +- $.powerTip.closeTip = $.powerTip.hide; +- +- /** +- * Creates a new CSSCoordinates object. +- * @private +- * @constructor +- */ +- function CSSCoordinates() { +- var me = this; +- +- // initialize object properties +- me.top = 'auto'; +- me.left = 'auto'; +- me.right = 'auto'; +- me.bottom = 'auto'; +- +- /** +- * Set a property to a value. +- * @private +- * @param {string} property The name of the property. +- * @param {number} value The value of the property. +- */ +- me.set = function(property, value) { +- if ($.isNumeric(value)) { +- me[property] = Math.round(value); +- } +- }; +- } +- +- /** +- * Creates a new tooltip display controller. +- * @private +- * @constructor +- * @param {jQuery} element The element that this controller will handle. +- * @param {Object} options Options object containing settings. +- * @param {TooltipController} tipController The TooltipController object for +- * this instance. +- */ +- function DisplayController(element, options, tipController) { +- var hoverTimer = null; +- +- /** +- * Begins the process of showing a tooltip. +- * @private +- * @param {boolean=} immediate Skip intent testing (optional). +- * @param {boolean=} forceOpen Ignore cursor position and force tooltip to +- * open (optional). +- */ +- function openTooltip(immediate, forceOpen) { +- cancelTimer(); +- if (!element.data(DATA_HASACTIVEHOVER)) { +- if (!immediate) { +- session.tipOpenImminent = true; +- hoverTimer = setTimeout( +- function intentDelay() { +- hoverTimer = null; +- checkForIntent(); +- }, +- options.intentPollInterval +- ); +- } else { +- if (forceOpen) { +- element.data(DATA_FORCEDOPEN, true); +- } +- tipController.showTip(element); +- } +- } +- } +- +- /** +- * Begins the process of closing a tooltip. +- * @private +- * @param {boolean=} disableDelay Disable close delay (optional). +- */ +- function closeTooltip(disableDelay) { +- cancelTimer(); +- session.tipOpenImminent = false; +- if (element.data(DATA_HASACTIVEHOVER)) { +- element.data(DATA_FORCEDOPEN, false); +- if (!disableDelay) { +- session.delayInProgress = true; +- hoverTimer = setTimeout( +- function closeDelay() { +- hoverTimer = null; +- tipController.hideTip(element); +- session.delayInProgress = false; +- }, +- options.closeDelay +- ); +- } else { +- tipController.hideTip(element); +- } +- } +- } +- +- /** +- * Checks mouse position to make sure that the user intended to hover on the +- * specified element before showing the tooltip. +- * @private +- */ +- function checkForIntent() { +- // calculate mouse position difference +- var xDifference = Math.abs(session.previousX - session.currentX), +- yDifference = Math.abs(session.previousY - session.currentY), +- totalDifference = xDifference + yDifference; +- +- // check if difference has passed the sensitivity threshold +- if (totalDifference < options.intentSensitivity) { +- tipController.showTip(element); +- } else { +- // try again +- session.previousX = session.currentX; +- session.previousY = session.currentY; +- openTooltip(); +- } +- } +- +- /** +- * Cancels active hover timer. +- * @private +- */ +- function cancelTimer() { +- hoverTimer = clearTimeout(hoverTimer); +- session.delayInProgress = false; +- } +- +- /** +- * Repositions the tooltip on this element. +- * @private +- */ +- function repositionTooltip() { +- tipController.resetPosition(element); +- } +- +- // expose the methods +- this.show = openTooltip; +- this.hide = closeTooltip; +- this.cancel = cancelTimer; +- this.resetPosition = repositionTooltip; +- } +- +- /** +- * Creates a new Placement Calculator. +- * @private +- * @constructor +- */ +- function PlacementCalculator() { +- /** +- * Compute the CSS position to display a tooltip at the specified placement +- * relative to the specified element. +- * @private +- * @param {jQuery} element The element that the tooltip should target. +- * @param {string} placement The placement for the tooltip. +- * @param {number} tipWidth Width of the tooltip element in pixels. +- * @param {number} tipHeight Height of the tooltip element in pixels. +- * @param {number} offset Distance to offset tooltips in pixels. +- * @return {CSSCoordinates} A CSSCoordinates object with the position. +- */ +- function computePlacementCoords(element, placement, tipWidth, tipHeight, offset) { +- var placementBase = placement.split('-')[0], // ignore 'alt' for corners +- coords = new CSSCoordinates(), +- position; +- +- if (isSvgElement(element)) { +- position = getSvgPlacement(element, placementBase); +- } else { +- position = getHtmlPlacement(element, placementBase); +- } +- +- // calculate the appropriate x and y position in the document +- switch (placement) { +- case 'n': +- coords.set('left', position.left - (tipWidth / 2)); +- coords.set('bottom', session.windowHeight - position.top + offset); +- break; +- case 'e': +- coords.set('left', position.left + offset); +- coords.set('top', position.top - (tipHeight / 2)); +- break; +- case 's': +- coords.set('left', position.left - (tipWidth / 2)); +- coords.set('top', position.top + offset); +- break; +- case 'w': +- coords.set('top', position.top - (tipHeight / 2)); +- coords.set('right', session.windowWidth - position.left + offset); +- break; +- case 'nw': +- coords.set('bottom', session.windowHeight - position.top + offset); +- coords.set('right', session.windowWidth - position.left - 20); +- break; +- case 'nw-alt': +- coords.set('left', position.left); +- coords.set('bottom', session.windowHeight - position.top + offset); +- break; +- case 'ne': +- coords.set('left', position.left - 20); +- coords.set('bottom', session.windowHeight - position.top + offset); +- break; +- case 'ne-alt': +- coords.set('bottom', session.windowHeight - position.top + offset); +- coords.set('right', session.windowWidth - position.left); +- break; +- case 'sw': +- coords.set('top', position.top + offset); +- coords.set('right', session.windowWidth - position.left - 20); +- break; +- case 'sw-alt': +- coords.set('left', position.left); +- coords.set('top', position.top + offset); +- break; +- case 'se': +- coords.set('left', position.left - 20); +- coords.set('top', position.top + offset); +- break; +- case 'se-alt': +- coords.set('top', position.top + offset); +- coords.set('right', session.windowWidth - position.left); +- break; +- } +- +- return coords; +- } +- +- /** +- * Finds the tooltip attachment point in the document for a HTML DOM element +- * for the specified placement. +- * @private +- * @param {jQuery} element The element that the tooltip should target. +- * @param {string} placement The placement for the tooltip. +- * @return {Object} An object with the top,left position values. +- */ +- function getHtmlPlacement(element, placement) { +- var objectOffset = element.offset(), +- objectWidth = element.outerWidth(), +- objectHeight = element.outerHeight(), +- left, +- top; +- +- // calculate the appropriate x and y position in the document +- switch (placement) { +- case 'n': +- left = objectOffset.left + objectWidth / 2; +- top = objectOffset.top; +- break; +- case 'e': +- left = objectOffset.left + objectWidth; +- top = objectOffset.top + objectHeight / 2; +- break; +- case 's': +- left = objectOffset.left + objectWidth / 2; +- top = objectOffset.top + objectHeight; +- break; +- case 'w': +- left = objectOffset.left; +- top = objectOffset.top + objectHeight / 2; +- break; +- case 'nw': +- left = objectOffset.left; +- top = objectOffset.top; +- break; +- case 'ne': +- left = objectOffset.left + objectWidth; +- top = objectOffset.top; +- break; +- case 'sw': +- left = objectOffset.left; +- top = objectOffset.top + objectHeight; +- break; +- case 'se': +- left = objectOffset.left + objectWidth; +- top = objectOffset.top + objectHeight; +- break; +- } +- +- return { +- top: top, +- left: left +- }; +- } +- +- /** +- * Finds the tooltip attachment point in the document for a SVG element for +- * the specified placement. +- * @private +- * @param {jQuery} element The element that the tooltip should target. +- * @param {string} placement The placement for the tooltip. +- * @return {Object} An object with the top,left position values. +- */ +- function getSvgPlacement(element, placement) { +- var svgElement = element.closest('svg')[0], +- domElement = element[0], +- point = svgElement.createSVGPoint(), +- boundingBox = domElement.getBBox(), +- matrix = domElement.getScreenCTM(), +- halfWidth = boundingBox.width / 2, +- halfHeight = boundingBox.height / 2, +- placements = [], +- placementKeys = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w'], +- coords, +- rotation, +- steps, +- x; +- +- function pushPlacement() { +- placements.push(point.matrixTransform(matrix)); +- } +- +- // get bounding box corners and midpoints +- point.x = boundingBox.x; +- point.y = boundingBox.y; +- pushPlacement(); +- point.x += halfWidth; +- pushPlacement(); +- point.x += halfWidth; +- pushPlacement(); +- point.y += halfHeight; +- pushPlacement(); +- point.y += halfHeight; +- pushPlacement(); +- point.x -= halfWidth; +- pushPlacement(); +- point.x -= halfWidth; +- pushPlacement(); +- point.y -= halfHeight; +- pushPlacement(); +- +- // determine rotation +- if (placements[0].y !== placements[1].y || placements[0].x !== placements[7].x) { +- rotation = Math.atan2(matrix.b, matrix.a) * RAD2DEG; +- steps = Math.ceil(((rotation % 360) - 22.5) / 45); +- if (steps < 1) { +- steps += 8; +- } +- while (steps--) { +- placementKeys.push(placementKeys.shift()); +- } +- } +- +- // find placement +- for (x = 0; x < placements.length; x++) { +- if (placementKeys[x] === placement) { +- coords = placements[x]; +- break; +- } +- } +- +- return { +- top: coords.y + session.scrollTop, +- left: coords.x + session.scrollLeft +- }; +- } +- +- // expose methods +- this.compute = computePlacementCoords; +- } +- +- /** +- * Creates a new tooltip controller. +- * @private +- * @constructor +- * @param {Object} options Options object containing settings. +- */ +- function TooltipController(options) { +- var placementCalculator = new PlacementCalculator(), +- tipElement = $('#' + options.popupId); +- +- // build and append tooltip div if it does not already exist +- if (tipElement.length === 0) { +- tipElement = $('
', { id: options.popupId }); +- // grab body element if it was not populated when the script loaded +- // note: this hack exists solely for jsfiddle support +- if ($body.length === 0) { +- $body = $('body'); +- } +- $body.append(tipElement); +- } +- +- // hook mousemove for cursor follow tooltips +- if (options.followMouse) { +- // only one positionTipOnCursor hook per tooltip element, please +- if (!tipElement.data(DATA_HASMOUSEMOVE)) { +- $document.on('mousemove', positionTipOnCursor); +- $window.on('scroll', positionTipOnCursor); +- tipElement.data(DATA_HASMOUSEMOVE, true); +- } +- } +- +- // if we want to be able to mouse onto the tooltip then we need to attach +- // hover events to the tooltip that will cancel a close request on hover and +- // start a new close request on mouseleave +- if (options.mouseOnToPopup) { +- tipElement.on({ +- mouseenter: function tipMouseEnter() { +- // we only let the mouse stay on the tooltip if it is set to let +- // users interact with it +- if (tipElement.data(DATA_MOUSEONTOTIP)) { +- // check activeHover in case the mouse cursor entered the +- // tooltip during the fadeOut and close cycle +- if (session.activeHover) { +- session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel(); +- } +- } +- }, +- mouseleave: function tipMouseLeave() { +- // check activeHover in case the mouse cursor entered the +- // tooltip during the fadeOut and close cycle +- if (session.activeHover) { +- session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(); +- } +- } +- }); +- } +- +- /** +- * Gives the specified element the active-hover state and queues up the +- * showTip function. +- * @private +- * @param {jQuery} element The element that the tooltip should target. +- */ +- function beginShowTip(element) { +- element.data(DATA_HASACTIVEHOVER, true); +- // show tooltip, asap +- tipElement.queue(function queueTipInit(next) { +- showTip(element); +- next(); +- }); +- } +- +- /** +- * Shows the tooltip, as soon as possible. +- * @private +- * @param {jQuery} element The element that the tooltip should target. +- */ +- function showTip(element) { +- var tipContent; +- +- // it is possible, especially with keyboard navigation, to move on to +- // another element with a tooltip during the queue to get to this point +- // in the code. if that happens then we need to not proceed or we may +- // have the fadeout callback for the last tooltip execute immediately +- // after this code runs, causing bugs. +- if (!element.data(DATA_HASACTIVEHOVER)) { +- return; +- } +- +- // if the tooltip is open and we got asked to open another one then the +- // old one is still in its fadeOut cycle, so wait and try again +- if (session.isTipOpen) { +- if (!session.isClosing) { +- hideTip(session.activeHover); +- } +- tipElement.delay(100).queue(function queueTipAgain(next) { +- showTip(element); +- next(); +- }); +- return; +- } +- +- // trigger powerTipPreRender event +- element.trigger('powerTipPreRender'); +- +- // set tooltip content +- tipContent = getTooltipContent(element); +- if (tipContent) { +- tipElement.empty().append(tipContent); +- } else { +- // we have no content to display, give up +- return; +- } +- +- // trigger powerTipRender event +- element.trigger('powerTipRender'); +- +- session.activeHover = element; +- session.isTipOpen = true; +- +- tipElement.data(DATA_MOUSEONTOTIP, options.mouseOnToPopup); +- +- // set tooltip position +- if (!options.followMouse) { +- positionTipOnElement(element); +- session.isFixedTipOpen = true; +- } else { +- positionTipOnCursor(); +- } +- +- // fadein +- tipElement.fadeIn(options.fadeInTime, function fadeInCallback() { +- // start desync polling +- if (!session.desyncTimeout) { +- session.desyncTimeout = setInterval(closeDesyncedTip, 500); +- } +- +- // trigger powerTipOpen event +- element.trigger('powerTipOpen'); +- }); +- } +- +- /** +- * Hides the tooltip. +- * @private +- * @param {jQuery} element The element that the tooltip should target. +- */ +- function hideTip(element) { +- // reset session +- session.isClosing = true; +- session.activeHover = null; +- session.isTipOpen = false; +- +- // stop desync polling +- session.desyncTimeout = clearInterval(session.desyncTimeout); +- +- // reset element state +- element.data(DATA_HASACTIVEHOVER, false); +- element.data(DATA_FORCEDOPEN, false); +- +- // fade out +- tipElement.fadeOut(options.fadeOutTime, function fadeOutCallback() { +- var coords = new CSSCoordinates(); +- +- // reset session and tooltip element +- session.isClosing = false; +- session.isFixedTipOpen = false; +- tipElement.removeClass(); +- +- // support mouse-follow and fixed position tips at the same time by +- // moving the tooltip to the last cursor location after it is hidden +- coords.set('top', session.currentY + options.offset); +- coords.set('left', session.currentX + options.offset); +- tipElement.css(coords); +- +- // trigger powerTipClose event +- element.trigger('powerTipClose'); +- }); +- } +- +- /** +- * Moves the tooltip to the users mouse cursor. +- * @private +- */ +- function positionTipOnCursor() { +- // to support having fixed tooltips on the same page as cursor tooltips, +- // where both instances are referencing the same tooltip element, we +- // need to keep track of the mouse position constantly, but we should +- // only set the tip location if a fixed tip is not currently open, a tip +- // open is imminent or active, and the tooltip element in question does +- // have a mouse-follow using it. +- if (!session.isFixedTipOpen && (session.isTipOpen || (session.tipOpenImminent && tipElement.data(DATA_HASMOUSEMOVE)))) { +- // grab measurements +- var tipWidth = tipElement.outerWidth(), +- tipHeight = tipElement.outerHeight(), +- coords = new CSSCoordinates(), +- collisions, +- collisionCount; +- +- // grab collisions +- coords.set('top', session.currentY + options.offset); +- coords.set('left', session.currentX + options.offset); +- collisions = getViewportCollisions( +- coords, +- tipWidth, +- tipHeight +- ); +- +- // handle tooltip view port collisions +- if (collisions !== Collision.none) { +- collisionCount = countFlags(collisions); +- if (collisionCount === 1) { +- // if there is only one collision (bottom or right) then +- // simply constrain the tooltip to the view port +- if (collisions === Collision.right) { +- coords.set('left', session.windowWidth - tipWidth); +- } else if (collisions === Collision.bottom) { +- coords.set('top', session.scrollTop + session.windowHeight - tipHeight); +- } +- } else { +- // if the tooltip has more than one collision then it is +- // trapped in the corner and should be flipped to get it out +- // of the users way +- coords.set('left', session.currentX - tipWidth - options.offset); +- coords.set('top', session.currentY - tipHeight - options.offset); +- } +- } +- +- // position the tooltip +- tipElement.css(coords); +- } +- } +- +- /** +- * Sets the tooltip to the correct position relative to the specified target +- * element. Based on options settings. +- * @private +- * @param {jQuery} element The element that the tooltip should target. +- */ +- function positionTipOnElement(element) { +- var priorityList, +- finalPlacement; +- +- if (options.smartPlacement) { +- priorityList = $.fn.powerTip.smartPlacementLists[options.placement]; +- +- // iterate over the priority list and use the first placement option +- // that does not collide with the view port. if they all collide +- // then the last placement in the list will be used. +- $.each(priorityList, function(idx, pos) { +- // place tooltip and find collisions +- var collisions = getViewportCollisions( +- placeTooltip(element, pos), +- tipElement.outerWidth(), +- tipElement.outerHeight() +- ); +- +- // update the final placement variable +- finalPlacement = pos; +- +- // break if there were no collisions +- if (collisions === Collision.none) { +- return false; +- } +- }); +- } else { +- // if we're not going to use the smart placement feature then just +- // compute the coordinates and do it +- placeTooltip(element, options.placement); +- finalPlacement = options.placement; +- } +- +- // add placement as class for CSS arrows +- tipElement.addClass(finalPlacement); +- } +- +- /** +- * Sets the tooltip position to the appropriate values to show the tip at +- * the specified placement. This function will iterate and test the tooltip +- * to support elastic tooltips. +- * @private +- * @param {jQuery} element The element that the tooltip should target. +- * @param {string} placement The placement for the tooltip. +- * @return {CSSCoordinates} A CSSCoordinates object with the top, left, and +- * right position values. +- */ +- function placeTooltip(element, placement) { +- var iterationCount = 0, +- tipWidth, +- tipHeight, +- coords = new CSSCoordinates(); +- +- // set the tip to 0,0 to get the full expanded width +- coords.set('top', 0); +- coords.set('left', 0); +- tipElement.css(coords); +- +- // to support elastic tooltips we need to check for a change in the +- // rendered dimensions after the tooltip has been positioned +- do { +- // grab the current tip dimensions +- tipWidth = tipElement.outerWidth(); +- tipHeight = tipElement.outerHeight(); +- +- // get placement coordinates +- coords = placementCalculator.compute( +- element, +- placement, +- tipWidth, +- tipHeight, +- options.offset +- ); +- +- // place the tooltip +- tipElement.css(coords); +- } while ( +- // sanity check: limit to 5 iterations, and... +- ++iterationCount <= 5 && +- // try again if the dimensions changed after placement +- (tipWidth !== tipElement.outerWidth() || tipHeight !== tipElement.outerHeight()) +- ); +- +- return coords; +- } +- +- /** +- * Checks for a tooltip desync and closes the tooltip if one occurs. +- * @private +- */ +- function closeDesyncedTip() { +- var isDesynced = false; +- // It is possible for the mouse cursor to leave an element without +- // firing the mouseleave or blur event. This most commonly happens when +- // the element is disabled under mouse cursor. If this happens it will +- // result in a desynced tooltip because the tooltip was never asked to +- // close. So we should periodically check for a desync situation and +- // close the tip if such a situation arises. +- if (session.isTipOpen && !session.isClosing && !session.delayInProgress) { +- // user moused onto another tip or active hover is disabled +- if (session.activeHover.data(DATA_HASACTIVEHOVER) === false || session.activeHover.is(':disabled')) { +- isDesynced = true; +- } else { +- // hanging tip - have to test if mouse position is not over the +- // active hover and not over a tooltip set to let the user +- // interact with it. +- // for keyboard navigation: this only counts if the element does +- // not have focus. +- // for tooltips opened via the api: we need to check if it has +- // the forcedOpen flag. +- if (!isMouseOver(session.activeHover) && !session.activeHover.is(':focus') && !session.activeHover.data(DATA_FORCEDOPEN)) { +- if (tipElement.data(DATA_MOUSEONTOTIP)) { +- if (!isMouseOver(tipElement)) { +- isDesynced = true; +- } +- } else { +- isDesynced = true; +- } +- } +- } +- +- if (isDesynced) { +- // close the desynced tip +- hideTip(session.activeHover); +- } +- } +- } +- +- // expose methods +- this.showTip = beginShowTip; +- this.hideTip = hideTip; +- this.resetPosition = positionTipOnElement; +- } +- +- /** +- * Determine whether a jQuery object is an SVG element +- * @private +- * @param {jQuery} element The element to check +- * @return {boolean} Whether this is an SVG element +- */ +- function isSvgElement(element) { +- return window.SVGElement && element[0] instanceof SVGElement; +- } +- +- /** +- * Initializes the viewport dimension cache and hooks up the mouse position +- * tracking and viewport dimension tracking events. +- * Prevents attaching the events more than once. +- * @private +- */ +- function initTracking() { +- if (!session.mouseTrackingActive) { +- session.mouseTrackingActive = true; +- +- // grab the current viewport dimensions on load +- $(function getViewportDimensions() { +- session.scrollLeft = $window.scrollLeft(); +- session.scrollTop = $window.scrollTop(); +- session.windowWidth = $window.width(); +- session.windowHeight = $window.height(); +- }); +- +- // hook mouse move tracking +- $document.on('mousemove', trackMouse); +- +- // hook viewport dimensions tracking +- $window.on({ +- resize: function trackResize() { +- session.windowWidth = $window.width(); +- session.windowHeight = $window.height(); +- }, +- scroll: function trackScroll() { +- var x = $window.scrollLeft(), +- y = $window.scrollTop(); +- if (x !== session.scrollLeft) { +- session.currentX += x - session.scrollLeft; +- session.scrollLeft = x; +- } +- if (y !== session.scrollTop) { +- session.currentY += y - session.scrollTop; +- session.scrollTop = y; +- } +- } +- }); +- } +- } +- +- /** +- * Saves the current mouse coordinates to the session object. +- * @private +- * @param {jQuery.Event} event The mousemove event for the document. +- */ +- function trackMouse(event) { +- session.currentX = event.pageX; +- session.currentY = event.pageY; +- } +- +- /** +- * Tests if the mouse is currently over the specified element. +- * @private +- * @param {jQuery} element The element to check for hover. +- * @return {boolean} +- */ +- function isMouseOver(element) { +- // use getBoundingClientRect() because jQuery's width() and height() +- // methods do not work with SVG elements +- // compute width/height because those properties do not exist on the object +- // returned by getBoundingClientRect() in older versions of IE +- var elementPosition = element.offset(), +- elementBox = element[0].getBoundingClientRect(), +- elementWidth = elementBox.right - elementBox.left, +- elementHeight = elementBox.bottom - elementBox.top; +- +- return session.currentX >= elementPosition.left && +- session.currentX <= elementPosition.left + elementWidth && +- session.currentY >= elementPosition.top && +- session.currentY <= elementPosition.top + elementHeight; +- } +- +- /** +- * Fetches the tooltip content from the specified element's data attributes. +- * @private +- * @param {jQuery} element The element to get the tooltip content for. +- * @return {(string|jQuery|undefined)} The text/HTML string, jQuery object, or +- * undefined if there was no tooltip content for the element. +- */ +- function getTooltipContent(element) { +- var tipText = element.data(DATA_POWERTIP), +- tipObject = element.data(DATA_POWERTIPJQ), +- tipTarget = element.data(DATA_POWERTIPTARGET), +- targetElement, +- content; +- +- if (tipText) { +- if ($.isFunction(tipText)) { +- tipText = tipText.call(element[0]); +- } +- content = tipText; +- } else if (tipObject) { +- if ($.isFunction(tipObject)) { +- tipObject = tipObject.call(element[0]); +- } +- if (tipObject.length > 0) { +- content = tipObject.clone(true, true); +- } +- } else if (tipTarget) { +- targetElement = $('#' + tipTarget); +- if (targetElement.length > 0) { +- content = targetElement.html(); +- } +- } +- +- return content; +- } +- +- /** +- * Finds any viewport collisions that an element (the tooltip) would have if it +- * were absolutely positioned at the specified coordinates. +- * @private +- * @param {CSSCoordinates} coords Coordinates for the element. +- * @param {number} elementWidth Width of the element in pixels. +- * @param {number} elementHeight Height of the element in pixels. +- * @return {number} Value with the collision flags. +- */ +- function getViewportCollisions(coords, elementWidth, elementHeight) { +- var viewportTop = session.scrollTop, +- viewportLeft = session.scrollLeft, +- viewportBottom = viewportTop + session.windowHeight, +- viewportRight = viewportLeft + session.windowWidth, +- collisions = Collision.none; +- +- if (coords.top < viewportTop || Math.abs(coords.bottom - session.windowHeight) - elementHeight < viewportTop) { +- collisions |= Collision.top; +- } +- if (coords.top + elementHeight > viewportBottom || Math.abs(coords.bottom - session.windowHeight) > viewportBottom) { +- collisions |= Collision.bottom; +- } +- if (coords.left < viewportLeft || coords.right + elementWidth > viewportRight) { +- collisions |= Collision.left; +- } +- if (coords.left + elementWidth > viewportRight || coords.right < viewportLeft) { +- collisions |= Collision.right; +- } +- +- return collisions; +- } +- +- /** +- * Counts the number of bits set on a flags value. +- * @param {number} value The flags value. +- * @return {number} The number of bits that have been set. +- */ +- function countFlags(value) { +- var count = 0; +- while (value) { +- value &= value - 1; +- count++; +- } +- return count; +- } +- +-})); +diff -Nur doxygen-1.8.14.orig/jquery/jquery.powertip-1.3.1.mod.js doxygen-1.8.14/jquery/jquery.powertip-1.3.1.mod.js +--- doxygen-1.8.14.orig/jquery/jquery.powertip-1.3.1.mod.js 1970-01-01 01:00:00.000000000 +0100 ++++ doxygen-1.8.14/jquery/jquery.powertip-1.3.1.mod.js 2020-01-03 23:51:18.000000000 +0100 +@@ -0,0 +1,1324 @@ ++/*! ++ PowerTip v1.3.1 (2018-04-15) ++ https://stevenbenner.github.io/jquery-powertip/ ++ Copyright (c) 2018 Steven Benner (http://stevenbenner.com/). ++ Released under MIT license. ++ https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt ++*/ ++(function(root, factory) { ++ // support loading the plugin via common patterns ++ if (typeof define === 'function' && define.amd) { ++ // load the plugin as an amd module ++ define([ 'jquery' ], factory); ++ } else if (typeof module === 'object' && module.exports) { ++ // load the plugin as a commonjs module ++ module.exports = factory(require('jquery')); ++ } else { ++ // load the plugin as a global ++ factory(root.jQuery); ++ } ++}(this, function($) { ++ // useful private variables ++ var $document = $(document), ++ $window = $(window), ++ $body = $('body'); ++ ++ // constants ++ var DATA_DISPLAYCONTROLLER = 'displayController', ++ DATA_HASACTIVEHOVER = 'hasActiveHover', ++ DATA_FORCEDOPEN = 'forcedOpen', ++ DATA_HASMOUSEMOVE = 'hasMouseMove', ++ DATA_MOUSEONTOTIP = 'mouseOnToPopup', ++ DATA_ORIGINALTITLE = 'originalTitle', ++ DATA_POWERTIP = 'powertip', ++ DATA_POWERTIPJQ = 'powertipjq', ++ DATA_POWERTIPTARGET = 'powertiptarget', ++ EVENT_NAMESPACE = '.powertip', ++ RAD2DEG = 180 / Math.PI, ++ MOUSE_EVENTS = [ ++ 'click', ++ 'dblclick', ++ 'mousedown', ++ 'mouseup', ++ 'mousemove', ++ 'mouseover', ++ 'mouseout', ++ 'mouseenter', ++ 'mouseleave', ++ 'contextmenu' ++ ]; ++ ++ /** ++ * Session data ++ * Private properties global to all powerTip instances ++ */ ++ var session = { ++ tooltips: null, ++ isTipOpen: false, ++ isFixedTipOpen: false, ++ isClosing: false, ++ tipOpenImminent: false, ++ activeHover: null, ++ currentX: 0, ++ currentY: 0, ++ previousX: 0, ++ previousY: 0, ++ desyncTimeout: null, ++ closeDelayTimeout: null, ++ mouseTrackingActive: false, ++ delayInProgress: false, ++ windowWidth: 0, ++ windowHeight: 0, ++ scrollTop: 0, ++ scrollLeft: 0 ++ }; ++ ++ /** ++ * Collision enumeration ++ * @enum {number} ++ */ ++ var Collision = { ++ none: 0, ++ top: 1, ++ bottom: 2, ++ left: 4, ++ right: 8 ++ }; ++ ++ /** ++ * Display hover tooltips on the matched elements. ++ * @param {(Object|string)=} opts The options object to use for the plugin, or ++ * the name of a method to invoke on the first matched element. ++ * @param {*=} [arg] Argument for an invoked method (optional). ++ * @return {jQuery} jQuery object for the matched selectors. ++ */ ++ $.fn.powerTip = function(opts, arg) { ++ var targetElements = this, ++ options, ++ tipController; ++ ++ // don't do any work if there were no matched elements ++ if (!targetElements.length) { ++ return targetElements; ++ } ++ ++ // handle api method calls on the plugin, e.g. powerTip('hide') ++ if ($.type(opts) === 'string' && $.powerTip[opts]) { ++ return $.powerTip[opts].call(targetElements, targetElements, arg); ++ } ++ ++ // extend options ++ options = $.extend({}, $.fn.powerTip.defaults, opts); ++ ++ // instantiate the TooltipController for this instance ++ tipController = new TooltipController(options); ++ ++ // hook mouse and viewport dimension tracking ++ initTracking(); ++ ++ // setup the elements ++ targetElements.each(function elementSetup() { ++ var $this = $(this), ++ dataPowertip = $this.data(DATA_POWERTIP), ++ dataElem = $this.data(DATA_POWERTIPJQ), ++ dataTarget = $this.data(DATA_POWERTIPTARGET), ++ title = $this.attr('title'); ++ ++ // attempt to use title attribute text if there is no data-powertip, ++ // data-powertipjq or data-powertiptarget. If we do use the title ++ // attribute, delete the attribute so the browser will not show it ++ if (!dataPowertip && !dataTarget && !dataElem && title) { ++ $this.data(DATA_POWERTIP, title); ++ $this.data(DATA_ORIGINALTITLE, title); ++ $this.removeAttr('title'); ++ } ++ ++ // create hover controllers for each element ++ $this.data( ++ DATA_DISPLAYCONTROLLER, ++ new DisplayController($this, options, tipController) ++ ); ++ }); ++ ++ // attach events to matched elements if the manual option is not enabled ++ if (!options.manual) { ++ // attach open events ++ $.each(options.openEvents, function(idx, evt) { ++ if ($.inArray(evt, options.closeEvents) > -1) { ++ // event is in both openEvents and closeEvents, so toggle it ++ targetElements.on(evt + EVENT_NAMESPACE, function elementToggle(event) { ++ $.powerTip.toggle(this, event); ++ }); ++ } else { ++ targetElements.on(evt + EVENT_NAMESPACE, function elementOpen(event) { ++ $.powerTip.show(this, event); ++ }); ++ } ++ }); ++ ++ // attach close events ++ $.each(options.closeEvents, function(idx, evt) { ++ if ($.inArray(evt, options.openEvents) < 0) { ++ targetElements.on(evt + EVENT_NAMESPACE, function elementClose(event) { ++ // set immediate to true for any event without mouse info ++ $.powerTip.hide(this, !isMouseEvent(event)); ++ }); ++ } ++ }); ++ ++ // attach escape key close event ++ targetElements.on('keydown' + EVENT_NAMESPACE, function elementKeyDown(event) { ++ // always close tooltip when the escape key is pressed ++ if (event.keyCode === 27) { ++ $.powerTip.hide(this, true); ++ } ++ }); ++ } ++ ++ return targetElements; ++ }; ++ ++ /** ++ * Default options for the powerTip plugin. ++ */ ++ $.fn.powerTip.defaults = { ++ fadeInTime: 200, ++ fadeOutTime: 100, ++ followMouse: false, ++ popupId: 'powerTip', ++ popupClass: null, ++ intentSensitivity: 7, ++ intentPollInterval: 100, ++ closeDelay: 100, ++ placement: 'n', ++ smartPlacement: false, ++ offset: 10, ++ mouseOnToPopup: false, ++ manual: false, ++ openEvents: [ 'mouseenter', 'focus' ], ++ closeEvents: [ 'mouseleave', 'blur' ] ++ }; ++ ++ /** ++ * Default smart placement priority lists. ++ * The first item in the array is the highest priority, the last is the lowest. ++ * The last item is also the default, which will be used if all previous options ++ * do not fit. ++ */ ++ $.fn.powerTip.smartPlacementLists = { ++ n: [ 'n', 'ne', 'nw', 's' ], ++ e: [ 'e', 'ne', 'se', 'w', 'nw', 'sw', 'n', 's', 'e' ], ++ s: [ 's', 'se', 'sw', 'n' ], ++ w: [ 'w', 'nw', 'sw', 'e', 'ne', 'se', 'n', 's', 'w' ], ++ nw: [ 'nw', 'w', 'sw', 'n', 's', 'se', 'nw' ], ++ ne: [ 'ne', 'e', 'se', 'n', 's', 'sw', 'ne' ], ++ sw: [ 'sw', 'w', 'nw', 's', 'n', 'ne', 'sw' ], ++ se: [ 'se', 'e', 'ne', 's', 'n', 'nw', 'se' ], ++ 'nw-alt': [ 'nw-alt', 'n', 'ne-alt', 'sw-alt', 's', 'se-alt', 'w', 'e' ], ++ 'ne-alt': [ 'ne-alt', 'n', 'nw-alt', 'se-alt', 's', 'sw-alt', 'e', 'w' ], ++ 'sw-alt': [ 'sw-alt', 's', 'se-alt', 'nw-alt', 'n', 'ne-alt', 'w', 'e' ], ++ 'se-alt': [ 'se-alt', 's', 'sw-alt', 'ne-alt', 'n', 'nw-alt', 'e', 'w' ] ++ }; ++ ++ /** ++ * Public API ++ */ ++ $.powerTip = { ++ /** ++ * Attempts to show the tooltip for the specified element. ++ * @param {jQuery|Element} element The element to open the tooltip for. ++ * @param {jQuery.Event=} event jQuery event for hover intent and mouse ++ * tracking (optional). ++ * @return {jQuery|Element} The original jQuery object or DOM Element. ++ */ ++ show: function apiShowTip(element, event) { ++ // if we were given a mouse event then run the hover intent testing, ++ // otherwise, simply show the tooltip asap ++ if (isMouseEvent(event)) { ++ trackMouse(event); ++ session.previousX = event.pageX; ++ session.previousY = event.pageY; ++ $(element).data(DATA_DISPLAYCONTROLLER).show(); ++ } else { ++ $(element).first().data(DATA_DISPLAYCONTROLLER).show(true, true); ++ } ++ return element; ++ }, ++ ++ /** ++ * Repositions the tooltip on the element. ++ * @param {jQuery|Element} element The element the tooltip is shown for. ++ * @return {jQuery|Element} The original jQuery object or DOM Element. ++ */ ++ reposition: function apiResetPosition(element) { ++ $(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition(); ++ return element; ++ }, ++ ++ /** ++ * Attempts to close any open tooltips. ++ * @param {(jQuery|Element)=} element The element with the tooltip that ++ * should be closed (optional). ++ * @param {boolean=} immediate Disable close delay (optional). ++ * @return {jQuery|Element|undefined} The original jQuery object or DOM ++ * Element, if one was specified. ++ */ ++ hide: function apiCloseTip(element, immediate) { ++ var displayController; ++ ++ // set immediate to true when no element is specified ++ immediate = element ? immediate : true; ++ ++ // find the relevant display controller ++ if (element) { ++ displayController = $(element).first().data(DATA_DISPLAYCONTROLLER); ++ } else if (session.activeHover) { ++ displayController = session.activeHover.data(DATA_DISPLAYCONTROLLER); ++ } ++ ++ // if found, hide the tip ++ if (displayController) { ++ displayController.hide(immediate); ++ } ++ ++ return element; ++ }, ++ ++ /** ++ * Toggles the tooltip for the specified element. This will open a closed ++ * tooltip, or close an open tooltip. ++ * @param {jQuery|Element} element The element with the tooltip that ++ * should be toggled. ++ * @param {jQuery.Event=} event jQuery event for hover intent and mouse ++ * tracking (optional). ++ * @return {jQuery|Element} The original jQuery object or DOM Element. ++ */ ++ toggle: function apiToggle(element, event) { ++ if (session.activeHover && session.activeHover.is(element)) { ++ // tooltip for element is active, so close it ++ $.powerTip.hide(element, !isMouseEvent(event)); ++ } else { ++ // tooltip for element is not active, so open it ++ $.powerTip.show(element, event); ++ } ++ return element; ++ }, ++ ++ }; ++ ++ // API aliasing ++ $.powerTip.showTip = $.powerTip.show; ++ $.powerTip.closeTip = $.powerTip.hide; ++ ++ /** ++ * Creates a new CSSCoordinates object. ++ * @private ++ * @constructor ++ */ ++ function CSSCoordinates() { ++ var me = this; ++ ++ // initialize object properties ++ me.top = 'auto'; ++ me.left = 'auto'; ++ me.right = 'auto'; ++ me.bottom = 'auto'; ++ ++ /** ++ * Set a property to a value. ++ * @private ++ * @param {string} property The name of the property. ++ * @param {number} value The value of the property. ++ */ ++ me.set = function(property, value) { ++ if ($.isNumeric(value)) { ++ me[property] = Math.round(value); ++ } ++ }; ++ } ++ ++ /** ++ * Creates a new tooltip display controller. ++ * @private ++ * @constructor ++ * @param {jQuery} element The element that this controller will handle. ++ * @param {Object} options Options object containing settings. ++ * @param {TooltipController} tipController The TooltipController object for ++ * this instance. ++ */ ++ function DisplayController(element, options, tipController) { ++ var hoverTimer = null, ++ myCloseDelay = null; ++ ++ /** ++ * Begins the process of showing a tooltip. ++ * @private ++ * @param {boolean=} immediate Skip intent testing (optional). ++ * @param {boolean=} forceOpen Ignore cursor position and force tooltip to ++ * open (optional). ++ */ ++ function openTooltip(immediate, forceOpen) { ++ cancelTimer(); ++ if (!element.data(DATA_HASACTIVEHOVER)) { ++ if (!immediate) { ++ session.tipOpenImminent = true; ++ hoverTimer = setTimeout( ++ function intentDelay() { ++ hoverTimer = null; ++ checkForIntent(); ++ }, ++ options.intentPollInterval ++ ); ++ } else { ++ if (forceOpen) { ++ element.data(DATA_FORCEDOPEN, true); ++ } ++ closeAnyDelayed(); ++ tipController.showTip(element); ++ } ++ } else { ++ // cursor left and returned to this element, cancel close ++ cancelClose(); ++ } ++ } ++ ++ /** ++ * Begins the process of closing a tooltip. ++ * @private ++ * @param {boolean=} disableDelay Disable close delay (optional). ++ */ ++ function closeTooltip(disableDelay) { ++ // if this instance already has a close delay in progress then halt it ++ if (myCloseDelay) { ++ myCloseDelay = session.closeDelayTimeout = clearTimeout(myCloseDelay); ++ session.delayInProgress = false; ++ } ++ cancelTimer(); ++ session.tipOpenImminent = false; ++ if (element.data(DATA_HASACTIVEHOVER)) { ++ element.data(DATA_FORCEDOPEN, false); ++ if (!disableDelay) { ++ session.delayInProgress = true; ++ session.closeDelayTimeout = setTimeout( ++ function closeDelay() { ++ session.closeDelayTimeout = null; ++ tipController.hideTip(element); ++ session.delayInProgress = false; ++ myCloseDelay = null; ++ }, ++ options.closeDelay ++ ); ++ // save internal reference close delay id so we can check if the ++ // active close delay belongs to this instance ++ myCloseDelay = session.closeDelayTimeout; ++ } else { ++ tipController.hideTip(element); ++ } ++ } ++ } ++ ++ /** ++ * Checks mouse position to make sure that the user intended to hover on the ++ * specified element before showing the tooltip. ++ * @private ++ */ ++ function checkForIntent() { ++ // calculate mouse position difference ++ var xDifference = Math.abs(session.previousX - session.currentX), ++ yDifference = Math.abs(session.previousY - session.currentY), ++ totalDifference = xDifference + yDifference; ++ ++ // check if difference has passed the sensitivity threshold ++ if (totalDifference < options.intentSensitivity) { ++ cancelClose(); ++ closeAnyDelayed(); ++ tipController.showTip(element); ++ } else { ++ // try again ++ session.previousX = session.currentX; ++ session.previousY = session.currentY; ++ openTooltip(); ++ } ++ } ++ ++ /** ++ * Cancels active hover timer. ++ * @private ++ * @param {boolean=} stopClose Cancel any active close delay timer. ++ */ ++ function cancelTimer(stopClose) { ++ hoverTimer = clearTimeout(hoverTimer); ++ // cancel the current close delay if the active close delay is for this ++ // element or the stopClose argument is true ++ if (session.closeDelayTimeout && myCloseDelay === session.closeDelayTimeout || stopClose) { ++ cancelClose(); ++ } ++ } ++ ++ /** ++ * Cancels any active close delay timer. ++ * @private ++ */ ++ function cancelClose() { ++ session.closeDelayTimeout = clearTimeout(session.closeDelayTimeout); ++ session.delayInProgress = false; ++ } ++ ++ /** ++ * Asks any tooltips waiting on their close delay to close now. ++ * @private ++ */ ++ function closeAnyDelayed() { ++ // if another element is waiting for its close delay then we should ask ++ // it to close immediately so we can proceed without unexpected timeout ++ // code being run during this tooltip's lifecycle ++ if (session.delayInProgress && session.activeHover && !session.activeHover.is(element)) { ++ session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(true); ++ } ++ } ++ ++ /** ++ * Repositions the tooltip on this element. ++ * @private ++ */ ++ function repositionTooltip() { ++ tipController.resetPosition(element); ++ } ++ ++ // expose the methods ++ this.show = openTooltip; ++ this.hide = closeTooltip; ++ this.cancel = cancelTimer; ++ this.resetPosition = repositionTooltip; ++ } ++ ++ /** ++ * Creates a new Placement Calculator. ++ * @private ++ * @constructor ++ */ ++ function PlacementCalculator() { ++ /** ++ * Compute the CSS position to display a tooltip at the specified placement ++ * relative to the specified element. ++ * @private ++ * @param {jQuery} element The element that the tooltip should target. ++ * @param {string} placement The placement for the tooltip. ++ * @param {number} tipWidth Width of the tooltip element in pixels. ++ * @param {number} tipHeight Height of the tooltip element in pixels. ++ * @param {number} offset Distance to offset tooltips in pixels. ++ * @return {CSSCoordinates} A CSSCoordinates object with the position. ++ */ ++ function computePlacementCoords(element, placement, tipWidth, tipHeight, offset) { ++ var placementBase = placement.split('-')[0], // ignore 'alt' for corners ++ coords = new CSSCoordinates(), ++ position; ++ ++ if (isSvgElement(element)) { ++ position = getSvgPlacement(element, placementBase); ++ } else { ++ position = getHtmlPlacement(element, placementBase); ++ } ++ ++ // calculate the appropriate x and y position in the document ++ switch (placement) { ++ case 'n': ++ coords.set('left', position.left - (tipWidth / 2)); ++ coords.set('bottom', session.windowHeight - position.top + offset); ++ break; ++ case 'e': ++ coords.set('left', position.left + offset); ++ coords.set('top', position.top - (tipHeight / 2)); ++ break; ++ case 's': ++ coords.set('left', position.left - (tipWidth / 2)); ++ coords.set('top', position.top + offset); ++ break; ++ case 'w': ++ coords.set('top', position.top - (tipHeight / 2)); ++ coords.set('right', session.windowWidth - position.left + offset); ++ break; ++ case 'nw': ++ coords.set('bottom', session.windowHeight - position.top + offset); ++ coords.set('right', session.windowWidth - position.left - 20); ++ break; ++ case 'nw-alt': ++ coords.set('left', position.left); ++ coords.set('bottom', session.windowHeight - position.top + offset); ++ break; ++ case 'ne': ++ coords.set('left', position.left - 20); ++ coords.set('bottom', session.windowHeight - position.top + offset); ++ break; ++ case 'ne-alt': ++ coords.set('bottom', session.windowHeight - position.top + offset); ++ coords.set('right', session.windowWidth - position.left); ++ break; ++ case 'sw': ++ coords.set('top', position.top + offset); ++ coords.set('right', session.windowWidth - position.left - 20); ++ break; ++ case 'sw-alt': ++ coords.set('left', position.left); ++ coords.set('top', position.top + offset); ++ break; ++ case 'se': ++ coords.set('left', position.left - 20); ++ coords.set('top', position.top + offset); ++ break; ++ case 'se-alt': ++ coords.set('top', position.top + offset); ++ coords.set('right', session.windowWidth - position.left); ++ break; ++ } ++ ++ return coords; ++ } ++ ++ /** ++ * Finds the tooltip attachment point in the document for a HTML DOM element ++ * for the specified placement. ++ * @private ++ * @param {jQuery} element The element that the tooltip should target. ++ * @param {string} placement The placement for the tooltip. ++ * @return {Object} An object with the top,left position values. ++ */ ++ function getHtmlPlacement(element, placement) { ++ var objectOffset = element.offset(), ++ objectWidth = element.outerWidth(), ++ objectHeight = element.outerHeight(), ++ left, ++ top; ++ ++ // calculate the appropriate x and y position in the document ++ switch (placement) { ++ case 'n': ++ left = objectOffset.left + objectWidth / 2; ++ top = objectOffset.top; ++ break; ++ case 'e': ++ left = objectOffset.left + objectWidth; ++ top = objectOffset.top + objectHeight / 2; ++ break; ++ case 's': ++ left = objectOffset.left + objectWidth / 2; ++ top = objectOffset.top + objectHeight; ++ break; ++ case 'w': ++ left = objectOffset.left; ++ top = objectOffset.top + objectHeight / 2; ++ break; ++ case 'nw': ++ left = objectOffset.left; ++ top = objectOffset.top; ++ break; ++ case 'ne': ++ left = objectOffset.left + objectWidth; ++ top = objectOffset.top; ++ break; ++ case 'sw': ++ left = objectOffset.left; ++ top = objectOffset.top + objectHeight; ++ break; ++ case 'se': ++ left = objectOffset.left + objectWidth; ++ top = objectOffset.top + objectHeight; ++ break; ++ } ++ ++ return { ++ top: top, ++ left: left ++ }; ++ } ++ ++ /** ++ * Finds the tooltip attachment point in the document for a SVG element for ++ * the specified placement. ++ * @private ++ * @param {jQuery} element The element that the tooltip should target. ++ * @param {string} placement The placement for the tooltip. ++ * @return {Object} An object with the top,left position values. ++ */ ++ function getSvgPlacement(element, placement) { ++ var svgElement = element.closest('svg')[0], ++ domElement = element[0], ++ point = svgElement.createSVGPoint(), ++ boundingBox = domElement.getBBox(), ++ matrix = domElement.getScreenCTM(), ++ halfWidth = boundingBox.width / 2, ++ halfHeight = boundingBox.height / 2, ++ placements = [], ++ placementKeys = [ 'nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w' ], ++ coords, ++ rotation, ++ steps, ++ x; ++ ++ /** ++ * Transform and append the current points to the placements list. ++ * @private ++ */ ++ function pushPlacement() { ++ placements.push(point.matrixTransform(matrix)); ++ } ++ ++ // get bounding box corners and midpoints ++ point.x = boundingBox.x; ++ point.y = boundingBox.y; ++ pushPlacement(); ++ point.x += halfWidth; ++ pushPlacement(); ++ point.x += halfWidth; ++ pushPlacement(); ++ point.y += halfHeight; ++ pushPlacement(); ++ point.y += halfHeight; ++ pushPlacement(); ++ point.x -= halfWidth; ++ pushPlacement(); ++ point.x -= halfWidth; ++ pushPlacement(); ++ point.y -= halfHeight; ++ pushPlacement(); ++ ++ // determine rotation ++ if (placements[0].y !== placements[1].y || placements[0].x !== placements[7].x) { ++ rotation = Math.atan2(matrix.b, matrix.a) * RAD2DEG; ++ steps = Math.ceil(((rotation % 360) - 22.5) / 45); ++ if (steps < 1) { ++ steps += 8; ++ } ++ while (steps--) { ++ placementKeys.push(placementKeys.shift()); ++ } ++ } ++ ++ // find placement ++ for (x = 0; x < placements.length; x++) { ++ if (placementKeys[x] === placement) { ++ coords = placements[x]; ++ break; ++ } ++ } ++ ++ return { ++ top: coords.y + session.scrollTop, ++ left: coords.x + session.scrollLeft ++ }; ++ } ++ ++ // expose methods ++ this.compute = computePlacementCoords; ++ } ++ ++ /** ++ * Creates a new tooltip controller. ++ * @private ++ * @constructor ++ * @param {Object} options Options object containing settings. ++ */ ++ function TooltipController(options) { ++ var placementCalculator = new PlacementCalculator(), ++ tipElement = $('#' + options.popupId); ++ ++ // build and append tooltip div if it does not already exist ++ if (tipElement.length === 0) { ++ tipElement = $('
', { id: options.popupId }); ++ // grab body element if it was not populated when the script loaded ++ // note: this hack exists solely for jsfiddle support ++ if ($body.length === 0) { ++ $body = $('body'); ++ } ++ $body.append(tipElement); ++ // remember the tooltip elements that the plugin has created ++ session.tooltips = session.tooltips ? session.tooltips.add(tipElement) : tipElement; ++ } ++ ++ // hook mousemove for cursor follow tooltips ++ if (options.followMouse) { ++ // only one positionTipOnCursor hook per tooltip element, please ++ if (!tipElement.data(DATA_HASMOUSEMOVE)) { ++ $document.on('mousemove' + EVENT_NAMESPACE, positionTipOnCursor); ++ $window.on('scroll' + EVENT_NAMESPACE, positionTipOnCursor); ++ tipElement.data(DATA_HASMOUSEMOVE, true); ++ } ++ } ++ ++ /** ++ * Gives the specified element the active-hover state and queues up the ++ * showTip function. ++ * @private ++ * @param {jQuery} element The element that the tooltip should target. ++ */ ++ function beginShowTip(element) { ++ element.data(DATA_HASACTIVEHOVER, true); ++ // show tooltip, asap ++ tipElement.queue(function queueTipInit(next) { ++ showTip(element); ++ next(); ++ }); ++ } ++ ++ /** ++ * Shows the tooltip, as soon as possible. ++ * @private ++ * @param {jQuery} element The element that the tooltip should target. ++ */ ++ function showTip(element) { ++ var tipContent; ++ ++ // it is possible, especially with keyboard navigation, to move on to ++ // another element with a tooltip during the queue to get to this point ++ // in the code. if that happens then we need to not proceed or we may ++ // have the fadeout callback for the last tooltip execute immediately ++ // after this code runs, causing bugs. ++ if (!element.data(DATA_HASACTIVEHOVER)) { ++ return; ++ } ++ ++ // if the tooltip is open and we got asked to open another one then the ++ // old one is still in its fadeOut cycle, so wait and try again ++ if (session.isTipOpen) { ++ if (!session.isClosing) { ++ hideTip(session.activeHover); ++ } ++ tipElement.delay(100).queue(function queueTipAgain(next) { ++ showTip(element); ++ next(); ++ }); ++ return; ++ } ++ ++ // trigger powerTipPreRender event ++ element.trigger('powerTipPreRender'); ++ ++ // set tooltip content ++ tipContent = getTooltipContent(element); ++ if (tipContent) { ++ tipElement.empty().append(tipContent); ++ } else { ++ // we have no content to display, give up ++ return; ++ } ++ ++ // trigger powerTipRender event ++ element.trigger('powerTipRender'); ++ ++ session.activeHover = element; ++ session.isTipOpen = true; ++ ++ tipElement.data(DATA_MOUSEONTOTIP, options.mouseOnToPopup); ++ ++ // add custom class to tooltip element ++ tipElement.addClass(options.popupClass); ++ ++ // set tooltip position ++ // revert to static placement when the "force open" flag was set because ++ // that flag means that we do not have accurate mouse position info ++ if (!options.followMouse || element.data(DATA_FORCEDOPEN)) { ++ positionTipOnElement(element); ++ session.isFixedTipOpen = true; ++ } else { ++ positionTipOnCursor(); ++ } ++ ++ // close tooltip when clicking anywhere on the page, with the exception ++ // of the tooltip's trigger element and any elements that are within a ++ // tooltip that has 'mouseOnToPopup' option enabled ++ // always enable this feature when the "force open" flag is set on a ++ // followMouse tooltip because we reverted to static placement above ++ if (!element.data(DATA_FORCEDOPEN) && !options.followMouse) { ++ $document.on('click' + EVENT_NAMESPACE, function documentClick(event) { ++ var target = event.target; ++ if (target !== element[0]) { ++ if (options.mouseOnToPopup) { ++ if (target !== tipElement[0] && !$.contains(tipElement[0], target)) { ++ $.powerTip.hide(); ++ } ++ } else { ++ $.powerTip.hide(); ++ } ++ } ++ }); ++ } ++ ++ // if we want to be able to mouse on to the tooltip then we need to ++ // attach hover events to the tooltip that will cancel a close request ++ // on mouseenter and start a new close request on mouseleave ++ // only hook these listeners if we're not in manual mode ++ if (options.mouseOnToPopup && !options.manual) { ++ tipElement.on('mouseenter' + EVENT_NAMESPACE, function tipMouseEnter() { ++ // check activeHover in case the mouse cursor entered the ++ // tooltip during the fadeOut and close cycle ++ if (session.activeHover) { ++ session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel(); ++ } ++ }); ++ tipElement.on('mouseleave' + EVENT_NAMESPACE, function tipMouseLeave() { ++ // check activeHover in case the mouse cursor left the tooltip ++ // during the fadeOut and close cycle ++ if (session.activeHover) { ++ session.activeHover.data(DATA_DISPLAYCONTROLLER).hide(); ++ } ++ }); ++ } ++ ++ // fadein ++ tipElement.fadeIn(options.fadeInTime, function fadeInCallback() { ++ // start desync polling ++ if (!session.desyncTimeout) { ++ session.desyncTimeout = setInterval(closeDesyncedTip, 500); ++ } ++ ++ // trigger powerTipOpen event ++ element.trigger('powerTipOpen'); ++ }); ++ } ++ ++ /** ++ * Hides the tooltip. ++ * @private ++ * @param {jQuery} element The element that the tooltip should target. ++ */ ++ function hideTip(element) { ++ // reset session ++ session.isClosing = true; ++ session.isTipOpen = false; ++ ++ // stop desync polling ++ session.desyncTimeout = clearInterval(session.desyncTimeout); ++ ++ // reset element state ++ element.data(DATA_HASACTIVEHOVER, false); ++ element.data(DATA_FORCEDOPEN, false); ++ ++ // remove document click handler ++ $document.off('click' + EVENT_NAMESPACE); ++ ++ // unbind the mouseOnToPopup events if they were set ++ tipElement.off(EVENT_NAMESPACE); ++ ++ // fade out ++ tipElement.fadeOut(options.fadeOutTime, function fadeOutCallback() { ++ var coords = new CSSCoordinates(); ++ ++ // reset session and tooltip element ++ session.activeHover = null; ++ session.isClosing = false; ++ session.isFixedTipOpen = false; ++ tipElement.removeClass(); ++ ++ // support mouse-follow and fixed position tips at the same time by ++ // moving the tooltip to the last cursor location after it is hidden ++ coords.set('top', session.currentY + options.offset); ++ coords.set('left', session.currentX + options.offset); ++ tipElement.css(coords); ++ ++ // trigger powerTipClose event ++ element.trigger('powerTipClose'); ++ }); ++ } ++ ++ /** ++ * Moves the tooltip to the users mouse cursor. ++ * @private ++ */ ++ function positionTipOnCursor() { ++ var tipWidth, ++ tipHeight, ++ coords, ++ collisions, ++ collisionCount; ++ ++ // to support having fixed tooltips on the same page as cursor tooltips, ++ // where both instances are referencing the same tooltip element, we ++ // need to keep track of the mouse position constantly, but we should ++ // only set the tip location if a fixed tip is not currently open, a tip ++ // open is imminent or active, and the tooltip element in question does ++ // have a mouse-follow using it. ++ if (!session.isFixedTipOpen && (session.isTipOpen || (session.tipOpenImminent && tipElement.data(DATA_HASMOUSEMOVE)))) { ++ // grab measurements ++ tipWidth = tipElement.outerWidth(); ++ tipHeight = tipElement.outerHeight(); ++ coords = new CSSCoordinates(); ++ ++ // grab collisions ++ coords.set('top', session.currentY + options.offset); ++ coords.set('left', session.currentX + options.offset); ++ collisions = getViewportCollisions( ++ coords, ++ tipWidth, ++ tipHeight ++ ); ++ ++ // handle tooltip view port collisions ++ if (collisions !== Collision.none) { ++ collisionCount = countFlags(collisions); ++ if (collisionCount === 1) { ++ // if there is only one collision (bottom or right) then ++ // simply constrain the tooltip to the view port ++ if (collisions === Collision.right) { ++ coords.set('left', session.scrollLeft + session.windowWidth - tipWidth); ++ } else if (collisions === Collision.bottom) { ++ coords.set('top', session.scrollTop + session.windowHeight - tipHeight); ++ } ++ } else { ++ // if the tooltip has more than one collision then it is ++ // trapped in the corner and should be flipped to get it out ++ // of the users way ++ coords.set('left', session.currentX - tipWidth - options.offset); ++ coords.set('top', session.currentY - tipHeight - options.offset); ++ } ++ } ++ ++ // position the tooltip ++ tipElement.css(coords); ++ } ++ } ++ ++ /** ++ * Sets the tooltip to the correct position relative to the specified target ++ * element. Based on options settings. ++ * @private ++ * @param {jQuery} element The element that the tooltip should target. ++ */ ++ function positionTipOnElement(element) { ++ var priorityList, ++ finalPlacement; ++ ++ // when the followMouse option is enabled and the "force open" flag is ++ // set we revert to static positioning. since the developer may not have ++ // considered this scenario we should use smart placement ++ if (options.smartPlacement || (options.followMouse && element.data(DATA_FORCEDOPEN))) { ++ priorityList = $.fn.powerTip.smartPlacementLists[options.placement]; ++ ++ // iterate over the priority list and use the first placement option ++ // that does not collide with the view port. if they all collide ++ // then the last placement in the list will be used. ++ $.each(priorityList, function(idx, pos) { ++ // place tooltip and find collisions ++ var collisions = getViewportCollisions( ++ placeTooltip(element, pos), ++ tipElement.outerWidth(), ++ tipElement.outerHeight() ++ ); ++ ++ // update the final placement variable ++ finalPlacement = pos; ++ ++ // break if there were no collisions ++ return collisions !== Collision.none; ++ }); ++ } else { ++ // if we're not going to use the smart placement feature then just ++ // compute the coordinates and do it ++ placeTooltip(element, options.placement); ++ finalPlacement = options.placement; ++ } ++ ++ // add placement as class for CSS arrows ++ tipElement.removeClass('w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt'); ++ tipElement.addClass(finalPlacement); ++ } ++ ++ /** ++ * Sets the tooltip position to the appropriate values to show the tip at ++ * the specified placement. This function will iterate and test the tooltip ++ * to support elastic tooltips. ++ * @private ++ * @param {jQuery} element The element that the tooltip should target. ++ * @param {string} placement The placement for the tooltip. ++ * @return {CSSCoordinates} A CSSCoordinates object with the top, left, and ++ * right position values. ++ */ ++ function placeTooltip(element, placement) { ++ var iterationCount = 0, ++ tipWidth, ++ tipHeight, ++ coords = new CSSCoordinates(); ++ ++ // set the tip to 0,0 to get the full expanded width ++ coords.set('top', 0); ++ coords.set('left', 0); ++ tipElement.css(coords); ++ ++ // to support elastic tooltips we need to check for a change in the ++ // rendered dimensions after the tooltip has been positioned ++ do { ++ // grab the current tip dimensions ++ tipWidth = tipElement.outerWidth(); ++ tipHeight = tipElement.outerHeight(); ++ ++ // get placement coordinates ++ coords = placementCalculator.compute( ++ element, ++ placement, ++ tipWidth, ++ tipHeight, ++ options.offset ++ ); ++ ++ // place the tooltip ++ tipElement.css(coords); ++ } while ( ++ // sanity check: limit to 5 iterations, and... ++ ++iterationCount <= 5 && ++ // try again if the dimensions changed after placement ++ (tipWidth !== tipElement.outerWidth() || tipHeight !== tipElement.outerHeight()) ++ ); ++ ++ return coords; ++ } ++ ++ /** ++ * Checks for a tooltip desync and closes the tooltip if one occurs. ++ * @private ++ */ ++ function closeDesyncedTip() { ++ var isDesynced = false, ++ hasDesyncableCloseEvent = $.grep( ++ [ 'mouseleave', 'mouseout', 'blur', 'focusout' ], ++ function(eventType) { ++ return $.inArray(eventType, options.closeEvents) !== -1; ++ } ++ ).length > 0; ++ ++ // It is possible for the mouse cursor to leave an element without ++ // firing the mouseleave or blur event. This most commonly happens when ++ // the element is disabled under mouse cursor. If this happens it will ++ // result in a desynced tooltip because the tooltip was never asked to ++ // close. So we should periodically check for a desync situation and ++ // close the tip if such a situation arises. ++ if (session.isTipOpen && !session.isClosing && !session.delayInProgress && hasDesyncableCloseEvent) { ++ if (session.activeHover.data(DATA_HASACTIVEHOVER) === false || session.activeHover.is(':disabled')) { ++ // user moused onto another tip or active hover is disabled ++ isDesynced = true; ++ } else if (!isMouseOver(session.activeHover) && !session.activeHover.is(':focus') && !session.activeHover.data(DATA_FORCEDOPEN)) { ++ // hanging tip - have to test if mouse position is not over the ++ // active hover and not over a tooltip set to let the user ++ // interact with it. ++ // for keyboard navigation: this only counts if the element does ++ // not have focus. ++ // for tooltips opened via the api: we need to check if it has ++ // the forcedOpen flag. ++ if (tipElement.data(DATA_MOUSEONTOTIP)) { ++ if (!isMouseOver(tipElement)) { ++ isDesynced = true; ++ } ++ } else { ++ isDesynced = true; ++ } ++ } ++ ++ if (isDesynced) { ++ // close the desynced tip ++ hideTip(session.activeHover); ++ } ++ } ++ } ++ ++ // expose methods ++ this.showTip = beginShowTip; ++ this.hideTip = hideTip; ++ this.resetPosition = positionTipOnElement; ++ } ++ ++ /** ++ * Determine whether a jQuery object is an SVG element ++ * @private ++ * @param {jQuery} element The element to check ++ * @return {boolean} Whether this is an SVG element ++ */ ++ function isSvgElement(element) { ++ return Boolean(window.SVGElement && element[0] instanceof SVGElement); ++ } ++ ++ /** ++ * Determines if the specified jQuery.Event object has mouse data. ++ * @private ++ * @param {jQuery.Event=} event The jQuery.Event object to test. ++ * @return {boolean} True if there is mouse data, otherwise false. ++ */ ++ function isMouseEvent(event) { ++ return Boolean(event && $.inArray(event.type, MOUSE_EVENTS) > -1 && ++ typeof event.pageX === 'number'); ++ } ++ ++ /** ++ * Initializes the viewport dimension cache and hooks up the mouse position ++ * tracking and viewport dimension tracking events. ++ * Prevents attaching the events more than once. ++ * @private ++ */ ++ function initTracking() { ++ if (!session.mouseTrackingActive) { ++ session.mouseTrackingActive = true; ++ ++ // grab the current viewport dimensions on load ++ getViewportDimensions(); ++ $(getViewportDimensions); ++ ++ // hook mouse move tracking ++ $document.on('mousemove' + EVENT_NAMESPACE, trackMouse); ++ ++ // hook viewport dimensions tracking ++ $window.on('resize' + EVENT_NAMESPACE, trackResize); ++ $window.on('scroll' + EVENT_NAMESPACE, trackScroll); ++ } ++ } ++ ++ /** ++ * Updates the viewport dimensions cache. ++ * @private ++ */ ++ function getViewportDimensions() { ++ session.scrollLeft = $window.scrollLeft(); ++ session.scrollTop = $window.scrollTop(); ++ session.windowWidth = $window.width(); ++ session.windowHeight = $window.height(); ++ } ++ ++ /** ++ * Updates the window size info in the viewport dimensions cache. ++ * @private ++ */ ++ function trackResize() { ++ session.windowWidth = $window.width(); ++ session.windowHeight = $window.height(); ++ } ++ ++ /** ++ * Updates the scroll offset info in the viewport dimensions cache. ++ * @private ++ */ ++ function trackScroll() { ++ var x = $window.scrollLeft(), ++ y = $window.scrollTop(); ++ if (x !== session.scrollLeft) { ++ session.currentX += x - session.scrollLeft; ++ session.scrollLeft = x; ++ } ++ if (y !== session.scrollTop) { ++ session.currentY += y - session.scrollTop; ++ session.scrollTop = y; ++ } ++ } ++ ++ /** ++ * Saves the current mouse coordinates to the session object. ++ * @private ++ * @param {jQuery.Event} event The mousemove event for the document. ++ */ ++ function trackMouse(event) { ++ session.currentX = event.pageX; ++ session.currentY = event.pageY; ++ } ++ ++ /** ++ * Tests if the mouse is currently over the specified element. ++ * @private ++ * @param {jQuery} element The element to check for hover. ++ * @return {boolean} True if the mouse is over the element, otherwise false. ++ */ ++ function isMouseOver(element) { ++ // use getBoundingClientRect() because jQuery's width() and height() ++ // methods do not work with SVG elements ++ // compute width/height because those properties do not exist on the object ++ // returned by getBoundingClientRect() in older versions of IE ++ var elementPosition = element.offset(), ++ elementBox = element[0].getBoundingClientRect(), ++ elementWidth = elementBox.right - elementBox.left, ++ elementHeight = elementBox.bottom - elementBox.top; ++ ++ return session.currentX >= elementPosition.left && ++ session.currentX <= elementPosition.left + elementWidth && ++ session.currentY >= elementPosition.top && ++ session.currentY <= elementPosition.top + elementHeight; ++ } ++ ++ /** ++ * Fetches the tooltip content from the specified element's data attributes. ++ * @private ++ * @param {jQuery} element The element to get the tooltip content for. ++ * @return {(string|jQuery|undefined)} The text/HTML string, jQuery object, or ++ * undefined if there was no tooltip content for the element. ++ */ ++ function getTooltipContent(element) { ++ var tipText = element.data(DATA_POWERTIP), ++ tipObject = element.data(DATA_POWERTIPJQ), ++ tipTarget = element.data(DATA_POWERTIPTARGET), ++ targetElement, ++ content; ++ ++ if (tipText) { ++ if ($.isFunction(tipText)) { ++ tipText = tipText.call(element[0]); ++ } ++ content = tipText; ++ } else if (tipObject) { ++ if ($.isFunction(tipObject)) { ++ tipObject = tipObject.call(element[0]); ++ } ++ if (tipObject.length > 0) { ++ content = tipObject.clone(true, true); ++ } ++ } else if (tipTarget) { ++ targetElement = $('#' + tipTarget); ++ if (targetElement.length > 0) { ++ content = targetElement.html(); ++ } ++ } ++ ++ return content; ++ } ++ ++ /** ++ * Finds any viewport collisions that an element (the tooltip) would have if it ++ * were absolutely positioned at the specified coordinates. ++ * @private ++ * @param {CSSCoordinates} coords Coordinates for the element. ++ * @param {number} elementWidth Width of the element in pixels. ++ * @param {number} elementHeight Height of the element in pixels. ++ * @return {number} Value with the collision flags. ++ */ ++ function getViewportCollisions(coords, elementWidth, elementHeight) { ++ var viewportTop = session.scrollTop, ++ viewportLeft = session.scrollLeft, ++ viewportBottom = viewportTop + session.windowHeight, ++ viewportRight = viewportLeft + session.windowWidth, ++ collisions = Collision.none; ++ ++ if (coords.top < viewportTop || Math.abs(coords.bottom - session.windowHeight) - elementHeight < viewportTop) { ++ collisions |= Collision.top; ++ } ++ if (coords.top + elementHeight > viewportBottom || Math.abs(coords.bottom - session.windowHeight) > viewportBottom) { ++ collisions |= Collision.bottom; ++ } ++ if (coords.left < viewportLeft || coords.right + elementWidth > viewportRight) { ++ collisions |= Collision.left; ++ } ++ if (coords.left + elementWidth > viewportRight || coords.right < viewportLeft) { ++ collisions |= Collision.right; ++ } ++ ++ return collisions; ++ } ++ ++ /** ++ * Counts the number of bits set on a flags value. ++ * @param {number} value The flags value. ++ * @return {number} The number of bits that have been set. ++ */ ++ function countFlags(value) { ++ var count = 0; ++ while (value) { ++ value &= value - 1; ++ count++; ++ } ++ return count; ++ } ++ ++ // return api for commonjs and amd environments ++ return $.powerTip; ++})); +diff -Nur doxygen-1.8.14.orig/jquery/jquery.powertip-1.3.1.mod.min.js doxygen-1.8.14/jquery/jquery.powertip-1.3.1.mod.min.js +--- doxygen-1.8.14.orig/jquery/jquery.powertip-1.3.1.mod.min.js 1970-01-01 01:00:00.000000000 +0100 ++++ doxygen-1.8.14/jquery/jquery.powertip-1.3.1.mod.min.js 2020-01-03 23:51:18.000000000 +0100 +@@ -0,0 +1,8 @@ ++/*! ++ PowerTip v1.3.1 (2018-04-15) ++ https://stevenbenner.github.io/jquery-powertip/ ++ Copyright (c) 2018 Steven Benner (http://stevenbenner.com/). ++ Released under MIT license. ++ https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt ++*/ ++(function(root,factory){if(typeof define==="function"&&define.amd){define(["jquery"],factory)}else if(typeof module==="object"&&module.exports){module.exports=factory(require("jquery"))}else{factory(root.jQuery)}})(this,function($){var $document=$(document),$window=$(window),$body=$("body");var DATA_DISPLAYCONTROLLER="displayController",DATA_HASACTIVEHOVER="hasActiveHover",DATA_FORCEDOPEN="forcedOpen",DATA_HASMOUSEMOVE="hasMouseMove",DATA_MOUSEONTOTIP="mouseOnToPopup",DATA_ORIGINALTITLE="originalTitle",DATA_POWERTIP="powertip",DATA_POWERTIPJQ="powertipjq",DATA_POWERTIPTARGET="powertiptarget",EVENT_NAMESPACE=".powertip",RAD2DEG=180/Math.PI,MOUSE_EVENTS=["click","dblclick","mousedown","mouseup","mousemove","mouseover","mouseout","mouseenter","mouseleave","contextmenu"];var session={tooltips:null,isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,closeDelayTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var Collision={none:0,top:1,bottom:2,left:4,right:8};$.fn.powerTip=function(opts,arg){var targetElements=this,options,tipController;if(!targetElements.length){return targetElements}if($.type(opts)==="string"&&$.powerTip[opts]){return $.powerTip[opts].call(targetElements,targetElements,arg)}options=$.extend({},$.fn.powerTip.defaults,opts);tipController=new TooltipController(options);initTracking();targetElements.each(function elementSetup(){var $this=$(this),dataPowertip=$this.data(DATA_POWERTIP),dataElem=$this.data(DATA_POWERTIPJQ),dataTarget=$this.data(DATA_POWERTIPTARGET),title=$this.attr("title");if(!dataPowertip&&!dataTarget&&!dataElem&&title){$this.data(DATA_POWERTIP,title);$this.data(DATA_ORIGINALTITLE,title);$this.removeAttr("title")}$this.data(DATA_DISPLAYCONTROLLER,new DisplayController($this,options,tipController))});if(!options.manual){$.each(options.openEvents,function(idx,evt){if($.inArray(evt,options.closeEvents)>-1){targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if(session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)}closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if(session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE,function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList,finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight()));return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")}function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(),elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight,viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.topviewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.leftviewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right= 1.3 ? 0 : 1 +- }; +- +- // Returns the element that needs to be animated to scroll the window. +- // Kept for backwards compatibility (specially for localScroll & serialScroll) +- $scrollTo.window = function( scope ){ +- return $(window)._scrollable(); +- }; +- +- // Hack, hack, hack :) +- // Returns the real elements to scroll (supports window/iframes, documents and regular nodes) +- $.fn._scrollable = function(){ +- return this.map(function(){ +- var elem = this, +- isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1; +- +- if( !isWin ) +- return elem; +- +- var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem; +- +- return $.browser.safari || doc.compatMode == 'BackCompat' ? +- doc.body : +- doc.documentElement; +- }); +- }; +- +- $.fn.scrollTo = function( target, duration, settings ){ +- if( typeof duration == 'object' ){ +- settings = duration; +- duration = 0; +- } +- if( typeof settings == 'function' ) +- settings = { onAfter:settings }; +- +- if( target == 'max' ) +- target = 9e9; +- +- settings = $.extend( {}, $scrollTo.defaults, settings ); +- // Speed is still recognized for backwards compatibility +- duration = duration || settings.speed || settings.duration; +- // Make sure the settings are given right +- settings.queue = settings.queue && settings.axis.length > 1; +- +- if( settings.queue ) +- // Let's keep the overall duration +- duration /= 2; +- settings.offset = both( settings.offset ); +- settings.over = both( settings.over ); +- +- return this._scrollable().each(function(){ +- var elem = this, +- $elem = $(elem), +- targ = target, toff, attr = {}, +- win = $elem.is('html,body'); +- +- switch( typeof targ ){ +- // A number will pass the regex +- case 'number': +- case 'string': +- if( /^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ) ){ +- targ = both( targ ); +- // We are done +- break; +- } +- // Relative selector, no break! +- targ = $(targ,this); +- case 'object': +- // DOMElement / jQuery +- if( targ.is || targ.style ) +- // Get the real position of the target +- toff = (targ = $(targ)).offset(); +- } +- $.each( settings.axis.split(''), function( i, axis ){ +- var Pos = axis == 'x' ? 'Left' : 'Top', +- pos = Pos.toLowerCase(), +- key = 'scroll' + Pos, +- old = elem[key], +- max = $scrollTo.max(elem, axis); +- +- if( toff ){// jQuery / DOMElement +- attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] ); +- +- // If it's a dom element, reduce the margin +- if( settings.margin ){ +- attr[key] -= parseInt(targ.css('margin'+Pos)) || 0; +- attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0; +- } +- +- attr[key] += settings.offset[pos] || 0; +- +- if( settings.over[pos] ) +- // Scroll to a fraction of its width/height +- attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos]; +- }else{ +- var val = targ[pos]; +- // Handle percentage values +- attr[key] = val.slice && val.slice(-1) == '%' ? +- parseFloat(val) / 100 * max +- : val; +- } +- +- // Number or 'number' +- if( /^\d+$/.test(attr[key]) ) +- // Check the limits +- attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max ); +- +- // Queueing axes +- if( !i && settings.queue ){ +- // Don't waste time animating, if there's no need. +- if( old != attr[key] ) +- // Intermediate animation +- animate( settings.onAfterFirst ); +- // Don't animate this axis again in the next iteration. +- delete attr[key]; +- } +- }); +- +- animate( settings.onAfter ); +- +- function animate( callback ){ +- $elem.animate( attr, duration, settings.easing, callback && function(){ +- callback.call(this, target, settings); +- }); +- }; +- +- }).end(); +- }; +- +- // Max scrolling position, works on quirks mode +- // It only fails (not too badly) on IE, quirks mode. +- $scrollTo.max = function( elem, axis ){ +- var Dim = axis == 'x' ? 'Width' : 'Height', +- scroll = 'scroll'+Dim; +- +- if( !$(elem).is('html,body') ) +- return elem[scroll] - $(elem)[Dim.toLowerCase()](); +- +- var size = 'client' + Dim, +- html = elem.ownerDocument.documentElement, +- body = elem.ownerDocument.body; +- +- return Math.max( html[scroll], body[scroll] ) +- - Math.min( html[size] , body[size] ); +- +- }; +- +- function both( val ){ +- return typeof val == 'object' ? val : { top:val, left:val }; +- }; +- +-})( jQuery ); +\ No newline at end of file +diff -Nur doxygen-1.8.14.orig/jquery/jquery.scrollTo-2.1.2.min.js doxygen-1.8.14/jquery/jquery.scrollTo-2.1.2.min.js +--- doxygen-1.8.14.orig/jquery/jquery.scrollTo-2.1.2.min.js 1970-01-01 01:00:00.000000000 +0100 ++++ doxygen-1.8.14/jquery/jquery.scrollTo-2.1.2.min.js 2020-01-03 23:51:18.000000000 +0100 +@@ -0,0 +1,7 @@ ++/** ++ * Copyright (c) 2007 Ariel Flesler - aflesler ○ gmail • com | https://github.com/flesler ++ * Licensed under MIT ++ * @author Ariel Flesler ++ * @version 2.1.2 ++ */ ++;(function(f){"use strict";"function"===typeof define&&define.amd?define(["jquery"],f):"undefined"!==typeof module&&module.exports?module.exports=f(require("jquery")):f(jQuery)})(function($){"use strict";function n(a){return!a.nodeName||-1!==$.inArray(a.nodeName.toLowerCase(),["iframe","#document","html","body"])}function h(a){return $.isFunction(a)||$.isPlainObject(a)?a:{top:a,left:a}}var p=$.scrollTo=function(a,d,b){return $(window).scrollTo(a,d,b)};p.defaults={axis:"xy",duration:0,limit:!0};$.fn.scrollTo=function(a,d,b){"object"=== typeof d&&(b=d,d=0);"function"===typeof b&&(b={onAfter:b});"max"===a&&(a=9E9);b=$.extend({},p.defaults,b);d=d||b.duration;var u=b.queue&&1=f[g]?0:Math.min(f[g],n));!a&&1 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { +- mouse = true; +- // if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes +- if (firstTime) { +- var $a = $(e.target).closest('a'); +- if ($a.is('a')) { +- $.each(menuTrees, function() { +- if ($.contains(this.$root[0], $a[0])) { +- this.itemEnter({ currentTarget: $a[0] }); +- return false; +- } +- }); +- } +- firstTime = false; +- } +- } +- } +- lastMove = thisMove; +- }], +- [touchEvents ? 'touchstart' : 'pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut', function(e) { +- if (isTouchEvent(e.originalEvent)) { +- mouse = false; +- } +- }] +- ], eNS)); +- mouseDetectionEnabled = true; +- } else if (mouseDetectionEnabled && disable) { +- $(document).unbind(eNS); +- mouseDetectionEnabled = false; +- } +- } +- +- function isTouchEvent(e) { +- return !/^(4|mouse)$/.test(e.pointerType); +- } +- +- // returns a jQuery bind() ready object +- function getEventsNS(defArr, eNS) { +- if (!eNS) { +- eNS = ''; +- } +- var obj = {}; +- $.each(defArr, function(index, value) { +- obj[value[0].split(' ').join(eNS + ' ') + eNS] = value[1]; +- }); +- return obj; +- } +- +- $.SmartMenus = function(elm, options) { +- this.$root = $(elm); +- this.opts = options; +- this.rootId = ''; // internal +- this.accessIdPrefix = ''; +- this.$subArrow = null; +- this.activatedItems = []; // stores last activated A's for each level +- this.visibleSubMenus = []; // stores visible sub menus UL's (might be in no particular order) +- this.showTimeout = 0; +- this.hideTimeout = 0; +- this.scrollTimeout = 0; +- this.clickActivated = false; +- this.focusActivated = false; +- this.zIndexInc = 0; +- this.idInc = 0; +- this.$firstLink = null; // we'll use these for some tests +- this.$firstSub = null; // at runtime so we'll cache them +- this.disabled = false; +- this.$disableOverlay = null; +- this.$touchScrollingSub = null; +- this.cssTransforms3d = 'perspective' in elm.style || 'webkitPerspective' in elm.style; +- this.wasCollapsible = false; +- this.init(); +- }; +- +- $.extend($.SmartMenus, { +- hideAll: function() { +- $.each(menuTrees, function() { +- this.menuHideAll(); +- }); +- }, +- destroy: function() { +- while (menuTrees.length) { +- menuTrees[0].destroy(); +- } +- initMouseDetection(true); +- }, +- prototype: { +- init: function(refresh) { +- var self = this; +- +- if (!refresh) { +- menuTrees.push(this); +- +- this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); +- this.accessIdPrefix = 'sm-' + this.rootId + '-'; +- +- if (this.$root.hasClass('sm-rtl')) { +- this.opts.rightToLeftSubMenus = true; +- } +- +- // init root (main menu) +- var eNS = '.smartmenus'; +- this.$root +- .data('smartmenus', this) +- .attr('data-smartmenus-id', this.rootId) +- .dataSM('level', 1) +- .bind(getEventsNS([ +- ['mouseover focusin', $.proxy(this.rootOver, this)], +- ['mouseout focusout', $.proxy(this.rootOut, this)], +- ['keydown', $.proxy(this.rootKeyDown, this)] +- ], eNS)) +- .delegate('a', getEventsNS([ +- ['mouseenter', $.proxy(this.itemEnter, this)], +- ['mouseleave', $.proxy(this.itemLeave, this)], +- ['mousedown', $.proxy(this.itemDown, this)], +- ['focus', $.proxy(this.itemFocus, this)], +- ['blur', $.proxy(this.itemBlur, this)], +- ['click', $.proxy(this.itemClick, this)] +- ], eNS)); +- +- // hide menus on tap or click outside the root UL +- eNS += this.rootId; +- if (this.opts.hideOnClick) { +- $(document).bind(getEventsNS([ +- ['touchstart', $.proxy(this.docTouchStart, this)], +- ['touchmove', $.proxy(this.docTouchMove, this)], +- ['touchend', $.proxy(this.docTouchEnd, this)], +- // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too +- ['click', $.proxy(this.docClick, this)] +- ], eNS)); +- } +- // hide sub menus on resize +- $(window).bind(getEventsNS([['resize orientationchange', $.proxy(this.winResize, this)]], eNS)); +- +- if (this.opts.subIndicators) { +- this.$subArrow = $('').addClass('sub-arrow'); +- if (this.opts.subIndicatorsText) { +- this.$subArrow.html(this.opts.subIndicatorsText); +- } +- } +- +- // make sure mouse detection is enabled +- initMouseDetection(); +- } +- +- // init sub menus +- this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); +- +- this.$firstLink = this.$root.find('a').eq(0); +- +- // find current item +- if (this.opts.markCurrentItem) { +- var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, +- reHash = /#.*/, +- locHref = window.location.href.replace(reDefaultDoc, ''), +- locHrefNoHash = locHref.replace(reHash, ''); +- this.$root.find('a').each(function() { +- var href = this.href.replace(reDefaultDoc, ''), +- $this = $(this); +- if (href == locHref || href == locHrefNoHash) { +- $this.addClass('current'); +- if (self.opts.markCurrentTree) { +- $this.parentsUntil('[data-smartmenus-id]', 'ul').each(function() { +- $(this).dataSM('parent-a').addClass('current'); +- }); +- } +- } +- }); +- } +- +- // save initial state +- this.wasCollapsible = this.isCollapsible(); +- }, +- destroy: function(refresh) { +- if (!refresh) { +- var eNS = '.smartmenus'; +- this.$root +- .removeData('smartmenus') +- .removeAttr('data-smartmenus-id') +- .removeDataSM('level') +- .unbind(eNS) +- .undelegate(eNS); +- eNS += this.rootId; +- $(document).unbind(eNS); +- $(window).unbind(eNS); +- if (this.opts.subIndicators) { +- this.$subArrow = null; +- } +- } +- this.menuHideAll(); +- var self = this; +- this.$root.find('ul').each(function() { +- var $this = $(this); +- if ($this.dataSM('scroll-arrows')) { +- $this.dataSM('scroll-arrows').remove(); +- } +- if ($this.dataSM('shown-before')) { +- if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { +- $this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); +- } +- if ($this.dataSM('scroll-arrows')) { +- $this.dataSM('scroll-arrows').remove(); +- } +- $this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); +- } +- if (($this.attr('id') || '').indexOf(self.accessIdPrefix) == 0) { +- $this.removeAttr('id'); +- } +- }) +- .removeDataSM('in-mega') +- .removeDataSM('shown-before') +- .removeDataSM('ie-shim') +- .removeDataSM('scroll-arrows') +- .removeDataSM('parent-a') +- .removeDataSM('level') +- .removeDataSM('beforefirstshowfired') +- .removeAttr('role') +- .removeAttr('aria-hidden') +- .removeAttr('aria-labelledby') +- .removeAttr('aria-expanded'); +- this.$root.find('a.has-submenu').each(function() { +- var $this = $(this); +- if ($this.attr('id').indexOf(self.accessIdPrefix) == 0) { +- $this.removeAttr('id'); +- } +- }) +- .removeClass('has-submenu') +- .removeDataSM('sub') +- .removeAttr('aria-haspopup') +- .removeAttr('aria-controls') +- .removeAttr('aria-expanded') +- .closest('li').removeDataSM('sub'); +- if (this.opts.subIndicators) { +- this.$root.find('span.sub-arrow').remove(); +- } +- if (this.opts.markCurrentItem) { +- this.$root.find('a.current').removeClass('current'); +- } +- if (!refresh) { +- this.$root = null; +- this.$firstLink = null; +- this.$firstSub = null; +- if (this.$disableOverlay) { +- this.$disableOverlay.remove(); +- this.$disableOverlay = null; +- } +- menuTrees.splice($.inArray(this, menuTrees), 1); +- } +- }, +- disable: function(noOverlay) { +- if (!this.disabled) { +- this.menuHideAll(); +- // display overlay over the menu to prevent interaction +- if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { +- var pos = this.$root.offset(); +- this.$disableOverlay = $('
').css({ +- position: 'absolute', +- top: pos.top, +- left: pos.left, +- width: this.$root.outerWidth(), +- height: this.$root.outerHeight(), +- zIndex: this.getStartZIndex(true), +- opacity: 0 +- }).appendTo(document.body); +- } +- this.disabled = true; +- } +- }, +- docClick: function(e) { +- if (this.$touchScrollingSub) { +- this.$touchScrollingSub = null; +- return; +- } +- // hide on any click outside the menu or on a menu link +- if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { +- this.menuHideAll(); +- } +- }, +- docTouchEnd: function(e) { +- if (!this.lastTouch) { +- return; +- } +- if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) { +- if (this.hideTimeout) { +- clearTimeout(this.hideTimeout); +- this.hideTimeout = 0; +- } +- // hide with a delay to prevent triggering accidental unwanted click on some page element +- var self = this; +- this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, 350); +- } +- this.lastTouch = null; +- }, +- docTouchMove: function(e) { +- if (!this.lastTouch) { +- return; +- } +- var touchPoint = e.originalEvent.touches[0]; +- this.lastTouch.x2 = touchPoint.pageX; +- this.lastTouch.y2 = touchPoint.pageY; +- }, +- docTouchStart: function(e) { +- var touchPoint = e.originalEvent.touches[0]; +- this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; +- }, +- enable: function() { +- if (this.disabled) { +- if (this.$disableOverlay) { +- this.$disableOverlay.remove(); +- this.$disableOverlay = null; +- } +- this.disabled = false; +- } +- }, +- getClosestMenu: function(elm) { +- var $closestMenu = $(elm).closest('ul'); +- while ($closestMenu.dataSM('in-mega')) { +- $closestMenu = $closestMenu.parent().closest('ul'); +- } +- return $closestMenu[0] || null; +- }, +- getHeight: function($elm) { +- return this.getOffset($elm, true); +- }, +- // returns precise width/height float values +- getOffset: function($elm, height) { +- var old; +- if ($elm.css('display') == 'none') { +- old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; +- $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); +- } +- var box = $elm[0].getBoundingClientRect && $elm[0].getBoundingClientRect(), +- val = box && (height ? box.height || box.bottom - box.top : box.width || box.right - box.left); +- if (!val && val !== 0) { +- val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; +- } +- if (old) { +- $elm.hide().css(old); +- } +- return val; +- }, +- getStartZIndex: function(root) { +- var zIndex = parseInt(this[root ? '$root' : '$firstSub'].css('z-index')); +- if (!root && isNaN(zIndex)) { +- zIndex = parseInt(this.$root.css('z-index')); +- } +- return !isNaN(zIndex) ? zIndex : 1; +- }, +- getTouchPoint: function(e) { +- return e.touches && e.touches[0] || e.changedTouches && e.changedTouches[0] || e; +- }, +- getViewport: function(height) { +- var name = height ? 'Height' : 'Width', +- val = document.documentElement['client' + name], +- val2 = window['inner' + name]; +- if (val2) { +- val = Math.min(val, val2); +- } +- return val; +- }, +- getViewportHeight: function() { +- return this.getViewport(true); +- }, +- getViewportWidth: function() { +- return this.getViewport(); +- }, +- getWidth: function($elm) { +- return this.getOffset($elm); +- }, +- handleEvents: function() { +- return !this.disabled && this.isCSSOn(); +- }, +- handleItemEvents: function($a) { +- return this.handleEvents() && !this.isLinkInMegaMenu($a); +- }, +- isCollapsible: function() { +- return this.$firstSub.css('position') == 'static'; +- }, +- isCSSOn: function() { +- return this.$firstLink.css('display') == 'block'; +- }, +- isFixed: function() { +- var isFixed = this.$root.css('position') == 'fixed'; +- if (!isFixed) { +- this.$root.parentsUntil('body').each(function() { +- if ($(this).css('position') == 'fixed') { +- isFixed = true; +- return false; +- } +- }); +- } +- return isFixed; +- }, +- isLinkInMegaMenu: function($a) { +- return $(this.getClosestMenu($a[0])).hasClass('mega-menu'); +- }, +- isTouchMode: function() { +- return !mouse || this.opts.noMouseOver || this.isCollapsible(); +- }, +- itemActivate: function($a, focus) { +- var $ul = $a.closest('ul'), +- level = $ul.dataSM('level'); +- // if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first +- if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { +- var self = this; +- $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { +- self.itemActivate($(this).dataSM('parent-a')); +- }); +- } +- // hide any visible deeper level sub menus +- if (!this.isCollapsible() || focus) { +- this.menuHideSubMenus(!this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level); +- } +- // save new active item for this level +- this.activatedItems[level - 1] = $a; +- if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { +- return; +- } +- // show the sub menu if this item has one +- var $sub = $a.dataSM('sub'); +- if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { +- this.menuShow($sub); +- } +- }, +- itemBlur: function(e) { +- var $a = $(e.currentTarget); +- if (!this.handleItemEvents($a)) { +- return; +- } +- this.$root.triggerHandler('blur.smapi', $a[0]); +- }, +- itemClick: function(e) { +- var $a = $(e.currentTarget); +- if (!this.handleItemEvents($a)) { +- return; +- } +- if (this.$touchScrollingSub && this.$touchScrollingSub[0] == $a.closest('ul')[0]) { +- this.$touchScrollingSub = null; +- e.stopPropagation(); +- return false; +- } +- if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { +- return false; +- } +- var subArrowClicked = $(e.target).is('span.sub-arrow'), +- $sub = $a.dataSM('sub'), +- firstLevelSub = $sub ? $sub.dataSM('level') == 2 : false; +- // if the sub is not visible +- if ($sub && !$sub.is(':visible')) { +- if (this.opts.showOnClick && firstLevelSub) { +- this.clickActivated = true; +- } +- // try to activate the item and show the sub +- this.itemActivate($a); +- // if "itemActivate" showed the sub, prevent the click so that the link is not loaded +- // if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded +- if ($sub.is(':visible')) { +- this.focusActivated = true; +- return false; +- } +- } else if (this.isCollapsible() && subArrowClicked) { +- this.itemActivate($a); +- this.menuHide($sub); +- return false; +- } +- if (this.opts.showOnClick && firstLevelSub || $a.hasClass('disabled') || this.$root.triggerHandler('select.smapi', $a[0]) === false) { +- return false; +- } +- }, +- itemDown: function(e) { +- var $a = $(e.currentTarget); +- if (!this.handleItemEvents($a)) { +- return; +- } +- $a.dataSM('mousedown', true); +- }, +- itemEnter: function(e) { +- var $a = $(e.currentTarget); +- if (!this.handleItemEvents($a)) { +- return; +- } +- if (!this.isTouchMode()) { +- if (this.showTimeout) { +- clearTimeout(this.showTimeout); +- this.showTimeout = 0; +- } +- var self = this; +- this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.closest('ul').dataSM('level') == 1 ? 1 : this.opts.showTimeout); +- } +- this.$root.triggerHandler('mouseenter.smapi', $a[0]); +- }, +- itemFocus: function(e) { +- var $a = $(e.currentTarget); +- if (!this.handleItemEvents($a)) { +- return; +- } +- // fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus +- if (this.focusActivated && (!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { +- this.itemActivate($a, true); +- } +- this.$root.triggerHandler('focus.smapi', $a[0]); +- }, +- itemLeave: function(e) { +- var $a = $(e.currentTarget); +- if (!this.handleItemEvents($a)) { +- return; +- } +- if (!this.isTouchMode()) { +- $a[0].blur(); +- if (this.showTimeout) { +- clearTimeout(this.showTimeout); +- this.showTimeout = 0; +- } +- } +- $a.removeDataSM('mousedown'); +- this.$root.triggerHandler('mouseleave.smapi', $a[0]); +- }, +- menuHide: function($sub) { +- if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { +- return; +- } +- $sub.stop(true, true); +- if ($sub.css('display') != 'none') { +- var complete = function() { +- // unset z-index +- $sub.css('z-index', ''); +- }; +- // if sub is collapsible (mobile view) +- if (this.isCollapsible()) { +- if (this.opts.collapsibleHideFunction) { +- this.opts.collapsibleHideFunction.call(this, $sub, complete); +- } else { +- $sub.hide(this.opts.collapsibleHideDuration, complete); +- } +- } else { +- if (this.opts.hideFunction) { +- this.opts.hideFunction.call(this, $sub, complete); +- } else { +- $sub.hide(this.opts.hideDuration, complete); +- } +- } +- // remove IE iframe shim +- if ($sub.dataSM('ie-shim')) { +- $sub.dataSM('ie-shim').remove().css({ '-webkit-transform': '', transform: '' }); +- } +- // deactivate scrolling if it is activated for this sub +- if ($sub.dataSM('scroll')) { +- this.menuScrollStop($sub); +- $sub.css({ 'touch-action': '', '-ms-touch-action': '', '-webkit-transform': '', transform: '' }) +- .unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); +- } +- // unhighlight parent item + accessibility +- $sub.dataSM('parent-a').removeClass('highlighted').attr('aria-expanded', 'false'); +- $sub.attr({ +- 'aria-expanded': 'false', +- 'aria-hidden': 'true' +- }); +- var level = $sub.dataSM('level'); +- this.activatedItems.splice(level - 1, 1); +- this.visibleSubMenus.splice($.inArray($sub, this.visibleSubMenus), 1); +- this.$root.triggerHandler('hide.smapi', $sub[0]); +- } +- }, +- menuHideAll: function() { +- if (this.showTimeout) { +- clearTimeout(this.showTimeout); +- this.showTimeout = 0; +- } +- // hide all subs +- // if it's a popup, this.visibleSubMenus[0] is the root UL +- var level = this.opts.isPopup ? 1 : 0; +- for (var i = this.visibleSubMenus.length - 1; i >= level; i--) { +- this.menuHide(this.visibleSubMenus[i]); +- } +- // hide root if it's popup +- if (this.opts.isPopup) { +- this.$root.stop(true, true); +- if (this.$root.is(':visible')) { +- if (this.opts.hideFunction) { +- this.opts.hideFunction.call(this, this.$root); +- } else { +- this.$root.hide(this.opts.hideDuration); +- } +- // remove IE iframe shim +- if (this.$root.dataSM('ie-shim')) { +- this.$root.dataSM('ie-shim').remove(); +- } +- } +- } +- this.activatedItems = []; +- this.visibleSubMenus = []; +- this.clickActivated = false; +- this.focusActivated = false; +- // reset z-index increment +- this.zIndexInc = 0; +- this.$root.triggerHandler('hideAll.smapi'); +- }, +- menuHideSubMenus: function(level) { +- for (var i = this.activatedItems.length - 1; i >= level; i--) { +- var $sub = this.activatedItems[i].dataSM('sub'); +- if ($sub) { +- this.menuHide($sub); +- } +- } +- }, +- menuIframeShim: function($ul) { +- // create iframe shim for the menu +- if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { +- $ul.dataSM('ie-shim', $('