Merge lp:~hrvojem/tcprstat/sphinx_doc into lp:tcprstat

Proposed by Hrvoje Matijakovic
Status: Needs review
Proposed branch: lp:~hrvojem/tcprstat/sphinx_doc
Merge into: lp:tcprstat
Diff against target: 17878 lines
To merge this branch: bzr merge lp:~hrvojem/tcprstat/sphinx_doc
Reviewer Review Type Date Requested Status
Ignacio Nin Pending
Review via email: mp+96529@code.launchpad.net
To post a comment you must log in.

Unmerged revisions

74. By Hrvoje Matijakovic

ported documentation from wiki to sphinx doc

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'doc'
=== added file 'doc/Makefile'
--- doc/Makefile 1970-01-01 00:00:00 +0000
+++ doc/Makefile 2012-03-08 09:19:21 +0000
@@ -0,0 +1,130 @@
1# Makefile for Sphinx documentation
2#
3
4# You can set these variables from the command line.
5SPHINXOPTS =
6SPHINXBUILD = sphinx-build
7PAPER =
8BUILDDIR = build
9
10# Internal variables.
11PAPEROPT_a4 = -D latex_paper_size=a4
12PAPEROPT_letter = -D latex_paper_size=letter
13ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
14
15.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
16
17help:
18 @echo "Please use \`make <target>' where <target> is one of"
19 @echo " html to make standalone HTML files"
20 @echo " dirhtml to make HTML files named index.html in directories"
21 @echo " singlehtml to make a single large HTML file"
22 @echo " pickle to make pickle files"
23 @echo " json to make JSON files"
24 @echo " htmlhelp to make HTML files and a HTML help project"
25 @echo " qthelp to make HTML files and a qthelp project"
26 @echo " devhelp to make HTML files and a Devhelp project"
27 @echo " epub to make an epub"
28 @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
29 @echo " latexpdf to make LaTeX files and run them through pdflatex"
30 @echo " text to make text files"
31 @echo " man to make manual pages"
32 @echo " changes to make an overview of all changed/added/deprecated items"
33 @echo " linkcheck to check all external links for integrity"
34 @echo " doctest to run all doctests embedded in the documentation (if enabled)"
35
36clean:
37 -rm -rf $(BUILDDIR)/*
38
39html:
40 $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
41 @echo
42 @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
43
44dirhtml:
45 $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
46 @echo
47 @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
48
49singlehtml:
50 $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
51 @echo
52 @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
53
54pickle:
55 $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
56 @echo
57 @echo "Build finished; now you can process the pickle files."
58
59json:
60 $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
61 @echo
62 @echo "Build finished; now you can process the JSON files."
63
64htmlhelp:
65 $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
66 @echo
67 @echo "Build finished; now you can run HTML Help Workshop with the" \
68 ".hhp project file in $(BUILDDIR)/htmlhelp."
69
70qthelp:
71 $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
72 @echo
73 @echo "Build finished; now you can run "qcollectiongenerator" with the" \
74 ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
75 @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PerconaXtraBackup.qhcp"
76 @echo "To view the help file:"
77 @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PerconaXtraBackup.qhc"
78
79devhelp:
80 $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
81 @echo
82 @echo "Build finished."
83 @echo "To view the help file:"
84 @echo "# mkdir -p $$HOME/.local/share/devhelp/PerconaXtraBackup"
85 @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PerconaXtraBackup"
86 @echo "# devhelp"
87
88epub:
89 $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
90 @echo
91 @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
92
93latex:
94 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
95 @echo
96 @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
97 @echo "Run \`make' in that directory to run these through (pdf)latex" \
98 "(use \`make latexpdf' here to do that automatically)."
99
100latexpdf:
101 $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
102 @echo "Running LaTeX files through pdflatex..."
103 make -C $(BUILDDIR)/latex all-pdf
104 @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
105
106text:
107 $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
108 @echo
109 @echo "Build finished. The text files are in $(BUILDDIR)/text."
110
111man:
112 $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
113 @echo
114 @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
115
116changes:
117 $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
118 @echo
119 @echo "The overview file is in $(BUILDDIR)/changes."
120
121linkcheck:
122 $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
123 @echo
124 @echo "Link check complete; look for any errors in the above output " \
125 "or in $(BUILDDIR)/linkcheck/output.txt."
126
127doctest:
128 $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
129 @echo "Testing of doctests in the sources finished, look at the " \
130 "results in $(BUILDDIR)/doctest/output.txt."
0131
=== added directory 'doc/build'
=== added directory 'doc/build/doctrees'
=== added file 'doc/build/doctrees/environment.pickle'
1Binary files doc/build/doctrees/environment.pickle 1970-01-01 00:00:00 +0000 and doc/build/doctrees/environment.pickle 2012-03-08 09:19:21 +0000 differ132Binary files doc/build/doctrees/environment.pickle 1970-01-01 00:00:00 +0000 and doc/build/doctrees/environment.pickle 2012-03-08 09:19:21 +0000 differ
=== added file 'doc/build/doctrees/index.doctree'
2Binary files doc/build/doctrees/index.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/index.doctree 2012-03-08 09:19:21 +0000 differ133Binary files doc/build/doctrees/index.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/index.doctree 2012-03-08 09:19:21 +0000 differ
=== added file 'doc/build/doctrees/installation.doctree'
3Binary files doc/build/doctrees/installation.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/installation.doctree 2012-03-08 09:19:21 +0000 differ134Binary files doc/build/doctrees/installation.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/installation.doctree 2012-03-08 09:19:21 +0000 differ
=== added file 'doc/build/doctrees/intro.doctree'
4Binary files doc/build/doctrees/intro.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/intro.doctree 2012-03-08 09:19:21 +0000 differ135Binary files doc/build/doctrees/intro.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/intro.doctree 2012-03-08 09:19:21 +0000 differ
=== added file 'doc/build/doctrees/manual.doctree'
5Binary files doc/build/doctrees/manual.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/manual.doctree 2012-03-08 09:19:21 +0000 differ136Binary files doc/build/doctrees/manual.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/manual.doctree 2012-03-08 09:19:21 +0000 differ
=== added file 'doc/build/doctrees/support.doctree'
6Binary files doc/build/doctrees/support.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/support.doctree 2012-03-08 09:19:21 +0000 differ137Binary files doc/build/doctrees/support.doctree 1970-01-01 00:00:00 +0000 and doc/build/doctrees/support.doctree 2012-03-08 09:19:21 +0000 differ
=== added directory 'doc/build/html'
=== added file 'doc/build/html/.buildinfo'
--- doc/build/html/.buildinfo 1970-01-01 00:00:00 +0000
+++ doc/build/html/.buildinfo 2012-03-08 09:19:21 +0000
@@ -0,0 +1,4 @@
1# Sphinx build info version 1
2# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
3config: 157b3cb084d64187df07ef5c09529c53
4tags: fbb0d17656682115ca4d033fb2f83ba1
05
=== added directory 'doc/build/html/_sources'
=== added file 'doc/build/html/_sources/index.txt'
--- doc/build/html/_sources/index.txt 1970-01-01 00:00:00 +0000
+++ doc/build/html/_sources/index.txt 2012-03-08 09:19:21 +0000
@@ -0,0 +1,47 @@
1============================================================
2 Tcprstat - Documentation
3============================================================
4
5Introduction
6============
7
8.. toctree::
9 :maxdepth: 1
10 :glob:
11
12 intro
13
14Installation
15============
16
17.. toctree::
18 :maxdepth: 2
19 :glob:
20
21 installation
22
23User's Manual
24=============
25
26.. toctree::
27 :maxdepth: 2
28 :glob:
29
30 manual
31
32Miscellaneous
33=============
34
35.. toctree::
36 :maxdepth: 1
37 :glob:
38
39 support
40
41Indices and tables
42==================
43
44* :ref:`genindex`
45
46* :ref:`search`
47
048
=== added file 'doc/build/html/_sources/installation.txt'
--- doc/build/html/_sources/installation.txt 1970-01-01 00:00:00 +0000
+++ doc/build/html/_sources/installation.txt 2012-03-08 09:19:21 +0000
@@ -0,0 +1,12 @@
1=====================
2 Installing tcprstat
3=====================
4
5For portability and ease of use, we build a single statically linked binary, which can be downloaded and used as-is on 64-bit platforms. At present there is no installation mechanism, so to use tcprstat, you simply need to:
6
7 * Download the `statically linked 64-bit binary (version 0.3.1) <http://github.com/downloads/Lowercases/tcprstat/tcprstat-static.v0.3.1.x86_64>`_
8 * Move it into a directory in your PATH, such as /usr/bin
9 * Rename it to tcprstat
10 * Make it executable with chmod +x
11
12There are currently no operating-system-specific packages for tcprstat, although in the future we plan to include it in our APT and YUM repositories. If you need to run tcprstat on 32-bit systems, you will need to build it from source.
013
=== added file 'doc/build/html/_sources/intro.txt'
--- doc/build/html/_sources/intro.txt 1970-01-01 00:00:00 +0000
+++ doc/build/html/_sources/intro.txt 2012-03-08 09:19:21 +0000
@@ -0,0 +1,27 @@
1==============
2About tcprstat
3==============
4
5.. toctree::
6 :hidden:
7
8tcprstat is a free, open-source TCP analysis tool that watches network traffic and computes the delay between requests and responses. From this it derives response-time statistics and prints them out. The output is similar to other Unix -stat tools such as vmstat, iostat, and mpstat. The tool can optionally watch traffic to only a specified port, which makes it practical for timing requests and responses to a single daemon process such as mysqld, httpd, memcached, or any of a variety of other server processes.
9
10The advantages of tcprstat are as follows:
11
12 * It is lightweight and unobtrusive. No bulky log files need be written and analyzed.
13 * Requests and responses are timed with microsecond resolution.
14 * The output is easy to import into spreadsheets, manipulate with command-line scripts, graph with gnuplot, and so on.
15 * It is protocol-agnostic, and works well for a large variety of client-server protocols that have a simple request-response model.
16
17tcprstat is related to the `tcpstat <http://www.frenchfries.net/paul/tcpstat/>`_ tool, but it focuses on response time measurements, not on the amount and size of the network traffic. This makes it useful for response time analysis, which is needed for techniques such as `Goal-Driven Performance Optimization <http://www.percona.com/about-us/white-papers>`_.
18
19tcprstat development is hosted on `Launchpad <https://launchpad.net/tcprstat>`_. We are currently moving downloads and bug tracking from GitHub to Launchpad, so some links in this document may refer to GitHub until that process is complete.
20
21Development Status
22==================
23tcprstat is currently in Beta, although we consider it ready for production testing. Several C++ experts have reviewed the code, and it has been observed in high-stress production environments for many weeks with no apparent problems. Please test and review the code, and report any issues or suggestions you have. Please also review our `roadmap <https://launchpad.net/tcprstat/+milestones>`_ and contribute your suggestions.
24
25Authors
26=======
27tcprstat was written by `Ignacio Nin <http://www.percona.com/about-us/our-team/ignacio-nin/>`_, based on ideas from `Baron Schwartz <http://www.percona.com/about-us/our-team/baron-schwartz/>`_ and other Percona consultants. The code was reviewed by Oleg Tsarev, Sasha Pachev, and other members of the Percona development team.
028
=== added file 'doc/build/html/_sources/manual.txt'
--- doc/build/html/_sources/manual.txt 1970-01-01 00:00:00 +0000
+++ doc/build/html/_sources/manual.txt 2012-03-08 09:19:21 +0000
@@ -0,0 +1,126 @@
1.. _user-manual:
2
3======================
4tcprstat User's Manual
5======================
6
7.. toctree::
8 :maxdepth: 1
9 :hidden:
10
11Running tcprstat
12================
13
14tcprstat requires root permissions to execute. If you are not root, you should either become root with su, or execute tcprstat with sudo. The following examples assume you are root, and do not show the use of sudo.
15
16Default Usage
17-------------
18The simplest functionality is to accept all defaults and simply execute the tool. By default, it will measure the TCP traffic for 10 seconds and print out a header, followed by a single line of statistics. ::
19
20 # timestamp count max min avg med stddev 95_max 95_avg 95_std 99_max 99_avg 99_std
21 1283265068 23892 425546 30 505 161 6240 835 186 102 4179 261 429
22
23
24Basic, Useful Functionality
25---------------------------
26
27In practice, you will usually select a specific port to measure, set the tool to iterate infinitely, and possibly change the default 10-second interval. To accomplish this, use the following options:
28
29 * -p <port> selects a port
30 * -i <secs> sets the measurement interval, in seconds
31 * -n <iter> specifies the number of iterations to run; 0 means to run forever
32
33For example, to watch Sphinx traffic in one-second intervals forever, execute: ::
34
35 # tcprstat -p 3312 -i 1 -n 0.
36
37Customizing The Output
38----------------------
39
40tcprstat's output can be changed to include or omit various types of statistics on the traffic it measures. The default output includes columns that are useful for many purposes. The output is specified with %C format codes, where C is a single character. The following table documents the available format codes and their meaning.
41
42=========== ============= ======== ==========================================================
43Format Code Header Default? Meaning
44=========== ============= ======== ==========================================================
45%n count y Count of requests that completed during this iteration
46%a avg y Average response time
47%s sum y Sum of response times
48%x sqs n Sum of squares of response times
49%m min y Minimum response time
50%M max y Maximum response time
51%h med y Median response time
52%S stddev y Standard deviation of response times
53%v var n Variance of response times
54%I iter# n Iteration number
55%t elapsed n Seconds elapsed since the first iteration
56%T timestamp y Unix timestamp
57%% A literal %
58\t A tab character
59\n A newline character
6095,99 Adds a prefix y A percentile indicator; see later in this section for more
61=========== ============= ======== ==========================================================
62
63You can change the tcprstat output format by customizing the -f option. For example, to print out the number of requests per second to a MySQL server on port 3306, execute the following: ::
64
65 # tcprstat -f '%n\n' -p 3306 -t 1 -n 0
66 count
67 2212
68 2070
69 ...
70
71You can also include a percentile indicator, to compute the statistics over the Nth percentile of the response times. The tool currently supports only the 95th and 99th percentiles. To print out statistics for a given percentile, include the percentile number between the % character and the format code. The default column header will then include the percentile value. The following example prints the maximum, 95th percentile maximum, and 99th percentile maximum response times in microseconds: ::
72
73 # tcprstat -f '%M\t%95M\t%99M\n' -p 3306 -t 1 -n 0
74 max 95_max 99_max
75 31221 411 3001
76 52721 495 2828
77 12173 507 1513
78 ...
79
80Analyzing a pcap File
81---------------------
82
83tcprstat has the ability not only to analyze traffic live as it is captured, but also to analyze traffic from a file created by tcpdump. This makes it possible to gather traffic on one machine and analyze it elsewhere at a different time. To save traffic for later analysis, execute tcpdump with the -w option and specify the file in which to store the resulting traffic. Use the -r option to tcprstat to read traffic from that file and analyze it.
84
85tcprstat normally decides what traffic is incoming (a request) and what traffic is outbound (a response) by finding a list of IP addresses bound to the local network interfaces. However, this will not work correctly when traffic is analyzed from a file that was gathered on a different host. You can use the -l option to specify a list of local IP addresses in this case.
86
87Command-Line Options
88====================
89
90The following is a complete list of tcprstat's command-line options. You can always find a full list of the available command-line options and brief usage information by giving the --help option.
91
92.. option:: --format -f
93
94 A format string. Detailed description of supported values can bee seen in the table above.
95
96.. option:: --[no]header
97
98 If no argument is given, tcprstat auto-generates the header based on --format. If an argument is given, tcprstat uses that as the header instead. If --no-header is used, tcprstat will not print a header.
99
100.. option:: --help
101
102 Shows program information and usage.
103
104.. option:: --interval -t
105
106 The number of seconds tcprstat waits between each successive line of output. Default value is 10.
107
108.. option:: --iterations -n
109
110 How many iterations tcprstat should execute before exiting; 0 means infinity. Default value is 1.
111
112.. option:: --local -l
113
114 Accepts a comma-separated list of IP addresses to consider as local IP addresses, instead of getting a list from the operating system.
115
116.. option:: --port -p
117
118 Capture traffic only for the specified TCP port; if none, capture all traffic.
119
120.. option:: --read -r
121
122 Read the specified pcap file instead of capturing traffic from the network.
123
124.. option:: --version
125
126 Shows tcprstat version.
0127
=== added file 'doc/build/html/_sources/support.txt'
--- doc/build/html/_sources/support.txt 1970-01-01 00:00:00 +0000
+++ doc/build/html/_sources/support.txt 2012-03-08 09:19:21 +0000
@@ -0,0 +1,7 @@
1================
2Help and Support
3================
4
5Please use `Launchpad's issue tracking system <https://bugs.launchpad.net/tcprstat>`_ to report issues and request features. For general discussion, please use the `Percona-Discussion Google Group <http://groups.google.com/group/percona-discussion>`_. You can use the #percona IRC channel on FreeNode to chat with community members.
6
7For commercial support, maintenance packages, or to sponsor features, please contact `Percona Sales <http://www.percona.com/contact/sales>`_.
08
=== added directory 'doc/build/html/_static'
=== added file 'doc/build/html/_static/basic.css'
--- doc/build/html/_static/basic.css 1970-01-01 00:00:00 +0000
+++ doc/build/html/_static/basic.css 2012-03-08 09:19:21 +0000
@@ -0,0 +1,528 @@
1/*
2 * basic.css
3 * ~~~~~~~~~
4 *
5 * Sphinx stylesheet -- basic theme.
6 *
7 * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
8 * :license: BSD, see LICENSE for details.
9 *
10 */
11
12/* -- main layout ----------------------------------------------------------- */
13
14div.clearer {
15 clear: both;
16}
17
18/* -- relbar ---------------------------------------------------------------- */
19
20div.related {
21 width: 100%;
22 font-size: 90%;
23}
24
25div.related h3 {
26 display: none;
27}
28
29div.related ul {
30 margin: 0;
31 padding: 0 0 0 10px;
32 list-style: none;
33}
34
35div.related li {
36 display: inline;
37}
38
39div.related li.right {
40 float: right;
41 margin-right: 5px;
42}
43
44/* -- sidebar --------------------------------------------------------------- */
45
46div.sphinxsidebarwrapper {
47 padding: 10px 5px 0 10px;
48}
49
50div.sphinxsidebar {
51 float: left;
52 width: 230px;
53 margin-left: -100%;
54 font-size: 90%;
55}
56
57div.sphinxsidebar ul {
58 list-style: none;
59}
60
61div.sphinxsidebar ul ul,
62div.sphinxsidebar ul.want-points {
63 margin-left: 20px;
64 list-style: square;
65}
66
67div.sphinxsidebar ul ul {
68 margin-top: 0;
69 margin-bottom: 0;
70}
71
72div.sphinxsidebar form {
73 margin-top: 10px;
74}
75
76div.sphinxsidebar input {
77 border: 1px solid #98dbcc;
78 font-family: sans-serif;
79 font-size: 1em;
80}
81
82img {
83 border: 0;
84}
85
86/* -- search page ----------------------------------------------------------- */
87
88ul.search {
89 margin: 10px 0 0 20px;
90 padding: 0;
91}
92
93ul.search li {
94 padding: 5px 0 5px 20px;
95 background-image: url(file.png);
96 background-repeat: no-repeat;
97 background-position: 0 7px;
98}
99
100ul.search li a {
101 font-weight: bold;
102}
103
104ul.search li div.context {
105 color: #888;
106 margin: 2px 0 0 30px;
107 text-align: left;
108}
109
110ul.keywordmatches li.goodmatch a {
111 font-weight: bold;
112}
113
114/* -- index page ------------------------------------------------------------ */
115
116table.contentstable {
117 width: 90%;
118}
119
120table.contentstable p.biglink {
121 line-height: 150%;
122}
123
124a.biglink {
125 font-size: 1.3em;
126}
127
128span.linkdescr {
129 font-style: italic;
130 padding-top: 5px;
131 font-size: 90%;
132}
133
134/* -- general index --------------------------------------------------------- */
135
136table.indextable {
137 width: 100%;
138}
139
140table.indextable td {
141 text-align: left;
142 vertical-align: top;
143}
144
145table.indextable dl, table.indextable dd {
146 margin-top: 0;
147 margin-bottom: 0;
148}
149
150table.indextable tr.pcap {
151 height: 10px;
152}
153
154table.indextable tr.cap {
155 margin-top: 10px;
156 background-color: #f2f2f2;
157}
158
159img.toggler {
160 margin-right: 3px;
161 margin-top: 3px;
162 cursor: pointer;
163}
164
165div.modindex-jumpbox {
166 border-top: 1px solid #ddd;
167 border-bottom: 1px solid #ddd;
168 margin: 1em 0 1em 0;
169 padding: 0.4em;
170}
171
172div.genindex-jumpbox {
173 border-top: 1px solid #ddd;
174 border-bottom: 1px solid #ddd;
175 margin: 1em 0 1em 0;
176 padding: 0.4em;
177}
178
179/* -- general body styles --------------------------------------------------- */
180
181a.headerlink {
182 visibility: hidden;
183}
184
185h1:hover > a.headerlink,
186h2:hover > a.headerlink,
187h3:hover > a.headerlink,
188h4:hover > a.headerlink,
189h5:hover > a.headerlink,
190h6:hover > a.headerlink,
191dt:hover > a.headerlink {
192 visibility: visible;
193}
194
195div.body p.caption {
196 text-align: inherit;
197}
198
199div.body td {
200 text-align: left;
201}
202
203.field-list ul {
204 padding-left: 1em;
205}
206
207.first {
208 margin-top: 0 !important;
209}
210
211p.rubric {
212 margin-top: 30px;
213 font-weight: bold;
214}
215
216img.align-left, .figure.align-left, object.align-left {
217 clear: left;
218 float: left;
219 margin-right: 1em;
220}
221
222img.align-right, .figure.align-right, object.align-right {
223 clear: right;
224 float: right;
225 margin-left: 1em;
226}
227
228img.align-center, .figure.align-center, object.align-center {
229 display: block;
230 margin-left: auto;
231 margin-right: auto;
232}
233
234.align-left {
235 text-align: left;
236}
237
238.align-center {
239 clear: both;
240 text-align: center;
241}
242
243.align-right {
244 text-align: right;
245}
246
247/* -- sidebars -------------------------------------------------------------- */
248
249div.sidebar {
250 margin: 0 0 0.5em 1em;
251 border: 1px solid #ddb;
252 padding: 7px 7px 0 7px;
253 background-color: #ffe;
254 width: 40%;
255 float: right;
256}
257
258p.sidebar-title {
259 font-weight: bold;
260}
261
262/* -- topics ---------------------------------------------------------------- */
263
264div.topic {
265 border: 1px solid #ccc;
266 padding: 7px 7px 0 7px;
267 margin: 10px 0 10px 0;
268}
269
270p.topic-title {
271 font-size: 1.1em;
272 font-weight: bold;
273 margin-top: 10px;
274}
275
276/* -- admonitions ----------------------------------------------------------- */
277
278div.admonition {
279 margin-top: 10px;
280 margin-bottom: 10px;
281 padding: 7px;
282}
283
284div.admonition dt {
285 font-weight: bold;
286}
287
288div.admonition dl {
289 margin-bottom: 0;
290}
291
292p.admonition-title {
293 margin: 0px 10px 5px 0px;
294 font-weight: bold;
295}
296
297div.body p.centered {
298 text-align: center;
299 margin-top: 25px;
300}
301
302/* -- tables ---------------------------------------------------------------- */
303
304table.docutils {
305 border: 0;
306 border-collapse: collapse;
307}
308
309table.docutils td, table.docutils th {
310 padding: 1px 8px 1px 5px;
311 border-top: 0;
312 border-left: 0;
313 border-right: 0;
314 border-bottom: 1px solid #aaa;
315}
316
317table.field-list td, table.field-list th {
318 border: 0 !important;
319}
320
321table.footnote td, table.footnote th {
322 border: 0 !important;
323}
324
325th {
326 text-align: left;
327 padding-right: 5px;
328}
329
330table.citation {
331 border-left: solid 1px gray;
332 margin-left: 1px;
333}
334
335table.citation td {
336 border-bottom: none;
337}
338
339/* -- other body styles ----------------------------------------------------- */
340
341ol.arabic {
342 list-style: decimal;
343}
344
345ol.loweralpha {
346 list-style: lower-alpha;
347}
348
349ol.upperalpha {
350 list-style: upper-alpha;
351}
352
353ol.lowerroman {
354 list-style: lower-roman;
355}
356
357ol.upperroman {
358 list-style: upper-roman;
359}
360
361dl {
362 margin-bottom: 15px;
363}
364
365dd p {
366 margin-top: 0px;
367}
368
369dd ul, dd table {
370 margin-bottom: 10px;
371}
372
373dd {
374 margin-top: 3px;
375 margin-bottom: 10px;
376 margin-left: 30px;
377}
378
379dt:target, .highlighted {
380 background-color: #fbe54e;
381}
382
383dl.glossary dt {
384 font-weight: bold;
385 font-size: 1.1em;
386}
387
388.field-list ul {
389 margin: 0;
390 padding-left: 1em;
391}
392
393.field-list p {
394 margin: 0;
395}
396
397.refcount {
398 color: #060;
399}
400
401.optional {
402 font-size: 1.3em;
403}
404
405.versionmodified {
406 font-style: italic;
407}
408
409.system-message {
410 background-color: #fda;
411 padding: 5px;
412 border: 3px solid red;
413}
414
415.footnote:target {
416 background-color: #ffa;
417}
418
419.line-block {
420 display: block;
421 margin-top: 1em;
422 margin-bottom: 1em;
423}
424
425.line-block .line-block {
426 margin-top: 0;
427 margin-bottom: 0;
428 margin-left: 1.5em;
429}
430
431.guilabel, .menuselection {
432 font-family: sans-serif;
433}
434
435.accelerator {
436 text-decoration: underline;
437}
438
439.classifier {
440 font-style: oblique;
441}
442
443/* -- code displays --------------------------------------------------------- */
444
445pre {
446 overflow: auto;
447 overflow-y: hidden; /* fixes display issues on Chrome browsers */
448}
449
450td.linenos pre {
451 padding: 5px 0px;
452 border: 0;
453 background-color: transparent;
454 color: #aaa;
455}
456
457table.highlighttable {
458 margin-left: 0.5em;
459}
460
461table.highlighttable td {
462 padding: 0 0.5em 0 0.5em;
463}
464
465tt.descname {
466 background-color: transparent;
467 font-weight: bold;
468 font-size: 1.2em;
469}
470
471tt.descclassname {
472 background-color: transparent;
473}
474
475tt.xref, a tt {
476 background-color: transparent;
477 font-weight: bold;
478}
479
480h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
481 background-color: transparent;
482}
483
484.viewcode-link {
485 float: right;
486}
487
488.viewcode-back {
489 float: right;
490 font-family: sans-serif;
491}
492
493div.viewcode-block:target {
494 margin: -1px -10px;
495 padding: 0 10px;
496}
497
498/* -- math display ---------------------------------------------------------- */
499
500img.math {
501 vertical-align: middle;
502}
503
504div.body div.math p {
505 text-align: center;
506}
507
508span.eqno {
509 float: right;
510}
511
512/* -- printout stylesheet --------------------------------------------------- */
513
514@media print {
515 div.document,
516 div.documentwrapper,
517 div.bodywrapper {
518 margin: 0 !important;
519 width: 100%;
520 }
521
522 div.sphinxsidebar,
523 div.related,
524 div.footer,
525 #top-link {
526 display: none;
527 }
528}
0529
=== added file 'doc/build/html/_static/default.css'
--- doc/build/html/_static/default.css 1970-01-01 00:00:00 +0000
+++ doc/build/html/_static/default.css 2012-03-08 09:19:21 +0000
@@ -0,0 +1,414 @@
1/*
2 * default.css_t
3 * ~~~~~~~~~~~~~
4 *
5 * Sphinx stylesheet -- default theme.
6 *
7 * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
8 * :license: BSD, see LICENSE for details.
9 *
10 */
11
12@import url("basic.css");
13
14/* -- page layout ----------------------------------------------------------- */
15
16body {
17 font-family: Arial,Helvetica,sans-serif;
18 font-size: 14px;
19 background-color: #fff;
20 color: #333333;
21 line-height: 20px;
22 margin: 0;
23 padding: 0;
24
25}
26
27div.document {
28 background-color: #fff;
29 margin: 0 auto;
30 overflow: hidden;
31 padding: 30px 0;
32 width: 960px;
33}
34
35div.documentwrapper {
36 /* float: left; */
37 /* width: 100%; */
38
39}
40
41div.bodywrapper {
42 margin: 10 0 0 0px;
43 width: 660px;
44 float:right;
45}
46
47div.body {
48 background-color: #fff;
49 color: #333333;
50 padding: 0 0 20px;
51}
52
53div.footer {
54 /* color: #ffffff; */
55 /* width: 100%; */
56 /* padding: 9px 0 9px 0; */
57 /* text-align: center; */
58 /* font-size: 75%; */
59 font: 80% "Lucida Grande",Verdana,Lucida,Helvetica,Arial,sans-serif;
60 background: none repeat scroll 0 0 #333333;
61 border-top: 2px solid #D95200;
62 overflow: hidden;
63}
64
65div.footer a {
66 color: #ffffff;
67 text-decoration: underline;
68}
69
70div.related {
71 background-color: #ccc;
72 line-height: 30px;
73 color: #333;
74 background: none repeat scroll 0 0 #F8F8F8;
75 border: 1px solid #E0E0E0;
76 clear: both;
77 padding: 10px;
78 width: 635px;
79 margin-bottom: 5px;
80}
81
82div.related a {
83 color: #999;
84}
85
86div.sphinxsidebar {
87 margin-left: 0px;
88 margin-right: 30px;
89 color: #eee;
90 font-family: Arial,Helvetica,sans-serif;
91 width: 260px;
92}
93
94div.sphinxsidebar h3 {
95 /* font-family: 'Arial', 'Helvetica' sans-serif; */
96 color: #999;
97 font-size: 18px;
98 line-height: 15px;
99 font-weight: 400;
100 margin-left: 5px;
101 padding: 0;
102}
103
104div.sphinxsidebar h3 a {
105 color: #333;
106}
107
108div.sphinxsidebar a:hover {
109 /* color: #333; */
110}
111
112div.sphinxsidebar h4 {
113 /* font-family: 'Arial', 'Helvetica' sans-serif; */
114 color: #666;
115 font-size: 18px;
116 font-weight: normal;
117 margin: 5px 0 0 5px;
118 padding: 0;
119}
120
121div.sphinxsidebar p {
122 color: #333;
123 margin-bottom: 5px;
124 margin-left: 5px;
125}
126
127div.sphinxsidebar p.topless {
128 margin: 5px 10px 10px 10px;
129}
130
131div.sphinxsidebar ul {
132 margin: 10px;
133 padding-left: 5px;
134 color: #333;
135}
136
137div.sphinxsidebar a {
138 color: #D12907;
139}
140
141div.sphinxsidebar input {
142 border: 1px solid #999;
143 font-family: sans-serif;
144 font-size: 1em;
145}
146
147
148
149/* -- hyperlink styles ------------------------------------------------------ */
150
151a {
152 color: #D12907;
153 text-decoration: underline;
154 border: medium none;
155 cursor: pointer;
156}
157
158a:visited {
159 color: #D12907;
160 text-decoration: underline;
161}
162
163a:hover {
164 color: #D12907;
165 text-decoration: underline;
166}
167
168
169
170/* -- body styles ----------------------------------------------------------- */
171
172div.body h1,
173div.body h2,
174div.body h3,
175div.body h4,
176div.body h5,
177div.body h6 {
178 font-family: Arial,Helvetica,sans-serif;
179 background-color: #fff;
180 font-weight: 400;
181
182 /* border-bottom: 1px solid #ccc; */
183 /* margin: 20px -20px 10px -20px; */
184 /* padding: 0; */
185 /* padding: 3px 0 3px 10px; */
186 text-decoration: none !important;
187
188 border-bottom: 1px solid #E0E0E0;
189 font-size: 20px;
190 line-height: 20px;
191 margin: 30px 0 15px;
192 padding: 0 0 3px;
193 color: #000;
194}
195
196div.body h1 {
197 font-size: 32px;
198 color: #D12907;
199 line-height: 40px;
200 margin: 10px 0 20px 0;
201 text-decoration: none !important;
202 border-bottom: none;
203 margin-top: 35px;
204}
205
206div.body h2 { font-size: 150%; }
207div.body h3 { font-size: 140%; }
208div.body h4 { font-size: 120%; }
209div.body h5 { font-size: 110%; }
210div.body h6 { font-size: 100%; }
211
212a.headerlink {
213 color: #c60f0f;
214 font-size: 0.8em;
215 padding: 0 4px 0 4px;
216 text-decoration: none;
217}
218
219a.headerlink:hover {
220 background-color: #c60f0f;
221 color: white;
222}
223
224div.body dd, div.body li {
225 text-align: justify;
226}
227
228div.body dt {
229 list-style-type: square;
230 /* margin: 8px 0 8px 30px; */
231 padding: 0 4px 0 5px;
232
233}
234
235div.body p {
236 text-align: justify;
237/* line-height: 130%;*/
238 margin: 10px 0;
239}
240
241/* div.body ul, */
242div.body li {
243 list-style-type: square;
244 margin: 8px 0 8px 30px;
245 padding: 0 4px 0 5px;
246}
247
248.reference em {
249 font-style: normal;
250}
251
252.std-term {
253 font-style: normal;
254 font-weight: 400;
255 color: #FF7400
256}
257
258div.admonition p.admonition-title + p {
259 display: inline;
260}
261
262div.admonition p {
263 margin-bottom: 5px;
264}
265
266div.admonition pre {
267 margin-bottom: 5px;
268}
269
270div.admonition ul, div.admonition ol {
271 margin-bottom: 5px;
272}
273
274div.note {
275 background-color: #eee;
276 border: 1px solid #ccc;
277}
278
279div.seealso {
280 background-color: #ffc;
281 border: 1px solid #ff6;
282}
283
284div.topic {
285 background-color: #eee;
286}
287
288div.warning {
289 background-color: #ffe4e4;
290 border: 1px solid #f66;
291}
292
293p.admonition-title {
294 display: inline;
295}
296
297p.admonition-title:after {
298 content: ":";
299}
300
301pre {
302 padding: 10px;
303 background-color: #F0E6D9/* #eeffcc */;
304 color: #333333;
305 line-height: 120%;
306 border: 1px dashed #ED9821;
307 font-size: 80%;
308 overflow: auto;
309 /* border-left: none; */
310 /* border-right: none; */
311}
312
313tt {
314/* background-color: #ecf0f3;
315 padding: 0 1px 0 1px;
316 font-size: 0.95em;*/
317 font-weight: 400;
318}
319
320div.body td {
321 text-align: none;
322}
323
324table.docutils th {
325 background-color: #DEE7EC;
326 border: 1px solid #8CACBB;
327 padding: 3px;
328 text-align: center;
329 font-style: normal;
330 font-weight: 400;
331}
332
333table.docutils td {
334 border: 1px solid #8CACBB;
335 padding: 3px;
336 line-height: 16px;
337 vertical-align: middle;
338}
339
340.warning tt {
341 background: #efc2c2;
342}
343
344.note tt {
345 background: #d6d6d6;
346}
347
348.viewcode-back {
349 font-family: sans-serif;
350}
351
352div.viewcode-block:target {
353 background-color: #f4debf;
354 border-top: 1px solid #ac9;
355 border-bottom: 1px solid #ac9;
356}
357
358.file-bugs {
359 background: none repeat scroll 0 0 #E8E8E8;
360 border: 1px solid #E0E0E0;
361 clear: both;
362 color: #333333;
363 padding: 10px;
364 text-align: center;
365 font-size: 90%;
366}
367
368div.footer .footer {
369 margin: 0 auto;
370 overflow: hidden;
371 padding: 10px 0;
372 width: 960px;
373 border-top: none;
374}
375
376div.footer .footer .logo {
377 float: left;
378 overflow: hidden;
379 padding: 17px 0 0;
380}
381
382div.footer .footer .text {
383 color: #E0E0E0;
384 float: right;
385 font-family: Arial,Helvetica,sans-serif;
386 font-size: 11px;
387 line-height: 15px;
388 overflow: hidden;
389 text-align: right;
390}
391
392div.license {
393 font-size: 80%;
394 /* padding: 0.5em; */
395 text-align: center;
396 margin: 13px 0 -15px;
397}
398
399#sidenavi.noborder {
400 border-right: medium none;
401 border-top: medium none;
402 margin: 0;
403}
404
405#sidenavi {
406 color: #333333;
407 /* float: left; */
408 font-family: Arial,Helvetica,sans-serif;
409 font-size: 18px;
410 line-height: 25px;
411 overflow: hidden;
412 padding: 10px 0 8px 0px;
413 width: 255px;
414}
0415
=== added file 'doc/build/html/_static/doctools.js'
--- doc/build/html/_static/doctools.js 1970-01-01 00:00:00 +0000
+++ doc/build/html/_static/doctools.js 2012-03-08 09:19:21 +0000
@@ -0,0 +1,247 @@
1/*
2 * doctools.js
3 * ~~~~~~~~~~~
4 *
5 * Sphinx JavaScript utilties for all documentation.
6 *
7 * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
8 * :license: BSD, see LICENSE for details.
9 *
10 */
11
12/**
13 * select a different prefix for underscore
14 */
15$u = _.noConflict();
16
17/**
18 * make the code below compatible with browsers without
19 * an installed firebug like debugger
20if (!window.console || !console.firebug) {
21 var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
22 "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
23 "profile", "profileEnd"];
24 window.console = {};
25 for (var i = 0; i < names.length; ++i)
26 window.console[names[i]] = function() {};
27}
28 */
29
30/**
31 * small helper function to urldecode strings
32 */
33jQuery.urldecode = function(x) {
34 return decodeURIComponent(x).replace(/\+/g, ' ');
35}
36
37/**
38 * small helper function to urlencode strings
39 */
40jQuery.urlencode = encodeURIComponent;
41
42/**
43 * This function returns the parsed url parameters of the
44 * current request. Multiple values per key are supported,
45 * it will always return arrays of strings for the value parts.
46 */
47jQuery.getQueryParameters = function(s) {
48 if (typeof s == 'undefined')
49 s = document.location.search;
50 var parts = s.substr(s.indexOf('?') + 1).split('&');
51 var result = {};
52 for (var i = 0; i < parts.length; i++) {
53 var tmp = parts[i].split('=', 2);
54 var key = jQuery.urldecode(tmp[0]);
55 var value = jQuery.urldecode(tmp[1]);
56 if (key in result)
57 result[key].push(value);
58 else
59 result[key] = [value];
60 }
61 return result;
62};
63
64/**
65 * small function to check if an array contains
66 * a given item.
67 */
68jQuery.contains = function(arr, item) {
69 for (var i = 0; i < arr.length; i++) {
70 if (arr[i] == item)
71 return true;
72 }
73 return false;
74};
75
76/**
77 * highlight a given string on a jquery object by wrapping it in
78 * span elements with the given class name.
79 */
80jQuery.fn.highlightText = function(text, className) {
81 function highlight(node) {
82 if (node.nodeType == 3) {
83 var val = node.nodeValue;
84 var pos = val.toLowerCase().indexOf(text);
85 if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
86 var span = document.createElement("span");
87 span.className = className;
88 span.appendChild(document.createTextNode(val.substr(pos, text.length)));
89 node.parentNode.insertBefore(span, node.parentNode.insertBefore(
90 document.createTextNode(val.substr(pos + text.length)),
91 node.nextSibling));
92 node.nodeValue = val.substr(0, pos);
93 }
94 }
95 else if (!jQuery(node).is("button, select, textarea")) {
96 jQuery.each(node.childNodes, function() {
97 highlight(this);
98 });
99 }
100 }
101 return this.each(function() {
102 highlight(this);
103 });
104};
105
106/**
107 * Small JavaScript module for the documentation.
108 */
109var Documentation = {
110
111 init : function() {
112 this.fixFirefoxAnchorBug();
113 this.highlightSearchWords();
114 this.initIndexTable();
115 },
116
117 /**
118 * i18n support
119 */
120 TRANSLATIONS : {},
121 PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
122 LOCALE : 'unknown',
123
124 // gettext and ngettext don't access this so that the functions
125 // can safely bound to a different name (_ = Documentation.gettext)
126 gettext : function(string) {
127 var translated = Documentation.TRANSLATIONS[string];
128 if (typeof translated == 'undefined')
129 return string;
130 return (typeof translated == 'string') ? translated : translated[0];
131 },
132
133 ngettext : function(singular, plural, n) {
134 var translated = Documentation.TRANSLATIONS[singular];
135 if (typeof translated == 'undefined')
136 return (n == 1) ? singular : plural;
137 return translated[Documentation.PLURALEXPR(n)];
138 },
139
140 addTranslations : function(catalog) {
141 for (var key in catalog.messages)
142 this.TRANSLATIONS[key] = catalog.messages[key];
143 this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
144 this.LOCALE = catalog.locale;
145 },
146
147 /**
148 * add context elements like header anchor links
149 */
150 addContextElements : function() {
151 $('div[id] > :header:first').each(function() {
152 $('<a class="headerlink">\u00B6</a>').
153 attr('href', '#' + this.id).
154 attr('title', _('Permalink to this headline')).
155 appendTo(this);
156 });
157 $('dt[id]').each(function() {
158 $('<a class="headerlink">\u00B6</a>').
159 attr('href', '#' + this.id).
160 attr('title', _('Permalink to this definition')).
161 appendTo(this);
162 });
163 },
164
165 /**
166 * workaround a firefox stupidity
167 */
168 fixFirefoxAnchorBug : function() {
169 if (document.location.hash && $.browser.mozilla)
170 window.setTimeout(function() {
171 document.location.href += '';
172 }, 10);
173 },
174
175 /**
176 * highlight the search words provided in the url in the text
177 */
178 highlightSearchWords : function() {
179 var params = $.getQueryParameters();
180 var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
181 if (terms.length) {
182 var body = $('div.body');
183 window.setTimeout(function() {
184 $.each(terms, function() {
185 body.highlightText(this.toLowerCase(), 'highlighted');
186 });
187 }, 10);
188 $('<li class="highlight-link"><a href="javascript:Documentation.' +
189 'hideSearchWords()">' + _('Hide Search Matches') + '</a></li>')
190 .appendTo($('.sidebar .this-page-menu'));
191 }
192 },
193
194 /**
195 * init the domain index toggle buttons
196 */
197 initIndexTable : function() {
198 var togglers = $('img.toggler').click(function() {
199 var src = $(this).attr('src');
200 var idnum = $(this).attr('id').substr(7);
201 $('tr.cg-' + idnum).toggle();
202 if (src.substr(-9) == 'minus.png')
203 $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
204 else
205 $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
206 }).css('display', '');
207 if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
208 togglers.click();
209 }
210 },
211
212 /**
213 * helper function to hide the search marks again
214 */
215 hideSearchWords : function() {
216 $('.sidebar .this-page-menu li.highlight-link').fadeOut(300);
217 $('span.highlighted').removeClass('highlighted');
218 },
219
220 /**
221 * make the url absolute
222 */
223 makeURL : function(relativeURL) {
224 return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
225 },
226
227 /**
228 * get the current relative url
229 */
230 getCurrentURL : function() {
231 var path = document.location.pathname;
232 var parts = path.split(/\//);
233 $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
234 if (this == '..')
235 parts.pop();
236 });
237 var url = parts.join('/');
238 return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
239 }
240};
241
242// quick alias for translations
243_ = Documentation.gettext;
244
245$(document).ready(function() {
246 Documentation.init();
247});
0248
=== added file 'doc/build/html/_static/email-small.png'
1Binary files doc/build/html/_static/email-small.png 1970-01-01 00:00:00 +0000 and doc/build/html/_static/email-small.png 2012-03-08 09:19:21 +0000 differ249Binary files doc/build/html/_static/email-small.png 1970-01-01 00:00:00 +0000 and doc/build/html/_static/email-small.png 2012-03-08 09:19:21 +0000 differ
=== added file 'doc/build/html/_static/file.png'
2Binary files doc/build/html/_static/file.png 1970-01-01 00:00:00 +0000 and doc/build/html/_static/file.png 2012-03-08 09:19:21 +0000 differ250Binary files doc/build/html/_static/file.png 1970-01-01 00:00:00 +0000 and doc/build/html/_static/file.png 2012-03-08 09:19:21 +0000 differ
=== added file 'doc/build/html/_static/jquery.js'
--- doc/build/html/_static/jquery.js 1970-01-01 00:00:00 +0000
+++ doc/build/html/_static/jquery.js 2012-03-08 09:19:21 +0000
@@ -0,0 +1,8981 @@
1/*!
2 * jQuery JavaScript Library v1.6.2
3 * http://jquery.com/
4 *
5 * Copyright 2011, John Resig
6 * Dual licensed under the MIT or GPL Version 2 licenses.
7 * http://jquery.org/license
8 *
9 * Includes Sizzle.js
10 * http://sizzlejs.com/
11 * Copyright 2011, The Dojo Foundation
12 * Released under the MIT, BSD, and GPL Licenses.
13 *
14 * Date: Thu Jun 30 14:16:56 2011 -0400
15 */
16(function( window, undefined ) {
17
18// Use the correct document accordingly with window argument (sandbox)
19var document = window.document,
20 navigator = window.navigator,
21 location = window.location;
22var jQuery = (function() {
23
24// Define a local copy of jQuery
25var jQuery = function( selector, context ) {
26 // The jQuery object is actually just the init constructor 'enhanced'
27 return new jQuery.fn.init( selector, context, rootjQuery );
28 },
29
30 // Map over jQuery in case of overwrite
31 _jQuery = window.jQuery,
32
33 // Map over the $ in case of overwrite
34 _$ = window.$,
35
36 // A central reference to the root jQuery(document)
37 rootjQuery,
38
39 // A simple way to check for HTML strings or ID strings
40 // (both of which we optimize for)
41 quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
42
43 // Check if a string has a non-whitespace character in it
44 rnotwhite = /\S/,
45
46 // Used for trimming whitespace
47 trimLeft = /^\s+/,
48 trimRight = /\s+$/,
49
50 // Check for digits
51 rdigit = /\d/,
52
53 // Match a standalone tag
54 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
55
56 // JSON RegExp
57 rvalidchars = /^[\],:{}\s]*$/,
58 rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
59 rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
60 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
61
62 // Useragent RegExp
63 rwebkit = /(webkit)[ \/]([\w.]+)/,
64 ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
65 rmsie = /(msie) ([\w.]+)/,
66 rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
67
68 // Matches dashed string for camelizing
69 rdashAlpha = /-([a-z])/ig,
70
71 // Used by jQuery.camelCase as callback to replace()
72 fcamelCase = function( all, letter ) {
73 return letter.toUpperCase();
74 },
75
76 // Keep a UserAgent string for use with jQuery.browser
77 userAgent = navigator.userAgent,
78
79 // For matching the engine and version of the browser
80 browserMatch,
81
82 // The deferred used on DOM ready
83 readyList,
84
85 // The ready event handler
86 DOMContentLoaded,
87
88 // Save a reference to some core methods
89 toString = Object.prototype.toString,
90 hasOwn = Object.prototype.hasOwnProperty,
91 push = Array.prototype.push,
92 slice = Array.prototype.slice,
93 trim = String.prototype.trim,
94 indexOf = Array.prototype.indexOf,
95
96 // [[Class]] -> type pairs
97 class2type = {};
98
99jQuery.fn = jQuery.prototype = {
100 constructor: jQuery,
101 init: function( selector, context, rootjQuery ) {
102 var match, elem, ret, doc;
103
104 // Handle $(""), $(null), or $(undefined)
105 if ( !selector ) {
106 return this;
107 }
108
109 // Handle $(DOMElement)
110 if ( selector.nodeType ) {
111 this.context = this[0] = selector;
112 this.length = 1;
113 return this;
114 }
115
116 // The body element only exists once, optimize finding it
117 if ( selector === "body" && !context && document.body ) {
118 this.context = document;
119 this[0] = document.body;
120 this.selector = selector;
121 this.length = 1;
122 return this;
123 }
124
125 // Handle HTML strings
126 if ( typeof selector === "string" ) {
127 // Are we dealing with HTML string or an ID?
128 if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
129 // Assume that strings that start and end with <> are HTML and skip the regex check
130 match = [ null, selector, null ];
131
132 } else {
133 match = quickExpr.exec( selector );
134 }
135
136 // Verify a match, and that no context was specified for #id
137 if ( match && (match[1] || !context) ) {
138
139 // HANDLE: $(html) -> $(array)
140 if ( match[1] ) {
141 context = context instanceof jQuery ? context[0] : context;
142 doc = (context ? context.ownerDocument || context : document);
143
144 // If a single string is passed in and it's a single tag
145 // just do a createElement and skip the rest
146 ret = rsingleTag.exec( selector );
147
148 if ( ret ) {
149 if ( jQuery.isPlainObject( context ) ) {
150 selector = [ document.createElement( ret[1] ) ];
151 jQuery.fn.attr.call( selector, context, true );
152
153 } else {
154 selector = [ doc.createElement( ret[1] ) ];
155 }
156
157 } else {
158 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
159 selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
160 }
161
162 return jQuery.merge( this, selector );
163
164 // HANDLE: $("#id")
165 } else {
166 elem = document.getElementById( match[2] );
167
168 // Check parentNode to catch when Blackberry 4.6 returns
169 // nodes that are no longer in the document #6963
170 if ( elem && elem.parentNode ) {
171 // Handle the case where IE and Opera return items
172 // by name instead of ID
173 if ( elem.id !== match[2] ) {
174 return rootjQuery.find( selector );
175 }
176
177 // Otherwise, we inject the element directly into the jQuery object
178 this.length = 1;
179 this[0] = elem;
180 }
181
182 this.context = document;
183 this.selector = selector;
184 return this;
185 }
186
187 // HANDLE: $(expr, $(...))
188 } else if ( !context || context.jquery ) {
189 return (context || rootjQuery).find( selector );
190
191 // HANDLE: $(expr, context)
192 // (which is just equivalent to: $(context).find(expr)
193 } else {
194 return this.constructor( context ).find( selector );
195 }
196
197 // HANDLE: $(function)
198 // Shortcut for document ready
199 } else if ( jQuery.isFunction( selector ) ) {
200 return rootjQuery.ready( selector );
201 }
202
203 if (selector.selector !== undefined) {
204 this.selector = selector.selector;
205 this.context = selector.context;
206 }
207
208 return jQuery.makeArray( selector, this );
209 },
210
211 // Start with an empty selector
212 selector: "",
213
214 // The current version of jQuery being used
215 jquery: "1.6.2",
216
217 // The default length of a jQuery object is 0
218 length: 0,
219
220 // The number of elements contained in the matched element set
221 size: function() {
222 return this.length;
223 },
224
225 toArray: function() {
226 return slice.call( this, 0 );
227 },
228
229 // Get the Nth element in the matched element set OR
230 // Get the whole matched element set as a clean array
231 get: function( num ) {
232 return num == null ?
233
234 // Return a 'clean' array
235 this.toArray() :
236
237 // Return just the object
238 ( num < 0 ? this[ this.length + num ] : this[ num ] );
239 },
240
241 // Take an array of elements and push it onto the stack
242 // (returning the new matched element set)
243 pushStack: function( elems, name, selector ) {
244 // Build a new jQuery matched element set
245 var ret = this.constructor();
246
247 if ( jQuery.isArray( elems ) ) {
248 push.apply( ret, elems );
249
250 } else {
251 jQuery.merge( ret, elems );
252 }
253
254 // Add the old object onto the stack (as a reference)
255 ret.prevObject = this;
256
257 ret.context = this.context;
258
259 if ( name === "find" ) {
260 ret.selector = this.selector + (this.selector ? " " : "") + selector;
261 } else if ( name ) {
262 ret.selector = this.selector + "." + name + "(" + selector + ")";
263 }
264
265 // Return the newly-formed element set
266 return ret;
267 },
268
269 // Execute a callback for every element in the matched set.
270 // (You can seed the arguments with an array of args, but this is
271 // only used internally.)
272 each: function( callback, args ) {
273 return jQuery.each( this, callback, args );
274 },
275
276 ready: function( fn ) {
277 // Attach the listeners
278 jQuery.bindReady();
279
280 // Add the callback
281 readyList.done( fn );
282
283 return this;
284 },
285
286 eq: function( i ) {
287 return i === -1 ?
288 this.slice( i ) :
289 this.slice( i, +i + 1 );
290 },
291
292 first: function() {
293 return this.eq( 0 );
294 },
295
296 last: function() {
297 return this.eq( -1 );
298 },
299
300 slice: function() {
301 return this.pushStack( slice.apply( this, arguments ),
302 "slice", slice.call(arguments).join(",") );
303 },
304
305 map: function( callback ) {
306 return this.pushStack( jQuery.map(this, function( elem, i ) {
307 return callback.call( elem, i, elem );
308 }));
309 },
310
311 end: function() {
312 return this.prevObject || this.constructor(null);
313 },
314
315 // For internal use only.
316 // Behaves like an Array's method, not like a jQuery method.
317 push: push,
318 sort: [].sort,
319 splice: [].splice
320};
321
322// Give the init function the jQuery prototype for later instantiation
323jQuery.fn.init.prototype = jQuery.fn;
324
325jQuery.extend = jQuery.fn.extend = function() {
326 var options, name, src, copy, copyIsArray, clone,
327 target = arguments[0] || {},
328 i = 1,
329 length = arguments.length,
330 deep = false;
331
332 // Handle a deep copy situation
333 if ( typeof target === "boolean" ) {
334 deep = target;
335 target = arguments[1] || {};
336 // skip the boolean and the target
337 i = 2;
338 }
339
340 // Handle case when target is a string or something (possible in deep copy)
341 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
342 target = {};
343 }
344
345 // extend jQuery itself if only one argument is passed
346 if ( length === i ) {
347 target = this;
348 --i;
349 }
350
351 for ( ; i < length; i++ ) {
352 // Only deal with non-null/undefined values
353 if ( (options = arguments[ i ]) != null ) {
354 // Extend the base object
355 for ( name in options ) {
356 src = target[ name ];
357 copy = options[ name ];
358
359 // Prevent never-ending loop
360 if ( target === copy ) {
361 continue;
362 }
363
364 // Recurse if we're merging plain objects or arrays
365 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
366 if ( copyIsArray ) {
367 copyIsArray = false;
368 clone = src && jQuery.isArray(src) ? src : [];
369
370 } else {
371 clone = src && jQuery.isPlainObject(src) ? src : {};
372 }
373
374 // Never move original objects, clone them
375 target[ name ] = jQuery.extend( deep, clone, copy );
376
377 // Don't bring in undefined values
378 } else if ( copy !== undefined ) {
379 target[ name ] = copy;
380 }
381 }
382 }
383 }
384
385 // Return the modified object
386 return target;
387};
388
389jQuery.extend({
390 noConflict: function( deep ) {
391 if ( window.$ === jQuery ) {
392 window.$ = _$;
393 }
394
395 if ( deep && window.jQuery === jQuery ) {
396 window.jQuery = _jQuery;
397 }
398
399 return jQuery;
400 },
401
402 // Is the DOM ready to be used? Set to true once it occurs.
403 isReady: false,
404
405 // A counter to track how many items to wait for before
406 // the ready event fires. See #6781
407 readyWait: 1,
408
409 // Hold (or release) the ready event
410 holdReady: function( hold ) {
411 if ( hold ) {
412 jQuery.readyWait++;
413 } else {
414 jQuery.ready( true );
415 }
416 },
417
418 // Handle when the DOM is ready
419 ready: function( wait ) {
420 // Either a released hold or an DOMready/load event and not yet ready
421 if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
422 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
423 if ( !document.body ) {
424 return setTimeout( jQuery.ready, 1 );
425 }
426
427 // Remember that the DOM is ready
428 jQuery.isReady = true;
429
430 // If a normal DOM Ready event fired, decrement, and wait if need be
431 if ( wait !== true && --jQuery.readyWait > 0 ) {
432 return;
433 }
434
435 // If there are functions bound, to execute
436 readyList.resolveWith( document, [ jQuery ] );
437
438 // Trigger any bound ready events
439 if ( jQuery.fn.trigger ) {
440 jQuery( document ).trigger( "ready" ).unbind( "ready" );
441 }
442 }
443 },
444
445 bindReady: function() {
446 if ( readyList ) {
447 return;
448 }
449
450 readyList = jQuery._Deferred();
451
452 // Catch cases where $(document).ready() is called after the
453 // browser event has already occurred.
454 if ( document.readyState === "complete" ) {
455 // Handle it asynchronously to allow scripts the opportunity to delay ready
456 return setTimeout( jQuery.ready, 1 );
457 }
458
459 // Mozilla, Opera and webkit nightlies currently support this event
460 if ( document.addEventListener ) {
461 // Use the handy event callback
462 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
463
464 // A fallback to window.onload, that will always work
465 window.addEventListener( "load", jQuery.ready, false );
466
467 // If IE event model is used
468 } else if ( document.attachEvent ) {
469 // ensure firing before onload,
470 // maybe late but safe also for iframes
471 document.attachEvent( "onreadystatechange", DOMContentLoaded );
472
473 // A fallback to window.onload, that will always work
474 window.attachEvent( "onload", jQuery.ready );
475
476 // If IE and not a frame
477 // continually check to see if the document is ready
478 var toplevel = false;
479
480 try {
481 toplevel = window.frameElement == null;
482 } catch(e) {}
483
484 if ( document.documentElement.doScroll && toplevel ) {
485 doScrollCheck();
486 }
487 }
488 },
489
490 // See test/unit/core.js for details concerning isFunction.
491 // Since version 1.3, DOM methods and functions like alert
492 // aren't supported. They return false on IE (#2968).
493 isFunction: function( obj ) {
494 return jQuery.type(obj) === "function";
495 },
496
497 isArray: Array.isArray || function( obj ) {
498 return jQuery.type(obj) === "array";
499 },
500
501 // A crude way of determining if an object is a window
502 isWindow: function( obj ) {
503 return obj && typeof obj === "object" && "setInterval" in obj;
504 },
505
506 isNaN: function( obj ) {
507 return obj == null || !rdigit.test( obj ) || isNaN( obj );
508 },
509
510 type: function( obj ) {
511 return obj == null ?
512 String( obj ) :
513 class2type[ toString.call(obj) ] || "object";
514 },
515
516 isPlainObject: function( obj ) {
517 // Must be an Object.
518 // Because of IE, we also have to check the presence of the constructor property.
519 // Make sure that DOM nodes and window objects don't pass through, as well
520 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
521 return false;
522 }
523
524 // Not own constructor property must be Object
525 if ( obj.constructor &&
526 !hasOwn.call(obj, "constructor") &&
527 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
528 return false;
529 }
530
531 // Own properties are enumerated firstly, so to speed up,
532 // if last one is own, then all properties are own.
533
534 var key;
535 for ( key in obj ) {}
536
537 return key === undefined || hasOwn.call( obj, key );
538 },
539
540 isEmptyObject: function( obj ) {
541 for ( var name in obj ) {
542 return false;
543 }
544 return true;
545 },
546
547 error: function( msg ) {
548 throw msg;
549 },
550
551 parseJSON: function( data ) {
552 if ( typeof data !== "string" || !data ) {
553 return null;
554 }
555
556 // Make sure leading/trailing whitespace is removed (IE can't handle it)
557 data = jQuery.trim( data );
558
559 // Attempt to parse using the native JSON parser first
560 if ( window.JSON && window.JSON.parse ) {
561 return window.JSON.parse( data );
562 }
563
564 // Make sure the incoming data is actual JSON
565 // Logic borrowed from http://json.org/json2.js
566 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
567 .replace( rvalidtokens, "]" )
568 .replace( rvalidbraces, "")) ) {
569
570 return (new Function( "return " + data ))();
571
572 }
573 jQuery.error( "Invalid JSON: " + data );
574 },
575
576 // Cross-browser xml parsing
577 // (xml & tmp used internally)
578 parseXML: function( data , xml , tmp ) {
579
580 if ( window.DOMParser ) { // Standard
581 tmp = new DOMParser();
582 xml = tmp.parseFromString( data , "text/xml" );
583 } else { // IE
584 xml = new ActiveXObject( "Microsoft.XMLDOM" );
585 xml.async = "false";
586 xml.loadXML( data );
587 }
588
589 tmp = xml.documentElement;
590
591 if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
592 jQuery.error( "Invalid XML: " + data );
593 }
594
595 return xml;
596 },
597
598 noop: function() {},
599
600 // Evaluates a script in a global context
601 // Workarounds based on findings by Jim Driscoll
602 // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
603 globalEval: function( data ) {
604 if ( data && rnotwhite.test( data ) ) {
605 // We use execScript on Internet Explorer
606 // We use an anonymous function so that context is window
607 // rather than jQuery in Firefox
608 ( window.execScript || function( data ) {
609 window[ "eval" ].call( window, data );
610 } )( data );
611 }
612 },
613
614 // Converts a dashed string to camelCased string;
615 // Used by both the css and data modules
616 camelCase: function( string ) {
617 return string.replace( rdashAlpha, fcamelCase );
618 },
619
620 nodeName: function( elem, name ) {
621 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
622 },
623
624 // args is for internal usage only
625 each: function( object, callback, args ) {
626 var name, i = 0,
627 length = object.length,
628 isObj = length === undefined || jQuery.isFunction( object );
629
630 if ( args ) {
631 if ( isObj ) {
632 for ( name in object ) {
633 if ( callback.apply( object[ name ], args ) === false ) {
634 break;
635 }
636 }
637 } else {
638 for ( ; i < length; ) {
639 if ( callback.apply( object[ i++ ], args ) === false ) {
640 break;
641 }
642 }
643 }
644
645 // A special, fast, case for the most common use of each
646 } else {
647 if ( isObj ) {
648 for ( name in object ) {
649 if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
650 break;
651 }
652 }
653 } else {
654 for ( ; i < length; ) {
655 if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
656 break;
657 }
658 }
659 }
660 }
661
662 return object;
663 },
664
665 // Use native String.trim function wherever possible
666 trim: trim ?
667 function( text ) {
668 return text == null ?
669 "" :
670 trim.call( text );
671 } :
672
673 // Otherwise use our own trimming functionality
674 function( text ) {
675 return text == null ?
676 "" :
677 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
678 },
679
680 // results is for internal usage only
681 makeArray: function( array, results ) {
682 var ret = results || [];
683
684 if ( array != null ) {
685 // The window, strings (and functions) also have 'length'
686 // The extra typeof function check is to prevent crashes
687 // in Safari 2 (See: #3039)
688 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
689 var type = jQuery.type( array );
690
691 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
692 push.call( ret, array );
693 } else {
694 jQuery.merge( ret, array );
695 }
696 }
697
698 return ret;
699 },
700
701 inArray: function( elem, array ) {
702
703 if ( indexOf ) {
704 return indexOf.call( array, elem );
705 }
706
707 for ( var i = 0, length = array.length; i < length; i++ ) {
708 if ( array[ i ] === elem ) {
709 return i;
710 }
711 }
712
713 return -1;
714 },
715
716 merge: function( first, second ) {
717 var i = first.length,
718 j = 0;
719
720 if ( typeof second.length === "number" ) {
721 for ( var l = second.length; j < l; j++ ) {
722 first[ i++ ] = second[ j ];
723 }
724
725 } else {
726 while ( second[j] !== undefined ) {
727 first[ i++ ] = second[ j++ ];
728 }
729 }
730
731 first.length = i;
732
733 return first;
734 },
735
736 grep: function( elems, callback, inv ) {
737 var ret = [], retVal;
738 inv = !!inv;
739
740 // Go through the array, only saving the items
741 // that pass the validator function
742 for ( var i = 0, length = elems.length; i < length; i++ ) {
743 retVal = !!callback( elems[ i ], i );
744 if ( inv !== retVal ) {
745 ret.push( elems[ i ] );
746 }
747 }
748
749 return ret;
750 },
751
752 // arg is for internal usage only
753 map: function( elems, callback, arg ) {
754 var value, key, ret = [],
755 i = 0,
756 length = elems.length,
757 // jquery objects are treated as arrays
758 isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
759
760 // Go through the array, translating each of the items to their
761 if ( isArray ) {
762 for ( ; i < length; i++ ) {
763 value = callback( elems[ i ], i, arg );
764
765 if ( value != null ) {
766 ret[ ret.length ] = value;
767 }
768 }
769
770 // Go through every key on the object,
771 } else {
772 for ( key in elems ) {
773 value = callback( elems[ key ], key, arg );
774
775 if ( value != null ) {
776 ret[ ret.length ] = value;
777 }
778 }
779 }
780
781 // Flatten any nested arrays
782 return ret.concat.apply( [], ret );
783 },
784
785 // A global GUID counter for objects
786 guid: 1,
787
788 // Bind a function to a context, optionally partially applying any
789 // arguments.
790 proxy: function( fn, context ) {
791 if ( typeof context === "string" ) {
792 var tmp = fn[ context ];
793 context = fn;
794 fn = tmp;
795 }
796
797 // Quick check to determine if target is callable, in the spec
798 // this throws a TypeError, but we will just return undefined.
799 if ( !jQuery.isFunction( fn ) ) {
800 return undefined;
801 }
802
803 // Simulated bind
804 var args = slice.call( arguments, 2 ),
805 proxy = function() {
806 return fn.apply( context, args.concat( slice.call( arguments ) ) );
807 };
808
809 // Set the guid of unique handler to the same of original handler, so it can be removed
810 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
811
812 return proxy;
813 },
814
815 // Mutifunctional method to get and set values to a collection
816 // The value/s can optionally be executed if it's a function
817 access: function( elems, key, value, exec, fn, pass ) {
818 var length = elems.length;
819
820 // Setting many attributes
821 if ( typeof key === "object" ) {
822 for ( var k in key ) {
823 jQuery.access( elems, k, key[k], exec, fn, value );
824 }
825 return elems;
826 }
827
828 // Setting one attribute
829 if ( value !== undefined ) {
830 // Optionally, function values get executed if exec is true
831 exec = !pass && exec && jQuery.isFunction(value);
832
833 for ( var i = 0; i < length; i++ ) {
834 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
835 }
836
837 return elems;
838 }
839
840 // Getting an attribute
841 return length ? fn( elems[0], key ) : undefined;
842 },
843
844 now: function() {
845 return (new Date()).getTime();
846 },
847
848 // Use of jQuery.browser is frowned upon.
849 // More details: http://docs.jquery.com/Utilities/jQuery.browser
850 uaMatch: function( ua ) {
851 ua = ua.toLowerCase();
852
853 var match = rwebkit.exec( ua ) ||
854 ropera.exec( ua ) ||
855 rmsie.exec( ua ) ||
856 ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
857 [];
858
859 return { browser: match[1] || "", version: match[2] || "0" };
860 },
861
862 sub: function() {
863 function jQuerySub( selector, context ) {
864 return new jQuerySub.fn.init( selector, context );
865 }
866 jQuery.extend( true, jQuerySub, this );
867 jQuerySub.superclass = this;
868 jQuerySub.fn = jQuerySub.prototype = this();
869 jQuerySub.fn.constructor = jQuerySub;
870 jQuerySub.sub = this.sub;
871 jQuerySub.fn.init = function init( selector, context ) {
872 if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
873 context = jQuerySub( context );
874 }
875
876 return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
877 };
878 jQuerySub.fn.init.prototype = jQuerySub.fn;
879 var rootjQuerySub = jQuerySub(document);
880 return jQuerySub;
881 },
882
883 browser: {}
884});
885
886// Populate the class2type map
887jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
888 class2type[ "[object " + name + "]" ] = name.toLowerCase();
889});
890
891browserMatch = jQuery.uaMatch( userAgent );
892if ( browserMatch.browser ) {
893 jQuery.browser[ browserMatch.browser ] = true;
894 jQuery.browser.version = browserMatch.version;
895}
896
897// Deprecated, use jQuery.browser.webkit instead
898if ( jQuery.browser.webkit ) {
899 jQuery.browser.safari = true;
900}
901
902// IE doesn't match non-breaking spaces with \s
903if ( rnotwhite.test( "\xA0" ) ) {
904 trimLeft = /^[\s\xA0]+/;
905 trimRight = /[\s\xA0]+$/;
906}
907
908// All jQuery objects should point back to these
909rootjQuery = jQuery(document);
910
911// Cleanup functions for the document ready method
912if ( document.addEventListener ) {
913 DOMContentLoaded = function() {
914 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
915 jQuery.ready();
916 };
917
918} else if ( document.attachEvent ) {
919 DOMContentLoaded = function() {
920 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
921 if ( document.readyState === "complete" ) {
922 document.detachEvent( "onreadystatechange", DOMContentLoaded );
923 jQuery.ready();
924 }
925 };
926}
927
928// The DOM ready check for Internet Explorer
929function doScrollCheck() {
930 if ( jQuery.isReady ) {
931 return;
932 }
933
934 try {
935 // If IE is used, use the trick by Diego Perini
936 // http://javascript.nwbox.com/IEContentLoaded/
937 document.documentElement.doScroll("left");
938 } catch(e) {
939 setTimeout( doScrollCheck, 1 );
940 return;
941 }
942
943 // and execute any waiting functions
944 jQuery.ready();
945}
946
947return jQuery;
948
949})();
950
951
952var // Promise methods
953 promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ),
954 // Static reference to slice
955 sliceDeferred = [].slice;
956
957jQuery.extend({
958 // Create a simple deferred (one callbacks list)
959 _Deferred: function() {
960 var // callbacks list
961 callbacks = [],
962 // stored [ context , args ]
963 fired,
964 // to avoid firing when already doing so
965 firing,
966 // flag to know if the deferred has been cancelled
967 cancelled,
968 // the deferred itself
969 deferred = {
970
971 // done( f1, f2, ...)
972 done: function() {
973 if ( !cancelled ) {
974 var args = arguments,
975 i,
976 length,
977 elem,
978 type,
979 _fired;
980 if ( fired ) {
981 _fired = fired;
982 fired = 0;
983 }
984 for ( i = 0, length = args.length; i < length; i++ ) {
985 elem = args[ i ];
986 type = jQuery.type( elem );
987 if ( type === "array" ) {
988 deferred.done.apply( deferred, elem );
989 } else if ( type === "function" ) {
990 callbacks.push( elem );
991 }
992 }
993 if ( _fired ) {
994 deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
995 }
996 }
997 return this;
998 },
999
1000 // resolve with given context and args
1001 resolveWith: function( context, args ) {
1002 if ( !cancelled && !fired && !firing ) {
1003 // make sure args are available (#8421)
1004 args = args || [];
1005 firing = 1;
1006 try {
1007 while( callbacks[ 0 ] ) {
1008 callbacks.shift().apply( context, args );
1009 }
1010 }
1011 finally {
1012 fired = [ context, args ];
1013 firing = 0;
1014 }
1015 }
1016 return this;
1017 },
1018
1019 // resolve with this as context and given arguments
1020 resolve: function() {
1021 deferred.resolveWith( this, arguments );
1022 return this;
1023 },
1024
1025 // Has this deferred been resolved?
1026 isResolved: function() {
1027 return !!( firing || fired );
1028 },
1029
1030 // Cancel
1031 cancel: function() {
1032 cancelled = 1;
1033 callbacks = [];
1034 return this;
1035 }
1036 };
1037
1038 return deferred;
1039 },
1040
1041 // Full fledged deferred (two callbacks list)
1042 Deferred: function( func ) {
1043 var deferred = jQuery._Deferred(),
1044 failDeferred = jQuery._Deferred(),
1045 promise;
1046 // Add errorDeferred methods, then and promise
1047 jQuery.extend( deferred, {
1048 then: function( doneCallbacks, failCallbacks ) {
1049 deferred.done( doneCallbacks ).fail( failCallbacks );
1050 return this;
1051 },
1052 always: function() {
1053 return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
1054 },
1055 fail: failDeferred.done,
1056 rejectWith: failDeferred.resolveWith,
1057 reject: failDeferred.resolve,
1058 isRejected: failDeferred.isResolved,
1059 pipe: function( fnDone, fnFail ) {
1060 return jQuery.Deferred(function( newDefer ) {
1061 jQuery.each( {
1062 done: [ fnDone, "resolve" ],
1063 fail: [ fnFail, "reject" ]
1064 }, function( handler, data ) {
1065 var fn = data[ 0 ],
1066 action = data[ 1 ],
1067 returned;
1068 if ( jQuery.isFunction( fn ) ) {
1069 deferred[ handler ](function() {
1070 returned = fn.apply( this, arguments );
1071 if ( returned && jQuery.isFunction( returned.promise ) ) {
1072 returned.promise().then( newDefer.resolve, newDefer.reject );
1073 } else {
1074 newDefer[ action ]( returned );
1075 }
1076 });
1077 } else {
1078 deferred[ handler ]( newDefer[ action ] );
1079 }
1080 });
1081 }).promise();
1082 },
1083 // Get a promise for this deferred
1084 // If obj is provided, the promise aspect is added to the object
1085 promise: function( obj ) {
1086 if ( obj == null ) {
1087 if ( promise ) {
1088 return promise;
1089 }
1090 promise = obj = {};
1091 }
1092 var i = promiseMethods.length;
1093 while( i-- ) {
1094 obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
1095 }
1096 return obj;
1097 }
1098 });
1099 // Make sure only one callback list will be used
1100 deferred.done( failDeferred.cancel ).fail( deferred.cancel );
1101 // Unexpose cancel
1102 delete deferred.cancel;
1103 // Call given func if any
1104 if ( func ) {
1105 func.call( deferred, deferred );
1106 }
1107 return deferred;
1108 },
1109
1110 // Deferred helper
1111 when: function( firstParam ) {
1112 var args = arguments,
1113 i = 0,
1114 length = args.length,
1115 count = length,
1116 deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
1117 firstParam :
1118 jQuery.Deferred();
1119 function resolveFunc( i ) {
1120 return function( value ) {
1121 args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
1122 if ( !( --count ) ) {
1123 // Strange bug in FF4:
1124 // Values changed onto the arguments object sometimes end up as undefined values
1125 // outside the $.when method. Cloning the object into a fresh array solves the issue
1126 deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );
1127 }
1128 };
1129 }
1130 if ( length > 1 ) {
1131 for( ; i < length; i++ ) {
1132 if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {
1133 args[ i ].promise().then( resolveFunc(i), deferred.reject );
1134 } else {
1135 --count;
1136 }
1137 }
1138 if ( !count ) {
1139 deferred.resolveWith( deferred, args );
1140 }
1141 } else if ( deferred !== firstParam ) {
1142 deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
1143 }
1144 return deferred.promise();
1145 }
1146});
1147
1148
1149
1150jQuery.support = (function() {
1151
1152 var div = document.createElement( "div" ),
1153 documentElement = document.documentElement,
1154 all,
1155 a,
1156 select,
1157 opt,
1158 input,
1159 marginDiv,
1160 support,
1161 fragment,
1162 body,
1163 testElementParent,
1164 testElement,
1165 testElementStyle,
1166 tds,
1167 events,
1168 eventName,
1169 i,
1170 isSupported;
1171
1172 // Preliminary tests
1173 div.setAttribute("className", "t");
1174 div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
1175
1176 all = div.getElementsByTagName( "*" );
1177 a = div.getElementsByTagName( "a" )[ 0 ];
1178
1179 // Can't get basic test support
1180 if ( !all || !all.length || !a ) {
1181 return {};
1182 }
1183
1184 // First batch of supports tests
1185 select = document.createElement( "select" );
1186 opt = select.appendChild( document.createElement("option") );
1187 input = div.getElementsByTagName( "input" )[ 0 ];
1188
1189 support = {
1190 // IE strips leading whitespace when .innerHTML is used
1191 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1192
1193 // Make sure that tbody elements aren't automatically inserted
1194 // IE will insert them into empty tables
1195 tbody: !div.getElementsByTagName( "tbody" ).length,
1196
1197 // Make sure that link elements get serialized correctly by innerHTML
1198 // This requires a wrapper element in IE
1199 htmlSerialize: !!div.getElementsByTagName( "link" ).length,
1200
1201 // Get the style information from getAttribute
1202 // (IE uses .cssText instead)
1203 style: /top/.test( a.getAttribute("style") ),
1204
1205 // Make sure that URLs aren't manipulated
1206 // (IE normalizes it by default)
1207 hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
1208
1209 // Make sure that element opacity exists
1210 // (IE uses filter instead)
1211 // Use a regex to work around a WebKit issue. See #5145
1212 opacity: /^0.55$/.test( a.style.opacity ),
1213
1214 // Verify style float existence
1215 // (IE uses styleFloat instead of cssFloat)
1216 cssFloat: !!a.style.cssFloat,
1217
1218 // Make sure that if no value is specified for a checkbox
1219 // that it defaults to "on".
1220 // (WebKit defaults to "" instead)
1221 checkOn: ( input.value === "on" ),
1222
1223 // Make sure that a selected-by-default option has a working selected property.
1224 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1225 optSelected: opt.selected,
1226
1227 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1228 getSetAttribute: div.className !== "t",
1229
1230 // Will be defined later
1231 submitBubbles: true,
1232 changeBubbles: true,
1233 focusinBubbles: false,
1234 deleteExpando: true,
1235 noCloneEvent: true,
1236 inlineBlockNeedsLayout: false,
1237 shrinkWrapBlocks: false,
1238 reliableMarginRight: true
1239 };
1240
1241 // Make sure checked status is properly cloned
1242 input.checked = true;
1243 support.noCloneChecked = input.cloneNode( true ).checked;
1244
1245 // Make sure that the options inside disabled selects aren't marked as disabled
1246 // (WebKit marks them as disabled)
1247 select.disabled = true;
1248 support.optDisabled = !opt.disabled;
1249
1250 // Test to see if it's possible to delete an expando from an element
1251 // Fails in Internet Explorer
1252 try {
1253 delete div.test;
1254 } catch( e ) {
1255 support.deleteExpando = false;
1256 }
1257
1258 if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
1259 div.attachEvent( "onclick", function() {
1260 // Cloning a node shouldn't copy over any
1261 // bound event handlers (IE does this)
1262 support.noCloneEvent = false;
1263 });
1264 div.cloneNode( true ).fireEvent( "onclick" );
1265 }
1266
1267 // Check if a radio maintains it's value
1268 // after being appended to the DOM
1269 input = document.createElement("input");
1270 input.value = "t";
1271 input.setAttribute("type", "radio");
1272 support.radioValue = input.value === "t";
1273
1274 input.setAttribute("checked", "checked");
1275 div.appendChild( input );
1276 fragment = document.createDocumentFragment();
1277 fragment.appendChild( div.firstChild );
1278
1279 // WebKit doesn't clone checked state correctly in fragments
1280 support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1281
1282 div.innerHTML = "";
1283
1284 // Figure out if the W3C box model works as expected
1285 div.style.width = div.style.paddingLeft = "1px";
1286
1287 body = document.getElementsByTagName( "body" )[ 0 ];
1288 // We use our own, invisible, body unless the body is already present
1289 // in which case we use a div (#9239)
1290 testElement = document.createElement( body ? "div" : "body" );
1291 testElementStyle = {
1292 visibility: "hidden",
1293 width: 0,
1294 height: 0,
1295 border: 0,
1296 margin: 0
1297 };
1298 if ( body ) {
1299 jQuery.extend( testElementStyle, {
1300 position: "absolute",
1301 left: -1000,
1302 top: -1000
1303 });
1304 }
1305 for ( i in testElementStyle ) {
1306 testElement.style[ i ] = testElementStyle[ i ];
1307 }
1308 testElement.appendChild( div );
1309 testElementParent = body || documentElement;
1310 testElementParent.insertBefore( testElement, testElementParent.firstChild );
1311
1312 // Check if a disconnected checkbox will retain its checked
1313 // value of true after appended to the DOM (IE6/7)
1314 support.appendChecked = input.checked;
1315
1316 support.boxModel = div.offsetWidth === 2;
1317
1318 if ( "zoom" in div.style ) {
1319 // Check if natively block-level elements act like inline-block
1320 // elements when setting their display to 'inline' and giving
1321 // them layout
1322 // (IE < 8 does this)
1323 div.style.display = "inline";
1324 div.style.zoom = 1;
1325 support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
1326
1327 // Check if elements with layout shrink-wrap their children
1328 // (IE 6 does this)
1329 div.style.display = "";
1330 div.innerHTML = "<div style='width:4px;'></div>";
1331 support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
1332 }
1333
1334 div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
1335 tds = div.getElementsByTagName( "td" );
1336
1337 // Check if table cells still have offsetWidth/Height when they are set
1338 // to display:none and there are still other visible table cells in a
1339 // table row; if so, offsetWidth/Height are not reliable for use when
1340 // determining if an element has been hidden directly using
1341 // display:none (it is still safe to use offsets if a parent element is
1342 // hidden; don safety goggles and see bug #4512 for more information).
1343 // (only IE 8 fails this test)
1344 isSupported = ( tds[ 0 ].offsetHeight === 0 );
1345
1346 tds[ 0 ].style.display = "";
1347 tds[ 1 ].style.display = "none";
1348
1349 // Check if empty table cells still have offsetWidth/Height
1350 // (IE < 8 fail this test)
1351 support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
1352 div.innerHTML = "";
1353
1354 // Check if div with explicit width and no margin-right incorrectly
1355 // gets computed margin-right based on width of container. For more
1356 // info see bug #3333
1357 // Fails in WebKit before Feb 2011 nightlies
1358 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
1359 if ( document.defaultView && document.defaultView.getComputedStyle ) {
1360 marginDiv = document.createElement( "div" );
1361 marginDiv.style.width = "0";
1362 marginDiv.style.marginRight = "0";
1363 div.appendChild( marginDiv );
1364 support.reliableMarginRight =
1365 ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
1366 }
1367
1368 // Remove the body element we added
1369 testElement.innerHTML = "";
1370 testElementParent.removeChild( testElement );
1371
1372 // Technique from Juriy Zaytsev
1373 // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
1374 // We only care about the case where non-standard event systems
1375 // are used, namely in IE. Short-circuiting here helps us to
1376 // avoid an eval call (in setAttribute) which can cause CSP
1377 // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
1378 if ( div.attachEvent ) {
1379 for( i in {
1380 submit: 1,
1381 change: 1,
1382 focusin: 1
1383 } ) {
1384 eventName = "on" + i;
1385 isSupported = ( eventName in div );
1386 if ( !isSupported ) {
1387 div.setAttribute( eventName, "return;" );
1388 isSupported = ( typeof div[ eventName ] === "function" );
1389 }
1390 support[ i + "Bubbles" ] = isSupported;
1391 }
1392 }
1393
1394 // Null connected elements to avoid leaks in IE
1395 testElement = fragment = select = opt = body = marginDiv = div = input = null;
1396
1397 return support;
1398})();
1399
1400// Keep track of boxModel
1401jQuery.boxModel = jQuery.support.boxModel;
1402
1403
1404
1405
1406var rbrace = /^(?:\{.*\}|\[.*\])$/,
1407 rmultiDash = /([a-z])([A-Z])/g;
1408
1409jQuery.extend({
1410 cache: {},
1411
1412 // Please use with caution
1413 uuid: 0,
1414
1415 // Unique for each copy of jQuery on the page
1416 // Non-digits removed to match rinlinejQuery
1417 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
1418
1419 // The following elements throw uncatchable exceptions if you
1420 // attempt to add expando properties to them.
1421 noData: {
1422 "embed": true,
1423 // Ban all objects except for Flash (which handle expandos)
1424 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1425 "applet": true
1426 },
1427
1428 hasData: function( elem ) {
1429 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1430
1431 return !!elem && !isEmptyDataObject( elem );
1432 },
1433
1434 data: function( elem, name, data, pvt /* Internal Use Only */ ) {
1435 if ( !jQuery.acceptData( elem ) ) {
1436 return;
1437 }
1438
1439 var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
1440
1441 // We have to handle DOM nodes and JS objects differently because IE6-7
1442 // can't GC object references properly across the DOM-JS boundary
1443 isNode = elem.nodeType,
1444
1445 // Only DOM nodes need the global jQuery cache; JS object data is
1446 // attached directly to the object so GC can occur automatically
1447 cache = isNode ? jQuery.cache : elem,
1448
1449 // Only defining an ID for JS objects if its cache already exists allows
1450 // the code to shortcut on the same path as a DOM node with no cache
1451 id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
1452
1453 // Avoid doing any more work than we need to when trying to get data on an
1454 // object that has no data at all
1455 if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
1456 return;
1457 }
1458
1459 if ( !id ) {
1460 // Only DOM nodes need a new unique ID for each element since their data
1461 // ends up in the global cache
1462 if ( isNode ) {
1463 elem[ jQuery.expando ] = id = ++jQuery.uuid;
1464 } else {
1465 id = jQuery.expando;
1466 }
1467 }
1468
1469 if ( !cache[ id ] ) {
1470 cache[ id ] = {};
1471
1472 // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
1473 // metadata on plain JS objects when the object is serialized using
1474 // JSON.stringify
1475 if ( !isNode ) {
1476 cache[ id ].toJSON = jQuery.noop;
1477 }
1478 }
1479
1480 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1481 // shallow copied over onto the existing cache
1482 if ( typeof name === "object" || typeof name === "function" ) {
1483 if ( pvt ) {
1484 cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
1485 } else {
1486 cache[ id ] = jQuery.extend(cache[ id ], name);
1487 }
1488 }
1489
1490 thisCache = cache[ id ];
1491
1492 // Internal jQuery data is stored in a separate object inside the object's data
1493 // cache in order to avoid key collisions between internal data and user-defined
1494 // data
1495 if ( pvt ) {
1496 if ( !thisCache[ internalKey ] ) {
1497 thisCache[ internalKey ] = {};
1498 }
1499
1500 thisCache = thisCache[ internalKey ];
1501 }
1502
1503 if ( data !== undefined ) {
1504 thisCache[ jQuery.camelCase( name ) ] = data;
1505 }
1506
1507 // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
1508 // not attempt to inspect the internal events object using jQuery.data, as this
1509 // internal data object is undocumented and subject to change.
1510 if ( name === "events" && !thisCache[name] ) {
1511 return thisCache[ internalKey ] && thisCache[ internalKey ].events;
1512 }
1513
1514 return getByName ?
1515 // Check for both converted-to-camel and non-converted data property names
1516 thisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] :
1517 thisCache;
1518 },
1519
1520 removeData: function( elem, name, pvt /* Internal Use Only */ ) {
1521 if ( !jQuery.acceptData( elem ) ) {
1522 return;
1523 }
1524
1525 var internalKey = jQuery.expando, isNode = elem.nodeType,
1526
1527 // See jQuery.data for more information
1528 cache = isNode ? jQuery.cache : elem,
1529
1530 // See jQuery.data for more information
1531 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1532
1533 // If there is already no cache entry for this object, there is no
1534 // purpose in continuing
1535 if ( !cache[ id ] ) {
1536 return;
1537 }
1538
1539 if ( name ) {
1540 var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
1541
1542 if ( thisCache ) {
1543 delete thisCache[ name ];
1544
1545 // If there is no data left in the cache, we want to continue
1546 // and let the cache object itself get destroyed
1547 if ( !isEmptyDataObject(thisCache) ) {
1548 return;
1549 }
1550 }
1551 }
1552
1553 // See jQuery.data for more information
1554 if ( pvt ) {
1555 delete cache[ id ][ internalKey ];
1556
1557 // Don't destroy the parent cache unless the internal data object
1558 // had been the only thing left in it
1559 if ( !isEmptyDataObject(cache[ id ]) ) {
1560 return;
1561 }
1562 }
1563
1564 var internalCache = cache[ id ][ internalKey ];
1565
1566 // Browsers that fail expando deletion also refuse to delete expandos on
1567 // the window, but it will allow it on all other JS objects; other browsers
1568 // don't care
1569 if ( jQuery.support.deleteExpando || cache != window ) {
1570 delete cache[ id ];
1571 } else {
1572 cache[ id ] = null;
1573 }
1574
1575 // We destroyed the entire user cache at once because it's faster than
1576 // iterating through each key, but we need to continue to persist internal
1577 // data if it existed
1578 if ( internalCache ) {
1579 cache[ id ] = {};
1580 // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
1581 // metadata on plain JS objects when the object is serialized using
1582 // JSON.stringify
1583 if ( !isNode ) {
1584 cache[ id ].toJSON = jQuery.noop;
1585 }
1586
1587 cache[ id ][ internalKey ] = internalCache;
1588
1589 // Otherwise, we need to eliminate the expando on the node to avoid
1590 // false lookups in the cache for entries that no longer exist
1591 } else if ( isNode ) {
1592 // IE does not allow us to delete expando properties from nodes,
1593 // nor does it have a removeAttribute function on Document nodes;
1594 // we must handle all of these cases
1595 if ( jQuery.support.deleteExpando ) {
1596 delete elem[ jQuery.expando ];
1597 } else if ( elem.removeAttribute ) {
1598 elem.removeAttribute( jQuery.expando );
1599 } else {
1600 elem[ jQuery.expando ] = null;
1601 }
1602 }
1603 },
1604
1605 // For internal use only.
1606 _data: function( elem, name, data ) {
1607 return jQuery.data( elem, name, data, true );
1608 },
1609
1610 // A method for determining if a DOM node can handle the data expando
1611 acceptData: function( elem ) {
1612 if ( elem.nodeName ) {
1613 var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
1614
1615 if ( match ) {
1616 return !(match === true || elem.getAttribute("classid") !== match);
1617 }
1618 }
1619
1620 return true;
1621 }
1622});
1623
1624jQuery.fn.extend({
1625 data: function( key, value ) {
1626 var data = null;
1627
1628 if ( typeof key === "undefined" ) {
1629 if ( this.length ) {
1630 data = jQuery.data( this[0] );
1631
1632 if ( this[0].nodeType === 1 ) {
1633 var attr = this[0].attributes, name;
1634 for ( var i = 0, l = attr.length; i < l; i++ ) {
1635 name = attr[i].name;
1636
1637 if ( name.indexOf( "data-" ) === 0 ) {
1638 name = jQuery.camelCase( name.substring(5) );
1639
1640 dataAttr( this[0], name, data[ name ] );
1641 }
1642 }
1643 }
1644 }
1645
1646 return data;
1647
1648 } else if ( typeof key === "object" ) {
1649 return this.each(function() {
1650 jQuery.data( this, key );
1651 });
1652 }
1653
1654 var parts = key.split(".");
1655 parts[1] = parts[1] ? "." + parts[1] : "";
1656
1657 if ( value === undefined ) {
1658 data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1659
1660 // Try to fetch any internally stored data first
1661 if ( data === undefined && this.length ) {
1662 data = jQuery.data( this[0], key );
1663 data = dataAttr( this[0], key, data );
1664 }
1665
1666 return data === undefined && parts[1] ?
1667 this.data( parts[0] ) :
1668 data;
1669
1670 } else {
1671 return this.each(function() {
1672 var $this = jQuery( this ),
1673 args = [ parts[0], value ];
1674
1675 $this.triggerHandler( "setData" + parts[1] + "!", args );
1676 jQuery.data( this, key, value );
1677 $this.triggerHandler( "changeData" + parts[1] + "!", args );
1678 });
1679 }
1680 },
1681
1682 removeData: function( key ) {
1683 return this.each(function() {
1684 jQuery.removeData( this, key );
1685 });
1686 }
1687});
1688
1689function dataAttr( elem, key, data ) {
1690 // If nothing was found internally, try to fetch any
1691 // data from the HTML5 data-* attribute
1692 if ( data === undefined && elem.nodeType === 1 ) {
1693 var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
1694
1695 data = elem.getAttribute( name );
1696
1697 if ( typeof data === "string" ) {
1698 try {
1699 data = data === "true" ? true :
1700 data === "false" ? false :
1701 data === "null" ? null :
1702 !jQuery.isNaN( data ) ? parseFloat( data ) :
1703 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1704 data;
1705 } catch( e ) {}
1706
1707 // Make sure we set the data so it isn't changed later
1708 jQuery.data( elem, key, data );
1709
1710 } else {
1711 data = undefined;
1712 }
1713 }
1714
1715 return data;
1716}
1717
1718// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON
1719// property to be considered empty objects; this property always exists in
1720// order to make sure JSON.stringify does not expose internal metadata
1721function isEmptyDataObject( obj ) {
1722 for ( var name in obj ) {
1723 if ( name !== "toJSON" ) {
1724 return false;
1725 }
1726 }
1727
1728 return true;
1729}
1730
1731
1732
1733
1734function handleQueueMarkDefer( elem, type, src ) {
1735 var deferDataKey = type + "defer",
1736 queueDataKey = type + "queue",
1737 markDataKey = type + "mark",
1738 defer = jQuery.data( elem, deferDataKey, undefined, true );
1739 if ( defer &&
1740 ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
1741 ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {
1742 // Give room for hard-coded callbacks to fire first
1743 // and eventually mark/queue something else on the element
1744 setTimeout( function() {
1745 if ( !jQuery.data( elem, queueDataKey, undefined, true ) &&
1746 !jQuery.data( elem, markDataKey, undefined, true ) ) {
1747 jQuery.removeData( elem, deferDataKey, true );
1748 defer.resolve();
1749 }
1750 }, 0 );
1751 }
1752}
1753
1754jQuery.extend({
1755
1756 _mark: function( elem, type ) {
1757 if ( elem ) {
1758 type = (type || "fx") + "mark";
1759 jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );
1760 }
1761 },
1762
1763 _unmark: function( force, elem, type ) {
1764 if ( force !== true ) {
1765 type = elem;
1766 elem = force;
1767 force = false;
1768 }
1769 if ( elem ) {
1770 type = type || "fx";
1771 var key = type + "mark",
1772 count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );
1773 if ( count ) {
1774 jQuery.data( elem, key, count, true );
1775 } else {
1776 jQuery.removeData( elem, key, true );
1777 handleQueueMarkDefer( elem, type, "mark" );
1778 }
1779 }
1780 },
1781
1782 queue: function( elem, type, data ) {
1783 if ( elem ) {
1784 type = (type || "fx") + "queue";
1785 var q = jQuery.data( elem, type, undefined, true );
1786 // Speed up dequeue by getting out quickly if this is just a lookup
1787 if ( data ) {
1788 if ( !q || jQuery.isArray(data) ) {
1789 q = jQuery.data( elem, type, jQuery.makeArray(data), true );
1790 } else {
1791 q.push( data );
1792 }
1793 }
1794 return q || [];
1795 }
1796 },
1797
1798 dequeue: function( elem, type ) {
1799 type = type || "fx";
1800
1801 var queue = jQuery.queue( elem, type ),
1802 fn = queue.shift(),
1803 defer;
1804
1805 // If the fx queue is dequeued, always remove the progress sentinel
1806 if ( fn === "inprogress" ) {
1807 fn = queue.shift();
1808 }
1809
1810 if ( fn ) {
1811 // Add a progress sentinel to prevent the fx queue from being
1812 // automatically dequeued
1813 if ( type === "fx" ) {
1814 queue.unshift("inprogress");
1815 }
1816
1817 fn.call(elem, function() {
1818 jQuery.dequeue(elem, type);
1819 });
1820 }
1821
1822 if ( !queue.length ) {
1823 jQuery.removeData( elem, type + "queue", true );
1824 handleQueueMarkDefer( elem, type, "queue" );
1825 }
1826 }
1827});
1828
1829jQuery.fn.extend({
1830 queue: function( type, data ) {
1831 if ( typeof type !== "string" ) {
1832 data = type;
1833 type = "fx";
1834 }
1835
1836 if ( data === undefined ) {
1837 return jQuery.queue( this[0], type );
1838 }
1839 return this.each(function() {
1840 var queue = jQuery.queue( this, type, data );
1841
1842 if ( type === "fx" && queue[0] !== "inprogress" ) {
1843 jQuery.dequeue( this, type );
1844 }
1845 });
1846 },
1847 dequeue: function( type ) {
1848 return this.each(function() {
1849 jQuery.dequeue( this, type );
1850 });
1851 },
1852 // Based off of the plugin by Clint Helfers, with permission.
1853 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1854 delay: function( time, type ) {
1855 time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
1856 type = type || "fx";
1857
1858 return this.queue( type, function() {
1859 var elem = this;
1860 setTimeout(function() {
1861 jQuery.dequeue( elem, type );
1862 }, time );
1863 });
1864 },
1865 clearQueue: function( type ) {
1866 return this.queue( type || "fx", [] );
1867 },
1868 // Get a promise resolved when queues of a certain type
1869 // are emptied (fx is the type by default)
1870 promise: function( type, object ) {
1871 if ( typeof type !== "string" ) {
1872 object = type;
1873 type = undefined;
1874 }
1875 type = type || "fx";
1876 var defer = jQuery.Deferred(),
1877 elements = this,
1878 i = elements.length,
1879 count = 1,
1880 deferDataKey = type + "defer",
1881 queueDataKey = type + "queue",
1882 markDataKey = type + "mark",
1883 tmp;
1884 function resolve() {
1885 if ( !( --count ) ) {
1886 defer.resolveWith( elements, [ elements ] );
1887 }
1888 }
1889 while( i-- ) {
1890 if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
1891 ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
1892 jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
1893 jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
1894 count++;
1895 tmp.done( resolve );
1896 }
1897 }
1898 resolve();
1899 return defer.promise();
1900 }
1901});
1902
1903
1904
1905
1906var rclass = /[\n\t\r]/g,
1907 rspace = /\s+/,
1908 rreturn = /\r/g,
1909 rtype = /^(?:button|input)$/i,
1910 rfocusable = /^(?:button|input|object|select|textarea)$/i,
1911 rclickable = /^a(?:rea)?$/i,
1912 rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
1913 rinvalidChar = /\:|^on/,
1914 formHook, boolHook;
1915
1916jQuery.fn.extend({
1917 attr: function( name, value ) {
1918 return jQuery.access( this, name, value, true, jQuery.attr );
1919 },
1920
1921 removeAttr: function( name ) {
1922 return this.each(function() {
1923 jQuery.removeAttr( this, name );
1924 });
1925 },
1926
1927 prop: function( name, value ) {
1928 return jQuery.access( this, name, value, true, jQuery.prop );
1929 },
1930
1931 removeProp: function( name ) {
1932 name = jQuery.propFix[ name ] || name;
1933 return this.each(function() {
1934 // try/catch handles cases where IE balks (such as removing a property on window)
1935 try {
1936 this[ name ] = undefined;
1937 delete this[ name ];
1938 } catch( e ) {}
1939 });
1940 },
1941
1942 addClass: function( value ) {
1943 var classNames, i, l, elem,
1944 setClass, c, cl;
1945
1946 if ( jQuery.isFunction( value ) ) {
1947 return this.each(function( j ) {
1948 jQuery( this ).addClass( value.call(this, j, this.className) );
1949 });
1950 }
1951
1952 if ( value && typeof value === "string" ) {
1953 classNames = value.split( rspace );
1954
1955 for ( i = 0, l = this.length; i < l; i++ ) {
1956 elem = this[ i ];
1957
1958 if ( elem.nodeType === 1 ) {
1959 if ( !elem.className && classNames.length === 1 ) {
1960 elem.className = value;
1961
1962 } else {
1963 setClass = " " + elem.className + " ";
1964
1965 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
1966 if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
1967 setClass += classNames[ c ] + " ";
1968 }
1969 }
1970 elem.className = jQuery.trim( setClass );
1971 }
1972 }
1973 }
1974 }
1975
1976 return this;
1977 },
1978
1979 removeClass: function( value ) {
1980 var classNames, i, l, elem, className, c, cl;
1981
1982 if ( jQuery.isFunction( value ) ) {
1983 return this.each(function( j ) {
1984 jQuery( this ).removeClass( value.call(this, j, this.className) );
1985 });
1986 }
1987
1988 if ( (value && typeof value === "string") || value === undefined ) {
1989 classNames = (value || "").split( rspace );
1990
1991 for ( i = 0, l = this.length; i < l; i++ ) {
1992 elem = this[ i ];
1993
1994 if ( elem.nodeType === 1 && elem.className ) {
1995 if ( value ) {
1996 className = (" " + elem.className + " ").replace( rclass, " " );
1997 for ( c = 0, cl = classNames.length; c < cl; c++ ) {
1998 className = className.replace(" " + classNames[ c ] + " ", " ");
1999 }
2000 elem.className = jQuery.trim( className );
2001
2002 } else {
2003 elem.className = "";
2004 }
2005 }
2006 }
2007 }
2008
2009 return this;
2010 },
2011
2012 toggleClass: function( value, stateVal ) {
2013 var type = typeof value,
2014 isBool = typeof stateVal === "boolean";
2015
2016 if ( jQuery.isFunction( value ) ) {
2017 return this.each(function( i ) {
2018 jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
2019 });
2020 }
2021
2022 return this.each(function() {
2023 if ( type === "string" ) {
2024 // toggle individual class names
2025 var className,
2026 i = 0,
2027 self = jQuery( this ),
2028 state = stateVal,
2029 classNames = value.split( rspace );
2030
2031 while ( (className = classNames[ i++ ]) ) {
2032 // check each className given, space seperated list
2033 state = isBool ? state : !self.hasClass( className );
2034 self[ state ? "addClass" : "removeClass" ]( className );
2035 }
2036
2037 } else if ( type === "undefined" || type === "boolean" ) {
2038 if ( this.className ) {
2039 // store className if set
2040 jQuery._data( this, "__className__", this.className );
2041 }
2042
2043 // toggle whole className
2044 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2045 }
2046 });
2047 },
2048
2049 hasClass: function( selector ) {
2050 var className = " " + selector + " ";
2051 for ( var i = 0, l = this.length; i < l; i++ ) {
2052 if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2053 return true;
2054 }
2055 }
2056
2057 return false;
2058 },
2059
2060 val: function( value ) {
2061 var hooks, ret,
2062 elem = this[0];
2063
2064 if ( !arguments.length ) {
2065 if ( elem ) {
2066 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
2067
2068 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2069 return ret;
2070 }
2071
2072 ret = elem.value;
2073
2074 return typeof ret === "string" ?
2075 // handle most common string cases
2076 ret.replace(rreturn, "") :
2077 // handle cases where value is null/undef or number
2078 ret == null ? "" : ret;
2079 }
2080
2081 return undefined;
2082 }
2083
2084 var isFunction = jQuery.isFunction( value );
2085
2086 return this.each(function( i ) {
2087 var self = jQuery(this), val;
2088
2089 if ( this.nodeType !== 1 ) {
2090 return;
2091 }
2092
2093 if ( isFunction ) {
2094 val = value.call( this, i, self.val() );
2095 } else {
2096 val = value;
2097 }
2098
2099 // Treat null/undefined as ""; convert numbers to string
2100 if ( val == null ) {
2101 val = "";
2102 } else if ( typeof val === "number" ) {
2103 val += "";
2104 } else if ( jQuery.isArray( val ) ) {
2105 val = jQuery.map(val, function ( value ) {
2106 return value == null ? "" : value + "";
2107 });
2108 }
2109
2110 hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
2111
2112 // If set returns undefined, fall back to normal setting
2113 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
2114 this.value = val;
2115 }
2116 });
2117 }
2118});
2119
2120jQuery.extend({
2121 valHooks: {
2122 option: {
2123 get: function( elem ) {
2124 // attributes.value is undefined in Blackberry 4.7 but
2125 // uses .value. See #6932
2126 var val = elem.attributes.value;
2127 return !val || val.specified ? elem.value : elem.text;
2128 }
2129 },
2130 select: {
2131 get: function( elem ) {
2132 var value,
2133 index = elem.selectedIndex,
2134 values = [],
2135 options = elem.options,
2136 one = elem.type === "select-one";
2137
2138 // Nothing was selected
2139 if ( index < 0 ) {
2140 return null;
2141 }
2142
2143 // Loop through all the selected options
2144 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
2145 var option = options[ i ];
2146
2147 // Don't return options that are disabled or in a disabled optgroup
2148 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
2149 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
2150
2151 // Get the specific value for the option
2152 value = jQuery( option ).val();
2153
2154 // We don't need an array for one selects
2155 if ( one ) {
2156 return value;
2157 }
2158
2159 // Multi-Selects return an array
2160 values.push( value );
2161 }
2162 }
2163
2164 // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
2165 if ( one && !values.length && options.length ) {
2166 return jQuery( options[ index ] ).val();
2167 }
2168
2169 return values;
2170 },
2171
2172 set: function( elem, value ) {
2173 var values = jQuery.makeArray( value );
2174
2175 jQuery(elem).find("option").each(function() {
2176 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2177 });
2178
2179 if ( !values.length ) {
2180 elem.selectedIndex = -1;
2181 }
2182 return values;
2183 }
2184 }
2185 },
2186
2187 attrFn: {
2188 val: true,
2189 css: true,
2190 html: true,
2191 text: true,
2192 data: true,
2193 width: true,
2194 height: true,
2195 offset: true
2196 },
2197
2198 attrFix: {
2199 // Always normalize to ensure hook usage
2200 tabindex: "tabIndex"
2201 },
2202
2203 attr: function( elem, name, value, pass ) {
2204 var nType = elem.nodeType;
2205
2206 // don't get/set attributes on text, comment and attribute nodes
2207 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2208 return undefined;
2209 }
2210
2211 if ( pass && name in jQuery.attrFn ) {
2212 return jQuery( elem )[ name ]( value );
2213 }
2214
2215 // Fallback to prop when attributes are not supported
2216 if ( !("getAttribute" in elem) ) {
2217 return jQuery.prop( elem, name, value );
2218 }
2219
2220 var ret, hooks,
2221 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2222
2223 // Normalize the name if needed
2224 if ( notxml ) {
2225 name = jQuery.attrFix[ name ] || name;
2226
2227 hooks = jQuery.attrHooks[ name ];
2228
2229 if ( !hooks ) {
2230 // Use boolHook for boolean attributes
2231 if ( rboolean.test( name ) ) {
2232
2233 hooks = boolHook;
2234
2235 // Use formHook for forms and if the name contains certain characters
2236 } else if ( formHook && name !== "className" &&
2237 (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) {
2238
2239 hooks = formHook;
2240 }
2241 }
2242 }
2243
2244 if ( value !== undefined ) {
2245
2246 if ( value === null ) {
2247 jQuery.removeAttr( elem, name );
2248 return undefined;
2249
2250 } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
2251 return ret;
2252
2253 } else {
2254 elem.setAttribute( name, "" + value );
2255 return value;
2256 }
2257
2258 } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
2259 return ret;
2260
2261 } else {
2262
2263 ret = elem.getAttribute( name );
2264
2265 // Non-existent attributes return null, we normalize to undefined
2266 return ret === null ?
2267 undefined :
2268 ret;
2269 }
2270 },
2271
2272 removeAttr: function( elem, name ) {
2273 var propName;
2274 if ( elem.nodeType === 1 ) {
2275 name = jQuery.attrFix[ name ] || name;
2276
2277 if ( jQuery.support.getSetAttribute ) {
2278 // Use removeAttribute in browsers that support it
2279 elem.removeAttribute( name );
2280 } else {
2281 jQuery.attr( elem, name, "" );
2282 elem.removeAttributeNode( elem.getAttributeNode( name ) );
2283 }
2284
2285 // Set corresponding property to false for boolean attributes
2286 if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) {
2287 elem[ propName ] = false;
2288 }
2289 }
2290 },
2291
2292 attrHooks: {
2293 type: {
2294 set: function( elem, value ) {
2295 // We can't allow the type property to be changed (since it causes problems in IE)
2296 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
2297 jQuery.error( "type property can't be changed" );
2298 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2299 // Setting the type on a radio button after the value resets the value in IE6-9
2300 // Reset value to it's default in case type is set after value
2301 // This is for element creation
2302 var val = elem.value;
2303 elem.setAttribute( "type", value );
2304 if ( val ) {
2305 elem.value = val;
2306 }
2307 return value;
2308 }
2309 }
2310 },
2311 tabIndex: {
2312 get: function( elem ) {
2313 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2314 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2315 var attributeNode = elem.getAttributeNode("tabIndex");
2316
2317 return attributeNode && attributeNode.specified ?
2318 parseInt( attributeNode.value, 10 ) :
2319 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2320 0 :
2321 undefined;
2322 }
2323 },
2324 // Use the value property for back compat
2325 // Use the formHook for button elements in IE6/7 (#1954)
2326 value: {
2327 get: function( elem, name ) {
2328 if ( formHook && jQuery.nodeName( elem, "button" ) ) {
2329 return formHook.get( elem, name );
2330 }
2331 return name in elem ?
2332 elem.value :
2333 null;
2334 },
2335 set: function( elem, value, name ) {
2336 if ( formHook && jQuery.nodeName( elem, "button" ) ) {
2337 return formHook.set( elem, value, name );
2338 }
2339 // Does not return so that setAttribute is also used
2340 elem.value = value;
2341 }
2342 }
2343 },
2344
2345 propFix: {
2346 tabindex: "tabIndex",
2347 readonly: "readOnly",
2348 "for": "htmlFor",
2349 "class": "className",
2350 maxlength: "maxLength",
2351 cellspacing: "cellSpacing",
2352 cellpadding: "cellPadding",
2353 rowspan: "rowSpan",
2354 colspan: "colSpan",
2355 usemap: "useMap",
2356 frameborder: "frameBorder",
2357 contenteditable: "contentEditable"
2358 },
2359
2360 prop: function( elem, name, value ) {
2361 var nType = elem.nodeType;
2362
2363 // don't get/set properties on text, comment and attribute nodes
2364 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2365 return undefined;
2366 }
2367
2368 var ret, hooks,
2369 notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2370
2371 if ( notxml ) {
2372 // Fix name and attach hooks
2373 name = jQuery.propFix[ name ] || name;
2374 hooks = jQuery.propHooks[ name ];
2375 }
2376
2377 if ( value !== undefined ) {
2378 if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
2379 return ret;
2380
2381 } else {
2382 return (elem[ name ] = value);
2383 }
2384
2385 } else {
2386 if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
2387 return ret;
2388
2389 } else {
2390 return elem[ name ];
2391 }
2392 }
2393 },
2394
2395 propHooks: {}
2396});
2397
2398// Hook for boolean attributes
2399boolHook = {
2400 get: function( elem, name ) {
2401 // Align boolean attributes with corresponding properties
2402 return jQuery.prop( elem, name ) ?
2403 name.toLowerCase() :
2404 undefined;
2405 },
2406 set: function( elem, value, name ) {
2407 var propName;
2408 if ( value === false ) {
2409 // Remove boolean attributes when set to false
2410 jQuery.removeAttr( elem, name );
2411 } else {
2412 // value is true since we know at this point it's type boolean and not false
2413 // Set boolean attributes to the same name and set the DOM property
2414 propName = jQuery.propFix[ name ] || name;
2415 if ( propName in elem ) {
2416 // Only set the IDL specifically if it already exists on the element
2417 elem[ propName ] = true;
2418 }
2419
2420 elem.setAttribute( name, name.toLowerCase() );
2421 }
2422 return name;
2423 }
2424};
2425
2426// IE6/7 do not support getting/setting some attributes with get/setAttribute
2427if ( !jQuery.support.getSetAttribute ) {
2428
2429 // propFix is more comprehensive and contains all fixes
2430 jQuery.attrFix = jQuery.propFix;
2431
2432 // Use this for any attribute on a form in IE6/7
2433 formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = {
2434 get: function( elem, name ) {
2435 var ret;
2436 ret = elem.getAttributeNode( name );
2437 // Return undefined if nodeValue is empty string
2438 return ret && ret.nodeValue !== "" ?
2439 ret.nodeValue :
2440 undefined;
2441 },
2442 set: function( elem, value, name ) {
2443 // Check form objects in IE (multiple bugs related)
2444 // Only use nodeValue if the attribute node exists on the form
2445 var ret = elem.getAttributeNode( name );
2446 if ( ret ) {
2447 ret.nodeValue = value;
2448 return value;
2449 }
2450 }
2451 };
2452
2453 // Set width and height to auto instead of 0 on empty string( Bug #8150 )
2454 // This is for removals
2455 jQuery.each([ "width", "height" ], function( i, name ) {
2456 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2457 set: function( elem, value ) {
2458 if ( value === "" ) {
2459 elem.setAttribute( name, "auto" );
2460 return value;
2461 }
2462 }
2463 });
2464 });
2465}
2466
2467
2468// Some attributes require a special call on IE
2469if ( !jQuery.support.hrefNormalized ) {
2470 jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
2471 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
2472 get: function( elem ) {
2473 var ret = elem.getAttribute( name, 2 );
2474 return ret === null ? undefined : ret;
2475 }
2476 });
2477 });
2478}
2479
2480if ( !jQuery.support.style ) {
2481 jQuery.attrHooks.style = {
2482 get: function( elem ) {
2483 // Return undefined in the case of empty string
2484 // Normalize to lowercase since IE uppercases css property names
2485 return elem.style.cssText.toLowerCase() || undefined;
2486 },
2487 set: function( elem, value ) {
2488 return (elem.style.cssText = "" + value);
2489 }
2490 };
2491}
2492
2493// Safari mis-reports the default selected property of an option
2494// Accessing the parent's selectedIndex property fixes it
2495if ( !jQuery.support.optSelected ) {
2496 jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
2497 get: function( elem ) {
2498 var parent = elem.parentNode;
2499
2500 if ( parent ) {
2501 parent.selectedIndex;
2502
2503 // Make sure that it also works with optgroups, see #5701
2504 if ( parent.parentNode ) {
2505 parent.parentNode.selectedIndex;
2506 }
2507 }
2508 }
2509 });
2510}
2511
2512// Radios and checkboxes getter/setter
2513if ( !jQuery.support.checkOn ) {
2514 jQuery.each([ "radio", "checkbox" ], function() {
2515 jQuery.valHooks[ this ] = {
2516 get: function( elem ) {
2517 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
2518 return elem.getAttribute("value") === null ? "on" : elem.value;
2519 }
2520 };
2521 });
2522}
2523jQuery.each([ "radio", "checkbox" ], function() {
2524 jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
2525 set: function( elem, value ) {
2526 if ( jQuery.isArray( value ) ) {
2527 return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);
2528 }
2529 }
2530 });
2531});
2532
2533
2534
2535
2536var rnamespaces = /\.(.*)$/,
2537 rformElems = /^(?:textarea|input|select)$/i,
2538 rperiod = /\./g,
2539 rspaces = / /g,
2540 rescape = /[^\w\s.|`]/g,
2541 fcleanup = function( nm ) {
2542 return nm.replace(rescape, "\\$&");
2543 };
2544
2545/*
2546 * A number of helper functions used for managing events.
2547 * Many of the ideas behind this code originated from
2548 * Dean Edwards' addEvent library.
2549 */
2550jQuery.event = {
2551
2552 // Bind an event to an element
2553 // Original by Dean Edwards
2554 add: function( elem, types, handler, data ) {
2555 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2556 return;
2557 }
2558
2559 if ( handler === false ) {
2560 handler = returnFalse;
2561 } else if ( !handler ) {
2562 // Fixes bug #7229. Fix recommended by jdalton
2563 return;
2564 }
2565
2566 var handleObjIn, handleObj;
2567
2568 if ( handler.handler ) {
2569 handleObjIn = handler;
2570 handler = handleObjIn.handler;
2571 }
2572
2573 // Make sure that the function being executed has a unique ID
2574 if ( !handler.guid ) {
2575 handler.guid = jQuery.guid++;
2576 }
2577
2578 // Init the element's event structure
2579 var elemData = jQuery._data( elem );
2580
2581 // If no elemData is found then we must be trying to bind to one of the
2582 // banned noData elements
2583 if ( !elemData ) {
2584 return;
2585 }
2586
2587 var events = elemData.events,
2588 eventHandle = elemData.handle;
2589
2590 if ( !events ) {
2591 elemData.events = events = {};
2592 }
2593
2594 if ( !eventHandle ) {
2595 elemData.handle = eventHandle = function( e ) {
2596 // Discard the second event of a jQuery.event.trigger() and
2597 // when an event is called after a page has unloaded
2598 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
2599 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
2600 undefined;
2601 };
2602 }
2603
2604 // Add elem as a property of the handle function
2605 // This is to prevent a memory leak with non-native events in IE.
2606 eventHandle.elem = elem;
2607
2608 // Handle multiple events separated by a space
2609 // jQuery(...).bind("mouseover mouseout", fn);
2610 types = types.split(" ");
2611
2612 var type, i = 0, namespaces;
2613
2614 while ( (type = types[ i++ ]) ) {
2615 handleObj = handleObjIn ?
2616 jQuery.extend({}, handleObjIn) :
2617 { handler: handler, data: data };
2618
2619 // Namespaced event handlers
2620 if ( type.indexOf(".") > -1 ) {
2621 namespaces = type.split(".");
2622 type = namespaces.shift();
2623 handleObj.namespace = namespaces.slice(0).sort().join(".");
2624
2625 } else {
2626 namespaces = [];
2627 handleObj.namespace = "";
2628 }
2629
2630 handleObj.type = type;
2631 if ( !handleObj.guid ) {
2632 handleObj.guid = handler.guid;
2633 }
2634
2635 // Get the current list of functions bound to this event
2636 var handlers = events[ type ],
2637 special = jQuery.event.special[ type ] || {};
2638
2639 // Init the event handler queue
2640 if ( !handlers ) {
2641 handlers = events[ type ] = [];
2642
2643 // Check for a special event handler
2644 // Only use addEventListener/attachEvent if the special
2645 // events handler returns false
2646 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2647 // Bind the global event handler to the element
2648 if ( elem.addEventListener ) {
2649 elem.addEventListener( type, eventHandle, false );
2650
2651 } else if ( elem.attachEvent ) {
2652 elem.attachEvent( "on" + type, eventHandle );
2653 }
2654 }
2655 }
2656
2657 if ( special.add ) {
2658 special.add.call( elem, handleObj );
2659
2660 if ( !handleObj.handler.guid ) {
2661 handleObj.handler.guid = handler.guid;
2662 }
2663 }
2664
2665 // Add the function to the element's handler list
2666 handlers.push( handleObj );
2667
2668 // Keep track of which events have been used, for event optimization
2669 jQuery.event.global[ type ] = true;
2670 }
2671
2672 // Nullify elem to prevent memory leaks in IE
2673 elem = null;
2674 },
2675
2676 global: {},
2677
2678 // Detach an event or set of events from an element
2679 remove: function( elem, types, handler, pos ) {
2680 // don't do events on text and comment nodes
2681 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2682 return;
2683 }
2684
2685 if ( handler === false ) {
2686 handler = returnFalse;
2687 }
2688
2689 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
2690 elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
2691 events = elemData && elemData.events;
2692
2693 if ( !elemData || !events ) {
2694 return;
2695 }
2696
2697 // types is actually an event object here
2698 if ( types && types.type ) {
2699 handler = types.handler;
2700 types = types.type;
2701 }
2702
2703 // Unbind all events for the element
2704 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
2705 types = types || "";
2706
2707 for ( type in events ) {
2708 jQuery.event.remove( elem, type + types );
2709 }
2710
2711 return;
2712 }
2713
2714 // Handle multiple events separated by a space
2715 // jQuery(...).unbind("mouseover mouseout", fn);
2716 types = types.split(" ");
2717
2718 while ( (type = types[ i++ ]) ) {
2719 origType = type;
2720 handleObj = null;
2721 all = type.indexOf(".") < 0;
2722 namespaces = [];
2723
2724 if ( !all ) {
2725 // Namespaced event handlers
2726 namespaces = type.split(".");
2727 type = namespaces.shift();
2728
2729 namespace = new RegExp("(^|\\.)" +
2730 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
2731 }
2732
2733 eventType = events[ type ];
2734
2735 if ( !eventType ) {
2736 continue;
2737 }
2738
2739 if ( !handler ) {
2740 for ( j = 0; j < eventType.length; j++ ) {
2741 handleObj = eventType[ j ];
2742
2743 if ( all || namespace.test( handleObj.namespace ) ) {
2744 jQuery.event.remove( elem, origType, handleObj.handler, j );
2745 eventType.splice( j--, 1 );
2746 }
2747 }
2748
2749 continue;
2750 }
2751
2752 special = jQuery.event.special[ type ] || {};
2753
2754 for ( j = pos || 0; j < eventType.length; j++ ) {
2755 handleObj = eventType[ j ];
2756
2757 if ( handler.guid === handleObj.guid ) {
2758 // remove the given handler for the given type
2759 if ( all || namespace.test( handleObj.namespace ) ) {
2760 if ( pos == null ) {
2761 eventType.splice( j--, 1 );
2762 }
2763
2764 if ( special.remove ) {
2765 special.remove.call( elem, handleObj );
2766 }
2767 }
2768
2769 if ( pos != null ) {
2770 break;
2771 }
2772 }
2773 }
2774
2775 // remove generic event handler if no more handlers exist
2776 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
2777 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
2778 jQuery.removeEvent( elem, type, elemData.handle );
2779 }
2780
2781 ret = null;
2782 delete events[ type ];
2783 }
2784 }
2785
2786 // Remove the expando if it's no longer used
2787 if ( jQuery.isEmptyObject( events ) ) {
2788 var handle = elemData.handle;
2789 if ( handle ) {
2790 handle.elem = null;
2791 }
2792
2793 delete elemData.events;
2794 delete elemData.handle;
2795
2796 if ( jQuery.isEmptyObject( elemData ) ) {
2797 jQuery.removeData( elem, undefined, true );
2798 }
2799 }
2800 },
2801
2802 // Events that are safe to short-circuit if no handlers are attached.
2803 // Native DOM events should not be added, they may have inline handlers.
2804 customEvent: {
2805 "getData": true,
2806 "setData": true,
2807 "changeData": true
2808 },
2809
2810 trigger: function( event, data, elem, onlyHandlers ) {
2811 // Event object or event type
2812 var type = event.type || event,
2813 namespaces = [],
2814 exclusive;
2815
2816 if ( type.indexOf("!") >= 0 ) {
2817 // Exclusive events trigger only for the exact event (no namespaces)
2818 type = type.slice(0, -1);
2819 exclusive = true;
2820 }
2821
2822 if ( type.indexOf(".") >= 0 ) {
2823 // Namespaced trigger; create a regexp to match event type in handle()
2824 namespaces = type.split(".");
2825 type = namespaces.shift();
2826 namespaces.sort();
2827 }
2828
2829 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
2830 // No jQuery handlers for this event type, and it can't have inline handlers
2831 return;
2832 }
2833
2834 // Caller can pass in an Event, Object, or just an event type string
2835 event = typeof event === "object" ?
2836 // jQuery.Event object
2837 event[ jQuery.expando ] ? event :
2838 // Object literal
2839 new jQuery.Event( type, event ) :
2840 // Just the event type (string)
2841 new jQuery.Event( type );
2842
2843 event.type = type;
2844 event.exclusive = exclusive;
2845 event.namespace = namespaces.join(".");
2846 event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)");
2847
2848 // triggerHandler() and global events don't bubble or run the default action
2849 if ( onlyHandlers || !elem ) {
2850 event.preventDefault();
2851 event.stopPropagation();
2852 }
2853
2854 // Handle a global trigger
2855 if ( !elem ) {
2856 // TODO: Stop taunting the data cache; remove global events and always attach to document
2857 jQuery.each( jQuery.cache, function() {
2858 // internalKey variable is just used to make it easier to find
2859 // and potentially change this stuff later; currently it just
2860 // points to jQuery.expando
2861 var internalKey = jQuery.expando,
2862 internalCache = this[ internalKey ];
2863 if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
2864 jQuery.event.trigger( event, data, internalCache.handle.elem );
2865 }
2866 });
2867 return;
2868 }
2869
2870 // Don't do events on text and comment nodes
2871 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2872 return;
2873 }
2874
2875 // Clean up the event in case it is being reused
2876 event.result = undefined;
2877 event.target = elem;
2878
2879 // Clone any incoming data and prepend the event, creating the handler arg list
2880 data = data != null ? jQuery.makeArray( data ) : [];
2881 data.unshift( event );
2882
2883 var cur = elem,
2884 // IE doesn't like method names with a colon (#3533, #8272)
2885 ontype = type.indexOf(":") < 0 ? "on" + type : "";
2886
2887 // Fire event on the current element, then bubble up the DOM tree
2888 do {
2889 var handle = jQuery._data( cur, "handle" );
2890
2891 event.currentTarget = cur;
2892 if ( handle ) {
2893 handle.apply( cur, data );
2894 }
2895
2896 // Trigger an inline bound script
2897 if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {
2898 event.result = false;
2899 event.preventDefault();
2900 }
2901
2902 // Bubble up to document, then to window
2903 cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;
2904 } while ( cur && !event.isPropagationStopped() );
2905
2906 // If nobody prevented the default action, do it now
2907 if ( !event.isDefaultPrevented() ) {
2908 var old,
2909 special = jQuery.event.special[ type ] || {};
2910
2911 if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&
2912 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
2913
2914 // Call a native DOM method on the target with the same name name as the event.
2915 // Can't use an .isFunction)() check here because IE6/7 fails that test.
2916 // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.
2917 try {
2918 if ( ontype && elem[ type ] ) {
2919 // Don't re-trigger an onFOO event when we call its FOO() method
2920 old = elem[ ontype ];
2921
2922 if ( old ) {
2923 elem[ ontype ] = null;
2924 }
2925
2926 jQuery.event.triggered = type;
2927 elem[ type ]();
2928 }
2929 } catch ( ieError ) {}
2930
2931 if ( old ) {
2932 elem[ ontype ] = old;
2933 }
2934
2935 jQuery.event.triggered = undefined;
2936 }
2937 }
2938
2939 return event.result;
2940 },
2941
2942 handle: function( event ) {
2943 event = jQuery.event.fix( event || window.event );
2944 // Snapshot the handlers list since a called handler may add/remove events.
2945 var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0),
2946 run_all = !event.exclusive && !event.namespace,
2947 args = Array.prototype.slice.call( arguments, 0 );
2948
2949 // Use the fix-ed Event rather than the (read-only) native event
2950 args[0] = event;
2951 event.currentTarget = this;
2952
2953 for ( var j = 0, l = handlers.length; j < l; j++ ) {
2954 var handleObj = handlers[ j ];
2955
2956 // Triggered event must 1) be non-exclusive and have no namespace, or
2957 // 2) have namespace(s) a subset or equal to those in the bound event.
2958 if ( run_all || event.namespace_re.test( handleObj.namespace ) ) {
2959 // Pass in a reference to the handler function itself
2960 // So that we can later remove it
2961 event.handler = handleObj.handler;
2962 event.data = handleObj.data;
2963 event.handleObj = handleObj;
2964
2965 var ret = handleObj.handler.apply( this, args );
2966
2967 if ( ret !== undefined ) {
2968 event.result = ret;
2969 if ( ret === false ) {
2970 event.preventDefault();
2971 event.stopPropagation();
2972 }
2973 }
2974
2975 if ( event.isImmediatePropagationStopped() ) {
2976 break;
2977 }
2978 }
2979 }
2980 return event.result;
2981 },
2982
2983 props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
2984
2985 fix: function( event ) {
2986 if ( event[ jQuery.expando ] ) {
2987 return event;
2988 }
2989
2990 // store a copy of the original event object
2991 // and "clone" to set read-only properties
2992 var originalEvent = event;
2993 event = jQuery.Event( originalEvent );
2994
2995 for ( var i = this.props.length, prop; i; ) {
2996 prop = this.props[ --i ];
2997 event[ prop ] = originalEvent[ prop ];
2998 }
2999
3000 // Fix target property, if necessary
3001 if ( !event.target ) {
3002 // Fixes #1925 where srcElement might not be defined either
3003 event.target = event.srcElement || document;
3004 }
3005
3006 // check if target is a textnode (safari)
3007 if ( event.target.nodeType === 3 ) {
3008 event.target = event.target.parentNode;
3009 }
3010
3011 // Add relatedTarget, if necessary
3012 if ( !event.relatedTarget && event.fromElement ) {
3013 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
3014 }
3015
3016 // Calculate pageX/Y if missing and clientX/Y available
3017 if ( event.pageX == null && event.clientX != null ) {
3018 var eventDocument = event.target.ownerDocument || document,
3019 doc = eventDocument.documentElement,
3020 body = eventDocument.body;
3021
3022 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
3023 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
3024 }
3025
3026 // Add which for key events
3027 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
3028 event.which = event.charCode != null ? event.charCode : event.keyCode;
3029 }
3030
3031 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
3032 if ( !event.metaKey && event.ctrlKey ) {
3033 event.metaKey = event.ctrlKey;
3034 }
3035
3036 // Add which for click: 1 === left; 2 === middle; 3 === right
3037 // Note: button is not normalized, so don't use it
3038 if ( !event.which && event.button !== undefined ) {
3039 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
3040 }
3041
3042 return event;
3043 },
3044
3045 // Deprecated, use jQuery.guid instead
3046 guid: 1E8,
3047
3048 // Deprecated, use jQuery.proxy instead
3049 proxy: jQuery.proxy,
3050
3051 special: {
3052 ready: {
3053 // Make sure the ready event is setup
3054 setup: jQuery.bindReady,
3055 teardown: jQuery.noop
3056 },
3057
3058 live: {
3059 add: function( handleObj ) {
3060 jQuery.event.add( this,
3061 liveConvert( handleObj.origType, handleObj.selector ),
3062 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
3063 },
3064
3065 remove: function( handleObj ) {
3066 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
3067 }
3068 },
3069
3070 beforeunload: {
3071 setup: function( data, namespaces, eventHandle ) {
3072 // We only want to do this special case on windows
3073 if ( jQuery.isWindow( this ) ) {
3074 this.onbeforeunload = eventHandle;
3075 }
3076 },
3077
3078 teardown: function( namespaces, eventHandle ) {
3079 if ( this.onbeforeunload === eventHandle ) {
3080 this.onbeforeunload = null;
3081 }
3082 }
3083 }
3084 }
3085};
3086
3087jQuery.removeEvent = document.removeEventListener ?
3088 function( elem, type, handle ) {
3089 if ( elem.removeEventListener ) {
3090 elem.removeEventListener( type, handle, false );
3091 }
3092 } :
3093 function( elem, type, handle ) {
3094 if ( elem.detachEvent ) {
3095 elem.detachEvent( "on" + type, handle );
3096 }
3097 };
3098
3099jQuery.Event = function( src, props ) {
3100 // Allow instantiation without the 'new' keyword
3101 if ( !this.preventDefault ) {
3102 return new jQuery.Event( src, props );
3103 }
3104
3105 // Event object
3106 if ( src && src.type ) {
3107 this.originalEvent = src;
3108 this.type = src.type;
3109
3110 // Events bubbling up the document may have been marked as prevented
3111 // by a handler lower down the tree; reflect the correct value.
3112 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
3113 src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
3114
3115 // Event type
3116 } else {
3117 this.type = src;
3118 }
3119
3120 // Put explicitly provided properties onto the event object
3121 if ( props ) {
3122 jQuery.extend( this, props );
3123 }
3124
3125 // timeStamp is buggy for some events on Firefox(#3843)
3126 // So we won't rely on the native value
3127 this.timeStamp = jQuery.now();
3128
3129 // Mark it as fixed
3130 this[ jQuery.expando ] = true;
3131};
3132
3133function returnFalse() {
3134 return false;
3135}
3136function returnTrue() {
3137 return true;
3138}
3139
3140// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3141// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3142jQuery.Event.prototype = {
3143 preventDefault: function() {
3144 this.isDefaultPrevented = returnTrue;
3145
3146 var e = this.originalEvent;
3147 if ( !e ) {
3148 return;
3149 }
3150
3151 // if preventDefault exists run it on the original event
3152 if ( e.preventDefault ) {
3153 e.preventDefault();
3154
3155 // otherwise set the returnValue property of the original event to false (IE)
3156 } else {
3157 e.returnValue = false;
3158 }
3159 },
3160 stopPropagation: function() {
3161 this.isPropagationStopped = returnTrue;
3162
3163 var e = this.originalEvent;
3164 if ( !e ) {
3165 return;
3166 }
3167 // if stopPropagation exists run it on the original event
3168 if ( e.stopPropagation ) {
3169 e.stopPropagation();
3170 }
3171 // otherwise set the cancelBubble property of the original event to true (IE)
3172 e.cancelBubble = true;
3173 },
3174 stopImmediatePropagation: function() {
3175 this.isImmediatePropagationStopped = returnTrue;
3176 this.stopPropagation();
3177 },
3178 isDefaultPrevented: returnFalse,
3179 isPropagationStopped: returnFalse,
3180 isImmediatePropagationStopped: returnFalse
3181};
3182
3183// Checks if an event happened on an element within another element
3184// Used in jQuery.event.special.mouseenter and mouseleave handlers
3185var withinElement = function( event ) {
3186
3187 // Check if mouse(over|out) are still within the same parent element
3188 var related = event.relatedTarget,
3189 inside = false,
3190 eventType = event.type;
3191
3192 event.type = event.data;
3193
3194 if ( related !== this ) {
3195
3196 if ( related ) {
3197 inside = jQuery.contains( this, related );
3198 }
3199
3200 if ( !inside ) {
3201
3202 jQuery.event.handle.apply( this, arguments );
3203
3204 event.type = eventType;
3205 }
3206 }
3207},
3208
3209// In case of event delegation, we only need to rename the event.type,
3210// liveHandler will take care of the rest.
3211delegate = function( event ) {
3212 event.type = event.data;
3213 jQuery.event.handle.apply( this, arguments );
3214};
3215
3216// Create mouseenter and mouseleave events
3217jQuery.each({
3218 mouseenter: "mouseover",
3219 mouseleave: "mouseout"
3220}, function( orig, fix ) {
3221 jQuery.event.special[ orig ] = {
3222 setup: function( data ) {
3223 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
3224 },
3225 teardown: function( data ) {
3226 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
3227 }
3228 };
3229});
3230
3231// submit delegation
3232if ( !jQuery.support.submitBubbles ) {
3233
3234 jQuery.event.special.submit = {
3235 setup: function( data, namespaces ) {
3236 if ( !jQuery.nodeName( this, "form" ) ) {
3237 jQuery.event.add(this, "click.specialSubmit", function( e ) {
3238 var elem = e.target,
3239 type = elem.type;
3240
3241 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
3242 trigger( "submit", this, arguments );
3243 }
3244 });
3245
3246 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
3247 var elem = e.target,
3248 type = elem.type;
3249
3250 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
3251 trigger( "submit", this, arguments );
3252 }
3253 });
3254
3255 } else {
3256 return false;
3257 }
3258 },
3259
3260 teardown: function( namespaces ) {
3261 jQuery.event.remove( this, ".specialSubmit" );
3262 }
3263 };
3264
3265}
3266
3267// change delegation, happens here so we have bind.
3268if ( !jQuery.support.changeBubbles ) {
3269
3270 var changeFilters,
3271
3272 getVal = function( elem ) {
3273 var type = elem.type, val = elem.value;
3274
3275 if ( type === "radio" || type === "checkbox" ) {
3276 val = elem.checked;
3277
3278 } else if ( type === "select-multiple" ) {
3279 val = elem.selectedIndex > -1 ?
3280 jQuery.map( elem.options, function( elem ) {
3281 return elem.selected;
3282 }).join("-") :
3283 "";
3284
3285 } else if ( jQuery.nodeName( elem, "select" ) ) {
3286 val = elem.selectedIndex;
3287 }
3288
3289 return val;
3290 },
3291
3292 testChange = function testChange( e ) {
3293 var elem = e.target, data, val;
3294
3295 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
3296 return;
3297 }
3298
3299 data = jQuery._data( elem, "_change_data" );
3300 val = getVal(elem);
3301
3302 // the current data will be also retrieved by beforeactivate
3303 if ( e.type !== "focusout" || elem.type !== "radio" ) {
3304 jQuery._data( elem, "_change_data", val );
3305 }
3306
3307 if ( data === undefined || val === data ) {
3308 return;
3309 }
3310
3311 if ( data != null || val ) {
3312 e.type = "change";
3313 e.liveFired = undefined;
3314 jQuery.event.trigger( e, arguments[1], elem );
3315 }
3316 };
3317
3318 jQuery.event.special.change = {
3319 filters: {
3320 focusout: testChange,
3321
3322 beforedeactivate: testChange,
3323
3324 click: function( e ) {
3325 var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
3326
3327 if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) {
3328 testChange.call( this, e );
3329 }
3330 },
3331
3332 // Change has to be called before submit
3333 // Keydown will be called before keypress, which is used in submit-event delegation
3334 keydown: function( e ) {
3335 var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
3336
3337 if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) ||
3338 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
3339 type === "select-multiple" ) {
3340 testChange.call( this, e );
3341 }
3342 },
3343
3344 // Beforeactivate happens also before the previous element is blurred
3345 // with this event you can't trigger a change event, but you can store
3346 // information
3347 beforeactivate: function( e ) {
3348 var elem = e.target;
3349 jQuery._data( elem, "_change_data", getVal(elem) );
3350 }
3351 },
3352
3353 setup: function( data, namespaces ) {
3354 if ( this.type === "file" ) {
3355 return false;
3356 }
3357
3358 for ( var type in changeFilters ) {
3359 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
3360 }
3361
3362 return rformElems.test( this.nodeName );
3363 },
3364
3365 teardown: function( namespaces ) {
3366 jQuery.event.remove( this, ".specialChange" );
3367
3368 return rformElems.test( this.nodeName );
3369 }
3370 };
3371
3372 changeFilters = jQuery.event.special.change.filters;
3373
3374 // Handle when the input is .focus()'d
3375 changeFilters.focus = changeFilters.beforeactivate;
3376}
3377
3378function trigger( type, elem, args ) {
3379 // Piggyback on a donor event to simulate a different one.
3380 // Fake originalEvent to avoid donor's stopPropagation, but if the
3381 // simulated event prevents default then we do the same on the donor.
3382 // Don't pass args or remember liveFired; they apply to the donor event.
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches