r85993 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r85992‎ | r85993 | r85994 >
Date:22:22, 13 April 2011
Author:jeroendedauw
Status:deferred (Comments)
Tags:
Comment:
importing Ratings extension
Modified paths:
  • /trunk/extensions/Ratings (added) (history)
  • /trunk/extensions/Ratings/COPYING (added) (history)
  • /trunk/extensions/Ratings/INSTALL (added) (history)
  • /trunk/extensions/Ratings/README (added) (history)
  • /trunk/extensions/Ratings/RELEASE-NOTES (added) (history)
  • /trunk/extensions/Ratings/Ratings.class.php (added) (history)
  • /trunk/extensions/Ratings/Ratings.hooks.php (added) (history)
  • /trunk/extensions/Ratings/Ratings.i18n.php (added) (history)
  • /trunk/extensions/Ratings/Ratings.php (added) (history)
  • /trunk/extensions/Ratings/Ratings.settings.php (added) (history)
  • /trunk/extensions/Ratings/Ratings.sql (added) (history)
  • /trunk/extensions/Ratings/api (added) (history)
  • /trunk/extensions/Ratings/api/ApiDoRating.php (added) (history)
  • /trunk/extensions/Ratings/api/ApiQueryRatings.php (added) (history)
  • /trunk/extensions/Ratings/starrating (added) (history)
  • /trunk/extensions/Ratings/starrating/RatingsStars.php (added) (history)
  • /trunk/extensions/Ratings/starrating/ext.ratings.stars.js (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/delete.gif (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/documentation.css (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/documentation.html (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/documentation.js (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/index.html (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/jquery.MetaData.js (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/jquery.js (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/jquery.rating.css (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/jquery.rating.js (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/jquery.rating.pack.js (added) (history)
  • /trunk/extensions/Ratings/starrating/star-rating/star.gif (added) (history)
  • /trunk/extensions/Ratings/votesummary (added) (history)
  • /trunk/extensions/Ratings/votesummary/RatingsVoteSummary.php (added) (history)

Diff [purge]

Index: trunk/extensions/Ratings/Ratings.hooks.php
@@ -0,0 +1,63 @@
 2+<?php
 3+
 4+/**
 5+ * Static class for hooks handled by the Ratings extension.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file Ratings.hooks.php
 10+ * @ingroup Ratings
 11+ *
 12+ * @licence GNU GPL v3
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+final class RatingsHooks {
 16+
 17+ /**
 18+ * Schema update to set up the needed database tables.
 19+ *
 20+ * @since 0.1
 21+ *
 22+ * @param DatabaseUpdater $updater
 23+ *
 24+ * @return true
 25+ */
 26+ public static function onSchemaUpdate( /* DatabaseUpdater */ $updater = null ) {
 27+ global $wgDBtype;
 28+
 29+ if ( $wgDBtype == 'mysql' ) {
 30+ // Set up the current schema.
 31+ if ( $updater === null ) {
 32+ global $wgExtNewTables, $wgExtNewIndexes, $wgExtNewFields;
 33+
 34+ $wgExtNewTables[] = array(
 35+ 'votes',
 36+ dirname( __FILE__ ) . '/Ratings.sql',
 37+ true
 38+ );
 39+ $wgExtNewTables[] = array(
 40+ 'votes_props',
 41+ dirname( __FILE__ ) . '/Ratings.sql',
 42+ true
 43+ );
 44+ }
 45+ else {
 46+ $updater->addExtensionUpdate( array(
 47+ 'addTable',
 48+ 'votes',
 49+ dirname( __FILE__ ) . '/Ratings.sql',
 50+ true
 51+ ) );
 52+ $updater->addExtensionUpdate( array(
 53+ 'addTable',
 54+ 'votes_props',
 55+ dirname( __FILE__ ) . '/Ratings.sql',
 56+ true
 57+ ) );
 58+ }
 59+ }
 60+
 61+ return true;
 62+ }
 63+
 64+}
Property changes on: trunk/extensions/Ratings/Ratings.hooks.php
___________________________________________________________________
Added: svn:eol-style
165 + native
Index: trunk/extensions/Ratings/Ratings.class.php
@@ -0,0 +1,152 @@
 2+<?php
 3+
 4+/**
 5+ * Static class for general functions of the Ratings extension.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file Ratings.php
 10+ * @ingroup Ratings
 11+ *
 12+ * @licence GNU GPL v3
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+final class Ratings {
 16+
 17+ /**
 18+ * Cache results for a single request.
 19+ *
 20+ * @since 0.1
 21+ *
 22+ * @var array
 23+ */
 24+ protected static $pageRatings = array();
 25+
 26+ /**
 27+ * Gets a summary message of the current votes for a tag on a page.
 28+ *
 29+ * @since 0.1
 30+ *
 31+ * @param Title $title
 32+ * @param string $tagName
 33+ *
 34+ * @return string
 35+ */
 36+ public static function getRatingSummaryMessage( Title $title, $tagName ) {
 37+ $tagData = self::getCurrentRatingForTag( $title, $tagName );
 38+
 39+ if ( count( $tagData['count'] ) > 0 ) {
 40+ $message = wfMsgExt(
 41+ 'ratings-current-score',
 42+ 'parsemag',
 43+ $tagData['avarage'] + 1, // Internal representatation is 0 based, don't confuse poor users :)
 44+ $tagData['count']
 45+ );
 46+ }
 47+ else {
 48+ $message = wfMsg( 'ratings-no-votes-yet' );
 49+ }
 50+
 51+ return $message;
 52+ }
 53+
 54+ /**
 55+ * Returns the data for the tag in an array, or false is there is no data.
 56+ *
 57+ * @since 0.1
 58+ *
 59+ * @param Title $titleObject
 60+ * @param string $tagName
 61+ *
 62+ * @return false or array
 63+ */
 64+ protected static function getCurrentRatingForTag( Title $titleObject, $tagName ) {
 65+ $title = $titleObject->getFullText();
 66+
 67+ if ( !array_key_exists( $title, self::$pageRatings ) ) {
 68+ self::$pageRatings[$title] = array();
 69+
 70+ // The keys are the tag ids, but they are not known here, so change to tag names, which are known.
 71+ foreach ( self::getPageRatings( $titleObject ) as $tagId => $tagData ) {
 72+ self::$pageRatings[$title][$tagData['name']] = array_merge( array( 'id' => $tagId ), $tagData );
 73+ }
 74+ }
 75+
 76+ return array_key_exists( $tagName, self::$pageRatings[$title] ) ? self::$pageRatings[$title][$tagName] : false;
 77+ }
 78+
 79+ /**
 80+ * Schema update to set up the needed database tables.
 81+ *
 82+ * @since 0.1
 83+ *
 84+ * @param DatabaseUpdater $updater
 85+ *
 86+ * @return true
 87+ */
 88+ public static function getPageRatings( Title $page, $forceUpdate = false ) {
 89+ if ( !$forceUpdate ) {
 90+ $cached = self::getCachedPageRatings( $page );
 91+
 92+ if ( $cached !== false ) {
 93+ return $cached;
 94+ }
 95+ }
 96+
 97+ return self::getAndCalcPageRatings( $page );
 98+ }
 99+
 100+ protected static function getAndCalcPageRatings( Title $page ) {
 101+ $tags = array();
 102+
 103+ foreach ( self::getTagNames() as $tagName => $tagId ) {
 104+ $tags[$tagId] = array( 'count' => 0, 'total' => 0, 'name' => $tagName );
 105+ }
 106+
 107+ $dbr = wfGetDb( DB_SLAVE );
 108+
 109+ $votes = $dbr->select(
 110+ 'votes',
 111+ array(
 112+ 'vote_prop_id',
 113+ 'vote_value'
 114+ ),
 115+ array(
 116+ 'vote_page_id' => $page->getArticleId()
 117+ )
 118+ );
 119+
 120+ while ( $vote = $votes->fetchObject() ) {
 121+ $tags[$vote->vote_prop_id]['count']++;
 122+ $tags[$vote->vote_prop_id]['total'] += $vote->vote_value;
 123+ }
 124+
 125+ foreach ( $tags as &$tag ) {
 126+ $tag['avarage'] = $tag['total'] / $tag['count'];
 127+ }
 128+
 129+ return $tags;
 130+ }
 131+
 132+ protected static function getCachedPageRatings( Title $page ) {
 133+ return false;
 134+ }
 135+
 136+ public static function getTagNames() {
 137+ $dbr = wfGetDb( DB_SLAVE );
 138+
 139+ $props = $dbr->select(
 140+ 'vote_props',
 141+ array( 'prop_id', 'prop_name' )
 142+ );
 143+
 144+ $tags = array();
 145+
 146+ while ( $tag = $props->fetchObject() ) {
 147+ $tags[$tag->prop_name] = $tag->prop_id;
 148+ }
 149+
 150+ return $tags;
 151+ }
 152+
 153+}
Property changes on: trunk/extensions/Ratings/Ratings.class.php
___________________________________________________________________
Added: svn:eol-style
1154 + native
Index: trunk/extensions/Ratings/Ratings.sql
@@ -0,0 +1,21 @@
 2+-- MySQL version of the database schema for the Ratings extension.
 3+
 4+-- Special translations table.
 5+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/votes (
 6+ vote_id INT(10) unsigned NOT NULL auto_increment PRIMARY KEY,
 7+ vote_page_id INT(10) unsigned NOT NULL,
 8+ vote_prop_id INT(5) unsigned NOT NULL,
 9+ vote_user_text VARCHAR(255) binary NOT NULL default '',
 10+ vote_value INT(4) unsigned NOT NULL,
 11+ vote_time CHAR(14) binary NOT NULL default ''
 12+) /*$wgDBTableOptions*/;
 13+
 14+CREATE UNIQUE INDEX vote ON /*$wgDBprefix*/votes (vote_user_text, vote_page_id, vote_prop_id);
 15+
 16+-- Table to keep track of translation memories for the special words.
 17+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/vote_props (
 18+ prop_id INT(5) unsigned NOT NULL auto_increment PRIMARY KEY,
 19+ prop_name VARCHAR(255) NOT NULL
 20+) /*$wgDBTableOptions*/;
 21+
 22+CREATE UNIQUE INDEX prop_name ON /*$wgDBprefix*/vote_props (prop_name);
\ No newline at end of file
Property changes on: trunk/extensions/Ratings/Ratings.sql
___________________________________________________________________
Added: svn:eol-style
123 + native
Index: trunk/extensions/Ratings/INSTALL
@@ -0,0 +1,23 @@
 2+These is the install file for the Ratings extension.
 3+
 4+Extension page on mediawiki.org: http://www.mediawiki.org/wiki/Extension:Ratings
 5+Latest version of the install file: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Ratings/INSTALL?view=co
 6+
 7+
 8+== Installation ==
 9+
 10+Once you have downloaded the code, place the ''Ratings'' directory within your MediaWiki 'extensions' directory.
 11+Then add the following code to your [[Manual:LocalSettings.php|LocalSettings.php]] file:
 12+
 13+# Ratings
 14+require_once( "$IP/extensions/Ratings/Ratings.php" );
 15+
 16+== Configuration ==
 17+
 18+Configuration of Ratings is done by adding simple PHP statements to your [[Manual:LocalSettings.php|LocalSettings.php]]
 19+file. These statements need to be placed AFTER the inclusion of Ratings. The options are listed below and their default
 20+is set in the [http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Ratings/Ratings.settings.php?view=markup Ratings
 21+settings file]. You should NOT modify the settings file, but can have a look at it to get an idea of how to use the
 22+settings, in case the below descriptions do not suffice.
 23+
 24+There are no settings yet.
Index: trunk/extensions/Ratings/RELEASE-NOTES
@@ -0,0 +1,10 @@
 2+These are the release notes for the Ratings extension.
 3+
 4+Extension page on mediawiki.org: http://www.mediawiki.org/wiki/Extension:Ratings
 5+Latest version of the release notes: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Ratings/RELEASE-NOTES?view=co
 6+
 7+
 8+=== Version 0.1 ===
 9+2011-03-xx
 10+
 11+* Initial release
\ No newline at end of file
Index: trunk/extensions/Ratings/COPYING
@@ -0,0 +1,682 @@
 2+The license text below "----" applies to all files within this distribution, other
 3+than those that are in a directory which contains files named "LICENSE" or
 4+"COPYING", or a subdirectory thereof. For those files, the license text contained in
 5+said file overrides any license information contained in directories of smaller depth.
 6+Alternative licenses are typically used for software that is provided by external
 7+parties, and merely packaged with this software for convenience.
 8+----
 9+
 10+ GNU GENERAL PUBLIC LICENSE
 11+ Version 3, 29 June 2007
 12+
 13+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 14+ Everyone is permitted to copy and distribute verbatim copies
 15+ of this license document, but changing it is not allowed.
 16+
 17+ Preamble
 18+
 19+ The GNU General Public License is a free, copyleft license for
 20+software and other kinds of works.
 21+
 22+ The licenses for most software and other practical works are designed
 23+to take away your freedom to share and change the works. By contrast,
 24+the GNU General Public License is intended to guarantee your freedom to
 25+share and change all versions of a program--to make sure it remains free
 26+software for all its users. We, the Free Software Foundation, use the
 27+GNU General Public License for most of our software; it applies also to
 28+any other work released this way by its authors. You can apply it to
 29+your programs, too.
 30+
 31+ When we speak of free software, we are referring to freedom, not
 32+price. Our General Public Licenses are designed to make sure that you
 33+have the freedom to distribute copies of free software (and charge for
 34+them if you wish), that you receive source code or can get it if you
 35+want it, that you can change the software or use pieces of it in new
 36+free programs, and that you know you can do these things.
 37+
 38+ To protect your rights, we need to prevent others from denying you
 39+these rights or asking you to surrender the rights. Therefore, you have
 40+certain responsibilities if you distribute copies of the software, or if
 41+you modify it: responsibilities to respect the freedom of others.
 42+
 43+ For example, if you distribute copies of such a program, whether
 44+gratis or for a fee, you must pass on to the recipients the same
 45+freedoms that you received. You must make sure that they, too, receive
 46+or can get the source code. And you must show them these terms so they
 47+know their rights.
 48+
 49+ Developers that use the GNU GPL protect your rights with two steps:
 50+(1) assert copyright on the software, and (2) offer you this License
 51+giving you legal permission to copy, distribute and/or modify it.
 52+
 53+ For the developers' and authors' protection, the GPL clearly explains
 54+that there is no warranty for this free software. For both users' and
 55+authors' sake, the GPL requires that modified versions be marked as
 56+changed, so that their problems will not be attributed erroneously to
 57+authors of previous versions.
 58+
 59+ Some devices are designed to deny users access to install or run
 60+modified versions of the software inside them, although the manufacturer
 61+can do so. This is fundamentally incompatible with the aim of
 62+protecting users' freedom to change the software. The systematic
 63+pattern of such abuse occurs in the area of products for individuals to
 64+use, which is precisely where it is most unacceptable. Therefore, we
 65+have designed this version of the GPL to prohibit the practice for those
 66+products. If such problems arise substantially in other domains, we
 67+stand ready to extend this provision to those domains in future versions
 68+of the GPL, as needed to protect the freedom of users.
 69+
 70+ Finally, every program is threatened constantly by software patents.
 71+States should not allow patents to restrict development and use of
 72+software on general-purpose computers, but in those that do, we wish to
 73+avoid the special danger that patents applied to a free program could
 74+make it effectively proprietary. To prevent this, the GPL assures that
 75+patents cannot be used to render the program non-free.
 76+
 77+ The precise terms and conditions for copying, distribution and
 78+modification follow.
 79+
 80+ TERMS AND CONDITIONS
 81+
 82+ 0. Definitions.
 83+
 84+ "This License" refers to version 3 of the GNU General Public License.
 85+
 86+ "Copyright" also means copyright-like laws that apply to other kinds of
 87+works, such as semiconductor masks.
 88+
 89+ "The Program" refers to any copyrightable work licensed under this
 90+License. Each licensee is addressed as "you". "Licensees" and
 91+"recipients" may be individuals or organizations.
 92+
 93+ To "modify" a work means to copy from or adapt all or part of the work
 94+in a fashion requiring copyright permission, other than the making of an
 95+exact copy. The resulting work is called a "modified version" of the
 96+earlier work or a work "based on" the earlier work.
 97+
 98+ A "covered work" means either the unmodified Program or a work based
 99+on the Program.
 100+
 101+ To "propagate" a work means to do anything with it that, without
 102+permission, would make you directly or secondarily liable for
 103+infringement under applicable copyright law, except executing it on a
 104+computer or modifying a private copy. Propagation includes copying,
 105+distribution (with or without modification), making available to the
 106+public, and in some countries other activities as well.
 107+
 108+ To "convey" a work means any kind of propagation that enables other
 109+parties to make or receive copies. Mere interaction with a user through
 110+a computer network, with no transfer of a copy, is not conveying.
 111+
 112+ An interactive user interface displays "Appropriate Legal Notices"
 113+to the extent that it includes a convenient and prominently visible
 114+feature that (1) displays an appropriate copyright notice, and (2)
 115+tells the user that there is no warranty for the work (except to the
 116+extent that warranties are provided), that licensees may convey the
 117+work under this License, and how to view a copy of this License. If
 118+the interface presents a list of user commands or options, such as a
 119+menu, a prominent item in the list meets this criterion.
 120+
 121+ 1. Source Code.
 122+
 123+ The "source code" for a work means the preferred form of the work
 124+for making modifications to it. "Object code" means any non-source
 125+form of a work.
 126+
 127+ A "Standard Interface" means an interface that either is an official
 128+standard defined by a recognized standards body, or, in the case of
 129+interfaces specified for a particular programming language, one that
 130+is widely used among developers working in that language.
 131+
 132+ The "System Libraries" of an executable work include anything, other
 133+than the work as a whole, that (a) is included in the normal form of
 134+packaging a Major Component, but which is not part of that Major
 135+Component, and (b) serves only to enable use of the work with that
 136+Major Component, or to implement a Standard Interface for which an
 137+implementation is available to the public in source code form. A
 138+"Major Component", in this context, means a major essential component
 139+(kernel, window system, and so on) of the specific operating system
 140+(if any) on which the executable work runs, or a compiler used to
 141+produce the work, or an object code interpreter used to run it.
 142+
 143+ The "Corresponding Source" for a work in object code form means all
 144+the source code needed to generate, install, and (for an executable
 145+work) run the object code and to modify the work, including scripts to
 146+control those activities. However, it does not include the work's
 147+System Libraries, or general-purpose tools or generally available free
 148+programs which are used unmodified in performing those activities but
 149+which are not part of the work. For example, Corresponding Source
 150+includes interface definition files associated with source files for
 151+the work, and the source code for shared libraries and dynamically
 152+linked subprograms that the work is specifically designed to require,
 153+such as by intimate data communication or control flow between those
 154+subprograms and other parts of the work.
 155+
 156+ The Corresponding Source need not include anything that users
 157+can regenerate automatically from other parts of the Corresponding
 158+Source.
 159+
 160+ The Corresponding Source for a work in source code form is that
 161+same work.
 162+
 163+ 2. Basic Permissions.
 164+
 165+ All rights granted under this License are granted for the term of
 166+copyright on the Program, and are irrevocable provided the stated
 167+conditions are met. This License explicitly affirms your unlimited
 168+permission to run the unmodified Program. The output from running a
 169+covered work is covered by this License only if the output, given its
 170+content, constitutes a covered work. This License acknowledges your
 171+rights of fair use or other equivalent, as provided by copyright law.
 172+
 173+ You may make, run and propagate covered works that you do not
 174+convey, without conditions so long as your license otherwise remains
 175+in force. You may convey covered works to others for the sole purpose
 176+of having them make modifications exclusively for you, or provide you
 177+with facilities for running those works, provided that you comply with
 178+the terms of this License in conveying all material for which you do
 179+not control copyright. Those thus making or running the covered works
 180+for you must do so exclusively on your behalf, under your direction
 181+and control, on terms that prohibit them from making any copies of
 182+your copyrighted material outside their relationship with you.
 183+
 184+ Conveying under any other circumstances is permitted solely under
 185+the conditions stated below. Sublicensing is not allowed; section 10
 186+makes it unnecessary.
 187+
 188+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
 189+
 190+ No covered work shall be deemed part of an effective technological
 191+measure under any applicable law fulfilling obligations under article
 192+11 of the WIPO copyright treaty adopted on 20 December 1996, or
 193+similar laws prohibiting or restricting circumvention of such
 194+measures.
 195+
 196+ When you convey a covered work, you waive any legal power to forbid
 197+circumvention of technological measures to the extent such circumvention
 198+is effected by exercising rights under this License with respect to
 199+the covered work, and you disclaim any intention to limit operation or
 200+modification of the work as a means of enforcing, against the work's
 201+users, your or third parties' legal rights to forbid circumvention of
 202+technological measures.
 203+
 204+ 4. Conveying Verbatim Copies.
 205+
 206+ You may convey verbatim copies of the Program's source code as you
 207+receive it, in any medium, provided that you conspicuously and
 208+appropriately publish on each copy an appropriate copyright notice;
 209+keep intact all notices stating that this License and any
 210+non-permissive terms added in accord with section 7 apply to the code;
 211+keep intact all notices of the absence of any warranty; and give all
 212+recipients a copy of this License along with the Program.
 213+
 214+ You may charge any price or no price for each copy that you convey,
 215+and you may offer support or warranty protection for a fee.
 216+
 217+ 5. Conveying Modified Source Versions.
 218+
 219+ You may convey a work based on the Program, or the modifications to
 220+produce it from the Program, in the form of source code under the
 221+terms of section 4, provided that you also meet all of these conditions:
 222+
 223+ a) The work must carry prominent notices stating that you modified
 224+ it, and giving a relevant date.
 225+
 226+ b) The work must carry prominent notices stating that it is
 227+ released under this License and any conditions added under section
 228+ 7. This requirement modifies the requirement in section 4 to
 229+ "keep intact all notices".
 230+
 231+ c) You must license the entire work, as a whole, under this
 232+ License to anyone who comes into possession of a copy. This
 233+ License will therefore apply, along with any applicable section 7
 234+ additional terms, to the whole of the work, and all its parts,
 235+ regardless of how they are packaged. This License gives no
 236+ permission to license the work in any other way, but it does not
 237+ invalidate such permission if you have separately received it.
 238+
 239+ d) If the work has interactive user interfaces, each must display
 240+ Appropriate Legal Notices; however, if the Program has interactive
 241+ interfaces that do not display Appropriate Legal Notices, your
 242+ work need not make them do so.
 243+
 244+ A compilation of a covered work with other separate and independent
 245+works, which are not by their nature extensions of the covered work,
 246+and which are not combined with it such as to form a larger program,
 247+in or on a volume of a storage or distribution medium, is called an
 248+"aggregate" if the compilation and its resulting copyright are not
 249+used to limit the access or legal rights of the compilation's users
 250+beyond what the individual works permit. Inclusion of a covered work
 251+in an aggregate does not cause this License to apply to the other
 252+parts of the aggregate.
 253+
 254+ 6. Conveying Non-Source Forms.
 255+
 256+ You may convey a covered work in object code form under the terms
 257+of sections 4 and 5, provided that you also convey the
 258+machine-readable Corresponding Source under the terms of this License,
 259+in one of these ways:
 260+
 261+ a) Convey the object code in, or embodied in, a physical product
 262+ (including a physical distribution medium), accompanied by the
 263+ Corresponding Source fixed on a durable physical medium
 264+ customarily used for software interchange.
 265+
 266+ b) Convey the object code in, or embodied in, a physical product
 267+ (including a physical distribution medium), accompanied by a
 268+ written offer, valid for at least three years and valid for as
 269+ long as you offer spare parts or customer support for that product
 270+ model, to give anyone who possesses the object code either (1) a
 271+ copy of the Corresponding Source for all the software in the
 272+ product that is covered by this License, on a durable physical
 273+ medium customarily used for software interchange, for a price no
 274+ more than your reasonable cost of physically performing this
 275+ conveying of source, or (2) access to copy the
 276+ Corresponding Source from a network server at no charge.
 277+
 278+ c) Convey individual copies of the object code with a copy of the
 279+ written offer to provide the Corresponding Source. This
 280+ alternative is allowed only occasionally and noncommercially, and
 281+ only if you received the object code with such an offer, in accord
 282+ with subsection 6b.
 283+
 284+ d) Convey the object code by offering access from a designated
 285+ place (gratis or for a charge), and offer equivalent access to the
 286+ Corresponding Source in the same way through the same place at no
 287+ further charge. You need not require recipients to copy the
 288+ Corresponding Source along with the object code. If the place to
 289+ copy the object code is a network server, the Corresponding Source
 290+ may be on a different server (operated by you or a third party)
 291+ that supports equivalent copying facilities, provided you maintain
 292+ clear directions next to the object code saying where to find the
 293+ Corresponding Source. Regardless of what server hosts the
 294+ Corresponding Source, you remain obligated to ensure that it is
 295+ available for as long as needed to satisfy these requirements.
 296+
 297+ e) Convey the object code using peer-to-peer transmission, provided
 298+ you inform other peers where the object code and Corresponding
 299+ Source of the work are being offered to the general public at no
 300+ charge under subsection 6d.
 301+
 302+ A separable portion of the object code, whose source code is excluded
 303+from the Corresponding Source as a System Library, need not be
 304+included in conveying the object code work.
 305+
 306+ A "User Product" is either (1) a "consumer product", which means any
 307+tangible personal property which is normally used for personal, family,
 308+or household purposes, or (2) anything designed or sold for incorporation
 309+into a dwelling. In determining whether a product is a consumer product,
 310+doubtful cases shall be resolved in favor of coverage. For a particular
 311+product received by a particular user, "normally used" refers to a
 312+typical or common use of that class of product, regardless of the status
 313+of the particular user or of the way in which the particular user
 314+actually uses, or expects or is expected to use, the product. A product
 315+is a consumer product regardless of whether the product has substantial
 316+commercial, industrial or non-consumer uses, unless such uses represent
 317+the only significant mode of use of the product.
 318+
 319+ "Installation Information" for a User Product means any methods,
 320+procedures, authorization keys, or other information required to install
 321+and execute modified versions of a covered work in that User Product from
 322+a modified version of its Corresponding Source. The information must
 323+suffice to ensure that the continued functioning of the modified object
 324+code is in no case prevented or interfered with solely because
 325+modification has been made.
 326+
 327+ If you convey an object code work under this section in, or with, or
 328+specifically for use in, a User Product, and the conveying occurs as
 329+part of a transaction in which the right of possession and use of the
 330+User Product is transferred to the recipient in perpetuity or for a
 331+fixed term (regardless of how the transaction is characterized), the
 332+Corresponding Source conveyed under this section must be accompanied
 333+by the Installation Information. But this requirement does not apply
 334+if neither you nor any third party retains the ability to install
 335+modified object code on the User Product (for example, the work has
 336+been installed in ROM).
 337+
 338+ The requirement to provide Installation Information does not include a
 339+requirement to continue to provide support service, warranty, or updates
 340+for a work that has been modified or installed by the recipient, or for
 341+the User Product in which it has been modified or installed. Access to a
 342+network may be denied when the modification itself materially and
 343+adversely affects the operation of the network or violates the rules and
 344+protocols for communication across the network.
 345+
 346+ Corresponding Source conveyed, and Installation Information provided,
 347+in accord with this section must be in a format that is publicly
 348+documented (and with an implementation available to the public in
 349+source code form), and must require no special password or key for
 350+unpacking, reading or copying.
 351+
 352+ 7. Additional Terms.
 353+
 354+ "Additional permissions" are terms that supplement the terms of this
 355+License by making exceptions from one or more of its conditions.
 356+Additional permissions that are applicable to the entire Program shall
 357+be treated as though they were included in this License, to the extent
 358+that they are valid under applicable law. If additional permissions
 359+apply only to part of the Program, that part may be used separately
 360+under those permissions, but the entire Program remains governed by
 361+this License without regard to the additional permissions.
 362+
 363+ When you convey a copy of a covered work, you may at your option
 364+remove any additional permissions from that copy, or from any part of
 365+it. (Additional permissions may be written to require their own
 366+removal in certain cases when you modify the work.) You may place
 367+additional permissions on material, added by you to a covered work,
 368+for which you have or can give appropriate copyright permission.
 369+
 370+ Notwithstanding any other provision of this License, for material you
 371+add to a covered work, you may (if authorized by the copyright holders of
 372+that material) supplement the terms of this License with terms:
 373+
 374+ a) Disclaiming warranty or limiting liability differently from the
 375+ terms of sections 15 and 16 of this License; or
 376+
 377+ b) Requiring preservation of specified reasonable legal notices or
 378+ author attributions in that material or in the Appropriate Legal
 379+ Notices displayed by works containing it; or
 380+
 381+ c) Prohibiting misrepresentation of the origin of that material, or
 382+ requiring that modified versions of such material be marked in
 383+ reasonable ways as different from the original version; or
 384+
 385+ d) Limiting the use for publicity purposes of names of licensors or
 386+ authors of the material; or
 387+
 388+ e) Declining to grant rights under trademark law for use of some
 389+ trade names, trademarks, or service marks; or
 390+
 391+ f) Requiring indemnification of licensors and authors of that
 392+ material by anyone who conveys the material (or modified versions of
 393+ it) with contractual assumptions of liability to the recipient, for
 394+ any liability that these contractual assumptions directly impose on
 395+ those licensors and authors.
 396+
 397+ All other non-permissive additional terms are considered "further
 398+restrictions" within the meaning of section 10. If the Program as you
 399+received it, or any part of it, contains a notice stating that it is
 400+governed by this License along with a term that is a further
 401+restriction, you may remove that term. If a license document contains
 402+a further restriction but permits relicensing or conveying under this
 403+License, you may add to a covered work material governed by the terms
 404+of that license document, provided that the further restriction does
 405+not survive such relicensing or conveying.
 406+
 407+ If you add terms to a covered work in accord with this section, you
 408+must place, in the relevant source files, a statement of the
 409+additional terms that apply to those files, or a notice indicating
 410+where to find the applicable terms.
 411+
 412+ Additional terms, permissive or non-permissive, may be stated in the
 413+form of a separately written license, or stated as exceptions;
 414+the above requirements apply either way.
 415+
 416+ 8. Termination.
 417+
 418+ You may not propagate or modify a covered work except as expressly
 419+provided under this License. Any attempt otherwise to propagate or
 420+modify it is void, and will automatically terminate your rights under
 421+this License (including any patent licenses granted under the third
 422+paragraph of section 11).
 423+
 424+ However, if you cease all violation of this License, then your
 425+license from a particular copyright holder is reinstated (a)
 426+provisionally, unless and until the copyright holder explicitly and
 427+finally terminates your license, and (b) permanently, if the copyright
 428+holder fails to notify you of the violation by some reasonable means
 429+prior to 60 days after the cessation.
 430+
 431+ Moreover, your license from a particular copyright holder is
 432+reinstated permanently if the copyright holder notifies you of the
 433+violation by some reasonable means, this is the first time you have
 434+received notice of violation of this License (for any work) from that
 435+copyright holder, and you cure the violation prior to 30 days after
 436+your receipt of the notice.
 437+
 438+ Termination of your rights under this section does not terminate the
 439+licenses of parties who have received copies or rights from you under
 440+this License. If your rights have been terminated and not permanently
 441+reinstated, you do not qualify to receive new licenses for the same
 442+material under section 10.
 443+
 444+ 9. Acceptance Not Required for Having Copies.
 445+
 446+ You are not required to accept this License in order to receive or
 447+run a copy of the Program. Ancillary propagation of a covered work
 448+occurring solely as a consequence of using peer-to-peer transmission
 449+to receive a copy likewise does not require acceptance. However,
 450+nothing other than this License grants you permission to propagate or
 451+modify any covered work. These actions infringe copyright if you do
 452+not accept this License. Therefore, by modifying or propagating a
 453+covered work, you indicate your acceptance of this License to do so.
 454+
 455+ 10. Automatic Licensing of Downstream Recipients.
 456+
 457+ Each time you convey a covered work, the recipient automatically
 458+receives a license from the original licensors, to run, modify and
 459+propagate that work, subject to this License. You are not responsible
 460+for enforcing compliance by third parties with this License.
 461+
 462+ An "entity transaction" is a transaction transferring control of an
 463+organization, or substantially all assets of one, or subdividing an
 464+organization, or merging organizations. If propagation of a covered
 465+work results from an entity transaction, each party to that
 466+transaction who receives a copy of the work also receives whatever
 467+licenses to the work the party's predecessor in interest had or could
 468+give under the previous paragraph, plus a right to possession of the
 469+Corresponding Source of the work from the predecessor in interest, if
 470+the predecessor has it or can get it with reasonable efforts.
 471+
 472+ You may not impose any further restrictions on the exercise of the
 473+rights granted or affirmed under this License. For example, you may
 474+not impose a license fee, royalty, or other charge for exercise of
 475+rights granted under this License, and you may not initiate litigation
 476+(including a cross-claim or counterclaim in a lawsuit) alleging that
 477+any patent claim is infringed by making, using, selling, offering for
 478+sale, or importing the Program or any portion of it.
 479+
 480+ 11. Patents.
 481+
 482+ A "contributor" is a copyright holder who authorizes use under this
 483+License of the Program or a work on which the Program is based. The
 484+work thus licensed is called the contributor's "contributor version".
 485+
 486+ A contributor's "essential patent claims" are all patent claims
 487+owned or controlled by the contributor, whether already acquired or
 488+hereafter acquired, that would be infringed by some manner, permitted
 489+by this License, of making, using, or selling its contributor version,
 490+but do not include claims that would be infringed only as a
 491+consequence of further modification of the contributor version. For
 492+purposes of this definition, "control" includes the right to grant
 493+patent sublicenses in a manner consistent with the requirements of
 494+this License.
 495+
 496+ Each contributor grants you a non-exclusive, worldwide, royalty-free
 497+patent license under the contributor's essential patent claims, to
 498+make, use, sell, offer for sale, import and otherwise run, modify and
 499+propagate the contents of its contributor version.
 500+
 501+ In the following three paragraphs, a "patent license" is any express
 502+agreement or commitment, however denominated, not to enforce a patent
 503+(such as an express permission to practice a patent or covenant not to
 504+sue for patent infringement). To "grant" such a patent license to a
 505+party means to make such an agreement or commitment not to enforce a
 506+patent against the party.
 507+
 508+ If you convey a covered work, knowingly relying on a patent license,
 509+and the Corresponding Source of the work is not available for anyone
 510+to copy, free of charge and under the terms of this License, through a
 511+publicly available network server or other readily accessible means,
 512+then you must either (1) cause the Corresponding Source to be so
 513+available, or (2) arrange to deprive yourself of the benefit of the
 514+patent license for this particular work, or (3) arrange, in a manner
 515+consistent with the requirements of this License, to extend the patent
 516+license to downstream recipients. "Knowingly relying" means you have
 517+actual knowledge that, but for the patent license, your conveying the
 518+covered work in a country, or your recipient's use of the covered work
 519+in a country, would infringe one or more identifiable patents in that
 520+country that you have reason to believe are valid.
 521+
 522+ If, pursuant to or in connection with a single transaction or
 523+arrangement, you convey, or propagate by procuring conveyance of, a
 524+covered work, and grant a patent license to some of the parties
 525+receiving the covered work authorizing them to use, propagate, modify
 526+or convey a specific copy of the covered work, then the patent license
 527+you grant is automatically extended to all recipients of the covered
 528+work and works based on it.
 529+
 530+ A patent license is "discriminatory" if it does not include within
 531+the scope of its coverage, prohibits the exercise of, or is
 532+conditioned on the non-exercise of one or more of the rights that are
 533+specifically granted under this License. You may not convey a covered
 534+work if you are a party to an arrangement with a third party that is
 535+in the business of distributing software, under which you make payment
 536+to the third party based on the extent of your activity of conveying
 537+the work, and under which the third party grants, to any of the
 538+parties who would receive the covered work from you, a discriminatory
 539+patent license (a) in connection with copies of the covered work
 540+conveyed by you (or copies made from those copies), or (b) primarily
 541+for and in connection with specific products or compilations that
 542+contain the covered work, unless you entered into that arrangement,
 543+or that patent license was granted, prior to 28 March 2007.
 544+
 545+ Nothing in this License shall be construed as excluding or limiting
 546+any implied license or other defenses to infringement that may
 547+otherwise be available to you under applicable patent law.
 548+
 549+ 12. No Surrender of Others' Freedom.
 550+
 551+ If conditions are imposed on you (whether by court order, agreement or
 552+otherwise) that contradict the conditions of this License, they do not
 553+excuse you from the conditions of this License. If you cannot convey a
 554+covered work so as to satisfy simultaneously your obligations under this
 555+License and any other pertinent obligations, then as a consequence you may
 556+not convey it at all. For example, if you agree to terms that obligate you
 557+to collect a royalty for further conveying from those to whom you convey
 558+the Program, the only way you could satisfy both those terms and this
 559+License would be to refrain entirely from conveying the Program.
 560+
 561+ 13. Use with the GNU Affero General Public License.
 562+
 563+ Notwithstanding any other provision of this License, you have
 564+permission to link or combine any covered work with a work licensed
 565+under version 3 of the GNU Affero General Public License into a single
 566+combined work, and to convey the resulting work. The terms of this
 567+License will continue to apply to the part which is the covered work,
 568+but the special requirements of the GNU Affero General Public License,
 569+section 13, concerning interaction through a network will apply to the
 570+combination as such.
 571+
 572+ 14. Revised Versions of this License.
 573+
 574+ The Free Software Foundation may publish revised and/or new versions of
 575+the GNU General Public License from time to time. Such new versions will
 576+be similar in spirit to the present version, but may differ in detail to
 577+address new problems or concerns.
 578+
 579+ Each version is given a distinguishing version number. If the
 580+Program specifies that a certain numbered version of the GNU General
 581+Public License "or any later version" applies to it, you have the
 582+option of following the terms and conditions either of that numbered
 583+version or of any later version published by the Free Software
 584+Foundation. If the Program does not specify a version number of the
 585+GNU General Public License, you may choose any version ever published
 586+by the Free Software Foundation.
 587+
 588+ If the Program specifies that a proxy can decide which future
 589+versions of the GNU General Public License can be used, that proxy's
 590+public statement of acceptance of a version permanently authorizes you
 591+to choose that version for the Program.
 592+
 593+ Later license versions may give you additional or different
 594+permissions. However, no additional obligations are imposed on any
 595+author or copyright holder as a result of your choosing to follow a
 596+later version.
 597+
 598+ 15. Disclaimer of Warranty.
 599+
 600+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
 601+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
 602+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
 603+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
 604+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 605+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
 606+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
 607+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
 608+
 609+ 16. Limitation of Liability.
 610+
 611+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 612+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
 613+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
 614+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
 615+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
 616+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
 617+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
 618+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
 619+SUCH DAMAGES.
 620+
 621+ 17. Interpretation of Sections 15 and 16.
 622+
 623+ If the disclaimer of warranty and limitation of liability provided
 624+above cannot be given local legal effect according to their terms,
 625+reviewing courts shall apply local law that most closely approximates
 626+an absolute waiver of all civil liability in connection with the
 627+Program, unless a warranty or assumption of liability accompanies a
 628+copy of the Program in return for a fee.
 629+
 630+ END OF TERMS AND CONDITIONS
 631+
 632+ How to Apply These Terms to Your New Programs
 633+
 634+ If you develop a new program, and you want it to be of the greatest
 635+possible use to the public, the best way to achieve this is to make it
 636+free software which everyone can redistribute and change under these terms.
 637+
 638+ To do so, attach the following notices to the program. It is safest
 639+to attach them to the start of each source file to most effectively
 640+state the exclusion of warranty; and each file should have at least
 641+the "copyright" line and a pointer to where the full notice is found.
 642+
 643+ <one line to give the program's name and a brief idea of what it does.>
 644+ Copyright (C) <year> <name of author>
 645+
 646+ This program is free software: you can redistribute it and/or modify
 647+ it under the terms of the GNU General Public License as published by
 648+ the Free Software Foundation, either version 3 of the License, or
 649+ (at your option) any later version.
 650+
 651+ This program is distributed in the hope that it will be useful,
 652+ but WITHOUT ANY WARRANTY; without even the implied warranty of
 653+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 654+ GNU General Public License for more details.
 655+
 656+ You should have received a copy of the GNU General Public License
 657+ along with this program. If not, see <http://www.gnu.org/licenses/>.
 658+
 659+Also add information on how to contact you by electronic and paper mail.
 660+
 661+ If the program does terminal interaction, make it output a short
 662+notice like this when it starts in an interactive mode:
 663+
 664+ <program> Copyright (C) <year> <name of author>
 665+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 666+ This is free software, and you are welcome to redistribute it
 667+ under certain conditions; type `show c' for details.
 668+
 669+The hypothetical commands `show w' and `show c' should show the appropriate
 670+parts of the General Public License. Of course, your program's commands
 671+might be different; for a GUI interface, you would use an "about box".
 672+
 673+ You should also get your employer (if you work as a programmer) or school,
 674+if any, to sign a "copyright disclaimer" for the program, if necessary.
 675+For more information on this, and how to apply and follow the GNU GPL, see
 676+<http://www.gnu.org/licenses/>.
 677+
 678+ The GNU General Public License does not permit incorporating your program
 679+into proprietary programs. If your program is a subroutine library, you
 680+may consider it more useful to permit linking proprietary applications with
 681+the library. If this is what you want to do, use the GNU Lesser General
 682+Public License instead of this License. But first, please read
 683+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
\ No newline at end of file
Index: trunk/extensions/Ratings/api/ApiDoRating.php
@@ -0,0 +1,250 @@
 2+<?php
 3+
 4+/**
 5+ * API module to rate properties of pages.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file ApiDoRating.php
 10+ * @ingroup Ratings
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+class ApiDoRating extends ApiBase {
 16+
 17+ public function __construct( $main, $action ) {
 18+ parent::__construct( $main, $action );
 19+ }
 20+
 21+ public function execute() {
 22+ $params = $this->extractRequestParams();
 23+
 24+ global $wgUser;
 25+
 26+ if ( !$wgUser->isAllowed( 'rate' ) || $wgUser->isBlocked()
 27+ /*|| !array_key_exists( 'token', $params ) || !$wgUser->matchEditToken( $params['token'] )*/ ) {
 28+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
 29+ }
 30+
 31+ // In MW 1.17 and above ApiBase::PARAM_REQUIRED can be used, this is for b/c with 1.16.
 32+ foreach ( array( 'tag', 'pagename', 'value' ) as $requiredParam ) {
 33+ if ( !isset( $params[$requiredParam] ) ) {
 34+ $this->dieUsageMsg( array( 'missingparam', $requiredParam ) );
 35+ }
 36+ }
 37+
 38+ $page = Title::newFromText( $params['pagename'] );
 39+
 40+ if ( !$page->exists() ) {
 41+ $this->dieUsageMsg( array( 'notanarticle' ) );
 42+ }
 43+
 44+ $userText = $wgUser->getName();
 45+
 46+ $tagId = $this->getTagId( $params['tag'] );
 47+ $voteId = $this->userAlreadyVoted( $page, $tagId, $userText );
 48+
 49+ if ( $voteId === false ) {
 50+ $result = $this->insertRating( $page, $tagId, $params['value'], $userText );
 51+ }
 52+ else {
 53+ $result = $this->updateRating( $voteId, $params['value'] );
 54+ }
 55+
 56+ if ( $result && $GLOBALS['egRatingsInvalidateOnVote'] ) {
 57+ $page->invalidateCache();
 58+ }
 59+
 60+ $this->getResult()->addValue(
 61+ 'result',
 62+ 'success',
 63+ $result
 64+ );
 65+ }
 66+
 67+ /**
 68+ * Get the ID for the current tag.
 69+ * Makes sure the tag exists by creating it if it doesn't yet.
 70+ *
 71+ * @since 0.1
 72+ *
 73+ * @param string $tagName
 74+ *
 75+ * @return integer
 76+ */
 77+ protected function getTagId( $tagName ) {
 78+ $dbr = wfGetDB( DB_SLAVE );
 79+
 80+ $prop = $dbr->selectRow(
 81+ 'vote_props',
 82+ array( 'prop_id' ),
 83+ array(
 84+ 'prop_name' => $tagName
 85+ )
 86+ );
 87+
 88+ if ( $prop ) {
 89+ return $prop->prop_id;
 90+ }
 91+ else {
 92+ $this->createTag( $tagName );
 93+ return $this->getTagId( $tagName );
 94+ }
 95+ }
 96+
 97+ /**
 98+ * Insers a new tag.
 99+ *
 100+ * @since 0.1
 101+ *
 102+ * @param string $tagName
 103+ */
 104+ protected function createTag( $tagName ) {
 105+ $dbw = wfGetDB( DB_MASTER );
 106+
 107+ $dbw->insert(
 108+ 'vote_props',
 109+ array( 'prop_name' => $tagName )
 110+ );
 111+ }
 112+
 113+ /**
 114+ * Returns the id of the users vote for the property on this page or
 115+ * false when there is no such vote yet.
 116+ *
 117+ * @since 0.1
 118+ *
 119+ * @param Title $page
 120+ * @param integer $tagId
 121+ * @param string $userText
 122+ *
 123+ * @return false or intger
 124+ */
 125+ protected function userAlreadyVoted( Title $page, $tagId, $userText ) {
 126+ $dbr = wfGetDB( DB_SLAVE );
 127+
 128+ $vote = $dbr->selectRow(
 129+ 'votes',
 130+ array( 'vote_id' ),
 131+ array(
 132+ 'vote_user_text' => $userText,
 133+ 'vote_page_id' => $page->getArticleID(),
 134+ 'vote_prop_id' => $tagId
 135+ )
 136+ );
 137+
 138+ return $vote ? $vote->vote_id : false;
 139+ }
 140+
 141+ /**
 142+ * Insers a new vote.
 143+ *
 144+ * @since 0.1
 145+ *
 146+ * @param Title $page
 147+ * @param integer $tagId
 148+ * @param integer $value
 149+ * @param string $userText
 150+ *
 151+ * @return boolean
 152+ */
 153+ protected function insertRating( Title $page, $tagId, $value, $userText ) {
 154+ $dbw = wfGetDB( DB_MASTER );
 155+
 156+ return $dbw->insert(
 157+ 'votes',
 158+ array(
 159+ 'vote_user_text' => $userText,
 160+ 'vote_page_id' => $page->getArticleID(),
 161+ 'vote_prop_id' => $tagId,
 162+ 'vote_value' => $value,
 163+ 'vote_time' => $dbw->timestamp()
 164+ )
 165+ );
 166+ }
 167+
 168+ /**
 169+ * Updates an existing vote with a new value.
 170+ *
 171+ * @since 0.1
 172+ *
 173+ * @param integer $voteId
 174+ * @param integer $value
 175+ *
 176+ * @return boolean
 177+ */
 178+ protected function updateRating( $voteId, $value ) {
 179+ $dbw = wfGetDB( DB_MASTER );
 180+
 181+ return $dbw->update(
 182+ 'votes',
 183+ array(
 184+ 'vote_value' => $value,
 185+ 'vote_time' => $dbw->timestamp()
 186+ ),
 187+ array(
 188+ 'vote_id' => $voteId,
 189+ )
 190+ );
 191+ }
 192+
 193+ public function getAllowedParams() {
 194+ return array(
 195+ 'tag' => array(
 196+ ApiBase::PARAM_TYPE => 'string',
 197+ //ApiBase::PARAM_REQUIRED => true,
 198+ ),
 199+ 'pagename' => array(
 200+ ApiBase::PARAM_TYPE => 'string',
 201+ //ApiBase::PARAM_REQUIRED => true,
 202+ ),
 203+ 'value' => array(
 204+ ApiBase::PARAM_TYPE => 'integer',
 205+ //ApiBase::PARAM_REQUIRED => true,
 206+ ),
 207+ 'revid' => array(
 208+ ApiBase::PARAM_TYPE => 'integer'
 209+ ),
 210+ 'token' => null,
 211+ );
 212+ }
 213+
 214+ public function getParamDescription() {
 215+ return array(
 216+ 'tag' => 'The tag that is rated',
 217+ 'pagename' => 'Name of the page',
 218+ 'value' => 'The value of the rating'
 219+ );
 220+ }
 221+
 222+ public function getDescription() {
 223+ return array(
 224+ 'Allows rating a single tag for a single page.'
 225+ );
 226+ }
 227+
 228+ public function getPossibleErrors() {
 229+ return array_merge( parent::getPossibleErrors(), array(
 230+ array( 'badaccess-groups' ),
 231+ array( 'missingparam', 'tag' ),
 232+ array( 'missingparam', 'pagename' ),
 233+ array( 'missingparam', 'value' ),
 234+ ) );
 235+ }
 236+
 237+ protected function getExamples() {
 238+ return array(
 239+ 'api.php?action=dorating&pagename=User:Jeroen_De_Dauw&tag=awesomeness&value=9001&token=ABC012',
 240+ );
 241+ }
 242+
 243+ public function needsToken() {
 244+ return true;
 245+ }
 246+
 247+ public function getVersion() {
 248+ return __CLASS__ . ': $Id: $';
 249+ }
 250+
 251+}
Property changes on: trunk/extensions/Ratings/api/ApiDoRating.php
___________________________________________________________________
Added: svn:eol-style
1252 + native
Index: trunk/extensions/Ratings/api/ApiQueryRatings.php
@@ -0,0 +1,164 @@
 2+<?php
 3+
 4+/**
 5+ * API module to get the ratings of a single page.
 6+ * This includes the current total votes, the current avarage
 7+ * and optionally the value of the current users vote.
 8+ *
 9+ * @since 0.1
 10+ *
 11+ * @file ApiQueryRatings.php
 12+ * @ingroup Ratings
 13+ *
 14+ * @licence GNU GPL v3 or later
 15+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 16+ */
 17+class ApiQueryRatings extends ApiQueryBase {
 18+ public function __construct( $main, $action ) {
 19+ parent :: __construct( $main, $action, 'qr' );
 20+ }
 21+
 22+ /**
 23+ * Retrieve the specil words from the database.
 24+ */
 25+ public function execute() {
 26+ // Get the requests parameters.
 27+ $params = $this->extractRequestParams();
 28+
 29+ // In MW 1.17 and above ApiBase::PARAM_REQUIRED can be used, this is for b/c with 1.16.
 30+ foreach ( array( 'page' ) as $requiredParam ) {
 31+ if ( !isset( $params[$requiredParam] ) ) {
 32+ $this->dieUsageMsg( array( 'missingparam', $requiredParam ) );
 33+ }
 34+ }
 35+
 36+ $page = Title::newFromText( $params['page'] );
 37+
 38+ if ( !$page->exists() ) {
 39+ $this->dieUsageMsg( array( 'notanarticle' ) );
 40+ }
 41+
 42+ $this->addTables( array( 'votes', 'vote_props' ) );
 43+
 44+ $this->addJoinConds( array(
 45+ 'vote_props' => array( 'LEFT JOIN', array( 'vote_prop_id=prop_id' ) ),
 46+ ) );
 47+
 48+ $this->addFields( array(
 49+ 'vote_id',
 50+ 'vote_value',
 51+ 'vote_time',
 52+ 'prop_name'
 53+ ) );
 54+
 55+ $this->addWhere( array(
 56+ 'vote_page_id' => $page->getArticleID(),
 57+ 'vote_user_text' => isset( $params['user'] ) ? $params['user'] : $GLOBALS['wgUser']->getName()
 58+ ) );
 59+
 60+ if ( !is_null( $params['continue'] ) ) {
 61+ $dbr = wfGetDB( DB_SLAVE );
 62+ $this->addWhere( 'vote_id >= ' . $dbr->addQuotes( $params['continue'] ) );
 63+ }
 64+
 65+ $this->addOption( 'LIMIT', $params['limit'] + 1 );
 66+ $this->addOption( 'ORDER BY', 'vote_id ASC' );
 67+
 68+ $ratings = $this->select( __METHOD__ );
 69+ $count = 0;
 70+ $limitTags = isset( $params['tags'] );
 71+
 72+ while ( $rating = $ratings->fetchObject() ) {
 73+ if ( ++$count > $params['limit'] ) {
 74+ // We've reached the one extra which shows that
 75+ // there are additional pages to be had. Stop here...
 76+ $this->setContinueEnumParameter( 'continue', $rating->vote_id );
 77+ break;
 78+ }
 79+
 80+ if ( !$limitTags || in_array( $rating->prop_name, $params['tags'] ) ) {
 81+ $this->getResult()->addValue(
 82+ 'userratings',
 83+ $rating->prop_name,
 84+ (int)$rating->vote_value
 85+ );
 86+ }
 87+ }
 88+ }
 89+
 90+ /**
 91+ * (non-PHPdoc)
 92+ * @see includes/api/ApiBase#getAllowedParams()
 93+ */
 94+ public function getAllowedParams() {
 95+ return array (
 96+ 'page' => array(
 97+ ApiBase::PARAM_TYPE => 'string',
 98+ //ApiBase::PARAM_REQUIRED => true,
 99+ ),
 100+ 'user' => array(
 101+ ApiBase::PARAM_TYPE => 'string',
 102+ ),
 103+ 'limit' => array(
 104+ ApiBase :: PARAM_DFLT => 500,
 105+ ApiBase :: PARAM_TYPE => 'limit',
 106+ ApiBase :: PARAM_MIN => 1,
 107+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 108+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 109+ ),
 110+ 'continue' => null,
 111+ 'tags' => array(
 112+ ApiBase::PARAM_TYPE => 'string',
 113+ ApiBase::PARAM_ISMULTI => true,
 114+ ),
 115+ );
 116+ }
 117+
 118+ /**
 119+ * (non-PHPdoc)
 120+ * @see includes/api/ApiBase#getParamDescription()
 121+ */
 122+ public function getParamDescription() {
 123+ return array (
 124+ 'page' => 'The page to get rating values for',
 125+ 'user' => 'The name of the user to get rating values for',
 126+ 'continue' => 'Offset number from where to continue the query',
 127+ 'limit' => 'Max amount of words to return',
 128+ 'tags' => 'Can be used to limit the tags for which values are returned'
 129+ );
 130+ }
 131+
 132+ /**
 133+ * (non-PHPdoc)
 134+ * @see includes/api/ApiBase#getDescription()
 135+ */
 136+ public function getDescription() {
 137+ return 'This module returns all special words defined in the wikis Live Translate Dictionary for a given language';
 138+ }
 139+
 140+ /**
 141+ * (non-PHPdoc)
 142+ * @see includes/api/ApiBase#getPossibleErrors()
 143+ */
 144+ public function getPossibleErrors() {
 145+ return array_merge( parent::getPossibleErrors(), array(
 146+ array( 'missingparam', 'page' ),
 147+ array( 'missingparam', 'user' )
 148+ ) );
 149+ }
 150+
 151+ /**
 152+ * (non-PHPdoc)
 153+ * @see includes/api/ApiBase#getExamples()
 154+ */
 155+ protected function getExamples() {
 156+ return array (
 157+ 'api.php?action=query&list=ratings&qrpage=Main_page&qruser=0:0:0:0:0:0:0:1',
 158+ );
 159+ }
 160+
 161+ public function getVersion() {
 162+ return __CLASS__ . ': $Id: $';
 163+ }
 164+
 165+}
Property changes on: trunk/extensions/Ratings/api/ApiQueryRatings.php
___________________________________________________________________
Added: svn:eol-style
1166 + native
Index: trunk/extensions/Ratings/Ratings.i18n.php
@@ -0,0 +1,39 @@
 2+<?php
 3+
 4+/**
 5+ * Internationalization file for the Include WP extension.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file IncludeWP.i18n.php
 10+ * @ingroup IncludeWP
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+
 16+$messages = array();
 17+
 18+/** English
 19+ * @author Jeroen De Dauw
 20+ */
 21+$messages['en'] = array(
 22+ 'ratings-desc' => 'Simple rating extension for MediaWiki',
 23+
 24+ // Rating stars
 25+ 'ratings-par-page' => 'The page the rating applies to.',
 26+ 'ratings-par-tag' => 'Tha rating tag. The tag indicates what "property" of the page gets rated.',
 27+ 'ratings-par-showdisabled' => 'Show ratings when the user can not vote (in read-only mode).',
 28+ 'ratings-par-incsummary' => 'Show a summary of the current votes above the rating element?',
 29+
 30+ // Vote summary
 31+ 'ratings-current-score' => 'Current user rating: $1 ($2 {{PLURAL:$2|rating|ratings}})',
 32+ 'ratings-no-votes-yet' => 'No one has rated this yet.',
 33+);
 34+
 35+/** Message documentation (Message documentation)
 36+ * @author Jeroen De Dauw
 37+ */
 38+$messages['qqq'] = array(
 39+ 'ratings-desc' => '{{desc}}',
 40+);
Property changes on: trunk/extensions/Ratings/Ratings.i18n.php
___________________________________________________________________
Added: svn:eol-style
141 + native
Index: trunk/extensions/Ratings/votesummary/RatingsVoteSummary.php
@@ -0,0 +1,118 @@
 2+<?php
 3+
 4+/**
 5+ * Class to show a summary of votes for a single page, tag combination.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file RatingsVoteSummary.php
 10+ * @ingroup Ratings
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+final class RatingsVoteSummary extends ParserHook {
 16+
 17+ /**
 18+ * No LSB in pre-5.3 PHP *sigh*.
 19+ * This is to be refactored as soon as php >=5.3 becomes acceptable.
 20+ */
 21+ public static function staticMagic( array &$magicWords, $langCode ) {
 22+ $instance = new self;
 23+ return $instance->magic( $magicWords, $langCode );
 24+ }
 25+
 26+ /**
 27+ * No LSB in pre-5.3 PHP *sigh*.
 28+ * This is to be refactored as soon as php >=5.3 becomes acceptable.
 29+ */
 30+ public static function staticInit( Parser &$parser ) {
 31+ $instance = new self;
 32+ return $instance->init( $parser );
 33+ }
 34+
 35+ /**
 36+ * Gets the name of the parser hook.
 37+ * @see ParserHook::getName
 38+ *
 39+ * @since 0.1
 40+ *
 41+ * @return string
 42+ */
 43+ protected function getName() {
 44+ return array( 'votesummary' );
 45+ }
 46+
 47+ /**
 48+ * Returns an array containing the parameter info.
 49+ * @see ParserHook::getParameterInfo
 50+ *
 51+ * @since 0.1
 52+ *
 53+ * @return array
 54+ */
 55+ protected function getParameterInfo( $type ) {
 56+ $params = array();
 57+
 58+ $params['page'] = new Parameter( 'page' );
 59+ $params['page']->setDescription( wfMsg( 'ratings-par-page' ) );
 60+ $params['page']->setDefault( false, false );
 61+
 62+ $params['tag'] = new Parameter( 'tag' );
 63+ $params['tag']->setDescription( wfMsg( 'ratings-par-tag' ) );
 64+
 65+ return $params;
 66+ }
 67+
 68+ /**
 69+ * Returns the list of default parameters.
 70+ * @see ParserHook::getDefaultParameters
 71+ *
 72+ * @since 0.1
 73+ *
 74+ * @return array
 75+ */
 76+ protected function getDefaultParameters( $type ) {
 77+ return array( 'tag', 'page' );
 78+ }
 79+
 80+ /**
 81+ * Renders and returns the output.
 82+ * @see ParserHook::render
 83+ *
 84+ * @since 0.1
 85+ *
 86+ * @param array $parameters
 87+ *
 88+ * @return string
 89+ */
 90+ public function render( array $parameters ) {
 91+ $parameters['page'] = $parameters['page'] === false ? $GLOBALS['wgTitle'] : Title::newFromText( $parameters['page'] );
 92+ return htmlspecialchars( Ratings::getRatingSummaryMessage( $parameters['page'], $parameters['tag'] ) );
 93+ }
 94+
 95+ /**
 96+ * Returns the parser function otpions.
 97+ * @see ParserHook::getFunctionOptions
 98+ *
 99+ * @since 0.1
 100+ *
 101+ * @return array
 102+ */
 103+ protected function getFunctionOptions() {
 104+ return array(
 105+ 'noparse' => true,
 106+ 'isHTML' => true
 107+ );
 108+ }
 109+
 110+ /**
 111+ * @see ParserHook::getDescription()
 112+ *
 113+ * @since 0.1
 114+ */
 115+ public function getDescription() {
 116+ return wfMsg( 'ratings-starsratings-desc' );
 117+ }
 118+
 119+}
Property changes on: trunk/extensions/Ratings/votesummary/RatingsVoteSummary.php
___________________________________________________________________
Added: svn:eol-style
1120 + native
Index: trunk/extensions/Ratings/Ratings.settings.php
@@ -0,0 +1,32 @@
 2+<?php
 3+
 4+/**
 5+ * File defining the settings for the Ratings extension.
 6+ * More info can be found at http://www.mediawiki.org/wiki/Extension:Ratings#Settings
 7+ *
 8+ * NOTICE:
 9+ * Changing one of these settings can be done by copieng or cutting it,
 10+ * and placing it in LocalSettings.php, AFTER the inclusion of this extension.
 11+ *
 12+ * @file Ratings.Settings.php
 13+ * @ingroup Ratings
 14+ *
 15+ * @licence GNU GPL v3 or above
 16+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 17+ */
 18+
 19+if ( !defined( 'MEDIAWIKI' ) ) {
 20+ die( 'Not an entry point.' );
 21+}
 22+
 23+# When a user is not allowed to rate, show the rating stars (disabled) or not?.
 24+$egRatingsShowWhenDisabled = true;
 25+
 26+# Users that can rate.
 27+$wgGroupPermissions['*']['rate'] = true;
 28+
 29+# Set to true to invalidate the cache of pages when a vote for them is made.
 30+$egRatingsInvalidateOnVote = false;
 31+
 32+# Include a summary by default above ratings?
 33+$egRatingsIncSummary = false;
\ No newline at end of file
Property changes on: trunk/extensions/Ratings/Ratings.settings.php
___________________________________________________________________
Added: svn:eol-style
134 + native
Index: trunk/extensions/Ratings/README
@@ -0,0 +1,23 @@
 2+These is the readme file for the Ratings extension.
 3+
 4+Extension page on mediawiki.org: http://www.mediawiki.org/wiki/Extension:Ratings
 5+Latest version of the readme file: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Ratings/README?view=co
 6+
 7+== About ==
 8+
 9+The Ratings extension provides a tag extension that when embedded in a page allows users to
 10+rate different "properties" of the page.
 11+
 12+The main reason for creating a new extension is that Rating Bar has been replaced by "W4G Rating Bar",
 13+which is not open source, so does not allow for adding any improvements.
 14+
 15+== Alpha version ==
 16+
 17+Do note this extension is still in alpha stage. Although core functionality is mostly working,
 18+some things still need to be implemented, and many things are in need of some polishing. A
 19+particular thing lacking decent support now is handling of the rating control when the
 20+user is not allowed to rate.
 21+
 22+Some feature that might be added in the feature is displaying lists of votes and lists of
 23+pages based on votes. Integration with SMW is also possible. And vote summaries can be
 24+cached better.
\ No newline at end of file
Index: trunk/extensions/Ratings/Ratings.php
@@ -0,0 +1,102 @@
 2+<?php
 3+
 4+/**
 5+ * Initialization file for the Ratings extension.
 6+ *
 7+ * Documentation: http://www.mediawiki.org/wiki/Extension:Ratings
 8+ * Support http://www.mediawiki.org/wiki/Extension_talk:Ratings
 9+ * Source code: http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/Ratings
 10+ *
 11+ * @file Ratings.php
 12+ * @ingroup Ratings
 13+ *
 14+ * @licence GNU GPL v3
 15+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 16+ */
 17+
 18+/**
 19+ * This documenation group collects source code files belonging to Ratings.
 20+ *
 21+ * @defgroup Ratings Ratings
 22+ */
 23+
 24+if ( !defined( 'MEDIAWIKI' ) ) {
 25+ die( 'Not an entry point.' );
 26+}
 27+
 28+if ( version_compare( $wgVersion, '1.16', '<' ) ) {
 29+ die( 'Ratings requires MediaWiki 1.16 or above.' );
 30+}
 31+
 32+// Include the Validator extension if that hasn't been done yet, since it's required for Include WP to work.
 33+if ( !defined( 'Validator_VERSION' ) ) {
 34+ @include_once( dirname( __FILE__ ) . '/../Validator/Validator.php' );
 35+}
 36+
 37+// Only initialize the extension when all dependencies are present.
 38+if ( ! defined( 'Validator_VERSION' ) ) {
 39+ die( '<b>Error:</b> You need to have <a href="http://www.mediawiki.org/wiki/Extension:Validator">Validator</a> installed in order to use <a href="http://www.mediawiki.org/wiki/Extension:SubPageList">SubPageList</a>.<br />' );
 40+}
 41+
 42+define( 'Ratings_VERSION', '0.1 alpha' );
 43+
 44+$wgExtensionCredits['other'][] = array(
 45+ 'path' => __FILE__,
 46+ 'name' => 'Ratings',
 47+ 'version' => Ratings_VERSION,
 48+ 'author' => array(
 49+ '[http://www.mediawiki.org/wiki/User:Jeroen_De_Dauw Jeroen De Dauw]',
 50+ ),
 51+ 'url' => 'http://www.mediawiki.org/wiki/Extension:Ratings',
 52+ 'descriptionmsg' => 'ratings-desc'
 53+);
 54+
 55+$egRatingsScriptPath = $wgExtensionAssetsPath === false ? $wgScriptPath . '/extensions/Ratings' : $wgExtensionAssetsPath . '/Ratings';
 56+
 57+$wgExtensionMessagesFiles['Ratings'] = dirname( __FILE__ ) . '/Ratings.i18n.php';
 58+
 59+$wgAutoloadClasses['ApiDoRating'] = dirname( __FILE__ ) . '/api/ApiDoRating.php';
 60+$wgAutoloadClasses['ApiQueryRatings'] = dirname( __FILE__ ) . '/api/ApiQueryRatings.php';
 61+
 62+$wgAPIModules['dorating'] = 'ApiDoRating';
 63+$wgAPIListModules['ratings'] = 'ApiQueryRatings';
 64+
 65+$wgAutoloadClasses['RatingsStars'] = dirname( __FILE__ ) . '/starrating/RatingsStars.php';
 66+
 67+$wgHooks['ParserFirstCallInit'][] = 'RatingsStars::staticInit';
 68+$wgHooks['LanguageGetMagic'][] = 'RatingsStars::staticMagic';
 69+
 70+$wgAutoloadClasses['RatingsVoteSummary'] = dirname( __FILE__ ) . '/votesummary/RatingsVoteSummary.php';
 71+
 72+$wgHooks['ParserFirstCallInit'][] = 'RatingsVoteSummary::staticInit';
 73+$wgHooks['LanguageGetMagic'][] = 'RatingsVoteSummary::staticMagic';
 74+
 75+$wgAutoloadClasses['Ratings'] = dirname( __FILE__ ) . '/Ratings.class.php';
 76+$wgAutoloadClasses['RatingsHooks'] = dirname( __FILE__ ) . '/Ratings.hooks.php';
 77+
 78+$wgHooks['LoadExtensionSchemaUpdates'][] = 'RatingsHooks::onSchemaUpdate';
 79+
 80+$egRatingsStarsJSMessages = array(
 81+);
 82+
 83+// For backward compatibility with MW < 1.17.
 84+if ( defined( 'MW_SUPPORTS_RESOURCE_MODULES' ) ) {
 85+ $moduleTemplate = array(
 86+ 'localBasePath' => dirname( __FILE__ ),
 87+ 'remoteBasePath' => $egRatingsScriptPath
 88+ );
 89+
 90+ $wgResourceModules['ext.ratings.stars'] = $moduleTemplate + array(
 91+ 'styles' => array(
 92+ 'starrating/star-rating/jquery.rating.css'
 93+ ),
 94+ 'scripts' => array(
 95+ 'starrating/star-rating/jquery.rating.js',
 96+ 'starrating/ext.ratings.stars.js'
 97+ ),
 98+ 'dependencies' => array(),
 99+ 'messages' => $egRatingsStarsJSMessages
 100+ );
 101+}
 102+
 103+require_once 'Ratings.settings.php';
Property changes on: trunk/extensions/Ratings/Ratings.php
___________________________________________________________________
Added: svn:eol-style
1104 + native
Index: trunk/extensions/Ratings/starrating/RatingsStars.php
@@ -0,0 +1,236 @@
 2+<?php
 3+
 4+/**
 5+ * Class to render star ratings.
 6+ *
 7+ * @since 0.1
 8+ *
 9+ * @file RatingsStars.php
 10+ * @ingroup Ratings
 11+ *
 12+ * @licence GNU GPL v3 or later
 13+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 14+ */
 15+final class RatingsStars extends ParserHook {
 16+
 17+ /**
 18+ * No LSB in pre-5.3 PHP *sigh*.
 19+ * This is to be refactored as soon as php >=5.3 becomes acceptable.
 20+ */
 21+ public static function staticMagic( array &$magicWords, $langCode ) {
 22+ $instance = new self;
 23+ return $instance->magic( $magicWords, $langCode );
 24+ }
 25+
 26+ /**
 27+ * No LSB in pre-5.3 PHP *sigh*.
 28+ * This is to be refactored as soon as php >=5.3 becomes acceptable.
 29+ */
 30+ public static function staticInit( Parser &$parser ) {
 31+ $instance = new self;
 32+ return $instance->init( $parser );
 33+ }
 34+
 35+ /**
 36+ * Gets the name of the parser hook.
 37+ * @see ParserHook::getName
 38+ *
 39+ * @since 0.1
 40+ *
 41+ * @return string
 42+ */
 43+ protected function getName() {
 44+ return array( 'starrating' );
 45+ }
 46+
 47+ /**
 48+ * Returns an array containing the parameter info.
 49+ * @see ParserHook::getParameterInfo
 50+ *
 51+ * @since 0.1
 52+ *
 53+ * @return array
 54+ */
 55+ protected function getParameterInfo( $type ) {
 56+ global $egRatingsShowWhenDisabled, $egRatingsIncSummary;
 57+
 58+ $params = array();
 59+
 60+ $params['page'] = new Parameter( 'page' );
 61+ $params['page']->setDescription( wfMsg( 'ratings-par-page' ) );
 62+ $params['page']->setDefault( false, false );
 63+
 64+ $params['tag'] = new Parameter( 'tag' );
 65+ $params['tag']->setDescription( wfMsg( 'ratings-par-tag' ) );
 66+
 67+ $params['showdisabled'] = new Parameter( 'showdisabled', Parameter::TYPE_BOOLEAN );
 68+ $params['showdisabled']->setDescription( wfMsg( 'ratings-par-showdisabled' ) );
 69+ $params['showdisabled']->setDefault( $egRatingsShowWhenDisabled );
 70+
 71+ $params['incsummary'] = new Parameter( 'incsummary', Parameter::TYPE_BOOLEAN );
 72+ $params['incsummary']->setDescription( wfMsg( 'ratings-par-incsummary' ) );
 73+ $params['incsummary']->setDefault( $egRatingsIncSummary );
 74+
 75+ return $params;
 76+ }
 77+
 78+ /**
 79+ * Returns the list of default parameters.
 80+ * @see ParserHook::getDefaultParameters
 81+ *
 82+ * @since 0.1
 83+ *
 84+ * @return array
 85+ */
 86+ protected function getDefaultParameters( $type ) {
 87+ return array( 'tag', 'page' );
 88+ }
 89+
 90+ /**
 91+ * Renders and returns the output.
 92+ * @see ParserHook::render
 93+ *
 94+ * @since 0.1
 95+ *
 96+ * @param array $parameters
 97+ *
 98+ * @return string
 99+ */
 100+ public function render( array $parameters ) {
 101+ $this->loadJs( $parameters );
 102+
 103+ $parameters['page'] = $parameters['page'] === false ? $GLOBALS['wgTitle'] : Title::newFromText( $parameters['page'] );
 104+
 105+ static $ratingStarNr = 0; $ratingStarNr++;
 106+
 107+ $inputs = array();
 108+
 109+ for ( $i = 0; $i < 5; $i++ ) {
 110+ $inputs[] = Html::element(
 111+ 'input',
 112+ array(
 113+ 'class' => 'starrating',
 114+ 'type' => 'radio',
 115+ 'name' => 'ratingstars_' . $ratingStarNr,
 116+ 'value' => $i,
 117+ 'page' => $parameters['page']->getFullText(),
 118+ 'tag' => $parameters['tag'],
 119+ )
 120+ );
 121+ }
 122+
 123+ if ( $parameters['incsummary'] ) {
 124+ array_unshift( $inputs, htmlspecialchars( Ratings::getRatingSummaryMessage( $parameters['page'], $parameters['tag'] ) ) . '<br />' );
 125+ }
 126+
 127+ return Html::rawElement(
 128+ 'div',
 129+ array( 'style' => 'display:none; position:static', 'class' => 'starrating-div' ),
 130+ implode( '', $inputs )
 131+ );
 132+ }
 133+
 134+ /**
 135+ * Loads the needed JavaScript.
 136+ * Takes care of non-RL compatibility.
 137+ *
 138+ * @since 0.1
 139+ *
 140+ * @param array $parameters
 141+ */
 142+ protected function loadJs( array $parameters ) {
 143+ static $loadedJs = false;
 144+
 145+ if ( $loadedJs ) {
 146+ return;
 147+ }
 148+
 149+ $loadedJs = true;
 150+
 151+ $this->addJSWikiData( $parameters );
 152+
 153+ // For backward compatibility with MW < 1.17.
 154+ if ( is_callable( array( $this->parser->getOutput(), 'addModules' ) ) ) {
 155+ $this->parser->getOutput()->addModules( 'ext.ratings.stars' );
 156+ }
 157+ else {
 158+ global $egRatingsScriptPath, $wgStylePath, $wgStyleVersion;
 159+
 160+ $this->addJSLocalisation();
 161+
 162+ $this->parser->getOutput()->addHeadItem(
 163+ Html::linkedScript( "$wgStylePath/common/jquery.min.js?$wgStyleVersion" ),
 164+ 'jQuery'
 165+ );
 166+
 167+ $this->parser->getOutput()->addHeadItem(
 168+ Html::linkedScript( $egRatingsScriptPath . '/starrating/star-rating/jquery.rating.js' )
 169+ . Html::linkedStyle( $egRatingsScriptPath . '/starrating/star-rating/jquery.rating.css' ),
 170+ 'ext.ratings.stars.jquery'
 171+ );
 172+
 173+ $this->parser->getOutput()->addHeadItem(
 174+ Html::linkedScript( $egRatingsScriptPath . '/starrating/ext.ratings.stars.js' ),
 175+ 'ext.ratings.stars'
 176+ );
 177+ }
 178+ }
 179+
 180+ /**
 181+ * Ouput the wiki data needed to display the licence links.
 182+ *
 183+ * @since 0.1
 184+ *
 185+ * @param array $parameters
 186+ */
 187+ protected function addJSWikiData( array $parameters ) {
 188+ $this->parser->getOutput()->addHeadItem(
 189+ Html::inlineScript(
 190+ 'var wgRatingsShowDisabled =' . json_encode( $parameters['showdisabled'] ) . ';'
 191+ )
 192+ );
 193+ }
 194+
 195+ /**
 196+ * Adds the needed JS messages to the page output.
 197+ * This is for backward compatibility with pre-RL MediaWiki.
 198+ *
 199+ * @since 0.1
 200+ */
 201+ protected function addJSLocalisation() {
 202+ global $egRatingsStarsJSMessages;
 203+
 204+ $data = array();
 205+
 206+ foreach ( $egRatingsStarsJSMessages as $msg ) {
 207+ $data[$msg] = wfMsgNoTrans( $msg );
 208+ }
 209+
 210+ $this->parser->getOutput()->addHeadItem( Html::inlineScript( 'var wgRatingsStarsMessages = ' . json_encode( $data ) . ';' ) );
 211+ }
 212+
 213+ /**
 214+ * Returns the parser function otpions.
 215+ * @see ParserHook::getFunctionOptions
 216+ *
 217+ * @since 0.1
 218+ *
 219+ * @return array
 220+ */
 221+ protected function getFunctionOptions() {
 222+ return array(
 223+ 'noparse' => true,
 224+ 'isHTML' => true
 225+ );
 226+ }
 227+
 228+ /**
 229+ * @see ParserHook::getDescription()
 230+ *
 231+ * @since 0.1
 232+ */
 233+ public function getDescription() {
 234+ return wfMsg( 'ratings-starsratings-desc' );
 235+ }
 236+
 237+}
Property changes on: trunk/extensions/Ratings/starrating/RatingsStars.php
___________________________________________________________________
Added: svn:eol-style
1238 + native
Index: trunk/extensions/Ratings/starrating/star-rating/documentation.css
@@ -0,0 +1,80 @@
 2+*{ font-family:Arial, Helvetica, sans-serif; margin:0; padding:0; outline:none; }
 3+form{ padding:0/*!important*/; margin:0/*!important*/; }
 4+img{ border:0; }
 5+ul,ol{ padding:2px 5px; margin:0 0 0 20px; }
 6+
 7+body{ font-size:72%; color: #333; background:#fff; margin:0px; padding:0px; }
 8+h1{ color:#333; font-size:140%; float:left; width:auto; margin:0px 5px 0 0; }
 9+h2{ color:#666; margin:20px 0 3px 0; }
 10+h3{ color:#666; margin:10px 0 1px 0; }
 11+p{ margin:10px 0; }
 12+/*pre,code{ clear:both; display:block; }*/
 13+pre.code{
 14+ background-color:#F7F7F7;
 15+ border-color:#A7A7CC;
 16+ border-style:solid;
 17+ border-width:1px 1px 1px 5px;
 18+ font-size:small;
 19+ overflow-x:auto;
 20+ padding:5px 5px 5px 15px;
 21+}
 22+
 23+@media screen{
 24+ /* LAYOUT 1 - sticky footer */
 25+ /*ALL*/html,body,#wrap{ min-height: 100%; height: auto !important; height: 100%; }
 26+ /* FIXED HEADER/FOOTER: */
 27+ #roof{ height:24px; position:fixed; width:100%; z-index:9999; left:0; top:0; }
 28+ #head{ height:30px; position:fixed; width:100%; z-index:9999; left:0; top:25px; }
 29+ #foot{ height:55px; position:fixed; width:100%; z-index:9999; left:0; bottom:0; }
 30+ #wrap{ padding:85px 0; }
 31+ #wrap{ padding:95px 0 !IE; }
 32+ html > body #roof{ height:14px; }
 33+}
 34+
 35+
 36+@media debug{
 37+ #wrap{ background:#ffeeee;/*IE8*/ background:#eeffee;/*IE7*/ }
 38+ html > body #wrap{ background:#eeeeff;/*MOZ*/ }
 39+}
 40+
 41+#head, #foot{ border:#AAA solid 2px; }
 42+#head{ background:#F7F7F7 url('/jquery/project/head.png') bottom left repeat-x; }
 43+#foot{ background:#F7F7F7 url('/jquery/project/foot.png') top left repeat-x; }
 44+#head{ border-width:0 0 2px 0; }
 45+#foot{ border-width:2px 0 0 0; padding:0 0 20px 0; }
 46+
 47+#roof{ height:14px; background:#e7e7e7; border-bottom:#AAA solid 1px; padding:5px; }
 48+#roof{ color:#777; font-size:94%; }
 49+#roof a{ color:#00A; }
 50+
 51+#body{ margin:10px; }
 52+
 53+#ad{ position:absolute; right:0; /*background:#090;*/ padding:5px; margin:5px 0 0 0; width:160px !important; overflow:hidden !important; }
 54+#ad iframe{ width:160px !important; overflow:hidden !important; }
 55+#documentation{ margin-right:170px; }
 56+
 57+#search{ text-align:right; padding:0; margin:5px 0; border:0; display:inline; clear:none; width:200px; }
 58+#search *{ display:inline; float:left; clear:none; }
 59+#search label{ color:#C00; font-weight:bold; font-size:100%; margin:2px 5px 0 0; }
 60+#search input{ font-weight:bold; font-size:95%; }
 61+
 62+.license-info{ padding:10px 20px; margin:0px 50px; border:#77cc77 solid 1px; background:#f3f9f3; }
 63+.hint{ padding:3px; background:#FFFF99; color:#000; border-bottom:#CC9900 solid 1px; margin:0 0 10px 0; }
 64+
 65+/* Utilities */
 66+.P5{ padding:5px; }
 67+.Warning,.No,.Error{ color:red; }
 68+.Success,.Yes,.Y{ color:green; }
 69+.Bold,.B{ font-weight:bold; }
 70+
 71+/* FROM: http://roscoecreations.com/help/css/global2.css */
 72+.Clear:after {content: "."; display: block; clear: both; visibility: hidden; line-height: 0; height: 0;}
 73+.Clear {display: inline-block;}
 74+html[xmlns] .Clear {display: block;}
 75+* html .Clear {height: 1%;}
 76+/* - END - */
 77+
 78+/* tabs css */
 79+@media projection,screen{.tabs-hide{display:none}}@media print{.tabs-nav{display:none}}.tabs-nav{list-style:none;margin:0;padding:0 0 0 4px}.tabs-nav:after{display:block;clear:both;content:" "}.tabs-nav li{float:left;margin:0 0 0 1px}.tabs-nav a{display:block;position:relative;top:1px;z-index:2;padding:6px 10px 0;height:18px;color:#27537a;font-size:12px;font-weight:bold;line-height:1.2;text-align:center;text-decoration:none;background:url(/@/js/tabs/tab.png) no-repeat}.tabs-nav .tabs-selected a{padding-top:7px;color:#000}.tabs-nav .tabs-selected a,.tabs-nav a:hover,.tabs-nav a:focus,.tabs-nav a:active{background-position:0 -50px;outline:0}.tabs-nav .tabs-disabled a:hover,.tabs-nav .tabs-disabled a:focus,.tabs-nav .tabs-disabled a:active{background-position:0 0}.tabs-nav .tabs-selected a:link,.tabs-nav .tabs-selected a:visited,.tabs-nav .tabs-disabled a:link,.tabs-nav .tabs-disabled a:visited{cursor:text;cursor:default}.tabs-nav a:hover,.tabs-nav a:focus,.tabs-nav a:active{cursor:pointer;cursor:hand}.tabs-nav .tabs-disabled{opacity:.4}.tabs-container{border-top:1px solid #97a5b0;padding:1em 8px;background:#fff}.tabs-loading span{padding:0 0 0 20px;background:url(/@/js/tabs/loading.gif) no-repeat 0 50%}.tabs-nav li{margin:0px;padding:0px 4px 0px 0px}.tabs-nav a{position:relative;padding:5px 3px 0px 3px;font-size:100%;font-weight:normal;line-height:1;height:16px;border:#ccc solid;border-width:1px 1px 0px 1px;background:#f5f5f5;color:#333!important}.tabs-nav a:hover{color:#339!important;text-decoration:underline}.tabs-nav .tabs-selected a{padding-top:6px;border-width:1px 1px 0px 1px;background:#e7e7e7;color:#000!important}.tabs-nav .tabs-disabled a{border-color:#ccc;color:#555!important}.tabs-container{border-top:1px solid #e0e0e0;padding:0px 0px;background:transparent}* html .tabs-nav a{display:inline-block;height:23px}.tabs-nav li > a{}
 80+
 81+.tabs-nav{ font-size:110%; }.tabs-nav a{ font-weight:bold; }
Property changes on: trunk/extensions/Ratings/starrating/star-rating/documentation.css
___________________________________________________________________
Added: svn:eol-style
182 + native
Index: trunk/extensions/Ratings/starrating/star-rating/documentation.js
@@ -0,0 +1,15 @@
 2+// chili-1.7.packed.ks
 3+eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('8={3b:"1.6",2o:"1B.1Y,1B.23,1B.2e",2i:"",2H:1a,12:"",2C:1a,Z:"",2a:\'<H V="$0">$$</H>\',R:"&#F;",1j:"&#F;&#F;&#F;&#F;",1f:"&#F;<1W/>",3c:5(){9 $(y).39("1k")[0]},I:{},N:{}};(5($){$(5(){5 1J(l,a){5 2I(A,h){4 3=(1v h.3=="1h")?h.3:h.3.1w;k.1m({A:A,3:"("+3+")",u:1+(3.c(/\\\\./g,"%").c(/\\[.*?\\]/g,"%").3a(/\\((?!\\?)/g)||[]).u,z:(h.z)?h.z:8.2a})}5 2z(){4 1E=0;4 1x=x 2A;Q(4 i=0;i<k.u;i++){4 3=k[i].3;3=3.c(/\\\\\\\\|\\\\(\\d+)/g,5(m,1F){9!1F?m:"\\\\"+(1E+1+1t(1F))});1x.1m(3);1E+=k[i].u}4 1w=1x.3d("|");9 x 1u(1w,(a.3g)?"2j":"g")}5 1S(o){9 o.c(/&/g,"&3h;").c(/</g,"&3e;")}5 1R(o){9 o.c(/ +/g,5(1X){9 1X.c(/ /g,R)})}5 G(o){o=1S(o);7(R){o=1R(o)}9 o}5 2m(2E){4 i=0;4 j=1;4 h;19(h=k[i++]){4 1b=D;7(1b[j]){4 1U=/(\\\\\\$)|(?:\\$\\$)|(?:\\$(\\d+))/g;4 z=h.z.c(1U,5(m,1V,K){4 3f=\'\';7(1V){9"$"}v 7(!K){9 G(1b[j])}v 7(K=="0"){9 h.A}v{9 G(1b[j+1t(K,10)])}});4 1A=D[D.u-2];4 2h=D[D.u-1];4 2G=2h.2v(11,1A);11=1A+2E.u;14+=G(2G)+z;9 z}v{j+=h.u}}}4 R=8.R;4 k=x 2A;Q(4 A 2r a.k){2I(A,a.k[A])}4 14="";4 11=0;l.c(2z(),2m);4 2y=l.2v(11,l.u);14+=G(2y);9 14}5 2B(X){7(!8.N[X]){4 Y=\'<Y 32="1p" 33="p/2u"\'+\' 30="\'+X+\'">\';8.N[X]=1H;7($.31.34){4 W=J.1L(Y);4 $W=$(W);$("2d").1O($W)}v{$("2d").1O(Y)}}}5 1q(e,a){4 l=e&&e.1g&&e.1g[0]&&e.1g[0].37;7(!l)l="";l=l.c(/\\r\\n?/g,"\\n");4 C=1J(l,a);7(8.1j){C=C.c(/\\t/g,8.1j)}7(8.1f){C=C.c(/\\n/g,8.1f)}$(e).38(c)}5 1o(q,13){4 1l={12:8.12,2x:q+".1d",Z:8.Z,2w:q+".2u"};4 B;7(13&&1v 13=="2l")B=$.35(1l,13);v B=1l;9{a:B.12+B.2x,1p:B.Z+B.2w}}7($.2q)$.2q({36:"2l.15"});4 2n=x 1u("\\\\b"+8.2i+"\\\\b","2j");4 1e=[];$(8.2o).2D(5(){4 e=y;4 1n=$(e).3i("V");7(!1n){9}4 q=$.3u(1n.c(2n,""));7(\'\'!=q){1e.1m(e);4 f=1o(q,e.15);7(8.2H||e.15){7(!8.N[f.a]){1D{8.N[f.a]=1H;$.3v(f.a,5(M){M.f=f.a;8.I[f.a]=M;7(8.2C){2B(f.1p)}$("."+q).2D(5(){4 f=1o(q,y.15);7(M.f==f.a){1q(y,M)}})})}1I(3s){3t("a 3w Q: "+q+\'@\'+3z)}}}v{4 a=8.I[f.a];7(a){1q(e,a)}}}});7(J.1i&&J.1i.29){5 22(p){7(\'\'==p){9""}1z{4 16=(x 3A()).2k()}19(p.3x(16)>-1);p=p.c(/\\<1W[^>]*?\\>/3y,16);4 e=J.1L(\'<1k>\');e.3l=p;p=e.3m.c(x 1u(16,"g"),\'\\r\\n\');9 p}4 T="";4 18=1G;$(1e).3j().G("1k").U("2c",5(){18=y}).U("1M",5(){7(18==y)T=J.1i.29().3k});$("3n").U("3q",5(){7(\'\'!=T){2p.3r.3o(\'3p\',22(T));2V.2R=1a}}).U("2c",5(){T=""}).U("1M",5(){18=1G})}})})(1Z);8.I["1Y.1d"]={k:{2M:{3:/\\/\\*[^*]*\\*+(?:[^\\/][^*]*\\*+)*\\//},25:{3:/\\<!--(?:.|\\n)*?--\\>/},2f:{3:/\\/\\/.*/},2P:{3:/2L|2T|2J|2O|2N|2X|2K|2Z|2U|2S|2W|2Y|2Q|51|c-50/},53:{3:/\\/[^\\/\\\\\\n]*(?:\\\\.[^\\/\\\\\\n]*)*\\/[52]*/},1h:{3:/(?:\\\'[^\\\'\\\\\\n]*(?:\\\\.[^\\\'\\\\\\n]*)*\\\')|(?:\\"[^\\"\\\\\\n]*(?:\\\\.[^\\"\\\\\\n]*)*\\")/},27:{3:/\\b[+-]?(?:\\d*\\.?\\d+|\\d+\\.?\\d*)(?:[1r][+-]?\\d+)?\\b/},4X:{3:/\\b(D|1N|1K|1I|2t|2s|4W|1z|v|1a|Q|5|7|2r|4Z|x|1G|9|1Q|y|1H|1D|1v|4|4Y|19|59)\\b/},1y:{3:/\\b(58|2k|2p|5b|5a|55|J|54|57|1t|56|4L|4K|4N|4M|4H|4G|4J)\\b/},1C:{3:/(?:\\<\\w+)|(?:\\>)|(?:\\<\\/\\w+\\>)|(?:\\/\\>)/},26:{3:/\\s+\\w+(?=\\s*=)/},20:{3:/([\\"\\\'])(?:(?:[^\\1\\\\\\r\\n]*?(?:\\1\\1|\\\\.))*[^\\1\\\\\\r\\n]*?)\\1/},21:{3:/&[\\w#]+?;/},4I:{3:/(\\$|1Z)/}}};8.I["23.1d"]={k:{25:{3:/\\<!--(?:.|\\n)*?--\\>/},1h:{3:/(?:\\\'[^\\\'\\\\\\n]*(?:\\\\.[^\\\'\\\\\\n]*)*\\\')|(?:\\"[^\\"\\\\\\n]*(?:\\\\.[^\\"\\\\\\n]*)*\\")/},27:{3:/\\b[+-]?(?:\\d*\\.?\\d+|\\d+\\.?\\d*)(?:[1r][+-]?\\d+)?\\b/},1C:{3:/(?:\\<\\w+)|(?:\\>)|(?:\\<\\/\\w+\\>)|(?:\\/\\>)/},26:{3:/\\s+\\w+(?=\\s*=)/},20:{3:/([\\"\\\'])(?:(?:[^\\1\\\\\\r\\n]*?(?:\\1\\1|\\\\.))*[^\\1\\\\\\r\\n]*?)\\1/},21:{3:/&[\\w#]+?;/}}};8.I["2e.1d"]={k:{4S:{3:/\\/\\*[^*]*\\*+([^\\/][^*]*\\*+)*\\//},2f:{3:/(?:\\/\\/.*)|(?:[^\\\\]\\#.*)/},4V:{3:/\\\'[^\\\'\\\\]*(?:\\\\.[^\\\'\\\\]*)*\\\'/},4U:{3:/\\"[^\\"\\\\]*(?:\\\\.[^\\"\\\\]*)*\\"/},4P:{3:/\\b(?:[4O][2b][1s][1s]|[4R][4Q][2b][1P]|[5c][5v][1s][5u][1P])\\b/},5x:{3:/\\b[+-]?(\\d*\\.?\\d+|\\d+\\.?\\d*)([1r][+-]?\\d+)?\\b/},5y:{3:/\\b(?:5z|5w(?:5A|5E(?:5F(?:17|1c)|5G(?:17|1c))|17|1T|5B|5C|5D(?:17|1T|1c)|1c)|P(?:5h(?:5k|5j)|5e(?:5d|5g(?:5f|5l)|5r|E(?:5t|5s)|5n(?:5m|5p)|L(?:3X|3W)|O(?:S|3Y(?:3T|3S|3V))|3U|S(?:44|47|46)|41))|40)\\b/},1y:{3:/(?:\\$43|\\$42|\\$3R|\\$3G|\\$3F|\\$3I|\\$3H|\\$3C|\\$3B|\\$3D)\\b/},28:{3:/\\b(?:3O|3N|3P|3K|3J|3M|3L|48|4v|1N|1K|1I|4u|V|4x|4w|2t|4r|2s|4q|1z|4t|v|4s|4D|4C|4F|4E|4z|4y|4B|4A|4p|4d|2F|2F|4g|Q|4f|5|1y|7|4a|4m|4l|4o|4i|4k|x|4j|4h|4n|4b|4c|49|4e|3Q|3E|9|45|1Q|y|3Z|1D|5o|5q|4|19|5i)\\b/},2g:{3:/\\$(\\w+)/,z:\'<H V="28">$</H><H V="2g">$1</H>\'},1C:{3:/(?:\\<\\?[24][4T][24])|(?:\\<\\?)|(?:\\?\\>)/}}}',62,353,'|||exp|var|function||if|ChiliBook|return|recipe||replace||el|path||step|||steps|ingredients|||str|text|recipeName||||length|else||new|this|replacement|stepName|settings|dish|arguments||160|filter|span|recipes|document|||recipeLoaded|required|||for|replaceSpace||insidePRE|bind|class|domLink|stylesheetPath|link|stylesheetFolder||lastIndex|recipeFolder|options|perfect|chili|newline|ERROR|downPRE|while|false|aux|WARNING|js|codes|replaceNewLine|childNodes|string|selection|replaceTab|pre|settingsDef|push|elClass|getPath|stylesheet|makeDish|eE|Ll|parseInt|RegExp|typeof|source|exps|global|do|offset|code|tag|try|prevLength|aNum|null|true|catch|cook|case|createElement|mouseup|break|append|Ee|switch|replaceSpaces|escapeHTML|NOTICE|pattern|escaped|br|spaces|mix|jQuery|avalue|entity|preformatted|xml|Pp|htcom|aname|numbers|keyword|createRange|defaultReplacement|Uu|mousedown|head|php|com|variable|input|elementClass|gi|valueOf|object|chef|selectClass|elementPath|window|metaobjects|in|default|continue|css|substring|stylesheetFile|recipeFile|lastUnmatched|knowHow|Array|checkCSS|stylesheetLoading|each|matched|extends|unmatched|recipeLoading|prepareStep|unblockUI|ajaxSubmit|silverlight|jscom|unblock|block|plugin|clearFields|returnValue|fieldValue|blockUI|formSerialize|event|resetForm|ajaxForm|clearForm|fieldSerialize|href|browser|rel|type|msie|extend|selector|data|html|next|match|version|getPRE|join|lt|bit|ignoreCase|amp|attr|parents|htmlText|innerHTML|innerText|body|setData|Text|copy|clipboardData|recipeNotAvailable|alert|trim|getJSON|unavailable|indexOf|ig|recipePath|Date|_SESSION|_SERVER|php_errormsg|require_once|_GET|_FILES|_REQUEST|_POST|__METHOD__|__LINE__|and|abstract|__FILE__|__CLASS__|__FUNCTION__|require|_ENV|END|CONT|PREFIX|START|OCALSTATEDIR|IBDIR|UTPUT_HANDLER_|throw|__COMPILER_HALT_OFFSET__|VERSION|_COOKIE|GLOBALS|API|static|YSCONFDIR|HLIB_SUFFIX|array|protected|implements|print|private|exit|public|foreach|final|or|isset|old_function|list|include_once|include|php_user_filter|interface|exception|die|declare|elseif|echo|cfunction|as|const|clone|endswitch|endif|eval|endwhile|enddeclare|empty|endforeach|endfor|isNaN|NaN|jquery|Infinity|clearTimeout|setTimeout|clearInterval|setInterval|Nn|value|Rr|Tt|mlcom|Hh|string2|string1|delete|keywords|void|instanceof|content|taconite|gim|regexp|escape|constructor|parseFloat|unescape|toString|with|prototype|element|Ff|BINDIR|HP_|PATH|CONFIG_FILE_|EAR_|xor|INSTALL_DIR|EXTENSION_DIR|SCAN_DIR|MAX|INT_|unset|SIZE|use|DATADIR|XTENSION_DIR|OL|Ss|Aa|E_|number|const1|DEFAULT_INCLUDE_PATH|ALL|PARSE|STRICT|USER_|CO|MPILE_|RE_'.split('|'),0,{}))
 4+
 5+// jQuery.tabs.packed.js
 6+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(4($){$.2l({z:{2k:0}});$.1P.z=4(x,w){3(O x==\'2Y\')w=x;w=$.2l({K:(x&&O x==\'1Z\'&&x>0)?--x:0,12:C,J:$.1f?2h:T,18:T,1r:\'2X&#2Q;\',21:\'18-2F-\',1m:C,1u:C,1l:C,1F:C,1x:\'2u\',2r:C,2p:C,2m:T,2i:C,1d:C,1c:C,1j:\'z-1M\',H:\'z-2b\',14:\'z-12\',16:\'z-26\',1q:\'z-1H\',1L:\'z-2L\',2j:\'10\'},w||{});$.8.1D=$.8.U&&($.8.1Y&&$.8.1Y<7||/2A 6.0/.2y(2x.2w));4 1w(){1V(0,0)}F 5.Y(4(){2 p=5;2 r=$(\'13.\'+w.1j,p);r=r.V()&&r||$(\'>13:9(0)\',p);2 j=$(\'a\',r);3(w.18){j.Y(4(){2 c=w.21+(++$.z.2k),B=\'#\'+c,2f=5.1O;5.1O=B;$(\'<10 S="\'+c+\'" 34="\'+w.16+\'"></10>\').2c(p);$(5).19(\'1B\',4(e,a){2 b=$(5).I(w.1L),X=$(\'X\',5)[0],27=X.1J;3(w.1r){X.1J=\'<24>\'+w.1r+\'</24>\'}1p(4(){$(B).2T(2f,4(){3(w.1r){X.1J=27}b.17(w.1L);a&&a()})},0)})})}2 n=$(\'10.\'+w.16,p);n=n.V()&&n||$(\'>\'+w.2j,p);r.P(\'.\'+w.1j)||r.I(w.1j);n.Y(4(){2 a=$(5);a.P(\'.\'+w.16)||a.I(w.16)});2 s=$(\'A\',r).20($(\'A.\'+w.H,r)[0]);3(s>=0){w.K=s}3(1e.B){j.Y(4(i){3(5.B==1e.B){w.K=i;3(($.8.U||$.8.2E)&&!w.18){2 a=$(1e.B);2 b=a.15(\'S\');a.15(\'S\',\'\');1p(4(){a.15(\'S\',b)},2D)}1w();F T}})}3($.8.U){1w()}n.1a(\':9(\'+w.K+\')\').1C().1n().2C(\':9(\'+w.K+\')\').I(w.1q);$(\'A\',r).17(w.H).9(w.K).I(w.H);j.9(w.K).N(\'1B\').1n();3(w.2m){2 l=4(d){2 c=$.2B(n.1t(),4(a){2 h,1A=$(a);3(d){3($.8.1D){a.Z.2z(\'1X\');a.Z.G=\'\';a.1k=C}h=1A.L({\'1h-G\':\'\'}).G()}E{h=1A.G()}F h}).2v(4(a,b){F b-a});3($.8.1D){n.Y(4(){5.1k=c[0]+\'1W\';5.Z.2t(\'1X\',\'5.Z.G = 5.1k ? 5.1k : "2s"\')})}E{n.L({\'1h-G\':c[0]+\'1W\'})}};l();2 q=p.1U;2 m=p.1v;2 v=$(\'#z-2q-2o-V\').1t(0)||$(\'<X S="z-2q-2o-V">M</X>\').L({1T:\'2n\',3a:\'39\',38:\'37\'}).2c(Q.1S).1t(0);2 o=v.1v;36(4(){2 b=p.1U;2 a=p.1v;2 c=v.1v;3(a>m||b!=q||c!=o){l((b>q||c<o));q=b;m=a;o=c}},35)}2 u={},11={},1R=w.2r||w.1x,1Q=w.2p||w.1x;3(w.1u||w.1m){3(w.1u){u[\'G\']=\'1C\';11[\'G\']=\'1H\'}3(w.1m){u[\'W\']=\'1C\';11[\'W\']=\'1H\'}}E{3(w.1l){u=w.1l}E{u[\'1h-2g\']=0;1R=1}3(w.1F){11=w.1F}E{11[\'1h-2g\']=0;1Q=1}}2 t=w.2i,1d=w.1d,1c=w.1c;j.19(\'2e\',4(){2 c=$(5).1g(\'A:9(0)\');3(p.1i||c.P(\'.\'+w.H)||c.P(\'.\'+w.14)){F T}2 a=5.B;3($.8.U){$(5).N(\'1b\');3(w.J){$.1f.1N(a);1e.B=a.1z(\'#\',\'\')}}E 3($.8.1y){2 b=$(\'<2d 33="\'+a+\'"><10><32 31="2a" 30="h" /></10></2d>\').1t(0);b.2a();$(5).N(\'1b\');3(w.J){$.1f.1N(a)}}E{3(w.J){1e.B=a.1z(\'#\',\'\')}E{$(5).N(\'1b\')}}});j.19(\'1E\',4(){2 a=$(5).1g(\'A:9(0)\');3($.8.1y){a.1o({W:0},1,4(){a.L({W:\'\'})})}a.I(w.14)});3(w.12&&w.12.1K){29(2 i=0,k=w.12.1K;i<k;i++){j.9(--w.12[i]).N(\'1E\').1n()}};j.19(\'28\',4(){2 a=$(5).1g(\'A:9(0)\');a.17(w.14);3($.8.1y){a.1o({W:1},1,4(){a.L({W:\'\'})})}});j.19(\'1b\',4(e){2 g=e.2Z;2 d=5,A=$(5).1g(\'A:9(0)\'),D=$(5.B),R=n.1a(\':2W\');3(p[\'1i\']||A.P(\'.\'+w.H)||A.P(\'.\'+w.14)||O t==\'4\'&&t(5,D[0],R[0])===T){5.25();F T}p[\'1i\']=2h;3(D.V()){3($.8.U&&w.J){2 c=5.B.1z(\'#\',\'\');D.15(\'S\',\'\');1p(4(){D.15(\'S\',c)},0)}2 f={1T:\'\',2V:\'\',G:\'\'};3(!$.8.U){f[\'W\']=\'\'}4 1I(){3(w.J&&g){$.1f.1N(d.B)}R.1o(11,1Q,4(){$(d).1g(\'A:9(0)\').I(w.H).2U().17(w.H);R.I(w.1q).L(f);3(O 1d==\'4\'){1d(d,D[0],R[0])}3(!(w.1u||w.1m||w.1l)){D.L(\'1T\',\'2n\')}D.1o(u,1R,4(){D.17(w.1q).L(f);3($.8.U){R[0].Z.1a=\'\';D[0].Z.1a=\'\'}3(O 1c==\'4\'){1c(d,D[0],R[0])}p[\'1i\']=C})})}3(!w.18){1I()}E{$(d).N(\'1B\',[1I])}}E{2S(\'2R P 2P 2O 26.\')}2 a=1G.2N||Q.1s&&Q.1s.23||Q.1S.23||0;2 b=1G.2M||Q.1s&&Q.1s.22||Q.1S.22||0;1p(4(){1G.1V(a,b)},0);5.25();F w.J&&!!g});3(w.J){$.1f.2K(4(){j.9(w.K).N(\'1b\').1n()})}})};2 y=[\'2e\',\'1E\',\'28\'];29(2 i=0;i<y.1K;i++){$.1P[y[i]]=(4(d){F 4(c){F 5.Y(4(){2 b=$(\'13.z-1M\',5);b=b.V()&&b||$(\'>13:9(0)\',5);2 a;3(!c||O c==\'1Z\'){a=$(\'A a\',b).9((c&&c>0&&c-1||0))}E 3(O c==\'2J\'){a=$(\'A a[1O$="#\'+c+\'"]\',b)}a.N(d)})}})(y[i])}$.1P.2I=4(){2 c=[];5.Y(4(){2 a=$(\'13.z-1M\',5);a=a.V()&&a||$(\'>13:9(0)\',5);2 b=$(\'A\',a);c.2H(b.20(b.1a(\'.z-2b\')[0])+1)});F c[0]}})(2G);',62,197,'||var|if|function|this|||browser|eq||||||||||||||||||||||||||tabs|li|hash|null|toShow|else|return|height|selectedClass|addClass|bookmarkable|initial|css||trigger|typeof|is|document|toHide|id|false|msie|size|opacity|span|each|style|div|hideAnim|disabled|ul|disabledClass|attr|containerClass|removeClass|remote|bind|filter|click|onShow|onHide|location|ajaxHistory|parents|min|locked|navClass|minHeight|fxShow|fxFade|end|animate|setTimeout|hideClass|spinner|documentElement|get|fxSlide|offsetHeight|unFocus|fxSpeed|safari|replace|jq|loadRemoteTab|show|msie6|disableTab|fxHide|window|hide|switchTab|innerHTML|length|loadingClass|nav|update|href|fn|hideSpeed|showSpeed|body|display|offsetWidth|scrollTo|px|behaviour|version|number|index|hashPrefix|scrollTop|scrollLeft|em|blur|container|tabTitle|enableTab|for|submit|selected|appendTo|form|triggerTab|url|width|true|onClick|tabStruct|remoteCount|extend|fxAutoHeight|block|font|fxHideSpeed|watch|fxShowSpeed|1px|setExpression|normal|sort|userAgent|navigator|test|removeExpression|MSIE|map|not|500|opera|tab|jQuery|push|activeTab|string|initialize|loading|pageYOffset|pageXOffset|such|no|8230|There|alert|load|siblings|overflow|visible|Loading|object|clientX|value|type|input|action|class|50|setInterval|hidden|visibility|absolute|position'.split('|'),0,{}));
 7+
 8+// jQuery.history.packed.js
 9+eval(function(p,a,c,k,e,d){e=function(c){return(c<a?"":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p;}('(4($){$.x=16 4(){3 g=\'17\';3 6=8.2;3 A=T;3 m;c.n=4(){};3 w=4(){3 d=$(\'.s-d\');5(d.15().Q()>0){d.13()}};$(b).U(g,w);5($.v.14){3 r;$(4(){r=$(\'<7 1b="1c: 1a;"></7>\').X(b.W).18(0);3 7=r.D.b;7.F();7.I();7.8.2=6.G(\'#\',\'\')});c.n=4(2){6=2;3 7=r.D.b;7.F();7.I();7.8.2=2.G(\'#\',\'\')};m=4(){3 7=r.D.b;3 l=7.8.2;5(l!=6){6=l;5(l!=\'#\'){$(\'a[f$="\'+l+\'"]\').k();8.2=l}j{8.2=\'\';$(b).y(g)}}}}j 5($.v.11||$.v.Y){c.n=4(2){6=2};m=4(){5(8.2){5(6!=8.2){6=8.2;$(\'a[f$="\'+6+\'"]\').k()}}j 5(6){6=\'\';$(b).y(g)}}}j 5($.v.1o){3 9,q,t;$(4(){9=[];9.h=B.h;q=[]});3 o=C;t=4(2){9.M(2);q.h=0;o=C};c.n=4(2){6=2;t(6)};m=4(){3 p=B.h-9.h;5(p){o=C;5(p<0){H(3 i=0;i<1p.1k(p);i++)q.1m(9.1l())}j{H(3 i=0;i<p;i++)9.M(q.1e())}3 J=9[9.h-1];$(\'a[f$="\'+J+\'"]\').k();6=8.2}j 5(9[9.h-1]==O&&!o){5(b.L.1d(\'#\')>=0){$(\'a[f$="\'+\'#\'+b.L.1g(\'#\')[1]+\'"]\').k()}j{$(b).y(g)}o=1i}}}c.1h=4(z){5(P z==\'4\'){$(b).1j(g,w).U(g,z)}5(8.2&&P t==\'O\'){$(\'a.s[f$="\'+8.2+\'"]\').k()}5(m&&A==T){A=1f(m,1n);}}};$.R.s=4(d){3 E=$(d).Q()&&$(d)||$(\'<N></N>\').X(\'W\');E.Z(\'s-d\');V c.12(4(i){3 S=c.f;3 2=\'#s-\'+ ++i;c.f=2;$(c).k(4(e){3 u=e.K;E.19(S,4(){5(u){$.x.n(2);}})})})};$.R.B=4(){V c.k(4(e){3 u=e.K;5(u){$.x.n(c.2)}})}})(10);',62,88,'||hash|var|function|if|_currentHash|iframe|location|_backStack||document|this|output||href|RESET_EVENT|length||else|click|iframeHash|_observeHistory|update|isFirst|historyDelta|_forwardStack|_historyIframe|remote|_addHistory|trueClick|browser|_defaultReset|ajaxHistory|trigger|callback|_intervalId|history|false|contentWindow|target|open|replace|for|close|cachedHash|clientX|URL|push|div|undefined|typeof|size|fn|remoteURL|null|bind|return|body|appendTo|opera|addClass|jQuery|mozilla|each|empty|msie|children|new|historyReset|get|load|none|style|display|indexOf|shift|setInterval|split|initialize|true|unbind|abs|pop|unshift|200|safari|Math'.split('|'),0,{}))
 10+
 11+// Implementation
 12+;if(window.jQuery) (function($){ $(function(){
 13+
 14+$('.tabs').addClass('Clear').tabs();
 15+
 16+}) })(jQuery);
Property changes on: trunk/extensions/Ratings/starrating/star-rating/documentation.js
___________________________________________________________________
Added: svn:eol-style
117 + native
Index: trunk/extensions/Ratings/starrating/star-rating/delete.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/Ratings/starrating/star-rating/delete.gif
___________________________________________________________________
Added: svn:mime-type
218 + application/octet-stream
Index: trunk/extensions/Ratings/starrating/star-rating/jquery.MetaData.js
@@ -0,0 +1,121 @@
 2+/*
 3+ * Metadata - jQuery plugin for parsing metadata from elements
 4+ *
 5+ * Copyright (c) 2006 John Resig, Yehuda Katz, J�rn Zaefferer, Paul McLanahan
 6+ *
 7+ * Dual licensed under the MIT and GPL licenses:
 8+ * http://www.opensource.org/licenses/mit-license.php
 9+ * http://www.gnu.org/licenses/gpl.html
 10+ *
 11+ * Revision: $Id$
 12+ *
 13+ */
 14+
 15+/**
 16+ * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 17+ * in the JSON will become a property of the element itself.
 18+ *
 19+ * There are three supported types of metadata storage:
 20+ *
 21+ * attr: Inside an attribute. The name parameter indicates *which* attribute.
 22+ *
 23+ * class: Inside the class attribute, wrapped in curly braces: { }
 24+ *
 25+ * elem: Inside a child element (e.g. a script tag). The
 26+ * name parameter indicates *which* element.
 27+ *
 28+ * The metadata for an element is loaded the first time the element is accessed via jQuery.
 29+ *
 30+ * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 31+ * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 32+ *
 33+ * @name $.metadata.setType
 34+ *
 35+ * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 36+ * @before $.metadata.setType("class")
 37+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 38+ * @desc Reads metadata from the class attribute
 39+ *
 40+ * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 41+ * @before $.metadata.setType("attr", "data")
 42+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 43+ * @desc Reads metadata from a "data" attribute
 44+ *
 45+ * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 46+ * @before $.metadata.setType("elem", "script")
 47+ * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 48+ * @desc Reads metadata from a nested script element
 49+ *
 50+ * @param String type The encoding type
 51+ * @param String name The name of the attribute to be used to get metadata (optional)
 52+ * @cat Plugins/Metadata
 53+ * @descr Sets the type of encoding to be used when loading metadata for the first time
 54+ * @type undefined
 55+ * @see metadata()
 56+ */
 57+
 58+(function($) {
 59+
 60+$.extend({
 61+ metadata : {
 62+ defaults : {
 63+ type: 'class',
 64+ name: 'metadata',
 65+ cre: /({.*})/,
 66+ single: 'metadata'
 67+ },
 68+ setType: function( type, name ){
 69+ this.defaults.type = type;
 70+ this.defaults.name = name;
 71+ },
 72+ get: function( elem, opts ){
 73+ var settings = $.extend({},this.defaults,opts);
 74+ // check for empty string in single property
 75+ if ( !settings.single.length ) settings.single = 'metadata';
 76+
 77+ var data = $.data(elem, settings.single);
 78+ // returned cached data if it already exists
 79+ if ( data ) return data;
 80+
 81+ data = "{}";
 82+
 83+ if ( settings.type == "class" ) {
 84+ var m = settings.cre.exec( elem.className );
 85+ if ( m )
 86+ data = m[1];
 87+ } else if ( settings.type == "elem" ) {
 88+ if( !elem.getElementsByTagName ) return;
 89+ var e = elem.getElementsByTagName(settings.name);
 90+ if ( e.length )
 91+ data = $.trim(e[0].innerHTML);
 92+ } else if ( elem.getAttribute != undefined ) {
 93+ var attr = elem.getAttribute( settings.name );
 94+ if ( attr )
 95+ data = attr;
 96+ }
 97+
 98+ if ( data.indexOf( '{' ) <0 )
 99+ data = "{" + data + "}";
 100+
 101+ data = eval("(" + data + ")");
 102+
 103+ $.data( elem, settings.single, data );
 104+ return data;
 105+ }
 106+ }
 107+});
 108+
 109+/**
 110+ * Returns the metadata object for the first member of the jQuery object.
 111+ *
 112+ * @name metadata
 113+ * @descr Returns element's metadata object
 114+ * @param Object opts An object contianing settings to override the defaults
 115+ * @type jQuery
 116+ * @cat Plugins/Metadata
 117+ */
 118+$.fn.metadata = function( opts ){
 119+ return $.metadata.get( this[0], opts );
 120+};
 121+
 122+})(jQuery);
\ No newline at end of file
Property changes on: trunk/extensions/Ratings/starrating/star-rating/jquery.MetaData.js
___________________________________________________________________
Added: svn:eol-style
1123 + native
Index: trunk/extensions/Ratings/starrating/star-rating/jquery.rating.css
@@ -0,0 +1,12 @@
 2+/* jQuery.Rating Plugin CSS - http://www.fyneworks.com/jquery/star-rating/ */
 3+div.rating-cancel,div.star-rating{float:left;width:17px;height:15px;text-indent:-999em;cursor:pointer;display:block;background:transparent;overflow:hidden}
 4+div.star-rating,div.star-rating a{background:url(star.gif) no-repeat 0 0px}
 5+div.rating-cancel,div.rating-cancel a{background:url(delete.gif) no-repeat 0 -16px}
 6+div.rating-cancel a,div.star-rating a{display:block;width:16px;height:100%;background-position:0 0px;border:0}
 7+div.star-rating-on a{background-position:0 -16px!important}
 8+div.star-rating-hover a{background-position:0 -32px}
 9+/* Read Only CSS */
 10+div.star-rating-readonly a{cursor:default !important}
 11+/* Partial Star CSS */
 12+div.star-rating{background:transparent!important;overflow:hidden!important}
 13+/* END jQuery.Rating Plugin CSS */
\ No newline at end of file
Property changes on: trunk/extensions/Ratings/starrating/star-rating/jquery.rating.css
___________________________________________________________________
Added: svn:eol-style
114 + native
Index: trunk/extensions/Ratings/starrating/star-rating/index.html
@@ -0,0 +1,19 @@
 2+<html>
 3+<head>
 4+</head>
 5+<body>
 6+
 7+<div style="padding:50px; font-family:Arial, Helvetica, sans-serif; font-size:150%;">
 8+ This project has moved. Hold on, I'm taking you there...<br/>
 9+ <a href="http://www.fyneworks.com/jquery/">http://www.fyneworks.com/jquery/</a>
 10+</div>
 11+
 12+<script language="javascript">
 13+if(window.location.toString().match(/localhost/i))
 14+ window.location = 'index.asp';
 15+else
 16+ window.location = "http://www.fyneworks.com/jquery/star-rating/";
 17+</script>
 18+
 19+</body>
 20+</html>
Index: trunk/extensions/Ratings/starrating/star-rating/jquery.js
@@ -0,0 +1,6001 @@
 2+/*!
 3+ * jQuery JavaScript Library v1.4
 4+ * http://jquery.com/
 5+ *
 6+ * Copyright 2010, John Resig
 7+ * Dual licensed under the MIT or GPL Version 2 licenses.
 8+ * http://docs.jquery.com/License
 9+ *
 10+ * Includes Sizzle.js
 11+ * http://sizzlejs.com/
 12+ * Copyright 2010, The Dojo Foundation
 13+ * Released under the MIT, BSD, and GPL Licenses.
 14+ *
 15+ * Date: Wed Jan 13 15:23:05 2010 -0500
 16+ */
 17+(function( window, undefined ) {
 18+
 19+// Define a local copy of jQuery
 20+var jQuery = function( selector, context ) {
 21+ // The jQuery object is actually just the init constructor 'enhanced'
 22+ return new jQuery.fn.init( selector, context );
 23+ },
 24+
 25+ // Map over jQuery in case of overwrite
 26+ _jQuery = window.jQuery,
 27+
 28+ // Map over the $ in case of overwrite
 29+ _$ = window.$,
 30+
 31+ // Use the correct document accordingly with window argument (sandbox)
 32+ document = window.document,
 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+ // Is it a simple selector
 42+ isSimple = /^.[^:#\[\.,]*$/,
 43+
 44+ // Check if a string has a non-whitespace character in it
 45+ rnotwhite = /\S/,
 46+
 47+ // Used for trimming whitespace
 48+ rtrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g,
 49+
 50+ // Match a standalone tag
 51+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
 52+
 53+ // Keep a UserAgent string for use with jQuery.browser
 54+ userAgent = navigator.userAgent,
 55+
 56+ // For matching the engine and version of the browser
 57+ browserMatch,
 58+
 59+ // Has the ready events already been bound?
 60+ readyBound = false,
 61+
 62+ // The functions to execute on DOM ready
 63+ readyList = [],
 64+
 65+ // The ready event handler
 66+ DOMContentLoaded,
 67+
 68+ // Save a reference to some core methods
 69+ toString = Object.prototype.toString,
 70+ hasOwnProperty = Object.prototype.hasOwnProperty,
 71+ push = Array.prototype.push,
 72+ slice = Array.prototype.slice,
 73+ indexOf = Array.prototype.indexOf;
 74+
 75+jQuery.fn = jQuery.prototype = {
 76+ init: function( selector, context ) {
 77+ var match, elem, ret, doc;
 78+
 79+ // Handle $(""), $(null), or $(undefined)
 80+ if ( !selector ) {
 81+ return this;
 82+ }
 83+
 84+ // Handle $(DOMElement)
 85+ if ( selector.nodeType ) {
 86+ this.context = this[0] = selector;
 87+ this.length = 1;
 88+ return this;
 89+ }
 90+
 91+ // Handle HTML strings
 92+ if ( typeof selector === "string" ) {
 93+ // Are we dealing with HTML string or an ID?
 94+ match = quickExpr.exec( selector );
 95+
 96+ // Verify a match, and that no context was specified for #id
 97+ if ( match && (match[1] || !context) ) {
 98+
 99+ // HANDLE: $(html) -> $(array)
 100+ if ( match[1] ) {
 101+ doc = (context ? context.ownerDocument || context : document);
 102+
 103+ // If a single string is passed in and it's a single tag
 104+ // just do a createElement and skip the rest
 105+ ret = rsingleTag.exec( selector );
 106+
 107+ if ( ret ) {
 108+ if ( jQuery.isPlainObject( context ) ) {
 109+ selector = [ document.createElement( ret[1] ) ];
 110+ jQuery.fn.attr.call( selector, context, true );
 111+
 112+ } else {
 113+ selector = [ doc.createElement( ret[1] ) ];
 114+ }
 115+
 116+ } else {
 117+ ret = buildFragment( [ match[1] ], [ doc ] );
 118+ selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
 119+ }
 120+
 121+ // HANDLE: $("#id")
 122+ } else {
 123+ elem = document.getElementById( match[2] );
 124+
 125+ if ( elem ) {
 126+ // Handle the case where IE and Opera return items
 127+ // by name instead of ID
 128+ if ( elem.id !== match[2] ) {
 129+ return rootjQuery.find( selector );
 130+ }
 131+
 132+ // Otherwise, we inject the element directly into the jQuery object
 133+ this.length = 1;
 134+ this[0] = elem;
 135+ }
 136+
 137+ this.context = document;
 138+ this.selector = selector;
 139+ return this;
 140+ }
 141+
 142+ // HANDLE: $("TAG")
 143+ } else if ( !context && /^\w+$/.test( selector ) ) {
 144+ this.selector = selector;
 145+ this.context = document;
 146+ selector = document.getElementsByTagName( selector );
 147+
 148+ // HANDLE: $(expr, $(...))
 149+ } else if ( !context || context.jquery ) {
 150+ return (context || rootjQuery).find( selector );
 151+
 152+ // HANDLE: $(expr, context)
 153+ // (which is just equivalent to: $(context).find(expr)
 154+ } else {
 155+ return jQuery( context ).find( selector );
 156+ }
 157+
 158+ // HANDLE: $(function)
 159+ // Shortcut for document ready
 160+ } else if ( jQuery.isFunction( selector ) ) {
 161+ return rootjQuery.ready( selector );
 162+ }
 163+
 164+ if (selector.selector !== undefined) {
 165+ this.selector = selector.selector;
 166+ this.context = selector.context;
 167+ }
 168+
 169+ return jQuery.isArray( selector ) ?
 170+ this.setArray( selector ) :
 171+ jQuery.makeArray( selector, this );
 172+ },
 173+
 174+ // Start with an empty selector
 175+ selector: "",
 176+
 177+ // The current version of jQuery being used
 178+ jquery: "1.4",
 179+
 180+ // The default length of a jQuery object is 0
 181+ length: 0,
 182+
 183+ // The number of elements contained in the matched element set
 184+ size: function() {
 185+ return this.length;
 186+ },
 187+
 188+ toArray: function() {
 189+ return slice.call( this, 0 );
 190+ },
 191+
 192+ // Get the Nth element in the matched element set OR
 193+ // Get the whole matched element set as a clean array
 194+ get: function( num ) {
 195+ return num == null ?
 196+
 197+ // Return a 'clean' array
 198+ this.toArray() :
 199+
 200+ // Return just the object
 201+ ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
 202+ },
 203+
 204+ // Take an array of elements and push it onto the stack
 205+ // (returning the new matched element set)
 206+ pushStack: function( elems, name, selector ) {
 207+ // Build a new jQuery matched element set
 208+ var ret = jQuery( elems || null );
 209+
 210+ // Add the old object onto the stack (as a reference)
 211+ ret.prevObject = this;
 212+
 213+ ret.context = this.context;
 214+
 215+ if ( name === "find" ) {
 216+ ret.selector = this.selector + (this.selector ? " " : "") + selector;
 217+ } else if ( name ) {
 218+ ret.selector = this.selector + "." + name + "(" + selector + ")";
 219+ }
 220+
 221+ // Return the newly-formed element set
 222+ return ret;
 223+ },
 224+
 225+ // Force the current matched set of elements to become
 226+ // the specified array of elements (destroying the stack in the process)
 227+ // You should use pushStack() in order to do this, but maintain the stack
 228+ setArray: function( elems ) {
 229+ // Resetting the length to 0, then using the native Array push
 230+ // is a super-fast way to populate an object with array-like properties
 231+ this.length = 0;
 232+ push.apply( this, elems );
 233+
 234+ return this;
 235+ },
 236+
 237+ // Execute a callback for every element in the matched set.
 238+ // (You can seed the arguments with an array of args, but this is
 239+ // only used internally.)
 240+ each: function( callback, args ) {
 241+ return jQuery.each( this, callback, args );
 242+ },
 243+
 244+ ready: function( fn ) {
 245+ // Attach the listeners
 246+ jQuery.bindReady();
 247+
 248+ // If the DOM is already ready
 249+ if ( jQuery.isReady ) {
 250+ // Execute the function immediately
 251+ fn.call( document, jQuery );
 252+
 253+ // Otherwise, remember the function for later
 254+ } else if ( readyList ) {
 255+ // Add the function to the wait list
 256+ readyList.push( fn );
 257+ }
 258+
 259+ return this;
 260+ },
 261+
 262+ eq: function( i ) {
 263+ return i === -1 ?
 264+ this.slice( i ) :
 265+ this.slice( i, +i + 1 );
 266+ },
 267+
 268+ first: function() {
 269+ return this.eq( 0 );
 270+ },
 271+
 272+ last: function() {
 273+ return this.eq( -1 );
 274+ },
 275+
 276+ slice: function() {
 277+ return this.pushStack( slice.apply( this, arguments ),
 278+ "slice", slice.call(arguments).join(",") );
 279+ },
 280+
 281+ map: function( callback ) {
 282+ return this.pushStack( jQuery.map(this, function( elem, i ) {
 283+ return callback.call( elem, i, elem );
 284+ }));
 285+ },
 286+
 287+ end: function() {
 288+ return this.prevObject || jQuery(null);
 289+ },
 290+
 291+ // For internal use only.
 292+ // Behaves like an Array's method, not like a jQuery method.
 293+ push: push,
 294+ sort: [].sort,
 295+ splice: [].splice
 296+};
 297+
 298+// Give the init function the jQuery prototype for later instantiation
 299+jQuery.fn.init.prototype = jQuery.fn;
 300+
 301+jQuery.extend = jQuery.fn.extend = function() {
 302+ // copy reference to target object
 303+ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
 304+
 305+ // Handle a deep copy situation
 306+ if ( typeof target === "boolean" ) {
 307+ deep = target;
 308+ target = arguments[1] || {};
 309+ // skip the boolean and the target
 310+ i = 2;
 311+ }
 312+
 313+ // Handle case when target is a string or something (possible in deep copy)
 314+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
 315+ target = {};
 316+ }
 317+
 318+ // extend jQuery itself if only one argument is passed
 319+ if ( length === i ) {
 320+ target = this;
 321+ --i;
 322+ }
 323+
 324+ for ( ; i < length; i++ ) {
 325+ // Only deal with non-null/undefined values
 326+ if ( (options = arguments[ i ]) != null ) {
 327+ // Extend the base object
 328+ for ( name in options ) {
 329+ src = target[ name ];
 330+ copy = options[ name ];
 331+
 332+ // Prevent never-ending loop
 333+ if ( target === copy ) {
 334+ continue;
 335+ }
 336+
 337+ // Recurse if we're merging object literal values or arrays
 338+ if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
 339+ var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
 340+ : jQuery.isArray(copy) ? [] : {};
 341+
 342+ // Never move original objects, clone them
 343+ target[ name ] = jQuery.extend( deep, clone, copy );
 344+
 345+ // Don't bring in undefined values
 346+ } else if ( copy !== undefined ) {
 347+ target[ name ] = copy;
 348+ }
 349+ }
 350+ }
 351+ }
 352+
 353+ // Return the modified object
 354+ return target;
 355+};
 356+
 357+jQuery.extend({
 358+ noConflict: function( deep ) {
 359+ window.$ = _$;
 360+
 361+ if ( deep ) {
 362+ window.jQuery = _jQuery;
 363+ }
 364+
 365+ return jQuery;
 366+ },
 367+
 368+ // Is the DOM ready to be used? Set to true once it occurs.
 369+ isReady: false,
 370+
 371+ // Handle when the DOM is ready
 372+ ready: function() {
 373+ // Make sure that the DOM is not already loaded
 374+ if ( !jQuery.isReady ) {
 375+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
 376+ if ( !document.body ) {
 377+ return setTimeout( jQuery.ready, 13 );
 378+ }
 379+
 380+ // Remember that the DOM is ready
 381+ jQuery.isReady = true;
 382+
 383+ // If there are functions bound, to execute
 384+ if ( readyList ) {
 385+ // Execute all of them
 386+ var fn, i = 0;
 387+ while ( (fn = readyList[ i++ ]) ) {
 388+ fn.call( document, jQuery );
 389+ }
 390+
 391+ // Reset the list of functions
 392+ readyList = null;
 393+ }
 394+
 395+ // Trigger any bound ready events
 396+ if ( jQuery.fn.triggerHandler ) {
 397+ jQuery( document ).triggerHandler( "ready" );
 398+ }
 399+ }
 400+ },
 401+
 402+ bindReady: function() {
 403+ if ( readyBound ) {
 404+ return;
 405+ }
 406+
 407+ readyBound = true;
 408+
 409+ // Catch cases where $(document).ready() is called after the
 410+ // browser event has already occurred.
 411+ if ( document.readyState === "complete" ) {
 412+ return jQuery.ready();
 413+ }
 414+
 415+ // Mozilla, Opera and webkit nightlies currently support this event
 416+ if ( document.addEventListener ) {
 417+ // Use the handy event callback
 418+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 419+
 420+ // A fallback to window.onload, that will always work
 421+ window.addEventListener( "load", jQuery.ready, false );
 422+
 423+ // If IE event model is used
 424+ } else if ( document.attachEvent ) {
 425+ // ensure firing before onload,
 426+ // maybe late but safe also for iframes
 427+ document.attachEvent("onreadystatechange", DOMContentLoaded);
 428+
 429+ // A fallback to window.onload, that will always work
 430+ window.attachEvent( "onload", jQuery.ready );
 431+
 432+ // If IE and not a frame
 433+ // continually check to see if the document is ready
 434+ var toplevel = false;
 435+
 436+ try {
 437+ toplevel = window.frameElement == null;
 438+ } catch(e) {}
 439+
 440+ if ( document.documentElement.doScroll && toplevel ) {
 441+ doScrollCheck();
 442+ }
 443+ }
 444+ },
 445+
 446+ // See test/unit/core.js for details concerning isFunction.
 447+ // Since version 1.3, DOM methods and functions like alert
 448+ // aren't supported. They return false on IE (#2968).
 449+ isFunction: function( obj ) {
 450+ return toString.call(obj) === "[object Function]";
 451+ },
 452+
 453+ isArray: function( obj ) {
 454+ return toString.call(obj) === "[object Array]";
 455+ },
 456+
 457+ isPlainObject: function( obj ) {
 458+ // Must be an Object.
 459+ // Because of IE, we also have to check the presence of the constructor property.
 460+ // Make sure that DOM nodes and window objects don't pass through, as well
 461+ if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
 462+ return false;
 463+ }
 464+
 465+ // Not own constructor property must be Object
 466+ if ( obj.constructor
 467+ && !hasOwnProperty.call(obj, "constructor")
 468+ && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
 469+ return false;
 470+ }
 471+
 472+ // Own properties are enumerated firstly, so to speed up,
 473+ // if last one is own, then all properties are own.
 474+
 475+ var key;
 476+ for ( key in obj ) {}
 477+
 478+ return key === undefined || hasOwnProperty.call( obj, key );
 479+ },
 480+
 481+ isEmptyObject: function( obj ) {
 482+ for ( var name in obj ) {
 483+ return false;
 484+ }
 485+ return true;
 486+ },
 487+
 488+ noop: function() {},
 489+
 490+ // Evalulates a script in a global context
 491+ globalEval: function( data ) {
 492+ if ( data && rnotwhite.test(data) ) {
 493+ // Inspired by code by Andrea Giammarchi
 494+ // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
 495+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
 496+ script = document.createElement("script");
 497+
 498+ script.type = "text/javascript";
 499+
 500+ if ( jQuery.support.scriptEval ) {
 501+ script.appendChild( document.createTextNode( data ) );
 502+ } else {
 503+ script.text = data;
 504+ }
 505+
 506+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
 507+ // This arises when a base node is used (#2709).
 508+ head.insertBefore( script, head.firstChild );
 509+ head.removeChild( script );
 510+ }
 511+ },
 512+
 513+ nodeName: function( elem, name ) {
 514+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
 515+ },
 516+
 517+ // args is for internal usage only
 518+ each: function( object, callback, args ) {
 519+ var name, i = 0,
 520+ length = object.length,
 521+ isObj = length === undefined || jQuery.isFunction(object);
 522+
 523+ if ( args ) {
 524+ if ( isObj ) {
 525+ for ( name in object ) {
 526+ if ( callback.apply( object[ name ], args ) === false ) {
 527+ break;
 528+ }
 529+ }
 530+ } else {
 531+ for ( ; i < length; ) {
 532+ if ( callback.apply( object[ i++ ], args ) === false ) {
 533+ break;
 534+ }
 535+ }
 536+ }
 537+
 538+ // A special, fast, case for the most common use of each
 539+ } else {
 540+ if ( isObj ) {
 541+ for ( name in object ) {
 542+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
 543+ break;
 544+ }
 545+ }
 546+ } else {
 547+ for ( var value = object[0];
 548+ i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
 549+ }
 550+ }
 551+
 552+ return object;
 553+ },
 554+
 555+ trim: function( text ) {
 556+ return (text || "").replace( rtrim, "" );
 557+ },
 558+
 559+ // results is for internal usage only
 560+ makeArray: function( array, results ) {
 561+ var ret = results || [];
 562+
 563+ if ( array != null ) {
 564+ // The window, strings (and functions) also have 'length'
 565+ // The extra typeof function check is to prevent crashes
 566+ // in Safari 2 (See: #3039)
 567+ if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
 568+ push.call( ret, array );
 569+ } else {
 570+ jQuery.merge( ret, array );
 571+ }
 572+ }
 573+
 574+ return ret;
 575+ },
 576+
 577+ inArray: function( elem, array ) {
 578+ if ( array.indexOf ) {
 579+ return array.indexOf( elem );
 580+ }
 581+
 582+ for ( var i = 0, length = array.length; i < length; i++ ) {
 583+ if ( array[ i ] === elem ) {
 584+ return i;
 585+ }
 586+ }
 587+
 588+ return -1;
 589+ },
 590+
 591+ merge: function( first, second ) {
 592+ var i = first.length, j = 0;
 593+
 594+ if ( typeof second.length === "number" ) {
 595+ for ( var l = second.length; j < l; j++ ) {
 596+ first[ i++ ] = second[ j ];
 597+ }
 598+ } else {
 599+ while ( second[j] !== undefined ) {
 600+ first[ i++ ] = second[ j++ ];
 601+ }
 602+ }
 603+
 604+ first.length = i;
 605+
 606+ return first;
 607+ },
 608+
 609+ grep: function( elems, callback, inv ) {
 610+ var ret = [];
 611+
 612+ // Go through the array, only saving the items
 613+ // that pass the validator function
 614+ for ( var i = 0, length = elems.length; i < length; i++ ) {
 615+ if ( !inv !== !callback( elems[ i ], i ) ) {
 616+ ret.push( elems[ i ] );
 617+ }
 618+ }
 619+
 620+ return ret;
 621+ },
 622+
 623+ // arg is for internal usage only
 624+ map: function( elems, callback, arg ) {
 625+ var ret = [], value;
 626+
 627+ // Go through the array, translating each of the items to their
 628+ // new value (or values).
 629+ for ( var i = 0, length = elems.length; i < length; i++ ) {
 630+ value = callback( elems[ i ], i, arg );
 631+
 632+ if ( value != null ) {
 633+ ret[ ret.length ] = value;
 634+ }
 635+ }
 636+
 637+ return ret.concat.apply( [], ret );
 638+ },
 639+
 640+ // A global GUID counter for objects
 641+ guid: 1,
 642+
 643+ proxy: function( fn, proxy, thisObject ) {
 644+ if ( arguments.length === 2 ) {
 645+ if ( typeof proxy === "string" ) {
 646+ thisObject = fn;
 647+ fn = thisObject[ proxy ];
 648+ proxy = undefined;
 649+
 650+ } else if ( proxy && !jQuery.isFunction( proxy ) ) {
 651+ thisObject = proxy;
 652+ proxy = undefined;
 653+ }
 654+ }
 655+
 656+ if ( !proxy && fn ) {
 657+ proxy = function() {
 658+ return fn.apply( thisObject || this, arguments );
 659+ };
 660+ }
 661+
 662+ // Set the guid of unique handler to the same of original handler, so it can be removed
 663+ if ( fn ) {
 664+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
 665+ }
 666+
 667+ // So proxy can be declared as an argument
 668+ return proxy;
 669+ },
 670+
 671+ // Use of jQuery.browser is frowned upon.
 672+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
 673+ uaMatch: function( ua ) {
 674+ var ret = { browser: "" };
 675+
 676+ ua = ua.toLowerCase();
 677+
 678+ if ( /webkit/.test( ua ) ) {
 679+ ret = { browser: "webkit", version: /webkit[\/ ]([\w.]+)/ };
 680+
 681+ } else if ( /opera/.test( ua ) ) {
 682+ ret = { browser: "opera", version: /version/.test( ua ) ? /version[\/ ]([\w.]+)/ : /opera[\/ ]([\w.]+)/ };
 683+
 684+ } else if ( /msie/.test( ua ) ) {
 685+ ret = { browser: "msie", version: /msie ([\w.]+)/ };
 686+
 687+ } else if ( /mozilla/.test( ua ) && !/compatible/.test( ua ) ) {
 688+ ret = { browser: "mozilla", version: /rv:([\w.]+)/ };
 689+ }
 690+
 691+ ret.version = (ret.version && ret.version.exec( ua ) || [0, "0"])[1];
 692+
 693+ return ret;
 694+ },
 695+
 696+ browser: {}
 697+});
 698+
 699+browserMatch = jQuery.uaMatch( userAgent );
 700+if ( browserMatch.browser ) {
 701+ jQuery.browser[ browserMatch.browser ] = true;
 702+ jQuery.browser.version = browserMatch.version;
 703+}
 704+
 705+// Deprecated, use jQuery.browser.webkit instead
 706+if ( jQuery.browser.webkit ) {
 707+ jQuery.browser.safari = true;
 708+}
 709+
 710+if ( indexOf ) {
 711+ jQuery.inArray = function( elem, array ) {
 712+ return indexOf.call( array, elem );
 713+ };
 714+}
 715+
 716+// All jQuery objects should point back to these
 717+rootjQuery = jQuery(document);
 718+
 719+// Cleanup functions for the document ready method
 720+if ( document.addEventListener ) {
 721+ DOMContentLoaded = function() {
 722+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 723+ jQuery.ready();
 724+ };
 725+
 726+} else if ( document.attachEvent ) {
 727+ DOMContentLoaded = function() {
 728+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
 729+ if ( document.readyState === "complete" ) {
 730+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
 731+ jQuery.ready();
 732+ }
 733+ };
 734+}
 735+
 736+// The DOM ready check for Internet Explorer
 737+function doScrollCheck() {
 738+ if ( jQuery.isReady ) {
 739+ return;
 740+ }
 741+
 742+ try {
 743+ // If IE is used, use the trick by Diego Perini
 744+ // http://javascript.nwbox.com/IEContentLoaded/
 745+ document.documentElement.doScroll("left");
 746+ } catch( error ) {
 747+ setTimeout( doScrollCheck, 1 );
 748+ return;
 749+ }
 750+
 751+ // and execute any waiting functions
 752+ jQuery.ready();
 753+}
 754+
 755+if ( indexOf ) {
 756+ jQuery.inArray = function( elem, array ) {
 757+ return indexOf.call( array, elem );
 758+ };
 759+}
 760+
 761+function evalScript( i, elem ) {
 762+ if ( elem.src ) {
 763+ jQuery.ajax({
 764+ url: elem.src,
 765+ async: false,
 766+ dataType: "script"
 767+ });
 768+ } else {
 769+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
 770+ }
 771+
 772+ if ( elem.parentNode ) {
 773+ elem.parentNode.removeChild( elem );
 774+ }
 775+}
 776+
 777+// Mutifunctional method to get and set values to a collection
 778+// The value/s can be optionally by executed if its a function
 779+function access( elems, key, value, exec, fn, pass ) {
 780+ var length = elems.length;
 781+
 782+ // Setting many attributes
 783+ if ( typeof key === "object" ) {
 784+ for ( var k in key ) {
 785+ access( elems, k, key[k], exec, fn, value );
 786+ }
 787+ return elems;
 788+ }
 789+
 790+ // Setting one attribute
 791+ if ( value !== undefined ) {
 792+ // Optionally, function values get executed if exec is true
 793+ exec = !pass && exec && jQuery.isFunction(value);
 794+
 795+ for ( var i = 0; i < length; i++ ) {
 796+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
 797+ }
 798+
 799+ return elems;
 800+ }
 801+
 802+ // Getting an attribute
 803+ return length ? fn( elems[0], key ) : null;
 804+}
 805+
 806+function now() {
 807+ return (new Date).getTime();
 808+}
 809+(function() {
 810+
 811+ jQuery.support = {};
 812+
 813+ var root = document.documentElement,
 814+ script = document.createElement("script"),
 815+ div = document.createElement("div"),
 816+ id = "script" + now();
 817+
 818+ div.style.display = "none";
 819+ div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
 820+
 821+ var all = div.getElementsByTagName("*"),
 822+ a = div.getElementsByTagName("a")[0];
 823+
 824+ // Can't get basic test support
 825+ if ( !all || !all.length || !a ) {
 826+ return;
 827+ }
 828+
 829+ jQuery.support = {
 830+ // IE strips leading whitespace when .innerHTML is used
 831+ leadingWhitespace: div.firstChild.nodeType === 3,
 832+
 833+ // Make sure that tbody elements aren't automatically inserted
 834+ // IE will insert them into empty tables
 835+ tbody: !div.getElementsByTagName("tbody").length,
 836+
 837+ // Make sure that link elements get serialized correctly by innerHTML
 838+ // This requires a wrapper element in IE
 839+ htmlSerialize: !!div.getElementsByTagName("link").length,
 840+
 841+ // Get the style information from getAttribute
 842+ // (IE uses .cssText insted)
 843+ style: /red/.test( a.getAttribute("style") ),
 844+
 845+ // Make sure that URLs aren't manipulated
 846+ // (IE normalizes it by default)
 847+ hrefNormalized: a.getAttribute("href") === "/a",
 848+
 849+ // Make sure that element opacity exists
 850+ // (IE uses filter instead)
 851+ // Use a regex to work around a WebKit issue. See #5145
 852+ opacity: /^0.55$/.test( a.style.opacity ),
 853+
 854+ // Verify style float existence
 855+ // (IE uses styleFloat instead of cssFloat)
 856+ cssFloat: !!a.style.cssFloat,
 857+
 858+ // Make sure that if no value is specified for a checkbox
 859+ // that it defaults to "on".
 860+ // (WebKit defaults to "" instead)
 861+ checkOn: div.getElementsByTagName("input")[0].value === "on",
 862+
 863+ // Make sure that a selected-by-default option has a working selected property.
 864+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
 865+ optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
 866+
 867+ // Will be defined later
 868+ scriptEval: false,
 869+ noCloneEvent: true,
 870+ boxModel: null
 871+ };
 872+
 873+ script.type = "text/javascript";
 874+ try {
 875+ script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
 876+ } catch(e) {}
 877+
 878+ root.insertBefore( script, root.firstChild );
 879+
 880+ // Make sure that the execution of code works by injecting a script
 881+ // tag with appendChild/createTextNode
 882+ // (IE doesn't support this, fails, and uses .text instead)
 883+ if ( window[ id ] ) {
 884+ jQuery.support.scriptEval = true;
 885+ delete window[ id ];
 886+ }
 887+
 888+ root.removeChild( script );
 889+
 890+ if ( div.attachEvent && div.fireEvent ) {
 891+ div.attachEvent("onclick", function click() {
 892+ // Cloning a node shouldn't copy over any
 893+ // bound event handlers (IE does this)
 894+ jQuery.support.noCloneEvent = false;
 895+ div.detachEvent("onclick", click);
 896+ });
 897+ div.cloneNode(true).fireEvent("onclick");
 898+ }
 899+
 900+ // Figure out if the W3C box model works as expected
 901+ // document.body must exist before we can do this
 902+ // TODO: This timeout is temporary until I move ready into core.js.
 903+ jQuery(function() {
 904+ var div = document.createElement("div");
 905+ div.style.width = div.style.paddingLeft = "1px";
 906+
 907+ document.body.appendChild( div );
 908+ jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
 909+ document.body.removeChild( div ).style.display = 'none';
 910+ div = null;
 911+ });
 912+
 913+ // Technique from Juriy Zaytsev
 914+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
 915+ var eventSupported = function( eventName ) {
 916+ var el = document.createElement("div");
 917+ eventName = "on" + eventName;
 918+
 919+ var isSupported = (eventName in el);
 920+ if ( !isSupported ) {
 921+ el.setAttribute(eventName, "return;");
 922+ isSupported = typeof el[eventName] === "function";
 923+ }
 924+ el = null;
 925+
 926+ return isSupported;
 927+ };
 928+
 929+ jQuery.support.submitBubbles = eventSupported("submit");
 930+ jQuery.support.changeBubbles = eventSupported("change");
 931+
 932+ // release memory in IE
 933+ root = script = div = all = a = null;
 934+})();
 935+
 936+jQuery.props = {
 937+ "for": "htmlFor",
 938+ "class": "className",
 939+ readonly: "readOnly",
 940+ maxlength: "maxLength",
 941+ cellspacing: "cellSpacing",
 942+ rowspan: "rowSpan",
 943+ colspan: "colSpan",
 944+ tabindex: "tabIndex",
 945+ usemap: "useMap",
 946+ frameborder: "frameBorder"
 947+};
 948+var expando = "jQuery" + now(), uuid = 0, windowData = {};
 949+var emptyObject = {};
 950+
 951+jQuery.extend({
 952+ cache: {},
 953+
 954+ expando:expando,
 955+
 956+ // The following elements throw uncatchable exceptions if you
 957+ // attempt to add expando properties to them.
 958+ noData: {
 959+ "embed": true,
 960+ "object": true,
 961+ "applet": true
 962+ },
 963+
 964+ data: function( elem, name, data ) {
 965+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
 966+ return;
 967+ }
 968+
 969+ elem = elem == window ?
 970+ windowData :
 971+ elem;
 972+
 973+ var id = elem[ expando ], cache = jQuery.cache, thisCache;
 974+
 975+ // Handle the case where there's no name immediately
 976+ if ( !name && !id ) {
 977+ return null;
 978+ }
 979+
 980+ // Compute a unique ID for the element
 981+ if ( !id ) {
 982+ id = ++uuid;
 983+ }
 984+
 985+ // Avoid generating a new cache unless none exists and we
 986+ // want to manipulate it.
 987+ if ( typeof name === "object" ) {
 988+ elem[ expando ] = id;
 989+ thisCache = cache[ id ] = jQuery.extend(true, {}, name);
 990+ } else if ( cache[ id ] ) {
 991+ thisCache = cache[ id ];
 992+ } else if ( typeof data === "undefined" ) {
 993+ thisCache = emptyObject;
 994+ } else {
 995+ thisCache = cache[ id ] = {};
 996+ }
 997+
 998+ // Prevent overriding the named cache with undefined values
 999+ if ( data !== undefined ) {
 1000+ elem[ expando ] = id;
 1001+ thisCache[ name ] = data;
 1002+ }
 1003+
 1004+ return typeof name === "string" ? thisCache[ name ] : thisCache;
 1005+ },
 1006+
 1007+ removeData: function( elem, name ) {
 1008+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
 1009+ return;
 1010+ }
 1011+
 1012+ elem = elem == window ?
 1013+ windowData :
 1014+ elem;
 1015+
 1016+ var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];
 1017+
 1018+ // If we want to remove a specific section of the element's data
 1019+ if ( name ) {
 1020+ if ( thisCache ) {
 1021+ // Remove the section of cache data
 1022+ delete thisCache[ name ];
 1023+
 1024+ // If we've removed all the data, remove the element's cache
 1025+ if ( jQuery.isEmptyObject(thisCache) ) {
 1026+ jQuery.removeData( elem );
 1027+ }
 1028+ }
 1029+
 1030+ // Otherwise, we want to remove all of the element's data
 1031+ } else {
 1032+ // Clean up the element expando
 1033+ try {
 1034+ delete elem[ expando ];
 1035+ } catch( e ) {
 1036+ // IE has trouble directly removing the expando
 1037+ // but it's ok with using removeAttribute
 1038+ if ( elem.removeAttribute ) {
 1039+ elem.removeAttribute( expando );
 1040+ }
 1041+ }
 1042+
 1043+ // Completely remove the data cache
 1044+ delete cache[ id ];
 1045+ }
 1046+ }
 1047+});
 1048+
 1049+jQuery.fn.extend({
 1050+ data: function( key, value ) {
 1051+ if ( typeof key === "undefined" && this.length ) {
 1052+ return jQuery.data( this[0] );
 1053+
 1054+ } else if ( typeof key === "object" ) {
 1055+ return this.each(function() {
 1056+ jQuery.data( this, key );
 1057+ });
 1058+ }
 1059+
 1060+ var parts = key.split(".");
 1061+ parts[1] = parts[1] ? "." + parts[1] : "";
 1062+
 1063+ if ( value === undefined ) {
 1064+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
 1065+
 1066+ if ( data === undefined && this.length ) {
 1067+ data = jQuery.data( this[0], key );
 1068+ }
 1069+ return data === undefined && parts[1] ?
 1070+ this.data( parts[0] ) :
 1071+ data;
 1072+ } else {
 1073+ return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
 1074+ jQuery.data( this, key, value );
 1075+ });
 1076+ }
 1077+ },
 1078+
 1079+ removeData: function( key ) {
 1080+ return this.each(function() {
 1081+ jQuery.removeData( this, key );
 1082+ });
 1083+ }
 1084+});
 1085+jQuery.extend({
 1086+ queue: function( elem, type, data ) {
 1087+ if ( !elem ) {
 1088+ return;
 1089+ }
 1090+
 1091+ type = (type || "fx") + "queue";
 1092+ var q = jQuery.data( elem, type );
 1093+
 1094+ // Speed up dequeue by getting out quickly if this is just a lookup
 1095+ if ( !data ) {
 1096+ return q || [];
 1097+ }
 1098+
 1099+ if ( !q || jQuery.isArray(data) ) {
 1100+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
 1101+
 1102+ } else {
 1103+ q.push( data );
 1104+ }
 1105+
 1106+ return q;
 1107+ },
 1108+
 1109+ dequeue: function( elem, type ) {
 1110+ type = type || "fx";
 1111+
 1112+ var queue = jQuery.queue( elem, type ), fn = queue.shift();
 1113+
 1114+ // If the fx queue is dequeued, always remove the progress sentinel
 1115+ if ( fn === "inprogress" ) {
 1116+ fn = queue.shift();
 1117+ }
 1118+
 1119+ if ( fn ) {
 1120+ // Add a progress sentinel to prevent the fx queue from being
 1121+ // automatically dequeued
 1122+ if ( type === "fx" ) {
 1123+ queue.unshift("inprogress");
 1124+ }
 1125+
 1126+ fn.call(elem, function() {
 1127+ jQuery.dequeue(elem, type);
 1128+ });
 1129+ }
 1130+ }
 1131+});
 1132+
 1133+jQuery.fn.extend({
 1134+ queue: function( type, data ) {
 1135+ if ( typeof type !== "string" ) {
 1136+ data = type;
 1137+ type = "fx";
 1138+ }
 1139+
 1140+ if ( data === undefined ) {
 1141+ return jQuery.queue( this[0], type );
 1142+ }
 1143+ return this.each(function( i, elem ) {
 1144+ var queue = jQuery.queue( this, type, data );
 1145+
 1146+ if ( type === "fx" && queue[0] !== "inprogress" ) {
 1147+ jQuery.dequeue( this, type );
 1148+ }
 1149+ });
 1150+ },
 1151+ dequeue: function( type ) {
 1152+ return this.each(function() {
 1153+ jQuery.dequeue( this, type );
 1154+ });
 1155+ },
 1156+
 1157+ // Based off of the plugin by Clint Helfers, with permission.
 1158+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
 1159+ delay: function( time, type ) {
 1160+ time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
 1161+ type = type || "fx";
 1162+
 1163+ return this.queue( type, function() {
 1164+ var elem = this;
 1165+ setTimeout(function() {
 1166+ jQuery.dequeue( elem, type );
 1167+ }, time );
 1168+ });
 1169+ },
 1170+
 1171+ clearQueue: function( type ) {
 1172+ return this.queue( type || "fx", [] );
 1173+ }
 1174+});
 1175+var rclass = /[\n\t]/g,
 1176+ rspace = /\s+/,
 1177+ rreturn = /\r/g,
 1178+ rspecialurl = /href|src|style/,
 1179+ rtype = /(button|input)/i,
 1180+ rfocusable = /(button|input|object|select|textarea)/i,
 1181+ rclickable = /^(a|area)$/i,
 1182+ rradiocheck = /radio|checkbox/;
 1183+
 1184+jQuery.fn.extend({
 1185+ attr: function( name, value ) {
 1186+ return access( this, name, value, true, jQuery.attr );
 1187+ },
 1188+
 1189+ removeAttr: function( name, fn ) {
 1190+ return this.each(function(){
 1191+ jQuery.attr( this, name, "" );
 1192+ if ( this.nodeType === 1 ) {
 1193+ this.removeAttribute( name );
 1194+ }
 1195+ });
 1196+ },
 1197+
 1198+ addClass: function( value ) {
 1199+ if ( jQuery.isFunction(value) ) {
 1200+ return this.each(function(i) {
 1201+ var self = jQuery(this);
 1202+ self.addClass( value.call(this, i, self.attr("class")) );
 1203+ });
 1204+ }
 1205+
 1206+ if ( value && typeof value === "string" ) {
 1207+ var classNames = (value || "").split( rspace );
 1208+
 1209+ for ( var i = 0, l = this.length; i < l; i++ ) {
 1210+ var elem = this[i];
 1211+
 1212+ if ( elem.nodeType === 1 ) {
 1213+ if ( !elem.className ) {
 1214+ elem.className = value;
 1215+
 1216+ } else {
 1217+ var className = " " + elem.className + " ";
 1218+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
 1219+ if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
 1220+ elem.className += " " + classNames[c];
 1221+ }
 1222+ }
 1223+ }
 1224+ }
 1225+ }
 1226+ }
 1227+
 1228+ return this;
 1229+ },
 1230+
 1231+ removeClass: function( value ) {
 1232+ if ( jQuery.isFunction(value) ) {
 1233+ return this.each(function(i) {
 1234+ var self = jQuery(this);
 1235+ self.removeClass( value.call(this, i, self.attr("class")) );
 1236+ });
 1237+ }
 1238+
 1239+ if ( (value && typeof value === "string") || value === undefined ) {
 1240+ var classNames = (value || "").split(rspace);
 1241+
 1242+ for ( var i = 0, l = this.length; i < l; i++ ) {
 1243+ var elem = this[i];
 1244+
 1245+ if ( elem.nodeType === 1 && elem.className ) {
 1246+ if ( value ) {
 1247+ var className = (" " + elem.className + " ").replace(rclass, " ");
 1248+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
 1249+ className = className.replace(" " + classNames[c] + " ", " ");
 1250+ }
 1251+ elem.className = className.substring(1, className.length - 1);
 1252+
 1253+ } else {
 1254+ elem.className = "";
 1255+ }
 1256+ }
 1257+ }
 1258+ }
 1259+
 1260+ return this;
 1261+ },
 1262+
 1263+ toggleClass: function( value, stateVal ) {
 1264+ var type = typeof value, isBool = typeof stateVal === "boolean";
 1265+
 1266+ if ( jQuery.isFunction( value ) ) {
 1267+ return this.each(function(i) {
 1268+ var self = jQuery(this);
 1269+ self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
 1270+ });
 1271+ }
 1272+
 1273+ return this.each(function() {
 1274+ if ( type === "string" ) {
 1275+ // toggle individual class names
 1276+ var className, i = 0, self = jQuery(this),
 1277+ state = stateVal,
 1278+ classNames = value.split( rspace );
 1279+
 1280+ while ( (className = classNames[ i++ ]) ) {
 1281+ // check each className given, space seperated list
 1282+ state = isBool ? state : !self.hasClass( className );
 1283+ self[ state ? "addClass" : "removeClass" ]( className );
 1284+ }
 1285+
 1286+ } else if ( type === "undefined" || type === "boolean" ) {
 1287+ if ( this.className ) {
 1288+ // store className if set
 1289+ jQuery.data( this, "__className__", this.className );
 1290+ }
 1291+
 1292+ // toggle whole className
 1293+ this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
 1294+ }
 1295+ });
 1296+ },
 1297+
 1298+ hasClass: function( selector ) {
 1299+ var className = " " + selector + " ";
 1300+ for ( var i = 0, l = this.length; i < l; i++ ) {
 1301+ if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
 1302+ return true;
 1303+ }
 1304+ }
 1305+
 1306+ return false;
 1307+ },
 1308+
 1309+ val: function( value ) {
 1310+ if ( value === undefined ) {
 1311+ var elem = this[0];
 1312+
 1313+ if ( elem ) {
 1314+ if ( jQuery.nodeName( elem, "option" ) ) {
 1315+ return (elem.attributes.value || {}).specified ? elem.value : elem.text;
 1316+ }
 1317+
 1318+ // We need to handle select boxes special
 1319+ if ( jQuery.nodeName( elem, "select" ) ) {
 1320+ var index = elem.selectedIndex,
 1321+ values = [],
 1322+ options = elem.options,
 1323+ one = elem.type === "select-one";
 1324+
 1325+ // Nothing was selected
 1326+ if ( index < 0 ) {
 1327+ return null;
 1328+ }
 1329+
 1330+ // Loop through all the selected options
 1331+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
 1332+ var option = options[ i ];
 1333+
 1334+ if ( option.selected ) {
 1335+ // Get the specifc value for the option
 1336+ value = jQuery(option).val();
 1337+
 1338+ // We don't need an array for one selects
 1339+ if ( one ) {
 1340+ return value;
 1341+ }
 1342+
 1343+ // Multi-Selects return an array
 1344+ values.push( value );
 1345+ }
 1346+ }
 1347+
 1348+ return values;
 1349+ }
 1350+
 1351+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
 1352+ if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
 1353+ return elem.getAttribute("value") === null ? "on" : elem.value;
 1354+ }
 1355+
 1356+
 1357+ // Everything else, we just grab the value
 1358+ return (elem.value || "").replace(rreturn, "");
 1359+
 1360+ }
 1361+
 1362+ return undefined;
 1363+ }
 1364+
 1365+ var isFunction = jQuery.isFunction(value);
 1366+
 1367+ return this.each(function(i) {
 1368+ var self = jQuery(this), val = value;
 1369+
 1370+ if ( this.nodeType !== 1 ) {
 1371+ return;
 1372+ }
 1373+
 1374+ if ( isFunction ) {
 1375+ val = value.call(this, i, self.val());
 1376+ }
 1377+
 1378+ // Typecast each time if the value is a Function and the appended
 1379+ // value is therefore different each time.
 1380+ if ( typeof val === "number" ) {
 1381+ val += "";
 1382+ }
 1383+
 1384+ if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
 1385+ this.checked = jQuery.inArray( self.val(), val ) >= 0;
 1386+
 1387+ } else if ( jQuery.nodeName( this, "select" ) ) {
 1388+ var values = jQuery.makeArray(val);
 1389+
 1390+ jQuery( "option", this ).each(function() {
 1391+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
 1392+ });
 1393+
 1394+ if ( !values.length ) {
 1395+ this.selectedIndex = -1;
 1396+ }
 1397+
 1398+ } else {
 1399+ this.value = val;
 1400+ }
 1401+ });
 1402+ }
 1403+});
 1404+
 1405+jQuery.extend({
 1406+ attrFn: {
 1407+ val: true,
 1408+ css: true,
 1409+ html: true,
 1410+ text: true,
 1411+ data: true,
 1412+ width: true,
 1413+ height: true,
 1414+ offset: true
 1415+ },
 1416+
 1417+ attr: function( elem, name, value, pass ) {
 1418+ // don't set attributes on text and comment nodes
 1419+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
 1420+ return undefined;
 1421+ }
 1422+
 1423+ if ( pass && name in jQuery.attrFn ) {
 1424+ return jQuery(elem)[name](value);
 1425+ }
 1426+
 1427+ var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
 1428+ // Whether we are setting (or getting)
 1429+ set = value !== undefined;
 1430+
 1431+ // Try to normalize/fix the name
 1432+ name = notxml && jQuery.props[ name ] || name;
 1433+
 1434+ // Only do all the following if this is a node (faster for style)
 1435+ if ( elem.nodeType === 1 ) {
 1436+ // These attributes require special treatment
 1437+ var special = rspecialurl.test( name );
 1438+
 1439+ // Safari mis-reports the default selected property of an option
 1440+ // Accessing the parent's selectedIndex property fixes it
 1441+ if ( name === "selected" && !jQuery.support.optSelected ) {
 1442+ var parent = elem.parentNode;
 1443+ if ( parent ) {
 1444+ parent.selectedIndex;
 1445+
 1446+ // Make sure that it also works with optgroups, see #5701
 1447+ if ( parent.parentNode ) {
 1448+ parent.parentNode.selectedIndex;
 1449+ }
 1450+ }
 1451+ }
 1452+
 1453+ // If applicable, access the attribute via the DOM 0 way
 1454+ if ( name in elem && notxml && !special ) {
 1455+ if ( set ) {
 1456+ // We can't allow the type property to be changed (since it causes problems in IE)
 1457+ if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
 1458+ throw "type property can't be changed";
 1459+ }
 1460+
 1461+ elem[ name ] = value;
 1462+ }
 1463+
 1464+ // browsers index elements by id/name on forms, give priority to attributes.
 1465+ if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
 1466+ return elem.getAttributeNode( name ).nodeValue;
 1467+ }
 1468+
 1469+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
 1470+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
 1471+ if ( name === "tabIndex" ) {
 1472+ var attributeNode = elem.getAttributeNode( "tabIndex" );
 1473+
 1474+ return attributeNode && attributeNode.specified ?
 1475+ attributeNode.value :
 1476+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
 1477+ 0 :
 1478+ undefined;
 1479+ }
 1480+
 1481+ return elem[ name ];
 1482+ }
 1483+
 1484+ if ( !jQuery.support.style && notxml && name === "style" ) {
 1485+ if ( set ) {
 1486+ elem.style.cssText = "" + value;
 1487+ }
 1488+
 1489+ return elem.style.cssText;
 1490+ }
 1491+
 1492+ if ( set ) {
 1493+ // convert the value to a string (all browsers do this but IE) see #1070
 1494+ elem.setAttribute( name, "" + value );
 1495+ }
 1496+
 1497+ var attr = !jQuery.support.hrefNormalized && notxml && special ?
 1498+ // Some attributes require a special call on IE
 1499+ elem.getAttribute( name, 2 ) :
 1500+ elem.getAttribute( name );
 1501+
 1502+ // Non-existent attributes return null, we normalize to undefined
 1503+ return attr === null ? undefined : attr;
 1504+ }
 1505+
 1506+ // elem is actually elem.style ... set the style
 1507+ // Using attr for specific style information is now deprecated. Use style insead.
 1508+ return jQuery.style( elem, name, value );
 1509+ }
 1510+});
 1511+var fcleanup = function( nm ) {
 1512+ return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
 1513+ return "\\" + ch;
 1514+ });
 1515+};
 1516+
 1517+/*
 1518+ * A number of helper functions used for managing events.
 1519+ * Many of the ideas behind this code originated from
 1520+ * Dean Edwards' addEvent library.
 1521+ */
 1522+jQuery.event = {
 1523+
 1524+ // Bind an event to an element
 1525+ // Original by Dean Edwards
 1526+ add: function( elem, types, handler, data ) {
 1527+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
 1528+ return;
 1529+ }
 1530+
 1531+ // For whatever reason, IE has trouble passing the window object
 1532+ // around, causing it to be cloned in the process
 1533+ if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
 1534+ elem = window;
 1535+ }
 1536+
 1537+ // Make sure that the function being executed has a unique ID
 1538+ if ( !handler.guid ) {
 1539+ handler.guid = jQuery.guid++;
 1540+ }
 1541+
 1542+ // if data is passed, bind to handler
 1543+ if ( data !== undefined ) {
 1544+ // Create temporary function pointer to original handler
 1545+ var fn = handler;
 1546+
 1547+ // Create unique handler function, wrapped around original handler
 1548+ handler = jQuery.proxy( fn );
 1549+
 1550+ // Store data in unique handler
 1551+ handler.data = data;
 1552+ }
 1553+
 1554+ // Init the element's event structure
 1555+ var events = jQuery.data( elem, "events" ) || jQuery.data( elem, "events", {} ),
 1556+ handle = jQuery.data( elem, "handle" ), eventHandle;
 1557+
 1558+ if ( !handle ) {
 1559+ eventHandle = function() {
 1560+ // Handle the second event of a trigger and when
 1561+ // an event is called after a page has unloaded
 1562+ return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
 1563+ jQuery.event.handle.apply( eventHandle.elem, arguments ) :
 1564+ undefined;
 1565+ };
 1566+
 1567+ handle = jQuery.data( elem, "handle", eventHandle );
 1568+ }
 1569+
 1570+ // If no handle is found then we must be trying to bind to one of the
 1571+ // banned noData elements
 1572+ if ( !handle ) {
 1573+ return;
 1574+ }
 1575+
 1576+ // Add elem as a property of the handle function
 1577+ // This is to prevent a memory leak with non-native
 1578+ // event in IE.
 1579+ handle.elem = elem;
 1580+
 1581+ // Handle multiple events separated by a space
 1582+ // jQuery(...).bind("mouseover mouseout", fn);
 1583+ types = types.split( /\s+/ );
 1584+ var type, i=0;
 1585+ while ( (type = types[ i++ ]) ) {
 1586+ // Namespaced event handlers
 1587+ var namespaces = type.split(".");
 1588+ type = namespaces.shift();
 1589+ handler.type = namespaces.slice(0).sort().join(".");
 1590+
 1591+ // Get the current list of functions bound to this event
 1592+ var handlers = events[ type ],
 1593+ special = this.special[ type ] || {};
 1594+
 1595+
 1596+
 1597+ // Init the event handler queue
 1598+ if ( !handlers ) {
 1599+ handlers = events[ type ] = {};
 1600+
 1601+ // Check for a special event handler
 1602+ // Only use addEventListener/attachEvent if the special
 1603+ // events handler returns false
 1604+ if ( !special.setup || special.setup.call( elem, data, namespaces, handler) === false ) {
 1605+ // Bind the global event handler to the element
 1606+ if ( elem.addEventListener ) {
 1607+ elem.addEventListener( type, handle, false );
 1608+ } else if ( elem.attachEvent ) {
 1609+ elem.attachEvent( "on" + type, handle );
 1610+ }
 1611+ }
 1612+ }
 1613+
 1614+ if ( special.add ) {
 1615+ var modifiedHandler = special.add.call( elem, handler, data, namespaces, handlers );
 1616+ if ( modifiedHandler && jQuery.isFunction( modifiedHandler ) ) {
 1617+ modifiedHandler.guid = modifiedHandler.guid || handler.guid;
 1618+ handler = modifiedHandler;
 1619+ }
 1620+ }
 1621+
 1622+ // Add the function to the element's handler list
 1623+ handlers[ handler.guid ] = handler;
 1624+
 1625+ // Keep track of which events have been used, for global triggering
 1626+ this.global[ type ] = true;
 1627+ }
 1628+
 1629+ // Nullify elem to prevent memory leaks in IE
 1630+ elem = null;
 1631+ },
 1632+
 1633+ global: {},
 1634+
 1635+ // Detach an event or set of events from an element
 1636+ remove: function( elem, types, handler ) {
 1637+ // don't do events on text and comment nodes
 1638+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
 1639+ return;
 1640+ }
 1641+
 1642+ var events = jQuery.data( elem, "events" ), ret, type, fn;
 1643+
 1644+ if ( events ) {
 1645+ // Unbind all events for the element
 1646+ if ( types === undefined || (typeof types === "string" && types.charAt(0) === ".") ) {
 1647+ for ( type in events ) {
 1648+ this.remove( elem, type + (types || "") );
 1649+ }
 1650+ } else {
 1651+ // types is actually an event object here
 1652+ if ( types.type ) {
 1653+ handler = types.handler;
 1654+ types = types.type;
 1655+ }
 1656+
 1657+ // Handle multiple events separated by a space
 1658+ // jQuery(...).unbind("mouseover mouseout", fn);
 1659+ types = types.split(/\s+/);
 1660+ var i = 0;
 1661+ while ( (type = types[ i++ ]) ) {
 1662+ // Namespaced event handlers
 1663+ var namespaces = type.split(".");
 1664+ type = namespaces.shift();
 1665+ var all = !namespaces.length,
 1666+ cleaned = jQuery.map( namespaces.slice(0).sort(), fcleanup ),
 1667+ namespace = new RegExp("(^|\\.)" + cleaned.join("\\.(?:.*\\.)?") + "(\\.|$)"),
 1668+ special = this.special[ type ] || {};
 1669+
 1670+ if ( events[ type ] ) {
 1671+ // remove the given handler for the given type
 1672+ if ( handler ) {
 1673+ fn = events[ type ][ handler.guid ];
 1674+ delete events[ type ][ handler.guid ];
 1675+
 1676+ // remove all handlers for the given type
 1677+ } else {
 1678+ for ( var handle in events[ type ] ) {
 1679+ // Handle the removal of namespaced events
 1680+ if ( all || namespace.test( events[ type ][ handle ].type ) ) {
 1681+ delete events[ type ][ handle ];
 1682+ }
 1683+ }
 1684+ }
 1685+
 1686+ if ( special.remove ) {
 1687+ special.remove.call( elem, namespaces, fn);
 1688+ }
 1689+
 1690+ // remove generic event handler if no more handlers exist
 1691+ for ( ret in events[ type ] ) {
 1692+ break;
 1693+ }
 1694+ if ( !ret ) {
 1695+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
 1696+ if ( elem.removeEventListener ) {
 1697+ elem.removeEventListener( type, jQuery.data( elem, "handle" ), false );
 1698+ } else if ( elem.detachEvent ) {
 1699+ elem.detachEvent( "on" + type, jQuery.data( elem, "handle" ) );
 1700+ }
 1701+ }
 1702+ ret = null;
 1703+ delete events[ type ];
 1704+ }
 1705+ }
 1706+ }
 1707+ }
 1708+
 1709+ // Remove the expando if it's no longer used
 1710+ for ( ret in events ) {
 1711+ break;
 1712+ }
 1713+ if ( !ret ) {
 1714+ var handle = jQuery.data( elem, "handle" );
 1715+ if ( handle ) {
 1716+ handle.elem = null;
 1717+ }
 1718+ jQuery.removeData( elem, "events" );
 1719+ jQuery.removeData( elem, "handle" );
 1720+ }
 1721+ }
 1722+ },
 1723+
 1724+ // bubbling is internal
 1725+ trigger: function( event, data, elem /*, bubbling */ ) {
 1726+ // Event object or event type
 1727+ var type = event.type || event,
 1728+ bubbling = arguments[3];
 1729+
 1730+ if ( !bubbling ) {
 1731+ event = typeof event === "object" ?
 1732+ // jQuery.Event object
 1733+ event[expando] ? event :
 1734+ // Object literal
 1735+ jQuery.extend( jQuery.Event(type), event ) :
 1736+ // Just the event type (string)
 1737+ jQuery.Event(type);
 1738+
 1739+ if ( type.indexOf("!") >= 0 ) {
 1740+ event.type = type = type.slice(0, -1);
 1741+ event.exclusive = true;
 1742+ }
 1743+
 1744+ // Handle a global trigger
 1745+ if ( !elem ) {
 1746+ // Don't bubble custom events when global (to avoid too much overhead)
 1747+ event.stopPropagation();
 1748+
 1749+ // Only trigger if we've ever bound an event for it
 1750+ if ( this.global[ type ] ) {
 1751+ jQuery.each( jQuery.cache, function() {
 1752+ if ( this.events && this.events[type] ) {
 1753+ jQuery.event.trigger( event, data, this.handle.elem );
 1754+ }
 1755+ });
 1756+ }
 1757+ }
 1758+
 1759+ // Handle triggering a single element
 1760+
 1761+ // don't do events on text and comment nodes
 1762+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
 1763+ return undefined;
 1764+ }
 1765+
 1766+ // Clean up in case it is reused
 1767+ event.result = undefined;
 1768+ event.target = elem;
 1769+
 1770+ // Clone the incoming data, if any
 1771+ data = jQuery.makeArray( data );
 1772+ data.unshift( event );
 1773+ }
 1774+
 1775+ event.currentTarget = elem;
 1776+
 1777+ // Trigger the event, it is assumed that "handle" is a function
 1778+ var handle = jQuery.data( elem, "handle" );
 1779+ if ( handle ) {
 1780+ handle.apply( elem, data );
 1781+ }
 1782+
 1783+ var nativeFn, nativeHandler;
 1784+ try {
 1785+ if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
 1786+ nativeFn = elem[ type ];
 1787+ nativeHandler = elem[ "on" + type ];
 1788+ }
 1789+ // prevent IE from throwing an error for some elements with some event types, see #3533
 1790+ } catch (e) {}
 1791+
 1792+ var isClick = jQuery.nodeName(elem, "a") && type === "click";
 1793+
 1794+ // Trigger the native events (except for clicks on links)
 1795+ if ( !bubbling && nativeFn && !event.isDefaultPrevented() && !isClick ) {
 1796+ this.triggered = true;
 1797+ try {
 1798+ elem[ type ]();
 1799+ // prevent IE from throwing an error for some hidden elements
 1800+ } catch (e) {}
 1801+
 1802+ // Handle triggering native .onfoo handlers
 1803+ } else if ( nativeHandler && elem[ "on" + type ].apply( elem, data ) === false ) {
 1804+ event.result = false;
 1805+ }
 1806+
 1807+ this.triggered = false;
 1808+
 1809+ if ( !event.isPropagationStopped() ) {
 1810+ var parent = elem.parentNode || elem.ownerDocument;
 1811+ if ( parent ) {
 1812+ jQuery.event.trigger( event, data, parent, true );
 1813+ }
 1814+ }
 1815+ },
 1816+
 1817+ handle: function( event ) {
 1818+ // returned undefined or false
 1819+ var all, handlers;
 1820+
 1821+ event = arguments[0] = jQuery.event.fix( event || window.event );
 1822+ event.currentTarget = this;
 1823+
 1824+ // Namespaced event handlers
 1825+ var namespaces = event.type.split(".");
 1826+ event.type = namespaces.shift();
 1827+
 1828+ // Cache this now, all = true means, any handler
 1829+ all = !namespaces.length && !event.exclusive;
 1830+
 1831+ var namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
 1832+
 1833+ handlers = ( jQuery.data(this, "events") || {} )[ event.type ];
 1834+
 1835+ for ( var j in handlers ) {
 1836+ var handler = handlers[ j ];
 1837+
 1838+ // Filter the functions by class
 1839+ if ( all || namespace.test(handler.type) ) {
 1840+ // Pass in a reference to the handler function itself
 1841+ // So that we can later remove it
 1842+ event.handler = handler;
 1843+ event.data = handler.data;
 1844+
 1845+ var ret = handler.apply( this, arguments );
 1846+
 1847+ if ( ret !== undefined ) {
 1848+ event.result = ret;
 1849+ if ( ret === false ) {
 1850+ event.preventDefault();
 1851+ event.stopPropagation();
 1852+ }
 1853+ }
 1854+
 1855+ if ( event.isImmediatePropagationStopped() ) {
 1856+ break;
 1857+ }
 1858+
 1859+ }
 1860+ }
 1861+
 1862+ return event.result;
 1863+ },
 1864+
 1865+ props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
 1866+
 1867+ fix: function( event ) {
 1868+ if ( event[ expando ] ) {
 1869+ return event;
 1870+ }
 1871+
 1872+ // store a copy of the original event object
 1873+ // and "clone" to set read-only properties
 1874+ var originalEvent = event;
 1875+ event = jQuery.Event( originalEvent );
 1876+
 1877+ for ( var i = this.props.length, prop; i; ) {
 1878+ prop = this.props[ --i ];
 1879+ event[ prop ] = originalEvent[ prop ];
 1880+ }
 1881+
 1882+ // Fix target property, if necessary
 1883+ if ( !event.target ) {
 1884+ event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
 1885+ }
 1886+
 1887+ // check if target is a textnode (safari)
 1888+ if ( event.target.nodeType === 3 ) {
 1889+ event.target = event.target.parentNode;
 1890+ }
 1891+
 1892+ // Add relatedTarget, if necessary
 1893+ if ( !event.relatedTarget && event.fromElement ) {
 1894+ event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
 1895+ }
 1896+
 1897+ // Calculate pageX/Y if missing and clientX/Y available
 1898+ if ( event.pageX == null && event.clientX != null ) {
 1899+ var doc = document.documentElement, body = document.body;
 1900+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
 1901+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
 1902+ }
 1903+
 1904+ // Add which for key events
 1905+ if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
 1906+ event.which = event.charCode || event.keyCode;
 1907+ }
 1908+
 1909+ // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
 1910+ if ( !event.metaKey && event.ctrlKey ) {
 1911+ event.metaKey = event.ctrlKey;
 1912+ }
 1913+
 1914+ // Add which for click: 1 === left; 2 === middle; 3 === right
 1915+ // Note: button is not normalized, so don't use it
 1916+ if ( !event.which && event.button !== undefined ) {
 1917+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
 1918+ }
 1919+
 1920+ return event;
 1921+ },
 1922+
 1923+ // Deprecated, use jQuery.guid instead
 1924+ guid: 1E8,
 1925+
 1926+ // Deprecated, use jQuery.proxy instead
 1927+ proxy: jQuery.proxy,
 1928+
 1929+ special: {
 1930+ ready: {
 1931+ // Make sure the ready event is setup
 1932+ setup: jQuery.bindReady,
 1933+ teardown: jQuery.noop
 1934+ },
 1935+
 1936+ live: {
 1937+ add: function( proxy, data, namespaces, live ) {
 1938+ jQuery.extend( proxy, data || {} );
 1939+
 1940+ proxy.guid += data.selector + data.live;
 1941+ jQuery.event.add( this, data.live, liveHandler, data );
 1942+
 1943+ },
 1944+
 1945+ remove: function( namespaces ) {
 1946+ if ( namespaces.length ) {
 1947+ var remove = 0, name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");
 1948+
 1949+ jQuery.each( (jQuery.data(this, "events").live || {}), function() {
 1950+ if ( name.test(this.type) ) {
 1951+ remove++;
 1952+ }
 1953+ });
 1954+
 1955+ if ( remove < 1 ) {
 1956+ jQuery.event.remove( this, namespaces[0], liveHandler );
 1957+ }
 1958+ }
 1959+ },
 1960+ special: {}
 1961+ },
 1962+ beforeunload: {
 1963+ setup: function( data, namespaces, fn ) {
 1964+ // We only want to do this special case on windows
 1965+ if ( this.setInterval ) {
 1966+ this.onbeforeunload = fn;
 1967+ }
 1968+
 1969+ return false;
 1970+ },
 1971+ teardown: function( namespaces, fn ) {
 1972+ if ( this.onbeforeunload === fn ) {
 1973+ this.onbeforeunload = null;
 1974+ }
 1975+ }
 1976+ }
 1977+ }
 1978+};
 1979+
 1980+jQuery.Event = function( src ) {
 1981+ // Allow instantiation without the 'new' keyword
 1982+ if ( !this.preventDefault ) {
 1983+ return new jQuery.Event( src );
 1984+ }
 1985+
 1986+ // Event object
 1987+ if ( src && src.type ) {
 1988+ this.originalEvent = src;
 1989+ this.type = src.type;
 1990+ // Event type
 1991+ } else {
 1992+ this.type = src;
 1993+ }
 1994+
 1995+ // timeStamp is buggy for some events on Firefox(#3843)
 1996+ // So we won't rely on the native value
 1997+ this.timeStamp = now();
 1998+
 1999+ // Mark it as fixed
 2000+ this[ expando ] = true;
 2001+};
 2002+
 2003+function returnFalse() {
 2004+ return false;
 2005+}
 2006+function returnTrue() {
 2007+ return true;
 2008+}
 2009+
 2010+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
 2011+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
 2012+jQuery.Event.prototype = {
 2013+ preventDefault: function() {
 2014+ this.isDefaultPrevented = returnTrue;
 2015+
 2016+ var e = this.originalEvent;
 2017+ if ( !e ) {
 2018+ return;
 2019+ }
 2020+
 2021+ // if preventDefault exists run it on the original event
 2022+ if ( e.preventDefault ) {
 2023+ e.preventDefault();
 2024+ }
 2025+ // otherwise set the returnValue property of the original event to false (IE)
 2026+ e.returnValue = false;
 2027+ },
 2028+ stopPropagation: function() {
 2029+ this.isPropagationStopped = returnTrue;
 2030+
 2031+ var e = this.originalEvent;
 2032+ if ( !e ) {
 2033+ return;
 2034+ }
 2035+ // if stopPropagation exists run it on the original event
 2036+ if ( e.stopPropagation ) {
 2037+ e.stopPropagation();
 2038+ }
 2039+ // otherwise set the cancelBubble property of the original event to true (IE)
 2040+ e.cancelBubble = true;
 2041+ },
 2042+ stopImmediatePropagation: function() {
 2043+ this.isImmediatePropagationStopped = returnTrue;
 2044+ this.stopPropagation();
 2045+ },
 2046+ isDefaultPrevented: returnFalse,
 2047+ isPropagationStopped: returnFalse,
 2048+ isImmediatePropagationStopped: returnFalse
 2049+};
 2050+
 2051+// Checks if an event happened on an element within another element
 2052+// Used in jQuery.event.special.mouseenter and mouseleave handlers
 2053+var withinElement = function( event ) {
 2054+ // Check if mouse(over|out) are still within the same parent element
 2055+ var parent = event.relatedTarget;
 2056+
 2057+ // Traverse up the tree
 2058+ while ( parent && parent !== this ) {
 2059+ // Firefox sometimes assigns relatedTarget a XUL element
 2060+ // which we cannot access the parentNode property of
 2061+ try {
 2062+ parent = parent.parentNode;
 2063+
 2064+ // assuming we've left the element since we most likely mousedover a xul element
 2065+ } catch(e) {
 2066+ break;
 2067+ }
 2068+ }
 2069+
 2070+ if ( parent !== this ) {
 2071+ // set the correct event type
 2072+ event.type = event.data;
 2073+
 2074+ // handle event if we actually just moused on to a non sub-element
 2075+ jQuery.event.handle.apply( this, arguments );
 2076+ }
 2077+
 2078+},
 2079+
 2080+// In case of event delegation, we only need to rename the event.type,
 2081+// liveHandler will take care of the rest.
 2082+delegate = function( event ) {
 2083+ event.type = event.data;
 2084+ jQuery.event.handle.apply( this, arguments );
 2085+};
 2086+
 2087+// Create mouseenter and mouseleave events
 2088+jQuery.each({
 2089+ mouseenter: "mouseover",
 2090+ mouseleave: "mouseout"
 2091+}, function( orig, fix ) {
 2092+ jQuery.event.special[ orig ] = {
 2093+ setup: function( data ) {
 2094+ jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
 2095+ },
 2096+ teardown: function( data ) {
 2097+ jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
 2098+ }
 2099+ };
 2100+});
 2101+
 2102+// submit delegation
 2103+if ( !jQuery.support.submitBubbles ) {
 2104+
 2105+jQuery.event.special.submit = {
 2106+ setup: function( data, namespaces, fn ) {
 2107+ if ( this.nodeName.toLowerCase() !== "form" ) {
 2108+ jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) {
 2109+ var elem = e.target, type = elem.type;
 2110+
 2111+ if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
 2112+ return trigger( "submit", this, arguments );
 2113+ }
 2114+ });
 2115+
 2116+ jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) {
 2117+ var elem = e.target, type = elem.type;
 2118+
 2119+ if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
 2120+ return trigger( "submit", this, arguments );
 2121+ }
 2122+ });
 2123+
 2124+ } else {
 2125+ return false;
 2126+ }
 2127+ },
 2128+
 2129+ remove: function( namespaces, fn ) {
 2130+ jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") );
 2131+ jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") );
 2132+ }
 2133+};
 2134+
 2135+}
 2136+
 2137+// change delegation, happens here so we have bind.
 2138+if ( !jQuery.support.changeBubbles ) {
 2139+
 2140+var formElems = /textarea|input|select/i;
 2141+
 2142+function getVal( elem ) {
 2143+ var type = elem.type, val = elem.value;
 2144+
 2145+ if ( type === "radio" || type === "checkbox" ) {
 2146+ val = elem.checked;
 2147+
 2148+ } else if ( type === "select-multiple" ) {
 2149+ val = elem.selectedIndex > -1 ?
 2150+ jQuery.map( elem.options, function( elem ) {
 2151+ return elem.selected;
 2152+ }).join("-") :
 2153+ "";
 2154+
 2155+ } else if ( elem.nodeName.toLowerCase() === "select" ) {
 2156+ val = elem.selectedIndex;
 2157+ }
 2158+
 2159+ return val;
 2160+}
 2161+
 2162+function testChange( e ) {
 2163+ var elem = e.target, data, val;
 2164+
 2165+ if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
 2166+ return;
 2167+ }
 2168+
 2169+ data = jQuery.data( elem, "_change_data" );
 2170+ val = getVal(elem);
 2171+
 2172+ if ( val === data ) {
 2173+ return;
 2174+ }
 2175+
 2176+ // the current data will be also retrieved by beforeactivate
 2177+ if ( e.type !== "focusout" || elem.type !== "radio" ) {
 2178+ jQuery.data( elem, "_change_data", val );
 2179+ }
 2180+
 2181+ if ( elem.type !== "select" && (data != null || val) ) {
 2182+ e.type = "change";
 2183+ return jQuery.event.trigger( e, arguments[1], this );
 2184+ }
 2185+}
 2186+
 2187+jQuery.event.special.change = {
 2188+ filters: {
 2189+ focusout: testChange,
 2190+
 2191+ click: function( e ) {
 2192+ var elem = e.target, type = elem.type;
 2193+
 2194+ if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
 2195+ return testChange.call( this, e );
 2196+ }
 2197+ },
 2198+
 2199+ // Change has to be called before submit
 2200+ // Keydown will be called before keypress, which is used in submit-event delegation
 2201+ keydown: function( e ) {
 2202+ var elem = e.target, type = elem.type;
 2203+
 2204+ if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
 2205+ (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
 2206+ type === "select-multiple" ) {
 2207+ return testChange.call( this, e );
 2208+ }
 2209+ },
 2210+
 2211+ // Beforeactivate happens also before the previous element is blurred
 2212+ // with this event you can't trigger a change event, but you can store
 2213+ // information/focus[in] is not needed anymore
 2214+ beforeactivate: function( e ) {
 2215+ var elem = e.target;
 2216+
 2217+ if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) {
 2218+ jQuery.data( elem, "_change_data", getVal(elem) );
 2219+ }
 2220+ }
 2221+ },
 2222+ setup: function( data, namespaces, fn ) {
 2223+ for ( var type in changeFilters ) {
 2224+ jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
 2225+ }
 2226+
 2227+ return formElems.test( this.nodeName );
 2228+ },
 2229+ remove: function( namespaces, fn ) {
 2230+ for ( var type in changeFilters ) {
 2231+ jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
 2232+ }
 2233+
 2234+ return formElems.test( this.nodeName );
 2235+ }
 2236+};
 2237+
 2238+var changeFilters = jQuery.event.special.change.filters;
 2239+
 2240+}
 2241+
 2242+function trigger( type, elem, args ) {
 2243+ args[0].type = type;
 2244+ return jQuery.event.handle.apply( elem, args );
 2245+}
 2246+
 2247+// Create "bubbling" focus and blur events
 2248+if ( document.addEventListener ) {
 2249+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
 2250+ jQuery.event.special[ fix ] = {
 2251+ setup: function() {
 2252+ this.addEventListener( orig, handler, true );
 2253+ },
 2254+ teardown: function() {
 2255+ this.removeEventListener( orig, handler, true );
 2256+ }
 2257+ };
 2258+
 2259+ function handler( e ) {
 2260+ e = jQuery.event.fix( e );
 2261+ e.type = fix;
 2262+ return jQuery.event.handle.call( this, e );
 2263+ }
 2264+ });
 2265+}
 2266+
 2267+jQuery.each(["bind", "one"], function( i, name ) {
 2268+ jQuery.fn[ name ] = function( type, data, fn ) {
 2269+ // Handle object literals
 2270+ if ( typeof type === "object" ) {
 2271+ for ( var key in type ) {
 2272+ this[ name ](key, data, type[key], fn);
 2273+ }
 2274+ return this;
 2275+ }
 2276+
 2277+ if ( jQuery.isFunction( data ) ) {
 2278+ thisObject = fn;
 2279+ fn = data;
 2280+ data = undefined;
 2281+ }
 2282+
 2283+ var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
 2284+ jQuery( this ).unbind( event, handler );
 2285+ return fn.apply( this, arguments );
 2286+ }) : fn;
 2287+
 2288+ return type === "unload" && name !== "one" ?
 2289+ this.one( type, data, fn, thisObject ) :
 2290+ this.each(function() {
 2291+ jQuery.event.add( this, type, handler, data );
 2292+ });
 2293+ };
 2294+});
 2295+
 2296+jQuery.fn.extend({
 2297+ unbind: function( type, fn ) {
 2298+ // Handle object literals
 2299+ if ( typeof type === "object" && !type.preventDefault ) {
 2300+ for ( var key in type ) {
 2301+ this.unbind(key, type[key]);
 2302+ }
 2303+ return this;
 2304+ }
 2305+
 2306+ return this.each(function() {
 2307+ jQuery.event.remove( this, type, fn );
 2308+ });
 2309+ },
 2310+ trigger: function( type, data ) {
 2311+ return this.each(function() {
 2312+ jQuery.event.trigger( type, data, this );
 2313+ });
 2314+ },
 2315+
 2316+ triggerHandler: function( type, data ) {
 2317+ if ( this[0] ) {
 2318+ var event = jQuery.Event( type );
 2319+ event.preventDefault();
 2320+ event.stopPropagation();
 2321+ jQuery.event.trigger( event, data, this[0] );
 2322+ return event.result;
 2323+ }
 2324+ },
 2325+
 2326+ toggle: function( fn ) {
 2327+ // Save reference to arguments for access in closure
 2328+ var args = arguments, i = 1;
 2329+
 2330+ // link all the functions, so any of them can unbind this click handler
 2331+ while ( i < args.length ) {
 2332+ jQuery.proxy( fn, args[ i++ ] );
 2333+ }
 2334+
 2335+ return this.click( jQuery.proxy( fn, function( event ) {
 2336+ // Figure out which function to execute
 2337+ var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
 2338+ jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
 2339+
 2340+ // Make sure that clicks stop
 2341+ event.preventDefault();
 2342+
 2343+ // and execute the function
 2344+ return args[ lastToggle ].apply( this, arguments ) || false;
 2345+ }));
 2346+ },
 2347+
 2348+ hover: function( fnOver, fnOut ) {
 2349+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
 2350+ },
 2351+
 2352+ live: function( type, data, fn ) {
 2353+ if ( jQuery.isFunction( data ) ) {
 2354+ fn = data;
 2355+ data = undefined;
 2356+ }
 2357+
 2358+ jQuery( this.context ).bind( liveConvert( type, this.selector ), {
 2359+ data: data, selector: this.selector, live: type
 2360+ }, fn );
 2361+
 2362+ return this;
 2363+ },
 2364+
 2365+ die: function( type, fn ) {
 2366+ jQuery( this.context ).unbind( liveConvert( type, this.selector ), fn ? { guid: fn.guid + this.selector + type } : null );
 2367+ return this;
 2368+ }
 2369+});
 2370+
 2371+function liveHandler( event ) {
 2372+ var stop = true, elems = [], selectors = [], args = arguments,
 2373+ related, match, fn, elem, j, i, data,
 2374+ live = jQuery.extend({}, jQuery.data( this, "events" ).live);
 2375+
 2376+ for ( j in live ) {
 2377+ fn = live[j];
 2378+ if ( fn.live === event.type ||
 2379+ fn.altLive && jQuery.inArray(event.type, fn.altLive) > -1 ) {
 2380+
 2381+ data = fn.data;
 2382+ if ( !(data.beforeFilter && data.beforeFilter[event.type] &&
 2383+ !data.beforeFilter[event.type](event)) ) {
 2384+ selectors.push( fn.selector );
 2385+ }
 2386+ } else {
 2387+ delete live[j];
 2388+ }
 2389+ }
 2390+
 2391+ match = jQuery( event.target ).closest( selectors, event.currentTarget );
 2392+
 2393+ for ( i = 0, l = match.length; i < l; i++ ) {
 2394+ for ( j in live ) {
 2395+ fn = live[j];
 2396+ elem = match[i].elem;
 2397+ related = null;
 2398+
 2399+ if ( match[i].selector === fn.selector ) {
 2400+ // Those two events require additional checking
 2401+ if ( fn.live === "mouseenter" || fn.live === "mouseleave" ) {
 2402+ related = jQuery( event.relatedTarget ).closest( fn.selector )[0];
 2403+ }
 2404+
 2405+ if ( !related || related !== elem ) {
 2406+ elems.push({ elem: elem, fn: fn });
 2407+ }
 2408+ }
 2409+ }
 2410+ }
 2411+
 2412+ for ( i = 0, l = elems.length; i < l; i++ ) {
 2413+ match = elems[i];
 2414+ event.currentTarget = match.elem;
 2415+ event.data = match.fn.data;
 2416+ if ( match.fn.apply( match.elem, args ) === false ) {
 2417+ stop = false;
 2418+ break;
 2419+ }
 2420+ }
 2421+
 2422+ return stop;
 2423+}
 2424+
 2425+function liveConvert( type, selector ) {
 2426+ return ["live", type, selector.replace(/\./g, "`").replace(/ /g, "&")].join(".");
 2427+}
 2428+
 2429+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
 2430+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
 2431+ "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
 2432+
 2433+ // Handle event binding
 2434+ jQuery.fn[ name ] = function( fn ) {
 2435+ return fn ? this.bind( name, fn ) : this.trigger( name );
 2436+ };
 2437+
 2438+ if ( jQuery.attrFn ) {
 2439+ jQuery.attrFn[ name ] = true;
 2440+ }
 2441+});
 2442+
 2443+// Prevent memory leaks in IE
 2444+// Window isn't included so as not to unbind existing unload events
 2445+// More info:
 2446+// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
 2447+if ( window.attachEvent && !window.addEventListener ) {
 2448+ window.attachEvent("onunload", function() {
 2449+ for ( var id in jQuery.cache ) {
 2450+ if ( jQuery.cache[ id ].handle ) {
 2451+ // Try/Catch is to handle iframes being unloaded, see #4280
 2452+ try {
 2453+ jQuery.event.remove( jQuery.cache[ id ].handle.elem );
 2454+ } catch(e) {}
 2455+ }
 2456+ }
 2457+ });
 2458+}
 2459+/*!
 2460+ * Sizzle CSS Selector Engine - v1.0
 2461+ * Copyright 2009, The Dojo Foundation
 2462+ * Released under the MIT, BSD, and GPL Licenses.
 2463+ * More information: http://sizzlejs.com/
 2464+ */
 2465+(function(){
 2466+
 2467+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
 2468+ done = 0,
 2469+ toString = Object.prototype.toString,
 2470+ hasDuplicate = false,
 2471+ baseHasDuplicate = true;
 2472+
 2473+// Here we check if the JavaScript engine is using some sort of
 2474+// optimization where it does not always call our comparision
 2475+// function. If that is the case, discard the hasDuplicate value.
 2476+// Thus far that includes Google Chrome.
 2477+[0, 0].sort(function(){
 2478+ baseHasDuplicate = false;
 2479+ return 0;
 2480+});
 2481+
 2482+var Sizzle = function(selector, context, results, seed) {
 2483+ results = results || [];
 2484+ var origContext = context = context || document;
 2485+
 2486+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
 2487+ return [];
 2488+ }
 2489+
 2490+ if ( !selector || typeof selector !== "string" ) {
 2491+ return results;
 2492+ }
 2493+
 2494+ var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
 2495+ soFar = selector;
 2496+
 2497+ // Reset the position of the chunker regexp (start from head)
 2498+ while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
 2499+ soFar = m[3];
 2500+
 2501+ parts.push( m[1] );
 2502+
 2503+ if ( m[2] ) {
 2504+ extra = m[3];
 2505+ break;
 2506+ }
 2507+ }
 2508+
 2509+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
 2510+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
 2511+ set = posProcess( parts[0] + parts[1], context );
 2512+ } else {
 2513+ set = Expr.relative[ parts[0] ] ?
 2514+ [ context ] :
 2515+ Sizzle( parts.shift(), context );
 2516+
 2517+ while ( parts.length ) {
 2518+ selector = parts.shift();
 2519+
 2520+ if ( Expr.relative[ selector ] ) {
 2521+ selector += parts.shift();
 2522+ }
 2523+
 2524+ set = posProcess( selector, set );
 2525+ }
 2526+ }
 2527+ } else {
 2528+ // Take a shortcut and set the context if the root selector is an ID
 2529+ // (but not if it'll be faster if the inner selector is an ID)
 2530+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
 2531+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
 2532+ var ret = Sizzle.find( parts.shift(), context, contextXML );
 2533+ context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
 2534+ }
 2535+
 2536+ if ( context ) {
 2537+ var ret = seed ?
 2538+ { expr: parts.pop(), set: makeArray(seed) } :
 2539+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
 2540+ set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
 2541+
 2542+ if ( parts.length > 0 ) {
 2543+ checkSet = makeArray(set);
 2544+ } else {
 2545+ prune = false;
 2546+ }
 2547+
 2548+ while ( parts.length ) {
 2549+ var cur = parts.pop(), pop = cur;
 2550+
 2551+ if ( !Expr.relative[ cur ] ) {
 2552+ cur = "";
 2553+ } else {
 2554+ pop = parts.pop();
 2555+ }
 2556+
 2557+ if ( pop == null ) {
 2558+ pop = context;
 2559+ }
 2560+
 2561+ Expr.relative[ cur ]( checkSet, pop, contextXML );
 2562+ }
 2563+ } else {
 2564+ checkSet = parts = [];
 2565+ }
 2566+ }
 2567+
 2568+ if ( !checkSet ) {
 2569+ checkSet = set;
 2570+ }
 2571+
 2572+ if ( !checkSet ) {
 2573+ throw "Syntax error, unrecognized expression: " + (cur || selector);
 2574+ }
 2575+
 2576+ if ( toString.call(checkSet) === "[object Array]" ) {
 2577+ if ( !prune ) {
 2578+ results.push.apply( results, checkSet );
 2579+ } else if ( context && context.nodeType === 1 ) {
 2580+ for ( var i = 0; checkSet[i] != null; i++ ) {
 2581+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
 2582+ results.push( set[i] );
 2583+ }
 2584+ }
 2585+ } else {
 2586+ for ( var i = 0; checkSet[i] != null; i++ ) {
 2587+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
 2588+ results.push( set[i] );
 2589+ }
 2590+ }
 2591+ }
 2592+ } else {
 2593+ makeArray( checkSet, results );
 2594+ }
 2595+
 2596+ if ( extra ) {
 2597+ Sizzle( extra, origContext, results, seed );
 2598+ Sizzle.uniqueSort( results );
 2599+ }
 2600+
 2601+ return results;
 2602+};
 2603+
 2604+Sizzle.uniqueSort = function(results){
 2605+ if ( sortOrder ) {
 2606+ hasDuplicate = baseHasDuplicate;
 2607+ results.sort(sortOrder);
 2608+
 2609+ if ( hasDuplicate ) {
 2610+ for ( var i = 1; i < results.length; i++ ) {
 2611+ if ( results[i] === results[i-1] ) {
 2612+ results.splice(i--, 1);
 2613+ }
 2614+ }
 2615+ }
 2616+ }
 2617+
 2618+ return results;
 2619+};
 2620+
 2621+Sizzle.matches = function(expr, set){
 2622+ return Sizzle(expr, null, null, set);
 2623+};
 2624+
 2625+Sizzle.find = function(expr, context, isXML){
 2626+ var set, match;
 2627+
 2628+ if ( !expr ) {
 2629+ return [];
 2630+ }
 2631+
 2632+ for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
 2633+ var type = Expr.order[i], match;
 2634+
 2635+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
 2636+ var left = match[1];
 2637+ match.splice(1,1);
 2638+
 2639+ if ( left.substr( left.length - 1 ) !== "\\" ) {
 2640+ match[1] = (match[1] || "").replace(/\\/g, "");
 2641+ set = Expr.find[ type ]( match, context, isXML );
 2642+ if ( set != null ) {
 2643+ expr = expr.replace( Expr.match[ type ], "" );
 2644+ break;
 2645+ }
 2646+ }
 2647+ }
 2648+ }
 2649+
 2650+ if ( !set ) {
 2651+ set = context.getElementsByTagName("*");
 2652+ }
 2653+
 2654+ return {set: set, expr: expr};
 2655+};
 2656+
 2657+Sizzle.filter = function(expr, set, inplace, not){
 2658+ var old = expr, result = [], curLoop = set, match, anyFound,
 2659+ isXMLFilter = set && set[0] && isXML(set[0]);
 2660+
 2661+ while ( expr && set.length ) {
 2662+ for ( var type in Expr.filter ) {
 2663+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
 2664+ var filter = Expr.filter[ type ], found, item, left = match[1];
 2665+ anyFound = false;
 2666+
 2667+ match.splice(1,1);
 2668+
 2669+ if ( left.substr( left.length - 1 ) === "\\" ) {
 2670+ continue;
 2671+ }
 2672+
 2673+ if ( curLoop === result ) {
 2674+ result = [];
 2675+ }
 2676+
 2677+ if ( Expr.preFilter[ type ] ) {
 2678+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
 2679+
 2680+ if ( !match ) {
 2681+ anyFound = found = true;
 2682+ } else if ( match === true ) {
 2683+ continue;
 2684+ }
 2685+ }
 2686+
 2687+ if ( match ) {
 2688+ for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
 2689+ if ( item ) {
 2690+ found = filter( item, match, i, curLoop );
 2691+ var pass = not ^ !!found;
 2692+
 2693+ if ( inplace && found != null ) {
 2694+ if ( pass ) {
 2695+ anyFound = true;
 2696+ } else {
 2697+ curLoop[i] = false;
 2698+ }
 2699+ } else if ( pass ) {
 2700+ result.push( item );
 2701+ anyFound = true;
 2702+ }
 2703+ }
 2704+ }
 2705+ }
 2706+
 2707+ if ( found !== undefined ) {
 2708+ if ( !inplace ) {
 2709+ curLoop = result;
 2710+ }
 2711+
 2712+ expr = expr.replace( Expr.match[ type ], "" );
 2713+
 2714+ if ( !anyFound ) {
 2715+ return [];
 2716+ }
 2717+
 2718+ break;
 2719+ }
 2720+ }
 2721+ }
 2722+
 2723+ // Improper expression
 2724+ if ( expr === old ) {
 2725+ if ( anyFound == null ) {
 2726+ throw "Syntax error, unrecognized expression: " + expr;
 2727+ } else {
 2728+ break;
 2729+ }
 2730+ }
 2731+
 2732+ old = expr;
 2733+ }
 2734+
 2735+ return curLoop;
 2736+};
 2737+
 2738+var Expr = Sizzle.selectors = {
 2739+ order: [ "ID", "NAME", "TAG" ],
 2740+ match: {
 2741+ ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
 2742+ CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
 2743+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
 2744+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
 2745+ TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
 2746+ CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
 2747+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
 2748+ PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
 2749+ },
 2750+ leftMatch: {},
 2751+ attrMap: {
 2752+ "class": "className",
 2753+ "for": "htmlFor"
 2754+ },
 2755+ attrHandle: {
 2756+ href: function(elem){
 2757+ return elem.getAttribute("href");
 2758+ }
 2759+ },
 2760+ relative: {
 2761+ "+": function(checkSet, part){
 2762+ var isPartStr = typeof part === "string",
 2763+ isTag = isPartStr && !/\W/.test(part),
 2764+ isPartStrNotTag = isPartStr && !isTag;
 2765+
 2766+ if ( isTag ) {
 2767+ part = part.toLowerCase();
 2768+ }
 2769+
 2770+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
 2771+ if ( (elem = checkSet[i]) ) {
 2772+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
 2773+
 2774+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
 2775+ elem || false :
 2776+ elem === part;
 2777+ }
 2778+ }
 2779+
 2780+ if ( isPartStrNotTag ) {
 2781+ Sizzle.filter( part, checkSet, true );
 2782+ }
 2783+ },
 2784+ ">": function(checkSet, part){
 2785+ var isPartStr = typeof part === "string";
 2786+
 2787+ if ( isPartStr && !/\W/.test(part) ) {
 2788+ part = part.toLowerCase();
 2789+
 2790+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 2791+ var elem = checkSet[i];
 2792+ if ( elem ) {
 2793+ var parent = elem.parentNode;
 2794+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
 2795+ }
 2796+ }
 2797+ } else {
 2798+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 2799+ var elem = checkSet[i];
 2800+ if ( elem ) {
 2801+ checkSet[i] = isPartStr ?
 2802+ elem.parentNode :
 2803+ elem.parentNode === part;
 2804+ }
 2805+ }
 2806+
 2807+ if ( isPartStr ) {
 2808+ Sizzle.filter( part, checkSet, true );
 2809+ }
 2810+ }
 2811+ },
 2812+ "": function(checkSet, part, isXML){
 2813+ var doneName = done++, checkFn = dirCheck;
 2814+
 2815+ if ( typeof part === "string" && !/\W/.test(part) ) {
 2816+ var nodeCheck = part = part.toLowerCase();
 2817+ checkFn = dirNodeCheck;
 2818+ }
 2819+
 2820+ checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
 2821+ },
 2822+ "~": function(checkSet, part, isXML){
 2823+ var doneName = done++, checkFn = dirCheck;
 2824+
 2825+ if ( typeof part === "string" && !/\W/.test(part) ) {
 2826+ var nodeCheck = part = part.toLowerCase();
 2827+ checkFn = dirNodeCheck;
 2828+ }
 2829+
 2830+ checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
 2831+ }
 2832+ },
 2833+ find: {
 2834+ ID: function(match, context, isXML){
 2835+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
 2836+ var m = context.getElementById(match[1]);
 2837+ return m ? [m] : [];
 2838+ }
 2839+ },
 2840+ NAME: function(match, context){
 2841+ if ( typeof context.getElementsByName !== "undefined" ) {
 2842+ var ret = [], results = context.getElementsByName(match[1]);
 2843+
 2844+ for ( var i = 0, l = results.length; i < l; i++ ) {
 2845+ if ( results[i].getAttribute("name") === match[1] ) {
 2846+ ret.push( results[i] );
 2847+ }
 2848+ }
 2849+
 2850+ return ret.length === 0 ? null : ret;
 2851+ }
 2852+ },
 2853+ TAG: function(match, context){
 2854+ return context.getElementsByTagName(match[1]);
 2855+ }
 2856+ },
 2857+ preFilter: {
 2858+ CLASS: function(match, curLoop, inplace, result, not, isXML){
 2859+ match = " " + match[1].replace(/\\/g, "") + " ";
 2860+
 2861+ if ( isXML ) {
 2862+ return match;
 2863+ }
 2864+
 2865+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
 2866+ if ( elem ) {
 2867+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
 2868+ if ( !inplace ) {
 2869+ result.push( elem );
 2870+ }
 2871+ } else if ( inplace ) {
 2872+ curLoop[i] = false;
 2873+ }
 2874+ }
 2875+ }
 2876+
 2877+ return false;
 2878+ },
 2879+ ID: function(match){
 2880+ return match[1].replace(/\\/g, "");
 2881+ },
 2882+ TAG: function(match, curLoop){
 2883+ return match[1].toLowerCase();
 2884+ },
 2885+ CHILD: function(match){
 2886+ if ( match[1] === "nth" ) {
 2887+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
 2888+ var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
 2889+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
 2890+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
 2891+
 2892+ // calculate the numbers (first)n+(last) including if they are negative
 2893+ match[2] = (test[1] + (test[2] || 1)) - 0;
 2894+ match[3] = test[3] - 0;
 2895+ }
 2896+
 2897+ // TODO: Move to normal caching system
 2898+ match[0] = done++;
 2899+
 2900+ return match;
 2901+ },
 2902+ ATTR: function(match, curLoop, inplace, result, not, isXML){
 2903+ var name = match[1].replace(/\\/g, "");
 2904+
 2905+ if ( !isXML && Expr.attrMap[name] ) {
 2906+ match[1] = Expr.attrMap[name];
 2907+ }
 2908+
 2909+ if ( match[2] === "~=" ) {
 2910+ match[4] = " " + match[4] + " ";
 2911+ }
 2912+
 2913+ return match;
 2914+ },
 2915+ PSEUDO: function(match, curLoop, inplace, result, not){
 2916+ if ( match[1] === "not" ) {
 2917+ // If we're dealing with a complex expression, or a simple one
 2918+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
 2919+ match[3] = Sizzle(match[3], null, null, curLoop);
 2920+ } else {
 2921+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
 2922+ if ( !inplace ) {
 2923+ result.push.apply( result, ret );
 2924+ }
 2925+ return false;
 2926+ }
 2927+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
 2928+ return true;
 2929+ }
 2930+
 2931+ return match;
 2932+ },
 2933+ POS: function(match){
 2934+ match.unshift( true );
 2935+ return match;
 2936+ }
 2937+ },
 2938+ filters: {
 2939+ enabled: function(elem){
 2940+ return elem.disabled === false && elem.type !== "hidden";
 2941+ },
 2942+ disabled: function(elem){
 2943+ return elem.disabled === true;
 2944+ },
 2945+ checked: function(elem){
 2946+ return elem.checked === true;
 2947+ },
 2948+ selected: function(elem){
 2949+ // Accessing this property makes selected-by-default
 2950+ // options in Safari work properly
 2951+ elem.parentNode.selectedIndex;
 2952+ return elem.selected === true;
 2953+ },
 2954+ parent: function(elem){
 2955+ return !!elem.firstChild;
 2956+ },
 2957+ empty: function(elem){
 2958+ return !elem.firstChild;
 2959+ },
 2960+ has: function(elem, i, match){
 2961+ return !!Sizzle( match[3], elem ).length;
 2962+ },
 2963+ header: function(elem){
 2964+ return /h\d/i.test( elem.nodeName );
 2965+ },
 2966+ text: function(elem){
 2967+ return "text" === elem.type;
 2968+ },
 2969+ radio: function(elem){
 2970+ return "radio" === elem.type;
 2971+ },
 2972+ checkbox: function(elem){
 2973+ return "checkbox" === elem.type;
 2974+ },
 2975+ file: function(elem){
 2976+ return "file" === elem.type;
 2977+ },
 2978+ password: function(elem){
 2979+ return "password" === elem.type;
 2980+ },
 2981+ submit: function(elem){
 2982+ return "submit" === elem.type;
 2983+ },
 2984+ image: function(elem){
 2985+ return "image" === elem.type;
 2986+ },
 2987+ reset: function(elem){
 2988+ return "reset" === elem.type;
 2989+ },
 2990+ button: function(elem){
 2991+ return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
 2992+ },
 2993+ input: function(elem){
 2994+ return /input|select|textarea|button/i.test(elem.nodeName);
 2995+ }
 2996+ },
 2997+ setFilters: {
 2998+ first: function(elem, i){
 2999+ return i === 0;
 3000+ },
 3001+ last: function(elem, i, match, array){
 3002+ return i === array.length - 1;
 3003+ },
 3004+ even: function(elem, i){
 3005+ return i % 2 === 0;
 3006+ },
 3007+ odd: function(elem, i){
 3008+ return i % 2 === 1;
 3009+ },
 3010+ lt: function(elem, i, match){
 3011+ return i < match[3] - 0;
 3012+ },
 3013+ gt: function(elem, i, match){
 3014+ return i > match[3] - 0;
 3015+ },
 3016+ nth: function(elem, i, match){
 3017+ return match[3] - 0 === i;
 3018+ },
 3019+ eq: function(elem, i, match){
 3020+ return match[3] - 0 === i;
 3021+ }
 3022+ },
 3023+ filter: {
 3024+ PSEUDO: function(elem, match, i, array){
 3025+ var name = match[1], filter = Expr.filters[ name ];
 3026+
 3027+ if ( filter ) {
 3028+ return filter( elem, i, match, array );
 3029+ } else if ( name === "contains" ) {
 3030+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
 3031+ } else if ( name === "not" ) {
 3032+ var not = match[3];
 3033+
 3034+ for ( var i = 0, l = not.length; i < l; i++ ) {
 3035+ if ( not[i] === elem ) {
 3036+ return false;
 3037+ }
 3038+ }
 3039+
 3040+ return true;
 3041+ } else {
 3042+ throw "Syntax error, unrecognized expression: " + name;
 3043+ }
 3044+ },
 3045+ CHILD: function(elem, match){
 3046+ var type = match[1], node = elem;
 3047+ switch (type) {
 3048+ case 'only':
 3049+ case 'first':
 3050+ while ( (node = node.previousSibling) ) {
 3051+ if ( node.nodeType === 1 ) {
 3052+ return false;
 3053+ }
 3054+ }
 3055+ if ( type === "first" ) {
 3056+ return true;
 3057+ }
 3058+ node = elem;
 3059+ case 'last':
 3060+ while ( (node = node.nextSibling) ) {
 3061+ if ( node.nodeType === 1 ) {
 3062+ return false;
 3063+ }
 3064+ }
 3065+ return true;
 3066+ case 'nth':
 3067+ var first = match[2], last = match[3];
 3068+
 3069+ if ( first === 1 && last === 0 ) {
 3070+ return true;
 3071+ }
 3072+
 3073+ var doneName = match[0],
 3074+ parent = elem.parentNode;
 3075+
 3076+ if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
 3077+ var count = 0;
 3078+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
 3079+ if ( node.nodeType === 1 ) {
 3080+ node.nodeIndex = ++count;
 3081+ }
 3082+ }
 3083+ parent.sizcache = doneName;
 3084+ }
 3085+
 3086+ var diff = elem.nodeIndex - last;
 3087+ if ( first === 0 ) {
 3088+ return diff === 0;
 3089+ } else {
 3090+ return ( diff % first === 0 && diff / first >= 0 );
 3091+ }
 3092+ }
 3093+ },
 3094+ ID: function(elem, match){
 3095+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
 3096+ },
 3097+ TAG: function(elem, match){
 3098+ return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
 3099+ },
 3100+ CLASS: function(elem, match){
 3101+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
 3102+ .indexOf( match ) > -1;
 3103+ },
 3104+ ATTR: function(elem, match){
 3105+ var name = match[1],
 3106+ result = Expr.attrHandle[ name ] ?
 3107+ Expr.attrHandle[ name ]( elem ) :
 3108+ elem[ name ] != null ?
 3109+ elem[ name ] :
 3110+ elem.getAttribute( name ),
 3111+ value = result + "",
 3112+ type = match[2],
 3113+ check = match[4];
 3114+
 3115+ return result == null ?
 3116+ type === "!=" :
 3117+ type === "=" ?
 3118+ value === check :
 3119+ type === "*=" ?
 3120+ value.indexOf(check) >= 0 :
 3121+ type === "~=" ?
 3122+ (" " + value + " ").indexOf(check) >= 0 :
 3123+ !check ?
 3124+ value && result !== false :
 3125+ type === "!=" ?
 3126+ value !== check :
 3127+ type === "^=" ?
 3128+ value.indexOf(check) === 0 :
 3129+ type === "$=" ?
 3130+ value.substr(value.length - check.length) === check :
 3131+ type === "|=" ?
 3132+ value === check || value.substr(0, check.length + 1) === check + "-" :
 3133+ false;
 3134+ },
 3135+ POS: function(elem, match, i, array){
 3136+ var name = match[2], filter = Expr.setFilters[ name ];
 3137+
 3138+ if ( filter ) {
 3139+ return filter( elem, i, match, array );
 3140+ }
 3141+ }
 3142+ }
 3143+};
 3144+
 3145+var origPOS = Expr.match.POS;
 3146+
 3147+for ( var type in Expr.match ) {
 3148+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
 3149+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
 3150+ return "\\" + (num - 0 + 1);
 3151+ }));
 3152+}
 3153+
 3154+var makeArray = function(array, results) {
 3155+ array = Array.prototype.slice.call( array, 0 );
 3156+
 3157+ if ( results ) {
 3158+ results.push.apply( results, array );
 3159+ return results;
 3160+ }
 3161+
 3162+ return array;
 3163+};
 3164+
 3165+// Perform a simple check to determine if the browser is capable of
 3166+// converting a NodeList to an array using builtin methods.
 3167+try {
 3168+ Array.prototype.slice.call( document.documentElement.childNodes, 0 );
 3169+
 3170+// Provide a fallback method if it does not work
 3171+} catch(e){
 3172+ makeArray = function(array, results) {
 3173+ var ret = results || [];
 3174+
 3175+ if ( toString.call(array) === "[object Array]" ) {
 3176+ Array.prototype.push.apply( ret, array );
 3177+ } else {
 3178+ if ( typeof array.length === "number" ) {
 3179+ for ( var i = 0, l = array.length; i < l; i++ ) {
 3180+ ret.push( array[i] );
 3181+ }
 3182+ } else {
 3183+ for ( var i = 0; array[i]; i++ ) {
 3184+ ret.push( array[i] );
 3185+ }
 3186+ }
 3187+ }
 3188+
 3189+ return ret;
 3190+ };
 3191+}
 3192+
 3193+var sortOrder;
 3194+
 3195+if ( document.documentElement.compareDocumentPosition ) {
 3196+ sortOrder = function( a, b ) {
 3197+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
 3198+ if ( a == b ) {
 3199+ hasDuplicate = true;
 3200+ }
 3201+ return a.compareDocumentPosition ? -1 : 1;
 3202+ }
 3203+
 3204+ var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
 3205+ if ( ret === 0 ) {
 3206+ hasDuplicate = true;
 3207+ }
 3208+ return ret;
 3209+ };
 3210+} else if ( "sourceIndex" in document.documentElement ) {
 3211+ sortOrder = function( a, b ) {
 3212+ if ( !a.sourceIndex || !b.sourceIndex ) {
 3213+ if ( a == b ) {
 3214+ hasDuplicate = true;
 3215+ }
 3216+ return a.sourceIndex ? -1 : 1;
 3217+ }
 3218+
 3219+ var ret = a.sourceIndex - b.sourceIndex;
 3220+ if ( ret === 0 ) {
 3221+ hasDuplicate = true;
 3222+ }
 3223+ return ret;
 3224+ };
 3225+} else if ( document.createRange ) {
 3226+ sortOrder = function( a, b ) {
 3227+ if ( !a.ownerDocument || !b.ownerDocument ) {
 3228+ if ( a == b ) {
 3229+ hasDuplicate = true;
 3230+ }
 3231+ return a.ownerDocument ? -1 : 1;
 3232+ }
 3233+
 3234+ var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
 3235+ aRange.setStart(a, 0);
 3236+ aRange.setEnd(a, 0);
 3237+ bRange.setStart(b, 0);
 3238+ bRange.setEnd(b, 0);
 3239+ var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
 3240+ if ( ret === 0 ) {
 3241+ hasDuplicate = true;
 3242+ }
 3243+ return ret;
 3244+ };
 3245+}
 3246+
 3247+// Utility function for retreiving the text value of an array of DOM nodes
 3248+function getText( elems ) {
 3249+ var ret = "", elem;
 3250+
 3251+ for ( var i = 0; elems[i]; i++ ) {
 3252+ elem = elems[i];
 3253+
 3254+ // Get the text from text nodes and CDATA nodes
 3255+ if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
 3256+ ret += elem.nodeValue;
 3257+
 3258+ // Traverse everything else, except comment nodes
 3259+ } else if ( elem.nodeType !== 8 ) {
 3260+ ret += getText( elem.childNodes );
 3261+ }
 3262+ }
 3263+
 3264+ return ret;
 3265+}
 3266+
 3267+// Check to see if the browser returns elements by name when
 3268+// querying by getElementById (and provide a workaround)
 3269+(function(){
 3270+ // We're going to inject a fake input element with a specified name
 3271+ var form = document.createElement("div"),
 3272+ id = "script" + (new Date).getTime();
 3273+ form.innerHTML = "<a name='" + id + "'/>";
 3274+
 3275+ // Inject it into the root element, check its status, and remove it quickly
 3276+ var root = document.documentElement;
 3277+ root.insertBefore( form, root.firstChild );
 3278+
 3279+ // The workaround has to do additional checks after a getElementById
 3280+ // Which slows things down for other browsers (hence the branching)
 3281+ if ( document.getElementById( id ) ) {
 3282+ Expr.find.ID = function(match, context, isXML){
 3283+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
 3284+ var m = context.getElementById(match[1]);
 3285+ return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
 3286+ }
 3287+ };
 3288+
 3289+ Expr.filter.ID = function(elem, match){
 3290+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
 3291+ return elem.nodeType === 1 && node && node.nodeValue === match;
 3292+ };
 3293+ }
 3294+
 3295+ root.removeChild( form );
 3296+ root = form = null; // release memory in IE
 3297+})();
 3298+
 3299+(function(){
 3300+ // Check to see if the browser returns only elements
 3301+ // when doing getElementsByTagName("*")
 3302+
 3303+ // Create a fake element
 3304+ var div = document.createElement("div");
 3305+ div.appendChild( document.createComment("") );
 3306+
 3307+ // Make sure no comments are found
 3308+ if ( div.getElementsByTagName("*").length > 0 ) {
 3309+ Expr.find.TAG = function(match, context){
 3310+ var results = context.getElementsByTagName(match[1]);
 3311+
 3312+ // Filter out possible comments
 3313+ if ( match[1] === "*" ) {
 3314+ var tmp = [];
 3315+
 3316+ for ( var i = 0; results[i]; i++ ) {
 3317+ if ( results[i].nodeType === 1 ) {
 3318+ tmp.push( results[i] );
 3319+ }
 3320+ }
 3321+
 3322+ results = tmp;
 3323+ }
 3324+
 3325+ return results;
 3326+ };
 3327+ }
 3328+
 3329+ // Check to see if an attribute returns normalized href attributes
 3330+ div.innerHTML = "<a href='#'></a>";
 3331+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
 3332+ div.firstChild.getAttribute("href") !== "#" ) {
 3333+ Expr.attrHandle.href = function(elem){
 3334+ return elem.getAttribute("href", 2);
 3335+ };
 3336+ }
 3337+
 3338+ div = null; // release memory in IE
 3339+})();
 3340+
 3341+if ( document.querySelectorAll ) {
 3342+ (function(){
 3343+ var oldSizzle = Sizzle, div = document.createElement("div");
 3344+ div.innerHTML = "<p class='TEST'></p>";
 3345+
 3346+ // Safari can't handle uppercase or unicode characters when
 3347+ // in quirks mode.
 3348+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
 3349+ return;
 3350+ }
 3351+
 3352+ Sizzle = function(query, context, extra, seed){
 3353+ context = context || document;
 3354+
 3355+ // Only use querySelectorAll on non-XML documents
 3356+ // (ID selectors don't work in non-HTML documents)
 3357+ if ( !seed && context.nodeType === 9 && !isXML(context) ) {
 3358+ try {
 3359+ return makeArray( context.querySelectorAll(query), extra );
 3360+ } catch(e){}
 3361+ }
 3362+
 3363+ return oldSizzle(query, context, extra, seed);
 3364+ };
 3365+
 3366+ for ( var prop in oldSizzle ) {
 3367+ Sizzle[ prop ] = oldSizzle[ prop ];
 3368+ }
 3369+
 3370+ div = null; // release memory in IE
 3371+ })();
 3372+}
 3373+
 3374+(function(){
 3375+ var div = document.createElement("div");
 3376+
 3377+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
 3378+
 3379+ // Opera can't find a second classname (in 9.6)
 3380+ // Also, make sure that getElementsByClassName actually exists
 3381+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
 3382+ return;
 3383+ }
 3384+
 3385+ // Safari caches class attributes, doesn't catch changes (in 3.2)
 3386+ div.lastChild.className = "e";
 3387+
 3388+ if ( div.getElementsByClassName("e").length === 1 ) {
 3389+ return;
 3390+ }
 3391+
 3392+ Expr.order.splice(1, 0, "CLASS");
 3393+ Expr.find.CLASS = function(match, context, isXML) {
 3394+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
 3395+ return context.getElementsByClassName(match[1]);
 3396+ }
 3397+ };
 3398+
 3399+ div = null; // release memory in IE
 3400+})();
 3401+
 3402+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
 3403+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 3404+ var elem = checkSet[i];
 3405+ if ( elem ) {
 3406+ elem = elem[dir];
 3407+ var match = false;
 3408+
 3409+ while ( elem ) {
 3410+ if ( elem.sizcache === doneName ) {
 3411+ match = checkSet[elem.sizset];
 3412+ break;
 3413+ }
 3414+
 3415+ if ( elem.nodeType === 1 && !isXML ){
 3416+ elem.sizcache = doneName;
 3417+ elem.sizset = i;
 3418+ }
 3419+
 3420+ if ( elem.nodeName.toLowerCase() === cur ) {
 3421+ match = elem;
 3422+ break;
 3423+ }
 3424+
 3425+ elem = elem[dir];
 3426+ }
 3427+
 3428+ checkSet[i] = match;
 3429+ }
 3430+ }
 3431+}
 3432+
 3433+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
 3434+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 3435+ var elem = checkSet[i];
 3436+ if ( elem ) {
 3437+ elem = elem[dir];
 3438+ var match = false;
 3439+
 3440+ while ( elem ) {
 3441+ if ( elem.sizcache === doneName ) {
 3442+ match = checkSet[elem.sizset];
 3443+ break;
 3444+ }
 3445+
 3446+ if ( elem.nodeType === 1 ) {
 3447+ if ( !isXML ) {
 3448+ elem.sizcache = doneName;
 3449+ elem.sizset = i;
 3450+ }
 3451+ if ( typeof cur !== "string" ) {
 3452+ if ( elem === cur ) {
 3453+ match = true;
 3454+ break;
 3455+ }
 3456+
 3457+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
 3458+ match = elem;
 3459+ break;
 3460+ }
 3461+ }
 3462+
 3463+ elem = elem[dir];
 3464+ }
 3465+
 3466+ checkSet[i] = match;
 3467+ }
 3468+ }
 3469+}
 3470+
 3471+var contains = document.compareDocumentPosition ? function(a, b){
 3472+ return a.compareDocumentPosition(b) & 16;
 3473+} : function(a, b){
 3474+ return a !== b && (a.contains ? a.contains(b) : true);
 3475+};
 3476+
 3477+var isXML = function(elem){
 3478+ // documentElement is verified for cases where it doesn't yet exist
 3479+ // (such as loading iframes in IE - #4833)
 3480+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
 3481+ return documentElement ? documentElement.nodeName !== "HTML" : false;
 3482+};
 3483+
 3484+var posProcess = function(selector, context){
 3485+ var tmpSet = [], later = "", match,
 3486+ root = context.nodeType ? [context] : context;
 3487+
 3488+ // Position selectors must be done after the filter
 3489+ // And so must :not(positional) so we move all PSEUDOs to the end
 3490+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
 3491+ later += match[0];
 3492+ selector = selector.replace( Expr.match.PSEUDO, "" );
 3493+ }
 3494+
 3495+ selector = Expr.relative[selector] ? selector + "*" : selector;
 3496+
 3497+ for ( var i = 0, l = root.length; i < l; i++ ) {
 3498+ Sizzle( selector, root[i], tmpSet );
 3499+ }
 3500+
 3501+ return Sizzle.filter( later, tmpSet );
 3502+};
 3503+
 3504+// EXPOSE
 3505+jQuery.find = Sizzle;
 3506+jQuery.expr = Sizzle.selectors;
 3507+jQuery.expr[":"] = jQuery.expr.filters;
 3508+jQuery.unique = Sizzle.uniqueSort;
 3509+jQuery.getText = getText;
 3510+jQuery.isXMLDoc = isXML;
 3511+jQuery.contains = contains;
 3512+
 3513+return;
 3514+
 3515+window.Sizzle = Sizzle;
 3516+
 3517+})();
 3518+var runtil = /Until$/,
 3519+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
 3520+ // Note: This RegExp should be improved, or likely pulled from Sizzle
 3521+ rmultiselector = /,/,
 3522+ slice = Array.prototype.slice;
 3523+
 3524+// Implement the identical functionality for filter and not
 3525+var winnow = function( elements, qualifier, keep ) {
 3526+ if ( jQuery.isFunction( qualifier ) ) {
 3527+ return jQuery.grep(elements, function( elem, i ) {
 3528+ return !!qualifier.call( elem, i, elem ) === keep;
 3529+ });
 3530+
 3531+ } else if ( qualifier.nodeType ) {
 3532+ return jQuery.grep(elements, function( elem, i ) {
 3533+ return (elem === qualifier) === keep;
 3534+ });
 3535+
 3536+ } else if ( typeof qualifier === "string" ) {
 3537+ var filtered = jQuery.grep(elements, function( elem ) {
 3538+ return elem.nodeType === 1;
 3539+ });
 3540+
 3541+ if ( isSimple.test( qualifier ) ) {
 3542+ return jQuery.filter(qualifier, filtered, !keep);
 3543+ } else {
 3544+ qualifier = jQuery.filter( qualifier, elements );
 3545+ }
 3546+ }
 3547+
 3548+ return jQuery.grep(elements, function( elem, i ) {
 3549+ return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
 3550+ });
 3551+};
 3552+
 3553+jQuery.fn.extend({
 3554+ find: function( selector ) {
 3555+ var ret = this.pushStack( "", "find", selector ), length = 0;
 3556+
 3557+ for ( var i = 0, l = this.length; i < l; i++ ) {
 3558+ length = ret.length;
 3559+ jQuery.find( selector, this[i], ret );
 3560+
 3561+ if ( i > 0 ) {
 3562+ // Make sure that the results are unique
 3563+ for ( var n = length; n < ret.length; n++ ) {
 3564+ for ( var r = 0; r < length; r++ ) {
 3565+ if ( ret[r] === ret[n] ) {
 3566+ ret.splice(n--, 1);
 3567+ break;
 3568+ }
 3569+ }
 3570+ }
 3571+ }
 3572+ }
 3573+
 3574+ return ret;
 3575+ },
 3576+
 3577+ has: function( target ) {
 3578+ var targets = jQuery( target );
 3579+ return this.filter(function() {
 3580+ for ( var i = 0, l = targets.length; i < l; i++ ) {
 3581+ if ( jQuery.contains( this, targets[i] ) ) {
 3582+ return true;
 3583+ }
 3584+ }
 3585+ });
 3586+ },
 3587+
 3588+ not: function( selector ) {
 3589+ return this.pushStack( winnow(this, selector, false), "not", selector);
 3590+ },
 3591+
 3592+ filter: function( selector ) {
 3593+ return this.pushStack( winnow(this, selector, true), "filter", selector );
 3594+ },
 3595+
 3596+ is: function( selector ) {
 3597+ return !!selector && jQuery.filter( selector, this ).length > 0;
 3598+ },
 3599+
 3600+ closest: function( selectors, context ) {
 3601+ if ( jQuery.isArray( selectors ) ) {
 3602+ var ret = [], cur = this[0], match, matches = {}, selector;
 3603+
 3604+ if ( cur && selectors.length ) {
 3605+ for ( var i = 0, l = selectors.length; i < l; i++ ) {
 3606+ selector = selectors[i];
 3607+
 3608+ if ( !matches[selector] ) {
 3609+ matches[selector] = jQuery.expr.match.POS.test( selector ) ?
 3610+ jQuery( selector, context || this.context ) :
 3611+ selector;
 3612+ }
 3613+ }
 3614+
 3615+ while ( cur && cur.ownerDocument && cur !== context ) {
 3616+ for ( selector in matches ) {
 3617+ match = matches[selector];
 3618+
 3619+ if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
 3620+ ret.push({ selector: selector, elem: cur });
 3621+ delete matches[selector];
 3622+ }
 3623+ }
 3624+ cur = cur.parentNode;
 3625+ }
 3626+ }
 3627+
 3628+ return ret;
 3629+ }
 3630+
 3631+ var pos = jQuery.expr.match.POS.test( selectors ) ?
 3632+ jQuery( selectors, context || this.context ) : null;
 3633+
 3634+ return this.map(function( i, cur ) {
 3635+ while ( cur && cur.ownerDocument && cur !== context ) {
 3636+ if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
 3637+ return cur;
 3638+ }
 3639+ cur = cur.parentNode;
 3640+ }
 3641+ return null;
 3642+ });
 3643+ },
 3644+
 3645+ // Determine the position of an element within
 3646+ // the matched set of elements
 3647+ index: function( elem ) {
 3648+ if ( !elem || typeof elem === "string" ) {
 3649+ return jQuery.inArray( this[0],
 3650+ // If it receives a string, the selector is used
 3651+ // If it receives nothing, the siblings are used
 3652+ elem ? jQuery( elem ) : this.parent().children() );
 3653+ }
 3654+ // Locate the position of the desired element
 3655+ return jQuery.inArray(
 3656+ // If it receives a jQuery object, the first element is used
 3657+ elem.jquery ? elem[0] : elem, this );
 3658+ },
 3659+
 3660+ add: function( selector, context ) {
 3661+ var set = typeof selector === "string" ?
 3662+ jQuery( selector, context || this.context ) :
 3663+ jQuery.makeArray( selector ),
 3664+ all = jQuery.merge( this.get(), set );
 3665+
 3666+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
 3667+ all :
 3668+ jQuery.unique( all ) );
 3669+ },
 3670+
 3671+ andSelf: function() {
 3672+ return this.add( this.prevObject );
 3673+ }
 3674+});
 3675+
 3676+// A painfully simple check to see if an element is disconnected
 3677+// from a document (should be improved, where feasible).
 3678+function isDisconnected( node ) {
 3679+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
 3680+}
 3681+
 3682+jQuery.each({
 3683+ parent: function( elem ) {
 3684+ var parent = elem.parentNode;
 3685+ return parent && parent.nodeType !== 11 ? parent : null;
 3686+ },
 3687+ parents: function( elem ) {
 3688+ return jQuery.dir( elem, "parentNode" );
 3689+ },
 3690+ parentsUntil: function( elem, i, until ) {
 3691+ return jQuery.dir( elem, "parentNode", until );
 3692+ },
 3693+ next: function( elem ) {
 3694+ return jQuery.nth( elem, 2, "nextSibling" );
 3695+ },
 3696+ prev: function( elem ) {
 3697+ return jQuery.nth( elem, 2, "previousSibling" );
 3698+ },
 3699+ nextAll: function( elem ) {
 3700+ return jQuery.dir( elem, "nextSibling" );
 3701+ },
 3702+ prevAll: function( elem ) {
 3703+ return jQuery.dir( elem, "previousSibling" );
 3704+ },
 3705+ nextUntil: function( elem, i, until ) {
 3706+ return jQuery.dir( elem, "nextSibling", until );
 3707+ },
 3708+ prevUntil: function( elem, i, until ) {
 3709+ return jQuery.dir( elem, "previousSibling", until );
 3710+ },
 3711+ siblings: function( elem ) {
 3712+ return jQuery.sibling( elem.parentNode.firstChild, elem );
 3713+ },
 3714+ children: function( elem ) {
 3715+ return jQuery.sibling( elem.firstChild );
 3716+ },
 3717+ contents: function( elem ) {
 3718+ return jQuery.nodeName( elem, "iframe" ) ?
 3719+ elem.contentDocument || elem.contentWindow.document :
 3720+ jQuery.makeArray( elem.childNodes );
 3721+ }
 3722+}, function( name, fn ) {
 3723+ jQuery.fn[ name ] = function( until, selector ) {
 3724+ var ret = jQuery.map( this, fn, until );
 3725+
 3726+ if ( !runtil.test( name ) ) {
 3727+ selector = until;
 3728+ }
 3729+
 3730+ if ( selector && typeof selector === "string" ) {
 3731+ ret = jQuery.filter( selector, ret );
 3732+ }
 3733+
 3734+ ret = this.length > 1 ? jQuery.unique( ret ) : ret;
 3735+
 3736+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
 3737+ ret = ret.reverse();
 3738+ }
 3739+
 3740+ return this.pushStack( ret, name, slice.call(arguments).join(",") );
 3741+ };
 3742+});
 3743+
 3744+jQuery.extend({
 3745+ filter: function( expr, elems, not ) {
 3746+ if ( not ) {
 3747+ expr = ":not(" + expr + ")";
 3748+ }
 3749+
 3750+ return jQuery.find.matches(expr, elems);
 3751+ },
 3752+
 3753+ dir: function( elem, dir, until ) {
 3754+ var matched = [], cur = elem[dir];
 3755+ while ( cur && cur.nodeType !== 9 && (until === undefined || !jQuery( cur ).is( until )) ) {
 3756+ if ( cur.nodeType === 1 ) {
 3757+ matched.push( cur );
 3758+ }
 3759+ cur = cur[dir];
 3760+ }
 3761+ return matched;
 3762+ },
 3763+
 3764+ nth: function( cur, result, dir, elem ) {
 3765+ result = result || 1;
 3766+ var num = 0;
 3767+
 3768+ for ( ; cur; cur = cur[dir] ) {
 3769+ if ( cur.nodeType === 1 && ++num === result ) {
 3770+ break;
 3771+ }
 3772+ }
 3773+
 3774+ return cur;
 3775+ },
 3776+
 3777+ sibling: function( n, elem ) {
 3778+ var r = [];
 3779+
 3780+ for ( ; n; n = n.nextSibling ) {
 3781+ if ( n.nodeType === 1 && n !== elem ) {
 3782+ r.push( n );
 3783+ }
 3784+ }
 3785+
 3786+ return r;
 3787+ }
 3788+});
 3789+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
 3790+ rleadingWhitespace = /^\s+/,
 3791+ rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
 3792+ rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
 3793+ rtagName = /<([\w:]+)/,
 3794+ rtbody = /<tbody/i,
 3795+ rhtml = /<|&\w+;/,
 3796+ fcloseTag = function( all, front, tag ) {
 3797+ return rselfClosing.test( tag ) ?
 3798+ all :
 3799+ front + "></" + tag + ">";
 3800+ },
 3801+ wrapMap = {
 3802+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
 3803+ legend: [ 1, "<fieldset>", "</fieldset>" ],
 3804+ thead: [ 1, "<table>", "</table>" ],
 3805+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
 3806+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
 3807+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
 3808+ area: [ 1, "<map>", "</map>" ],
 3809+ _default: [ 0, "", "" ]
 3810+ };
 3811+
 3812+wrapMap.optgroup = wrapMap.option;
 3813+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
 3814+wrapMap.th = wrapMap.td;
 3815+
 3816+// IE can't serialize <link> and <script> tags normally
 3817+if ( !jQuery.support.htmlSerialize ) {
 3818+ wrapMap._default = [ 1, "div<div>", "</div>" ];
 3819+}
 3820+
 3821+jQuery.fn.extend({
 3822+ text: function( text ) {
 3823+ if ( jQuery.isFunction(text) ) {
 3824+ return this.each(function(i) {
 3825+ var self = jQuery(this);
 3826+ return self.text( text.call(this, i, self.text()) );
 3827+ });
 3828+ }
 3829+
 3830+ if ( typeof text !== "object" && text !== undefined ) {
 3831+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
 3832+ }
 3833+
 3834+ return jQuery.getText( this );
 3835+ },
 3836+
 3837+ wrapAll: function( html ) {
 3838+ if ( jQuery.isFunction( html ) ) {
 3839+ return this.each(function(i) {
 3840+ jQuery(this).wrapAll( html.call(this, i) );
 3841+ });
 3842+ }
 3843+
 3844+ if ( this[0] ) {
 3845+ // The elements to wrap the target around
 3846+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
 3847+
 3848+ if ( this[0].parentNode ) {
 3849+ wrap.insertBefore( this[0] );
 3850+ }
 3851+
 3852+ wrap.map(function() {
 3853+ var elem = this;
 3854+
 3855+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
 3856+ elem = elem.firstChild;
 3857+ }
 3858+
 3859+ return elem;
 3860+ }).append(this);
 3861+ }
 3862+
 3863+ return this;
 3864+ },
 3865+
 3866+ wrapInner: function( html ) {
 3867+ return this.each(function() {
 3868+ var self = jQuery( this ), contents = self.contents();
 3869+
 3870+ if ( contents.length ) {
 3871+ contents.wrapAll( html );
 3872+
 3873+ } else {
 3874+ self.append( html );
 3875+ }
 3876+ });
 3877+ },
 3878+
 3879+ wrap: function( html ) {
 3880+ return this.each(function() {
 3881+ jQuery( this ).wrapAll( html );
 3882+ });
 3883+ },
 3884+
 3885+ unwrap: function() {
 3886+ return this.parent().each(function() {
 3887+ if ( !jQuery.nodeName( this, "body" ) ) {
 3888+ jQuery( this ).replaceWith( this.childNodes );
 3889+ }
 3890+ }).end();
 3891+ },
 3892+
 3893+ append: function() {
 3894+ return this.domManip(arguments, true, function( elem ) {
 3895+ if ( this.nodeType === 1 ) {
 3896+ this.appendChild( elem );
 3897+ }
 3898+ });
 3899+ },
 3900+
 3901+ prepend: function() {
 3902+ return this.domManip(arguments, true, function( elem ) {
 3903+ if ( this.nodeType === 1 ) {
 3904+ this.insertBefore( elem, this.firstChild );
 3905+ }
 3906+ });
 3907+ },
 3908+
 3909+ before: function() {
 3910+ if ( this[0] && this[0].parentNode ) {
 3911+ return this.domManip(arguments, false, function( elem ) {
 3912+ this.parentNode.insertBefore( elem, this );
 3913+ });
 3914+ } else if ( arguments.length ) {
 3915+ var set = jQuery(arguments[0]);
 3916+ set.push.apply( set, this.toArray() );
 3917+ return this.pushStack( set, "before", arguments );
 3918+ }
 3919+ },
 3920+
 3921+ after: function() {
 3922+ if ( this[0] && this[0].parentNode ) {
 3923+ return this.domManip(arguments, false, function( elem ) {
 3924+ this.parentNode.insertBefore( elem, this.nextSibling );
 3925+ });
 3926+ } else if ( arguments.length ) {
 3927+ var set = this.pushStack( this, "after", arguments );
 3928+ set.push.apply( set, jQuery(arguments[0]).toArray() );
 3929+ return set;
 3930+ }
 3931+ },
 3932+
 3933+ clone: function( events ) {
 3934+ // Do the clone
 3935+ var ret = this.map(function() {
 3936+ if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
 3937+ // IE copies events bound via attachEvent when
 3938+ // using cloneNode. Calling detachEvent on the
 3939+ // clone will also remove the events from the orignal
 3940+ // In order to get around this, we use innerHTML.
 3941+ // Unfortunately, this means some modifications to
 3942+ // attributes in IE that are actually only stored
 3943+ // as properties will not be copied (such as the
 3944+ // the name attribute on an input).
 3945+ var html = this.outerHTML, ownerDocument = this.ownerDocument;
 3946+ if ( !html ) {
 3947+ var div = ownerDocument.createElement("div");
 3948+ div.appendChild( this.cloneNode(true) );
 3949+ html = div.innerHTML;
 3950+ }
 3951+
 3952+ return jQuery.clean([html.replace(rinlinejQuery, "")
 3953+ .replace(rleadingWhitespace, "")], ownerDocument)[0];
 3954+ } else {
 3955+ return this.cloneNode(true);
 3956+ }
 3957+ });
 3958+
 3959+ // Copy the events from the original to the clone
 3960+ if ( events === true ) {
 3961+ cloneCopyEvent( this, ret );
 3962+ cloneCopyEvent( this.find("*"), ret.find("*") );
 3963+ }
 3964+
 3965+ // Return the cloned set
 3966+ return ret;
 3967+ },
 3968+
 3969+ html: function( value ) {
 3970+ if ( value === undefined ) {
 3971+ return this[0] && this[0].nodeType === 1 ?
 3972+ this[0].innerHTML.replace(rinlinejQuery, "") :
 3973+ null;
 3974+
 3975+ // See if we can take a shortcut and just use innerHTML
 3976+ } else if ( typeof value === "string" && !/<script/i.test( value ) &&
 3977+ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
 3978+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
 3979+
 3980+ try {
 3981+ for ( var i = 0, l = this.length; i < l; i++ ) {
 3982+ // Remove element nodes and prevent memory leaks
 3983+ if ( this[i].nodeType === 1 ) {
 3984+ cleanData( this[i].getElementsByTagName("*") );
 3985+ this[i].innerHTML = value;
 3986+ }
 3987+ }
 3988+
 3989+ // If using innerHTML throws an exception, use the fallback method
 3990+ } catch(e) {
 3991+ this.empty().append( value );
 3992+ }
 3993+
 3994+ } else if ( jQuery.isFunction( value ) ) {
 3995+ this.each(function(i){
 3996+ var self = jQuery(this), old = self.html();
 3997+ self.empty().append(function(){
 3998+ return value.call( this, i, old );
 3999+ });
 4000+ });
 4001+
 4002+ } else {
 4003+ this.empty().append( value );
 4004+ }
 4005+
 4006+ return this;
 4007+ },
 4008+
 4009+ replaceWith: function( value ) {
 4010+ if ( this[0] && this[0].parentNode ) {
 4011+ // Make sure that the elements are removed from the DOM before they are inserted
 4012+ // this can help fix replacing a parent with child elements
 4013+ if ( !jQuery.isFunction( value ) ) {
 4014+ value = jQuery( value ).detach();
 4015+ }
 4016+
 4017+ return this.each(function() {
 4018+ var next = this.nextSibling, parent = this.parentNode;
 4019+
 4020+ jQuery(this).remove();
 4021+
 4022+ if ( next ) {
 4023+ jQuery(next).before( value );
 4024+ } else {
 4025+ jQuery(parent).append( value );
 4026+ }
 4027+ });
 4028+ } else {
 4029+ return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
 4030+ }
 4031+ },
 4032+
 4033+ detach: function( selector ) {
 4034+ return this.remove( selector, true );
 4035+ },
 4036+
 4037+ domManip: function( args, table, callback ) {
 4038+ var results, first, value = args[0], scripts = [];
 4039+
 4040+ if ( jQuery.isFunction(value) ) {
 4041+ return this.each(function(i) {
 4042+ var self = jQuery(this);
 4043+ args[0] = value.call(this, i, table ? self.html() : undefined);
 4044+ return self.domManip( args, table, callback );
 4045+ });
 4046+ }
 4047+
 4048+ if ( this[0] ) {
 4049+ // If we're in a fragment, just use that instead of building a new one
 4050+ if ( args[0] && args[0].parentNode && args[0].parentNode.nodeType === 11 ) {
 4051+ results = { fragment: args[0].parentNode };
 4052+ } else {
 4053+ results = buildFragment( args, this, scripts );
 4054+ }
 4055+
 4056+ first = results.fragment.firstChild;
 4057+
 4058+ if ( first ) {
 4059+ table = table && jQuery.nodeName( first, "tr" );
 4060+
 4061+ for ( var i = 0, l = this.length; i < l; i++ ) {
 4062+ callback.call(
 4063+ table ?
 4064+ root(this[i], first) :
 4065+ this[i],
 4066+ results.cacheable || this.length > 1 || i > 0 ?
 4067+ results.fragment.cloneNode(true) :
 4068+ results.fragment
 4069+ );
 4070+ }
 4071+ }
 4072+
 4073+ if ( scripts ) {
 4074+ jQuery.each( scripts, evalScript );
 4075+ }
 4076+ }
 4077+
 4078+ return this;
 4079+
 4080+ function root( elem, cur ) {
 4081+ return jQuery.nodeName(elem, "table") ?
 4082+ (elem.getElementsByTagName("tbody")[0] ||
 4083+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
 4084+ elem;
 4085+ }
 4086+ }
 4087+});
 4088+
 4089+function cloneCopyEvent(orig, ret) {
 4090+ var i = 0;
 4091+
 4092+ ret.each(function() {
 4093+ if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
 4094+ return;
 4095+ }
 4096+
 4097+ var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;
 4098+
 4099+ if ( events ) {
 4100+ delete curData.handle;
 4101+ curData.events = {};
 4102+
 4103+ for ( var type in events ) {
 4104+ for ( var handler in events[ type ] ) {
 4105+ jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
 4106+ }
 4107+ }
 4108+ }
 4109+ });
 4110+}
 4111+
 4112+function buildFragment( args, nodes, scripts ) {
 4113+ var fragment, cacheable, cached, cacheresults, doc;
 4114+
 4115+ if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 ) {
 4116+ cacheable = true;
 4117+ cacheresults = jQuery.fragments[ args[0] ];
 4118+ if ( cacheresults ) {
 4119+ if ( cacheresults !== 1 ) {
 4120+ fragment = cacheresults;
 4121+ }
 4122+ cached = true;
 4123+ }
 4124+ }
 4125+
 4126+ if ( !fragment ) {
 4127+ doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
 4128+ fragment = doc.createDocumentFragment();
 4129+ jQuery.clean( args, doc, fragment, scripts );
 4130+ }
 4131+
 4132+ if ( cacheable ) {
 4133+ jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
 4134+ }
 4135+
 4136+ return { fragment: fragment, cacheable: cacheable };
 4137+}
 4138+
 4139+jQuery.fragments = {};
 4140+
 4141+jQuery.each({
 4142+ appendTo: "append",
 4143+ prependTo: "prepend",
 4144+ insertBefore: "before",
 4145+ insertAfter: "after",
 4146+ replaceAll: "replaceWith"
 4147+}, function( name, original ) {
 4148+ jQuery.fn[ name ] = function( selector ) {
 4149+ var ret = [], insert = jQuery( selector );
 4150+
 4151+ for ( var i = 0, l = insert.length; i < l; i++ ) {
 4152+ var elems = (i > 0 ? this.clone(true) : this).get();
 4153+ jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
 4154+ ret = ret.concat( elems );
 4155+ }
 4156+ return this.pushStack( ret, name, insert.selector );
 4157+ };
 4158+});
 4159+
 4160+jQuery.each({
 4161+ // keepData is for internal use only--do not document
 4162+ remove: function( selector, keepData ) {
 4163+ if ( !selector || jQuery.filter( selector, [ this ] ).length ) {
 4164+ if ( !keepData && this.nodeType === 1 ) {
 4165+ cleanData( this.getElementsByTagName("*") );
 4166+ cleanData( [ this ] );
 4167+ }
 4168+
 4169+ if ( this.parentNode ) {
 4170+ this.parentNode.removeChild( this );
 4171+ }
 4172+ }
 4173+ },
 4174+
 4175+ empty: function() {
 4176+ // Remove element nodes and prevent memory leaks
 4177+ if ( this.nodeType === 1 ) {
 4178+ cleanData( this.getElementsByTagName("*") );
 4179+ }
 4180+
 4181+ // Remove any remaining nodes
 4182+ while ( this.firstChild ) {
 4183+ this.removeChild( this.firstChild );
 4184+ }
 4185+ }
 4186+}, function( name, fn ) {
 4187+ jQuery.fn[ name ] = function() {
 4188+ return this.each( fn, arguments );
 4189+ };
 4190+});
 4191+
 4192+jQuery.extend({
 4193+ clean: function( elems, context, fragment, scripts ) {
 4194+ context = context || document;
 4195+
 4196+ // !context.createElement fails in IE with an error but returns typeof 'object'
 4197+ if ( typeof context.createElement === "undefined" ) {
 4198+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
 4199+ }
 4200+
 4201+ var ret = [];
 4202+
 4203+ jQuery.each(elems, function( i, elem ) {
 4204+ if ( typeof elem === "number" ) {
 4205+ elem += "";
 4206+ }
 4207+
 4208+ if ( !elem ) {
 4209+ return;
 4210+ }
 4211+
 4212+ // Convert html string into DOM nodes
 4213+ if ( typeof elem === "string" && !rhtml.test( elem ) ) {
 4214+ elem = context.createTextNode( elem );
 4215+
 4216+ } else if ( typeof elem === "string" ) {
 4217+ // Fix "XHTML"-style tags in all browsers
 4218+ elem = elem.replace(rxhtmlTag, fcloseTag);
 4219+
 4220+ // Trim whitespace, otherwise indexOf won't work as expected
 4221+ var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
 4222+ wrap = wrapMap[ tag ] || wrapMap._default,
 4223+ depth = wrap[0],
 4224+ div = context.createElement("div");
 4225+
 4226+ // Go to html and back, then peel off extra wrappers
 4227+ div.innerHTML = wrap[1] + elem + wrap[2];
 4228+
 4229+ // Move to the right depth
 4230+ while ( depth-- ) {
 4231+ div = div.lastChild;
 4232+ }
 4233+
 4234+ // Remove IE's autoinserted <tbody> from table fragments
 4235+ if ( !jQuery.support.tbody ) {
 4236+
 4237+ // String was a <table>, *may* have spurious <tbody>
 4238+ var hasBody = rtbody.test(elem),
 4239+ tbody = tag === "table" && !hasBody ?
 4240+ div.firstChild && div.firstChild.childNodes :
 4241+
 4242+ // String was a bare <thead> or <tfoot>
 4243+ wrap[1] === "<table>" && !hasBody ?
 4244+ div.childNodes :
 4245+ [];
 4246+
 4247+ for ( var j = tbody.length - 1; j >= 0 ; --j ) {
 4248+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
 4249+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
 4250+ }
 4251+ }
 4252+
 4253+ }
 4254+
 4255+ // IE completely kills leading whitespace when innerHTML is used
 4256+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
 4257+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
 4258+ }
 4259+
 4260+ elem = jQuery.makeArray( div.childNodes );
 4261+ }
 4262+
 4263+ if ( elem.nodeType ) {
 4264+ ret.push( elem );
 4265+ } else {
 4266+ ret = jQuery.merge( ret, elem );
 4267+ }
 4268+
 4269+ });
 4270+
 4271+ if ( fragment ) {
 4272+ for ( var i = 0; ret[i]; i++ ) {
 4273+ if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
 4274+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
 4275+ } else {
 4276+ if ( ret[i].nodeType === 1 ) {
 4277+ ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
 4278+ }
 4279+ fragment.appendChild( ret[i] );
 4280+ }
 4281+ }
 4282+ }
 4283+
 4284+ return ret;
 4285+ }
 4286+});
 4287+
 4288+function cleanData( elems ) {
 4289+ for ( var i = 0, elem, id; (elem = elems[i]) != null; i++ ) {
 4290+ if ( !jQuery.noData[elem.nodeName.toLowerCase()] && (id = elem[expando]) ) {
 4291+ delete jQuery.cache[ id ];
 4292+ }
 4293+ }
 4294+}
 4295+// exclude the following css properties to add px
 4296+var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
 4297+ ralpha = /alpha\([^)]*\)/,
 4298+ ropacity = /opacity=([^)]*)/,
 4299+ rfloat = /float/i,
 4300+ rdashAlpha = /-([a-z])/ig,
 4301+ rupper = /([A-Z])/g,
 4302+ rnumpx = /^-?\d+(?:px)?$/i,
 4303+ rnum = /^-?\d/,
 4304+
 4305+ cssShow = { position: "absolute", visibility: "hidden", display:"block" },
 4306+ cssWidth = [ "Left", "Right" ],
 4307+ cssHeight = [ "Top", "Bottom" ],
 4308+
 4309+ // cache check for defaultView.getComputedStyle
 4310+ getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
 4311+ // normalize float css property
 4312+ styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
 4313+ fcamelCase = function( all, letter ) {
 4314+ return letter.toUpperCase();
 4315+ };
 4316+
 4317+jQuery.fn.css = function( name, value ) {
 4318+ return access( this, name, value, true, function( elem, name, value ) {
 4319+ if ( value === undefined ) {
 4320+ return jQuery.curCSS( elem, name );
 4321+ }
 4322+
 4323+ if ( typeof value === "number" && !rexclude.test(name) ) {
 4324+ value += "px";
 4325+ }
 4326+
 4327+ jQuery.style( elem, name, value );
 4328+ });
 4329+};
 4330+
 4331+jQuery.extend({
 4332+ style: function( elem, name, value ) {
 4333+ // don't set styles on text and comment nodes
 4334+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
 4335+ return undefined;
 4336+ }
 4337+
 4338+ // ignore negative width and height values #1599
 4339+ if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
 4340+ value = undefined;
 4341+ }
 4342+
 4343+ var style = elem.style || elem, set = value !== undefined;
 4344+
 4345+ // IE uses filters for opacity
 4346+ if ( !jQuery.support.opacity && name === "opacity" ) {
 4347+ if ( set ) {
 4348+ // IE has trouble with opacity if it does not have layout
 4349+ // Force it by setting the zoom level
 4350+ style.zoom = 1;
 4351+
 4352+ // Set the alpha filter to set the opacity
 4353+ var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
 4354+ var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
 4355+ style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
 4356+ }
 4357+
 4358+ return style.filter && style.filter.indexOf("opacity=") >= 0 ?
 4359+ (parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
 4360+ "";
 4361+ }
 4362+
 4363+ // Make sure we're using the right name for getting the float value
 4364+ if ( rfloat.test( name ) ) {
 4365+ name = styleFloat;
 4366+ }
 4367+
 4368+ name = name.replace(rdashAlpha, fcamelCase);
 4369+
 4370+ if ( set ) {
 4371+ style[ name ] = value;
 4372+ }
 4373+
 4374+ return style[ name ];
 4375+ },
 4376+
 4377+ css: function( elem, name, force, extra ) {
 4378+ if ( name === "width" || name === "height" ) {
 4379+ var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;
 4380+
 4381+ function getWH() {
 4382+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
 4383+
 4384+ if ( extra === "border" ) {
 4385+ return;
 4386+ }
 4387+
 4388+ jQuery.each( which, function() {
 4389+ if ( !extra ) {
 4390+ val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
 4391+ }
 4392+
 4393+ if ( extra === "margin" ) {
 4394+ val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
 4395+ } else {
 4396+ val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
 4397+ }
 4398+ });
 4399+ }
 4400+
 4401+ if ( elem.offsetWidth !== 0 ) {
 4402+ getWH();
 4403+ } else {
 4404+ jQuery.swap( elem, props, getWH );
 4405+ }
 4406+
 4407+ return Math.max(0, Math.round(val));
 4408+ }
 4409+
 4410+ return jQuery.curCSS( elem, name, force );
 4411+ },
 4412+
 4413+ curCSS: function( elem, name, force ) {
 4414+ var ret, style = elem.style, filter;
 4415+
 4416+ // IE uses filters for opacity
 4417+ if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
 4418+ ret = ropacity.test(elem.currentStyle.filter || "") ?
 4419+ (parseFloat(RegExp.$1) / 100) + "" :
 4420+ "";
 4421+
 4422+ return ret === "" ?
 4423+ "1" :
 4424+ ret;
 4425+ }
 4426+
 4427+ // Make sure we're using the right name for getting the float value
 4428+ if ( rfloat.test( name ) ) {
 4429+ name = styleFloat;
 4430+ }
 4431+
 4432+ if ( !force && style && style[ name ] ) {
 4433+ ret = style[ name ];
 4434+
 4435+ } else if ( getComputedStyle ) {
 4436+
 4437+ // Only "float" is needed here
 4438+ if ( rfloat.test( name ) ) {
 4439+ name = "float";
 4440+ }
 4441+
 4442+ name = name.replace( rupper, "-$1" ).toLowerCase();
 4443+
 4444+ var defaultView = elem.ownerDocument.defaultView;
 4445+
 4446+ if ( !defaultView ) {
 4447+ return null;
 4448+ }
 4449+
 4450+ var computedStyle = defaultView.getComputedStyle( elem, null );
 4451+
 4452+ if ( computedStyle ) {
 4453+ ret = computedStyle.getPropertyValue( name );
 4454+ }
 4455+
 4456+ // We should always get a number back from opacity
 4457+ if ( name === "opacity" && ret === "" ) {
 4458+ ret = "1";
 4459+ }
 4460+
 4461+ } else if ( elem.currentStyle ) {
 4462+ var camelCase = name.replace(rdashAlpha, fcamelCase);
 4463+
 4464+ ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
 4465+
 4466+ // From the awesome hack by Dean Edwards
 4467+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
 4468+
 4469+ // If we're not dealing with a regular pixel number
 4470+ // but a number that has a weird ending, we need to convert it to pixels
 4471+ if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
 4472+ // Remember the original values
 4473+ var left = style.left, rsLeft = elem.runtimeStyle.left;
 4474+
 4475+ // Put in the new values to get a computed value out
 4476+ elem.runtimeStyle.left = elem.currentStyle.left;
 4477+ style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
 4478+ ret = style.pixelLeft + "px";
 4479+
 4480+ // Revert the changed values
 4481+ style.left = left;
 4482+ elem.runtimeStyle.left = rsLeft;
 4483+ }
 4484+ }
 4485+
 4486+ return ret;
 4487+ },
 4488+
 4489+ // A method for quickly swapping in/out CSS properties to get correct calculations
 4490+ swap: function( elem, options, callback ) {
 4491+ var old = {};
 4492+
 4493+ // Remember the old values, and insert the new ones
 4494+ for ( var name in options ) {
 4495+ old[ name ] = elem.style[ name ];
 4496+ elem.style[ name ] = options[ name ];
 4497+ }
 4498+
 4499+ callback.call( elem );
 4500+
 4501+ // Revert the old values
 4502+ for ( var name in options ) {
 4503+ elem.style[ name ] = old[ name ];
 4504+ }
 4505+ }
 4506+});
 4507+
 4508+if ( jQuery.expr && jQuery.expr.filters ) {
 4509+ jQuery.expr.filters.hidden = function( elem ) {
 4510+ var width = elem.offsetWidth, height = elem.offsetHeight,
 4511+ skip = elem.nodeName.toLowerCase() === "tr";
 4512+
 4513+ return width === 0 && height === 0 && !skip ?
 4514+ true :
 4515+ width > 0 && height > 0 && !skip ?
 4516+ false :
 4517+ jQuery.curCSS(elem, "display") === "none";
 4518+ };
 4519+
 4520+ jQuery.expr.filters.visible = function( elem ) {
 4521+ return !jQuery.expr.filters.hidden( elem );
 4522+ };
 4523+}
 4524+var jsc = now(),
 4525+ rscript = /<script(.|\s)*?\/script>/gi,
 4526+ rselectTextarea = /select|textarea/i,
 4527+ rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
 4528+ jsre = /=\?(&|$)/,
 4529+ rquery = /\?/,
 4530+ rts = /(\?|&)_=.*?(&|$)/,
 4531+ rurl = /^(\w+:)?\/\/([^\/?#]+)/,
 4532+ r20 = /%20/g;
 4533+
 4534+jQuery.fn.extend({
 4535+ // Keep a copy of the old load
 4536+ _load: jQuery.fn.load,
 4537+
 4538+ load: function( url, params, callback ) {
 4539+ if ( typeof url !== "string" ) {
 4540+ return this._load( url );
 4541+
 4542+ // Don't do a request if no elements are being requested
 4543+ } else if ( !this.length ) {
 4544+ return this;
 4545+ }
 4546+
 4547+ var off = url.indexOf(" ");
 4548+ if ( off >= 0 ) {
 4549+ var selector = url.slice(off, url.length);
 4550+ url = url.slice(0, off);
 4551+ }
 4552+
 4553+ // Default to a GET request
 4554+ var type = "GET";
 4555+
 4556+ // If the second parameter was provided
 4557+ if ( params ) {
 4558+ // If it's a function
 4559+ if ( jQuery.isFunction( params ) ) {
 4560+ // We assume that it's the callback
 4561+ callback = params;
 4562+ params = null;
 4563+
 4564+ // Otherwise, build a param string
 4565+ } else if ( typeof params === "object" ) {
 4566+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
 4567+ type = "POST";
 4568+ }
 4569+ }
 4570+
 4571+ // Request the remote document
 4572+ jQuery.ajax({
 4573+ url: url,
 4574+ type: type,
 4575+ dataType: "html",
 4576+ data: params,
 4577+ context:this,
 4578+ complete: function( res, status ) {
 4579+ // If successful, inject the HTML into all the matched elements
 4580+ if ( status === "success" || status === "notmodified" ) {
 4581+ // See if a selector was specified
 4582+ this.html( selector ?
 4583+ // Create a dummy div to hold the results
 4584+ jQuery("<div />")
 4585+ // inject the contents of the document in, removing the scripts
 4586+ // to avoid any 'Permission Denied' errors in IE
 4587+ .append(res.responseText.replace(rscript, ""))
 4588+
 4589+ // Locate the specified elements
 4590+ .find(selector) :
 4591+
 4592+ // If not, just inject the full result
 4593+ res.responseText );
 4594+ }
 4595+
 4596+ if ( callback ) {
 4597+ this.each( callback, [res.responseText, status, res] );
 4598+ }
 4599+ }
 4600+ });
 4601+
 4602+ return this;
 4603+ },
 4604+
 4605+ serialize: function() {
 4606+ return jQuery.param(this.serializeArray());
 4607+ },
 4608+ serializeArray: function() {
 4609+ return this.map(function() {
 4610+ return this.elements ? jQuery.makeArray(this.elements) : this;
 4611+ })
 4612+ .filter(function() {
 4613+ return this.name && !this.disabled &&
 4614+ (this.checked || rselectTextarea.test(this.nodeName) ||
 4615+ rinput.test(this.type));
 4616+ })
 4617+ .map(function( i, elem ) {
 4618+ var val = jQuery(this).val();
 4619+
 4620+ return val == null ?
 4621+ null :
 4622+ jQuery.isArray(val) ?
 4623+ jQuery.map( val, function( val, i ) {
 4624+ return { name: elem.name, value: val };
 4625+ }) :
 4626+ { name: elem.name, value: val };
 4627+ }).get();
 4628+ }
 4629+});
 4630+
 4631+// Attach a bunch of functions for handling common AJAX events
 4632+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
 4633+ jQuery.fn[o] = function( f ) {
 4634+ return this.bind(o, f);
 4635+ };
 4636+});
 4637+
 4638+jQuery.extend({
 4639+
 4640+ get: function( url, data, callback, type ) {
 4641+ // shift arguments if data argument was omited
 4642+ if ( jQuery.isFunction( data ) ) {
 4643+ type = type || callback;
 4644+ callback = data;
 4645+ data = null;
 4646+ }
 4647+
 4648+ return jQuery.ajax({
 4649+ type: "GET",
 4650+ url: url,
 4651+ data: data,
 4652+ success: callback,
 4653+ dataType: type
 4654+ });
 4655+ },
 4656+
 4657+ getScript: function( url, callback ) {
 4658+ return jQuery.get(url, null, callback, "script");
 4659+ },
 4660+
 4661+ getJSON: function( url, data, callback ) {
 4662+ return jQuery.get(url, data, callback, "json");
 4663+ },
 4664+
 4665+ post: function( url, data, callback, type ) {
 4666+ // shift arguments if data argument was omited
 4667+ if ( jQuery.isFunction( data ) ) {
 4668+ type = type || callback;
 4669+ callback = data;
 4670+ data = {};
 4671+ }
 4672+
 4673+ return jQuery.ajax({
 4674+ type: "POST",
 4675+ url: url,
 4676+ data: data,
 4677+ success: callback,
 4678+ dataType: type
 4679+ });
 4680+ },
 4681+
 4682+ ajaxSetup: function( settings ) {
 4683+ jQuery.extend( jQuery.ajaxSettings, settings );
 4684+ },
 4685+
 4686+ ajaxSettings: {
 4687+ url: location.href,
 4688+ global: true,
 4689+ type: "GET",
 4690+ contentType: "application/x-www-form-urlencoded",
 4691+ processData: true,
 4692+ async: true,
 4693+ /*
 4694+ timeout: 0,
 4695+ data: null,
 4696+ username: null,
 4697+ password: null,
 4698+ traditional: false,
 4699+ */
 4700+ // Create the request object; Microsoft failed to properly
 4701+ // implement the XMLHttpRequest in IE7 (can't request local files),
 4702+ // so we use the ActiveXObject when it is available
 4703+ // This function can be overriden by calling jQuery.ajaxSetup
 4704+ xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
 4705+ function() {
 4706+ return new window.XMLHttpRequest();
 4707+ } :
 4708+ function() {
 4709+ try {
 4710+ return new window.ActiveXObject("Microsoft.XMLHTTP");
 4711+ } catch(e) {}
 4712+ },
 4713+ accepts: {
 4714+ xml: "application/xml, text/xml",
 4715+ html: "text/html",
 4716+ script: "text/javascript, application/javascript",
 4717+ json: "application/json, text/javascript",
 4718+ text: "text/plain",
 4719+ _default: "*/*"
 4720+ }
 4721+ },
 4722+
 4723+ // Last-Modified header cache for next request
 4724+ lastModified: {},
 4725+ etag: {},
 4726+
 4727+ ajax: function( origSettings ) {
 4728+ var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
 4729+
 4730+ var jsonp, status, data,
 4731+ callbackContext = s.context || s,
 4732+ type = s.type.toUpperCase();
 4733+
 4734+ // convert data if not already a string
 4735+ if ( s.data && s.processData && typeof s.data !== "string" ) {
 4736+ s.data = jQuery.param( s.data, s.traditional );
 4737+ }
 4738+
 4739+ // Handle JSONP Parameter Callbacks
 4740+ if ( s.dataType === "jsonp" ) {
 4741+ if ( type === "GET" ) {
 4742+ if ( !jsre.test( s.url ) ) {
 4743+ s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
 4744+ }
 4745+ } else if ( !s.data || !jsre.test(s.data) ) {
 4746+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
 4747+ }
 4748+ s.dataType = "json";
 4749+ }
 4750+
 4751+ // Build temporary JSONP function
 4752+ if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
 4753+ jsonp = s.jsonpCallback || ("jsonp" + jsc++);
 4754+
 4755+ // Replace the =? sequence both in the query string and the data
 4756+ if ( s.data ) {
 4757+ s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
 4758+ }
 4759+
 4760+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
 4761+
 4762+ // We need to make sure
 4763+ // that a JSONP style response is executed properly
 4764+ s.dataType = "script";
 4765+
 4766+ // Handle JSONP-style loading
 4767+ window[ jsonp ] = window[ jsonp ] || function( tmp ) {
 4768+ data = tmp;
 4769+ success();
 4770+ complete();
 4771+ // Garbage collect
 4772+ window[ jsonp ] = undefined;
 4773+
 4774+ try {
 4775+ delete window[ jsonp ];
 4776+ } catch(e) {}
 4777+
 4778+ if ( head ) {
 4779+ head.removeChild( script );
 4780+ }
 4781+ };
 4782+ }
 4783+
 4784+ if ( s.dataType === "script" && s.cache === null ) {
 4785+ s.cache = false;
 4786+ }
 4787+
 4788+ if ( s.cache === false && type === "GET" ) {
 4789+ var ts = now();
 4790+
 4791+ // try replacing _= if it is there
 4792+ var ret = s.url.replace(rts, "$1_=" + ts + "$2");
 4793+
 4794+ // if nothing was replaced, add timestamp to the end
 4795+ s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
 4796+ }
 4797+
 4798+ // If data is available, append data to url for get requests
 4799+ if ( s.data && type === "GET" ) {
 4800+ s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
 4801+ }
 4802+
 4803+ // Watch for a new set of requests
 4804+ if ( s.global && ! jQuery.active++ ) {
 4805+ jQuery.event.trigger( "ajaxStart" );
 4806+ }
 4807+
 4808+ // Matches an absolute URL, and saves the domain
 4809+ var parts = rurl.exec( s.url ),
 4810+ remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
 4811+
 4812+ // If we're requesting a remote document
 4813+ // and trying to load JSON or Script with a GET
 4814+ if ( s.dataType === "script" && type === "GET" && remote ) {
 4815+ var head = document.getElementsByTagName("head")[0] || document.documentElement;
 4816+ var script = document.createElement("script");
 4817+ script.src = s.url;
 4818+ if ( s.scriptCharset ) {
 4819+ script.charset = s.scriptCharset;
 4820+ }
 4821+
 4822+ // Handle Script loading
 4823+ if ( !jsonp ) {
 4824+ var done = false;
 4825+
 4826+ // Attach handlers for all browsers
 4827+ script.onload = script.onreadystatechange = function() {
 4828+ if ( !done && (!this.readyState ||
 4829+ this.readyState === "loaded" || this.readyState === "complete") ) {
 4830+ done = true;
 4831+ success();
 4832+ complete();
 4833+
 4834+ // Handle memory leak in IE
 4835+ script.onload = script.onreadystatechange = null;
 4836+ if ( head && script.parentNode ) {
 4837+ head.removeChild( script );
 4838+ }
 4839+ }
 4840+ };
 4841+ }
 4842+
 4843+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
 4844+ // This arises when a base node is used (#2709 and #4378).
 4845+ head.insertBefore( script, head.firstChild );
 4846+
 4847+ // We handle everything using the script element injection
 4848+ return undefined;
 4849+ }
 4850+
 4851+ var requestDone = false;
 4852+
 4853+ // Create the request object
 4854+ var xhr = s.xhr();
 4855+
 4856+ if ( !xhr ) {
 4857+ return;
 4858+ }
 4859+
 4860+ // Open the socket
 4861+ // Passing null username, generates a login popup on Opera (#2865)
 4862+ if ( s.username ) {
 4863+ xhr.open(type, s.url, s.async, s.username, s.password);
 4864+ } else {
 4865+ xhr.open(type, s.url, s.async);
 4866+ }
 4867+
 4868+ // Need an extra try/catch for cross domain requests in Firefox 3
 4869+ try {
 4870+ // Set the correct header, if data is being sent
 4871+ if ( s.data || origSettings && origSettings.contentType ) {
 4872+ xhr.setRequestHeader("Content-Type", s.contentType);
 4873+ }
 4874+
 4875+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
 4876+ if ( s.ifModified ) {
 4877+ if ( jQuery.lastModified[s.url] ) {
 4878+ xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
 4879+ }
 4880+
 4881+ if ( jQuery.etag[s.url] ) {
 4882+ xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
 4883+ }
 4884+ }
 4885+
 4886+ // Set header so the called script knows that it's an XMLHttpRequest
 4887+ // Only send the header if it's not a remote XHR
 4888+ if ( !remote ) {
 4889+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
 4890+ }
 4891+
 4892+ // Set the Accepts header for the server, depending on the dataType
 4893+ xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
 4894+ s.accepts[ s.dataType ] + ", */*" :
 4895+ s.accepts._default );
 4896+ } catch(e) {}
 4897+
 4898+ // Allow custom headers/mimetypes and early abort
 4899+ if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
 4900+ // Handle the global AJAX counter
 4901+ if ( s.global && ! --jQuery.active ) {
 4902+ jQuery.event.trigger( "ajaxStop" );
 4903+ }
 4904+
 4905+ // close opended socket
 4906+ xhr.abort();
 4907+ return false;
 4908+ }
 4909+
 4910+ if ( s.global ) {
 4911+ trigger("ajaxSend", [xhr, s]);
 4912+ }
 4913+
 4914+ // Wait for a response to come back
 4915+ var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
 4916+ // The request was aborted
 4917+ if ( !xhr || xhr.readyState === 0 ) {
 4918+ // Opera doesn't call onreadystatechange before this point
 4919+ // so we simulate the call
 4920+ if ( !requestDone ) {
 4921+ complete();
 4922+ }
 4923+
 4924+ requestDone = true;
 4925+ if ( xhr ) {
 4926+ xhr.onreadystatechange = jQuery.noop;
 4927+ }
 4928+
 4929+ // The transfer is complete and the data is available, or the request timed out
 4930+ } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
 4931+ requestDone = true;
 4932+ xhr.onreadystatechange = jQuery.noop;
 4933+
 4934+ status = isTimeout === "timeout" ?
 4935+ "timeout" :
 4936+ !jQuery.httpSuccess( xhr ) ?
 4937+ "error" :
 4938+ s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
 4939+ "notmodified" :
 4940+ "success";
 4941+
 4942+ if ( status === "success" ) {
 4943+ // Watch for, and catch, XML document parse errors
 4944+ try {
 4945+ // process the data (runs the xml through httpData regardless of callback)
 4946+ data = jQuery.httpData( xhr, s.dataType, s );
 4947+ } catch(e) {
 4948+ status = "parsererror";
 4949+ }
 4950+ }
 4951+
 4952+ // Make sure that the request was successful or notmodified
 4953+ if ( status === "success" || status === "notmodified" ) {
 4954+ // JSONP handles its own success callback
 4955+ if ( !jsonp ) {
 4956+ success();
 4957+ }
 4958+ } else {
 4959+ jQuery.handleError(s, xhr, status);
 4960+ }
 4961+
 4962+ // Fire the complete handlers
 4963+ complete();
 4964+
 4965+ if ( isTimeout === "timeout" ) {
 4966+ xhr.abort();
 4967+ }
 4968+
 4969+ // Stop memory leaks
 4970+ if ( s.async ) {
 4971+ xhr = null;
 4972+ }
 4973+ }
 4974+ };
 4975+
 4976+ // Override the abort handler, if we can (IE doesn't allow it, but that's OK)
 4977+ // Opera doesn't fire onreadystatechange at all on abort
 4978+ try {
 4979+ var oldAbort = xhr.abort;
 4980+ xhr.abort = function() {
 4981+ if ( xhr ) {
 4982+ oldAbort.call( xhr );
 4983+ if ( xhr ) {
 4984+ xhr.readyState = 0;
 4985+ }
 4986+ }
 4987+
 4988+ onreadystatechange();
 4989+ };
 4990+ } catch(e) { }
 4991+
 4992+ // Timeout checker
 4993+ if ( s.async && s.timeout > 0 ) {
 4994+ setTimeout(function() {
 4995+ // Check to see if the request is still happening
 4996+ if ( xhr && !requestDone ) {
 4997+ onreadystatechange( "timeout" );
 4998+ }
 4999+ }, s.timeout);
 5000+ }
 5001+
 5002+ // Send the data
 5003+ try {
 5004+ xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
 5005+ } catch(e) {
 5006+ jQuery.handleError(s, xhr, null, e);
 5007+ // Fire the complete handlers
 5008+ complete();
 5009+ }
 5010+
 5011+ // firefox 1.5 doesn't fire statechange for sync requests
 5012+ if ( !s.async ) {
 5013+ onreadystatechange();
 5014+ }
 5015+
 5016+ function success() {
 5017+ // If a local callback was specified, fire it and pass it the data
 5018+ if ( s.success ) {
 5019+ s.success.call( callbackContext, data, status, xhr );
 5020+ }
 5021+
 5022+ // Fire the global callback
 5023+ if ( s.global ) {
 5024+ trigger( "ajaxSuccess", [xhr, s] );
 5025+ }
 5026+ }
 5027+
 5028+ function complete() {
 5029+ // Process result
 5030+ if ( s.complete ) {
 5031+ s.complete.call( callbackContext, xhr, status);
 5032+ }
 5033+
 5034+ // The request was completed
 5035+ if ( s.global ) {
 5036+ trigger( "ajaxComplete", [xhr, s] );
 5037+ }
 5038+
 5039+ // Handle the global AJAX counter
 5040+ if ( s.global && ! --jQuery.active ) {
 5041+ jQuery.event.trigger( "ajaxStop" );
 5042+ }
 5043+ }
 5044+
 5045+ function trigger(type, args) {
 5046+ (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
 5047+ }
 5048+
 5049+ // return XMLHttpRequest to allow aborting the request etc.
 5050+ return xhr;
 5051+ },
 5052+
 5053+ handleError: function( s, xhr, status, e ) {
 5054+ // If a local callback was specified, fire it
 5055+ if ( s.error ) {
 5056+ s.error.call( s.context || window, xhr, status, e );
 5057+ }
 5058+
 5059+ // Fire the global callback
 5060+ if ( s.global ) {
 5061+ (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
 5062+ }
 5063+ },
 5064+
 5065+ // Counter for holding the number of active queries
 5066+ active: 0,
 5067+
 5068+ // Determines if an XMLHttpRequest was successful or not
 5069+ httpSuccess: function( xhr ) {
 5070+ try {
 5071+ // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
 5072+ return !xhr.status && location.protocol === "file:" ||
 5073+ // Opera returns 0 when status is 304
 5074+ ( xhr.status >= 200 && xhr.status < 300 ) ||
 5075+ xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
 5076+ } catch(e) {}
 5077+
 5078+ return false;
 5079+ },
 5080+
 5081+ // Determines if an XMLHttpRequest returns NotModified
 5082+ httpNotModified: function( xhr, url ) {
 5083+ var lastModified = xhr.getResponseHeader("Last-Modified"),
 5084+ etag = xhr.getResponseHeader("Etag");
 5085+
 5086+ if ( lastModified ) {
 5087+ jQuery.lastModified[url] = lastModified;
 5088+ }
 5089+
 5090+ if ( etag ) {
 5091+ jQuery.etag[url] = etag;
 5092+ }
 5093+
 5094+ // Opera returns 0 when status is 304
 5095+ return xhr.status === 304 || xhr.status === 0;
 5096+ },
 5097+
 5098+ httpData: function( xhr, type, s ) {
 5099+ var ct = xhr.getResponseHeader("content-type") || "",
 5100+ xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
 5101+ data = xml ? xhr.responseXML : xhr.responseText;
 5102+
 5103+ if ( xml && data.documentElement.nodeName === "parsererror" ) {
 5104+ throw "parsererror";
 5105+ }
 5106+
 5107+ // Allow a pre-filtering function to sanitize the response
 5108+ // s is checked to keep backwards compatibility
 5109+ if ( s && s.dataFilter ) {
 5110+ data = s.dataFilter( data, type );
 5111+ }
 5112+
 5113+ // The filter can actually parse the response
 5114+ if ( typeof data === "string" ) {
 5115+ // Get the JavaScript object, if JSON is used.
 5116+ if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
 5117+ // Make sure the incoming data is actual JSON
 5118+ // Logic borrowed from http://json.org/json2.js
 5119+ if (/^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
 5120+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
 5121+ .replace(/(?:^|:|,)(?:\s*\[)+/g, ""))) {
 5122+
 5123+ // Try to use the native JSON parser first
 5124+ if ( window.JSON && window.JSON.parse ) {
 5125+ data = window.JSON.parse( data );
 5126+
 5127+ } else {
 5128+ data = (new Function("return " + data))();
 5129+ }
 5130+
 5131+ } else {
 5132+ throw "Invalid JSON: " + data;
 5133+ }
 5134+
 5135+ // If the type is "script", eval it in global context
 5136+ } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
 5137+ jQuery.globalEval( data );
 5138+ }
 5139+ }
 5140+
 5141+ return data;
 5142+ },
 5143+
 5144+ // Serialize an array of form elements or a set of
 5145+ // key/values into a query string
 5146+ param: function( a, traditional ) {
 5147+
 5148+ var s = [];
 5149+
 5150+ // Set traditional to true for jQuery <= 1.3.2 behavior.
 5151+ if ( traditional === undefined ) {
 5152+ traditional = jQuery.ajaxSettings.traditional;
 5153+ }
 5154+
 5155+ function add( key, value ) {
 5156+ // If value is a function, invoke it and return its value
 5157+ value = jQuery.isFunction(value) ? value() : value;
 5158+ s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
 5159+ }
 5160+
 5161+ // If an array was passed in, assume that it is an array of form elements.
 5162+ if ( jQuery.isArray(a) || a.jquery ) {
 5163+ // Serialize the form elements
 5164+ jQuery.each( a, function() {
 5165+ add( this.name, this.value );
 5166+ });
 5167+
 5168+ } else {
 5169+ // If traditional, encode the "old" way (the way 1.3.2 or older
 5170+ // did it), otherwise encode params recursively.
 5171+ jQuery.each( a, function buildParams( prefix, obj ) {
 5172+
 5173+ if ( jQuery.isArray(obj) ) {
 5174+ // Serialize array item.
 5175+ jQuery.each( obj, function( i, v ) {
 5176+ if ( traditional ) {
 5177+ // Treat each array item as a scalar.
 5178+ add( prefix, v );
 5179+ } else {
 5180+ // If array item is non-scalar (array or object), encode its
 5181+ // numeric index to resolve deserialization ambiguity issues.
 5182+ // Note that rack (as of 1.0.0) can't currently deserialize
 5183+ // nested arrays properly, and attempting to do so may cause
 5184+ // a server error. Possible fixes are to modify rack's
 5185+ // deserialization algorithm or to provide an option or flag
 5186+ // to force array serialization to be shallow.
 5187+ buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
 5188+ }
 5189+ });
 5190+
 5191+ } else if ( !traditional && obj != null && typeof obj === "object" ) {
 5192+ // Serialize object item.
 5193+ jQuery.each( obj, function( k, v ) {
 5194+ buildParams( prefix + "[" + k + "]", v );
 5195+ });
 5196+
 5197+ } else {
 5198+ // Serialize scalar item.
 5199+ add( prefix, obj );
 5200+ }
 5201+ });
 5202+ }
 5203+
 5204+ // Return the resulting serialization
 5205+ return s.join("&").replace(r20, "+");
 5206+ }
 5207+
 5208+});
 5209+var elemdisplay = {},
 5210+ rfxtypes = /toggle|show|hide/,
 5211+ rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
 5212+ timerId,
 5213+ fxAttrs = [
 5214+ // height animations
 5215+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
 5216+ // width animations
 5217+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
 5218+ // opacity animations
 5219+ [ "opacity" ]
 5220+ ];
 5221+
 5222+jQuery.fn.extend({
 5223+ show: function( speed, callback ) {
 5224+ if ( speed != null ) {
 5225+ return this.animate( genFx("show", 3), speed, callback);
 5226+
 5227+ } else {
 5228+ for ( var i = 0, l = this.length; i < l; i++ ) {
 5229+ var old = jQuery.data(this[i], "olddisplay");
 5230+
 5231+ this[i].style.display = old || "";
 5232+
 5233+ if ( jQuery.css(this[i], "display") === "none" ) {
 5234+ var nodeName = this[i].nodeName, display;
 5235+
 5236+ if ( elemdisplay[ nodeName ] ) {
 5237+ display = elemdisplay[ nodeName ];
 5238+
 5239+ } else {
 5240+ var elem = jQuery("<" + nodeName + " />").appendTo("body");
 5241+
 5242+ display = elem.css("display");
 5243+
 5244+ if ( display === "none" ) {
 5245+ display = "block";
 5246+ }
 5247+
 5248+ elem.remove();
 5249+
 5250+ elemdisplay[ nodeName ] = display;
 5251+ }
 5252+
 5253+ jQuery.data(this[i], "olddisplay", display);
 5254+ }
 5255+ }
 5256+
 5257+ // Set the display of the elements in a second loop
 5258+ // to avoid the constant reflow
 5259+ for ( var j = 0, k = this.length; j < k; j++ ) {
 5260+ this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
 5261+ }
 5262+
 5263+ return this;
 5264+ }
 5265+ },
 5266+
 5267+
 5268+
 5269+ hide: function( speed, callback ) {
 5270+ if ( speed != null ) {
 5271+ return this.animate( genFx("hide", 3), speed, callback);
 5272+
 5273+ } else {
 5274+ for ( var i = 0, l = this.length; i < l; i++ ) {
 5275+ var old = jQuery.data(this[i], "olddisplay");
 5276+ if ( !old && old !== "none" ) {
 5277+ jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
 5278+ }
 5279+ }
 5280+
 5281+ // Set the display of the elements in a second loop
 5282+ // to avoid the constant reflow
 5283+ for ( var j = 0, k = this.length; j < k; j++ ) {
 5284+ this[j].style.display = "none";
 5285+ }
 5286+
 5287+ return this;
 5288+ }
 5289+ },
 5290+
 5291+ // Save the old toggle function
 5292+ _toggle: jQuery.fn.toggle,
 5293+
 5294+ toggle: function( fn, fn2 ) {
 5295+ var bool = typeof fn === "boolean";
 5296+
 5297+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
 5298+ this._toggle.apply( this, arguments );
 5299+
 5300+ } else if ( fn == null || bool ) {
 5301+ this.each(function() {
 5302+ var state = bool ? fn : jQuery(this).is(":hidden");
 5303+ jQuery(this)[ state ? "show" : "hide" ]();
 5304+ });
 5305+
 5306+ } else {
 5307+ this.animate(genFx("toggle", 3), fn, fn2);
 5308+ }
 5309+
 5310+ return this;
 5311+ },
 5312+
 5313+ fadeTo: function( speed, to, callback ) {
 5314+ return this.filter(":hidden").css("opacity", 0).show().end()
 5315+ .animate({opacity: to}, speed, callback);
 5316+ },
 5317+
 5318+ animate: function( prop, speed, easing, callback ) {
 5319+ var optall = jQuery.speed(speed, easing, callback);
 5320+
 5321+ if ( jQuery.isEmptyObject( prop ) ) {
 5322+ return this.each( optall.complete );
 5323+ }
 5324+
 5325+ return this[ optall.queue === false ? "each" : "queue" ](function() {
 5326+ var opt = jQuery.extend({}, optall), p,
 5327+ hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
 5328+ self = this;
 5329+
 5330+ for ( p in prop ) {
 5331+ var name = p.replace(rdashAlpha, fcamelCase);
 5332+
 5333+ if ( p !== name ) {
 5334+ prop[ name ] = prop[ p ];
 5335+ delete prop[ p ];
 5336+ p = name;
 5337+ }
 5338+
 5339+ if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
 5340+ return opt.complete.call(this);
 5341+ }
 5342+
 5343+ if ( ( p === "height" || p === "width" ) && this.style ) {
 5344+ // Store display property
 5345+ opt.display = jQuery.css(this, "display");
 5346+
 5347+ // Make sure that nothing sneaks out
 5348+ opt.overflow = this.style.overflow;
 5349+ }
 5350+
 5351+ if ( jQuery.isArray( prop[p] ) ) {
 5352+ // Create (if needed) and add to specialEasing
 5353+ (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
 5354+ prop[p] = prop[p][0];
 5355+ }
 5356+ }
 5357+
 5358+ if ( opt.overflow != null ) {
 5359+ this.style.overflow = "hidden";
 5360+ }
 5361+
 5362+ opt.curAnim = jQuery.extend({}, prop);
 5363+
 5364+ jQuery.each( prop, function( name, val ) {
 5365+ var e = new jQuery.fx( self, opt, name );
 5366+
 5367+ if ( rfxtypes.test(val) ) {
 5368+ e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
 5369+
 5370+ } else {
 5371+ var parts = rfxnum.exec(val),
 5372+ start = e.cur(true) || 0;
 5373+
 5374+ if ( parts ) {
 5375+ var end = parseFloat( parts[2] ),
 5376+ unit = parts[3] || "px";
 5377+
 5378+ // We need to compute starting value
 5379+ if ( unit !== "px" ) {
 5380+ self.style[ name ] = (end || 1) + unit;
 5381+ start = ((end || 1) / e.cur(true)) * start;
 5382+ self.style[ name ] = start + unit;
 5383+ }
 5384+
 5385+ // If a +=/-= token was provided, we're doing a relative animation
 5386+ if ( parts[1] ) {
 5387+ end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
 5388+ }
 5389+
 5390+ e.custom( start, end, unit );
 5391+
 5392+ } else {
 5393+ e.custom( start, val, "" );
 5394+ }
 5395+ }
 5396+ });
 5397+
 5398+ // For JS strict compliance
 5399+ return true;
 5400+ });
 5401+ },
 5402+
 5403+ stop: function( clearQueue, gotoEnd ) {
 5404+ var timers = jQuery.timers;
 5405+
 5406+ if ( clearQueue ) {
 5407+ this.queue([]);
 5408+ }
 5409+
 5410+ this.each(function() {
 5411+ // go in reverse order so anything added to the queue during the loop is ignored
 5412+ for ( var i = timers.length - 1; i >= 0; i-- ) {
 5413+ if ( timers[i].elem === this ) {
 5414+ if (gotoEnd) {
 5415+ // force the next step to be the last
 5416+ timers[i](true);
 5417+ }
 5418+
 5419+ timers.splice(i, 1);
 5420+ }
 5421+ }
 5422+ });
 5423+
 5424+ // start the next in the queue if the last step wasn't forced
 5425+ if ( !gotoEnd ) {
 5426+ this.dequeue();
 5427+ }
 5428+
 5429+ return this;
 5430+ }
 5431+
 5432+});
 5433+
 5434+// Generate shortcuts for custom animations
 5435+jQuery.each({
 5436+ slideDown: genFx("show", 1),
 5437+ slideUp: genFx("hide", 1),
 5438+ slideToggle: genFx("toggle", 1),
 5439+ fadeIn: { opacity: "show" },
 5440+ fadeOut: { opacity: "hide" }
 5441+}, function( name, props ) {
 5442+ jQuery.fn[ name ] = function( speed, callback ) {
 5443+ return this.animate( props, speed, callback );
 5444+ };
 5445+});
 5446+
 5447+jQuery.extend({
 5448+ speed: function( speed, easing, fn ) {
 5449+ var opt = speed && typeof speed === "object" ? speed : {
 5450+ complete: fn || !fn && easing ||
 5451+ jQuery.isFunction( speed ) && speed,
 5452+ duration: speed,
 5453+ easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
 5454+ };
 5455+
 5456+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
 5457+ jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
 5458+
 5459+ // Queueing
 5460+ opt.old = opt.complete;
 5461+ opt.complete = function() {
 5462+ if ( opt.queue !== false ) {
 5463+ jQuery(this).dequeue();
 5464+ }
 5465+ if ( jQuery.isFunction( opt.old ) ) {
 5466+ opt.old.call( this );
 5467+ }
 5468+ };
 5469+
 5470+ return opt;
 5471+ },
 5472+
 5473+ easing: {
 5474+ linear: function( p, n, firstNum, diff ) {
 5475+ return firstNum + diff * p;
 5476+ },
 5477+ swing: function( p, n, firstNum, diff ) {
 5478+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
 5479+ }
 5480+ },
 5481+
 5482+ timers: [],
 5483+
 5484+ fx: function( elem, options, prop ) {
 5485+ this.options = options;
 5486+ this.elem = elem;
 5487+ this.prop = prop;
 5488+
 5489+ if ( !options.orig ) {
 5490+ options.orig = {};
 5491+ }
 5492+ }
 5493+
 5494+});
 5495+
 5496+jQuery.fx.prototype = {
 5497+ // Simple function for setting a style value
 5498+ update: function() {
 5499+ if ( this.options.step ) {
 5500+ this.options.step.call( this.elem, this.now, this );
 5501+ }
 5502+
 5503+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
 5504+
 5505+ // Set display property to block for height/width animations
 5506+ if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
 5507+ this.elem.style.display = "block";
 5508+ }
 5509+ },
 5510+
 5511+ // Get the current size
 5512+ cur: function( force ) {
 5513+ if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
 5514+ return this.elem[ this.prop ];
 5515+ }
 5516+
 5517+ var r = parseFloat(jQuery.css(this.elem, this.prop, force));
 5518+ return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
 5519+ },
 5520+
 5521+ // Start an animation from one number to another
 5522+ custom: function( from, to, unit ) {
 5523+ this.startTime = now();
 5524+ this.start = from;
 5525+ this.end = to;
 5526+ this.unit = unit || this.unit || "px";
 5527+ this.now = this.start;
 5528+ this.pos = this.state = 0;
 5529+
 5530+ var self = this;
 5531+ function t( gotoEnd ) {
 5532+ return self.step(gotoEnd);
 5533+ }
 5534+
 5535+ t.elem = this.elem;
 5536+
 5537+ if ( t() && jQuery.timers.push(t) && !timerId ) {
 5538+ timerId = setInterval(jQuery.fx.tick, 13);
 5539+ }
 5540+ },
 5541+
 5542+ // Simple 'show' function
 5543+ show: function() {
 5544+ // Remember where we started, so that we can go back to it later
 5545+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
 5546+ this.options.show = true;
 5547+
 5548+ // Begin the animation
 5549+ // Make sure that we start at a small width/height to avoid any
 5550+ // flash of content
 5551+ this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
 5552+
 5553+ // Start by showing the element
 5554+ jQuery( this.elem ).show();
 5555+ },
 5556+
 5557+ // Simple 'hide' function
 5558+ hide: function() {
 5559+ // Remember where we started, so that we can go back to it later
 5560+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
 5561+ this.options.hide = true;
 5562+
 5563+ // Begin the animation
 5564+ this.custom(this.cur(), 0);
 5565+ },
 5566+
 5567+ // Each step of an animation
 5568+ step: function( gotoEnd ) {
 5569+ var t = now(), done = true;
 5570+
 5571+ if ( gotoEnd || t >= this.options.duration + this.startTime ) {
 5572+ this.now = this.end;
 5573+ this.pos = this.state = 1;
 5574+ this.update();
 5575+
 5576+ this.options.curAnim[ this.prop ] = true;
 5577+
 5578+ for ( var i in this.options.curAnim ) {
 5579+ if ( this.options.curAnim[i] !== true ) {
 5580+ done = false;
 5581+ }
 5582+ }
 5583+
 5584+ if ( done ) {
 5585+ if ( this.options.display != null ) {
 5586+ // Reset the overflow
 5587+ this.elem.style.overflow = this.options.overflow;
 5588+
 5589+ // Reset the display
 5590+ var old = jQuery.data(this.elem, "olddisplay");
 5591+ this.elem.style.display = old ? old : this.options.display;
 5592+
 5593+ if ( jQuery.css(this.elem, "display") === "none" ) {
 5594+ this.elem.style.display = "block";
 5595+ }
 5596+ }
 5597+
 5598+ // Hide the element if the "hide" operation was done
 5599+ if ( this.options.hide ) {
 5600+ jQuery(this.elem).hide();
 5601+ }
 5602+
 5603+ // Reset the properties, if the item has been hidden or shown
 5604+ if ( this.options.hide || this.options.show ) {
 5605+ for ( var p in this.options.curAnim ) {
 5606+ jQuery.style(this.elem, p, this.options.orig[p]);
 5607+ }
 5608+ }
 5609+
 5610+ // Execute the complete function
 5611+ this.options.complete.call( this.elem );
 5612+ }
 5613+
 5614+ return false;
 5615+
 5616+ } else {
 5617+ var n = t - this.startTime;
 5618+ this.state = n / this.options.duration;
 5619+
 5620+ // Perform the easing function, defaults to swing
 5621+ var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
 5622+ var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
 5623+ this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
 5624+ this.now = this.start + ((this.end - this.start) * this.pos);
 5625+
 5626+ // Perform the next step of the animation
 5627+ this.update();
 5628+ }
 5629+
 5630+ return true;
 5631+ }
 5632+};
 5633+
 5634+jQuery.extend( jQuery.fx, {
 5635+ tick: function() {
 5636+ var timers = jQuery.timers;
 5637+
 5638+ for ( var i = 0; i < timers.length; i++ ) {
 5639+ if ( !timers[i]() ) {
 5640+ timers.splice(i--, 1);
 5641+ }
 5642+ }
 5643+
 5644+ if ( !timers.length ) {
 5645+ jQuery.fx.stop();
 5646+ }
 5647+ },
 5648+
 5649+ stop: function() {
 5650+ clearInterval( timerId );
 5651+ timerId = null;
 5652+ },
 5653+
 5654+ speeds: {
 5655+ slow: 600,
 5656+ fast: 200,
 5657+ // Default speed
 5658+ _default: 400
 5659+ },
 5660+
 5661+ step: {
 5662+ opacity: function( fx ) {
 5663+ jQuery.style(fx.elem, "opacity", fx.now);
 5664+ },
 5665+
 5666+ _default: function( fx ) {
 5667+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
 5668+ fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
 5669+ } else {
 5670+ fx.elem[ fx.prop ] = fx.now;
 5671+ }
 5672+ }
 5673+ }
 5674+});
 5675+
 5676+if ( jQuery.expr && jQuery.expr.filters ) {
 5677+ jQuery.expr.filters.animated = function( elem ) {
 5678+ return jQuery.grep(jQuery.timers, function( fn ) {
 5679+ return elem === fn.elem;
 5680+ }).length;
 5681+ };
 5682+}
 5683+
 5684+function genFx( type, num ) {
 5685+ var obj = {};
 5686+
 5687+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
 5688+ obj[ this ] = type;
 5689+ });
 5690+
 5691+ return obj;
 5692+}
 5693+if ( "getBoundingClientRect" in document.documentElement ) {
 5694+ jQuery.fn.offset = function( options ) {
 5695+ var elem = this[0];
 5696+
 5697+ if ( !elem || !elem.ownerDocument ) {
 5698+ return null;
 5699+ }
 5700+
 5701+ if ( options ) {
 5702+ return this.each(function( i ) {
 5703+ jQuery.offset.setOffset( this, options, i );
 5704+ });
 5705+ }
 5706+
 5707+ if ( elem === elem.ownerDocument.body ) {
 5708+ return jQuery.offset.bodyOffset( elem );
 5709+ }
 5710+
 5711+ var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
 5712+ clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
 5713+ top = box.top + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
 5714+ left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
 5715+
 5716+ return { top: top, left: left };
 5717+ };
 5718+
 5719+} else {
 5720+ jQuery.fn.offset = function( options ) {
 5721+ var elem = this[0];
 5722+
 5723+ if ( !elem || !elem.ownerDocument ) {
 5724+ return null;
 5725+ }
 5726+
 5727+ if ( options ) {
 5728+ return this.each(function( i ) {
 5729+ jQuery.offset.setOffset( this, options, i );
 5730+ });
 5731+ }
 5732+
 5733+ if ( elem === elem.ownerDocument.body ) {
 5734+ return jQuery.offset.bodyOffset( elem );
 5735+ }
 5736+
 5737+ jQuery.offset.initialize();
 5738+
 5739+ var offsetParent = elem.offsetParent, prevOffsetParent = elem,
 5740+ doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
 5741+ body = doc.body, defaultView = doc.defaultView,
 5742+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
 5743+ top = elem.offsetTop, left = elem.offsetLeft;
 5744+
 5745+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
 5746+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
 5747+ break;
 5748+ }
 5749+
 5750+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
 5751+ top -= elem.scrollTop;
 5752+ left -= elem.scrollLeft;
 5753+
 5754+ if ( elem === offsetParent ) {
 5755+ top += elem.offsetTop;
 5756+ left += elem.offsetLeft;
 5757+
 5758+ if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
 5759+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
 5760+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
 5761+ }
 5762+
 5763+ prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
 5764+ }
 5765+
 5766+ if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
 5767+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
 5768+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
 5769+ }
 5770+
 5771+ prevComputedStyle = computedStyle;
 5772+ }
 5773+
 5774+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
 5775+ top += body.offsetTop;
 5776+ left += body.offsetLeft;
 5777+ }
 5778+
 5779+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
 5780+ top += Math.max( docElem.scrollTop, body.scrollTop );
 5781+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
 5782+ }
 5783+
 5784+ return { top: top, left: left };
 5785+ };
 5786+}
 5787+
 5788+jQuery.offset = {
 5789+ initialize: function() {
 5790+ var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
 5791+ html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
 5792+
 5793+ jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
 5794+
 5795+ container.innerHTML = html;
 5796+ body.insertBefore( container, body.firstChild );
 5797+ innerDiv = container.firstChild;
 5798+ checkDiv = innerDiv.firstChild;
 5799+ td = innerDiv.nextSibling.firstChild.firstChild;
 5800+
 5801+ this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
 5802+ this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
 5803+
 5804+ checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
 5805+ // safari subtracts parent border width here which is 5px
 5806+ this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
 5807+ checkDiv.style.position = checkDiv.style.top = "";
 5808+
 5809+ innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
 5810+ this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
 5811+
 5812+ this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
 5813+
 5814+ body.removeChild( container );
 5815+ body = container = innerDiv = checkDiv = table = td = null;
 5816+ jQuery.offset.initialize = jQuery.noop;
 5817+ },
 5818+
 5819+ bodyOffset: function( body ) {
 5820+ var top = body.offsetTop, left = body.offsetLeft;
 5821+
 5822+ jQuery.offset.initialize();
 5823+
 5824+ if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
 5825+ top += parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0;
 5826+ left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
 5827+ }
 5828+
 5829+ return { top: top, left: left };
 5830+ },
 5831+
 5832+ setOffset: function( elem, options, i ) {
 5833+ // set position first, in-case top/left are set even on static elem
 5834+ if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
 5835+ elem.style.position = "relative";
 5836+ }
 5837+ var curElem = jQuery( elem ),
 5838+ curOffset = curElem.offset(),
 5839+ curTop = parseInt( jQuery.curCSS( elem, "top", true ), 10 ) || 0,
 5840+ curLeft = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
 5841+
 5842+ if ( jQuery.isFunction( options ) ) {
 5843+ options = options.call( elem, i, curOffset );
 5844+ }
 5845+
 5846+ var props = {
 5847+ top: (options.top - curOffset.top) + curTop,
 5848+ left: (options.left - curOffset.left) + curLeft
 5849+ };
 5850+
 5851+ if ( "using" in options ) {
 5852+ options.using.call( elem, props );
 5853+ } else {
 5854+ curElem.css( props );
 5855+ }
 5856+ }
 5857+};
 5858+
 5859+
 5860+jQuery.fn.extend({
 5861+ position: function() {
 5862+ if ( !this[0] ) {
 5863+ return null;
 5864+ }
 5865+
 5866+ var elem = this[0],
 5867+
 5868+ // Get *real* offsetParent
 5869+ offsetParent = this.offsetParent(),
 5870+
 5871+ // Get correct offsets
 5872+ offset = this.offset(),
 5873+ parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
 5874+
 5875+ // Subtract element margins
 5876+ // note: when an element has margin: auto the offsetLeft and marginLeft
 5877+ // are the same in Safari causing offset.left to incorrectly be 0
 5878+ offset.top -= parseFloat( jQuery.curCSS(elem, "marginTop", true) ) || 0;
 5879+ offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
 5880+
 5881+ // Add offsetParent borders
 5882+ parentOffset.top += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth", true) ) || 0;
 5883+ parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
 5884+
 5885+ // Subtract the two offsets
 5886+ return {
 5887+ top: offset.top - parentOffset.top,
 5888+ left: offset.left - parentOffset.left
 5889+ };
 5890+ },
 5891+
 5892+ offsetParent: function() {
 5893+ return this.map(function() {
 5894+ var offsetParent = this.offsetParent || document.body;
 5895+ while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
 5896+ offsetParent = offsetParent.offsetParent;
 5897+ }
 5898+ return offsetParent;
 5899+ });
 5900+ }
 5901+});
 5902+
 5903+
 5904+// Create scrollLeft and scrollTop methods
 5905+jQuery.each( ["Left", "Top"], function( i, name ) {
 5906+ var method = "scroll" + name;
 5907+
 5908+ jQuery.fn[ method ] = function(val) {
 5909+ var elem = this[0], win;
 5910+
 5911+ if ( !elem ) {
 5912+ return null;
 5913+ }
 5914+
 5915+ if ( val !== undefined ) {
 5916+ // Set the scroll offset
 5917+ return this.each(function() {
 5918+ win = getWindow( this );
 5919+
 5920+ if ( win ) {
 5921+ win.scrollTo(
 5922+ !i ? val : jQuery(win).scrollLeft(),
 5923+ i ? val : jQuery(win).scrollTop()
 5924+ );
 5925+
 5926+ } else {
 5927+ this[ method ] = val;
 5928+ }
 5929+ });
 5930+ } else {
 5931+ win = getWindow( elem );
 5932+
 5933+ // Return the scroll offset
 5934+ return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
 5935+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
 5936+ win.document.body[ method ] :
 5937+ elem[ method ];
 5938+ }
 5939+ };
 5940+});
 5941+
 5942+function getWindow( elem ) {
 5943+ return ("scrollTo" in elem && elem.document) ?
 5944+ elem :
 5945+ elem.nodeType === 9 ?
 5946+ elem.defaultView || elem.parentWindow :
 5947+ false;
 5948+}
 5949+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
 5950+jQuery.each([ "Height", "Width" ], function( i, name ) {
 5951+
 5952+ var type = name.toLowerCase();
 5953+
 5954+ // innerHeight and innerWidth
 5955+ jQuery.fn["inner" + name] = function() {
 5956+ return this[0] ?
 5957+ jQuery.css( this[0], type, false, "padding" ) :
 5958+ null;
 5959+ };
 5960+
 5961+ // outerHeight and outerWidth
 5962+ jQuery.fn["outer" + name] = function( margin ) {
 5963+ return this[0] ?
 5964+ jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
 5965+ null;
 5966+ };
 5967+
 5968+ jQuery.fn[ type ] = function( size ) {
 5969+ // Get window width or height
 5970+ var elem = this[0];
 5971+ if ( !elem ) {
 5972+ return size == null ? null : this;
 5973+ }
 5974+
 5975+ return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
 5976+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
 5977+ elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
 5978+ elem.document.body[ "client" + name ] :
 5979+
 5980+ // Get document width or height
 5981+ (elem.nodeType === 9) ? // is it a document
 5982+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
 5983+ Math.max(
 5984+ elem.documentElement["client" + name],
 5985+ elem.body["scroll" + name], elem.documentElement["scroll" + name],
 5986+ elem.body["offset" + name], elem.documentElement["offset" + name]
 5987+ ) :
 5988+
 5989+ // Get or set width or height on the element
 5990+ size === undefined ?
 5991+ // Get width or height on the element
 5992+ jQuery.css( elem, type ) :
 5993+
 5994+ // Set the width or height on the element (default to pixels if value is unitless)
 5995+ this.css( type, typeof size === "string" ? size : size + "px" );
 5996+ };
 5997+
 5998+});
 5999+// Expose jQuery to the global object
 6000+window.jQuery = window.$ = jQuery;
 6001+
 6002+})(window);
\ No newline at end of file
Property changes on: trunk/extensions/Ratings/starrating/star-rating/jquery.js
___________________________________________________________________
Added: svn:eol-style
16003 + native
Index: trunk/extensions/Ratings/starrating/star-rating/jquery.rating.pack.js
@@ -0,0 +1,11 @@
 2+/*
 3+ ### jQuery Star Rating Plugin v3.13 - 2009-03-26 ###
 4+ * Home: http://www.fyneworks.com/jquery/star-rating/
 5+ * Code: http://code.google.com/p/jquery-star-rating-plugin/
 6+ *
 7+ * Dual licensed under the MIT and GPL licenses:
 8+ * http://www.opensource.org/licenses/mit-license.php
 9+ * http://www.gnu.org/licenses/gpl.html
 10+ ###
 11+*/
 12+eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}(';5(29.1j)(7($){5($.1L.1J)1I{1t.1H("1K",J,H)}1M(e){};$.n.3=7(i){5(4.Q==0)k 4;5(A I[0]==\'1h\'){5(4.Q>1){8 j=I;k 4.W(7(){$.n.3.y($(4),j)})};$.n.3[I[0]].y(4,$.1T(I).1U(1)||[]);k 4};8 i=$.12({},$.n.3.1s,i||{});$.n.3.K++;4.2a(\'.9-3-1f\').o(\'9-3-1f\').W(7(){8 a,l=$(4);8 b=(4.23||\'21-3\').1v(/\\[|\\]/g,\'Z\').1v(/^\\Z+|\\Z+$/g,\'\');8 c=$(4.1X||1t.1W);8 d=c.6(\'3\');5(!d||d.18!=$.n.3.K)d={z:0,18:$.n.3.K};8 e=d[b];5(e)a=e.6(\'3\');5(e&&a)a.z++;x{a=$.12({},i||{},($.1b?l.1b():($.1S?l.6():s))||{},{z:0,F:[],v:[]});a.w=d.z++;e=$(\'<1R V="9-3-1Q"/>\');l.1P(e);e.o(\'3-15-T-17\');5(l.S(\'R\'))a.m=H;e.1c(a.E=$(\'<P V="3-E"><a 14="\'+a.E+\'">\'+a.1d+\'</a></P>\').1g(7(){$(4).3(\'O\');$(4).o(\'9-3-N\')}).1i(7(){$(4).3(\'u\');$(4).G(\'9-3-N\')}).1l(7(){$(4).3(\'r\')}).6(\'3\',a))};8 f=$(\'<P V="9-3 q-\'+a.w+\'"><a 14="\'+(4.14||4.1p)+\'">\'+4.1p+\'</a></P>\');e.1c(f);5(4.11)f.S(\'11\',4.11);5(4.1r)f.o(4.1r);5(a.1F)a.t=2;5(A a.t==\'1u\'&&a.t>0){8 g=($.n.10?f.10():0)||a.1w;8 h=(a.z%a.t),Y=1y.1z(g/a.t);f.10(Y).1A(\'a\').1B({\'1C-1D\':\'-\'+(h*Y)+\'1E\'})};5(a.m)f.o(\'9-3-1o\');x f.o(\'9-3-1G\').1g(7(){$(4).3(\'1n\');$(4).3(\'D\')}).1i(7(){$(4).3(\'u\');$(4).3(\'C\')}).1l(7(){$(4).3(\'r\')});5(4.L)a.p=f;l.1q();l.1N(7(){$(4).3(\'r\')});f.6(\'3.l\',l.6(\'3.9\',f));a.F[a.F.Q]=f[0];a.v[a.v.Q]=l[0];a.q=d[b]=e;a.1O=c;l.6(\'3\',a);e.6(\'3\',a);f.6(\'3\',a);c.6(\'3\',d)});$(\'.3-15-T-17\').3(\'u\').G(\'3-15-T-17\');k 4};$.12($.n.3,{K:0,D:7(){8 a=4.6(\'3\');5(!a)k 4;5(!a.D)k 4;8 b=$(4).6(\'3.l\')||$(4.U==\'13\'?4:s);5(a.D)a.D.y(b[0],[b.M(),$(\'a\',b.6(\'3.9\'))[0]])},C:7(){8 a=4.6(\'3\');5(!a)k 4;5(!a.C)k 4;8 b=$(4).6(\'3.l\')||$(4.U==\'13\'?4:s);5(a.C)a.C.y(b[0],[b.M(),$(\'a\',b.6(\'3.9\'))[0]])},1n:7(){8 a=4.6(\'3\');5(!a)k 4;5(a.m)k;4.3(\'O\');4.1a().19().X(\'.q-\'+a.w).o(\'9-3-N\')},O:7(){8 a=4.6(\'3\');5(!a)k 4;5(a.m)k;a.q.1V().X(\'.q-\'+a.w).G(\'9-3-1k\').G(\'9-3-N\')},u:7(){8 a=4.6(\'3\');5(!a)k 4;4.3(\'O\');5(a.p){a.p.6(\'3.l\').S(\'L\',\'L\');a.p.1a().19().X(\'.q-\'+a.w).o(\'9-3-1k\')}x $(a.v).1m(\'L\');a.E[a.m||a.1Y?\'1q\':\'1Z\']();4.20()[a.m?\'o\':\'G\'](\'9-3-1o\')},r:7(a,b){8 c=4.6(\'3\');5(!c)k 4;5(c.m)k;c.p=s;5(A a!=\'B\'){5(A a==\'1u\')k $(c.F[a]).3(\'r\',B,b);5(A a==\'1h\')$.W(c.F,7(){5($(4).6(\'3.l\').M()==a)$(4).3(\'r\',B,b)})}x c.p=4[0].U==\'13\'?4.6(\'3.9\'):(4.22(\'.q-\'+c.w)?4:s);4.6(\'3\',c);4.3(\'u\');8 d=$(c.p?c.p.6(\'3.l\'):s);5((b||b==B)&&c.1e)c.1e.y(d[0],[d.M(),$(\'a\',c.p)[0]])},m:7(a,b){8 c=4.6(\'3\');5(!c)k 4;c.m=a||a==B?H:J;5(b)$(c.v).S("R","R");x $(c.v).1m("R");4.6(\'3\',c);4.3(\'u\')},1x:7(){4.3(\'m\',H,H)},24:7(){4.3(\'m\',J,J)}});$.n.3.1s={E:\'25 26\',1d:\'\',t:0,1w:16};$(7(){$(\'l[27=28].9\').3()})})(1j);',62,135,'|||rating|this|if|data|function|var|star|||||||||||return|input|readOnly|fn|addClass|current|rater|select|null|split|draw|inputs|serial|else|apply|count|typeof|undefined|blur|focus|cancel|stars|removeClass|true|arguments|false|calls|checked|val|hover|drain|div|length|disabled|attr|be|tagName|class|each|filter|spw|_|width|id|extend|INPUT|title|to||drawn|call|andSelf|prevAll|metadata|append|cancelValue|callback|applied|mouseover|string|mouseout|jQuery|on|click|removeAttr|fill|readonly|value|hide|className|options|document|number|replace|starWidth|disable|Math|floor|find|css|margin|left|px|half|live|execCommand|try|msie|BackgroundImageCache|browser|catch|change|context|before|control|span|meta|makeArray|slice|children|body|form|required|show|siblings|unnamed|is|name|enable|Cancel|Rating|type|radio|window|not'.split('|'),0,{}))
\ No newline at end of file
Property changes on: trunk/extensions/Ratings/starrating/star-rating/jquery.rating.pack.js
___________________________________________________________________
Added: svn:eol-style
113 + native
Index: trunk/extensions/Ratings/starrating/star-rating/documentation.html
@@ -0,0 +1,1169 @@
 2+<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
 3+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 4+<head>
 5+ <title>jQuery Star Rating Plugin v3.13 (2009-03-26)</title>
 6+ <!--// documentation resources //-->
 7+ <script src='jquery.js' type="text/javascript"></script>
 8+ <script src='documentation.js' type="text/javascript"></script>
 9+ <link href='documentation.css' type="text/css" rel="stylesheet"/>
 10+ <!--// code-highlighting //-->
 11+ <script type="text/javaScript" src="/jquery/project/chili/jquery.chili-2.0.js"></script>
 12+ <!--///jquery/project/chili-toolbar/jquery.chili-toolbar.pack.js//-->
 13+ <script type="text/javascript">try{ChiliBook.recipeFolder="/jquery/project/chili/"}catch(e){}</script>
 14+ <!--// plugin-specific resources //-->
 15+ <script src='jquery.MetaData.js' type="text/javascript" language="javascript"></script>
 16+ <script src='jquery.rating.js' type="text/javascript" language="javascript"></script>
 17+ <link href='jquery.rating.css' type="text/css" rel="stylesheet"/>
 18+</head>
 19+<body>
 20+<a name="top"></a>
 21+<div id="wrap">
 22+ <div id="roof">
 23+ <a href="http://www.fyneworks.com/jquery/"><strong>jQuery Plugins</strong></a>:
 24+ <a href="http://www.fyneworks.com/jquery/multiple-file-upload/">Multiple File Upload</a>,
 25+ <a href="http://www.fyneworks.com/jquery/star-rating/">Star Rating</a>,
 26+ <strong>NEW:</strong>
 27+ <a href="http://www.fyneworks.com/jquery/CKEditor/">CKEditor</a>
 28+ (old: <a href="http://www.fyneworks.com/jquery/FCKEditor/">FCKEditor</a>),
 29+ <a href="http://www.fyneworks.com/jquery/Codepress/">Codepress</a>,
 30+ <a href="http://www.fyneworks.com/jquery/xml-to-json/">XML to JSON</a>
 31+ <span style="position:absolute; right:0;">
 32+ <script type="text/javascript">digg_title='jQuery Star Rating Plugin';</script>
 33+ <script type="text/javascript">digg_url='http://www.fyneworks.com/jquery/star-rating/';</script>
 34+ <script type="text/javascript">digg_bgcolor='#e7e7e7';digg_skin='compact';digg_window='new';</script>
 35+ <script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script>
 36+ </span>
 37+ </div>
 38+ <div id="head">
 39+ <table width="100%" cellspacing="5">
 40+ <tr>
 41+ <td valign="middle">
 42+ <h1>jQuery Star Rating Plugin</h1>
 43+ <span style="cursor:help; background:#C00; padding:2px; color:#FFF;" title="Current Version">
 44+ v<strong>3.13</strong>
 45+ </span>
 46+ </td>
 47+ <td valign="middle" width="450" align="right">
 48+ <div id="search" style="display:none">
 49+ <form action="http://www.google.com/cse" id="cse-search-box" target="_blank">
 50+ <label for="q">Find another jQuery plugin:</label>
 51+ <input type="hidden" name="cx" value="partner-pub-9465008056978568:j3ebzr-v1o0" />
 52+ <input type="hidden" name="ie" value="ISO-8859-1" />
 53+ <input type="text" name="q" id="q" size="20" />
 54+ <input type="submit" name="sa" value="Search" />
 55+ </form>
 56+ <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;lang=en"></script>
 57+ </div>
 58+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
 59+ <input type="hidden" name="cmd" value="_s-xclick">
 60+ <input type="hidden" name="hosted_button_id" value="6856904">
 61+ <input type="image" src="https://www.paypal.com/en_GB/i/btn/btn_donate_SM.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
 62+ <img alt="" border="0" src="https://www.paypal.com/en_GB/i/scr/pixel.gif" width="1" height="1">
 63+ </form>
 64+ </td>
 65+ </tr>
 66+ </table>
 67+ </div>
 68+ <div id="body">
 69+
 70+ <div id="ad">
 71+ <!--//
 72+ <div id='vu_ytplayer_vjVQa1PpcFNzWL_xJNUOpZhjtZP7PE8aGHuLQqHHrFI='><a href='http://www.youtube.com/browse'>Watch the latest videos on YouTube.com</a></div>
 73+ <script type='text/javascript' src='http://www.youtube.com/watch_custom_player?id=vjVQa1PpcFNzWL_xJNUOpZhjtZP7PE8aGHuLQqHHrFI='></script>
 74+ //-->
 75+<script type="text/javascript"><!--
 76+google_ad_client = "pub-9465008056978568";
 77+/* 120x600, created 25/11/09 */
 78+google_ad_slot = "4176621808";
 79+google_ad_width = 120;
 80+google_ad_height = 600;
 81+//-->
 82+</script>
 83+<script type="text/javascript"
 84+src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
 85+</script>
 86+ </div>
 87+
 88+ <div id="documentation" class="tabs">
 89+ <ul class="Clear">
 90+ <li><a href="#tab-Overview" id="btn-Overview">Intro</a></li>
 91+ <li><a href="#tab-Testing" id="btn-Testing">Demos</a></li>
 92+ <li><a href="#tab-API" id="btn-API">API</a></li>
 93+ <li><a href="#tab-Database" id="btn-Database">Database Integration</a></li>
 94+ <li><a href="#tab-Background" id="btn-Background">Background</a></li>
 95+ <li><a href="#tab-Download" id="btn-Download">Download</a></li>
 96+ <li><a href="#tab-Support" id="btn-Support">Support</a></li>
 97+ <li><a href="#tab-License" id="btn-License">License</a></li>
 98+ </ul><!--// tabs //-->
 99+ <!--//
 100+ ####################################
 101+ #
 102+ # * START CONTENT *
 103+ #
 104+ ####################################
 105+ //-->
 106+
 107+
 108+
 109+
 110+
 111+ <div id="tab-Overview">
 112+ <h2>What is this?</h2>
 113+ <p>
 114+ The <strong>Star Rating Plugin</strong> is a plugin
 115+ for the jQuery Javascript library that creates a non-obstrusive
 116+ star rating control based on a set of radio input boxes.
 117+ </p>
 118+
 119+ <h2>What does it do?</h2>
 120+ <ul>
 121+ <li>
 122+ It turns a collection of radio boxes into a neat star-rating control.
 123+ </li>
 124+ <li>
 125+ It creates the interface based on standard form elements, which means the
 126+ basic functionality will still be available even if Javascript is disabled.
 127+ </li>
 128+ <li>
 129+ <strong style="color: rgb(0, 153, 0);">NEW</strong> (12-Mar-08):
 130+ In read only mode (using the 'readOnly' option or <code>disabled</code> property), the plugin is a neat way of
 131+ displaying star-like values without any additional code
 132+ </li>
 133+ </ul>
 134+
 135+ <h2>How do I use it?</h2>
 136+ <p>
 137+ Just add the <code><strong>star</strong></code> class to your radio boxes
 138+ </p>
 139+ <table cellspacing="5" width="100%">
 140+ <tr>
 141+ <td valign="top">
 142+ <pre class="code"><code class="html">&lt;input name="star1" type="radio" class="star"/&gt;
 143+&lt;input name="star1" type="radio" class="star"/&gt;
 144+&lt;input name="star1" type="radio" class="star"/&gt;
 145+&lt;input name="star1" type="radio" class="star"/&gt;
 146+&lt;input name="star1" type="radio" class="star"/&gt;</code></pre>
 147+ </td>
 148+ <td valign="top" width="10">&raquo;</td>
 149+ <td valign="top" width="180">
 150+ <input name="star1" type="radio" class="star"/>
 151+ <input name="star1" type="radio" class="star"/>
 152+ <input name="star1" type="radio" class="star"/>
 153+ <input name="star1" type="radio" class="star"/>
 154+ <input name="star1" type="radio" class="star"/>
 155+ </td>
 156+ </tr>
 157+ </table>
 158+
 159+ <p>
 160+ Use the <code><strong>checked</strong></code> property to specify the initial/default value of the control
 161+ </p>
 162+ <table cellspacing="5" width="100%">
 163+ <tr>
 164+ <td valign="top">
 165+ <pre class="code"><code class="html">&lt;input name="star2" type="radio" class="star"/&gt;
 166+&lt;input name="star2" type="radio" class="star"/&gt;
 167+&lt;input name="star2" type="radio" class="star" checked="checked"/&gt;
 168+&lt;input name="star2" type="radio" class="star"/&gt;
 169+&lt;input name="star2" type="radio" class="star"/&gt;</code></pre>
 170+ </td>
 171+ <td valign="top" width="10">&raquo;</td>
 172+ <td valign="top" width="180">
 173+ <input name="star2" type="radio" class="star"/>
 174+ <input name="star2" type="radio" class="star"/>
 175+ <input name="star2" type="radio" class="star" checked="checked"/>
 176+ <input name="star2" type="radio" class="star"/>
 177+ <input name="star2" type="radio" class="star"/>
 178+ </td>
 179+ </tr>
 180+ </table>
 181+
 182+ <p>
 183+ Use the <code><strong>disabled</strong></code> property to use a control for display purposes only
 184+ </p>
 185+ <table cellspacing="5" width="100%">
 186+ <tr>
 187+ <td valign="top">
 188+ <pre class="code"><code class="html">&lt;input name="star3" type="radio" class="star" disabled="disabled"/&gt;
 189+&lt;input name="star3" type="radio" class="star" disabled="disabled"/&gt;
 190+&lt;input name="star3" type="radio" class="star" disabled="disabled" checked="checked"/&gt;
 191+&lt;input name="star3" type="radio" class="star" disabled="disabled"/&gt;
 192+&lt;input name="star3" type="radio" class="star" disabled="disabled"/&gt;</code></pre>
 193+ </td>
 194+ <td valign="top" width="10">&raquo;</td>
 195+ <td valign="top" width="180">
 196+ <input name="star3" type="radio" class="star" disabled="disabled"/>
 197+ <input name="star3" type="radio" class="star" disabled="disabled"/>
 198+ <input name="star3" type="radio" class="star" disabled="disabled" checked="checked"/>
 199+ <input name="star3" type="radio" class="star" disabled="disabled"/>
 200+ <input name="star3" type="radio" class="star" disabled="disabled"/>
 201+ </td>
 202+ </tr>
 203+ </table>
 204+
 205+ <h2>What about split stars and 'half ratings'???</h2>
 206+ <p>
 207+ Use metadata plugin to pass advanced settings to the plugin via the class property.
 208+ </p>
 209+ <table cellspacing="5" width="100%">
 210+ <tr>
 211+ <td valign="top">
 212+ <pre class="code"><code class="html">&lt;input name="adv1" type="radio" class="star {split:4}"/&gt;
 213+&lt;input name="adv1" type="radio" class="star {split:4}"/&gt;
 214+&lt;input name="adv1" type="radio" class="star {split:4}"/&gt;
 215+&lt;input name="adv1" type="radio" class="star {split:4}"/&gt;
 216+&lt;input name="adv1" type="radio" class="star {split:4}" checked="checked"/&gt;
 217+&lt;input name="adv1" type="radio" class="star {split:4}"/&gt;
 218+&lt;input name="adv1" type="radio" class="star {split:4}"/&gt;
 219+&lt;input name="adv1" type="radio" class="star {split:4}"/&gt;</code></pre>
 220+ </td>
 221+ <td valign="top" width="10">&raquo;</td>
 222+ <td valign="top" width="180">
 223+ <input name="adv1" type="radio" class="star {split:4}"/>
 224+ <input name="adv1" type="radio" class="star {split:4}"/>
 225+ <input name="adv1" type="radio" class="star {split:4}"/>
 226+ <input name="adv1" type="radio" class="star {split:4}"/>
 227+ <input name="adv1" type="radio" class="star {split:4}" checked="checked"/>
 228+ <input name="adv1" type="radio" class="star {split:4}"/>
 229+ <input name="adv1" type="radio" class="star {split:4}"/>
 230+ <input name="adv1" type="radio" class="star {split:4}"/>
 231+ </td>
 232+ </tr>
 233+ </table>
 234+
 235+ <p>
 236+ Use custom selector
 237+ </p>
 238+ <table cellspacing="5" width="100%">
 239+ <tr>
 240+ <td valign="top">
 241+ <script>$(function(){ // wait for document to load
 242+ $('input.wow').rating();
 243+});</script>
 244+ <pre class="code"><code class="js">$(function(){ // wait for document to load
 245+ $('input.wow').rating();
 246+});</code></pre>
 247+ <pre class="code"><code class="html">&lt;input name="adv2" type="radio" class="wow {split:4}"/&gt;
 248+&lt;input name="adv2" type="radio" class="wow {split:4}"/&gt;
 249+&lt;input name="adv2" type="radio" class="wow {split:4}"/&gt;
 250+&lt;input name="adv2" type="radio" class="wow {split:4}"/&gt;
 251+&lt;input name="adv2" type="radio" class="wow {split:4}" checked="checked"/&gt;
 252+&lt;input name="adv2" type="radio" class="wow {split:4}"/&gt;
 253+&lt;input name="adv2" type="radio" class="wow {split:4}"/&gt;
 254+&lt;input name="adv2" type="radio" class="wow {split:4}"/&gt;</code></pre>
 255+ </td>
 256+ <td valign="top" width="10">&raquo;</td>
 257+ <td valign="top" width="180">
 258+ <input name="adv2" type="radio" class="wow {split:4}"/>
 259+ <input name="adv2" type="radio" class="wow {split:4}"/>
 260+ <input name="adv2" type="radio" class="wow {split:4}"/>
 261+ <input name="adv2" type="radio" class="wow {split:4}"/>
 262+ <input name="adv2" type="radio" class="wow {split:4}" checked="checked"/>
 263+ <input name="adv2" type="radio" class="wow {split:4}"/>
 264+ <input name="adv2" type="radio" class="wow {split:4}"/>
 265+ <input name="adv2" type="radio" class="wow {split:4}"/>
 266+ </td>
 267+ </tr>
 268+ </table>
 269+ </div><!--// tab-Overview //-->
 270+
 271+ <div id="tab-Testing">
 272+ <h2>Test Suite</h2>
 273+<script type="text/javascript" language="javascript">
 274+$(function(){
 275+ $('#form1 :radio.star').rating();
 276+ $('#form2 :radio.star').rating({cancel: 'Cancel', cancelValue: '0'});
 277+ $('#form3 :radio.star').rating();
 278+ $('#form4 :radio.star').rating();
 279+});
 280+</script>
 281+<script>
 282+$(function(){
 283+ $('#tab-Testing form').submit(function(){
 284+ $('.test',this).html('');
 285+ $('input',this).each(function(){
 286+ if(this.checked) $('.test',this.form).append(''+this.name+': '+this.value+'<br/>');
 287+ });
 288+ return false;
 289+ });
 290+});
 291+</script>
 292+
 293+<div class="Clear">&nbsp;</div>
 294+<form id="form1">
 295+<strong style='font-size:150%'>Test 1</strong> - A blank form
 296+<table width="100%" cellspacing="10"> <tr>
 297+ <td valign="top" width="">
 298+ <table width="100%">
 299+ <tr>
 300+ <td valign="top" width="50%">
 301+<div class="Clear">
 302+ Rating 1:
 303+ (N/M/Y)
 304+ <input class="star" type="radio" name="test-1-rating-1" value="N" title="No"/>
 305+ <input class="star" type="radio" name="test-1-rating-1" value="M" title="Maybe"/>
 306+ <input class="star" type="radio" name="test-1-rating-1" value="Y" title="Yes"/>
 307+ </div>
 308+ <br/>
 309+ <div class="Clear">
 310+ Rating 2:
 311+ (10 - 50)
 312+ <input class="star" type="radio" name="test-1-rating-2" value="10"/>
 313+ <input class="star" type="radio" name="test-1-rating-2" value="20"/>
 314+ <input class="star" type="radio" name="test-1-rating-2" value="30"/>
 315+ <input class="star" type="radio" name="test-1-rating-2" value="40"/>
 316+ <input class="star" type="radio" name="test-1-rating-2" value="50"/>
 317+ </div>
 318+ <br/>
 319+ <div class="Clear">
 320+ Rating 3:
 321+ (1 - 7)
 322+ <input class="star" type="radio" name="test-1-rating-3" value="1"/>
 323+ <input class="star" type="radio" name="test-1-rating-3" value="2"/>
 324+ <input class="star" type="radio" name="test-1-rating-3" value="3"/>
 325+ <input class="star" type="radio" name="test-1-rating-3" value="4"/>
 326+ <input class="star" type="radio" name="test-1-rating-3" value="5"/>
 327+ <input class="star" type="radio" name="test-1-rating-3" value="6"/>
 328+ <input class="star" type="radio" name="test-1-rating-3" value="7"/>
 329+ </div>
 330+ </td>
 331+ <td valign="top" width="50%">
 332+ <div class="Clear">
 333+ Rating 4:
 334+ (1 - 5)
 335+ <input class="star" type="radio" name="test-1-rating-4" value="1" title="Worst"/>
 336+ <input class="star" type="radio" name="test-1-rating-4" value="2" title="Bad"/>
 337+ <input class="star" type="radio" name="test-1-rating-4" value="3" title="OK"/>
 338+ <input class="star" type="radio" name="test-1-rating-4" value="4" title="Good"/>
 339+ <input class="star" type="radio" name="test-1-rating-4" value="5" title="Best"/>
 340+ </div>
 341+ <br/>
 342+ <div class="Clear">
 343+ Rating 5:
 344+ (1 - 5)
 345+ <input class="star" type="radio" name="test-1-rating-5" value="1"/>
 346+ <input class="star" type="radio" name="test-1-rating-5" value="2"/>
 347+ <input class="star" type="radio" name="test-1-rating-5" value="3"/>
 348+ <input class="star" type="radio" name="test-1-rating-5" value="4"/>
 349+ <input class="star" type="radio" name="test-1-rating-5" value="5"/>
 350+ </div>
 351+ <br/>
 352+ <div class="Clear">
 353+ Rating 6 (readonly):
 354+ (1 - 5)
 355+ <input class="star" type="radio" name="test-1-rating-6" value="1" disabled="disabled"/>
 356+ <input class="star" type="radio" name="test-1-rating-6" value="2" disabled="disabled"/>
 357+ <input class="star" type="radio" name="test-1-rating-6" value="3" disabled="disabled"/>
 358+ <input class="star" type="radio" name="test-1-rating-6" value="4" disabled="disabled"/>
 359+ <input class="star" type="radio" name="test-1-rating-6" value="5" disabled="disabled"/>
 360+ </div>
 361+ </td>
 362+ </tr>
 363+ </table>
 364+ </td>
 365+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="50">
 366+ <input type="submit" value="Submit scores!" /> </td>
 367+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="160">
 368+ <u>Test results</u>:<br/><br/>
 369+ <div class="test Smaller">
 370+ <span style="color:#FF0000">Results will be displayed here</span>
 371+ </div>
 372+ </td>
 373+ </tr>
 374+</table>
 375+</form>
 376+
 377+<div class="Clear">&nbsp;</div><div class="Clear">&nbsp;</div>
 378+
 379+<form id="form2">
 380+<strong style='font-size:150%'>Test 2</strong> - With defaults ('checked')
 381+<table width="100%" cellspacing="10"> <tr>
 382+ <td valign="top" width="">
 383+ <table width="100%">
 384+ <tr>
 385+ <td valign="top" width="50%">
 386+ <div class="Clear">
 387+ Rating 1:
 388+ (N/M/Y, default M)
 389+ </div>
 390+ <div class="Clear">
 391+ <input class="star" type="radio" name="test-2-rating-1" value="N" title="No"/>
 392+ <input class="star" type="radio" name="test-2-rating-1" value="M" title="Maybe" checked="checked"/>
 393+ <input class="star" type="radio" name="test-2-rating-1" value="Y" title="Yes"/>
 394+ </div>
 395+ <div class="Clear">
 396+ Rating 2:
 397+ (10 - 50, default 30)
 398+ </div>
 399+ <div class="Clear">
 400+ <input class="star" type="radio" name="test-2-rating-2" value="10"/>
 401+ <input class="star" type="radio" name="test-2-rating-2" value="20"/>
 402+ <input class="star" type="radio" name="test-2-rating-2" value="30" checked="checked"/>
 403+ <input class="star" type="radio" name="test-2-rating-2" value="40"/>
 404+ <input class="star" type="radio" name="test-2-rating-2" value="50"/>
 405+ </div>
 406+ <div class="Clear">
 407+ Rating 3:
 408+ (1 - 7, default 4)
 409+ </div>
 410+ <div class="Clear">
 411+ <input class="star" type="radio" name="test-2-rating-3" value="1"/>
 412+ <input class="star" type="radio" name="test-2-rating-3" value="2"/>
 413+ <input class="star" type="radio" name="test-2-rating-3" value="3"/>
 414+ <input class="star" type="radio" name="test-2-rating-3" value="4" checked="checked"/>
 415+ <input class="star" type="radio" name="test-2-rating-3" value="5"/>
 416+ <input class="star" type="radio" name="test-2-rating-3" value="6"/>
 417+ <input class="star" type="radio" name="test-2-rating-3" value="7"/>
 418+ </div>
 419+ </td>
 420+ <td valign="top" width="50%">
 421+ <div class="Clear">
 422+ Rating 4:
 423+ (1 - 5, default 1)
 424+ </div>
 425+ <div class="Clear">
 426+ <input class="star" type="radio" name="test-2-rating-4" value="1" title="Worst" checked="checked"/>
 427+ <input class="star" type="radio" name="test-2-rating-4" value="2" title="Bad"/>
 428+ <input class="star" type="radio" name="test-2-rating-4" value="3" title="OK"/>
 429+ <input class="star" type="radio" name="test-2-rating-4" value="4" title="Good"/>
 430+ <input class="star" type="radio" name="test-2-rating-4" value="5" title="Best"/>
 431+ </div>
 432+ <div class="Clear">
 433+ Rating 5:
 434+ (1 - 5, default 5)
 435+ </div>
 436+ <div class="Clear">
 437+ <input class="star" type="radio" name="test-2-rating-5" value="1"/>
 438+ <input class="star" type="radio" name="test-2-rating-5" value="2"/>
 439+ <input class="star" type="radio" name="test-2-rating-5" value="3"/>
 440+ <input class="star" type="radio" name="test-2-rating-5" value="4"/>
 441+ <input class="star" type="radio" name="test-2-rating-5" value="5" checked="checked"/>
 442+ </div>
 443+ <div class="Clear">
 444+ Rating 6 (readonly):
 445+ (1 - 5, default 3)
 446+ </div>
 447+ <div class="Clear">
 448+ <input class="star" type="radio" name="test-2-rating-6" value="1" disabled="disabled"/>
 449+ <input class="star" type="radio" name="test-2-rating-6" value="2" disabled="disabled"/>
 450+ <input class="star" type="radio" name="test-2-rating-6" value="3" disabled="disabled" checked="checked"/>
 451+ <input class="star" type="radio" name="test-2-rating-6" value="4" disabled="disabled"/>
 452+ <input class="star" type="radio" name="test-2-rating-6" value="5" disabled="disabled"/>
 453+ </div>
 454+ </td>
 455+ </tr>
 456+</table>
 457+ </td>
 458+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="50">
 459+ <input type="submit" value="Submit scores!" /> </td>
 460+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="160">
 461+ <u>Test results</u>:<br/><br/>
 462+ <div class="test Smaller">
 463+ <span style="color:#FF0000">Results will be displayed here</span>
 464+ </div>
 465+ </td>
 466+ </tr>
 467+</table>
 468+</form>
 469+
 470+<div class="Clear">&nbsp;</div><div class="Clear">&nbsp;</div>
 471+
 472+<form id="form3A">
 473+<script>
 474+$(function(){
 475+ $('.auto-submit-star').rating({
 476+ callback: function(value, link){
 477+ // 'this' is the hidden form element holding the current value
 478+ // 'value' is the value selected
 479+ // 'element' points to the link element that received the click.
 480+ alert("The value selected was '" + value + "'\n\nWith this callback function I can automatically submit the form with this code:\nthis.form.submit();");
 481+
 482+ // To submit the form automatically:
 483+ //this.form.submit();
 484+
 485+ // To submit the form via ajax:
 486+ //$(this.form).ajaxSubmit();
 487+ }
 488+ });
 489+});
 490+</script>
 491+<strong style='font-size:150%'>Test 3-A</strong> - With callback
 492+<table width="100%" cellspacing="10"> <tr>
 493+ <td valign="top" width="">
 494+<div class="Clear">
 495+ Rating 1:
 496+ (1 - 3, default 2)
 497+ <input class="auto-submit-star" type="radio" name="test-3A-rating-1" value="1"/>
 498+ <input class="auto-submit-star" type="radio" name="test-3A-rating-1" value="2" checked="checked"/>
 499+ <input class="auto-submit-star" type="radio" name="test-3A-rating-1" value="3"/>
 500+ </div>
 501+ <div class="Clear">
 502+ <pre class="code"><code class="js">$('.auto-submit-star').rating({
 503+ callback: function(value, link){
 504+ alert(value);
 505+ }
 506+});</code></pre>
 507+ </div>
 508+ </td>
 509+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="50">
 510+ <input type="submit" value="Submit scores!" /> </td>
 511+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="160">
 512+ <u>Test results</u>:<br/><br/>
 513+ <div class="test Smaller">
 514+ <span style="color:#FF0000">Results will be displayed here</span>
 515+ </div>
 516+ </td>
 517+ </tr>
 518+</table>
 519+</form>
 520+
 521+<div class="Clear">&nbsp;</div><div class="Clear">&nbsp;</div>
 522+
 523+<script>
 524+$(function(){
 525+ $('.hover-star').rating({
 526+ focus: function(value, link){
 527+ // 'this' is the hidden form element holding the current value
 528+ // 'value' is the value selected
 529+ // 'element' points to the link element that received the click.
 530+ var tip = $('#hover-test');
 531+ tip[0].data = tip[0].data || tip.html();
 532+ tip.html(link.title || 'value: '+value);
 533+ },
 534+ blur: function(value, link){
 535+ var tip = $('#hover-test');
 536+ $('#hover-test').html(tip[0].data || '');
 537+ }
 538+ });
 539+});
 540+</script>
 541+<form id="form3B">
 542+<strong style='font-size:150%'>Test 3-B</strong> - With hover effects
 543+<table width="100%" cellspacing="10"> <tr>
 544+ <td valign="top" width="">
 545+<div class="Clear">
 546+ Rating 1:
 547+ (1 - 3, default 2)
 548+ <div>
 549+ <input class="hover-star" type="radio" name="test-3B-rating-1" value="1" title="Very poor"/>
 550+ <input class="hover-star" type="radio" name="test-3B-rating-1" value="2" title="Poor"/>
 551+ <input class="hover-star" type="radio" name="test-3B-rating-1" value="3" title="OK"/>
 552+ <input class="hover-star" type="radio" name="test-3B-rating-1" value="4" title="Good"/>
 553+ <input class="hover-star" type="radio" name="test-3B-rating-1" value="5" title="Very Good"/>
 554+ <span id="hover-test" style="margin:0 0 0 20px;">Hover tips will appear in here</span>
 555+ </div>
 556+ </div>
 557+ <div class="Clear">
 558+ <pre class="code"><code class="js">$('.hover-star').rating({
 559+ focus: function(value, link){
 560+ var tip = $('#hover-test');
 561+ tip[0].data = tip[0].data || tip.html();
 562+ tip.html(link.title || 'value: '+value);
 563+ },
 564+ blur: function(value, link){
 565+ var tip = $('#hover-test');
 566+ $('#hover-test').html(tip[0].data || '');
 567+ }
 568+});</code></pre>
 569+ </div>
 570+ </td>
 571+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="50">
 572+ <input type="submit" value="Submit scores!" /> </td>
 573+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="160">
 574+ <u>Test results</u>:<br/><br/>
 575+ <div class="test Smaller">
 576+ <span style="color:#FF0000">Results will be displayed here</span>
 577+ </div>
 578+ </td>
 579+ </tr>
 580+</table>
 581+</form>
 582+
 583+<div class="Clear">&nbsp;</div><div class="Clear">&nbsp;</div>
 584+
 585+<form id="form4">
 586+<strong style='font-size:150%'>Test 4</strong> - <strong>Half Stars</strong> and <strong>Split Stars</strong>
 587+<table width="100%" cellspacing="10"> <tr>
 588+ <td valign="top" width="">
 589+ <table width="100%">
 590+ <tr>
 591+ <td width="50%">
 592+ <div class="Clear">
 593+ Rating 1:
 594+ (N/M/Y/?)
 595+ <div><small><pre class="code"><code class="html">&lt;input class="star {half:true}"</code></pre></small></div>
 596+ <input class="star {half:true}" type="radio" name="test-4-rating-1" value="N" title="No"/>
 597+ <input class="star {half:true}" type="radio" name="test-4-rating-1" value="M" title="Maybe"/>
 598+ <input class="star {half:true}" type="radio" name="test-4-rating-1" value="Y" title="Yes"/>
 599+ <input class="star {half:true}" type="radio" name="test-4-rating-1" value="?" title="Don't Know"/>
 600+ </div>
 601+ <br/>
 602+ <div class="Clear">
 603+ Rating 2:
 604+ (10 - 60)
 605+ <div><small><pre class="code"><code class="html">&lt;input class="star {split:3}"</code></pre></small></div>
 606+ <input class="star {split:3}" type="radio" name="test-4-rating-2" value="10"/>
 607+ <input class="star {split:3}" type="radio" name="test-4-rating-2" value="20"/>
 608+ <input class="star {split:3}" type="radio" name="test-4-rating-2" value="30"/>
 609+ <input class="star {split:3}" type="radio" name="test-4-rating-2" value="40"/>
 610+ <input class="star {split:3}" type="radio" name="test-4-rating-2" value="50"/>
 611+ <input class="star {split:3}" type="radio" name="test-4-rating-2" value="60"/>
 612+ </div>
 613+ <br/>
 614+ <div class="Clear">
 615+ Rating 3:
 616+ (0-5.0, default 3.5)
 617+ <div><small><pre class="code"><code class="html">&lt;input class="star {split:2}"</code></pre></small></div>
 618+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="0.5"/>
 619+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="1.0"/>
 620+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="1.5"/>
 621+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="2.0"/>
 622+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="2.5"/>
 623+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="3.0"/>
 624+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="3.5" checked="checked"/>
 625+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="4.0"/>
 626+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="4.5"/>
 627+ <input class="star {split:2}" type="radio" name="test-4-rating-3" value="5.0"/>
 628+ </div>
 629+ </td>
 630+ <td valign="top" width="50%">
 631+ <div class="Clear">
 632+ Rating 4:
 633+ (1-6, default 5)
 634+ <div><small><pre class="code"><code class="html">&lt;input class="star {split:2}"</code></pre></small></div>
 635+ <input class="star {split:2}" type="radio" name="test-4-rating-4" value="1" title="Worst"/>
 636+ <input class="star {split:2}" type="radio" name="test-4-rating-4" value="2" title="Bad"/>
 637+ <input class="star {split:2}" type="radio" name="test-4-rating-4" value="3" title="OK"/>
 638+ <input class="star {split:2}" type="radio" name="test-4-rating-4" value="4" title="Good"/>
 639+ <input class="star {split:2}" type="radio" name="test-4-rating-4" value="5" title="Best" checked="checked"/>
 640+ <input class="star {split:2}" type="radio" name="test-4-rating-4" value="6" title="Bestest!!!"/>
 641+ </div>
 642+ <br/>
 643+ <div class="Clear">
 644+ Rating 5:
 645+ (1-20, default 11)
 646+ <div><small><pre class="code"><code class="html">&lt;input class="star {split:4}"</code></pre></small></div>
 647+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="1"/>
 648+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="2"/>
 649+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="3"/>
 650+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="4"/>
 651+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="5"/>
 652+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="6"/>
 653+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="7"/>
 654+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="8"/>
 655+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="9"/>
 656+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="10"/>
 657+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="11" checked="checked"/>
 658+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="12"/>
 659+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="13"/>
 660+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="14"/>
 661+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="15"/>
 662+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="16"/>
 663+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="17"/>
 664+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="18"/>
 665+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="19"/>
 666+ <input class="star {split:4}" type="radio" name="test-4-rating-5" value="20"/>
 667+ </div>
 668+ <br/>
 669+ <div class="Clear">
 670+ Rating 6 (readonly):
 671+ (1-20, default 13)
 672+ <div><small><pre class="code"><code class="html">&lt;input class="star {split:4}"</code></pre></small></div>
 673+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="1" disabled="disabled"/>
 674+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="2" disabled="disabled"/>
 675+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="3" disabled="disabled"/>
 676+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="4" disabled="disabled"/>
 677+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="5" disabled="disabled"/>
 678+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="6" disabled="disabled"/>
 679+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="7" disabled="disabled"/>
 680+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="8" disabled="disabled"/>
 681+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="9" disabled="disabled"/>
 682+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="10" disabled="disabled"/>
 683+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="11" disabled="disabled"/>
 684+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="12" disabled="disabled"/>
 685+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="13" disabled="disabled" checked="checked"/>
 686+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="14" disabled="disabled"/>
 687+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="15" disabled="disabled"/>
 688+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="16" disabled="disabled"/>
 689+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="17" disabled="disabled"/>
 690+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="18" disabled="disabled"/>
 691+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="19" disabled="disabled"/>
 692+ <input class="star {split:4}" type="radio" name="test-4-rating-6" value="20" disabled="disabled"/>
 693+ </div>
 694+ </td>
 695+ </tr>
 696+ </table>
 697+ </td>
 698+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="50">
 699+ <input type="submit" value="Submit scores!" /> </td>
 700+ <td valign="top" width="5">&nbsp;</td> <td valign="top" width="160">
 701+ <u>Test results</u>:<br/><br/>
 702+ <div class="test Smaller">
 703+ <span style="color:#FF0000">Results will be displayed here</span>
 704+ </div>
 705+ </td>
 706+ </tr>
 707+</table>
 708+</form>
 709+ </div><!--// tab-Testing //-->
 710+
 711+ <div id="tab-API">
 712+ <h2>API</h2>
 713+ <p class="B Yes">NEW to v3</p>
 714+
 715+ <p>API methods can be invoked this this:</p>
 716+ <div><pre class="code"><code class="js">$(selector).rating(
 717+ 'method', // method name
 718+ [] // method arguments (not required)
 719+);</code></pre></div>
 720+
 721+ <br/><br/><br/>
 722+
 723+ <h3>$().rating('select', index / value)</h3>
 724+ <p>
 725+ Use this method to set the value (and display) of the star rating control
 726+ via javascript. It accepts the index of the star you want to select (0 based)
 727+ or its value (which must be passed as a string.
 728+ </p>
 729+ <p>
 730+ Example: (values A/B/C/D/E)
 731+ </p>
 732+ <form name="api-select">
 733+ <input type="radio" class="star" name="api-select-test" value="A"/>
 734+ <input type="radio" class="star" name="api-select-test" value="B"/>
 735+ <input type="radio" class="star" name="api-select-test" value="C"/>
 736+ <input type="radio" class="star" name="api-select-test" value="D"/>
 737+ <input type="radio" class="star" name="api-select-test" value="E"/>
 738+ <input type="button" value="Submit &raquo;" onClick="
 739+ $(this).next().html( $(this.form).serialize() || '(nothing submitted)' );
 740+ "/>
 741+ <span></span>
 742+ <br/>
 743+ By index:
 744+ <input type="button" onClick="javascript:$('input',this.form).rating('select',0)" value="0"/>
 745+ <input type="button" onClick="javascript:$('input',this.form).rating('select',1)" value="1"/>
 746+ <input type="button" onClick="javascript:$('input',this.form).rating('select',2)" value="2"/>
 747+ <input type="button" onClick="javascript:$('input',this.form).rating('select',3)" value="3"/>
 748+ <input type="button" onClick="javascript:$('input',this.form).rating('select',4)" value="4"/>
 749+ eg.: $('input').rating('select',3)
 750+ <br/>
 751+ By value:
 752+ <input type="button" onClick="javascript:$('input',this.form).rating('select',this.value)" value="A"/>
 753+ <input type="button" onClick="javascript:$('input',this.form).rating('select',this.value)" value="B"/>
 754+ <input type="button" onClick="javascript:$('input',this.form).rating('select',this.value)" value="C"/>
 755+ <input type="button" onClick="javascript:$('input',this.form).rating('select',this.value)" value="D"/>
 756+ <input type="button" onClick="javascript:$('input',this.form).rating('select',this.value)" value="E"/>
 757+ eg.: $('input').rating('select','C')
 758+ </form>
 759+
 760+ <br/><br/><br/>
 761+
 762+ <h3>$().rating('readOnly', true / false)</h3>
 763+ <p>
 764+ Use this method to set the value (and display) of the star rating control
 765+ via javascript. It accepts the index of the star you want to select (0 based)
 766+ or its value (which must be passed as a string.
 767+ </p>
 768+ <p>
 769+ Example: (values 1,2,3...10)
 770+ </p>
 771+ <form name="api-readonly">
 772+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="1"/>
 773+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="2"/>
 774+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="3"/>
 775+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="4"/>
 776+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="5"/>
 777+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="6"/>
 778+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="7"/>
 779+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="8"/>
 780+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="9"/>
 781+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="10"/>
 782+ <input type="button" value="Submit &raquo;" onClick="
 783+ $(this).next().html( $(this.form).serialize() || '(nothing submitted)' );
 784+ "/>
 785+ <span></span>
 786+ <br/>
 787+ <input type="button" onClick="javascript:$('input',this.form).rating('readOnly',true)" value="Set readOnly = true"/>
 788+ eg.: $('input').rating('readOnly',true)
 789+ <br/>
 790+ <input type="button" onClick="javascript:$('input',this.form).rating('readOnly',false)" value="Set readOnly = false"/>
 791+ eg.: $('input').rating('readOnly',false) or simply $('input').rating('readOnly');
 792+ </form>
 793+
 794+ <br/><br/><br/>
 795+
 796+ <h3>$().rating('disable') / $().rating('enable')</h3>
 797+ <p>
 798+ These methods bahve almost exactly as the readOnly method, however
 799+ they also control whether or not the select value is submitted with
 800+ the form.
 801+ </p>
 802+ <p>
 803+ Example: (values 1,2,3...10)
 804+ </p>
 805+ <form name="api-readonly">
 806+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="1"/>
 807+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="2"/>
 808+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="3"/>
 809+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="4"/>
 810+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="5"/>
 811+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="6"/>
 812+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="7"/>
 813+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="8"/>
 814+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="9"/>
 815+ <input type="radio" class="star {split:2}" name="api-readonly-test" value="10"/>
 816+ <input type="button" value="Submit &raquo;" onClick="
 817+ $(this).next().html( $(this.form).serialize() || '(nothing submitted)' );
 818+ "/>
 819+ <span></span>
 820+ <br/>
 821+ <input type="button" onClick="javascript:$('input',this.form).rating('disable')" value="disable"/>
 822+ eg.: $('input').rating('disable')
 823+ <br/>
 824+ <input type="button" onClick="javascript:$('input',this.form).rating('enable')" value="enable"/>
 825+ eg.: $('input').rating('enable');
 826+ </form>
 827+ </div><!--// tab-API //-->
 828+
 829+ <div id="tab-Database">
 830+ <h2>Database Integration</h2>
 831+ <p>
 832+ I'm sorry to say that for the time being, <strong>it is up to you</strong>
 833+ to create the server-side code that will
 834+ process the form submission, store it somewhere (like a database) and do stuff with it -
 835+ such as displaying averages and stop users from voting more than once.
 836+ </p>
 837+ <p>
 838+ <strong>However</strong>, here are a few alternatives if you don't feel
 839+ like getting down and dirty with some good old coding:
 840+ <br>http://www.yvoschaap.com/index.php/weblog/css_star_rater_ajax_version/
 841+ <br>
 842+ <br>and
 843+ <br>part 1: http://www.komodomedia.com/blog/2005/08/creating-a-star-rater-using-css/
 844+ <br>part 2: http://slim.climaxdesigns.com/tutorial.php?section=slim&amp;id=2
 845+ <br>part 3: http://slim.climaxdesigns.com/tutorial.php?section=slim&amp;id=3
 846+ <br>part 4: http://slim.climaxdesigns.com/tutorial.php?section=slim&amp;id=9
 847+ </p>
 848+ </div><!--// tab-Database //-->
 849+
 850+ <div id="tab-Background">
 851+ <h2>Background Information</h2>
 852+ <p>As far as I know, this is how it goes...</p>
 853+ <ul type="1">
 854+ <li> It all started with <em>Will Stuckey</em>'s <a target="_blank" href="http://www.visualjquery.com/rating/rating_redux.html">jQuery Star Rating Super Interface!</a> </li>
 855+ <li> The original then became the inspiration for <em>Ritesh Agrawal</em>'s <a target="_blank" href="http://php.scripts.psu.edu/rja171/widgets/rating.php">Simple Star Rating System</a>,
 856+ which allows for a GMail like star/un-star toggle. </li>
 857+ <li> This was followed by several spin-offs... (one of which is the <a target="_blank" href="http://www.learningjquery.com/2007/05/half-star-rating-plugin">Half-star rating plugin</a>) </li>
 858+ <li> Then someone at <a target="_blank" href="http://www.phpletter.com/Demo/Jquery-Star-Rating-Plugin/">PHPLetter.com modified the plugin</a> to overcome the issues - then plugin was now based on standard form elements, meaning
 859+ the interface would still work with Javascript disabled making it <em>beautifully downgradable</em>. </li>
 860+ <li> Then I came along and noticed a fundamental flaw with the latter: there could only
 861+ be one star rating control per page. The rest of the story is what you will see below... </li>
 862+ <li> <strong style="color: rgb(0, 153, 0);">NEW</strong> (12-Mar-08): Then <strong>Keith Wood</strong> added some very nice functionality to the plugin:
 863+ option to disable the cancel button, option to make the plugin readOnly and ability to accept any value (other than whole numbers) </li>
 864+ <li> <strong style="color: rgb(0, 153, 0);">NEW</strong> (20-Mar-08): Now supports half-star, third-star, quater-star, etc... Not additional code required. No additional images required. </li>
 865+ <li> <strong style="color: rgb(0, 153, 0);">NEW</strong> (31-Mar-08): Two new events, hover/blur (arguments: [value, linkElement]) </li>
 866+ </ul>
 867+ </div><!--// tab-Background //-->
 868+
 869+ <div id="tab-Download">
 870+ <h2>Download</h2>
 871+ <p>
 872+ This project (and all related files) can also be accessed via its
 873+ <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/">Google Code Project Page</a>.
 874+ </p>
 875+ <table cellspacing="5">
 876+ <tr>
 877+ <td valign="top" align="right">Full Package:</td>
 878+ <td valign="top">
 879+ <big>
 880+ <img src="/@/download.gif" style="margin:0 5px 5px 0; float:left;">
 881+ v<strong>3.13</strong>
 882+ <a href="http://jquery-star-rating-plugin.googlecode.com/svn/trunk/star-rating.zip"><strong>star-rating.zip</strong></a>
 883+ </big>
 884+ </td>
 885+ </tr>
 886+ <tr>
 887+ <td valign="top" align="right"></td>
 888+ <td valign="top">
 889+ <div class="Clear" style="margin:0 0 10px 0;" onClick="$('a:eq(0)',this).click()">
 890+ <strong class="Yes" style="background:#090; color:#fff; padding:3px;">Stay up-to-date!</strong>
 891+ <span style="padding:3px;">
 892+ Major updates will be announced on
 893+ <a target="_blank" href="http://twitter.com/fyneworks" class="external">Twitter</a>:
 894+ <a target="_blank" href="http://twitter.com/fyneworks" class="external">@fyneworks</a>
 895+ </span>
 896+ </div>
 897+ </td>
 898+ </tr>
 899+ <tr>
 900+ <td valign="top" align="right">Core Files:</td>
 901+ <td valign="top">
 902+ These are the individual required files (<span class="Warning">already included in the zip package above</span>)
 903+ <ul>
 904+ <li><a href="http://jquery-star-rating-plugin.googlecode.com/svn/trunk/jquery.rating.js"><strong>jquery.rating.js</strong></a>
 905+ (packed version: <a href="http://jquery-star-rating-plugin.googlecode.com/svn/trunk/jquery.rating.pack.js">jquery.rating.pack.js</a>)</li>
 906+ <li><a target="_blank" href="http://jquery-star-rating-plugin.googlecode.com/svn/trunk/jquery.rating.css"><strong>jQuery.Rating.css</strong></a></li>
 907+ <li><a target="_blank" href="http://jquery-star-rating-plugin.googlecode.com/svn/trunk/delete.gif"><strong>delete.gif</strong></a></li>
 908+ <li><a target="_blank" href="http://jquery-star-rating-plugin.googlecode.com/svn/trunk/star.gif"><strong>star.gif</strong></a></li>
 909+ </ul>
 910+ </td>
 911+ </tr>
 912+ <tr>
 913+ <td valign="top" align="right">jQuery:</td>
 914+ <td valign="top">
 915+ <a target="_blank" href="http://jquery.com/src/jquery-latest.js">jquery-latest.js</a> (<a target="_blank" href="http://www.jquery.com/">see jQuery.com</a>)
 916+ </td>
 917+ </tr>
 918+ </table>
 919+
 920+ <h2>Related Downloads</h2>
 921+ <table cellspacing="5">
 922+ <tr>
 923+ <td valign="top" align="right">Related:</td>
 924+ <td valign="top">
 925+ <a target="_blank" href="http://plugins.jquery.com/project/metadata/">Metadata plugin</a> - Used to retrieve inline configuration from class variable
 926+ <br/>
 927+ <a target="_blank" href="http://www.malsup.com/jquery/form/">Form plugin</a> - Used to submit forms via ajax
 928+ </td>
 929+ </tr>
 930+ </table>
 931+
 932+ <h2>SVN Repository</h2>
 933+ <p>
 934+ If you're a major geek or if you really really want to stay up-to-date with
 935+ with future updates of this plugin, go ahead and plug yourself to the
 936+ <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/">SVN Repository</a>
 937+ on the official
 938+ <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/">Google Code Project Page</a>.
 939+ </p>
 940+ <table cellspacing="5">
 941+ <tr>
 942+ <td valign="top" align="right">SVN Checkout:</td>
 943+ <td valign="top">
 944+ <img src="/@/files/js.gif" style="margin:0 5px 5px 0; float:left;">
 945+ <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/source/checkout"><strong>SVN Checkout Instructions</strong></a>
 946+ </td>
 947+ </tr>
 948+ <tr>
 949+ <td valign="top" align="right">Browse Online:</td>
 950+ <td valign="top">
 951+ <img src="/@/folder.gif" style="margin:0 5px 5px 0; float:left;">
 952+ <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/source/browse/"><strong>Browse Source</strong></a>
 953+ </td>
 954+ </tr>
 955+ </table>
 956+
 957+ <h2>Alternative Download - From this website</h2>
 958+ <p>
 959+ Just in case it's the end of the world and the Google Code site becomes unavailable,
 960+ the project files can also be downloaded form this site.
 961+ <br/>
 962+ However, please note that this site is updated periodically whereas the Google Code
 963+ project is kept up-to-date almost instantaneously. If you'd like the very latest
 964+ version of this plugin
 965+ <strong>you are advised to use the links above and download the files from Google Code</strong>
 966+ - this will ensure the files you download have the very latest features and bug fixes.
 967+ </p>
 968+ <table cellspacing="5">
 969+ <tr>
 970+ <td valign="top" align="right">Full Package:</td>
 971+ <td valign="top">
 972+ <img src="/@/download.gif" style="margin:0 5px 5px 0; float:left;">
 973+ v<strong>3.13</strong>
 974+ <a href="http://jquery-star-rating-plugin.googlecode.com/svn/trunk/star-rating.zip"><strong>star-rating.zip</strong></a>
 975+ </td>
 976+ </tr>
 977+ <tr>
 978+ <td valign="top" align="right"></td>
 979+ <td valign="top">
 980+ <div class="Clear" style="margin:0 0 10px 0;" onClick="$('a:eq(0)',this).click()">
 981+ <strong class="Yes" style="background:#090; color:#fff; padding:3px;">Stay up-to-date!</strong>
 982+ <span style="padding:3px;">
 983+ Major updates will be announced on
 984+ <a target="_blank" href="http://twitter.com/fyneworks" class="external">Twitter</a>:
 985+ <a target="_blank" href="http://twitter.com/fyneworks" class="external">@fyneworks</a>
 986+ </span>
 987+ </div>
 988+ </td>
 989+ </tr>
 990+ <tr>
 991+ <td valign="top" align="right">Core Files:</td>
 992+ <td valign="top">
 993+ These are the individual required files (<span class="Warning">already included in the zip package above</span>)
 994+ <ul>
 995+ <li><a target="_blank" href='jquery.rating.js'><strong>jquery.rating.js</strong></a> (packed version: <a href="jquery.rating.pack.js">jquery.rating.pack.js</a>)</li>
 996+ <li><a target="_blank" href='jquery.rating.css'><strong>jQuery.Rating.css</strong></a></li>
 997+ <li><a target="_blank" href="delete.gif"><strong>delete.gif</strong></a></li>
 998+ <li><a target="_blank" href="star.gif"><strong>star.gif</strong></a></li>
 999+ </ul>
 1000+ </td>
 1001+ </tr>
 1002+ <tr>
 1003+ <td valign="top" align="right">jQuery:</td>
 1004+ <td valign="top">
 1005+ <a target="_blank" href="http://jquery.com/src/jquery-latest.js">jquery-latest.js</a> (<a target="_blank" href="http://www.jquery.com/">see jQuery.com</a>)
 1006+ </td>
 1007+ </tr>
 1008+ </table>
 1009+
 1010+ </div><!--// tab-Download //-->
 1011+
 1012+ <div id="tab-Support">
 1013+
 1014+ <h2>Support</h2>
 1015+ <p>
 1016+ Quick Support Links: <a href="http://groups.google.com/group/jquery-en" class="B Yes">Help me!</a>
 1017+ | <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/issues/entry">Report a bug</a>
 1018+ | <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/issues/entry">Suggest new feature</a>
 1019+<!--//
 1020+ OLD: Forget Trac - Let's use Google Code!
 1021+ | <a target="_blank" href="http://plugins.jquery.com/node/add/project_issue/MultiFile/bug">Report a bug</a>
 1022+ | <a target="_blank" href="http://plugins.jquery.com/node/add/project_issue/MultiFile/feature">Suggest new feature</a>
 1023+//-->
 1024+ </p>
 1025+ <p>
 1026+ Support for this plugin is available through the <a target="_blank" href="http://jquery.com/discuss/" class="external">jQuery Mailing List</a>.
 1027+ This is a very active list to which many jQuery developers and users subscribe.
 1028+ <br/>
 1029+ Access to the jQuery Mailing List is also available through
 1030+ <a target="_blank" href="http://www.nabble.com/JQuery-f15494.html" class="external">Nabble Forums</a>
 1031+ and the
 1032+ <a target="_blank" href="http://groups.google.com/group/jquery-en" class="external">jQuery Google Group</a>.
 1033+ </p>
 1034+ <p>
 1035+ <strong class="Warning">WARNING:</strong>
 1036+ Support will not be provided via the <a href="http://plugins.jquery.com/">jQuery Plugins</a>
 1037+ website.
 1038+ If you need help, please direct your questions to the
 1039+ <a target="_blank" href="http://groups.google.com/group/jquery-en" class="external">jQuery Mailing List</a>
 1040+ or
 1041+ <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/issues/entry">report an issue</a>
 1042+ on the official
 1043+ <a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/">Google Code Project Page</a>.
 1044+ </p>
 1045+
 1046+ <h2>Official Links</h2>
 1047+ <ul>
 1048+ <li><a target="_blank" href="http://plugins.jquery.com/project/MultipleFriendlyStarRating/" class="external">jQuery Plugin Project Page</a></li>
 1049+ <li><a target="_blank" href="http://code.google.com/p/jquery-star-rating-plugin/">Google Code Project Page</a></li>
 1050+ </ul>
 1051+
 1052+ <h2>Credit</h2>
 1053+ <ul>
 1054+ <li>Diego A. - Author, <a href="http://www.fyneworks.com/">London SEO Consultant</a></li>
 1055+ <li><a target="_blank" href="http://keith-wood.name/">Keith Wood</a> - The brain behind v2.1</li>
 1056+ <li>Dean Edwards - Author of <a target="_blank" href="http://dean.edwards.name/packer/">JS Packer</a> used to compress the plugin</li>
 1057+ <li>Will Stuckey, Ritesh Agrawal and everyone else who worked in the previous versions of the plugin - I'm not so good with research...</li>
 1058+ </ul>
 1059+ </div><!--// tab-Download //-->
 1060+
 1061+
 1062+
 1063+
 1064+
 1065+
 1066+ <!--//
 1067+ ####################################
 1068+ #
 1069+ # * END CONTENT *
 1070+ #
 1071+ ####################################
 1072+ //-->
 1073+ <div id="tab-License">
 1074+ <h2>Attribute this work</h2>
 1075+ <div class="license-info">
 1076+ <table cellspacing="5" width="100%">
 1077+ <tr>
 1078+ <td width="90" align="right">Attribution link:</td>
 1079+ <td valign="top">&copy; <a href="http://www.fyneworks.com/">Fyneworks.com</a></td>
 1080+ </tr>
 1081+ <tr>
 1082+ <td width="90" align="right">HTML Code:</td>
 1083+ <td valign="top">
 1084+ <input type="text" onFocus="this.select();" onClick="this.select()" style="width:100%;"
 1085+ value="&amp;copy; &lt;a href=&quot;http://www.fyneworks.com/&quot;&gt;Fyneworks.com&lt;/a&gt;"
 1086+ />
 1087+ </td>
 1088+ </tr>
 1089+ </table>
 1090+ </div>
 1091+ <h2>License Info</h2>
 1092+ <div class="license-info">
 1093+ <table cellspacing="5" width="100%">
 1094+ <tr>
 1095+ <td valign="middle">
 1096+ <strong>Star Rating Plugin</strong>
 1097+ by <a href="http://www.fyneworks.com/">Fyneworks.com</a>
 1098+ is licensed under the
 1099+ <a target="_blank" href="http://en.wikipedia.org/wiki/MIT_License">MIT License</a> and the
 1100+ <a target="_blank" href="http://creativecommons.org/licenses/GPL/2.0/">GPL License</a>.
 1101+ </td>
 1102+ <td width="100"><a target="_blank" href="http://creativecommons.org/licenses/GPL/2.0/"><img alt="Creative Commons License" style="border-width:0" src="http://creativecommons.org/images/public/somerights20.png"/></a></td>
 1103+ </tr>
 1104+ <tr>
 1105+ <td colspan="2">
 1106+ <pre class="copyright">Copyright &copy; 2008 <a href="http://www.fyneworks.com/">Fyneworks.com</a>
 1107+
 1108+ Permission is hereby granted, free of charge, to any person
 1109+ obtaining a copy of this software and associated documentation
 1110+ files (the "Software"), to deal in the Software without
 1111+ restriction, including without limitation the rights to use,
 1112+ copy, modify, merge, publish, distribute, sublicense, and/or sell
 1113+ copies of the Software, and to permit persons to whom the
 1114+ Software is furnished to do so, subject to the following
 1115+ conditions:
 1116+
 1117+ The above copyright notice and this permission notice shall be
 1118+ included in all copies or substantial portions of the Software.
 1119+
 1120+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 1121+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 1122+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 1123+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 1124+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 1125+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 1126+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 1127+ OTHER DEALINGS IN THE SOFTWARE.</pre>
 1128+ </td>
 1129+ </tr>
 1130+ </table>
 1131+ </div><!--// License Info //-->
 1132+ </div><!--// tab-License //-->
 1133+ </div><!--// documentation //-->
 1134+
 1135+ </div><!--// body //-->
 1136+ <div id="push"></div>
 1137+</div>
 1138+<div id="foot">
 1139+ <!--//<div class="Clear">//-->
 1140+ <table width="100%" cellspacing="5">
 1141+ <tr>
 1142+ <td valign="top">
 1143+ <strong>Star Rating Plugin</strong>
 1144+ by <a href="http://www.fyneworks.com/">Fyneworks.com</a>
 1145+ <br/>
 1146+ is licensed under the
 1147+ <a target="_blank" href="http://en.wikipedia.org/wiki/MIT_License">MIT License</a> and the
 1148+ <a target="_blank" href="http://creativecommons.org/licenses/GPL/2.0/">GPL License</a>.
 1149+ </td>
 1150+ <td valign="top" width="50%" align="right">
 1151+ <span style="margin:0 20px 0 0; color:#090;"
 1152+ >Tested with jQuery 1.4 on IE6, IE7, IE8, FF, Chrome, Opera and Safari</span>
 1153+ <a target="_blank" href="http://jquery.com/"><img src="/jquery/project/jq.png" alt="Powered by jQuery" style="vertical-align:middle;"/></a>
 1154+ </td>
 1155+ </tr>
 1156+ </table>
 1157+ <!--//</div>//-->
 1158+</div>
 1159+
 1160+ <script src='http://toolbar.wibiya.com/toolbarLoader.php?toolbarId=2147&nc=0&pl=1' type='text/javascript'></script>
 1161+ <!--//
 1162+ Wibiya clashes with jQuery so I found these articles:
 1163+ http://getsatisfaction.com/wibiya/topics/jquery_1_3_conflict
 1164+ http://getsatisfaction.com/wibiya/topics/wibiya_not_playing_nice_with_frontpage_slideshow_using_mootools
 1165+ //-->
 1166+
 1167+ <script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script><noscript>Google Analytics Script</noscript>
 1168+ <script type="text/javascript">try{_uacct = "UA-1942730-1";urchinTracker(); }catch(e){}</script><noscript>Google Analytics</noscript>
 1169+</body>
 1170+</html>
Index: trunk/extensions/Ratings/starrating/star-rating/jquery.rating.js
@@ -0,0 +1,383 @@
 2+/*
 3+ ### jQuery Star Rating Plugin v3.13 - 2009-03-26 ###
 4+ * Home: http://www.fyneworks.com/jquery/star-rating/
 5+ * Code: http://code.google.com/p/jquery-star-rating-plugin/
 6+ *
 7+ * Dual licensed under the MIT and GPL licenses:
 8+ * http://www.opensource.org/licenses/mit-license.php
 9+ * http://www.gnu.org/licenses/gpl.html
 10+ ###
 11+*/
 12+
 13+/*# AVOID COLLISIONS #*/
 14+;if(window.jQuery) (function($){
 15+/*# AVOID COLLISIONS #*/
 16+
 17+ // IE6 Background Image Fix
 18+ if ($.browser.msie) try { document.execCommand("BackgroundImageCache", false, true)} catch(e) { };
 19+ // Thanks to http://www.visualjquery.com/rating/rating_redux.html
 20+
 21+ // plugin initialization
 22+ $.fn.rating = function(options){
 23+ if(this.length==0) return this; // quick fail
 24+
 25+ // Handle API methods
 26+ if(typeof arguments[0]=='string'){
 27+ // Perform API methods on individual elements
 28+ if(this.length>1){
 29+ var args = arguments;
 30+ return this.each(function(){
 31+ $.fn.rating.apply($(this), args);
 32+ });
 33+ };
 34+ // Invoke API method handler
 35+ $.fn.rating[arguments[0]].apply(this, $.makeArray(arguments).slice(1) || []);
 36+ // Quick exit...
 37+ return this;
 38+ };
 39+
 40+ // Initialize options for this call
 41+ var options = $.extend(
 42+ {}/* new object */,
 43+ $.fn.rating.options/* default options */,
 44+ options || {} /* just-in-time options */
 45+ );
 46+
 47+ // Allow multiple controls with the same name by making each call unique
 48+ $.fn.rating.calls++;
 49+
 50+ // loop through each matched element
 51+ this
 52+ .not('.star-rating-applied')
 53+ .addClass('star-rating-applied')
 54+ .each(function(){
 55+
 56+ // Load control parameters / find context / etc
 57+ var control, input = $(this);
 58+ var eid = (this.name || 'unnamed-rating').replace(/\[|\]/g, '_').replace(/^\_+|\_+$/g,'');
 59+ var context = $(this.form || document.body);
 60+
 61+ // FIX: http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=23
 62+ var raters = context.data('rating');
 63+ if(!raters || raters.call!=$.fn.rating.calls) raters = { count:0, call:$.fn.rating.calls };
 64+ var rater = raters[eid];
 65+
 66+ // if rater is available, verify that the control still exists
 67+ if(rater) control = rater.data('rating');
 68+
 69+ if(rater && control)//{// save a byte!
 70+ // add star to control if rater is available and the same control still exists
 71+ control.count++;
 72+
 73+ //}// save a byte!
 74+ else{
 75+ // create new control if first star or control element was removed/replaced
 76+
 77+ // Initialize options for this raters
 78+ control = $.extend(
 79+ {}/* new object */,
 80+ options || {} /* current call options */,
 81+ ($.metadata? input.metadata(): ($.meta?input.data():null)) || {}, /* metadata options */
 82+ { count:0, stars: [], inputs: [] }
 83+ );
 84+
 85+ // increment number of rating controls
 86+ control.serial = raters.count++;
 87+
 88+ // create rating element
 89+ rater = $('<span class="star-rating-control" style="position:fixed" />');
 90+ input.before(rater);
 91+
 92+ // Mark element for initialization (once all stars are ready)
 93+ rater.addClass('rating-to-be-drawn');
 94+
 95+ // Accept readOnly setting from 'disabled' property
 96+ if(input.attr('disabled')) control.readOnly = true;
 97+
 98+ // Create 'cancel' button
 99+ rater.append(
 100+ control.cancel = $('<div class="rating-cancel"><a title="' + control.cancel + '">' + control.cancelValue + '</a></div>')
 101+ .mouseover(function(){
 102+ $(this).rating('drain');
 103+ $(this).addClass('star-rating-hover');
 104+ //$(this).rating('focus');
 105+ })
 106+ .mouseout(function(){
 107+ $(this).rating('draw');
 108+ $(this).removeClass('star-rating-hover');
 109+ //$(this).rating('blur');
 110+ })
 111+ .click(function(){
 112+ $(this).rating('select');
 113+ })
 114+ .data('rating', control)
 115+ );
 116+
 117+ }; // first element of group
 118+
 119+ // insert rating star
 120+ var star = $('<div class="star-rating rater-'+ control.serial +'"><a title="' + (this.title || this.value) + '">' + this.value + '</a></div>');
 121+ rater.append(star);
 122+
 123+ // inherit attributes from input element
 124+ if(this.id) star.attr('id', this.id);
 125+ if(this.className) star.addClass(this.className);
 126+
 127+ // Half-stars?
 128+ if(control.half) control.split = 2;
 129+
 130+ // Prepare division control
 131+ if(typeof control.split=='number' && control.split>0){
 132+ var stw = ($.fn.width ? star.width() : 0) || control.starWidth;
 133+ var spi = (control.count % control.split), spw = Math.floor(stw/control.split);
 134+ star
 135+ // restrict star's width and hide overflow (already in CSS)
 136+ .width(spw)
 137+ // move the star left by using a negative margin
 138+ // this is work-around to IE's stupid box model (position:relative doesn't work)
 139+ .find('a').css({ 'margin-left':'-'+ (spi*spw) +'px' })
 140+ };
 141+
 142+ // readOnly?
 143+ if(control.readOnly)//{ //save a byte!
 144+ // Mark star as readOnly so user can customize display
 145+ star.addClass('star-rating-readonly');
 146+ //} //save a byte!
 147+ else//{ //save a byte!
 148+ // Enable hover css effects
 149+ star.addClass('star-rating-live')
 150+ // Attach mouse events
 151+ .mouseover(function(){
 152+ $(this).rating('fill');
 153+ $(this).rating('focus');
 154+ })
 155+ .mouseout(function(){
 156+ $(this).rating('draw');
 157+ $(this).rating('blur');
 158+ })
 159+ .click(function(){
 160+ $(this).rating('select');
 161+ })
 162+ ;
 163+ //}; //save a byte!
 164+
 165+ // set current selection
 166+ if(this.checked) control.current = star;
 167+
 168+ // hide input element
 169+ input.hide();
 170+
 171+ // backward compatibility, form element to plugin
 172+ input.change(function(){
 173+ $(this).rating('select');
 174+ });
 175+
 176+ // attach reference to star to input element and vice-versa
 177+ star.data('rating.input', input.data('rating.star', star));
 178+
 179+ // store control information in form (or body when form not available)
 180+ control.stars[control.stars.length] = star[0];
 181+ control.inputs[control.inputs.length] = input[0];
 182+ control.rater = raters[eid] = rater;
 183+ control.context = context;
 184+
 185+ input.data('rating', control);
 186+ rater.data('rating', control);
 187+ star.data('rating', control);
 188+ context.data('rating', raters);
 189+ }); // each element
 190+
 191+ // Initialize ratings (first draw)
 192+ $('.rating-to-be-drawn').rating('draw').removeClass('rating-to-be-drawn');
 193+
 194+ return this; // don't break the chain...
 195+ };
 196+
 197+ /*--------------------------------------------------------*/
 198+
 199+ /*
 200+ ### Core functionality and API ###
 201+ */
 202+ $.extend($.fn.rating, {
 203+ // Used to append a unique serial number to internal control ID
 204+ // each time the plugin is invoked so same name controls can co-exist
 205+ calls: 0,
 206+
 207+ focus: function(){
 208+ var control = this.data('rating'); if(!control) return this;
 209+ if(!control.focus) return this; // quick fail if not required
 210+ // find data for event
 211+ var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
 212+ // focus handler, as requested by focusdigital.co.uk
 213+ if(control.focus) control.focus.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
 214+ }, // $.fn.rating.focus
 215+
 216+ blur: function(){
 217+ var control = this.data('rating'); if(!control) return this;
 218+ if(!control.blur) return this; // quick fail if not required
 219+ // find data for event
 220+ var input = $(this).data('rating.input') || $( this.tagName=='INPUT' ? this : null );
 221+ // blur handler, as requested by focusdigital.co.uk
 222+ if(control.blur) control.blur.apply(input[0], [input.val(), $('a', input.data('rating.star'))[0]]);
 223+ }, // $.fn.rating.blur
 224+
 225+ fill: function(){ // fill to the current mouse position.
 226+ var control = this.data('rating'); if(!control) return this;
 227+ // do not execute when control is in read-only mode
 228+ if(control.readOnly) return;
 229+ // Reset all stars and highlight them up to this element
 230+ this.rating('drain');
 231+ this.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-hover');
 232+ },// $.fn.rating.fill
 233+
 234+ drain: function() { // drain all the stars.
 235+ var control = this.data('rating'); if(!control) return this;
 236+ // do not execute when control is in read-only mode
 237+ if(control.readOnly) return;
 238+ // Reset all stars
 239+ control.rater.children().filter('.rater-'+ control.serial).removeClass('star-rating-on').removeClass('star-rating-hover');
 240+ },// $.fn.rating.drain
 241+
 242+ draw: function(){ // set value and stars to reflect current selection
 243+ var control = this.data('rating'); if(!control) return this;
 244+ // Clear all stars
 245+ this.rating('drain');
 246+ // Set control value
 247+ if(control.current){
 248+ control.current.data('rating.input').attr('checked','checked');
 249+ control.current.prevAll().andSelf().filter('.rater-'+ control.serial).addClass('star-rating-on');
 250+ }
 251+ else
 252+ $(control.inputs).removeAttr('checked');
 253+ // Show/hide 'cancel' button
 254+ control.cancel[/*control.readOnly || control.required?*/'hide'/*:'show'*/]();
 255+ // Add/remove read-only classes to remove hand pointer
 256+ this.siblings()[control.readOnly?'addClass':'removeClass']('star-rating-readonly');
 257+ },// $.fn.rating.draw
 258+
 259+
 260+
 261+
 262+
 263+ select: function(value,wantCallBack){ // select a value
 264+
 265+ // ***** MODIFICATION *****
 266+ // Thanks to faivre.thomas - http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=27
 267+ //
 268+ // ***** LIST OF MODIFICATION *****
 269+ // ***** added Parameter wantCallBack : false if you don't want a callback. true or undefined if you want postback to be performed at the end of this method'
 270+ // ***** recursive calls to this method were like : ... .rating('select') it's now like .rating('select',undefined,wantCallBack); (parameters are set.)
 271+ // ***** line which is calling callback
 272+ // ***** /LIST OF MODIFICATION *****
 273+
 274+ var control = this.data('rating'); if(!control) return this;
 275+ // do not execute when control is in read-only mode
 276+ if(control.readOnly) return;
 277+ // clear selection
 278+ control.current = null;
 279+ // programmatically (based on user input)
 280+ if(typeof value!='undefined'){
 281+ // select by index (0 based)
 282+ if(typeof value=='number')
 283+ return $(control.stars[value]).rating('select',undefined,wantCallBack);
 284+ // select by literal value (must be passed as a string
 285+ if(typeof value=='string')
 286+ //return
 287+ $.each(control.stars, function(){
 288+ if($(this).data('rating.input').val()==value) $(this).rating('select',undefined,wantCallBack);
 289+ });
 290+ }
 291+ else
 292+ control.current = this[0].tagName=='INPUT' ?
 293+ this.data('rating.star') :
 294+ (this.is('.rater-'+ control.serial) ? this : null);
 295+
 296+ // Update rating control state
 297+ this.data('rating', control);
 298+ // Update display
 299+ this.rating('draw');
 300+ // find data for event
 301+ var input = $( control.current ? control.current.data('rating.input') : null );
 302+ // click callback, as requested here: http://plugins.jquery.com/node/1655
 303+
 304+ // **** MODIFICATION *****
 305+ // Thanks to faivre.thomas - http://code.google.com/p/jquery-star-rating-plugin/issues/detail?id=27
 306+ //
 307+ //old line doing the callback :
 308+ //if(control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
 309+ //
 310+ //new line doing the callback (if i want :)
 311+ if((wantCallBack ||wantCallBack == undefined) && control.callback) control.callback.apply(input[0], [input.val(), $('a', control.current)[0]]);// callback event
 312+ //to ensure retro-compatibility, wantCallBack must be considered as true by default
 313+ // **** /MODIFICATION *****
 314+
 315+ },// $.fn.rating.select
 316+
 317+
 318+
 319+
 320+
 321+ readOnly: function(toggle, disable){ // make the control read-only (still submits value)
 322+ var control = this.data('rating'); if(!control) return this;
 323+ // setread-only status
 324+ control.readOnly = toggle || toggle==undefined ? true : false;
 325+ // enable/disable control value submission
 326+ if(disable) $(control.inputs).attr("disabled", "disabled");
 327+ else $(control.inputs).removeAttr("disabled");
 328+ // Update rating control state
 329+ this.data('rating', control);
 330+ // Update display
 331+ this.rating('draw');
 332+ },// $.fn.rating.readOnly
 333+
 334+ disable: function(){ // make read-only and never submit value
 335+ this.rating('readOnly', true, true);
 336+ },// $.fn.rating.disable
 337+
 338+ enable: function(){ // make read/write and submit value
 339+ this.rating('readOnly', false, false);
 340+ }// $.fn.rating.select
 341+
 342+ });
 343+
 344+ /*--------------------------------------------------------*/
 345+
 346+ /*
 347+ ### Default Settings ###
 348+ eg.: You can override default control like this:
 349+ $.fn.rating.options.cancel = 'Clear';
 350+ */
 351+ $.fn.rating.options = { //$.extend($.fn.rating, { options: {
 352+ cancel: 'Cancel Rating', // advisory title for the 'cancel' link
 353+ cancelValue: '', // value to submit when user click the 'cancel' link
 354+ split: 0, // split the star into how many parts?
 355+
 356+ // Width of star image in case the plugin can't work it out. This can happen if
 357+ // the jQuery.dimensions plugin is not available OR the image is hidden at installation
 358+ starWidth: 16//,
 359+
 360+ //NB.: These don't need to be pre-defined (can be undefined/null) so let's save some code!
 361+ //half: false, // just a shortcut to control.split = 2
 362+ //required: false, // disables the 'cancel' button so user can only select one of the specified values
 363+ //readOnly: false, // disable rating plugin interaction/ values cannot be changed
 364+ //focus: function(){}, // executed when stars are focused
 365+ //blur: function(){}, // executed when stars are focused
 366+ //callback: function(){}, // executed when a star is clicked
 367+ }; //} });
 368+
 369+ /*--------------------------------------------------------*/
 370+
 371+ /*
 372+ ### Default implementation ###
 373+ The plugin will attach itself to file inputs
 374+ with the class 'multi' when the page loads
 375+ */
 376+ $(function(){
 377+ $('input[type=radio].star').rating();
 378+ });
 379+
 380+
 381+
 382+/*# AVOID COLLISIONS #*/
 383+})(jQuery);
 384+/*# AVOID COLLISIONS #*/
Property changes on: trunk/extensions/Ratings/starrating/star-rating/jquery.rating.js
___________________________________________________________________
Added: svn:eol-style
1385 + native
Index: trunk/extensions/Ratings/starrating/star-rating/star.gif
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: trunk/extensions/Ratings/starrating/star-rating/star.gif
___________________________________________________________________
Added: svn:mime-type
2386 + application/octet-stream
Index: trunk/extensions/Ratings/starrating/ext.ratings.stars.js
@@ -0,0 +1,163 @@
 2+/**
 3+ * JavasSript for the Ratings extension.
 4+ * @see http://www.mediawiki.org/wiki/Extension:Ratings
 5+ *
 6+ * @licence GNU GPL v3 or later
 7+ * @author Jeroen De Dauw <jeroendedauw at gmail dot com>
 8+ */
 9+
 10+(function($) { $( document ).ready( function() {
 11+
 12+ var canRate = true; // TODO
 13+
 14+ if ( !canRate && !window.wgRatingsShowDisabled ) {
 15+ // If the user is not allowed to rate and ratings should not be
 16+ // shown disabled for unauthorized users, simply don't bother any setup.
 17+ return;
 18+ }
 19+
 20+ /**
 21+ * Self executing function to setup the rating stars on the page.
 22+ * This is done by finding all inputs belonging to a single rating
 23+ * element and initiating them as a rating element.
 24+ */
 25+ (function setupRatingElements() {
 26+ var groups = [];
 27+
 28+ $.each($(".starrating"), function(i,v) {
 29+ groups.push( $(this).attr( 'name' ) );
 30+ });
 31+
 32+ groups = $.unique( groups );
 33+
 34+ for ( i in groups ) {
 35+ $( "input[name='" + groups[i] + "']" ).rating({
 36+ callback: function( value, link ){
 37+ var self = $(this);
 38+ submitRating( self.attr( 'page' ), self.attr( 'tag' ), value );
 39+ },
 40+ });
 41+ }
 42+
 43+ $( '.starrating-div' ).css( 'display', 'inline' );
 44+
 45+ if ( canRate ) {
 46+ initGetRatings();
 47+ }
 48+ else {
 49+ $.each($(".starrating"), function(i,v) {
 50+ var self = $(this);
 51+
 52+ if ( typeof self.attr( 'page' ) != 'undefined' ) {
 53+ self.rating( 'disable' );
 54+ }
 55+ });
 56+ }
 57+
 58+ })();
 59+
 60+ /**
 61+ * Self executing function to set the current values of the rating elements.
 62+ * This is done by finding all tags for all pages that should
 63+ * be displayed and then gathering this data via the API to show
 64+ * the current vote values.
 65+ */
 66+ function initGetRatings() {
 67+ var ratings = {};
 68+
 69+ $.each($(".starrating"), function(i,v) {
 70+ var self = $(this);
 71+
 72+ if ( typeof self.attr( 'page' ) != 'undefined' ) {
 73+ if ( !ratings[self.attr( 'page' )] ) {
 74+ ratings[self.attr( 'page' )] = [];
 75+ }
 76+
 77+ ratings[self.attr( 'page' )].push( self.attr( 'tag' ) );
 78+ }
 79+ });
 80+
 81+ for ( i in ratings ) {
 82+ getRatingsForPage( i, $.unique( ratings[i] ) );
 83+ }
 84+ }
 85+
 86+ /**
 87+ * Obtain the vote values for a set of tags of a single page,
 88+ * and then find and update the corresponding rating stars.
 89+ *
 90+ * @param {string} page
 91+ * @param {Array} tags
 92+ */
 93+ function getRatingsForPage( page, tags ) {
 94+ $.getJSON(
 95+ wgScriptPath + '/api.php',
 96+ {
 97+ 'action': 'query',
 98+ 'format': 'json',
 99+ 'list': 'ratings',
 100+ 'qrpage': page,
 101+ 'qrtags': tags.join( '|' )
 102+ },
 103+ function( data ) {
 104+ if ( data.userratings ) {
 105+ initRatingElementsForPage( page, data.userratings );
 106+ }
 107+ else {
 108+ // TODO
 109+ }
 110+ }
 111+ );
 112+ }
 113+
 114+ /**
 115+ * Loop over all rating elements for the page and set their value when available.
 116+ *
 117+ * @param {string} page
 118+ * @param {Array} tagValues
 119+ */
 120+ function initRatingElementsForPage( page, tagValues ) {
 121+ $.each($(".starrating"), function(i,v) {
 122+ var self = $(this);
 123+
 124+ if ( typeof self.attr( 'page' ) != 'undefined' && self.attr( 'page' ) == page ) {
 125+ if ( typeof tagValues[self.attr( 'tag' )] != 'undefined' ) {
 126+ self.rating( 'select', tagValues[self.attr( 'tag' )], false );
 127+ }
 128+ }
 129+ });
 130+ }
 131+
 132+ /**
 133+ * Submit a rating.
 134+ *
 135+ * @param {string} page
 136+ * @param {string} tag
 137+ * @param {integer} value
 138+ */
 139+ function submitRating( page, tag, value ) {
 140+ $.post(
 141+ wgScriptPath + '/api.php',
 142+ {
 143+ 'action': 'dorating',
 144+ 'format': 'json',
 145+ 'pagename': page,
 146+ 'tag': tag,
 147+ 'value': value
 148+ },
 149+ function( data ) {
 150+ if ( data.error && data.error.info ) {
 151+ alert( data.error.info );
 152+ }
 153+ else if ( data.result.success ) {
 154+ // TODO
 155+ }
 156+ else {
 157+ alert( 'Failed to submit rating' ) // TODO
 158+ }
 159+ },
 160+ 'json'
 161+ );
 162+ }
 163+
 164+} ); })(jQuery);
\ No newline at end of file
Property changes on: trunk/extensions/Ratings/starrating/ext.ratings.stars.js
___________________________________________________________________
Added: svn:eol-style
1165 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r86017follow up to r85993jeroendedauw00:25, 14 April 2011

Comments

#Comment by Reedy (talk | contribs)   00:05, 14 April 2011
while ( $vote = $votes->fetchObject() ) {

should really be

foreach( $votes as $vote ) {
#Comment by Jeroen De Dauw (talk | contribs)   00:24, 14 April 2011

That also seems to work, which I find rather odd, since there must be some reason I started using the while loop instead of a simple foreach at some point. Any idea why that would be? Maybe this did not work with MW 1.15.x or so?

#Comment by Reedy (talk | contribs)   00:26, 14 April 2011

Nope. It's been the case as long as I can remember.. God knows! Heh :)

Status & tagging log