Merge lp:~fougner/ubuntu-packaging-guide/retheming into lp:ubuntu-packaging-guide

Proposed by Alexander Fougner
Status: Superseded
Proposed branch: lp:~fougner/ubuntu-packaging-guide/retheming
Merge into: lp:ubuntu-packaging-guide
Diff against target: 11864 lines (+11703/-2)
26 files modified
BORROWED-CODE (+7/-0)
conf.py (+2/-2)
debian/copyright (+41/-0)
themes/ubuntu/defindex.html (+35/-0)
themes/ubuntu/domainindex.html (+57/-0)
themes/ubuntu/genindex-single.html (+48/-0)
themes/ubuntu/genindex-split.html (+41/-0)
themes/ubuntu/genindex.html (+59/-0)
themes/ubuntu/globaltoc.html (+11/-0)
themes/ubuntu/layout.html (+224/-0)
themes/ubuntu/localtoc.html (+13/-0)
themes/ubuntu/opensearch.xml (+10/-0)
themes/ubuntu/page.html (+13/-0)
themes/ubuntu/relations.html (+19/-0)
themes/ubuntu/search.html (+56/-0)
themes/ubuntu/searchbox.html (+24/-0)
themes/ubuntu/sourcelink.html (+16/-0)
themes/ubuntu/static/default.css_t (+56/-0)
themes/ubuntu/static/doctools.js (+247/-0)
themes/ubuntu/static/jquery.js (+8176/-0)
themes/ubuntu/static/light-django-theme.css (+1265/-0)
themes/ubuntu/static/newstyle.css (+592/-0)
themes/ubuntu/static/searchtools.js (+518/-0)
themes/ubuntu/static/sidebar.js (+148/-0)
themes/ubuntu/static/underscore.js (+16/-0)
themes/ubuntu/theme.conf (+9/-0)
To merge this branch: bzr merge lp:~fougner/ubuntu-packaging-guide/retheming
Reviewer Review Type Date Requested Status
Iain Lane Needs Fixing
Review via email: mp+67513@code.launchpad.net

This proposal has been superseded by a proposal from 2011-07-22.

Description of the change

more Ubuntu-ish Sphinx theme!

To post a comment you must log in.
Revision history for this message
Daniel Holbach (dholbach) wrote :

The diff is not as bad as it looks. I'm quite happy with the changes (for a first start with the retheming). I would like to get somebody else's opinion though.

 - daniel@miyazaki:~$ wget -q http://loco.ubuntu.com/media/css/newstyle.css
   daniel@miyazaki:~$ diff -u newstyle.css bzr/ubuntu-packaging-guide.retheming/themes/ubuntu/static/newstyle.css
   daniel@miyazaki:~$

 - Actual theme changes: http://paste.ubuntu.com/642710/ (compared to standard sphinx theme)

 - Changes in the CSS:
   daniel@miyazaki:~$ bzr branch lp:ubuntu-website/light-django-theme
   Branched 31 revision(s).

   daniel@miyazaki:~$ diff -u light-django-theme/media/css/default.css bzr/ubuntu-packaging-guide.retheming/themes/ubuntu/static/light-django-theme.css
   --- light-django-theme/media/css/default.css 2011-07-12 17:29:45.334779000 +0200
   +++ bzr/ubuntu-packaging-guide.retheming/themes/ubuntu/static/light-django-theme.css 2011-07-12 17:26:58.420591381 +0200
   @@ -876,11 +876,11 @@
    }

    #page-footer {
   - background: url("../images/footer.png") repeat-x scroll 0 0 #EEECEA
   + background: url("footer.png") repeat-x scroll 0 0 #EEECEA
    }

     #page-footer .container {
   - background: url("../images/footer.png") repeat-x scroll 0 0 #EEECEA;
   + background: url("footer.png") repeat-x scroll 0 0 #EEECEA;
         padding: 0px 10px;
         width: 960px;
     }
   daniel@miyazaki:~$

Revision history for this message
Daniel Holbach (dholbach) wrote :

Thanks a lot Alexander! Fantastic work!

Revision history for this message
Alexander Fougner (fougner) wrote :

> Thanks a lot Alexander! Fantastic work!

You're welcome! Just give me a ping if there's more web stuff to do :)

Revision history for this message
Daniel Holbach (dholbach) wrote :

I feel what we still need to do is:

 - adding copyright/license/location information
 - remove the website links for now, as they're not really relevant to an HTML offline guide,
   and replace them with a <!-- website links --> HTML comment, which can be replace with actual
   HTML (for website links) for the more official location by a script

If you can think of anything else, please comment. :)

Revision history for this message
Iain Lane (laney) wrote :

(I re-merged your branch with trunk before looking)

Cheers for this! Looks very nice :-)

Comments:

  - I see "¶" at the end of headings that probably shouldn't be there.
  - "Index" in the main orange bar seems to go nowhere and the other index link leads to a page with only one entry. Do we plan on fleshing this out?
  - Looking at http://www.ubuntu.com/ubuntu, if that's what we're trying to be consistent with, the links at the top above the orange bar should be /in/ it. (Also there's no Ubuntu logo/text on the right hand side)
  - What's the login link for?
  - Is it possible to indent the code blocks a bit and/or give them a slightly shaded background?
  - Code blocks should probably have a fixed width font. For example, indentation matters when writing debian/changelog entries, and this should be clear on the page. See debian-dir-overview for examples of this.

Cheers!
Iain

review: Needs Fixing
47. By Alexander Fougner

some style fixes and removal of links as per dholbach's request

48. By Alexander Fougner

permalink appears when headers are hovered

Revision history for this message
Daniel Holbach (dholbach) wrote :

I'm very happy with the changes that Alexander got in. Do we want to merge this, go ahead with the current approach and file bugs for the rest of the issues or do we want to fix all of this before merging?

Revision history for this message
Stefano Rivera (stefanor) wrote :

I'm happy with either approach. If Alexander is prepared to do a few rounds of review, we can try and get this all in shape now, but I think it's pretty much mergeable as is.

Issues I see:
* Double copyright footer.
* What's the plan for the top bar? I assume it'll be static links to other related resources?
* The knowledge base articles have an odd link to the knowledge base section, in the second bar.
* The knowledge base page's nested lists don't look great.
* Licencing:
  - We are adding some BSD licensed code that refers to a non-existent LICENCE file.
    + Add such a file, add this to debian/copyright too.
  - Adding a new CC-BY-SA copyright holder.
    + Add the copyright holder to debian/copyright.
  - I guess our articles should get decent copyright attribution headers at some point, but that's out of the scope for this merge.
* Searching doesn't work, but it didn't seem to work before, either.

49. By Alexander Fougner

added js docs, added divider to sidebar

50. By Alexander Fougner

merged dholbach's changes

51. By Alexander Fougner

removed searchbox in relbar

Revision history for this message
Daniel Holbach (dholbach) wrote :

Maybe we should remove all the Javascript bits for now and remove the search bits and file a bug for it, so we can follow up on that later on (and hopefully avoid duplicating jquery bits).

52. By Alexander Fougner

disable js, remove searchbox, some style fixes

53. By Alexander Fougner

remove duplicate copyright text, some styling

54. By Alexander Fougner

removed all unchanged templates, inherits from basic theme instead

55. By Alexander Fougner

merged dholbach's js removals and fixes

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added file 'BORROWED-CODE'
--- BORROWED-CODE 1970-01-01 00:00:00 +0000
+++ BORROWED-CODE 2011-07-22 11:22:44 +0000
@@ -0,0 +1,7 @@
1themes/ubuntu/static/newstyle.css
2themes/ubuntu/static/images/*
3 From http://loco.ubuntu.com/media/css/newstyle.css
4 http://loco.ubuntu.com/media/images
5
6themes/ubuntu/static/light-django-theme.css
7 From lp:ubuntu-community-webthemes/light-django-theme
08
=== modified file 'conf.py'
--- conf.py 2010-11-19 12:07:36 +0000
+++ conf.py 2011-07-22 11:22:44 +0000
@@ -101,7 +101,7 @@
101101
102# The theme to use for HTML and HTML Help pages. See the documentation for102# The theme to use for HTML and HTML Help pages. See the documentation for
103# a list of builtin themes.103# a list of builtin themes.
104html_theme = 'default'104html_theme = 'ubuntu'
105105
106# Theme options are theme-specific and customize the look and feel of a theme106# Theme options are theme-specific and customize the look and feel of a theme
107# further. For a list of options available for each theme, see the107# further. For a list of options available for each theme, see the
@@ -109,7 +109,7 @@
109#html_theme_options = {}109#html_theme_options = {}
110110
111# Add any paths that contain custom themes here, relative to this directory.111# Add any paths that contain custom themes here, relative to this directory.
112#html_theme_path = []112html_theme_path = ['themes']
113113
114# The name for this set of Sphinx documents. If None, it defaults to114# The name for this set of Sphinx documents. If None, it defaults to
115# "<project> v<release> documentation".115# "<project> v<release> documentation".
116116
=== modified file 'debian/copyright'
--- debian/copyright 2011-04-19 08:27:41 +0000
+++ debian/copyright 2011-07-22 11:22:44 +0000
@@ -341,3 +341,44 @@
341 this trademark restriction does not form part of the License.341 this trademark restriction does not form part of the License.
342 .342 .
343 Creative Commons may be contacted at http://creativecommons.org/.343 Creative Commons may be contacted at http://creativecommons.org/.
344
345Files: themes/ubuntu/static/newstyle.css
346 themes/ubuntu/static/images/*
347Copyright: 2009-2011 LoCo Directory Hackers <loco-directory-dev@lists.ubuntu.com>
348License: AGPL-3
349 This program is free software: you can redistribute it and/or modify
350 it under the terms of the GNU Affero General Public License as published by
351 the Free Software Foundation, either version 3 of the License, or
352 (at your option) any later version.
353 .
354 This program is distributed in the hope that it will be useful,
355 but WITHOUT ANY WARRANTY; without even the implied warranty of
356 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
357 GNU Affero General Public License for more details.
358 .
359 You should have received a copy of the GNU Affero General Public License
360 along with this program. If not, see <http://www.gnu.org/licenses/>.
361
362Files: themes/ubuntu/static/light-django-theme.css
363Copyright: Ubuntu Community Web Themes Developers (https://launchpad.net/~ubuntu-community-webthemes)
364License: GPL-2+
365 This program is free software; you can redistribute it
366 and/or modify it under the terms of the GNU General Public
367 License as published by the Free Software Foundation; either
368 version 2 of the License, or (at your option) any later
369 version.
370 .
371 This program is distributed in the hope that it will be
372 useful, but WITHOUT ANY WARRANTY; without even the implied
373 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
374 PURPOSE. See the GNU General Public License for more
375 details.
376 .
377 You should have received a copy of the GNU General Public
378 License along with this package; if not, write to the Free
379 Software Foundation, Inc., 51 Franklin St, Fifth Floor,
380 Boston, MA 02110-1301 USA
381 .
382 On Debian systems, the full text of the GNU General Public
383 License version 2 can be found in the file
384 `/usr/share/common-licenses/GPL-2'.
344385
=== added directory 'themes'
=== added directory 'themes/ubuntu'
=== added file 'themes/ubuntu/defindex.html'
--- themes/ubuntu/defindex.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/defindex.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,35 @@
1{#
2 basic/defindex.html
3 ~~~~~~~~~~~~~~~~~~~
4
5 Default template for the "index" page.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{% extends "layout.html" %}
11{% set title = _('Overview') %}
12{% block body %}
13 <h1>{{ docstitle|e }}</h1>
14 <p>
15 Welcome! This is
16 {% block description %}the documentation for {{ project|e }}
17 {{ release|e }}{% if last_updated %}, last updated {{ last_updated|e }}{% endif %}{% endblock %}.
18 </p>
19 {% block tables %}
20 <p><strong>{{ _('Indices and tables:') }}</strong></p>
21 <table class="contentstable" align="center"><tr>
22 <td width="50%">
23 <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">{{ _('Complete Table of Contents') }}</a><br>
24 <span class="linkdescr">{{ _('lists all sections and subsections') }}</span></p>
25 <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">{{ _('Search Page') }}</a><br>
26 <span class="linkdescr">{{ _('search this documentation') }}</span></p>
27 </td><td width="50%">
28 <p class="biglink"><a class="biglink" href="{{ pathto("modindex") }}">{{ _('Global Module Index') }}</a><br>
29 <span class="linkdescr">{{ _('quick access to all modules') }}</span></p>
30 <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">{{ _('General Index') }}</a><br>
31 <span class="linkdescr">{{ _('all functions, classes, terms') }}</span></p>
32 </td></tr>
33 </table>
34 {% endblock %}
35{% endblock %}
036
=== added file 'themes/ubuntu/domainindex.html'
--- themes/ubuntu/domainindex.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/domainindex.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,57 @@
1{#
2 basic/domainindex.html
3 ~~~~~~~~~~~~~~~~~~~~~~
4
5 Template for domain indices (module index, ...).
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{% extends "layout.html" %}
11{% set title = indextitle %}
12{% block extrahead %}
13{{ super() }}
14{% if not embedded and collapse_index %}
15 <script type="text/javascript">
16 DOCUMENTATION_OPTIONS.COLLAPSE_INDEX = true;
17 </script>
18{% endif %}
19{% endblock %}
20{% block body %}
21
22 {%- set curr_group = 0 %}
23
24 <h1>{{ indextitle }}</h1>
25
26 <div class="modindex-jumpbox">
27 {%- for (letter, entries) in content %}
28 <a href="#cap-{{ letter }}"><strong>{{ letter }}</strong></a>
29 {%- if not loop.last %} | {% endif %}
30 {%- endfor %}
31 </div>
32
33 <table class="indextable modindextable" cellspacing="0" cellpadding="2">
34 {%- for letter, entries in content %}
35 <tr class="pcap"><td></td><td>&nbsp;</td><td></td></tr>
36 <tr class="cap"><td></td><td><a name="cap-{{ letter }}">
37 <strong>{{ letter }}</strong></a></td><td></td></tr>
38 {%- for (name, grouptype, page, anchor, extra, qualifier, description)
39 in entries %}
40 {%- if grouptype == 1 %}{% set curr_group = curr_group + 1 %}{% endif %}
41 <tr{% if grouptype == 2 %} class="cg-{{ curr_group }}"{% endif %}>
42 <td>{% if grouptype == 1 -%}
43 <img src="{{ pathto('_static/minus.png', 1) }}" id="toggle-{{ curr_group }}"
44 class="toggler" style="display: none" alt="-" />
45 {%- endif %}</td>
46 <td>{% if grouptype == 2 %}&nbsp;&nbsp;&nbsp;{% endif %}
47 {% if page %}<a href="{{ pathto(page) }}#{{ anchor }}">{% endif -%}
48 <tt class="xref">{{ name|e }}</tt>
49 {%- if page %}</a>{% endif %}
50 {%- if extra %} <em>({{ extra|e }})</em>{% endif -%}
51 </td><td>{% if qualifier %}<strong>{{ qualifier|e }}:</strong>{% endif %}
52 <em>{{ description|e }}</em></td></tr>
53 {%- endfor %}
54 {%- endfor %}
55 </table>
56
57{% endblock %}
058
=== added file 'themes/ubuntu/genindex-single.html'
--- themes/ubuntu/genindex-single.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/genindex-single.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,48 @@
1{#
2 basic/genindex-single.html
3 ~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5 Template for a "single" page of a split index.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{% extends "layout.html" %}
11{% set title = _('Index') %}
12{% block body %}
13
14 <h1 id="index">{% trans key=key %}Index &ndash; {{ key }}{% endtrans %}</h1>
15
16<table width="100%" class="indextable"><tr>
17 {%- for column in entries|slice(2) if column %}
18 <td width="33%" valign="top"><dl>
19 {%- for entryname, (links, subitems) in column %}
20 <dt>{% if links %}<a href="{{ links[0] }}">{{ entryname|e }}</a>
21 {%- for link in links[1:] %}, <a href="{{ link }}">[{{ loop.index }}]</a>{% endfor %}
22 {%- else %}{{ entryname|e }}{% endif %}</dt>
23 {%- if subitems %}
24 <dd><dl>
25 {%- for subentryname, subentrylinks in subitems %}
26 <dt><a href="{{ subentrylinks[0] }}">{{ subentryname|e }}</a>
27 {%- for link in subentrylinks[1:] %}, <a href="{{ link }}">[{{ loop.index }}]</a>{% endfor -%}
28 </dt>
29 {%- endfor %}
30 </dl></dd>
31 {%- endif -%}
32{%- endfor %}
33</dl></td>
34{%- endfor %}
35</tr></table>
36
37{% endblock %}
38
39{% block sidebarrel %}
40 <h4>Index</h4>
41 <p>{% for key, dummy in genindexentries -%}
42 <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a>
43 {% if not loop.last %}| {% endif %}
44 {%- endfor %}</p>
45
46 <p><a href="{{ pathto('genindex-all') }}"><strong>{{ _('Full index on one page') }}</strong></a></p>
47 {{ super() }}
48{% endblock %}
049
=== added file 'themes/ubuntu/genindex-split.html'
--- themes/ubuntu/genindex-split.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/genindex-split.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,41 @@
1{#
2 basic/genindex-split.html
3 ~~~~~~~~~~~~~~~~~~~~~~~~~
4
5 Template for a "split" index overview page.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{% extends "layout.html" %}
11{% set title = _('Index') %}
12{% block body %}
13
14 <h1 id="index">{{ _('Index') }}</h1>
15
16 <p>{{ _('Index pages by letter') }}:</p>
17
18 <div class="genindex-jumpbox">
19 <p>{% for key, dummy in genindexentries -%}
20 <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a>
21 {% if not loop.last %}| {% endif %}
22 {%- endfor %}</p>
23
24 <p><a href="{{ pathto('genindex-all') }}"><strong>{{ _('Full index on one page') }}</strong>
25 ({{ _('can be huge') }})</a></p>
26 </div>
27
28{% endblock %}
29
30{% block sidebarrel %}
31{% if split_index %}
32 <h4>Index</h4>
33 <p>{% for key, dummy in genindexentries -%}
34 <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a>
35 {% if not loop.last %}| {% endif %}
36 {%- endfor %}</p>
37
38 <p><a href="{{ pathto('genindex-all') }}"><strong>{{ _('Full index on one page') }}</strong></a></p>
39{% endif %}
40 {{ super() }}
41{% endblock %}
042
=== added file 'themes/ubuntu/genindex.html'
--- themes/ubuntu/genindex.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/genindex.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,59 @@
1{#
2 basic/genindex.html
3 ~~~~~~~~~~~~~~~~~~~
4
5 Template for an "all-in-one" index.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{% extends "layout.html" %}
11{% set title = _('Index') %}
12{% block body %}
13
14 <h1 id="index">{{ _('Index') }}</h1>
15
16 <div class="genindex-jumpbox">
17 {% for key, dummy in genindexentries -%}
18 <a href="#{{ key }}"><strong>{{ key }}</strong></a> {% if not loop.last %}| {% endif %}
19 {%- endfor %}
20 </div>
21
22 {%- for key, entries in genindexentries %}
23<h2 id="{{ key }}">{{ key }}</h2>
24<table width="100%" class="indextable genindextable"><tr>
25 {%- for column in entries|slice(2) if column %}
26 <td width="33%" valign="top"><dl>
27 {%- for entryname, (links, subitems) in column %}
28 <dt>{% if links %}<a href="{{ links[0] }}">{{ entryname|e }}</a>
29 {%- for link in links[1:] %}, <a href="{{ link }}">[{{ loop.index }}]</a>{% endfor %}
30 {%- else %}{{ entryname|e }}{% endif %}</dt>
31 {%- if subitems %}
32 <dd><dl>
33 {%- for subentryname, subentrylinks in subitems %}
34 <dt><a href="{{ subentrylinks[0] }}">{{ subentryname|e }}</a>
35 {%- for link in subentrylinks[1:] %}, <a href="{{ link }}">[{{ loop.index }}]</a>{% endfor -%}
36 </dt>
37 {%- endfor %}
38 </dl></dd>
39 {%- endif -%}
40{%- endfor %}
41</dl></td>
42{%- endfor %}
43</tr></table>
44{% endfor %}
45
46{% endblock %}
47
48{% block sidebarrel %}
49{% if split_index %}
50 <h4>{{ _('Index') }}</h4>
51 <p>{% for key, dummy in genindexentries -%}
52 <a href="{{ pathto('genindex-' + key) }}"><strong>{{ key }}</strong></a>
53 {% if not loop.last %}| {% endif %}
54 {%- endfor %}</p>
55
56 <p><a href="{{ pathto('genindex-all') }}"><strong>{{ _('Full index on one page') }}</strong></a></p>
57{% endif %}
58 {{ super() }}
59{% endblock %}
060
=== added file 'themes/ubuntu/globaltoc.html'
--- themes/ubuntu/globaltoc.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/globaltoc.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,11 @@
1{#
2 basic/globaltoc.html
3 ~~~~~~~~~~~~~~~~~~~~
4
5 Sphinx sidebar template: global table of contents.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
11{{ toctree() }}
012
=== added file 'themes/ubuntu/layout.html'
--- themes/ubuntu/layout.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/layout.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,224 @@
1{#
2 ubuntu/layout.html
3 ~~~~~~~~~~~~~~~~~
4
5 Ubuntu layout template for Sphinx themes.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{%- block doctype -%}
11<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
12 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
13{%- endblock %}
14{%- set reldelim1 = reldelim1 is not defined and ' &raquo;' or reldelim1 %}
15{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
16{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
17 (sidebars != []) %}
18{%- set url_root = pathto('', 1) %}
19{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
20
21
22{%- macro relbar() %}
23 <aside id="page-related">
24 <div class="container" id="sub-nav-container" >
25 <nav id="sub-nav">
26 {%- for rellink in rellinks %}
27 <a class="sub-nav-item" {% if loop.first %}style="margin-right: 10px"{% endif %}
28 href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
29 {{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
30 {%- endfor %}
31 {%- block rootrellink %}
32 <a class="sub-nav-item" href="{{ pathto(master_doc) }}">{{ shorttitle|e }} {{ reldelim1 }}</a>
33 {%- endblock %}
34 {%- for parent in parents %}
35 <a class="sub-nav-item" href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }} {{ reldelim1 }}</a>
36 {%- endfor %}
37 {%- block relbaritems %} {% endblock %}
38 </nav>
39 </div>
40</aside>
41{%- endmacro %}
42
43{%- macro sidebar() %}
44 {%- if render_sidebar %}
45 <div class="sphinxsidebar">
46 <div class="sphinxsidebarwrapper">
47 {%- block sidebarlogo %}
48 {%- if logo %}
49 <p class="logo"><a href="{{ pathto(master_doc) }}">
50 <img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
51 </a></p>
52 {%- endif %}
53 {%- endblock %}
54 {%- if sidebars != None %}
55 {#- new style sidebar: explicitly include/exclude templates #}
56 {%- for sidebartemplate in sidebars %}
57 {%- include sidebartemplate %}
58 {%- endfor %}
59 {%- else %}
60 {#- old style sidebars: using blocks -- should be deprecated #}
61 {%- block sidebartoc %}
62 {%- include "localtoc.html" %}
63 {%- endblock %}
64 {%- block sidebarrel %}
65 {%- include "relations.html" %}
66 {%- endblock %}
67 {%- block sidebarsourcelink %}
68 {%- include "sourcelink.html" %}
69 {%- endblock %}
70 {%- if customsidebar %}
71 {%- include customsidebar %}
72 {%- endif %}
73 {%- block sidebarsearch %}
74 {%- include "searchbox.html" %}
75 {%- endblock %}
76 {%- endif %}
77 </div>
78 </div>
79 {%- endif %}
80{%- endmacro %}
81
82<html xmlns="http://www.w3.org/1999/xhtml">
83 <head>
84 <meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
85 {{ metatags }}
86 {%- if not embedded and docstitle %}
87 {%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
88 {%- else %}
89 {%- set titlesuffix = "" %}
90 {%- endif %}
91 {%- block htmltitle %}
92 <title>{{ title|striptags|e }}{{ titlesuffix }}</title>
93 {%- endblock %}
94 <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
95 <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
96 {%- for cssfile in css_files %}
97 <link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
98 {%- endfor %}
99 {%- if not embedded %}
100 <script type="text/javascript">
101 var DOCUMENTATION_OPTIONS = {
102 URL_ROOT: '{{ url_root }}',
103 VERSION: '{{ release|e }}',
104 COLLAPSE_INDEX: false,
105 FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
106 HAS_SOURCE: {{ has_source|lower }}
107 };
108 </script>
109 {# %- for scriptfile in script_files %}
110 <script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
111 {%- endfor % #}
112 {%- if use_opensearch %}
113 <link rel="search" type="application/opensearchdescription+xml"
114 title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
115 href="{{ pathto('_static/opensearch.xml', 1) }}"/>
116 {%- endif %}
117 {%- if favicon %}
118 <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
119 {%- endif %}
120 {%- endif %}
121{%- block linktags %}
122 {%- if hasdoc('about') %}
123 <link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
124 {%- endif %}
125 {%- if hasdoc('genindex') %}
126 <link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
127 {%- endif %}
128 {%- if hasdoc('search') %}
129 <link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
130 {%- endif %}
131 {%- if hasdoc('copyright') %}
132 <link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
133 {%- endif %}
134 <link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
135 {%- if parents %}
136 <link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
137 {%- endif %}
138 {%- if next %}
139 <link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
140 {%- endif %}
141 {%- if prev %}
142 <link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
143 {%- endif %}
144{%- endblock %}
145{%- block extrahead %} {% endblock %}
146 </head>
147 <body id="home">
148
149<!--
150<aside id="top-nav">
151 <div class="container">
152
153 <section id="top-login">
154 <a class="top-login-item" href="/openid/login?next=/events/" title="Login">Login</a>
155 </section>
156 <nav id="top-related">
157 <a class="top-nav-item" href="http://www.ubuntu.com">Ubuntu.com</a>
158 <a class="top-nav-item" href="http://www.ubuntu.com/community">Community</a>
159 <a class="top-nav-item" href="http://www.ubuntu.com/support">Support</a>
160 <a class="top-nav-item" href="http://www.ubuntu.com/partners">Partners</a>
161 </nav>
162 </div>
163</aside>
164-->
165
166<header id="page-header">
167 <div class="container" >
168 <nav id="main-nav">
169 <a class="main-nav-item " title="Index" href="index.html">Index</a>
170 </nav>
171 </div>
172</header>
173
174{%- block header %}{% endblock %}
175
176{%- block relbar1 %}{{ relbar() }}{% endblock %}
177
178{%- block content %}
179 {%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
180
181 <section id="main-section">
182 {%- block document %}
183 <div class="container" >
184 {%- if render_sidebar %}
185 <section id="content">
186 {%- endif %}
187 <div class="body">
188 {%- block sidebar2 %}{{ sidebar() }}{% endblock %}
189 {% block body %} {% endblock %}
190 <div class="divide"></div>
191
192 </div>
193 {%- if render_sidebar %}
194 </section>
195 {%- endif %}
196 </div>
197 {%- endblock %}
198 </section>
199{%- endblock %}
200
201{%- block footer %}
202 <footer id="page-footer">
203 <div class="container">
204 <div class="copyright">
205&copy; 2008-2011 Canonical Ltd., Ubuntu Community. Ubuntu is a registered trademark of Canonical Ltd.<br />
206</div>
207 {%- if show_copyright %}
208 {%- if hasdoc('copyright') %}
209 {% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
210 {%- else %}
211 {% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}
212 {%- endif %}
213 {%- endif %}
214 {%- if last_updated %}
215 {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
216 {%- endif %}
217 {%- if show_sphinx %}
218 {% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
219 {%- endif %}
220 </div>
221 </footer>
222{%- endblock %}
223 </body>
224</html>
0225
=== added file 'themes/ubuntu/localtoc.html'
--- themes/ubuntu/localtoc.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/localtoc.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,13 @@
1{#
2 basic/localtoc.html
3 ~~~~~~~~~~~~~~~~~~~
4
5 Sphinx sidebar template: local table of contents.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{%- if display_toc %}
11 <h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
12 {{ toc }}
13{%- endif %}
014
=== added file 'themes/ubuntu/opensearch.xml'
--- themes/ubuntu/opensearch.xml 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/opensearch.xml 2011-07-22 11:22:44 +0000
@@ -0,0 +1,10 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
3 <ShortName>{{ project|e }}</ShortName>
4 <Description>{% trans docstitle=docstitle|e %}Search {{ docstitle }}{% endtrans %}</Description>
5 <InputEncoding>utf-8</InputEncoding>
6 <Url type="text/html" method="get"
7 template="{{ use_opensearch }}/{{ pathto('search') }}?q={searchTerms}&amp;check_keywords=yes&amp;area=default"/>
8 <LongName>{{ docstitle|e }}</LongName>
9{% block extra %} {# Put e.g. an <Image> element here. #} {% endblock %}
10</OpenSearchDescription>
011
=== added file 'themes/ubuntu/page.html'
--- themes/ubuntu/page.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/page.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,13 @@
1{#
2 basic/page.html
3 ~~~~~~~~~~~~~~~
4
5 Master template for simple pages.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{% extends "layout.html" %}
11{% block body %}
12 {{ body }}
13{% endblock %}
014
=== added file 'themes/ubuntu/relations.html'
--- themes/ubuntu/relations.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/relations.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,19 @@
1{#
2 basic/relations.html
3 ~~~~~~~~~~~~~~~~~~~~
4
5 Sphinx sidebar template: relation links.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{%- if prev %}
11 <h4>{{ _('Previous topic') }}</h4>
12 <p class="topless"><a href="{{ prev.link|e }}"
13 title="{{ _('previous chapter') }}">{{ prev.title }}</a></p>
14{%- endif %}
15{%- if next %}
16 <h4>{{ _('Next topic') }}</h4>
17 <p class="topless"><a href="{{ next.link|e }}"
18 title="{{ _('next chapter') }}">{{ next.title }}</a></p>
19{%- endif %}
020
=== added file 'themes/ubuntu/search.html'
--- themes/ubuntu/search.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/search.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,56 @@
1{#
2 basic/search.html
3 ~~~~~~~~~~~~~~~~~
4
5 Template for the search page.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{% extends "layout.html" %}
11{% set title = _('Search') %}
12{% set script_files = script_files + ['_static/searchtools.js'] %}
13{% block extrahead %}
14 <script type="text/javascript">
15 jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
16 </script>
17 {{ super() }}
18{% endblock %}
19{% block body %}
20 <h1 id="search-documentation">{{ _('Search') }}</h1>
21 <div id="fallback" class="admonition warning">
22 <script type="text/javascript">$('#fallback').hide();</script>
23 <p>
24 {% trans %}Please activate JavaScript to enable the search
25 functionality.{% endtrans %}
26 </p>
27 </div>
28 <p>
29 {% trans %}From here you can search these documents. Enter your search
30 words into the box below and click "search". Note that the search
31 function will automatically search for all of the words. Pages
32 containing fewer words won't appear in the result list.{% endtrans %}
33 </p>
34 <form action="" method="get">
35 <input type="text" name="q" value="" />
36 <input type="submit" value="{{ _('search') }}" />
37 <span id="search-progress" style="padding-left: 10px"></span>
38 </form>
39 {% if search_performed %}
40 <h2>{{ _('Search Results') }}</h2>
41 {% if not search_results %}
42 <p>{{ _('Your search did not match any results.') }}</p>
43 {% endif %}
44 {% endif %}
45 <div id="search-results">
46 {% if search_results %}
47 <ul>
48 {% for href, caption, context in search_results %}
49 <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
50 <div class="context">{{ context|e }}</div>
51 </li>
52 {% endfor %}
53 </ul>
54 {% endif %}
55 </div>
56{% endblock %}
057
=== added file 'themes/ubuntu/searchbox.html'
--- themes/ubuntu/searchbox.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/searchbox.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,24 @@
1{#
2 basic/searchbox.html
3 ~~~~~~~~~~~~~~~~~~~~
4
5 Sphinx sidebar template: quick search box.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{%- if pagename != "search" %}
11<div id="searchbox" style="display: none">
12 <h4>{{ _('Quick search') }}</h4>
13 <form class="search" action="{{ pathto('search') }}" method="get">
14 <input type="text" name="q" size="18" />
15 <input type="submit" value="{{ _('Go') }}" />
16 <input type="hidden" name="check_keywords" value="yes" />
17 <input type="hidden" name="area" value="default" />
18 </form>
19 <p class="searchtip" style="font-size: 90%">
20 {{ _('Enter search terms or a module, class or function name.') }}
21 </p>
22</div>
23<!--<script type="text/javascript">$('#searchbox').show(0);</script>-->
24{%- endif %}
025
=== added file 'themes/ubuntu/sourcelink.html'
--- themes/ubuntu/sourcelink.html 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/sourcelink.html 2011-07-22 11:22:44 +0000
@@ -0,0 +1,16 @@
1{#
2 basic/sourcelink.html
3 ~~~~~~~~~~~~~~~~~~~~~
4
5 Sphinx sidebar template: "show source" link.
6
7 :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
8 :license: BSD, see LICENSE for details.
9#}
10{%- if show_source and has_source and sourcename %}
11 <h3>{{ _('This Page') }}</h3>
12 <ul class="this-page-menu">
13 <li><a href="{{ pathto('_sources/' + sourcename, true)|e }}"
14 rel="nofollow">{{ _('Show Source') }}</a></li>
15 </ul>
16{%- endif %}
017
=== added directory 'themes/ubuntu/static'
=== added file 'themes/ubuntu/static/default.css_t'
--- themes/ubuntu/static/default.css_t 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/static/default.css_t 2011-07-22 11:22:44 +0000
@@ -0,0 +1,56 @@
1/*
2* License: GPLv2
3* Author : Alexander Fougner <fougner89 at gmail dot com>
4* Source : http://loco.ubuntu.com/media/css/newstyle.css
5* https://code.launchpad.net/~ubuntu-website-community/ubuntu-website/light-django-theme
6*/
7
8@import url("light-django-theme.css");
9@import url("newstyle.css");
10
11body {
12 background: url("images/dotted.png") repeat scroll 0 0 #FFFFFF;
13}
14
15#page-header {
16 background: url("images/header.png") repeat-x scroll 0 0 #DD4814;
17}
18
19div.sphinxsidebar {
20 float:right;
21 background: #f5f5f5;
22 border: 1px solid #ddd;
23 padding: 15px;
24 margin: 10px;
25 width: 230px;
26}
27
28div.sphinxsidebar ul {
29 margin-left: 10px;
30}
31
32pre {
33 font-family: monospace;
34 border: 1px solid #ddd;
35 background: #f5f5f5;
36 margin: 5px;
37 padding: 5px;
38}
39
40a.headerlink {
41 visibility: hidden;
42}
43
44h1:hover > a.headerlink,
45h2:hover > a.headerlink,
46h3:hover > a.headerlink,
47h4:hover > a.headerlink,
48h5:hover > a.headerlink,
49h6:hover > a.headerlink,
50dt:hover > a.headerlink {
51visibility: visible;
52}
53
54form.search_form input, #searchbox {
55height: auto;
56}
057
=== added file 'themes/ubuntu/static/doctools.js'
--- themes/ubuntu/static/doctools.js 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/static/doctools.js 2011-07-22 11:22:44 +0000
@@ -0,0 +1,247 @@
1/*
2 * doctools.js
3 * ~~~~~~~~~~~
4 *
5 * Sphinx JavaScript utilties for all documentation.
6 *
7 * :copyright: Copyright 2007-2010 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 directory 'themes/ubuntu/static/images'
=== added file 'themes/ubuntu/static/images/dotted.png'
1Binary files themes/ubuntu/static/images/dotted.png 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/dotted.png 2011-07-22 11:22:44 +0000 differ249Binary files themes/ubuntu/static/images/dotted.png 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/dotted.png 2011-07-22 11:22:44 +0000 differ
=== added file 'themes/ubuntu/static/images/favicon.ico'
2Binary files themes/ubuntu/static/images/favicon.ico 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/favicon.ico 2011-07-22 11:22:44 +0000 differ250Binary files themes/ubuntu/static/images/favicon.ico 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/favicon.ico 2011-07-22 11:22:44 +0000 differ
=== added file 'themes/ubuntu/static/images/footer.png'
3Binary files themes/ubuntu/static/images/footer.png 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/footer.png 2011-07-22 11:22:44 +0000 differ251Binary files themes/ubuntu/static/images/footer.png 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/footer.png 2011-07-22 11:22:44 +0000 differ
=== added file 'themes/ubuntu/static/images/header.png'
4Binary files themes/ubuntu/static/images/header.png 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/header.png 2011-07-22 11:22:44 +0000 differ252Binary files themes/ubuntu/static/images/header.png 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/header.png 2011-07-22 11:22:44 +0000 differ
=== added file 'themes/ubuntu/static/images/search.png'
5Binary files themes/ubuntu/static/images/search.png 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/search.png 2011-07-22 11:22:44 +0000 differ253Binary files themes/ubuntu/static/images/search.png 1970-01-01 00:00:00 +0000 and themes/ubuntu/static/images/search.png 2011-07-22 11:22:44 +0000 differ
=== added file 'themes/ubuntu/static/jquery.js'
--- themes/ubuntu/static/jquery.js 1970-01-01 00:00:00 +0000
+++ themes/ubuntu/static/jquery.js 2011-07-22 11:22:44 +0000
@@ -0,0 +1,8176 @@
1/*!
2 * jQuery JavaScript Library v1.5
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: Mon Jan 31 08:31:29 2011 -0500
15 */
16(function( window, undefined ) {
17
18// Use the correct document accordingly with window argument (sandbox)
19var document = window.document;
20var jQuery = (function() {
21
22// Define a local copy of jQuery
23var jQuery = function( selector, context ) {
24 // The jQuery object is actually just the init constructor 'enhanced'
25 return new jQuery.fn.init( selector, context, rootjQuery );
26 },
27
28 // Map over jQuery in case of overwrite
29 _jQuery = window.jQuery,
30
31 // Map over the $ in case of overwrite
32 _$ = window.$,
33
34 // A central reference to the root jQuery(document)
35 rootjQuery,
36
37 // A simple way to check for HTML strings or ID strings
38 // (both of which we optimize for)
39 quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,
40
41 // Check if a string has a non-whitespace character in it
42 rnotwhite = /\S/,
43
44 // Used for trimming whitespace
45 trimLeft = /^\s+/,
46 trimRight = /\s+$/,
47
48 // Check for digits
49 rdigit = /\d/,
50
51 // Match a standalone tag
52 rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
53
54 // JSON RegExp
55 rvalidchars = /^[\],:{}\s]*$/,
56 rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
57 rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
58 rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
59
60 // Useragent RegExp
61 rwebkit = /(webkit)[ \/]([\w.]+)/,
62 ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
63 rmsie = /(msie) ([\w.]+)/,
64 rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
65
66 // Keep a UserAgent string for use with jQuery.browser
67 userAgent = navigator.userAgent,
68
69 // For matching the engine and version of the browser
70 browserMatch,
71
72 // Has the ready events already been bound?
73 readyBound = false,
74
75 // The deferred used on DOM ready
76 readyList,
77
78 // Promise methods
79 promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
80
81 // The ready event handler
82 DOMContentLoaded,
83
84 // Save a reference to some core methods
85 toString = Object.prototype.toString,
86 hasOwn = Object.prototype.hasOwnProperty,
87 push = Array.prototype.push,
88 slice = Array.prototype.slice,
89 trim = String.prototype.trim,
90 indexOf = Array.prototype.indexOf,
91
92 // [[Class]] -> type pairs
93 class2type = {};
94
95jQuery.fn = jQuery.prototype = {
96 constructor: jQuery,
97 init: function( selector, context, rootjQuery ) {
98 var match, elem, ret, doc;
99
100 // Handle $(""), $(null), or $(undefined)
101 if ( !selector ) {
102 return this;
103 }
104
105 // Handle $(DOMElement)
106 if ( selector.nodeType ) {
107 this.context = this[0] = selector;
108 this.length = 1;
109 return this;
110 }
111
112 // The body element only exists once, optimize finding it
113 if ( selector === "body" && !context && document.body ) {
114 this.context = document;
115 this[0] = document.body;
116 this.selector = "body";
117 this.length = 1;
118 return this;
119 }
120
121 // Handle HTML strings
122 if ( typeof selector === "string" ) {
123 // Are we dealing with HTML string or an ID?
124 match = quickExpr.exec( selector );
125
126 // Verify a match, and that no context was specified for #id
127 if ( match && (match[1] || !context) ) {
128
129 // HANDLE: $(html) -> $(array)
130 if ( match[1] ) {
131 context = context instanceof jQuery ? context[0] : context;
132 doc = (context ? context.ownerDocument || context : document);
133
134 // If a single string is passed in and it's a single tag
135 // just do a createElement and skip the rest
136 ret = rsingleTag.exec( selector );
137
138 if ( ret ) {
139 if ( jQuery.isPlainObject( context ) ) {
140 selector = [ document.createElement( ret[1] ) ];
141 jQuery.fn.attr.call( selector, context, true );
142
143 } else {
144 selector = [ doc.createElement( ret[1] ) ];
145 }
146
147 } else {
148 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
149 selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
150 }
151
152 return jQuery.merge( this, selector );
153
154 // HANDLE: $("#id")
155 } else {
156 elem = document.getElementById( match[2] );
157
158 // Check parentNode to catch when Blackberry 4.6 returns
159 // nodes that are no longer in the document #6963
160 if ( elem && elem.parentNode ) {
161 // Handle the case where IE and Opera return items
162 // by name instead of ID
163 if ( elem.id !== match[2] ) {
164 return rootjQuery.find( selector );
165 }
166
167 // Otherwise, we inject the element directly into the jQuery object
168 this.length = 1;
169 this[0] = elem;
170 }
171
172 this.context = document;
173 this.selector = selector;
174 return this;
175 }
176
177 // HANDLE: $(expr, $(...))
178 } else if ( !context || context.jquery ) {
179 return (context || rootjQuery).find( selector );
180
181 // HANDLE: $(expr, context)
182 // (which is just equivalent to: $(context).find(expr)
183 } else {
184 return this.constructor( context ).find( selector );
185 }
186
187 // HANDLE: $(function)
188 // Shortcut for document ready
189 } else if ( jQuery.isFunction( selector ) ) {
190 return rootjQuery.ready( selector );
191 }
192
193 if (selector.selector !== undefined) {
194 this.selector = selector.selector;
195 this.context = selector.context;
196 }
197
198 return jQuery.makeArray( selector, this );
199 },
200
201 // Start with an empty selector
202 selector: "",
203
204 // The current version of jQuery being used
205 jquery: "1.5",
206
207 // The default length of a jQuery object is 0
208 length: 0,
209
210 // The number of elements contained in the matched element set
211 size: function() {
212 return this.length;
213 },
214
215 toArray: function() {
216 return slice.call( this, 0 );
217 },
218
219 // Get the Nth element in the matched element set OR
220 // Get the whole matched element set as a clean array
221 get: function( num ) {
222 return num == null ?
223
224 // Return a 'clean' array
225 this.toArray() :
226
227 // Return just the object
228 ( num < 0 ? this[ this.length + num ] : this[ num ] );
229 },
230
231 // Take an array of elements and push it onto the stack
232 // (returning the new matched element set)
233 pushStack: function( elems, name, selector ) {
234 // Build a new jQuery matched element set
235 var ret = this.constructor();
236
237 if ( jQuery.isArray( elems ) ) {
238 push.apply( ret, elems );
239
240 } else {
241 jQuery.merge( ret, elems );
242 }
243
244 // Add the old object onto the stack (as a reference)
245 ret.prevObject = this;
246
247 ret.context = this.context;
248
249 if ( name === "find" ) {
250 ret.selector = this.selector + (this.selector ? " " : "") + selector;
251 } else if ( name ) {
252 ret.selector = this.selector + "." + name + "(" + selector + ")";
253 }
254
255 // Return the newly-formed element set
256 return ret;
257 },
258
259 // Execute a callback for every element in the matched set.
260 // (You can seed the arguments with an array of args, but this is
261 // only used internally.)
262 each: function( callback, args ) {
263 return jQuery.each( this, callback, args );
264 },
265
266 ready: function( fn ) {
267 // Attach the listeners
268 jQuery.bindReady();
269
270 // Add the callback
271 readyList.done( fn );
272
273 return this;
274 },
275
276 eq: function( i ) {
277 return i === -1 ?
278 this.slice( i ) :
279 this.slice( i, +i + 1 );
280 },
281
282 first: function() {
283 return this.eq( 0 );
284 },
285
286 last: function() {
287 return this.eq( -1 );
288 },
289
290 slice: function() {
291 return this.pushStack( slice.apply( this, arguments ),
292 "slice", slice.call(arguments).join(",") );
293 },
294
295 map: function( callback ) {
296 return this.pushStack( jQuery.map(this, function( elem, i ) {
297 return callback.call( elem, i, elem );
298 }));
299 },
300
301 end: function() {
302 return this.prevObject || this.constructor(null);
303 },
304
305 // For internal use only.
306 // Behaves like an Array's method, not like a jQuery method.
307 push: push,
308 sort: [].sort,
309 splice: [].splice
310};
311
312// Give the init function the jQuery prototype for later instantiation
313jQuery.fn.init.prototype = jQuery.fn;
314
315jQuery.extend = jQuery.fn.extend = function() {
316 var options, name, src, copy, copyIsArray, clone,
317 target = arguments[0] || {},
318 i = 1,
319 length = arguments.length,
320 deep = false;
321
322 // Handle a deep copy situation
323 if ( typeof target === "boolean" ) {
324 deep = target;
325 target = arguments[1] || {};
326 // skip the boolean and the target
327 i = 2;
328 }
329
330 // Handle case when target is a string or something (possible in deep copy)
331 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
332 target = {};
333 }
334
335 // extend jQuery itself if only one argument is passed
336 if ( length === i ) {
337 target = this;
338 --i;
339 }
340
341 for ( ; i < length; i++ ) {
342 // Only deal with non-null/undefined values
343 if ( (options = arguments[ i ]) != null ) {
344 // Extend the base object
345 for ( name in options ) {
346 src = target[ name ];
347 copy = options[ name ];
348
349 // Prevent never-ending loop
350 if ( target === copy ) {
351 continue;
352 }
353
354 // Recurse if we're merging plain objects or arrays
355 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
356 if ( copyIsArray ) {
357 copyIsArray = false;
358 clone = src && jQuery.isArray(src) ? src : [];
359
360 } else {
361 clone = src && jQuery.isPlainObject(src) ? src : {};
362 }
363
364 // Never move original objects, clone them
365 target[ name ] = jQuery.extend( deep, clone, copy );
366
367 // Don't bring in undefined values
368 } else if ( copy !== undefined ) {
369 target[ name ] = copy;
370 }
371 }
372 }
373 }
374
375 // Return the modified object
376 return target;
377};
378
379jQuery.extend({
380 noConflict: function( deep ) {
381 window.$ = _$;
382
383 if ( deep ) {
384 window.jQuery = _jQuery;
385 }
386
387 return jQuery;
388 },
389
390 // Is the DOM ready to be used? Set to true once it occurs.
391 isReady: false,
392
393 // A counter to track how many items to wait for before
394 // the ready event fires. See #6781
395 readyWait: 1,
396
397 // Handle when the DOM is ready
398 ready: function( wait ) {
399 // A third-party is pushing the ready event forwards
400 if ( wait === true ) {
401 jQuery.readyWait--;
402 }
403
404 // Make sure that the DOM is not already loaded
405 if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
406 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
407 if ( !document.body ) {
408 return setTimeout( jQuery.ready, 1 );
409 }
410
411 // Remember that the DOM is ready
412 jQuery.isReady = true;
413
414 // If a normal DOM Ready event fired, decrement, and wait if need be
415 if ( wait !== true && --jQuery.readyWait > 0 ) {
416 return;
417 }
418
419 // If there are functions bound, to execute
420 readyList.resolveWith( document, [ jQuery ] );
421
422 // Trigger any bound ready events
423 if ( jQuery.fn.trigger ) {
424 jQuery( document ).trigger( "ready" ).unbind( "ready" );
425 }
426 }
427 },
428
429 bindReady: function() {
430 if ( readyBound ) {
431 return;
432 }
433
434 readyBound = true;
435
436 // Catch cases where $(document).ready() is called after the
437 // browser event has already occurred.
438 if ( document.readyState === "complete" ) {
439 // Handle it asynchronously to allow scripts the opportunity to delay ready
440 return setTimeout( jQuery.ready, 1 );
441 }
442
443 // Mozilla, Opera and webkit nightlies currently support this event
444 if ( document.addEventListener ) {
445 // Use the handy event callback
446 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
447
448 // A fallback to window.onload, that will always work
449 window.addEventListener( "load", jQuery.ready, false );
450
451 // If IE event model is used
452 } else if ( document.attachEvent ) {
453 // ensure firing before onload,
454 // maybe late but safe also for iframes
455 document.attachEvent("onreadystatechange", DOMContentLoaded);
456
457 // A fallback to window.onload, that will always work
458 window.attachEvent( "onload", jQuery.ready );
459
460 // If IE and not a frame
461 // continually check to see if the document is ready
462 var toplevel = false;
463
464 try {
465 toplevel = window.frameElement == null;
466 } catch(e) {}
467
468 if ( document.documentElement.doScroll && toplevel ) {
469 doScrollCheck();
470 }
471 }
472 },
473
474 // See test/unit/core.js for details concerning isFunction.
475 // Since version 1.3, DOM methods and functions like alert
476 // aren't supported. They return false on IE (#2968).
477 isFunction: function( obj ) {
478 return jQuery.type(obj) === "function";
479 },
480
481 isArray: Array.isArray || function( obj ) {
482 return jQuery.type(obj) === "array";
483 },
484
485 // A crude way of determining if an object is a window
486 isWindow: function( obj ) {
487 return obj && typeof obj === "object" && "setInterval" in obj;
488 },
489
490 isNaN: function( obj ) {
491 return obj == null || !rdigit.test( obj ) || isNaN( obj );
492 },
493
494 type: function( obj ) {
495 return obj == null ?
496 String( obj ) :
497 class2type[ toString.call(obj) ] || "object";
498 },
499
500 isPlainObject: function( obj ) {
501 // Must be an Object.
502 // Because of IE, we also have to check the presence of the constructor property.
503 // Make sure that DOM nodes and window objects don't pass through, as well
504 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
505 return false;
506 }
507
508 // Not own constructor property must be Object
509 if ( obj.constructor &&
510 !hasOwn.call(obj, "constructor") &&
511 !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
512 return false;
513 }
514
515 // Own properties are enumerated firstly, so to speed up,
516 // if last one is own, then all properties are own.
517
518 var key;
519 for ( key in obj ) {}
520
521 return key === undefined || hasOwn.call( obj, key );
522 },
523
524 isEmptyObject: function( obj ) {
525 for ( var name in obj ) {
526 return false;
527 }
528 return true;
529 },
530
531 error: function( msg ) {
532 throw msg;
533 },
534
535 parseJSON: function( data ) {
536 if ( typeof data !== "string" || !data ) {
537 return null;
538 }
539
540 // Make sure leading/trailing whitespace is removed (IE can't handle it)
541 data = jQuery.trim( data );
542
543 // Make sure the incoming data is actual JSON
544 // Logic borrowed from http://json.org/json2.js
545 if ( rvalidchars.test(data.replace(rvalidescape, "@")
546 .replace(rvalidtokens, "]")
547 .replace(rvalidbraces, "")) ) {
548
549 // Try to use the native JSON parser first
550 return window.JSON && window.JSON.parse ?
551 window.JSON.parse( data ) :
552 (new Function("return " + data))();
553
554 } else {
555 jQuery.error( "Invalid JSON: " + data );
556 }
557 },
558
559 // Cross-browser xml parsing
560 // (xml & tmp used internally)
561 parseXML: function( data , xml , tmp ) {
562
563 if ( window.DOMParser ) { // Standard
564 tmp = new DOMParser();
565 xml = tmp.parseFromString( data , "text/xml" );
566 } else { // IE
567 xml = new ActiveXObject( "Microsoft.XMLDOM" );
568 xml.async = "false";
569 xml.loadXML( data );
570 }
571
572 tmp = xml.documentElement;
573
574 if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
575 jQuery.error( "Invalid XML: " + data );
576 }
577
578 return xml;
579 },
580
581 noop: function() {},
582
583 // Evalulates a script in a global context
584 globalEval: function( data ) {
585 if ( data && rnotwhite.test(data) ) {
586 // Inspired by code by Andrea Giammarchi
587 // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
588 var head = document.getElementsByTagName("head")[0] || document.documentElement,
589 script = document.createElement("script");
590
591 script.type = "text/javascript";
592
593 if ( jQuery.support.scriptEval() ) {
594 script.appendChild( document.createTextNode( data ) );
595 } else {
596 script.text = data;
597 }
598
599 // Use insertBefore instead of appendChild to circumvent an IE6 bug.
600 // This arises when a base node is used (#2709).
601 head.insertBefore( script, head.firstChild );
602 head.removeChild( script );
603 }
604 },
605
606 nodeName: function( elem, name ) {
607 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
608 },
609
610 // args is for internal usage only
611 each: function( object, callback, args ) {
612 var name, i = 0,
613 length = object.length,
614 isObj = length === undefined || jQuery.isFunction(object);
615
616 if ( args ) {
617 if ( isObj ) {
618 for ( name in object ) {
619 if ( callback.apply( object[ name ], args ) === false ) {
620 break;
621 }
622 }
623 } else {
624 for ( ; i < length; ) {
625 if ( callback.apply( object[ i++ ], args ) === false ) {
626 break;
627 }
628 }
629 }
630
631 // A special, fast, case for the most common use of each
632 } else {
633 if ( isObj ) {
634 for ( name in object ) {
635 if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
636 break;
637 }
638 }
639 } else {
640 for ( var value = object[0];
641 i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
642 }
643 }
644
645 return object;
646 },
647
648 // Use native String.trim function wherever possible
649 trim: trim ?
650 function( text ) {
651 return text == null ?
652 "" :
653 trim.call( text );
654 } :
655
656 // Otherwise use our own trimming functionality
657 function( text ) {
658 return text == null ?
659 "" :
660 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
661 },
662
663 // results is for internal usage only
664 makeArray: function( array, results ) {
665 var ret = results || [];
666
667 if ( array != null ) {
668 // The window, strings (and functions) also have 'length'
669 // The extra typeof function check is to prevent crashes
670 // in Safari 2 (See: #3039)
671 // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
672 var type = jQuery.type(array);
673
674 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
675 push.call( ret, array );
676 } else {
677 jQuery.merge( ret, array );
678 }
679 }
680
681 return ret;
682 },
683
684 inArray: function( elem, array ) {
685 if ( array.indexOf ) {
686 return array.indexOf( elem );
687 }
688
689 for ( var i = 0, length = array.length; i < length; i++ ) {
690 if ( array[ i ] === elem ) {
691 return i;
692 }
693 }
694
695 return -1;
696 },
697
698 merge: function( first, second ) {
699 var i = first.length,
700 j = 0;
701
702 if ( typeof second.length === "number" ) {
703 for ( var l = second.length; j < l; j++ ) {
704 first[ i++ ] = second[ j ];
705 }
706
707 } else {
708 while ( second[j] !== undefined ) {
709 first[ i++ ] = second[ j++ ];
710 }
711 }
712
713 first.length = i;
714
715 return first;
716 },
717
718 grep: function( elems, callback, inv ) {
719 var ret = [], retVal;
720 inv = !!inv;
721
722 // Go through the array, only saving the items
723 // that pass the validator function
724 for ( var i = 0, length = elems.length; i < length; i++ ) {
725 retVal = !!callback( elems[ i ], i );
726 if ( inv !== retVal ) {
727 ret.push( elems[ i ] );
728 }
729 }
730
731 return ret;
732 },
733
734 // arg is for internal usage only
735 map: function( elems, callback, arg ) {
736 var ret = [], value;
737
738 // Go through the array, translating each of the items to their
739 // new value (or values).
740 for ( var i = 0, length = elems.length; i < length; i++ ) {
741 value = callback( elems[ i ], i, arg );
742
743 if ( value != null ) {
744 ret[ ret.length ] = value;
745 }
746 }
747
748 // Flatten any nested arrays
749 return ret.concat.apply( [], ret );
750 },
751
752 // A global GUID counter for objects
753 guid: 1,
754
755 proxy: function( fn, proxy, thisObject ) {
756 if ( arguments.length === 2 ) {
757 if ( typeof proxy === "string" ) {
758 thisObject = fn;
759 fn = thisObject[ proxy ];
760 proxy = undefined;
761
762 } else if ( proxy && !jQuery.isFunction( proxy ) ) {
763 thisObject = proxy;
764 proxy = undefined;
765 }
766 }
767
768 if ( !proxy && fn ) {
769 proxy = function() {
770 return fn.apply( thisObject || this, arguments );
771 };
772 }
773
774 // Set the guid of unique handler to the same of original handler, so it can be removed
775 if ( fn ) {
776 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
777 }
778
779 // So proxy can be declared as an argument
780 return proxy;
781 },
782
783 // Mutifunctional method to get and set values to a collection
784 // The value/s can be optionally by executed if its a function
785 access: function( elems, key, value, exec, fn, pass ) {
786 var length = elems.length;
787
788 // Setting many attributes
789 if ( typeof key === "object" ) {
790 for ( var k in key ) {
791 jQuery.access( elems, k, key[k], exec, fn, value );
792 }
793 return elems;
794 }
795
796 // Setting one attribute
797 if ( value !== undefined ) {
798 // Optionally, function values get executed if exec is true
799 exec = !pass && exec && jQuery.isFunction(value);
800
801 for ( var i = 0; i < length; i++ ) {
802 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
803 }
804
805 return elems;
806 }
807
808 // Getting an attribute
809 return length ? fn( elems[0], key ) : undefined;
810 },
811
812 now: function() {
813 return (new Date()).getTime();
814 },
815
816 // Create a simple deferred (one callbacks list)
817 _Deferred: function() {
818 var // callbacks list
819 callbacks = [],
820 // stored [ context , args ]
821 fired,
822 // to avoid firing when already doing so
823 firing,
824 // flag to know if the deferred has been cancelled
825 cancelled,
826 // the deferred itself
827 deferred = {
828
829 // done( f1, f2, ...)
830 done: function() {
831 if ( !cancelled ) {
832 var args = arguments,
833 i,
834 length,
835 elem,
836 type,
837 _fired;
838 if ( fired ) {
839 _fired = fired;
840 fired = 0;
841 }
842 for ( i = 0, length = args.length; i < length; i++ ) {
843 elem = args[ i ];
844 type = jQuery.type( elem );
845 if ( type === "array" ) {
846 deferred.done.apply( deferred, elem );
847 } else if ( type === "function" ) {
848 callbacks.push( elem );
849 }
850 }
851 if ( _fired ) {
852 deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
853 }
854 }
855 return this;
856 },
857
858 // resolve with given context and args
859 resolveWith: function( context, args ) {
860 if ( !cancelled && !fired && !firing ) {
861 firing = 1;
862 try {
863 while( callbacks[ 0 ] ) {
864 callbacks.shift().apply( context, args );
865 }
866 }
867 finally {
868 fired = [ context, args ];
869 firing = 0;
870 }
871 }
872 return this;
873 },
874
875 // resolve with this as context and given arguments
876 resolve: function() {
877 deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments );
878 return this;
879 },
880
881 // Has this deferred been resolved?
882 isResolved: function() {
883 return !!( firing || fired );
884 },
885
886 // Cancel
887 cancel: function() {
888 cancelled = 1;
889 callbacks = [];
890 return this;
891 }
892 };
893
894 return deferred;
895 },
896
897 // Full fledged deferred (two callbacks list)
898 Deferred: function( func ) {
899 var deferred = jQuery._Deferred(),
900 failDeferred = jQuery._Deferred(),
901 promise;
902 // Add errorDeferred methods, then and promise
903 jQuery.extend( deferred, {
904 then: function( doneCallbacks, failCallbacks ) {
905 deferred.done( doneCallbacks ).fail( failCallbacks );
906 return this;
907 },
908 fail: failDeferred.done,
909 rejectWith: failDeferred.resolveWith,
910 reject: failDeferred.resolve,
911 isRejected: failDeferred.isResolved,
912 // Get a promise for this deferred
913 // If obj is provided, the promise aspect is added to the object
914 promise: function( obj , i /* internal */ ) {
915 if ( obj == null ) {
916 if ( promise ) {
917 return promise;
918 }
919 promise = obj = {};
920 }
921 i = promiseMethods.length;
922 while( i-- ) {
923 obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ];
924 }
925 return obj;
926 }
927 } );
928 // Make sure only one callback list will be used
929 deferred.then( failDeferred.cancel, deferred.cancel );
930 // Unexpose cancel
931 delete deferred.cancel;
932 // Call given func if any
933 if ( func ) {
934 func.call( deferred, deferred );
935 }
936 return deferred;
937 },
938
939 // Deferred helper
940 when: function( object ) {
941 var args = arguments,
942 length = args.length,
943 deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
944 object :
945 jQuery.Deferred(),
946 promise = deferred.promise(),
947 resolveArray;
948
949 if ( length > 1 ) {
950 resolveArray = new Array( length );
951 jQuery.each( args, function( index, element ) {
952 jQuery.when( element ).then( function( value ) {
953 resolveArray[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value;
954 if( ! --length ) {
955 deferred.resolveWith( promise, resolveArray );
956 }
957 }, deferred.reject );
958 } );
959 } else if ( deferred !== object ) {
960 deferred.resolve( object );
961 }
962 return promise;
963 },
964
965 // Use of jQuery.browser is frowned upon.
966 // More details: http://docs.jquery.com/Utilities/jQuery.browser
967 uaMatch: function( ua ) {
968 ua = ua.toLowerCase();
969
970 var match = rwebkit.exec( ua ) ||
971 ropera.exec( ua ) ||
972 rmsie.exec( ua ) ||
973 ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
974 [];
975
976 return { browser: match[1] || "", version: match[2] || "0" };
977 },
978
979 sub: function() {
980 function jQuerySubclass( selector, context ) {
981 return new jQuerySubclass.fn.init( selector, context );
982 }
983 jQuery.extend( true, jQuerySubclass, this );
984 jQuerySubclass.superclass = this;
985 jQuerySubclass.fn = jQuerySubclass.prototype = this();
986 jQuerySubclass.fn.constructor = jQuerySubclass;
987 jQuerySubclass.subclass = this.subclass;
988 jQuerySubclass.fn.init = function init( selector, context ) {
989 if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) {
990 context = jQuerySubclass(context);
991 }
992
993 return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );
994 };
995 jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
996 var rootjQuerySubclass = jQuerySubclass(document);
997 return jQuerySubclass;
998 },
999
1000 browser: {}
1001});
1002
1003// Create readyList deferred
1004readyList = jQuery._Deferred();
1005
1006// Populate the class2type map
1007jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
1008 class2type[ "[object " + name + "]" ] = name.toLowerCase();
1009});
1010
1011browserMatch = jQuery.uaMatch( userAgent );
1012if ( browserMatch.browser ) {
1013 jQuery.browser[ browserMatch.browser ] = true;
1014 jQuery.browser.version = browserMatch.version;
1015}
1016
1017// Deprecated, use jQuery.browser.webkit instead
1018if ( jQuery.browser.webkit ) {
1019 jQuery.browser.safari = true;
1020}
1021
1022if ( indexOf ) {
1023 jQuery.inArray = function( elem, array ) {
1024 return indexOf.call( array, elem );
1025 };
1026}
1027
1028// IE doesn't match non-breaking spaces with \s
1029if ( rnotwhite.test( "\xA0" ) ) {
1030 trimLeft = /^[\s\xA0]+/;
1031 trimRight = /[\s\xA0]+$/;
1032}
1033
1034// All jQuery objects should point back to these
1035rootjQuery = jQuery(document);
1036
1037// Cleanup functions for the document ready method
1038if ( document.addEventListener ) {
1039 DOMContentLoaded = function() {
1040 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
1041 jQuery.ready();
1042 };
1043
1044} else if ( document.attachEvent ) {
1045 DOMContentLoaded = function() {
1046 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
1047 if ( document.readyState === "complete" ) {
1048 document.detachEvent( "onreadystatechange", DOMContentLoaded );
1049 jQuery.ready();
1050 }
1051 };
1052}
1053
1054// The DOM ready check for Internet Explorer
1055function doScrollCheck() {
1056 if ( jQuery.isReady ) {
1057 return;
1058 }
1059
1060 try {
1061 // If IE is used, use the trick by Diego Perini
1062 // http://javascript.nwbox.com/IEContentLoaded/
1063 document.documentElement.doScroll("left");
1064 } catch(e) {
1065 setTimeout( doScrollCheck, 1 );
1066 return;
1067 }
1068
1069 // and execute any waiting functions
1070 jQuery.ready();
1071}
1072
1073// Expose jQuery to the global object
1074return (window.jQuery = window.$ = jQuery);
1075
1076})();
1077
1078
1079(function() {
1080
1081 jQuery.support = {};
1082
1083 var div = document.createElement("div");
1084
1085 div.style.display = "none";
1086 div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
1087
1088 var all = div.getElementsByTagName("*"),
1089 a = div.getElementsByTagName("a")[0],
1090 select = document.createElement("select"),
1091 opt = select.appendChild( document.createElement("option") );
1092
1093 // Can't get basic test support
1094 if ( !all || !all.length || !a ) {
1095 return;
1096 }
1097
1098 jQuery.support = {
1099 // IE strips leading whitespace when .innerHTML is used
1100 leadingWhitespace: div.firstChild.nodeType === 3,
1101
1102 // Make sure that tbody elements aren't automatically inserted
1103 // IE will insert them into empty tables
1104 tbody: !div.getElementsByTagName("tbody").length,
1105
1106 // Make sure that link elements get serialized correctly by innerHTML
1107 // This requires a wrapper element in IE
1108 htmlSerialize: !!div.getElementsByTagName("link").length,
1109
1110 // Get the style information from getAttribute
1111 // (IE uses .cssText insted)
1112 style: /red/.test( a.getAttribute("style") ),
1113
1114 // Make sure that URLs aren't manipulated
1115 // (IE normalizes it by default)
1116 hrefNormalized: a.getAttribute("href") === "/a",
1117
1118 // Make sure that element opacity exists
1119 // (IE uses filter instead)
1120 // Use a regex to work around a WebKit issue. See #5145
1121 opacity: /^0.55$/.test( a.style.opacity ),
1122
1123 // Verify style float existence
1124 // (IE uses styleFloat instead of cssFloat)
1125 cssFloat: !!a.style.cssFloat,
1126
1127 // Make sure that if no value is specified for a checkbox
1128 // that it defaults to "on".
1129 // (WebKit defaults to "" instead)
1130 checkOn: div.getElementsByTagName("input")[0].value === "on",
1131
1132 // Make sure that a selected-by-default option has a working selected property.
1133 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1134 optSelected: opt.selected,
1135
1136 // Will be defined later
1137 deleteExpando: true,
1138 optDisabled: false,
1139 checkClone: false,
1140 _scriptEval: null,
1141 noCloneEvent: true,
1142 boxModel: null,
1143 inlineBlockNeedsLayout: false,
1144 shrinkWrapBlocks: false,
1145 reliableHiddenOffsets: true
1146 };
1147
1148 // Make sure that the options inside disabled selects aren't marked as disabled
1149 // (WebKit marks them as diabled)
1150 select.disabled = true;
1151 jQuery.support.optDisabled = !opt.disabled;
1152
1153 jQuery.support.scriptEval = function() {
1154 if ( jQuery.support._scriptEval === null ) {
1155 var root = document.documentElement,
1156 script = document.createElement("script"),
1157 id = "script" + jQuery.now();
1158
1159 script.type = "text/javascript";
1160 try {
1161 script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
1162 } catch(e) {}
1163
1164 root.insertBefore( script, root.firstChild );
1165
1166 // Make sure that the execution of code works by injecting a script
1167 // tag with appendChild/createTextNode
1168 // (IE doesn't support this, fails, and uses .text instead)
1169 if ( window[ id ] ) {
1170 jQuery.support._scriptEval = true;
1171 delete window[ id ];
1172 } else {
1173 jQuery.support._scriptEval = false;
1174 }
1175
1176 root.removeChild( script );
1177 // release memory in IE
1178 root = script = id = null;
1179 }
1180
1181 return jQuery.support._scriptEval;
1182 };
1183
1184 // Test to see if it's possible to delete an expando from an element
1185 // Fails in Internet Explorer
1186 try {
1187 delete div.test;
1188
1189 } catch(e) {
1190 jQuery.support.deleteExpando = false;
1191 }
1192
1193 if ( div.attachEvent && div.fireEvent ) {
1194 div.attachEvent("onclick", function click() {
1195 // Cloning a node shouldn't copy over any
1196 // bound event handlers (IE does this)
1197 jQuery.support.noCloneEvent = false;
1198 div.detachEvent("onclick", click);
1199 });
1200 div.cloneNode(true).fireEvent("onclick");
1201 }
1202
1203 div = document.createElement("div");
1204 div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
1205
1206 var fragment = document.createDocumentFragment();
1207 fragment.appendChild( div.firstChild );
1208
1209 // WebKit doesn't clone checked state correctly in fragments
1210 jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
1211
1212 // Figure out if the W3C box model works as expected
1213 // document.body must exist before we can do this
1214 jQuery(function() {
1215 var div = document.createElement("div"),
1216 body = document.getElementsByTagName("body")[0];
1217
1218 // Frameset documents with no body should not run this code
1219 if ( !body ) {
1220 return;
1221 }
1222
1223 div.style.width = div.style.paddingLeft = "1px";
1224 body.appendChild( div );
1225 jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
1226
1227 if ( "zoom" in div.style ) {
1228 // Check if natively block-level elements act like inline-block
1229 // elements when setting their display to 'inline' and giving
1230 // them layout
1231 // (IE < 8 does this)
1232 div.style.display = "inline";
1233 div.style.zoom = 1;
1234 jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;
1235
1236 // Check if elements with layout shrink-wrap their children
1237 // (IE 6 does this)
1238 div.style.display = "";
1239 div.innerHTML = "<div style='width:4px;'></div>";
1240 jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
1241 }
1242
1243 div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
1244 var tds = div.getElementsByTagName("td");
1245
1246 // Check if table cells still have offsetWidth/Height when they are set
1247 // to display:none and there are still other visible table cells in a
1248 // table row; if so, offsetWidth/Height are not reliable for use when
1249 // determining if an element has been hidden directly using
1250 // display:none (it is still safe to use offsets if a parent element is
1251 // hidden; don safety goggles and see bug #4512 for more information).
1252 // (only IE 8 fails this test)
1253 jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;
1254
1255 tds[0].style.display = "";
1256 tds[1].style.display = "none";
1257
1258 // Check if empty table cells still have offsetWidth/Height
1259 // (IE < 8 fail this test)
1260 jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
1261 div.innerHTML = "";
1262
1263 body.removeChild( div ).style.display = "none";
1264 div = tds = null;
1265 });
1266
1267 // Technique from Juriy Zaytsev
1268 // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
1269 var eventSupported = function( eventName ) {
1270 var el = document.createElement("div");
1271 eventName = "on" + eventName;
1272
1273 // We only care about the case where non-standard event systems
1274 // are used, namely in IE. Short-circuiting here helps us to
1275 // avoid an eval call (in setAttribute) which can cause CSP
1276 // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
1277 if ( !el.attachEvent ) {
1278 return true;
1279 }
1280
1281 var isSupported = (eventName in el);
1282 if ( !isSupported ) {
1283 el.setAttribute(eventName, "return;");
1284 isSupported = typeof el[eventName] === "function";
1285 }
1286 el = null;
1287
1288 return isSupported;
1289 };
1290
1291 jQuery.support.submitBubbles = eventSupported("submit");
1292 jQuery.support.changeBubbles = eventSupported("change");
1293
1294 // release memory in IE
1295 div = all = a = null;
1296})();
1297
1298
1299
1300var rbrace = /^(?:\{.*\}|\[.*\])$/;
1301
1302jQuery.extend({
1303 cache: {},
1304
1305 // Please use with caution
1306 uuid: 0,
1307
1308 // Unique for each copy of jQuery on the page
1309 // Non-digits removed to match rinlinejQuery
1310 expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
1311
1312 // The following elements throw uncatchable exceptions if you
1313 // attempt to add expando properties to them.
1314 noData: {
1315 "embed": true,
1316 // Ban all objects except for Flash (which handle expandos)
1317 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
1318 "applet": true
1319 },
1320
1321 hasData: function( elem ) {
1322 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
1323
1324 return !!elem && !jQuery.isEmptyObject(elem);
1325 },
1326
1327 data: function( elem, name, data, pvt /* Internal Use Only */ ) {
1328 if ( !jQuery.acceptData( elem ) ) {
1329 return;
1330 }
1331
1332 var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
1333
1334 // We have to handle DOM nodes and JS objects differently because IE6-7
1335 // can't GC object references properly across the DOM-JS boundary
1336 isNode = elem.nodeType,
1337
1338 // Only DOM nodes need the global jQuery cache; JS object data is
1339 // attached directly to the object so GC can occur automatically
1340 cache = isNode ? jQuery.cache : elem,
1341
1342 // Only defining an ID for JS objects if its cache already exists allows
1343 // the code to shortcut on the same path as a DOM node with no cache
1344 id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
1345
1346 // Avoid doing any more work than we need to when trying to get data on an
1347 // object that has no data at all
1348 if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
1349 return;
1350 }
1351
1352 if ( !id ) {
1353 // Only DOM nodes need a new unique ID for each element since their data
1354 // ends up in the global cache
1355 if ( isNode ) {
1356 elem[ jQuery.expando ] = id = ++jQuery.uuid;
1357 } else {
1358 id = jQuery.expando;
1359 }
1360 }
1361
1362 if ( !cache[ id ] ) {
1363 cache[ id ] = {};
1364 }
1365
1366 // An object can be passed to jQuery.data instead of a key/value pair; this gets
1367 // shallow copied over onto the existing cache
1368 if ( typeof name === "object" ) {
1369 if ( pvt ) {
1370 cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
1371 } else {
1372 cache[ id ] = jQuery.extend(cache[ id ], name);
1373 }
1374 }
1375
1376 thisCache = cache[ id ];
1377
1378 // Internal jQuery data is stored in a separate object inside the object's data
1379 // cache in order to avoid key collisions between internal data and user-defined
1380 // data
1381 if ( pvt ) {
1382 if ( !thisCache[ internalKey ] ) {
1383 thisCache[ internalKey ] = {};
1384 }
1385
1386 thisCache = thisCache[ internalKey ];
1387 }
1388
1389 if ( data !== undefined ) {
1390 thisCache[ name ] = data;
1391 }
1392
1393 // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
1394 // not attempt to inspect the internal events object using jQuery.data, as this
1395 // internal data object is undocumented and subject to change.
1396 if ( name === "events" && !thisCache[name] ) {
1397 return thisCache[ internalKey ] && thisCache[ internalKey ].events;
1398 }
1399
1400 return getByName ? thisCache[ name ] : thisCache;
1401 },
1402
1403 removeData: function( elem, name, pvt /* Internal Use Only */ ) {
1404 if ( !jQuery.acceptData( elem ) ) {
1405 return;
1406 }
1407
1408 var internalKey = jQuery.expando, isNode = elem.nodeType,
1409
1410 // See jQuery.data for more information
1411 cache = isNode ? jQuery.cache : elem,
1412
1413 // See jQuery.data for more information
1414 id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
1415
1416 // If there is already no cache entry for this object, there is no
1417 // purpose in continuing
1418 if ( !cache[ id ] ) {
1419 return;
1420 }
1421
1422 if ( name ) {
1423 var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
1424
1425 if ( thisCache ) {
1426 delete thisCache[ name ];
1427
1428 // If there is no data left in the cache, we want to continue
1429 // and let the cache object itself get destroyed
1430 if ( !jQuery.isEmptyObject(thisCache) ) {
1431 return;
1432 }
1433 }
1434 }
1435
1436 // See jQuery.data for more information
1437 if ( pvt ) {
1438 delete cache[ id ][ internalKey ];
1439
1440 // Don't destroy the parent cache unless the internal data object
1441 // had been the only thing left in it
1442 if ( !jQuery.isEmptyObject(cache[ id ]) ) {
1443 return;
1444 }
1445 }
1446
1447 var internalCache = cache[ id ][ internalKey ];
1448
1449 // Browsers that fail expando deletion also refuse to delete expandos on
1450 // the window, but it will allow it on all other JS objects; other browsers
1451 // don't care
1452 if ( jQuery.support.deleteExpando || cache != window ) {
1453 delete cache[ id ];
1454 } else {
1455 cache[ id ] = null;
1456 }
1457
1458 // We destroyed the entire user cache at once because it's faster than
1459 // iterating through each key, but we need to continue to persist internal
1460 // data if it existed
1461 if ( internalCache ) {
1462 cache[ id ] = {};
1463 cache[ id ][ internalKey ] = internalCache;
1464
1465 // Otherwise, we need to eliminate the expando on the node to avoid
1466 // false lookups in the cache for entries that no longer exist
1467 } else if ( isNode ) {
1468 // IE does not allow us to delete expando properties from nodes,
1469 // nor does it have a removeAttribute function on Document nodes;
1470 // we must handle all of these cases
1471 if ( jQuery.support.deleteExpando ) {
1472 delete elem[ jQuery.expando ];
1473 } else if ( elem.removeAttribute ) {
1474 elem.removeAttribute( jQuery.expando );
1475 } else {
1476 elem[ jQuery.expando ] = null;
1477 }
1478 }
1479 },
1480
1481 // For internal use only.
1482 _data: function( elem, name, data ) {
1483 return jQuery.data( elem, name, data, true );
1484 },
1485
1486 // A method for determining if a DOM node can handle the data expando
1487 acceptData: function( elem ) {
1488 if ( elem.nodeName ) {
1489 var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
1490
1491 if ( match ) {
1492 return !(match === true || elem.getAttribute("classid") !== match);
1493 }
1494 }
1495
1496 return true;
1497 }
1498});
1499
1500jQuery.fn.extend({
1501 data: function( key, value ) {
1502 var data = null;
1503
1504 if ( typeof key === "undefined" ) {
1505 if ( this.length ) {
1506 data = jQuery.data( this[0] );
1507
1508 if ( this[0].nodeType === 1 ) {
1509 var attr = this[0].attributes, name;
1510 for ( var i = 0, l = attr.length; i < l; i++ ) {
1511 name = attr[i].name;
1512
1513 if ( name.indexOf( "data-" ) === 0 ) {
1514 name = name.substr( 5 );
1515 dataAttr( this[0], name, data[ name ] );
1516 }
1517 }
1518 }
1519 }
1520
1521 return data;
1522
1523 } else if ( typeof key === "object" ) {
1524 return this.each(function() {
1525 jQuery.data( this, key );
1526 });
1527 }
1528
1529 var parts = key.split(".");
1530 parts[1] = parts[1] ? "." + parts[1] : "";
1531
1532 if ( value === undefined ) {
1533 data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
1534
1535 // Try to fetch any internally stored data first
1536 if ( data === undefined && this.length ) {
1537 data = jQuery.data( this[0], key );
1538 data = dataAttr( this[0], key, data );
1539 }
1540
1541 return data === undefined && parts[1] ?
1542 this.data( parts[0] ) :
1543 data;
1544
1545 } else {
1546 return this.each(function() {
1547 var $this = jQuery( this ),
1548 args = [ parts[0], value ];
1549
1550 $this.triggerHandler( "setData" + parts[1] + "!", args );
1551 jQuery.data( this, key, value );
1552 $this.triggerHandler( "changeData" + parts[1] + "!", args );
1553 });
1554 }
1555 },
1556
1557 removeData: function( key ) {
1558 return this.each(function() {
1559 jQuery.removeData( this, key );
1560 });
1561 }
1562});
1563
1564function dataAttr( elem, key, data ) {
1565 // If nothing was found internally, try to fetch any
1566 // data from the HTML5 data-* attribute
1567 if ( data === undefined && elem.nodeType === 1 ) {
1568 data = elem.getAttribute( "data-" + key );
1569
1570 if ( typeof data === "string" ) {
1571 try {
1572 data = data === "true" ? true :
1573 data === "false" ? false :
1574 data === "null" ? null :
1575 !jQuery.isNaN( data ) ? parseFloat( data ) :
1576 rbrace.test( data ) ? jQuery.parseJSON( data ) :
1577 data;
1578 } catch( e ) {}
1579
1580 // Make sure we set the data so it isn't changed later
1581 jQuery.data( elem, key, data );
1582
1583 } else {
1584 data = undefined;
1585 }
1586 }
1587
1588 return data;
1589}
1590
1591
1592
1593
1594jQuery.extend({
1595 queue: function( elem, type, data ) {
1596 if ( !elem ) {
1597 return;
1598 }
1599
1600 type = (type || "fx") + "queue";
1601 var q = jQuery._data( elem, type );
1602
1603 // Speed up dequeue by getting out quickly if this is just a lookup
1604 if ( !data ) {
1605 return q || [];
1606 }
1607
1608 if ( !q || jQuery.isArray(data) ) {
1609 q = jQuery._data( elem, type, jQuery.makeArray(data) );
1610
1611 } else {
1612 q.push( data );
1613 }
1614
1615 return q;
1616 },
1617
1618 dequeue: function( elem, type ) {
1619 type = type || "fx";
1620
1621 var queue = jQuery.queue( elem, type ),
1622 fn = queue.shift();
1623
1624 // If the fx queue is dequeued, always remove the progress sentinel
1625 if ( fn === "inprogress" ) {
1626 fn = queue.shift();
1627 }
1628
1629 if ( fn ) {
1630 // Add a progress sentinel to prevent the fx queue from being
1631 // automatically dequeued
1632 if ( type === "fx" ) {
1633 queue.unshift("inprogress");
1634 }
1635
1636 fn.call(elem, function() {
1637 jQuery.dequeue(elem, type);
1638 });
1639 }
1640
1641 if ( !queue.length ) {
1642 jQuery.removeData( elem, type + "queue", true );
1643 }
1644 }
1645});
1646
1647jQuery.fn.extend({
1648 queue: function( type, data ) {
1649 if ( typeof type !== "string" ) {
1650 data = type;
1651 type = "fx";
1652 }
1653
1654 if ( data === undefined ) {
1655 return jQuery.queue( this[0], type );
1656 }
1657 return this.each(function( i ) {
1658 var queue = jQuery.queue( this, type, data );
1659
1660 if ( type === "fx" && queue[0] !== "inprogress" ) {
1661 jQuery.dequeue( this, type );
1662 }
1663 });
1664 },
1665 dequeue: function( type ) {
1666 return this.each(function() {
1667 jQuery.dequeue( this, type );
1668 });
1669 },
1670
1671 // Based off of the plugin by Clint Helfers, with permission.
1672 // http://blindsignals.com/index.php/2009/07/jquery-delay/
1673 delay: function( time, type ) {
1674 time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
1675 type = type || "fx";
1676
1677 return this.queue( type, function() {
1678 var elem = this;
1679 setTimeout(function() {
1680 jQuery.dequeue( elem, type );
1681 }, time );
1682 });
1683 },
1684
1685 clearQueue: function( type ) {
1686 return this.queue( type || "fx", [] );
1687 }
1688});
1689
1690
1691
1692
1693var rclass = /[\n\t\r]/g,
1694 rspaces = /\s+/,
1695 rreturn = /\r/g,
1696 rspecialurl = /^(?:href|src|style)$/,
1697 rtype = /^(?:button|input)$/i,
1698 rfocusable = /^(?:button|input|object|select|textarea)$/i,
1699 rclickable = /^a(?:rea)?$/i,
1700 rradiocheck = /^(?:radio|checkbox)$/i;
1701
1702jQuery.props = {
1703 "for": "htmlFor",
1704 "class": "className",
1705 readonly: "readOnly",
1706 maxlength: "maxLength",
1707 cellspacing: "cellSpacing",
1708 rowspan: "rowSpan",
1709 colspan: "colSpan",
1710 tabindex: "tabIndex",
1711 usemap: "useMap",
1712 frameborder: "frameBorder"
1713};
1714
1715jQuery.fn.extend({
1716 attr: function( name, value ) {
1717 return jQuery.access( this, name, value, true, jQuery.attr );
1718 },
1719
1720 removeAttr: function( name, fn ) {
1721 return this.each(function(){
1722 jQuery.attr( this, name, "" );
1723 if ( this.nodeType === 1 ) {
1724 this.removeAttribute( name );
1725 }
1726 });
1727 },
1728
1729 addClass: function( value ) {
1730 if ( jQuery.isFunction(value) ) {
1731 return this.each(function(i) {
1732 var self = jQuery(this);
1733 self.addClass( value.call(this, i, self.attr("class")) );
1734 });
1735 }
1736
1737 if ( value && typeof value === "string" ) {
1738 var classNames = (value || "").split( rspaces );
1739
1740 for ( var i = 0, l = this.length; i < l; i++ ) {
1741 var elem = this[i];
1742
1743 if ( elem.nodeType === 1 ) {
1744 if ( !elem.className ) {
1745 elem.className = value;
1746
1747 } else {
1748 var className = " " + elem.className + " ",
1749 setClass = elem.className;
1750
1751 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1752 if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
1753 setClass += " " + classNames[c];
1754 }
1755 }
1756 elem.className = jQuery.trim( setClass );
1757 }
1758 }
1759 }
1760 }
1761
1762 return this;
1763 },
1764
1765 removeClass: function( value ) {
1766 if ( jQuery.isFunction(value) ) {
1767 return this.each(function(i) {
1768 var self = jQuery(this);
1769 self.removeClass( value.call(this, i, self.attr("class")) );
1770 });
1771 }
1772
1773 if ( (value && typeof value === "string") || value === undefined ) {
1774 var classNames = (value || "").split( rspaces );
1775
1776 for ( var i = 0, l = this.length; i < l; i++ ) {
1777 var elem = this[i];
1778
1779 if ( elem.nodeType === 1 && elem.className ) {
1780 if ( value ) {
1781 var className = (" " + elem.className + " ").replace(rclass, " ");
1782 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
1783 className = className.replace(" " + classNames[c] + " ", " ");
1784 }
1785 elem.className = jQuery.trim( className );
1786
1787 } else {
1788 elem.className = "";
1789 }
1790 }
1791 }
1792 }
1793
1794 return this;
1795 },
1796
1797 toggleClass: function( value, stateVal ) {
1798 var type = typeof value,
1799 isBool = typeof stateVal === "boolean";
1800
1801 if ( jQuery.isFunction( value ) ) {
1802 return this.each(function(i) {
1803 var self = jQuery(this);
1804 self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
1805 });
1806 }
1807
1808 return this.each(function() {
1809 if ( type === "string" ) {
1810 // toggle individual class names
1811 var className,
1812 i = 0,
1813 self = jQuery( this ),
1814 state = stateVal,
1815 classNames = value.split( rspaces );
1816
1817 while ( (className = classNames[ i++ ]) ) {
1818 // check each className given, space seperated list
1819 state = isBool ? state : !self.hasClass( className );
1820 self[ state ? "addClass" : "removeClass" ]( className );
1821 }
1822
1823 } else if ( type === "undefined" || type === "boolean" ) {
1824 if ( this.className ) {
1825 // store className if set
1826 jQuery._data( this, "__className__", this.className );
1827 }
1828
1829 // toggle whole className
1830 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
1831 }
1832 });
1833 },
1834
1835 hasClass: function( selector ) {
1836 var className = " " + selector + " ";
1837 for ( var i = 0, l = this.length; i < l; i++ ) {
1838 if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
1839 return true;
1840 }
1841 }
1842
1843 return false;
1844 },
1845
1846 val: function( value ) {
1847 if ( !arguments.length ) {
1848 var elem = this[0];
1849
1850 if ( elem ) {
1851 if ( jQuery.nodeName( elem, "option" ) ) {
1852 // attributes.value is undefined in Blackberry 4.7 but
1853 // uses .value. See #6932
1854 var val = elem.attributes.value;
1855 return !val || val.specified ? elem.value : elem.text;
1856 }
1857
1858 // We need to handle select boxes special
1859 if ( jQuery.nodeName( elem, "select" ) ) {
1860 var index = elem.selectedIndex,
1861 values = [],
1862 options = elem.options,
1863 one = elem.type === "select-one";
1864
1865 // Nothing was selected
1866 if ( index < 0 ) {
1867 return null;
1868 }
1869
1870 // Loop through all the selected options
1871 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
1872 var option = options[ i ];
1873
1874 // Don't return options that are disabled or in a disabled optgroup
1875 if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
1876 (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
1877
1878 // Get the specific value for the option
1879 value = jQuery(option).val();
1880
1881 // We don't need an array for one selects
1882 if ( one ) {
1883 return value;
1884 }
1885
1886 // Multi-Selects return an array
1887 values.push( value );
1888 }
1889 }
1890
1891 return values;
1892 }
1893
1894 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
1895 if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
1896 return elem.getAttribute("value") === null ? "on" : elem.value;
1897 }
1898
1899 // Everything else, we just grab the value
1900 return (elem.value || "").replace(rreturn, "");
1901
1902 }
1903
1904 return undefined;
1905 }
1906
1907 var isFunction = jQuery.isFunction(value);
1908
1909 return this.each(function(i) {
1910 var self = jQuery(this), val = value;
1911
1912 if ( this.nodeType !== 1 ) {
1913 return;
1914 }
1915
1916 if ( isFunction ) {
1917 val = value.call(this, i, self.val());
1918 }
1919
1920 // Treat null/undefined as ""; convert numbers to string
1921 if ( val == null ) {
1922 val = "";
1923 } else if ( typeof val === "number" ) {
1924 val += "";
1925 } else if ( jQuery.isArray(val) ) {
1926 val = jQuery.map(val, function (value) {
1927 return value == null ? "" : value + "";
1928 });
1929 }
1930
1931 if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
1932 this.checked = jQuery.inArray( self.val(), val ) >= 0;
1933
1934 } else if ( jQuery.nodeName( this, "select" ) ) {
1935 var values = jQuery.makeArray(val);
1936
1937 jQuery( "option", this ).each(function() {
1938 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
1939 });
1940
1941 if ( !values.length ) {
1942 this.selectedIndex = -1;
1943 }
1944
1945 } else {
1946 this.value = val;
1947 }
1948 });
1949 }
1950});
1951
1952jQuery.extend({
1953 attrFn: {
1954 val: true,
1955 css: true,
1956 html: true,
1957 text: true,
1958 data: true,
1959 width: true,
1960 height: true,
1961 offset: true
1962 },
1963
1964 attr: function( elem, name, value, pass ) {
1965 // don't get/set attributes on text, comment and attribute nodes
1966 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || elem.nodeType === 2 ) {
1967 return undefined;
1968 }
1969
1970 if ( pass && name in jQuery.attrFn ) {
1971 return jQuery(elem)[name](value);
1972 }
1973
1974 var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
1975 // Whether we are setting (or getting)
1976 set = value !== undefined;
1977
1978 // Try to normalize/fix the name
1979 name = notxml && jQuery.props[ name ] || name;
1980
1981 // Only do all the following if this is a node (faster for style)
1982 if ( elem.nodeType === 1 ) {
1983 // These attributes require special treatment
1984 var special = rspecialurl.test( name );
1985
1986 // Safari mis-reports the default selected property of an option
1987 // Accessing the parent's selectedIndex property fixes it
1988 if ( name === "selected" && !jQuery.support.optSelected ) {
1989 var parent = elem.parentNode;
1990 if ( parent ) {
1991 parent.selectedIndex;
1992
1993 // Make sure that it also works with optgroups, see #5701
1994 if ( parent.parentNode ) {
1995 parent.parentNode.selectedIndex;
1996 }
1997 }
1998 }
1999
2000 // If applicable, access the attribute via the DOM 0 way
2001 // 'in' checks fail in Blackberry 4.7 #6931
2002 if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {
2003 if ( set ) {
2004 // We can't allow the type property to be changed (since it causes problems in IE)
2005 if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
2006 jQuery.error( "type property can't be changed" );
2007 }
2008
2009 if ( value === null ) {
2010 if ( elem.nodeType === 1 ) {
2011 elem.removeAttribute( name );
2012 }
2013
2014 } else {
2015 elem[ name ] = value;
2016 }
2017 }
2018
2019 // browsers index elements by id/name on forms, give priority to attributes.
2020 if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
2021 return elem.getAttributeNode( name ).nodeValue;
2022 }
2023
2024 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2025 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2026 if ( name === "tabIndex" ) {
2027 var attributeNode = elem.getAttributeNode( "tabIndex" );
2028
2029 return attributeNode && attributeNode.specified ?
2030 attributeNode.value :
2031 rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2032 0 :
2033 undefined;
2034 }
2035
2036 return elem[ name ];
2037 }
2038
2039 if ( !jQuery.support.style && notxml && name === "style" ) {
2040 if ( set ) {
2041 elem.style.cssText = "" + value;
2042 }
2043
2044 return elem.style.cssText;
2045 }
2046
2047 if ( set ) {
2048 // convert the value to a string (all browsers do this but IE) see #1070
2049 elem.setAttribute( name, "" + value );
2050 }
2051
2052 // Ensure that missing attributes return undefined
2053 // Blackberry 4.7 returns "" from getAttribute #6938
2054 if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {
2055 return undefined;
2056 }
2057
2058 var attr = !jQuery.support.hrefNormalized && notxml && special ?
2059 // Some attributes require a special call on IE
2060 elem.getAttribute( name, 2 ) :
2061 elem.getAttribute( name );
2062
2063 // Non-existent attributes return null, we normalize to undefined
2064 return attr === null ? undefined : attr;
2065 }
2066 // Handle everything which isn't a DOM element node
2067 if ( set ) {
2068 elem[ name ] = value;
2069 }
2070 return elem[ name ];
2071 }
2072});
2073
2074
2075
2076
2077var rnamespaces = /\.(.*)$/,
2078 rformElems = /^(?:textarea|input|select)$/i,
2079 rperiod = /\./g,
2080 rspace = / /g,
2081 rescape = /[^\w\s.|`]/g,
2082 fcleanup = function( nm ) {
2083 return nm.replace(rescape, "\\$&");
2084 },
2085 eventKey = "events";
2086
2087/*
2088 * A number of helper functions used for managing events.
2089 * Many of the ideas behind this code originated from
2090 * Dean Edwards' addEvent library.
2091 */
2092jQuery.event = {
2093
2094 // Bind an event to an element
2095 // Original by Dean Edwards
2096 add: function( elem, types, handler, data ) {
2097 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2098 return;
2099 }
2100
2101 // For whatever reason, IE has trouble passing the window object
2102 // around, causing it to be cloned in the process
2103 if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
2104 elem = window;
2105 }
2106
2107 if ( handler === false ) {
2108 handler = returnFalse;
2109 } else if ( !handler ) {
2110 // Fixes bug #7229. Fix recommended by jdalton
2111 return;
2112 }
2113
2114 var handleObjIn, handleObj;
2115
2116 if ( handler.handler ) {
2117 handleObjIn = handler;
2118 handler = handleObjIn.handler;
2119 }
2120
2121 // Make sure that the function being executed has a unique ID
2122 if ( !handler.guid ) {
2123 handler.guid = jQuery.guid++;
2124 }
2125
2126 // Init the element's event structure
2127 var elemData = jQuery._data( elem );
2128
2129 // If no elemData is found then we must be trying to bind to one of the
2130 // banned noData elements
2131 if ( !elemData ) {
2132 return;
2133 }
2134
2135 var events = elemData[ eventKey ],
2136 eventHandle = elemData.handle;
2137
2138 if ( typeof events === "function" ) {
2139 // On plain objects events is a fn that holds the the data
2140 // which prevents this data from being JSON serialized
2141 // the function does not need to be called, it just contains the data
2142 eventHandle = events.handle;
2143 events = events.events;
2144
2145 } else if ( !events ) {
2146 if ( !elem.nodeType ) {
2147 // On plain objects, create a fn that acts as the holder
2148 // of the values to avoid JSON serialization of event data
2149 elemData[ eventKey ] = elemData = function(){};
2150 }
2151
2152 elemData.events = events = {};
2153 }
2154
2155 if ( !eventHandle ) {
2156 elemData.handle = eventHandle = function() {
2157 // Handle the second event of a trigger and when
2158 // an event is called after a page has unloaded
2159 return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
2160 jQuery.event.handle.apply( eventHandle.elem, arguments ) :
2161 undefined;
2162 };
2163 }
2164
2165 // Add elem as a property of the handle function
2166 // This is to prevent a memory leak with non-native events in IE.
2167 eventHandle.elem = elem;
2168
2169 // Handle multiple events separated by a space
2170 // jQuery(...).bind("mouseover mouseout", fn);
2171 types = types.split(" ");
2172
2173 var type, i = 0, namespaces;
2174
2175 while ( (type = types[ i++ ]) ) {
2176 handleObj = handleObjIn ?
2177 jQuery.extend({}, handleObjIn) :
2178 { handler: handler, data: data };
2179
2180 // Namespaced event handlers
2181 if ( type.indexOf(".") > -1 ) {
2182 namespaces = type.split(".");
2183 type = namespaces.shift();
2184 handleObj.namespace = namespaces.slice(0).sort().join(".");
2185
2186 } else {
2187 namespaces = [];
2188 handleObj.namespace = "";
2189 }
2190
2191 handleObj.type = type;
2192 if ( !handleObj.guid ) {
2193 handleObj.guid = handler.guid;
2194 }
2195
2196 // Get the current list of functions bound to this event
2197 var handlers = events[ type ],
2198 special = jQuery.event.special[ type ] || {};
2199
2200 // Init the event handler queue
2201 if ( !handlers ) {
2202 handlers = events[ type ] = [];
2203
2204 // Check for a special event handler
2205 // Only use addEventListener/attachEvent if the special
2206 // events handler returns false
2207 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
2208 // Bind the global event handler to the element
2209 if ( elem.addEventListener ) {
2210 elem.addEventListener( type, eventHandle, false );
2211
2212 } else if ( elem.attachEvent ) {
2213 elem.attachEvent( "on" + type, eventHandle );
2214 }
2215 }
2216 }
2217
2218 if ( special.add ) {
2219 special.add.call( elem, handleObj );
2220
2221 if ( !handleObj.handler.guid ) {
2222 handleObj.handler.guid = handler.guid;
2223 }
2224 }
2225
2226 // Add the function to the element's handler list
2227 handlers.push( handleObj );
2228
2229 // Keep track of which events have been used, for global triggering
2230 jQuery.event.global[ type ] = true;
2231 }
2232
2233 // Nullify elem to prevent memory leaks in IE
2234 elem = null;
2235 },
2236
2237 global: {},
2238
2239 // Detach an event or set of events from an element
2240 remove: function( elem, types, handler, pos ) {
2241 // don't do events on text and comment nodes
2242 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
2243 return;
2244 }
2245
2246 if ( handler === false ) {
2247 handler = returnFalse;
2248 }
2249
2250 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
2251 elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
2252 events = elemData && elemData[ eventKey ];
2253
2254 if ( !elemData || !events ) {
2255 return;
2256 }
2257
2258 if ( typeof events === "function" ) {
2259 elemData = events;
2260 events = events.events;
2261 }
2262
2263 // types is actually an event object here
2264 if ( types && types.type ) {
2265 handler = types.handler;
2266 types = types.type;
2267 }
2268
2269 // Unbind all events for the element
2270 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
2271 types = types || "";
2272
2273 for ( type in events ) {
2274 jQuery.event.remove( elem, type + types );
2275 }
2276
2277 return;
2278 }
2279
2280 // Handle multiple events separated by a space
2281 // jQuery(...).unbind("mouseover mouseout", fn);
2282 types = types.split(" ");
2283
2284 while ( (type = types[ i++ ]) ) {
2285 origType = type;
2286 handleObj = null;
2287 all = type.indexOf(".") < 0;
2288 namespaces = [];
2289
2290 if ( !all ) {
2291 // Namespaced event handlers
2292 namespaces = type.split(".");
2293 type = namespaces.shift();
2294
2295 namespace = new RegExp("(^|\\.)" +
2296 jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
2297 }
2298
2299 eventType = events[ type ];
2300
2301 if ( !eventType ) {
2302 continue;
2303 }
2304
2305 if ( !handler ) {
2306 for ( j = 0; j < eventType.length; j++ ) {
2307 handleObj = eventType[ j ];
2308
2309 if ( all || namespace.test( handleObj.namespace ) ) {
2310 jQuery.event.remove( elem, origType, handleObj.handler, j );
2311 eventType.splice( j--, 1 );
2312 }
2313 }
2314
2315 continue;
2316 }
2317
2318 special = jQuery.event.special[ type ] || {};
2319
2320 for ( j = pos || 0; j < eventType.length; j++ ) {
2321 handleObj = eventType[ j ];
2322
2323 if ( handler.guid === handleObj.guid ) {
2324 // remove the given handler for the given type
2325 if ( all || namespace.test( handleObj.namespace ) ) {
2326 if ( pos == null ) {
2327 eventType.splice( j--, 1 );
2328 }
2329
2330 if ( special.remove ) {
2331 special.remove.call( elem, handleObj );
2332 }
2333 }
2334
2335 if ( pos != null ) {
2336 break;
2337 }
2338 }
2339 }
2340
2341 // remove generic event handler if no more handlers exist
2342 if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
2343 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
2344 jQuery.removeEvent( elem, type, elemData.handle );
2345 }
2346
2347 ret = null;
2348 delete events[ type ];
2349 }
2350 }
2351
2352 // Remove the expando if it's no longer used
2353 if ( jQuery.isEmptyObject( events ) ) {
2354 var handle = elemData.handle;
2355 if ( handle ) {
2356 handle.elem = null;
2357 }
2358
2359 delete elemData.events;
2360 delete elemData.handle;
2361
2362 if ( typeof elemData === "function" ) {
2363 jQuery.removeData( elem, eventKey, true );
2364
2365 } else if ( jQuery.isEmptyObject( elemData ) ) {
2366 jQuery.removeData( elem, undefined, true );
2367 }
2368 }
2369 },
2370
2371 // bubbling is internal
2372 trigger: function( event, data, elem /*, bubbling */ ) {
2373 // Event object or event type
2374 var type = event.type || event,
2375 bubbling = arguments[3];
2376
2377 if ( !bubbling ) {
2378 event = typeof event === "object" ?
2379 // jQuery.Event object
2380 event[ jQuery.expando ] ? event :
2381 // Object literal
2382 jQuery.extend( jQuery.Event(type), event ) :
2383 // Just the event type (string)
2384 jQuery.Event(type);
2385
2386 if ( type.indexOf("!") >= 0 ) {
2387 event.type = type = type.slice(0, -1);
2388 event.exclusive = true;
2389 }
2390
2391 // Handle a global trigger
2392 if ( !elem ) {
2393 // Don't bubble custom events when global (to avoid too much overhead)
2394 event.stopPropagation();
2395
2396 // Only trigger if we've ever bound an event for it
2397 if ( jQuery.event.global[ type ] ) {
2398 // XXX This code smells terrible. event.js should not be directly
2399 // inspecting the data cache
2400 jQuery.each( jQuery.cache, function() {
2401 // internalKey variable is just used to make it easier to find
2402 // and potentially change this stuff later; currently it just
2403 // points to jQuery.expando
2404 var internalKey = jQuery.expando,
2405 internalCache = this[ internalKey ];
2406 if ( internalCache && internalCache.events && internalCache.events[type] ) {
2407 jQuery.event.trigger( event, data, internalCache.handle.elem );
2408 }
2409 });
2410 }
2411 }
2412
2413 // Handle triggering a single element
2414
2415 // don't do events on text and comment nodes
2416 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
2417 return undefined;
2418 }
2419
2420 // Clean up in case it is reused
2421 event.result = undefined;
2422 event.target = elem;
2423
2424 // Clone the incoming data, if any
2425 data = jQuery.makeArray( data );
2426 data.unshift( event );
2427 }
2428
2429 event.currentTarget = elem;
2430
2431 // Trigger the event, it is assumed that "handle" is a function
2432 var handle = elem.nodeType ?
2433 jQuery._data( elem, "handle" ) :
2434 (jQuery._data( elem, eventKey ) || {}).handle;
2435
2436 if ( handle ) {
2437 handle.apply( elem, data );
2438 }
2439
2440 var parent = elem.parentNode || elem.ownerDocument;
2441
2442 // Trigger an inline bound script
2443 try {
2444 if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
2445 if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
2446 event.result = false;
2447 event.preventDefault();
2448 }
2449 }
2450
2451 // prevent IE from throwing an error for some elements with some event types, see #3533
2452 } catch (inlineError) {}
2453
2454 if ( !event.isPropagationStopped() && parent ) {
2455 jQuery.event.trigger( event, data, parent, true );
2456
2457 } else if ( !event.isDefaultPrevented() ) {
2458 var old,
2459 target = event.target,
2460 targetType = type.replace( rnamespaces, "" ),
2461 isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
2462 special = jQuery.event.special[ targetType ] || {};
2463
2464 if ( (!special._default || special._default.call( elem, event ) === false) &&
2465 !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
2466
2467 try {
2468 if ( target[ targetType ] ) {
2469 // Make sure that we don't accidentally re-trigger the onFOO events
2470 old = target[ "on" + targetType ];
2471
2472 if ( old ) {
2473 target[ "on" + targetType ] = null;
2474 }
2475
2476 jQuery.event.triggered = true;
2477 target[ targetType ]();
2478 }
2479
2480 // prevent IE from throwing an error for some elements with some event types, see #3533
2481 } catch (triggerError) {}
2482
2483 if ( old ) {
2484 target[ "on" + targetType ] = old;
2485 }
2486
2487 jQuery.event.triggered = false;
2488 }
2489 }
2490 },
2491
2492 handle: function( event ) {
2493 var all, handlers, namespaces, namespace_re, events,
2494 namespace_sort = [],
2495 args = jQuery.makeArray( arguments );
2496
2497 event = args[0] = jQuery.event.fix( event || window.event );
2498 event.currentTarget = this;
2499
2500 // Namespaced event handlers
2501 all = event.type.indexOf(".") < 0 && !event.exclusive;
2502
2503 if ( !all ) {
2504 namespaces = event.type.split(".");
2505 event.type = namespaces.shift();
2506 namespace_sort = namespaces.slice(0).sort();
2507 namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
2508 }
2509
2510 event.namespace = event.namespace || namespace_sort.join(".");
2511
2512 events = jQuery._data(this, eventKey);
2513
2514 if ( typeof events === "function" ) {
2515 events = events.events;
2516 }
2517
2518 handlers = (events || {})[ event.type ];
2519
2520 if ( events && handlers ) {
2521 // Clone the handlers to prevent manipulation
2522 handlers = handlers.slice(0);
2523
2524 for ( var j = 0, l = handlers.length; j < l; j++ ) {
2525 var handleObj = handlers[ j ];
2526
2527 // Filter the functions by class
2528 if ( all || namespace_re.test( handleObj.namespace ) ) {
2529 // Pass in a reference to the handler function itself
2530 // So that we can later remove it
2531 event.handler = handleObj.handler;
2532 event.data = handleObj.data;
2533 event.handleObj = handleObj;
2534
2535 var ret = handleObj.handler.apply( this, args );
2536
2537 if ( ret !== undefined ) {
2538 event.result = ret;
2539 if ( ret === false ) {
2540 event.preventDefault();
2541 event.stopPropagation();
2542 }
2543 }
2544
2545 if ( event.isImmediatePropagationStopped() ) {
2546 break;
2547 }
2548 }
2549 }
2550 }
2551
2552 return event.result;
2553 },
2554
2555 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(" "),
2556
2557 fix: function( event ) {
2558 if ( event[ jQuery.expando ] ) {
2559 return event;
2560 }
2561
2562 // store a copy of the original event object
2563 // and "clone" to set read-only properties
2564 var originalEvent = event;
2565 event = jQuery.Event( originalEvent );
2566
2567 for ( var i = this.props.length, prop; i; ) {
2568 prop = this.props[ --i ];
2569 event[ prop ] = originalEvent[ prop ];
2570 }
2571
2572 // Fix target property, if necessary
2573 if ( !event.target ) {
2574 // Fixes #1925 where srcElement might not be defined either
2575 event.target = event.srcElement || document;
2576 }
2577
2578 // check if target is a textnode (safari)
2579 if ( event.target.nodeType === 3 ) {
2580 event.target = event.target.parentNode;
2581 }
2582
2583 // Add relatedTarget, if necessary
2584 if ( !event.relatedTarget && event.fromElement ) {
2585 event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
2586 }
2587
2588 // Calculate pageX/Y if missing and clientX/Y available
2589 if ( event.pageX == null && event.clientX != null ) {
2590 var doc = document.documentElement,
2591 body = document.body;
2592
2593 event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
2594 event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
2595 }
2596
2597 // Add which for key events
2598 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
2599 event.which = event.charCode != null ? event.charCode : event.keyCode;
2600 }
2601
2602 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
2603 if ( !event.metaKey && event.ctrlKey ) {
2604 event.metaKey = event.ctrlKey;
2605 }
2606
2607 // Add which for click: 1 === left; 2 === middle; 3 === right
2608 // Note: button is not normalized, so don't use it
2609 if ( !event.which && event.button !== undefined ) {
2610 event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
2611 }
2612
2613 return event;
2614 },
2615
2616 // Deprecated, use jQuery.guid instead
2617 guid: 1E8,
2618
2619 // Deprecated, use jQuery.proxy instead
2620 proxy: jQuery.proxy,
2621
2622 special: {
2623 ready: {
2624 // Make sure the ready event is setup
2625 setup: jQuery.bindReady,
2626 teardown: jQuery.noop
2627 },
2628
2629 live: {
2630 add: function( handleObj ) {
2631 jQuery.event.add( this,
2632 liveConvert( handleObj.origType, handleObj.selector ),
2633 jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
2634 },
2635
2636 remove: function( handleObj ) {
2637 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
2638 }
2639 },
2640
2641 beforeunload: {
2642 setup: function( data, namespaces, eventHandle ) {
2643 // We only want to do this special case on windows
2644 if ( jQuery.isWindow( this ) ) {
2645 this.onbeforeunload = eventHandle;
2646 }
2647 },
2648
2649 teardown: function( namespaces, eventHandle ) {
2650 if ( this.onbeforeunload === eventHandle ) {
2651 this.onbeforeunload = null;
2652 }
2653 }
2654 }
2655 }
2656};
2657
2658jQuery.removeEvent = document.removeEventListener ?
2659 function( elem, type, handle ) {
2660 if ( elem.removeEventListener ) {
2661 elem.removeEventListener( type, handle, false );
2662 }
2663 } :
2664 function( elem, type, handle ) {
2665 if ( elem.detachEvent ) {
2666 elem.detachEvent( "on" + type, handle );
2667 }
2668 };
2669
2670jQuery.Event = function( src ) {
2671 // Allow instantiation without the 'new' keyword
2672 if ( !this.preventDefault ) {
2673 return new jQuery.Event( src );
2674 }
2675
2676 // Event object
2677 if ( src && src.type ) {
2678 this.originalEvent = src;
2679 this.type = src.type;
2680
2681 // Events bubbling up the document may have been marked as prevented
2682 // by a handler lower down the tree; reflect the correct value.
2683 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
2684 src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
2685
2686 // Event type
2687 } else {
2688 this.type = src;
2689 }
2690
2691 // timeStamp is buggy for some events on Firefox(#3843)
2692 // So we won't rely on the native value
2693 this.timeStamp = jQuery.now();
2694
2695 // Mark it as fixed
2696 this[ jQuery.expando ] = true;
2697};
2698
2699function returnFalse() {
2700 return false;
2701}
2702function returnTrue() {
2703 return true;
2704}
2705
2706// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
2707// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
2708jQuery.Event.prototype = {
2709 preventDefault: function() {
2710 this.isDefaultPrevented = returnTrue;
2711
2712 var e = this.originalEvent;
2713 if ( !e ) {
2714 return;
2715 }
2716
2717 // if preventDefault exists run it on the original event
2718 if ( e.preventDefault ) {
2719 e.preventDefault();
2720
2721 // otherwise set the returnValue property of the original event to false (IE)
2722 } else {
2723 e.returnValue = false;
2724 }
2725 },
2726 stopPropagation: function() {
2727 this.isPropagationStopped = returnTrue;
2728
2729 var e = this.originalEvent;
2730 if ( !e ) {
2731 return;
2732 }
2733 // if stopPropagation exists run it on the original event
2734 if ( e.stopPropagation ) {
2735 e.stopPropagation();
2736 }
2737 // otherwise set the cancelBubble property of the original event to true (IE)
2738 e.cancelBubble = true;
2739 },
2740 stopImmediatePropagation: function() {
2741 this.isImmediatePropagationStopped = returnTrue;
2742 this.stopPropagation();
2743 },
2744 isDefaultPrevented: returnFalse,
2745 isPropagationStopped: returnFalse,
2746 isImmediatePropagationStopped: returnFalse
2747};
2748
2749// Checks if an event happened on an element within another element
2750// Used in jQuery.event.special.mouseenter and mouseleave handlers
2751var withinElement = function( event ) {
2752 // Check if mouse(over|out) are still within the same parent element
2753 var parent = event.relatedTarget;
2754
2755 // Firefox sometimes assigns relatedTarget a XUL element
2756 // which we cannot access the parentNode property of
2757 try {
2758 // Traverse up the tree
2759 while ( parent && parent !== this ) {
2760 parent = parent.parentNode;
2761 }
2762
2763 if ( parent !== this ) {
2764 // set the correct event type
2765 event.type = event.data;
2766
2767 // handle event if we actually just moused on to a non sub-element
2768 jQuery.event.handle.apply( this, arguments );
2769 }
2770
2771 // assuming we've left the element since we most likely mousedover a xul element
2772 } catch(e) { }
2773},
2774
2775// In case of event delegation, we only need to rename the event.type,
2776// liveHandler will take care of the rest.
2777delegate = function( event ) {
2778 event.type = event.data;
2779 jQuery.event.handle.apply( this, arguments );
2780};
2781
2782// Create mouseenter and mouseleave events
2783jQuery.each({
2784 mouseenter: "mouseover",
2785 mouseleave: "mouseout"
2786}, function( orig, fix ) {
2787 jQuery.event.special[ orig ] = {
2788 setup: function( data ) {
2789 jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
2790 },
2791 teardown: function( data ) {
2792 jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
2793 }
2794 };
2795});
2796
2797// submit delegation
2798if ( !jQuery.support.submitBubbles ) {
2799
2800 jQuery.event.special.submit = {
2801 setup: function( data, namespaces ) {
2802 if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
2803 jQuery.event.add(this, "click.specialSubmit", function( e ) {
2804 var elem = e.target,
2805 type = elem.type;
2806
2807 if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
2808 e.liveFired = undefined;
2809 return trigger( "submit", this, arguments );
2810 }
2811 });
2812
2813 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
2814 var elem = e.target,
2815 type = elem.type;
2816
2817 if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
2818 e.liveFired = undefined;
2819 return trigger( "submit", this, arguments );
2820 }
2821 });
2822
2823 } else {
2824 return false;
2825 }
2826 },
2827
2828 teardown: function( namespaces ) {
2829 jQuery.event.remove( this, ".specialSubmit" );
2830 }
2831 };
2832
2833}
2834
2835// change delegation, happens here so we have bind.
2836if ( !jQuery.support.changeBubbles ) {
2837
2838 var changeFilters,
2839
2840 getVal = function( elem ) {
2841 var type = elem.type, val = elem.value;
2842
2843 if ( type === "radio" || type === "checkbox" ) {
2844 val = elem.checked;
2845
2846 } else if ( type === "select-multiple" ) {
2847 val = elem.selectedIndex > -1 ?
2848 jQuery.map( elem.options, function( elem ) {
2849 return elem.selected;
2850 }).join("-") :
2851 "";
2852
2853 } else if ( elem.nodeName.toLowerCase() === "select" ) {
2854 val = elem.selectedIndex;
2855 }
2856
2857 return val;
2858 },
2859
2860 testChange = function testChange( e ) {
2861 var elem = e.target, data, val;
2862
2863 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
2864 return;
2865 }
2866
2867 data = jQuery._data( elem, "_change_data" );
2868 val = getVal(elem);
2869
2870 // the current data will be also retrieved by beforeactivate
2871 if ( e.type !== "focusout" || elem.type !== "radio" ) {
2872 jQuery._data( elem, "_change_data", val );
2873 }
2874
2875 if ( data === undefined || val === data ) {
2876 return;
2877 }
2878
2879 if ( data != null || val ) {
2880 e.type = "change";
2881 e.liveFired = undefined;
2882 return jQuery.event.trigger( e, arguments[1], elem );
2883 }
2884 };
2885
2886 jQuery.event.special.change = {
2887 filters: {
2888 focusout: testChange,
2889
2890 beforedeactivate: testChange,
2891
2892 click: function( e ) {
2893 var elem = e.target, type = elem.type;
2894
2895 if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
2896 return testChange.call( this, e );
2897 }
2898 },
2899
2900 // Change has to be called before submit
2901 // Keydown will be called before keypress, which is used in submit-event delegation
2902 keydown: function( e ) {
2903 var elem = e.target, type = elem.type;
2904
2905 if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
2906 (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
2907 type === "select-multiple" ) {
2908 return testChange.call( this, e );
2909 }
2910 },
2911
2912 // Beforeactivate happens also before the previous element is blurred
2913 // with this event you can't trigger a change event, but you can store
2914 // information
2915 beforeactivate: function( e ) {
2916 var elem = e.target;
2917 jQuery._data( elem, "_change_data", getVal(elem) );
2918 }
2919 },
2920
2921 setup: function( data, namespaces ) {
2922 if ( this.type === "file" ) {
2923 return false;
2924 }
2925
2926 for ( var type in changeFilters ) {
2927 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
2928 }
2929
2930 return rformElems.test( this.nodeName );
2931 },
2932
2933 teardown: function( namespaces ) {
2934 jQuery.event.remove( this, ".specialChange" );
2935
2936 return rformElems.test( this.nodeName );
2937 }
2938 };
2939
2940 changeFilters = jQuery.event.special.change.filters;
2941
2942 // Handle when the input is .focus()'d
2943 changeFilters.focus = changeFilters.beforeactivate;
2944}
2945
2946function trigger( type, elem, args ) {
2947 args[0].type = type;
2948 return jQuery.event.handle.apply( elem, args );
2949}
2950
2951// Create "bubbling" focus and blur events
2952if ( document.addEventListener ) {
2953 jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
2954 jQuery.event.special[ fix ] = {
2955 setup: function() {
2956 this.addEventListener( orig, handler, true );
2957 },
2958 teardown: function() {
2959 this.removeEventListener( orig, handler, true );
2960 }
2961 };
2962
2963 function handler( e ) {
2964 e = jQuery.event.fix( e );
2965 e.type = fix;
2966 return jQuery.event.handle.call( this, e );
2967 }
2968 });
2969}
2970
2971jQuery.each(["bind", "one"], function( i, name ) {
2972 jQuery.fn[ name ] = function( type, data, fn ) {
2973 // Handle object literals
2974 if ( typeof type === "object" ) {
2975 for ( var key in type ) {
2976 this[ name ](key, data, type[key], fn);
2977 }
2978 return this;
2979 }
2980
2981 if ( jQuery.isFunction( data ) || data === false ) {
2982 fn = data;
2983 data = undefined;
2984 }
2985
2986 var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
2987 jQuery( this ).unbind( event, handler );
2988 return fn.apply( this, arguments );
2989 }) : fn;
2990
2991 if ( type === "unload" && name !== "one" ) {
2992 this.one( type, data, fn );
2993
2994 } else {
2995 for ( var i = 0, l = this.length; i < l; i++ ) {
2996 jQuery.event.add( this[i], type, handler, data );
2997 }
2998 }
2999
3000 return this;
3001 };
3002});
3003
3004jQuery.fn.extend({
3005 unbind: function( type, fn ) {
3006 // Handle object literals
3007 if ( typeof type === "object" && !type.preventDefault ) {
3008 for ( var key in type ) {
3009 this.unbind(key, type[key]);
3010 }
3011
3012 } else {
3013 for ( var i = 0, l = this.length; i < l; i++ ) {
3014 jQuery.event.remove( this[i], type, fn );
3015 }
3016 }
3017
3018 return this;
3019 },
3020
3021 delegate: function( selector, types, data, fn ) {
3022 return this.live( types, data, fn, selector );
3023 },
3024
3025 undelegate: function( selector, types, fn ) {
3026 if ( arguments.length === 0 ) {
3027 return this.unbind( "live" );
3028
3029 } else {
3030 return this.die( types, null, fn, selector );
3031 }
3032 },
3033
3034 trigger: function( type, data ) {
3035 return this.each(function() {
3036 jQuery.event.trigger( type, data, this );
3037 });
3038 },
3039
3040 triggerHandler: function( type, data ) {
3041 if ( this[0] ) {
3042 var event = jQuery.Event( type );
3043 event.preventDefault();
3044 event.stopPropagation();
3045 jQuery.event.trigger( event, data, this[0] );
3046 return event.result;
3047 }
3048 },
3049
3050 toggle: function( fn ) {
3051 // Save reference to arguments for access in closure
3052 var args = arguments,
3053 i = 1;
3054
3055 // link all the functions, so any of them can unbind this click handler
3056 while ( i < args.length ) {
3057 jQuery.proxy( fn, args[ i++ ] );
3058 }
3059
3060 return this.click( jQuery.proxy( fn, function( event ) {
3061 // Figure out which function to execute
3062 var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
3063 jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
3064
3065 // Make sure that clicks stop
3066 event.preventDefault();
3067
3068 // and execute the function
3069 return args[ lastToggle ].apply( this, arguments ) || false;
3070 }));
3071 },
3072
3073 hover: function( fnOver, fnOut ) {
3074 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
3075 }
3076});
3077
3078var liveMap = {
3079 focus: "focusin",
3080 blur: "focusout",
3081 mouseenter: "mouseover",
3082 mouseleave: "mouseout"
3083};
3084
3085jQuery.each(["live", "die"], function( i, name ) {
3086 jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
3087 var type, i = 0, match, namespaces, preType,
3088 selector = origSelector || this.selector,
3089 context = origSelector ? this : jQuery( this.context );
3090
3091 if ( typeof types === "object" && !types.preventDefault ) {
3092 for ( var key in types ) {
3093 context[ name ]( key, data, types[key], selector );
3094 }
3095
3096 return this;
3097 }
3098
3099 if ( jQuery.isFunction( data ) ) {
3100 fn = data;
3101 data = undefined;
3102 }
3103
3104 types = (types || "").split(" ");
3105
3106 while ( (type = types[ i++ ]) != null ) {
3107 match = rnamespaces.exec( type );
3108 namespaces = "";
3109
3110 if ( match ) {
3111 namespaces = match[0];
3112 type = type.replace( rnamespaces, "" );
3113 }
3114
3115 if ( type === "hover" ) {
3116 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
3117 continue;
3118 }
3119
3120 preType = type;
3121
3122 if ( type === "focus" || type === "blur" ) {
3123 types.push( liveMap[ type ] + namespaces );
3124 type = type + namespaces;
3125
3126 } else {
3127 type = (liveMap[ type ] || type) + namespaces;
3128 }
3129
3130 if ( name === "live" ) {
3131 // bind live handler
3132 for ( var j = 0, l = context.length; j < l; j++ ) {
3133 jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
3134 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
3135 }
3136
3137 } else {
3138 // unbind live handler
3139 context.unbind( "live." + liveConvert( type, selector ), fn );
3140 }
3141 }
3142
3143 return this;
3144 };
3145});
3146
3147function liveHandler( event ) {
3148 var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
3149 elems = [],
3150 selectors = [],
3151 events = jQuery._data( this, eventKey );
3152
3153 if ( typeof events === "function" ) {
3154 events = events.events;
3155 }
3156
3157 // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
3158 if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
3159 return;
3160 }
3161
3162 if ( event.namespace ) {
3163 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
3164 }
3165
3166 event.liveFired = this;
3167
3168 var live = events.live.slice(0);
3169
3170 for ( j = 0; j < live.length; j++ ) {
3171 handleObj = live[j];
3172
3173 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
3174 selectors.push( handleObj.selector );
3175
3176 } else {
3177 live.splice( j--, 1 );
3178 }
3179 }
3180
3181 match = jQuery( event.target ).closest( selectors, event.currentTarget );
3182
3183 for ( i = 0, l = match.length; i < l; i++ ) {
3184 close = match[i];
3185
3186 for ( j = 0; j < live.length; j++ ) {
3187 handleObj = live[j];
3188
3189 if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) ) {
3190 elem = close.elem;
3191 related = null;
3192
3193 // Those two events require additional checking
3194 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
3195 event.type = handleObj.preType;
3196 related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
3197 }
3198
3199 if ( !related || related !== elem ) {
3200 elems.push({ elem: elem, handleObj: handleObj, level: close.level });
3201 }
3202 }
3203 }
3204 }
3205
3206 for ( i = 0, l = elems.length; i < l; i++ ) {
3207 match = elems[i];
3208
3209 if ( maxLevel && match.level > maxLevel ) {
3210 break;
3211 }
3212
3213 event.currentTarget = match.elem;
3214 event.data = match.handleObj.data;
3215 event.handleObj = match.handleObj;
3216
3217 ret = match.handleObj.origHandler.apply( match.elem, arguments );
3218
3219 if ( ret === false || event.isPropagationStopped() ) {
3220 maxLevel = match.level;
3221
3222 if ( ret === false ) {
3223 stop = false;
3224 }
3225 if ( event.isImmediatePropagationStopped() ) {
3226 break;
3227 }
3228 }
3229 }
3230
3231 return stop;
3232}
3233
3234function liveConvert( type, selector ) {
3235 return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
3236}
3237
3238jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
3239 "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
3240 "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
3241
3242 // Handle event binding
3243 jQuery.fn[ name ] = function( data, fn ) {
3244 if ( fn == null ) {
3245 fn = data;
3246 data = null;
3247 }
3248
3249 return arguments.length > 0 ?
3250 this.bind( name, data, fn ) :
3251 this.trigger( name );
3252 };
3253
3254 if ( jQuery.attrFn ) {
3255 jQuery.attrFn[ name ] = true;
3256 }
3257});
3258
3259
3260/*!
3261 * Sizzle CSS Selector Engine
3262 * Copyright 2011, The Dojo Foundation
3263 * Released under the MIT, BSD, and GPL Licenses.
3264 * More information: http://sizzlejs.com/
3265 */
3266(function(){
3267
3268var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
3269 done = 0,
3270 toString = Object.prototype.toString,
3271 hasDuplicate = false,
3272 baseHasDuplicate = true;
3273
3274// Here we check if the JavaScript engine is using some sort of
3275// optimization where it does not always call our comparision
3276// function. If that is the case, discard the hasDuplicate value.
3277// Thus far that includes Google Chrome.
3278[0, 0].sort(function() {
3279 baseHasDuplicate = false;
3280 return 0;
3281});
3282
3283var Sizzle = function( selector, context, results, seed ) {
3284 results = results || [];
3285 context = context || document;
3286
3287 var origContext = context;
3288
3289 if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
3290 return [];
3291 }
3292
3293 if ( !selector || typeof selector !== "string" ) {
3294 return results;
3295 }
3296
3297 var m, set, checkSet, extra, ret, cur, pop, i,
3298 prune = true,
3299 contextXML = Sizzle.isXML( context ),
3300 parts = [],
3301 soFar = selector;
3302
3303 // Reset the position of the chunker regexp (start from head)
3304 do {
3305 chunker.exec( "" );
3306 m = chunker.exec( soFar );
3307
3308 if ( m ) {
3309 soFar = m[3];
3310
3311 parts.push( m[1] );
3312
3313 if ( m[2] ) {
3314 extra = m[3];
3315 break;
3316 }
3317 }
3318 } while ( m );
3319
3320 if ( parts.length > 1 && origPOS.exec( selector ) ) {
3321
3322 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
3323 set = posProcess( parts[0] + parts[1], context );
3324
3325 } else {
3326 set = Expr.relative[ parts[0] ] ?
3327 [ context ] :
3328 Sizzle( parts.shift(), context );
3329
3330 while ( parts.length ) {
3331 selector = parts.shift();
3332
3333 if ( Expr.relative[ selector ] ) {
3334 selector += parts.shift();
3335 }
3336
3337 set = posProcess( selector, set );
3338 }
3339 }
3340
3341 } else {
3342 // Take a shortcut and set the context if the root selector is an ID
3343 // (but not if it'll be faster if the inner selector is an ID)
3344 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
3345 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
3346
3347 ret = Sizzle.find( parts.shift(), context, contextXML );
3348 context = ret.expr ?
3349 Sizzle.filter( ret.expr, ret.set )[0] :
3350 ret.set[0];
3351 }
3352
3353 if ( context ) {
3354 ret = seed ?
3355 { expr: parts.pop(), set: makeArray(seed) } :
3356 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
3357
3358 set = ret.expr ?
3359 Sizzle.filter( ret.expr, ret.set ) :
3360 ret.set;
3361
3362 if ( parts.length > 0 ) {
3363 checkSet = makeArray( set );
3364
3365 } else {
3366 prune = false;
3367 }
3368
3369 while ( parts.length ) {
3370 cur = parts.pop();
3371 pop = cur;
3372
3373 if ( !Expr.relative[ cur ] ) {
3374 cur = "";
3375 } else {
3376 pop = parts.pop();
3377 }
3378
3379 if ( pop == null ) {
3380 pop = context;
3381 }
3382
3383 Expr.relative[ cur ]( checkSet, pop, contextXML );
3384 }
3385
3386 } else {
3387 checkSet = parts = [];
3388 }
3389 }
3390
3391 if ( !checkSet ) {
3392 checkSet = set;
3393 }
3394
3395 if ( !checkSet ) {
3396 Sizzle.error( cur || selector );
3397 }
3398
3399 if ( toString.call(checkSet) === "[object Array]" ) {
3400 if ( !prune ) {
3401 results.push.apply( results, checkSet );
3402
3403 } else if ( context && context.nodeType === 1 ) {
3404 for ( i = 0; checkSet[i] != null; i++ ) {
3405 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
3406 results.push( set[i] );
3407 }
3408 }
3409
3410 } else {
3411 for ( i = 0; checkSet[i] != null; i++ ) {
3412 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
3413 results.push( set[i] );
3414 }
3415 }
3416 }
3417
3418 } else {
3419 makeArray( checkSet, results );
3420 }
3421
3422 if ( extra ) {
3423 Sizzle( extra, origContext, results, seed );
3424 Sizzle.uniqueSort( results );
3425 }
3426
3427 return results;
3428};
3429
3430Sizzle.uniqueSort = function( results ) {
3431 if ( sortOrder ) {
3432 hasDuplicate = baseHasDuplicate;
3433 results.sort( sortOrder );
3434
3435 if ( hasDuplicate ) {
3436 for ( var i = 1; i < results.length; i++ ) {
3437 if ( results[i] === results[ i - 1 ] ) {
3438 results.splice( i--, 1 );
3439 }
3440 }
3441 }
3442 }
3443
3444 return results;
3445};
3446
3447Sizzle.matches = function( expr, set ) {
3448 return Sizzle( expr, null, null, set );
3449};
3450
3451Sizzle.matchesSelector = function( node, expr ) {
3452 return Sizzle( expr, null, null, [node] ).length > 0;
3453};
3454
3455Sizzle.find = function( expr, context, isXML ) {
3456 var set;
3457
3458 if ( !expr ) {
3459 return [];
3460 }
3461
3462 for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
3463 var match,
3464 type = Expr.order[i];
3465
3466 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
3467 var left = match[1];
3468 match.splice( 1, 1 );
3469
3470 if ( left.substr( left.length - 1 ) !== "\\" ) {
3471 match[1] = (match[1] || "").replace(/\\/g, "");
3472 set = Expr.find[ type ]( match, context, isXML );
3473
3474 if ( set != null ) {
3475 expr = expr.replace( Expr.match[ type ], "" );
3476 break;
3477 }
3478 }
3479 }
3480 }
3481
3482 if ( !set ) {
3483 set = typeof context.getElementsByTagName !== "undefined" ?
3484 context.getElementsByTagName( "*" ) :
3485 [];
3486 }
3487
3488 return { set: set, expr: expr };
3489};
3490
3491Sizzle.filter = function( expr, set, inplace, not ) {
3492 var match, anyFound,
3493 old = expr,
3494 result = [],
3495 curLoop = set,
3496 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
3497
3498 while ( expr && set.length ) {
3499 for ( var type in Expr.filter ) {
3500 if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
3501 var found, item,
3502 filter = Expr.filter[ type ],
3503 left = match[1];
3504
3505 anyFound = false;
3506
3507 match.splice(1,1);
3508
3509 if ( left.substr( left.length - 1 ) === "\\" ) {
3510 continue;
3511 }
3512
3513 if ( curLoop === result ) {
3514 result = [];
3515 }
3516
3517 if ( Expr.preFilter[ type ] ) {
3518 match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
3519
3520 if ( !match ) {
3521 anyFound = found = true;
3522
3523 } else if ( match === true ) {
3524 continue;
3525 }
3526 }
3527
3528 if ( match ) {
3529 for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
3530 if ( item ) {
3531 found = filter( item, match, i, curLoop );
3532 var pass = not ^ !!found;
3533
3534 if ( inplace && found != null ) {
3535 if ( pass ) {
3536 anyFound = true;
3537
3538 } else {
3539 curLoop[i] = false;
3540 }
3541
3542 } else if ( pass ) {
3543 result.push( item );
3544 anyFound = true;
3545 }
3546 }
3547 }
3548 }
3549
3550 if ( found !== undefined ) {
3551 if ( !inplace ) {
3552 curLoop = result;
3553 }
3554
3555 expr = expr.replace( Expr.match[ type ], "" );
3556
3557 if ( !anyFound ) {
3558 return [];
3559 }
3560
3561 break;
3562 }
3563 }
3564 }
3565
3566 // Improper expression
3567 if ( expr === old ) {
3568 if ( anyFound == null ) {
3569 Sizzle.error( expr );
3570
3571 } else {
3572 break;
3573 }
3574 }
3575
3576 old = expr;
3577 }
3578
3579 return curLoop;
3580};
3581
3582Sizzle.error = function( msg ) {
3583 throw "Syntax error, unrecognized expression: " + msg;
3584};
3585
3586var Expr = Sizzle.selectors = {
3587 order: [ "ID", "NAME", "TAG" ],
3588
3589 match: {
3590 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
3591 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
3592 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
3593 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
3594 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
3595 CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
3596 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
3597 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
3598 },
3599
3600 leftMatch: {},
3601
3602 attrMap: {
3603 "class": "className",
3604 "for": "htmlFor"
3605 },
3606
3607 attrHandle: {
3608 href: function( elem ) {
3609 return elem.getAttribute( "href" );
3610 }
3611 },
3612
3613 relative: {
3614 "+": function(checkSet, part){
3615 var isPartStr = typeof part === "string",
3616 isTag = isPartStr && !/\W/.test( part ),
3617 isPartStrNotTag = isPartStr && !isTag;
3618
3619 if ( isTag ) {
3620 part = part.toLowerCase();
3621 }
3622
3623 for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
3624 if ( (elem = checkSet[i]) ) {
3625 while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
3626
3627 checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
3628 elem || false :
3629 elem === part;
3630 }
3631 }
3632
3633 if ( isPartStrNotTag ) {
3634 Sizzle.filter( part, checkSet, true );
3635 }
3636 },
3637
3638 ">": function( checkSet, part ) {
3639 var elem,
3640 isPartStr = typeof part === "string",
3641 i = 0,
3642 l = checkSet.length;
3643
3644 if ( isPartStr && !/\W/.test( part ) ) {
3645 part = part.toLowerCase();
3646
3647 for ( ; i < l; i++ ) {
3648 elem = checkSet[i];
3649
3650 if ( elem ) {
3651 var parent = elem.parentNode;
3652 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
3653 }
3654 }
3655
3656 } else {
3657 for ( ; i < l; i++ ) {
3658 elem = checkSet[i];
3659
3660 if ( elem ) {
3661 checkSet[i] = isPartStr ?
3662 elem.parentNode :
3663 elem.parentNode === part;
3664 }
3665 }
3666
3667 if ( isPartStr ) {
3668 Sizzle.filter( part, checkSet, true );
3669 }
3670 }
3671 },
3672
3673 "": function(checkSet, part, isXML){
3674 var nodeCheck,
3675 doneName = done++,
3676 checkFn = dirCheck;
3677
3678 if ( typeof part === "string" && !/\W/.test(part) ) {
3679 part = part.toLowerCase();
3680 nodeCheck = part;
3681 checkFn = dirNodeCheck;
3682 }
3683
3684 checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
3685 },
3686
3687 "~": function( checkSet, part, isXML ) {
3688 var nodeCheck,
3689 doneName = done++,
3690 checkFn = dirCheck;
3691
3692 if ( typeof part === "string" && !/\W/.test( part ) ) {
3693 part = part.toLowerCase();
3694 nodeCheck = part;
3695 checkFn = dirNodeCheck;
3696 }
3697
3698 checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
3699 }
3700 },
3701
3702 find: {
3703 ID: function( match, context, isXML ) {
3704 if ( typeof context.getElementById !== "undefined" && !isXML ) {
3705 var m = context.getElementById(match[1]);
3706 // Check parentNode to catch when Blackberry 4.6 returns
3707 // nodes that are no longer in the document #6963
3708 return m && m.parentNode ? [m] : [];
3709 }
3710 },
3711
3712 NAME: function( match, context ) {
3713 if ( typeof context.getElementsByName !== "undefined" ) {
3714 var ret = [],
3715 results = context.getElementsByName( match[1] );
3716
3717 for ( var i = 0, l = results.length; i < l; i++ ) {
3718 if ( results[i].getAttribute("name") === match[1] ) {
3719 ret.push( results[i] );
3720 }
3721 }
3722
3723 return ret.length === 0 ? null : ret;
3724 }
3725 },
3726
3727 TAG: function( match, context ) {
3728 if ( typeof context.getElementsByTagName !== "undefined" ) {
3729 return context.getElementsByTagName( match[1] );
3730 }
3731 }
3732 },
3733 preFilter: {
3734 CLASS: function( match, curLoop, inplace, result, not, isXML ) {
3735 match = " " + match[1].replace(/\\/g, "") + " ";
3736
3737 if ( isXML ) {
3738 return match;
3739 }
3740
3741 for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
3742 if ( elem ) {
3743 if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
3744 if ( !inplace ) {
3745 result.push( elem );
3746 }
3747
3748 } else if ( inplace ) {
3749 curLoop[i] = false;
3750 }
3751 }
3752 }
3753
3754 return false;
3755 },
3756
3757 ID: function( match ) {
3758 return match[1].replace(/\\/g, "");
3759 },
3760
3761 TAG: function( match, curLoop ) {
3762 return match[1].toLowerCase();
3763 },
3764
3765 CHILD: function( match ) {
3766 if ( match[1] === "nth" ) {
3767 if ( !match[2] ) {
3768 Sizzle.error( match[0] );
3769 }
3770
3771 match[2] = match[2].replace(/^\+|\s*/g, '');
3772
3773 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
3774 var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
3775 match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
3776 !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
3777
3778 // calculate the numbers (first)n+(last) including if they are negative
3779 match[2] = (test[1] + (test[2] || 1)) - 0;
3780 match[3] = test[3] - 0;
3781 }
3782 else if ( match[2] ) {
3783 Sizzle.error( match[0] );
3784 }
3785
3786 // TODO: Move to normal caching system
3787 match[0] = done++;
3788
3789 return match;
3790 },
3791
3792 ATTR: function( match, curLoop, inplace, result, not, isXML ) {
3793 var name = match[1] = match[1].replace(/\\/g, "");
3794
3795 if ( !isXML && Expr.attrMap[name] ) {
3796 match[1] = Expr.attrMap[name];
3797 }
3798
3799 // Handle if an un-quoted value was used
3800 match[4] = ( match[4] || match[5] || "" ).replace(/\\/g, "");
3801
3802 if ( match[2] === "~=" ) {
3803 match[4] = " " + match[4] + " ";
3804 }
3805
3806 return match;
3807 },
3808
3809 PSEUDO: function( match, curLoop, inplace, result, not ) {
3810 if ( match[1] === "not" ) {
3811 // If we're dealing with a complex expression, or a simple one
3812 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
3813 match[3] = Sizzle(match[3], null, null, curLoop);
3814
3815 } else {
3816 var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
3817
3818 if ( !inplace ) {
3819 result.push.apply( result, ret );
3820 }
3821
3822 return false;
3823 }
3824
3825 } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
3826 return true;
3827 }
3828
3829 return match;
3830 },
3831
3832 POS: function( match ) {
3833 match.unshift( true );
3834
3835 return match;
3836 }
3837 },
3838
3839 filters: {
3840 enabled: function( elem ) {
3841 return elem.disabled === false && elem.type !== "hidden";
3842 },
3843
3844 disabled: function( elem ) {
3845 return elem.disabled === true;
3846 },
3847
3848 checked: function( elem ) {
3849 return elem.checked === true;
3850 },
3851
3852 selected: function( elem ) {
3853 // Accessing this property makes selected-by-default
3854 // options in Safari work properly
3855 elem.parentNode.selectedIndex;
3856
3857 return elem.selected === true;
3858 },
3859
3860 parent: function( elem ) {
3861 return !!elem.firstChild;
3862 },
3863
3864 empty: function( elem ) {
3865 return !elem.firstChild;
3866 },
3867
3868 has: function( elem, i, match ) {
3869 return !!Sizzle( match[3], elem ).length;
3870 },
3871
3872 header: function( elem ) {
3873 return (/h\d/i).test( elem.nodeName );
3874 },
3875
3876 text: function( elem ) {
3877 return "text" === elem.type;
3878 },
3879 radio: function( elem ) {
3880 return "radio" === elem.type;
3881 },
3882
3883 checkbox: function( elem ) {
3884 return "checkbox" === elem.type;
3885 },
3886
3887 file: function( elem ) {
3888 return "file" === elem.type;
3889 },
3890 password: function( elem ) {
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches