r70831 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r70830‎ | r70831 | r70832 >
Date:16:19, 10 August 2010
Author:tkriplean
Status:deferred (Comments)
Tags:
Comment:
Copy-importing (no history) Reflect repo
Modified paths:
  • /trunk/extensions/Reflect (added) (history)
  • /trunk/extensions/Reflect/LICENSE (added) (history)
  • /trunk/extensions/Reflect/Reflect.php (added) (history)
  • /trunk/extensions/Reflect/client (added) (history)
  • /trunk/extensions/Reflect/client/css (added) (history)
  • /trunk/extensions/Reflect/client/css/jquery.ui.css (added) (history)
  • /trunk/extensions/Reflect/client/css/reflect.css (added) (history)
  • /trunk/extensions/Reflect/client/css/reflect.liquidthreads.css (added) (history)
  • /trunk/extensions/Reflect/client/css/reflect.study.css (added) (history)
  • /trunk/extensions/Reflect/client/js (added) (history)
  • /trunk/extensions/Reflect/client/js/reflect.js (added) (history)
  • /trunk/extensions/Reflect/client/js/reflect.liquidthreads.js (added) (history)
  • /trunk/extensions/Reflect/client/js/reflect.study.js (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party/inheritance.js (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party/jquery-1.4.2.js (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party/jquery.color.js (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party/jquery.highlight.js (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party/jquery.jqote2.min.js (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party/jquery.noblecount.min.js (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party/jquery.pulse.js (added) (history)
  • /trunk/extensions/Reflect/client/js/third_party/json2.js (added) (history)
  • /trunk/extensions/Reflect/client/media (added) (history)
  • /trunk/extensions/Reflect/client/media/bullet.png (added) (history)
  • /trunk/extensions/Reflect/client/media/cancel.png (added) (history)
  • /trunk/extensions/Reflect/client/media/cancel2.png (added) (history)
  • /trunk/extensions/Reflect/client/media/cancel_black.png (added) (history)
  • /trunk/extensions/Reflect/client/media/check.png (added) (history)
  • /trunk/extensions/Reflect/client/media/check2.png (added) (history)
  • /trunk/extensions/Reflect/client/media/comment-flag-hover.png (added) (history)
  • /trunk/extensions/Reflect/client/media/comment-flag.png (added) (history)
  • /trunk/extensions/Reflect/client/media/delete_gray.png (added) (history)
  • /trunk/extensions/Reflect/client/media/delete_red.png (added) (history)
  • /trunk/extensions/Reflect/client/media/dispute_gray.png (added) (history)
  • /trunk/extensions/Reflect/client/media/dispute_yellow.png (added) (history)
  • /trunk/extensions/Reflect/client/media/edit.png (added) (history)
  • /trunk/extensions/Reflect/client/media/edit_hover.png (added) (history)
  • /trunk/extensions/Reflect/client/media/help.png (added) (history)
  • /trunk/extensions/Reflect/client/media/response-maybe.png (added) (history)
  • /trunk/extensions/Reflect/client/media/response-no.png (added) (history)
  • /trunk/extensions/Reflect/client/media/response-yes.png (added) (history)
  • /trunk/extensions/Reflect/client/media/signal_maybe.png (added) (history)
  • /trunk/extensions/Reflect/client/media/signal_no.png (added) (history)
  • /trunk/extensions/Reflect/client/media/signal_yes.png (added) (history)
  • /trunk/extensions/Reflect/client/templates (added) (history)
  • /trunk/extensions/Reflect/client/templates/templates.html (added) (history)
  • /trunk/extensions/Reflect/reflect.sql (added) (history)
  • /trunk/extensions/Reflect/server (added) (history)
  • /trunk/extensions/Reflect/server/api (added) (history)
  • /trunk/extensions/Reflect/server/api/ApiReflectAction.php (added) (history)
  • /trunk/extensions/Reflect/server/api/ApiReflectStudyAction.php (added) (history)
  • /trunk/extensions/Reflect/server/classes (added) (history)
  • /trunk/extensions/Reflect/server/classes/Dispatch.php (added) (history)
  • /trunk/extensions/Reflect/server/i18n (added) (history)
  • /trunk/extensions/Reflect/server/i18n/Rf.alias.php (added) (history)
  • /trunk/extensions/Reflect/server/i18n/Rf.i18n.php (added) (history)
  • /trunk/extensions/Reflect/server/i18n/Rf.magic.php (added) (history)

Diff [purge]

Index: trunk/extensions/Reflect/LICENSE
@@ -0,0 +1,339 @@
 2+ GNU GENERAL PUBLIC LICENSE
 3+ Version 2, June 1991
 4+
 5+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
 6+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 7+ Everyone is permitted to copy and distribute verbatim copies
 8+ of this license document, but changing it is not allowed.
 9+
 10+ Preamble
 11+
 12+ The licenses for most software are designed to take away your
 13+freedom to share and change it. By contrast, the GNU General Public
 14+License is intended to guarantee your freedom to share and change free
 15+software--to make sure the software is free for all its users. This
 16+General Public License applies to most of the Free Software
 17+Foundation's software and to any other program whose authors commit to
 18+using it. (Some other Free Software Foundation software is covered by
 19+the GNU Lesser General Public License instead.) You can apply it to
 20+your programs, too.
 21+
 22+ When we speak of free software, we are referring to freedom, not
 23+price. Our General Public Licenses are designed to make sure that you
 24+have the freedom to distribute copies of free software (and charge for
 25+this service if you wish), that you receive source code or can get it
 26+if you want it, that you can change the software or use pieces of it
 27+in new free programs; and that you know you can do these things.
 28+
 29+ To protect your rights, we need to make restrictions that forbid
 30+anyone to deny you these rights or to ask you to surrender the rights.
 31+These restrictions translate to certain responsibilities for you if you
 32+distribute copies of the software, or if you modify it.
 33+
 34+ For example, if you distribute copies of such a program, whether
 35+gratis or for a fee, you must give the recipients all the rights that
 36+you have. You must make sure that they, too, receive or can get the
 37+source code. And you must show them these terms so they know their
 38+rights.
 39+
 40+ We protect your rights with two steps: (1) copyright the software, and
 41+(2) offer you this license which gives you legal permission to copy,
 42+distribute and/or modify the software.
 43+
 44+ Also, for each author's protection and ours, we want to make certain
 45+that everyone understands that there is no warranty for this free
 46+software. If the software is modified by someone else and passed on, we
 47+want its recipients to know that what they have is not the original, so
 48+that any problems introduced by others will not reflect on the original
 49+authors' reputations.
 50+
 51+ Finally, any free program is threatened constantly by software
 52+patents. We wish to avoid the danger that redistributors of a free
 53+program will individually obtain patent licenses, in effect making the
 54+program proprietary. To prevent this, we have made it clear that any
 55+patent must be licensed for everyone's free use or not licensed at all.
 56+
 57+ The precise terms and conditions for copying, distribution and
 58+modification follow.
 59+
 60+ GNU GENERAL PUBLIC LICENSE
 61+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 62+
 63+ 0. This License applies to any program or other work which contains
 64+a notice placed by the copyright holder saying it may be distributed
 65+under the terms of this General Public License. The "Program", below,
 66+refers to any such program or work, and a "work based on the Program"
 67+means either the Program or any derivative work under copyright law:
 68+that is to say, a work containing the Program or a portion of it,
 69+either verbatim or with modifications and/or translated into another
 70+language. (Hereinafter, translation is included without limitation in
 71+the term "modification".) Each licensee is addressed as "you".
 72+
 73+Activities other than copying, distribution and modification are not
 74+covered by this License; they are outside its scope. The act of
 75+running the Program is not restricted, and the output from the Program
 76+is covered only if its contents constitute a work based on the
 77+Program (independent of having been made by running the Program).
 78+Whether that is true depends on what the Program does.
 79+
 80+ 1. You may copy and distribute verbatim copies of the Program's
 81+source code as you receive it, in any medium, provided that you
 82+conspicuously and appropriately publish on each copy an appropriate
 83+copyright notice and disclaimer of warranty; keep intact all the
 84+notices that refer to this License and to the absence of any warranty;
 85+and give any other recipients of the Program a copy of this License
 86+along with the Program.
 87+
 88+You may charge a fee for the physical act of transferring a copy, and
 89+you may at your option offer warranty protection in exchange for a fee.
 90+
 91+ 2. You may modify your copy or copies of the Program or any portion
 92+of it, thus forming a work based on the Program, and copy and
 93+distribute such modifications or work under the terms of Section 1
 94+above, provided that you also meet all of these conditions:
 95+
 96+ a) You must cause the modified files to carry prominent notices
 97+ stating that you changed the files and the date of any change.
 98+
 99+ b) You must cause any work that you distribute or publish, that in
 100+ whole or in part contains or is derived from the Program or any
 101+ part thereof, to be licensed as a whole at no charge to all third
 102+ parties under the terms of this License.
 103+
 104+ c) If the modified program normally reads commands interactively
 105+ when run, you must cause it, when started running for such
 106+ interactive use in the most ordinary way, to print or display an
 107+ announcement including an appropriate copyright notice and a
 108+ notice that there is no warranty (or else, saying that you provide
 109+ a warranty) and that users may redistribute the program under
 110+ these conditions, and telling the user how to view a copy of this
 111+ License. (Exception: if the Program itself is interactive but
 112+ does not normally print such an announcement, your work based on
 113+ the Program is not required to print an announcement.)
 114+
 115+These requirements apply to the modified work as a whole. If
 116+identifiable sections of that work are not derived from the Program,
 117+and can be reasonably considered independent and separate works in
 118+themselves, then this License, and its terms, do not apply to those
 119+sections when you distribute them as separate works. But when you
 120+distribute the same sections as part of a whole which is a work based
 121+on the Program, the distribution of the whole must be on the terms of
 122+this License, whose permissions for other licensees extend to the
 123+entire whole, and thus to each and every part regardless of who wrote it.
 124+
 125+Thus, it is not the intent of this section to claim rights or contest
 126+your rights to work written entirely by you; rather, the intent is to
 127+exercise the right to control the distribution of derivative or
 128+collective works based on the Program.
 129+
 130+In addition, mere aggregation of another work not based on the Program
 131+with the Program (or with a work based on the Program) on a volume of
 132+a storage or distribution medium does not bring the other work under
 133+the scope of this License.
 134+
 135+ 3. You may copy and distribute the Program (or a work based on it,
 136+under Section 2) in object code or executable form under the terms of
 137+Sections 1 and 2 above provided that you also do one of the following:
 138+
 139+ a) Accompany it with the complete corresponding machine-readable
 140+ source code, which must be distributed under the terms of Sections
 141+ 1 and 2 above on a medium customarily used for software interchange; or,
 142+
 143+ b) Accompany it with a written offer, valid for at least three
 144+ years, to give any third party, for a charge no more than your
 145+ cost of physically performing source distribution, a complete
 146+ machine-readable copy of the corresponding source code, to be
 147+ distributed under the terms of Sections 1 and 2 above on a medium
 148+ customarily used for software interchange; or,
 149+
 150+ c) Accompany it with the information you received as to the offer
 151+ to distribute corresponding source code. (This alternative is
 152+ allowed only for noncommercial distribution and only if you
 153+ received the program in object code or executable form with such
 154+ an offer, in accord with Subsection b above.)
 155+
 156+The source code for a work means the preferred form of the work for
 157+making modifications to it. For an executable work, complete source
 158+code means all the source code for all modules it contains, plus any
 159+associated interface definition files, plus the scripts used to
 160+control compilation and installation of the executable. However, as a
 161+special exception, the source code distributed need not include
 162+anything that is normally distributed (in either source or binary
 163+form) with the major components (compiler, kernel, and so on) of the
 164+operating system on which the executable runs, unless that component
 165+itself accompanies the executable.
 166+
 167+If distribution of executable or object code is made by offering
 168+access to copy from a designated place, then offering equivalent
 169+access to copy the source code from the same place counts as
 170+distribution of the source code, even though third parties are not
 171+compelled to copy the source along with the object code.
 172+
 173+ 4. You may not copy, modify, sublicense, or distribute the Program
 174+except as expressly provided under this License. Any attempt
 175+otherwise to copy, modify, sublicense or distribute the Program is
 176+void, and will automatically terminate your rights under this License.
 177+However, parties who have received copies, or rights, from you under
 178+this License will not have their licenses terminated so long as such
 179+parties remain in full compliance.
 180+
 181+ 5. You are not required to accept this License, since you have not
 182+signed it. However, nothing else grants you permission to modify or
 183+distribute the Program or its derivative works. These actions are
 184+prohibited by law if you do not accept this License. Therefore, by
 185+modifying or distributing the Program (or any work based on the
 186+Program), you indicate your acceptance of this License to do so, and
 187+all its terms and conditions for copying, distributing or modifying
 188+the Program or works based on it.
 189+
 190+ 6. Each time you redistribute the Program (or any work based on the
 191+Program), the recipient automatically receives a license from the
 192+original licensor to copy, distribute or modify the Program subject to
 193+these terms and conditions. You may not impose any further
 194+restrictions on the recipients' exercise of the rights granted herein.
 195+You are not responsible for enforcing compliance by third parties to
 196+this License.
 197+
 198+ 7. If, as a consequence of a court judgment or allegation of patent
 199+infringement or for any other reason (not limited to patent issues),
 200+conditions are imposed on you (whether by court order, agreement or
 201+otherwise) that contradict the conditions of this License, they do not
 202+excuse you from the conditions of this License. If you cannot
 203+distribute so as to satisfy simultaneously your obligations under this
 204+License and any other pertinent obligations, then as a consequence you
 205+may not distribute the Program at all. For example, if a patent
 206+license would not permit royalty-free redistribution of the Program by
 207+all those who receive copies directly or indirectly through you, then
 208+the only way you could satisfy both it and this License would be to
 209+refrain entirely from distribution of the Program.
 210+
 211+If any portion of this section is held invalid or unenforceable under
 212+any particular circumstance, the balance of the section is intended to
 213+apply and the section as a whole is intended to apply in other
 214+circumstances.
 215+
 216+It is not the purpose of this section to induce you to infringe any
 217+patents or other property right claims or to contest validity of any
 218+such claims; this section has the sole purpose of protecting the
 219+integrity of the free software distribution system, which is
 220+implemented by public license practices. Many people have made
 221+generous contributions to the wide range of software distributed
 222+through that system in reliance on consistent application of that
 223+system; it is up to the author/donor to decide if he or she is willing
 224+to distribute software through any other system and a licensee cannot
 225+impose that choice.
 226+
 227+This section is intended to make thoroughly clear what is believed to
 228+be a consequence of the rest of this License.
 229+
 230+ 8. If the distribution and/or use of the Program is restricted in
 231+certain countries either by patents or by copyrighted interfaces, the
 232+original copyright holder who places the Program under this License
 233+may add an explicit geographical distribution limitation excluding
 234+those countries, so that distribution is permitted only in or among
 235+countries not thus excluded. In such case, this License incorporates
 236+the limitation as if written in the body of this License.
 237+
 238+ 9. The Free Software Foundation may publish revised and/or new versions
 239+of the General Public License from time to time. Such new versions will
 240+be similar in spirit to the present version, but may differ in detail to
 241+address new problems or concerns.
 242+
 243+Each version is given a distinguishing version number. If the Program
 244+specifies a version number of this License which applies to it and "any
 245+later version", you have the option of following the terms and conditions
 246+either of that version or of any later version published by the Free
 247+Software Foundation. If the Program does not specify a version number of
 248+this License, you may choose any version ever published by the Free Software
 249+Foundation.
 250+
 251+ 10. If you wish to incorporate parts of the Program into other free
 252+programs whose distribution conditions are different, write to the author
 253+to ask for permission. For software which is copyrighted by the Free
 254+Software Foundation, write to the Free Software Foundation; we sometimes
 255+make exceptions for this. Our decision will be guided by the two goals
 256+of preserving the free status of all derivatives of our free software and
 257+of promoting the sharing and reuse of software generally.
 258+
 259+ NO WARRANTY
 260+
 261+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 262+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
 263+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
 264+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
 265+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 266+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
 267+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
 268+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
 269+REPAIR OR CORRECTION.
 270+
 271+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
 272+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
 273+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
 274+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
 275+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
 276+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
 277+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 278+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 279+POSSIBILITY OF SUCH DAMAGES.
 280+
 281+ END OF TERMS AND CONDITIONS
 282+
 283+ How to Apply These Terms to Your New Programs
 284+
 285+ If you develop a new program, and you want it to be of the greatest
 286+possible use to the public, the best way to achieve this is to make it
 287+free software which everyone can redistribute and change under these terms.
 288+
 289+ To do so, attach the following notices to the program. It is safest
 290+to attach them to the start of each source file to most effectively
 291+convey the exclusion of warranty; and each file should have at least
 292+the "copyright" line and a pointer to where the full notice is found.
 293+
 294+ <one line to give the program's name and a brief idea of what it does.>
 295+ Copyright (C) <year> <name of author>
 296+
 297+ This program is free software; you can redistribute it and/or modify
 298+ it under the terms of the GNU General Public License as published by
 299+ the Free Software Foundation; either version 2 of the License, or
 300+ (at your option) any later version.
 301+
 302+ This program is distributed in the hope that it will be useful,
 303+ but WITHOUT ANY WARRANTY; without even the implied warranty of
 304+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 305+ GNU General Public License for more details.
 306+
 307+ You should have received a copy of the GNU General Public License along
 308+ with this program; if not, write to the Free Software Foundation, Inc.,
 309+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 310+
 311+Also add information on how to contact you by electronic and paper mail.
 312+
 313+If the program is interactive, make it output a short notice like this
 314+when it starts in an interactive mode:
 315+
 316+ Gnomovision version 69, Copyright (C) year name of author
 317+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
 318+ This is free software, and you are welcome to redistribute it
 319+ under certain conditions; type `show c' for details.
 320+
 321+The hypothetical commands `show w' and `show c' should show the appropriate
 322+parts of the General Public License. Of course, the commands you use may
 323+be called something other than `show w' and `show c'; they could even be
 324+mouse-clicks or menu items--whatever suits your program.
 325+
 326+You should also get your employer (if you work as a programmer) or your
 327+school, if any, to sign a "copyright disclaimer" for the program, if
 328+necessary. Here is a sample; alter the names:
 329+
 330+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
 331+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
 332+
 333+ <signature of Ty Coon>, 1 April 1989
 334+ Ty Coon, President of Vice
 335+
 336+This General Public License does not permit incorporating your program into
 337+proprietary programs. If your program is a subroutine library, you may
 338+consider it more useful to permit linking proprietary applications with the
 339+library. If this is what you want to do, use the GNU Lesser General
 340+Public License instead of this License.
Index: trunk/extensions/Reflect/reflect.sql
@@ -0,0 +1,77 @@
 2+CREATE TABLE /*$wgDBprefix*/reflect_bullet_current (
 3+ blc_id mediumint(9) NOT NULL AUTO_INCREMENT,
 4+
 5+ bl_id mediumint(9),
 6+ comment_id mediumint(9),
 7+ bl_rev_id mediumint(9),
 8+
 9+ PRIMARY KEY blc_id (blc_id),
 10+ FOREIGN KEY (comment_id) REFERENCES /*$wgDBprefix*/comments(comment_ID) ON DELETE SET NULL ON UPDATE CASCADE,
 11+ FOREIGN KEY (bl_id) REFERENCES /*$wgDBprefix*/reflect_bullets_revision(bl_id) ON DELETE CASCADE ON UPDATE CASCADE,
 12+ FOREIGN KEY (bl_rev_id) REFERENCES /*$wgDBprefix*/reflect_bullets_revision(bl_rev_id) ON DELETE CASCADE ON UPDATE CASCADE
 13+
 14+) /*$wgDBTableOptions*/;
 15+
 16+
 17+CREATE TABLE /*$wgDBprefix*/reflect_bullet_revision (
 18+
 19+ bl_rev_id mediumint(9) NOT NULL AUTO_INCREMENT,
 20+ bl_id mediumint(9) NOT NULL,
 21+ comment_id mediumint(9),
 22+
 23+ bl_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 24+ bl_user tinytext NOT NULL,
 25+
 26+ bl_text text NOT NULL,
 27+
 28+ PRIMARY KEY bl_rev_id (bl_rev_id),
 29+ INDEX (bl_id),
 30+ FOREIGN KEY (comment_id) REFERENCES /*$wgDBprefix*/comments(comment_ID) ON DELETE SET NULL ON UPDATE CASCADE
 31+) /*$wgDBTableOptions*/;
 32+
 33+
 34+CREATE TABLE /*$wgDBprefix*/reflect_highlight (
 35+ hl_id mediumint(9) NOT NULL AUTO_INCREMENT,
 36+ hl_element tinytext NOT NULL,
 37+ bl_id mediumint(9),
 38+ bl_rev_id mediumint(9),
 39+
 40+ PRIMARY KEY hl_id (hl_id),
 41+ FOREIGN KEY (bl_id) REFERENCES /*$wgDBprefix*/reflect_bullets_revision(bl_id) ON DELETE CASCADE ON UPDATE CASCADE,
 42+ FOREIGN KEY (bl_rev_id) REFERENCES /*$wgDBprefix*/reflect_bullets_revision(bl_rev_id) ON DELETE CASCADE ON UPDATE CASCADE
 43+
 44+) /*$wgDBTableOptions*/;
 45+
 46+CREATE TABLE /*$wgDBprefix*/reflect_response_revision (
 47+ rsp_rev_id mediumint(9) NOT NULL AUTO_INCREMENT,
 48+
 49+ rsp_id mediumint(9) NOT NULL,
 50+ bl_id mediumint(9) NOT NULL,
 51+
 52+ rsp_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 53+ rsp_user tinytext NOT NULL,
 54+
 55+ rsp_signal mediumint(9),
 56+
 57+ rsp_text text NOT NULL,
 58+
 59+ PRIMARY KEY rsp_rev_id (rsp_rev_id),
 60+ INDEX (rsp_id),
 61+ FOREIGN KEY (bl_id) REFERENCES /*$wgDBprefix*/reflect_bullets_revision(bl_id) ON DELETE CASCADE ON UPDATE CASCADE
 62+
 63+) /*$wgDBTableOptions*/;
 64+
 65+CREATE TABLE /*$wgDBprefix*/reflect_response_current(
 66+ rspc_id mediumint(9) NOT NULL AUTO_INCREMENT,
 67+ bl_id mediumint(9),
 68+ rsp_id mediumint(9),
 69+ rsp_rev_id mediumint(9),
 70+
 71+ PRIMARY KEY rspc_id (rspc_id),
 72+ FOREIGN KEY (bl_id) REFERENCES /*$wgDBprefix*/reflect_bullets_current(bl_id) ON DELETE CASCADE ON UPDATE CASCADE,
 73+ FOREIGN KEY (rsp_id) REFERENCES /*$wgDBprefix*/reflect_response_revision(rsp_id) ON DELETE CASCADE ON UPDATE CASCADE,
 74+ FOREIGN KEY (rsp_rev_id) REFERENCES /*$wgDBprefix*/reflect_response_revision(rsp_rev_id) ON DELETE CASCADE ON UPDATE CASCADE
 75+
 76+) /*$wgDBTableOptions*/;
 77+
 78+
Property changes on: trunk/extensions/Reflect/reflect.sql
___________________________________________________________________
Added: svn:eol-style
179 + native
Index: trunk/extensions/Reflect/server/i18n/Rf.alias.php
@@ -0,0 +1,14 @@
 2+<?php
 3+/**
 4+ * Aliases for special pages
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$aliases = array();
 11+
 12+/** English */
 13+$aliases['en'] = array();
 14+
 15+
Property changes on: trunk/extensions/Reflect/server/i18n/Rf.alias.php
___________________________________________________________________
Added: svn:eol-style
116 + native
Index: trunk/extensions/Reflect/server/i18n/Rf.i18n.php
@@ -0,0 +1,38 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for Reflect extension.
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ * @author Travis Kriplean <travis@cs.washington.edu>
 9+ * @licence GPL2
 10+ */
 11+
 12+$messages = array();
 13+
 14+$messages['en'] = array(
 15+ 'rf-bulleted' => "Hi $1,
 16+
 17+$2 has summarized a point that you made in the thread '$3'.
 18+
 19+Their summary: '$5'.
 20+
 21+You can verify whether $2 got your point right by visiting <$4>.
 22+
 23+You will be able to clarify your point if there is a misunderstanding.",
 24+
 25+ 'rf-bulleted-subject' => "[{{SITENAME}}] Your point was summarized by $2",
 26+
 27+ 'rf-responded' => "Hi $1,
 28+
 29+$2 has responded to your summary of a point that they made.
 30+
 31+The summary you left: '$6'.
 32+Their message: '$5'.
 33+
 34+If you want to read the response in context, visit <$4>.",
 35+
 36+ 'rf-responded-subject' => "[{{SITENAME}}] $2 has responded to your summary bullet point",
 37+
 38+);
 39+
Property changes on: trunk/extensions/Reflect/server/i18n/Rf.i18n.php
___________________________________________________________________
Added: svn:eol-style
140 + native
Index: trunk/extensions/Reflect/server/i18n/Rf.magic.php
@@ -0,0 +1,5 @@
 2+<?php
 3+
 4+$magicWords = array();
 5+
 6+$magicWords['en'] = array();
Property changes on: trunk/extensions/Reflect/server/i18n/Rf.magic.php
___________________________________________________________________
Added: svn:eol-style
17 + native
Index: trunk/extensions/Reflect/server/api/ApiReflectAction.php
@@ -0,0 +1,581 @@
 2+<?php
 3+
 4+/**
 5+ * Reflect API for getting and posting summary bullets and responses.
 6+ *
 7+ * Note, many of the methods for handling Responses are almost near
 8+ * duplicates of those handling Bullets.
 9+ */
 10+class ApiReflectAction extends ApiBase {
 11+
 12+ public function execute() {
 13+ $params = $this->extractRequestParams();
 14+
 15+ if ( empty( $params['reflectaction'] ) ) {
 16+ $this->dieUsageMsg( array( 'missingparam', 'action' ) );
 17+ }
 18+
 19+ $allowedAllActions = array();
 20+ $action = $params['reflectaction'];
 21+
 22+ // Find the appropriate module
 23+ $actions = $this->getActions();
 24+
 25+ $method = $actions[$action];
 26+ call_user_func_array( array( $this, $method ), array( $params ) );
 27+ }
 28+
 29+ /**
 30+ * Gets all the bullets and responses relevant for the given LQT threads.
 31+ *
 32+ * The params listed below are the items posted in $params.
 33+ * @param $comments JSON encoded list of comment ids.
 34+ * @return assoc array of commentIDs=>array(bullets = {bullet attributes, responses})
 35+ */
 36+ public function actionGetData( $params ) {
 37+ $dbr = wfGetDB( DB_SLAVE );
 38+
 39+ $data = array();
 40+
 41+ global $wgUser, $wgReflectStudy;
 42+ $user = $wgUser->getName();
 43+
 44+ $comments = json_decode( str_replace( '\\', '', $_GET['comments'] ) );
 45+
 46+ foreach ( $comments as $commentID ) {
 47+ $bullets = array();
 48+ $curBullets = $dbr->select(
 49+ $table = 'reflect_bullet_current',
 50+ $vars = array( 'bl_id', 'bl_rev_id' ),
 51+ $conds = 'comment_id = ' . $commentID );
 52+
 53+ foreach ( $curBullets as $curBullet ) {
 54+ // TODO: is it possible to make fewer DB calls?
 55+ $sel = array( 'bl_id as id', 'bl_timestamp as ts',
 56+ 'bl_user as u', 'bl_text as txt' );
 57+
 58+ // TODO: create a Bullet model class for abstracting this away
 59+ $bullet = $dbr->selectRow(
 60+ $table = 'reflect_bullet_revision',
 61+ $vars = $sel,
 62+ $conds = 'bl_rev_id = ' . $curBullet->bl_rev_id );
 63+ $bullet->rev = $curBullet->bl_rev_id;
 64+
 65+ $bullet->highlights = array();
 66+ $highlights = $dbr->select(
 67+ $table = 'reflect_highlight',
 68+ $vars = 'hl_element as eid',
 69+ $conds = 'bl_rev_id = ' . $curBullet->bl_rev_id );
 70+
 71+ // no fetchall?
 72+ foreach ( $highlights as $highlight ) {
 73+ $bullet->highlights[] = $highlight;
 74+ }
 75+
 76+ $curResponses = $dbr->select(
 77+ $table = 'reflect_response_current',
 78+ $vars = array( 'rsp_id', 'rsp_rev_id' ),
 79+ $conds = 'bl_id = ' . $bullet->id );
 80+
 81+ $responses = array();
 82+ foreach ( $curResponses as $curResponse ) {
 83+ $response = $dbr->selectRow(
 84+ $table = 'reflect_response_revision',
 85+ $vars = array( 'rsp_id as id', 'rsp_timestamp as ts',
 86+ 'rsp_user as u', 'rsp_text as txt', 'rsp_signal as sig' ),
 87+ $conds = 'rsp_rev_id = ' . $curResponse->rsp_rev_id );
 88+ $response->rev = $curResponse->rsp_rev_id;
 89+ $responses[$response->id] = $response;
 90+ }
 91+ $bullet->responses = $responses;
 92+ $bullets[$bullet->id] = $bullet;
 93+ }
 94+ $data[$commentID] = $bullets;
 95+ }
 96+
 97+ $this->getResult()->addValue( null, $this->getModuleName(), $data );
 98+ }
 99+
 100+ /**
 101+ * Deletes a response by removing it from the current responses table.
 102+ * A record of the response is still kept in the response revisions table.
 103+ *
 104+ * The params listed below are the items posted in $params.
 105+ * @param $response_id
 106+ * @return db's return from delete
 107+ */
 108+ private function deleteResponse( $params ) {
 109+ $dbw = wfGetDB( DB_MASTER );
 110+
 111+ $responseID = $params['response_id'];
 112+ $data = $dbw->delete(
 113+ $table = 'reflect_response_current',
 114+ $conds = array( 'rsp_id = ' . $responseID ) );
 115+
 116+ $this->getResult()->addValue( null, $this->getModuleName(), $data );
 117+ }
 118+
 119+ /**
 120+ * Deletes a bullet by removing it from the current bullets table.
 121+ * A record of the bullet is still kept in the bullet revisions table.
 122+ *
 123+ * The params listed below are the items posted in $params.
 124+ * @param $bullet_id
 125+ * @return db's return from delete
 126+ */
 127+ private function deleteBullet( $params ) {
 128+ $dbw = wfGetDB( DB_MASTER );
 129+
 130+ $bulletID = $params['bullet_id'];
 131+ $data = $dbw->delete(
 132+ $table = 'reflect_bullet_current',
 133+ $conds = array( 'bl_id = ' . $bulletID ) );
 134+ $this->getResult()->addValue( null, $this->getModuleName(), $data );
 135+ }
 136+
 137+ /**
 138+ * Adds a new bullet or modifies an existing bullet.
 139+ *
 140+ * The params listed below are the items posted in $params.
 141+ * @param $comment_id
 142+ * @param $bullet_id If set to valid bullet_id, signals a modification
 143+ * @param $text The bullet text
 144+ * @param $highlights Array of sentence ids that the bullet refers to
 145+ *
 146+ * @return assoc array with $insert_id as the bullet id and $rev_id as the new rev id
 147+ */
 148+ private function addBullet( $params ) {
 149+ $dbw = wfGetDB( DB_MASTER );
 150+ $dbr = wfGetDB( DB_SLAVE );
 151+
 152+ global $wgUser;
 153+
 154+ $user = $wgUser->getName();
 155+ $commentID = $params['comment_id'];
 156+
 157+ $bulletText = $params['text'];
 158+ if ( $bulletText == '' ) {
 159+ return '';
 160+ }
 161+
 162+ $modify = isset( $params['bullet_id'] );
 163+
 164+ if ( $modify ) {
 165+ $bulletID = $params['bullet_id'];
 166+ } else {
 167+ /*
 168+ * w/o lock, the following could lead to a race condition
 169+ * TODO: should $wgAntiLockFlags be used here?
 170+ */
 171+ $dbw->begin(); // start transaction
 172+ $res = $dbr->query(
 173+ 'SELECT MAX(bl_id)+1 AS next_bullet_id FROM ' .
 174+ $dbr->tableName( 'reflect_bullet_revision' )
 175+ );
 176+ $bulletID = $res->fetchRow();
 177+ $bulletID = $bulletID['next_bullet_id'];
 178+ if ( !$bulletID ) {
 179+ $bulletID = 0;
 180+ }
 181+ }
 182+
 183+ $dbw->insert( $table = 'reflect_bullet_revision', array(
 184+ 'comment_id' => $commentID,
 185+ 'bl_id' => $bulletID,
 186+ 'bl_user' => $user,
 187+ 'bl_text' => $params['text']
 188+ ) );
 189+
 190+ $bulletRev = $dbw->insertId();
 191+
 192+ if ( !$modify ) {
 193+ $dbw->commit(); // end transaction
 194+ }
 195+
 196+ if ( isset( $params['highlights'] ) ) {
 197+ $highlights = json_decode( str_replace( '\\', '',
 198+ $params['highlights'] ) );
 199+ $highlightsToInsert = array();
 200+
 201+ foreach ( $highlights as $value ) {
 202+ $highlightsToInsert[] = array(
 203+ 'bl_id' => $bulletID,
 204+ 'bl_rev_id' => $bulletRev,
 205+ 'hl_element' => $value->eid,
 206+ );
 207+ }
 208+
 209+ $dbw->insert( "reflect_highlight", $highlightsToInsert );
 210+ }
 211+
 212+ if ( $modify ) {
 213+ /* shouldn't lead to race condition as long as
 214+ * only bullet authors can update the bullet (DEFAULT) */
 215+ $dbw->update( $table = 'reflect_bullet_current',
 216+ $values = array( 'bl_rev_id' => $bulletRev ),
 217+ $conds = array( 'bl_id = ' . $bulletID ) );
 218+ } else {
 219+ $dbw->insert( $table = 'reflect_bullet_current', array(
 220+ 'bl_rev_id' => $bulletRev,
 221+ 'comment_id' => $commentID,
 222+ 'bl_id' => $bulletID,
 223+ ));
 224+ }
 225+
 226+ /* send email notification to commenter that someone bulleted their point
 227+ *
 228+ * TODO: consider possibility of someone submitting harmless bullet,
 229+ * getting it approved, then modifying it maliciously. By not sending
 230+ * notification on modification (as below), the commenter is opened to risk.
 231+ */
 232+ global $wgReflectEnotif;
 233+ if ($wgReflectEnotif && !$modify) {
 234+ $threadObj = Threads::withId( $commentID );
 235+ $to = $threadObj->author();
 236+ $catalystUser = $wgUser;
 237+ $this->sendMail( $threadObj, $to, $catalystUser,
 238+ 'rf-bulleted', array( $params['text'] ), array() );
 239+ }
 240+ return array( "insert_id" => $bulletID, "rev_id" => $bulletRev, "u" => $user );
 241+ }
 242+
 243+
 244+ /**
 245+ * Adds a new response or modifies an existing response.
 246+ *
 247+ * The params listed below are the items posted in $params.
 248+ * @param $comment_id
 249+ * @param $bullet_id The bullet to which this response addresses
 250+ * @param $bullet_rev The current revision of the above referenced bullet
 251+ * @param $response_id If set to valid bullet_id, signals a modification
 252+ * @param $text The bullet text
 253+ * @param $signal The accuracy rating for the respective bullet
 254+ *
 255+ * @return assoc array with $insert_id as the bullet id and $rev_id as the new rev id
 256+ */
 257+ function addResponse( $params ) {
 258+ $dbw = wfGetDB( DB_MASTER );
 259+ $dbr = wfGetDB( DB_SLAVE );
 260+
 261+ global $wgUser;
 262+ $user = $wgUser->getName();
 263+
 264+ $bulletID = $params['bullet_id'];
 265+ $commentID = $params['comment_id'];
 266+
 267+ $responseText = $params['text'];
 268+ if ( $responseText == '' ){
 269+ return '';
 270+ }
 271+
 272+ $signal = (int)$params['signal'];
 273+
 274+ $modify = isset( $params['response_id'] );
 275+ if ( $modify ) {
 276+ $responseID = $params['response_id'];
 277+ } else {
 278+ /*
 279+ * w/o lock, the following could lead to a race condition
 280+ * TODO: should $wgAntiLockFlags be used here?
 281+ */
 282+ $dbw->begin(); // start transaction
 283+
 284+ $res = $dbr->query(
 285+ 'select MAX(rsp_id)+1 as next_rsp_id from ' .
 286+ $dbr->tableName( 'reflect_response_revision' )
 287+ );
 288+ $responseID = $res->fetchRow();
 289+ $responseID = $responseID['next_rsp_id'];
 290+ if ( !$responseID ) {
 291+ $responseID = 0;
 292+ }
 293+ }
 294+
 295+ $dbw->insert( $table = 'reflect_response_revision', array(
 296+ 'rsp_id' => $responseID,
 297+ 'bl_id' => $bulletID,
 298+ 'rsp_user' => $user,
 299+ 'rsp_text' => $responseText,
 300+ 'rsp_signal' => $signal
 301+ ));
 302+ $responseRev = $dbw->insertId();
 303+
 304+ if (!$modify){
 305+ $dbw->commit(); // end transaction
 306+ }
 307+
 308+ if ( $modify ) {
 309+ /* shouldn't lead to race condition as long as
 310+ * only commenters can update their responses (DEFAULT) */
 311+ $dbw->update( $table = 'reflect_response_current',
 312+ $values = array( 'rsp_rev_id' => $responseRev ),
 313+ $conds = array( 'rsp_id =' . $responseID ) );
 314+ } else {
 315+ $dbw->insert( $table = 'reflect_response_current', array(
 316+ 'rsp_rev_id' => $responseRev,
 317+ 'rsp_id' => $responseID,
 318+ 'bl_id' => $bulletID,
 319+ ));
 320+ }
 321+
 322+ $bullet = $dbr->selectRow(
 323+ $table = 'reflect_bullet_revision',
 324+ $vars = array( 'bl_user as user', 'bl_text as text' ),
 325+ $conds = 'bl_rev_id = ' . $params['bullet_rev'] );
 326+
 327+ /* send email notification to bullet author that someone
 328+ * rated the accuracy of their bullet */
 329+ global $wgReflectEnotif;
 330+ if ($wgReflectEnotif && !$modify) {
 331+ $threadObj = Threads::withId( $commentID );
 332+ $to = User::newFromName( $bullet->user );
 333+ $catalystUser = $threadObj->author();
 334+ $this->sendMail( $threadObj, $to, $catalystUser, 'rf-responded',
 335+ array( $responseText, $bullet->text ), array() );
 336+ }
 337+ return array( "insert_id" => $responseID, "rev_id" => $responseRev,
 338+ "u" => $user, "sig" => $signal );
 339+ }
 340+
 341+ /**
 342+ * Sends a Reflect email in response to a new bullet or response.
 343+ *
 344+ * @param $threadObj A reference to the relevant LQT Thread
 345+ * @param $to A User object to whom the email will be sent
 346+ * @param $catalystUser A User object who triggered this series of events
 347+ * @param $msgType The name of the message type to be used in accessing localized msg
 348+ * @param $bodyParams Additional parameters to be used in the sprintf of the body text
 349+ * @param $subjectParams Additional parameters to be used in the sprintf of the subject text
 350+ *
 351+ */
 352+ private function sendMail( $threadObj, $to, $catalystUser,
 353+ $msgType, $bodyParams, $subjectParams )
 354+ {
 355+ global $wgPasswordSender, $wgLanguageCode;
 356+
 357+ // TODO: create Reflect mailing preferences for individuals & respect them
 358+ if ( !$to ) {
 359+ return;
 360+ }
 361+
 362+ $from = new MailAddress( $wgPasswordSender, 'WikiAdmin' );
 363+ $permaLink = LqtView::linkInContextURL( $threadObj );
 364+ $params = array( $to->getName(), $catalystUser->getName(),
 365+ $threadObj->subjectWithoutIncrement(), $permaLink, );
 366+ $bodyParams = array_merge( $params, $bodyParams );
 367+ $subjectParams = array_merge( $params, $subjectParams );
 368+ $msg = wfMsgReal( $msgType, $bodyParams, true, $wgLanguageCode, true );
 369+ $subject = wfMsgReal( $msgType . '-subject', $subjectParams,
 370+ true, $wgLanguageCode, true );
 371+
 372+ UserMailer::send( new MailAddress( $to ), $from, $subject, $msg );
 373+ }
 374+
 375+ /**
 376+ * Handles the bullet posts. Calls appropriate private helper functions
 377+ * for deletes and adds. Makes sure user has permission to perform requested
 378+ * actions.
 379+ *
 380+ * The params listed below are the items posted in $params.
 381+ * @param $delete True if post is delete. Default is add.
 382+ *
 383+ * @return The response from the respective helper function
 384+ */
 385+ public function actionPostBullet( $params ) {
 386+ if ( isset( $params['delete'] ) && $params['delete'] == 'true' ) {
 387+ $verb = 'delete';
 388+ } else {
 389+ $verb = 'add';
 390+ }
 391+
 392+ if ( !$this->hasPermission( $verb, 'bullet', $params ) ) {
 393+ return;
 394+ }
 395+
 396+ if ( $verb == 'delete' ) {
 397+ $resp = $this->deleteBullet( $params );
 398+ } else {
 399+ $resp = $this->addBullet( $params );
 400+ }
 401+
 402+ $this->getResult()->addValue( null, $this->getModuleName(), $resp );
 403+ }
 404+
 405+ /**
 406+ * Handles the response posts. Calls appropriate private helper functions
 407+ * for deletes and adds. Makes sure user has permission to perform requested
 408+ * actions.
 409+ *
 410+ * The params listed below are the items posted in $params.
 411+ * @param $delete True if post is delete. Default is add.
 412+ *
 413+ * @return The response from the respective helper function
 414+ */
 415+ public function actionPostResponse( $params ) {
 416+ if ( isset( $params['delete'] ) && $params['delete'] == 'true' ) {
 417+ $verb = 'delete';
 418+ } else {
 419+ $verb = 'add';
 420+ }
 421+
 422+ if ( !$this->hasPermission( $verb, 'response', $params ) ) {
 423+ return;
 424+ }
 425+
 426+ if ( $verb == 'delete' ) {
 427+ $resp = $this->deleteResponse( $params );
 428+ } else {
 429+ $resp = $this->addResponse( $params );
 430+ }
 431+
 432+ $this->getResult()->addValue( null, $this->getModuleName(), $resp );
 433+ }
 434+
 435+ /**
 436+ * Checks whether the current user has permission to execute a given action.
 437+ * Some of the characteristics examined include the users' level (admin,
 438+ * registered, anon) and their ownership of the object being acted on.
 439+ *
 440+ * @param $verb The action.
 441+ * @param $noun The object to be acted upon.
 442+ * @param $params The params posted by the requester.
 443+ *
 444+ * @return Returns true if the user has permission, false otherwise.
 445+ */
 446+ private function hasPermission( $verb, $noun, $params ) {
 447+
 448+ $dbr = wfGetDB( DB_SLAVE );
 449+ global $wgUser;
 450+
 451+ $commentID = $params['comment_id'];
 452+ $comment = $dbr->selectRow(
 453+ $table = 'thread',
 454+ $vars = array( 'thread_author_name as user' ),
 455+ $conds = 'thread_id = ' . $commentID );
 456+ $commentAuthor = $comment->user;
 457+
 458+ $bulletID = $params['bullet_id'];
 459+ if ( $bulletID ) {
 460+ $bullet = $dbr->selectRow(
 461+ $table = 'reflect_bullet_revision',
 462+ $vars = array( 'bl_id as id', 'bl_user as user' ),
 463+ $conds = 'bl_rev_id = ' . $params['bullet_rev'] );
 464+ $bulletAuthor = $bullet->user;
 465+ } else {
 466+ $bulletAuthor = $wgUser->getName();
 467+ }
 468+
 469+ if ( $wgUser->isAnon() ) {
 470+ $userLevel = -1;
 471+ } else if ( in_array( 'sysop', $wgUser->getGroups() ) ) {
 472+ $userLevel = 2;
 473+ } else {
 474+ $userLevel = 1;
 475+ }
 476+
 477+ $userName = $wgUser->getName();
 478+ if ( $noun == 'bullet' ) {
 479+ $denied = ( // only admins and bullet authors can delete bullets
 480+ $verb == 'delete'
 481+ && $bulletAuthor != $userName
 482+ && $userLevel < 2
 483+ )
 484+ || ( // commenters cann't add bullets to their comment
 485+ $verb == 'add'
 486+ && $commentAuthor == $userName
 487+ ) ;
 488+ } elseif ( $noun == 'response' ) {
 489+ $denied = ( // only admins and response authors can delete responses
 490+ $verb == 'delete'
 491+ && $commentAuthor != $userName
 492+ && $userLevel < 2
 493+ )
 494+ || ( // only comment authors can add responses
 495+ $verb == 'add'
 496+ && $commentAuthor != $userName
 497+ ) ;
 498+ }
 499+ return !$denied;
 500+ }
 501+
 502+ /**** ApiBase functions *****/
 503+
 504+ public function getDescription() {
 505+ return 'Enables Reflect on posts in Liquid-Threaded discussions.';
 506+ }
 507+
 508+ public function getActions() {
 509+ return array(
 510+ 'get_data' => 'actionGetData',
 511+ 'post_bullet' => 'actionPostBullet',
 512+ 'post_response' => 'actionPostResponse',
 513+ 'post_survey_bullets' => 'actionPostSurveyBullets',
 514+ );
 515+ }
 516+
 517+ public function getParamDescription() {
 518+ return array(
 519+ 'reflectaction' => 'The action to take',
 520+ 'token' => 'An edit token (from ?action=query&prop=info&intoken=edit)',
 521+ 'delete' => 'Whether this post is a delete request',
 522+ 'comment_id' => 'The id of the relevant thread',
 523+ 'bullet_id' => 'For modifying existing bullets. Don\'t set if posting new bullet.',
 524+ 'response' => 'Set to true if the post is posting a response',
 525+ 'response_id' => 'For modifying existing response. Don\'t set if posting new response.',
 526+ 'text' => 'The text relevant to the action',
 527+ 'user' => 'The user who took the action. We actually ignore this and use $wgUser instead.',
 528+ 'highlights' => 'For posting a bullet. An array of element ids corresponding to the highlighted elements of the comment',
 529+ 'signal' => 'For responses. ID of response to question about whether the commenter thinks the bullet is accurate',
 530+ 'comments' => 'For initial GET request. List of ids of all the threads on the current page',
 531+ 'bullet_rev' => 'The revision of the bullet to take action on.',
 532+ 'response_rev' => 'The revision of the response to take action on.',
 533+ );
 534+ }
 535+
 536+ public function getPossibleErrors() {
 537+ return array_merge( parent::getPossibleErrors(), array(
 538+ array( 'missingparam', 'action' ),
 539+ ) );
 540+ }
 541+
 542+ public function getExamples() {
 543+ return array();
 544+ }
 545+
 546+ public function getTokenSalt() {
 547+ return '';
 548+ }
 549+
 550+ public function getAllowedParams() {
 551+ return array(
 552+ 'reflectaction' => array(
 553+ ApiBase::PARAM_TYPE => array_keys( $this->getActions() ),
 554+ ),
 555+ 'token' => null,
 556+ 'delete' => null,
 557+ 'comment_id' => null,
 558+ 'bullet_id' => null,
 559+ 'response' => null,
 560+ 'response_id' => null,
 561+ 'text' => null,
 562+ 'user' => null,
 563+ 'highlights' => array(),
 564+ 'signal' => null,
 565+ 'comments' => null,
 566+ 'bullet_rev' => null,
 567+ 'response_rev' => null,
 568+ );
 569+ }
 570+
 571+ public function mustBePosted() {
 572+ return false;
 573+ }
 574+
 575+ public function isWriteMode() {
 576+ return true;
 577+ }
 578+
 579+ public function getVersion() {
 580+ return __CLASS__ . ': $Id: ApiReflectAction.php 66465 2010-05-15 11:31:55Z travis $';
 581+ }
 582+}
Property changes on: trunk/extensions/Reflect/server/api/ApiReflectAction.php
___________________________________________________________________
Added: svn:eol-style
1583 + native
Index: trunk/extensions/Reflect/server/api/ApiReflectStudyAction.php
@@ -0,0 +1,215 @@
 2+<?php
 3+
 4+/**
 5+* Implements the API for a research study investigating the affordances
 6+* of Reflect and LQT. Users are asked to fill out short surveys about
 7+* something that they just did (like why they just added a summary point).
 8+* These survey results are then posted to here.
 9+*
 10+* However, the survey responses cannot be added to the local wikimedia
 11+* installation's database. This is because of American Universities'
 12+* Institutional Review Board for approving research involving human
 13+* subjects (http://en.wikipedia.org/wiki/Institutional_review_board).
 14+* We need to store the results of the surveys on a university
 15+* server dissasociated from personally identifying information (i.e. username).
 16+*
 17+* Therefore, ApiReflectStudyAction handles posts but then creates an XML-RPC
 18+* connection to a remote server, where the survey response and a hash of the
 19+* user name are stored.
 20+*
 21+*/
 22+
 23+// dependency on http://pear.php.net/package/XML_RPC2/
 24+require_once 'XML/RPC2/Client.php';
 25+
 26+class ApiReflectStudyAction extends ApiBase {
 27+
 28+ public function execute() {
 29+ $params = $this->extractRequestParams();
 30+
 31+ if ( empty( $params['reflectstudyaction'] ) ) {
 32+ $this->dieUsageMsg( array( 'missingparam', 'action' ) );
 33+ }
 34+
 35+ $allowedAllActions = array();
 36+ $action = $params['reflectstudyaction'];
 37+
 38+ // Find the appropriate module
 39+ $actions = $this->getActions();
 40+
 41+ $method = $actions[$action];
 42+
 43+ call_user_func_array( array( $this, $method ), array( $params ) );
 44+ }
 45+
 46+ /**
 47+ * Fetches the surveys that the current user has already filled out.
 48+ * Only the bullet_ids of the completed surveys are returned from the
 49+ * remote server.
 50+ *
 51+ * The params listed below are the items posted in $params.
 52+ * @param $bullets List of bullet_ids for which the user MAY already have been surveyed
 53+ *
 54+ * @return Returns the response from the remote host.
 55+ */
 56+ public function actionGetSurveyBullets( $params ) {
 57+ global $wgUser;
 58+ $user = $wgUser->getName();
 59+ $user = md5( $user );
 60+
 61+ global $wgReflectStudyRPCHost, $wgReflectStudyDomain;
 62+
 63+ $rpcConn = XML_RPC2_Client::create( $wgReflectStudyRPCHost,
 64+ array( 'backend' => 'php' ) );
 65+ try {
 66+ $resp = $rpcConn->get_survey_responses( $wgReflectStudyDomain,
 67+ $params['bullets'], $user );
 68+ } catch ( XML_RPC2_FaultException $e ) {
 69+ // The XMLRPC server returns a XMLRPC error
 70+ die( 'Exception #' . $e->getFaultCode() . ' : ' . $e->getFaultString() );
 71+ } catch ( Exception $e ) {
 72+ // Other errors (HTTP or networking problems...)
 73+ die( 'Exception : ' . $e->getMessage() );
 74+ }
 75+
 76+ $this->getResult()->addValue( null, $this->getModuleName(), $resp );
 77+ }
 78+
 79+ /**
 80+ * Posts a survey response to the remote server. But first
 81+ * checks to make sure the current user is authorized to
 82+ * post the survey.
 83+ *
 84+ * The params listed below are the items posted in $params.
 85+ * @param $comment_id
 86+ * @param $bullet_id
 87+ * @param $bullet_rev
 88+ * @param $survey_id An identifier for the survey being responded to
 89+ * @param $response_id The answer to the response
 90+ * @param $text Free form survey response (if relevant)
 91+ *
 92+ * @return Returns the response from the remote host.
 93+ */
 94+ public function actionPostSurveyBullets( $params ) {
 95+ $dbr = wfGetDB( DB_SLAVE );
 96+
 97+ global $wgUser;
 98+ $user = $wgUser->getName();
 99+
 100+ $bulletID = $params['bullet_id'];
 101+ $commentID = $params['comment_id'];
 102+ $bulletRev = $params['bullet_rev'];
 103+ $surveyID = $params['survey_id'];
 104+ $responseID = $params['response_id'];
 105+ $text = $params['text'];
 106+
 107+ $comment = $dbr->selectRow(
 108+ $table = 'thread',
 109+ $vars = array( 'thread_author_name as user' ),
 110+ $conds = 'thread_id = ' . $commentID );
 111+
 112+ $bullet = $dbr->selectRow(
 113+ $table = 'reflect_bullet_revision',
 114+ $vars = array( 'bl_user as user' ),
 115+ $conds = 'bl_rev_id = ' . $bulletRev );
 116+
 117+ // only commenters can answer survey 2
 118+ // only bullet writers can answer survey 1
 119+ if ( ( $surveyID == "2" && $user != $comment->user )
 120+ || ( $surveyID == "1" && $user != $bullet->user ) )
 121+ {
 122+ $resp = array( 'invalid post' ); // TODO: use dieUsageMsg instead
 123+ } else {
 124+ global $wgReflectStudyRPCHost, $wgReflectStudyDomain;
 125+
 126+ // store hash of username on remote study server for anonymity
 127+ $user = md5( $user );
 128+
 129+ $rpcConn = XML_RPC2_Client::create( $wgReflectStudyRPCHost,
 130+ array( 'backend' => 'php' ) );
 131+ try {
 132+ if ( !$text ) $text = '';
 133+ $resp = $rpcConn->post_survey_response( $wgReflectStudyDomain,
 134+ $commentID, $bulletID, $bulletRev,
 135+ $responseID, $surveyID, $user, $text );
 136+ } catch ( XML_RPC2_FaultException $e ) {
 137+ // The XMLRPC server returns a XMLRPC error
 138+ die( 'Exception #' . $e->getFaultCode() . ' : ' . $e->getFaultString() );
 139+ } catch ( Exception $e ) {
 140+ // Other errors (HTTP or networking problems...)
 141+ die( 'Exception : ' . $e->getMessage() );
 142+ }
 143+ }
 144+
 145+ $this->getResult()->addValue( null, $this->getModuleName(), $resp );
 146+ }
 147+
 148+ /****** ApiBase methods ********/
 149+
 150+ public function getDescription() {
 151+ return 'Enables in-situ surveys for study Reflect activities in Liquid-Threaded discussions.';
 152+ }
 153+
 154+ public function getActions() {
 155+ return array(
 156+ 'post_survey_bullets' => 'actionPostSurveyBullets',
 157+ 'get_survey_responses' => 'actionGetSurveyBullets',
 158+ );
 159+ }
 160+
 161+ public function getParamDescription() {
 162+ return array(
 163+ 'reflectstudyaction' => 'The action to take',
 164+ 'token' => 'An edit token (from ?action=query&prop=info&intoken=edit)',
 165+ 'comment_id' => 'The id of the thread',
 166+ 'bullet_id' => 'The id of the bullet the survey is asking about',
 167+ 'bullet_rev' => 'The revid of the bullet the survey is asking about',
 168+ 'response_id' => 'An answer to a survey question',
 169+ 'survey_id' => 'An identifier for the specific survey being administered',
 170+ 'text' => 'Optional text field for open ended survey questions',
 171+ 'bullets' => 'list of bullets for survey to get'
 172+ );
 173+ }
 174+
 175+ public function getPossibleErrors() {
 176+ return array_merge( parent::getPossibleErrors(), array(
 177+ array( 'missingparam', 'action' ),
 178+ ) );
 179+ }
 180+
 181+ public function getExamples() {
 182+ return array();
 183+ }
 184+
 185+ public function getTokenSalt() {
 186+ return '';
 187+ }
 188+
 189+ public function getAllowedParams() {
 190+ return array(
 191+ 'reflectstudyaction' => array(
 192+ ApiBase::PARAM_TYPE => array_keys( $this->getActions() ),
 193+ ),
 194+ 'token' => null,
 195+ 'comment_id' => null,
 196+ 'bullet_id' => null,
 197+ 'bullet_rev' => null,
 198+ 'response_id' => null,
 199+ 'survey_id' => null,
 200+ 'text' => null,
 201+ 'bullets' => null,
 202+ );
 203+ }
 204+
 205+ public function mustBePosted() {
 206+ return false;
 207+ }
 208+
 209+ public function isWriteMode() {
 210+ return true;
 211+ }
 212+
 213+ public function getVersion() {
 214+ return __CLASS__ . ': $Id: ApiReflectStudyAction.php 66465 2010-07-30 11:31:55Z travis $';
 215+ }
 216+}
Property changes on: trunk/extensions/Reflect/server/api/ApiReflectStudyAction.php
___________________________________________________________________
Added: svn:eol-style
1217 + native
Index: trunk/extensions/Reflect/server/classes/Dispatch.php
@@ -0,0 +1,87 @@
 2+<?php
 3+
 4+/**
 5+* Checks to see if Reflect should be deployed on the to-be-rendered page.
 6+* If so, it adds the appropriate JS and CSS to the output.
 7+*/
 8+class ReflectDispatch {
 9+
 10+ /**
 11+ * Adds Reflect CSS & JS to the output
 12+ *
 13+ * @param $output
 14+ *
 15+ * @return Returns true
 16+ */
 17+ static private function reflectAddJSandCSS( &$output ) {
 18+
 19+ global $wgScriptPath, $wgReflectExtensionName, $wgReflectStudy;
 20+
 21+ $basePath = "$wgScriptPath/extensions/$wgReflectExtensionName/client";
 22+
 23+ $output->addExtensionStyle( "$basePath/css/reflect.css" );
 24+ $output->addExtensionStyle( "$basePath/css/reflect.liquidthreads.css" );
 25+ $output->addExtensionStyle( "$basePath/css/reflect.study.css" );
 26+ $output->addScriptFile( "$basePath/js/third_party/inheritance.js" );
 27+ $output->addScriptFile( "$basePath/js/third_party/jquery.color.js" );
 28+ $output->addScriptFile( "$basePath/js/third_party/jquery.highlight.js" );
 29+ $output->addScriptFile( "$basePath/js/third_party/jquery.noblecount.min.js" );
 30+ $output->addScriptFile( "$basePath/js/third_party/jquery.pulse.js" );
 31+ $output->addScriptFile( "$basePath/js/third_party/jquery.jqote2.min.js" );
 32+
 33+ $output->addScriptFile( "$basePath/js/third_party/json2.js" );
 34+ $output->addScriptFile( "$basePath/js/reflect.js" );
 35+ if ( $wgReflectStudy )
 36+ $output->addScriptFile( "$basePath/js/reflect.study.js" );
 37+ $output->addScriptFile( "$basePath/js/reflect.liquidthreads.js" );
 38+ return true;
 39+ }
 40+
 41+ /**
 42+ * View for altering a Reflect-ed talkpage. Currently only need to add CSS / JS.
 43+ *
 44+ * @param $output
 45+ *
 46+ * @return true if successfully alter page
 47+ */
 48+ static private function talkpageMain( &$output ) {
 49+ // We are given a talkpage article and title. Just insert the Reflect client side magic.
 50+ return self::reflectAddJSandCSS( $output );
 51+ }
 52+
 53+
 54+ /**
 55+ * Checks whether the current page should be Reflected. First, only LQT pages
 56+ * can be Reflected. Second, either Reflect must be enabled for all pages, or
 57+ * the current page must belong to a subset of pages Reflect is enabled on.
 58+ *
 59+ * @param $title Title of current page.
 60+ *
 61+ * @return Returns whether the current page should have Reflect added.
 62+ */
 63+ static private function isReflectPage( $title ) {
 64+ global $wgReflectPages, $wgReflectTalkPages;
 65+
 66+ $isReflectPage = LqtDispatch::isLqtPage( $title ) &&
 67+ ( $wgReflectTalkPages ||
 68+ in_array( $title->getPrefixedText(), $wgReflectPages ) );
 69+ return $isReflectPage;
 70+ }
 71+
 72+
 73+ /**
 74+ * If the current page is a Reflect page of any kind, process it
 75+ * as needed. This is the main dispatcher method.
 76+ *
 77+ * @param $output
 78+ *
 79+ * @return Whether processing is successful.
 80+ */
 81+ static function tryPage( $output ) {
 82+ $title = $output->getTitle();
 83+ if ( ReflectDispatch::isReflectPage( $title ) )
 84+ return self::talkpageMain( $output );
 85+ return true;
 86+ }
 87+
 88+}
Property changes on: trunk/extensions/Reflect/server/classes/Dispatch.php
___________________________________________________________________
Added: svn:eol-style
189 + native
Index: trunk/extensions/Reflect/Reflect.php
@@ -0,0 +1,82 @@
 2+<?php
 3+if ( !defined( 'MEDIAWIKI' ) )
 4+ die();
 5+
 6+$wgExtensionCredits['other'][] = array(
 7+ 'path' => __FILE__,
 8+ 'name' => 'Reflect',
 9+ 'version' => '0.1-alpha',
 10+ 'url' => 'http://www.cs.washington.edu/homes/travis/reflect/',
 11+ 'author' => array( 'Travis Kriplean' ),
 12+ 'descriptionmsg' => 'reflect-desc',
 13+);
 14+
 15+/*************************
 16+ * CONFIGURATION SECTION *
 17+ *************************/
 18+
 19+/* Allows activation of LiquidThreads on individual pages */
 20+$wgReflectTalkPages = array( 'Talk:Main_Page' );
 21+
 22+/* Allows switching Reflect off for regular talk pages
 23+ (intended for testing and transition) */
 24+$wgReflectPages = false;
 25+
 26+/* Whether or not to activate Reflect email notifications */
 27+$wgReflectEnotif = true;
 28+
 29+/* Whether or not a research study is being conducted
 30+ * This should not be enabled for a long-term deployments.
 31+ * Find more information in server/api/ApiReflectStudyAction.php */
 32+$wgReflectStudy = true;
 33+
 34+if ( $wgReflectStudy ) {
 35+ /* Unique identifier for the current study */
 36+ $wgReflectStudyDomain = 'mediawiki_chi';
 37+
 38+ /* The location of the study API for posting results of surveys through RPC */
 39+ $wgReflectStudyRPCHost = 'http://daniels.cs.washington.edu/reflect_study/rpc/';
 40+}
 41+/********* end configuration ***************/
 42+
 43+
 44+/****************************
 45+ * EXTENSION INITIALIZATION *
 46+ ****************************/
 47+
 48+$dir = dirname( __FILE__ ) . '/';
 49+
 50+$wgReflectExtensionName = 'Reflect';
 51+
 52+// Classes
 53+$wgAutoloadClasses['ApiReflectAction'] = "$dir/server/api/ApiReflectAction.php";
 54+$wgAutoloadClasses['ReflectDispatch'] = "$dir/server/classes/Dispatch.php";
 55+
 56+// API
 57+$wgAPIModules['reflectaction'] = 'ApiReflectAction';
 58+
 59+// Hooks
 60+$wgHooks['MakeGlobalVariablesScript'][] = 'reflectAddGlobalVars';
 61+$wgHooks['BeforePageDisplay'][] = 'ReflectDispatch::tryPage';
 62+
 63+// Localisation
 64+$wgExtensionMessagesFiles['Reflect'] = "$dir/server/i18n/Rf.i18n.php";
 65+$wgExtensionMessagesFiles['ReflectMagic'] = "$dir/server/i18n/Rf.magic.php";
 66+$wgExtensionAliasesFiles['Reflect'] = "$dir/server/i18n/Rf.alias.php";
 67+
 68+function reflectAddGlobalVars( &$vars ) {
 69+ global $wgUser, $wgReflectStudy;
 70+ $vars['wgUser'] = $wgUser->getName();
 71+ $vars['wgIsAdmin'] = in_array( 'sysop', $wgUser->getGroups() );
 72+ $vars['wgReflectStudyEnabled'] = $wgReflectStudy;
 73+ return true;
 74+}
 75+
 76+/* If this reflect deployment has a research component, need to enable XML-RPC
 77+ * NOTE: this requires http://pear.php.net/package/XML_RPC2/ */
 78+if ( $wgReflectStudy ) {
 79+ // Classes
 80+ $wgAutoloadClasses['ApiReflectStudyAction'] = "$dir/server/api/ApiReflectStudyAction.php";
 81+ // API
 82+ $wgAPIModules['reflectstudyaction'] = 'ApiReflectStudyAction';
 83+}
\ No newline at end of file
Property changes on: trunk/extensions/Reflect/Reflect.php
___________________________________________________________________
Added: svn:eol-style
184 + native
Index: trunk/extensions/Reflect/client/media/response-yes.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/response-yes.png
___________________________________________________________________
Added: svn:mime-type
285 + image/png
Index: trunk/extensions/Reflect/client/media/delete_red.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/delete_red.png
___________________________________________________________________
Added: svn:mime-type
386 + image/png
Index: trunk/extensions/Reflect/client/media/signal_yes.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/signal_yes.png
___________________________________________________________________
Added: svn:mime-type
487 + image/png
Index: trunk/extensions/Reflect/client/media/check2.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/check2.png
___________________________________________________________________
Added: svn:mime-type
588 + image/png
Index: trunk/extensions/Reflect/client/media/dispute_gray.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/dispute_gray.png
___________________________________________________________________
Added: svn:mime-type
689 + image/png
Index: trunk/extensions/Reflect/client/media/cancel2.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/cancel2.png
___________________________________________________________________
Added: svn:mime-type
790 + image/png
Index: trunk/extensions/Reflect/client/media/response-no.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/response-no.png
___________________________________________________________________
Added: svn:mime-type
891 + image/png
Index: trunk/extensions/Reflect/client/media/dispute_yellow.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/dispute_yellow.png
___________________________________________________________________
Added: svn:mime-type
992 + image/png
Index: trunk/extensions/Reflect/client/media/signal_no.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/signal_no.png
___________________________________________________________________
Added: svn:mime-type
1093 + image/png
Index: trunk/extensions/Reflect/client/media/comment-flag.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/comment-flag.png
___________________________________________________________________
Added: svn:mime-type
1194 + image/png
Index: trunk/extensions/Reflect/client/media/check.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/check.png
___________________________________________________________________
Added: svn:mime-type
1295 + image/png
Index: trunk/extensions/Reflect/client/media/cancel_black.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/cancel_black.png
___________________________________________________________________
Added: svn:mime-type
1396 + image/png
Index: trunk/extensions/Reflect/client/media/delete_gray.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/delete_gray.png
___________________________________________________________________
Added: svn:mime-type
1497 + image/png
Index: trunk/extensions/Reflect/client/media/cancel.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/cancel.png
___________________________________________________________________
Added: svn:mime-type
1598 + image/png
Index: trunk/extensions/Reflect/client/media/edit.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/edit.png
___________________________________________________________________
Added: svn:mime-type
1699 + image/png
Index: trunk/extensions/Reflect/client/media/bullet.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/bullet.png
___________________________________________________________________
Added: svn:mime-type
17100 + image/png
Index: trunk/extensions/Reflect/client/media/help.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/help.png
___________________________________________________________________
Added: svn:mime-type
18101 + image/png
Index: trunk/extensions/Reflect/client/media/edit_hover.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/edit_hover.png
___________________________________________________________________
Added: svn:mime-type
19102 + image/png
Index: trunk/extensions/Reflect/client/media/response-maybe.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/response-maybe.png
___________________________________________________________________
Added: svn:mime-type
20103 + image/png
Index: trunk/extensions/Reflect/client/media/comment-flag-hover.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/comment-flag-hover.png
___________________________________________________________________
Added: svn:mime-type
21104 + image/png
Index: trunk/extensions/Reflect/client/media/signal_maybe.png
Cannot display: file marked as a binary type.
svn:mime-type = image/png
Property changes on: trunk/extensions/Reflect/client/media/signal_maybe.png
___________________________________________________________________
Added: svn:mime-type
22105 + image/png
Index: trunk/extensions/Reflect/client/css/jquery.ui.css
@@ -0,0 +1,489 @@
 2+/*
 3+* jQuery UI CSS Framework
 4+* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 5+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
 6+*/
 7+
 8+/* Layout helpers
 9+----------------------------------*/
 10+.ui-helper-hidden { display: none; }
 11+.ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
 12+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
 13+.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
 14+.ui-helper-clearfix { display: inline-block; }
 15+/* required comment for clearfix to work in Opera \*/
 16+* html .ui-helper-clearfix { height:1%; }
 17+.ui-helper-clearfix { display:block; }
 18+/* end clearfix */
 19+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
 20+
 21+
 22+/* Interaction Cues
 23+----------------------------------*/
 24+.ui-state-disabled { cursor: default !important; }
 25+
 26+
 27+/* Icons
 28+----------------------------------*/
 29+
 30+/* states and images */
 31+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
 32+
 33+
 34+/* Misc visuals
 35+----------------------------------*/
 36+
 37+/* Overlays */
 38+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
 39+
 40+
 41+/*
 42+* jQuery UI CSS Framework
 43+* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
 44+* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
 45+* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,%20Arial,%20sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=6px&bgColorHeader=444444&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=44&borderColorHeader=333333&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=000000&bgTextureContent=14_loop.png&bgImgOpacityContent=25&borderColorContent=555555&fcContent=ffffff&iconColorContent=cccccc&bgColorDefault=222222&bgTextureDefault=03_highlight_soft.png&bgImgOpacityDefault=35&borderColorDefault=444444&fcDefault=eeeeee&iconColorDefault=cccccc&bgColorHover=003147&bgTextureHover=03_highlight_soft.png&bgImgOpacityHover=33&borderColorHover=0b93d5&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=0972a5&bgTextureActive=04_highlight_hard.png&bgImgOpacityActive=20&borderColorActive=26b3f7&fcActive=ffffff&iconColorActive=222222&bgColorHighlight=eeeeee&bgTextureHighlight=03_highlight_soft.png&bgImgOpacityHighlight=80&borderColorHighlight=cccccc&fcHighlight=2e7db2&iconColorHighlight=4b8e0b&bgColorError=ffc73d&bgTextureError=02_glass.png&bgImgOpacityError=40&borderColorError=ffb73d&fcError=111111&iconColorError=a83300&bgColorOverlay=5c5c5c&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=50&opacityOverlay=80&bgColorShadow=cccccc&bgTextureShadow=01_flat.png&bgImgOpacityShadow=30&opacityShadow=60&thicknessShadow=7px&offsetTopShadow=-7px&offsetLeftShadow=-7px&cornerRadiusShadow=8px
 46+*/
 47+
 48+
 49+/* Component containers
 50+----------------------------------*/
 51+.ui-widget { font-family: Verdana, Arial, sans-serif; font-size: 1.1em; }
 52+.ui-widget .ui-widget { font-size: 1em; }
 53+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana, Arial, sans-serif; font-size: 1em; }
 54+.ui-widget-content { border: 1px solid #555555; background: #000000 url(images/ui-bg_loop_25_000000_21x21.png) 50% 50% repeat; color: #ffffff; }
 55+.ui-widget-content a { color: #ffffff; }
 56+.ui-widget-header { border: 1px solid #333333; background: #444444 url(images/ui-bg_highlight-soft_44_444444_1x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
 57+.ui-widget-header a { color: #ffffff; }
 58+
 59+/* Interaction states
 60+----------------------------------*/
 61+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #444444; background: #222222 url(images/ui-bg_highlight-soft_35_222222_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #eeeeee; }
 62+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #eeeeee; text-decoration: none; }
 63+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #0b93d5; background: #003147 url(images/ui-bg_highlight-soft_33_003147_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
 64+.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; }
 65+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #26b3f7; background: #0972a5 url(images/ui-bg_highlight-hard_20_0972a5_1x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; }
 66+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #ffffff; text-decoration: none; }
 67+.ui-widget :active { outline: none; }
 68+
 69+/* Interaction Cues
 70+----------------------------------*/
 71+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #cccccc; background: #eeeeee url(images/ui-bg_highlight-soft_80_eeeeee_1x100.png) 50% top repeat-x; color: #2e7db2; }
 72+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #2e7db2; }
 73+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #ffb73d; background: #ffc73d url(images/ui-bg_glass_40_ffc73d_1x400.png) 50% 50% repeat-x; color: #111111; }
 74+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #111111; }
 75+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #111111; }
 76+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
 77+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
 78+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
 79+
 80+/* Icons
 81+----------------------------------*/
 82+
 83+/* states and images */
 84+.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_cccccc_256x240.png); }
 85+.ui-widget-content .ui-icon {background-image: url(images/ui-icons_cccccc_256x240.png); }
 86+.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
 87+.ui-state-default .ui-icon { background-image: url(images/ui-icons_cccccc_256x240.png); }
 88+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
 89+.ui-state-active .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
 90+.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_4b8e0b_256x240.png); }
 91+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_a83300_256x240.png); }
 92+
 93+/* positioning */
 94+.ui-icon-carat-1-n { background-position: 0 0; }
 95+.ui-icon-carat-1-ne { background-position: -16px 0; }
 96+.ui-icon-carat-1-e { background-position: -32px 0; }
 97+.ui-icon-carat-1-se { background-position: -48px 0; }
 98+.ui-icon-carat-1-s { background-position: -64px 0; }
 99+.ui-icon-carat-1-sw { background-position: -80px 0; }
 100+.ui-icon-carat-1-w { background-position: -96px 0; }
 101+.ui-icon-carat-1-nw { background-position: -112px 0; }
 102+.ui-icon-carat-2-n-s { background-position: -128px 0; }
 103+.ui-icon-carat-2-e-w { background-position: -144px 0; }
 104+.ui-icon-triangle-1-n { background-position: 0 -16px; }
 105+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
 106+.ui-icon-triangle-1-e { background-position: -32px -16px; }
 107+.ui-icon-triangle-1-se { background-position: -48px -16px; }
 108+.ui-icon-triangle-1-s { background-position: -64px -16px; }
 109+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
 110+.ui-icon-triangle-1-w { background-position: -96px -16px; }
 111+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
 112+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
 113+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
 114+.ui-icon-arrow-1-n { background-position: 0 -32px; }
 115+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
 116+.ui-icon-arrow-1-e { background-position: -32px -32px; }
 117+.ui-icon-arrow-1-se { background-position: -48px -32px; }
 118+.ui-icon-arrow-1-s { background-position: -64px -32px; }
 119+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
 120+.ui-icon-arrow-1-w { background-position: -96px -32px; }
 121+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
 122+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
 123+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
 124+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
 125+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
 126+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
 127+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
 128+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
 129+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
 130+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
 131+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
 132+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
 133+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
 134+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
 135+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
 136+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
 137+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
 138+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
 139+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
 140+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
 141+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
 142+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
 143+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
 144+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
 145+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
 146+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
 147+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
 148+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
 149+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
 150+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
 151+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
 152+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
 153+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
 154+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
 155+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
 156+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
 157+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
 158+.ui-icon-arrow-4 { background-position: 0 -80px; }
 159+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
 160+.ui-icon-extlink { background-position: -32px -80px; }
 161+.ui-icon-newwin { background-position: -48px -80px; }
 162+.ui-icon-refresh { background-position: -64px -80px; }
 163+.ui-icon-shuffle { background-position: -80px -80px; }
 164+.ui-icon-transfer-e-w { background-position: -96px -80px; }
 165+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
 166+.ui-icon-folder-collapsed { background-position: 0 -96px; }
 167+.ui-icon-folder-open { background-position: -16px -96px; }
 168+.ui-icon-document { background-position: -32px -96px; }
 169+.ui-icon-document-b { background-position: -48px -96px; }
 170+.ui-icon-note { background-position: -64px -96px; }
 171+.ui-icon-mail-closed { background-position: -80px -96px; }
 172+.ui-icon-mail-open { background-position: -96px -96px; }
 173+.ui-icon-suitcase { background-position: -112px -96px; }
 174+.ui-icon-comment { background-position: -128px -96px; }
 175+.ui-icon-person { background-position: -144px -96px; }
 176+.ui-icon-print { background-position: -160px -96px; }
 177+.ui-icon-trash { background-position: -176px -96px; }
 178+.ui-icon-locked { background-position: -192px -96px; }
 179+.ui-icon-unlocked { background-position: -208px -96px; }
 180+.ui-icon-bookmark { background-position: -224px -96px; }
 181+.ui-icon-tag { background-position: -240px -96px; }
 182+.ui-icon-home { background-position: 0 -112px; }
 183+.ui-icon-flag { background-position: -16px -112px; }
 184+.ui-icon-calendar { background-position: -32px -112px; }
 185+.ui-icon-cart { background-position: -48px -112px; }
 186+.ui-icon-pencil { background-position: -64px -112px; }
 187+.ui-icon-clock { background-position: -80px -112px; }
 188+.ui-icon-disk { background-position: -96px -112px; }
 189+.ui-icon-calculator { background-position: -112px -112px; }
 190+.ui-icon-zoomin { background-position: -128px -112px; }
 191+.ui-icon-zoomout { background-position: -144px -112px; }
 192+.ui-icon-search { background-position: -160px -112px; }
 193+.ui-icon-wrench { background-position: -176px -112px; }
 194+.ui-icon-gear { background-position: -192px -112px; }
 195+.ui-icon-heart { background-position: -208px -112px; }
 196+.ui-icon-star { background-position: -224px -112px; }
 197+.ui-icon-link { background-position: -240px -112px; }
 198+.ui-icon-cancel { background-position: 0 -128px; }
 199+.ui-icon-plus { background-position: -16px -128px; }
 200+.ui-icon-plusthick { background-position: -32px -128px; }
 201+.ui-icon-minus { background-position: -48px -128px; }
 202+.ui-icon-minusthick { background-position: -64px -128px; }
 203+.ui-icon-close { background-position: -80px -128px; }
 204+.ui-icon-closethick { background-position: -96px -128px; }
 205+.ui-icon-key { background-position: -112px -128px; }
 206+.ui-icon-lightbulb { background-position: -128px -128px; }
 207+.ui-icon-scissors { background-position: -144px -128px; }
 208+.ui-icon-clipboard { background-position: -160px -128px; }
 209+.ui-icon-copy { background-position: -176px -128px; }
 210+.ui-icon-contact { background-position: -192px -128px; }
 211+.ui-icon-image { background-position: -208px -128px; }
 212+.ui-icon-video { background-position: -224px -128px; }
 213+.ui-icon-script { background-position: -240px -128px; }
 214+.ui-icon-alert { background-position: 0 -144px; }
 215+.ui-icon-info { background-position: -16px -144px; }
 216+.ui-icon-notice { background-position: -32px -144px; }
 217+.ui-icon-help { background-position: -48px -144px; }
 218+.ui-icon-check { background-position: -64px -144px; }
 219+.ui-icon-bullet { background-position: -80px -144px; }
 220+.ui-icon-radio-off { background-position: -96px -144px; }
 221+.ui-icon-radio-on { background-position: -112px -144px; }
 222+.ui-icon-pin-w { background-position: -128px -144px; }
 223+.ui-icon-pin-s { background-position: -144px -144px; }
 224+.ui-icon-play { background-position: 0 -160px; }
 225+.ui-icon-pause { background-position: -16px -160px; }
 226+.ui-icon-seek-next { background-position: -32px -160px; }
 227+.ui-icon-seek-prev { background-position: -48px -160px; }
 228+.ui-icon-seek-end { background-position: -64px -160px; }
 229+.ui-icon-seek-start { background-position: -80px -160px; }
 230+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
 231+.ui-icon-seek-first { background-position: -80px -160px; }
 232+.ui-icon-stop { background-position: -96px -160px; }
 233+.ui-icon-eject { background-position: -112px -160px; }
 234+.ui-icon-volume-off { background-position: -128px -160px; }
 235+.ui-icon-volume-on { background-position: -144px -160px; }
 236+.ui-icon-power { background-position: 0 -176px; }
 237+.ui-icon-signal-diag { background-position: -16px -176px; }
 238+.ui-icon-signal { background-position: -32px -176px; }
 239+.ui-icon-battery-0 { background-position: -48px -176px; }
 240+.ui-icon-battery-1 { background-position: -64px -176px; }
 241+.ui-icon-battery-2 { background-position: -80px -176px; }
 242+.ui-icon-battery-3 { background-position: -96px -176px; }
 243+.ui-icon-circle-plus { background-position: 0 -192px; }
 244+.ui-icon-circle-minus { background-position: -16px -192px; }
 245+.ui-icon-circle-close { background-position: -32px -192px; }
 246+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
 247+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
 248+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
 249+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
 250+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
 251+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
 252+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
 253+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
 254+.ui-icon-circle-zoomin { background-position: -176px -192px; }
 255+.ui-icon-circle-zoomout { background-position: -192px -192px; }
 256+.ui-icon-circle-check { background-position: -208px -192px; }
 257+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
 258+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
 259+.ui-icon-circlesmall-close { background-position: -32px -208px; }
 260+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
 261+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
 262+.ui-icon-squaresmall-close { background-position: -80px -208px; }
 263+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
 264+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
 265+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
 266+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
 267+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
 268+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
 269+
 270+
 271+/* Misc visuals
 272+----------------------------------*/
 273+
 274+/* Corner radius */
 275+.ui-corner-tl { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; }
 276+.ui-corner-tr { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; }
 277+.ui-corner-bl { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
 278+.ui-corner-br { -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
 279+.ui-corner-top { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; }
 280+.ui-corner-bottom { -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
 281+.ui-corner-right { -moz-border-radius-topright: 6px; -webkit-border-top-right-radius: 6px; border-top-right-radius: 6px; -moz-border-radius-bottomright: 6px; -webkit-border-bottom-right-radius: 6px; border-bottom-right-radius: 6px; }
 282+.ui-corner-left { -moz-border-radius-topleft: 6px; -webkit-border-top-left-radius: 6px; border-top-left-radius: 6px; -moz-border-radius-bottomleft: 6px; -webkit-border-bottom-left-radius: 6px; border-bottom-left-radius: 6px; }
 283+.ui-corner-all { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; }
 284+
 285+/* Overlays */
 286+.ui-widget-overlay { background: #5c5c5c url(images/ui-bg_flat_50_5c5c5c_40x100.png) 50% 50% repeat-x; opacity: .80;filter:Alpha(Opacity=80); }
 287+.ui-widget-shadow { margin: -7px 0 0 -7px; padding: 7px; background: #cccccc url(images/ui-bg_flat_30_cccccc_40x100.png) 50% 50% repeat-x; opacity: .60;filter:Alpha(Opacity=60); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/* Resizable
 288+----------------------------------*/
 289+.ui-resizable { position: relative;}
 290+.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;}
 291+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
 292+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
 293+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
 294+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
 295+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
 296+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
 297+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
 298+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
 299+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Selectable
 300+----------------------------------*/
 301+.ui-selectable-helper { border:1px dotted black }
 302+/* Accordion
 303+----------------------------------*/
 304+.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
 305+.ui-accordion .ui-accordion-li-fix { display: inline; }
 306+.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
 307+.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
 308+/* IE7-/Win - Fix extra vertical space in lists */
 309+.ui-accordion a { zoom: 1; }
 310+.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
 311+.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
 312+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
 313+.ui-accordion .ui-accordion-content-active { display: block; }/* Autocomplete
 314+----------------------------------*/
 315+.ui-autocomplete { position: absolute; cursor: default; }
 316+.ui-autocomplete-loading { background: white url('images/ui-anim_basic_16x16.gif') right center no-repeat; }
 317+
 318+/* workarounds */
 319+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
 320+
 321+/* Menu
 322+----------------------------------*/
 323+.ui-menu {
 324+ list-style:none;
 325+ padding: 2px;
 326+ margin: 0;
 327+ display:block;
 328+}
 329+.ui-menu .ui-menu {
 330+ margin-top: -3px;
 331+}
 332+.ui-menu .ui-menu-item {
 333+ margin:0;
 334+ padding: 0;
 335+ zoom: 1;
 336+ float: left;
 337+ clear: left;
 338+ width: 100%;
 339+}
 340+.ui-menu .ui-menu-item a {
 341+ text-decoration:none;
 342+ display:block;
 343+ padding:.2em .4em;
 344+ line-height:1.5;
 345+ zoom:1;
 346+}
 347+.ui-menu .ui-menu-item a.ui-state-hover,
 348+.ui-menu .ui-menu-item a.ui-state-active {
 349+ font-weight: normal;
 350+ margin: -1px;
 351+}
 352+/* Button
 353+----------------------------------*/
 354+
 355+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
 356+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
 357+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
 358+.ui-button-icons-only { width: 3.4em; }
 359+button.ui-button-icons-only { width: 3.7em; }
 360+
 361+/*button text element */
 362+.ui-button .ui-button-text { display: block; line-height: 1.4; }
 363+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
 364+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
 365+.ui-button-text-icon .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
 366+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
 367+/* no icon support for input elements, provide padding by default */
 368+input.ui-button { padding: .4em 1em; }
 369+
 370+/*button icon element(s) */
 371+.ui-button-icon-only .ui-icon, .ui-button-text-icon .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
 372+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
 373+.ui-button-text-icon .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
 374+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
 375+
 376+/*button sets*/
 377+.ui-buttonset { margin-right: 7px; }
 378+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
 379+
 380+/* workarounds */
 381+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
 382+
 383+
 384+
 385+
 386+
 387+/* Dialog
 388+----------------------------------*/
 389+.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
 390+.ui-dialog .ui-dialog-titlebar { padding: .5em 1em .3em; position: relative; }
 391+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .2em 0; }
 392+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
 393+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
 394+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
 395+.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
 396+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
 397+.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; }
 398+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
 399+.ui-draggable .ui-dialog-titlebar { cursor: move; }
 400+/* Slider
 401+----------------------------------*/
 402+.ui-slider { position: relative; text-align: left; }
 403+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
 404+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
 405+
 406+.ui-slider-horizontal { height: .8em; }
 407+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
 408+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
 409+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
 410+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
 411+
 412+.ui-slider-vertical { width: .8em; height: 100px; }
 413+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
 414+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
 415+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
 416+.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs
 417+----------------------------------*/
 418+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
 419+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
 420+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
 421+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
 422+.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
 423+.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
 424+.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
 425+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
 426+.ui-tabs .ui-tabs-hide { display: none !important; }
 427+/* Datepicker
 428+----------------------------------*/
 429+.ui-datepicker { width: 17em; padding: .2em .2em 0; }
 430+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
 431+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
 432+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
 433+.ui-datepicker .ui-datepicker-prev { left:2px; }
 434+.ui-datepicker .ui-datepicker-next { right:2px; }
 435+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
 436+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
 437+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
 438+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
 439+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
 440+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
 441+.ui-datepicker select.ui-datepicker-month,
 442+.ui-datepicker select.ui-datepicker-year { width: 49%;}
 443+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
 444+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
 445+.ui-datepicker td { border: 0; padding: 1px; }
 446+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
 447+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
 448+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
 449+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
 450+
 451+/* with multiple calendars */
 452+.ui-datepicker.ui-datepicker-multi { width:auto; }
 453+.ui-datepicker-multi .ui-datepicker-group { float:left; }
 454+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
 455+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
 456+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
 457+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
 458+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
 459+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
 460+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
 461+.ui-datepicker-row-break { clear:both; width:100%; }
 462+
 463+/* RTL support */
 464+.ui-datepicker-rtl { direction: rtl; }
 465+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
 466+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
 467+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
 468+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
 469+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
 470+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
 471+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
 472+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
 473+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
 474+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
 475+
 476+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
 477+.ui-datepicker-cover {
 478+ display: none; /*sorry for IE5*/
 479+ display/**/: block; /*sorry for IE5*/
 480+ position: absolute; /*must have*/
 481+ z-index: -1; /*must have*/
 482+ filter: mask(); /*must have*/
 483+ top: -4px; /*must have*/
 484+ left: -4px; /*must have*/
 485+ width: 200px; /*must have*/
 486+ height: 200px; /*must have*/
 487+}/* Progressbar
 488+----------------------------------*/
 489+.ui-progressbar { height:2em; text-align: left; }
 490+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
Property changes on: trunk/extensions/Reflect/client/css/jquery.ui.css
___________________________________________________________________
Added: svn:eol-style
1491 + native
Index: trunk/extensions/Reflect/client/css/reflect.study.css
@@ -0,0 +1,58 @@
 2+#reflected .survey_prompt {
 3+ margin-top: 10px;
 4+}
 5+
 6+
 7+#reflected .survey_prompt {
 8+ padding: 5px;
 9+ background-color: #c1f6c2;
 10+ border: 1px solid #089C57;
 11+}
 12+
 13+#reflected .survey_prompt:hover {
 14+ background-color: #8fd98f;
 15+}
 16+
 17+
 18+#reflected .survey_intro {
 19+ font-size:90%;
 20+ font-weight:bold;
 21+}
 22+
 23+#reflected .click_to_answer {
 24+ font-size: 85%;
 25+}
 26+
 27+#reflected .survey_intro li {
 28+}
 29+
 30+#reflected .survey_intro li.survey_label {
 31+ float:left;
 32+ width:90%;
 33+ cursor:pointer;
 34+}
 35+
 36+#reflected .survey_intro li.cancel_survey {
 37+ float:right;
 38+ position:relative;
 39+ left: 5px;
 40+}
 41+
 42+#reflected .survey_intro li.cancel_survey .skip:hover {
 43+ background-color: #aaa;
 44+}
 45+
 46+#reflected .survey_intro button{
 47+ border:none;
 48+ background-color:inherit;
 49+ padding:0;
 50+ cursor:pointer;
 51+}
 52+
 53+#reflected .skip img {
 54+ width: 15px;
 55+}
 56+
 57+#reflected .survey_prompt fieldset {
 58+ padding: 4px;
 59+}
Property changes on: trunk/extensions/Reflect/client/css/reflect.study.css
___________________________________________________________________
Added: svn:eol-style
160 + native
Index: trunk/extensions/Reflect/client/css/reflect.css
@@ -0,0 +1,501 @@
 2+#reflected .cl {clear:both;}
 3+
 4+#reflected li {
 5+ background: none;
 6+}
 7+
 8+#reflected .rf_comment_author {
 9+ display:none;
 10+}
 11+
 12+#reflected .rf_comment_wrapper {
 13+ position:relative;
 14+}
 15+
 16+#reflected .rf_comment_summary ol,
 17+#reflected .rf_comment_summary ul,
 18+#reflected .rf_comment_summary ol li,
 19+#reflected .rf_comment_summary ul li{
 20+ margin: 0;
 21+ padding: 0;
 22+ list-style: none;
 23+}
 24+
 25+
 26+/* LAYOUT BASED */
 27+
 28+ #reflected div.rf_comment_text_wrapper {
 29+ width:50%;
 30+ float:left;
 31+ }
 32+
 33+ #reflected div.rf_comment_summary{
 34+ width:42%;
 35+ float:right;
 36+ }
 37+
 38+ #reflected .rf_comment_summary div.summary {
 39+
 40+ }
 41+
 42+ #reflected .rf_comment_summary p.byline {
 43+ margin-bottom:3px;
 44+ position:relative;
 45+ font-size:105%;
 46+ font-weight:bold;
 47+ }
 48+
 49+ #reflected .username {
 50+ color: #999;
 51+ font-size: 75%;
 52+ margin-left: 4px;
 53+ }
 54+ #reflected .rf_comment_summary p.byline a.user {
 55+ cursor:pointer;
 56+ }
 57+
 58+ #reflected .rf_comment_summary ul.bullet_list {
 59+ margin-left: 10px;
 60+ }
 61+
 62+ #reflected .rf_comment_summary li.bullet{
 63+ padding: 5px 0px 5px 10px;
 64+ display:list-item;
 65+ position:relative;
 66+ margin-bottom: 3px;
 67+
 68+ line-height:1.3em;
 69+ /*list-style-image:url('http://daniels.cs.washington.edu/javascript/bullet.png');*/
 70+ }
 71+
 72+ #reflected .rf_comment_summary ul.bullet_list li.bullet:hover {
 73+ /*border:4px solid #EC9E5B;*/
 74+ /*background-color:#f3f3f3;*/
 75+
 76+ }
 77+
 78+ #reflected .rf_comment_summary span.bullet_text {
 79+ font-size:105%;
 80+ overflow:hidden;
 81+ word-wrap: break-word;
 82+
 83+ }
 84+
 85+
 86+ #reflected .rf_comment_summary li.bullet_authored_by {
 87+ font-size:85%;
 88+ color:#777;
 89+ }
 90+
 91+ #reflected .rf_comment_summary ul.response_footer_wrapper,
 92+ #reflected .rf_comment_summary ul.bullet_operations {
 93+ margin-left: 6px;
 94+ }
 95+ #reflected .rf_comment_summary ul.response_footer_wrapper li,
 96+ #reflected .rf_comment_summary ul.bullet_operations li {
 97+ display:static;
 98+ }
 99+ #reflected .rf_comment_summary .bullet ul.response_footer_wrapper button,
 100+ #reflected .rf_comment_summary .bullet ul.bullet_operations button,
 101+ #reflected .rf_comment_summary .bullet .submit_buttons button {
 102+ border:none;
 103+ background-color:inherit;
 104+ padding:0;
 105+ cursor:pointer;
 106+
 107+ }
 108+
 109+ #reflected .rf_comment_summary button.modify {
 110+
 111+ }
 112+
 113+
 114+ #reflected .rf_comment_summary button.delete {
 115+
 116+ }
 117+
 118+ #reflected .rf_comment_summary li.dispute_operation{
 119+ cursor:pointer;
 120+ }
 121+
 122+ #reflected .rf_comment_summary span.bullet_prompt_problem{
 123+ text-decoration:underline;
 124+ color:#777;
 125+ cursor:pointer;
 126+ font-size:85%;
 127+ padding-right:3px;
 128+ }
 129+
 130+ #reflected .rf_comment_summary ul.bullet_report_problem{
 131+ display:none;
 132+ opacity:none;
 133+ z-index:99;
 134+ background-color: #fff;
 135+ position:absolute;
 136+ width:auto;
 137+ right:0px;
 138+ }
 139+
 140+ #reflected .rf_comment_summary ul.bullet_report_problem li {
 141+ padding:5px;
 142+ border: 1px solid #bbb;
 143+ display:block;
 144+ width:100%;
 145+ }
 146+ #reflected .rf_comment_summary ul.bullet_report_problem li.flag.set {
 147+ background-color:#333;
 148+ color:#ccc;
 149+ }
 150+ #reflected .rf_comment_summary ul.bullet_report_problem li:hover {
 151+ background-color: #eee;
 152+
 153+ }
 154+ #reflected .rf_comment_summary ul.bullet_report_problem li a.user:hover {
 155+ text-decoration:none;
 156+ }
 157+
 158+ #reflected img.hover {
 159+ display:none;
 160+ }
 161+
 162+
 163+
 164+ /*************************
 165+ * NEW BULLET *
 166+ ************************/
 167+
 168+ #reflected .rf_comment_summary li.new_bullet {
 169+ border:none;
 170+
 171+ }
 172+
 173+ #reflected .rf_comment_summary li.modify {
 174+ height:auto;
 175+ }
 176+
 177+ #reflected .rf_comment_summary ul.bullet_list li.new_bullet:hover {
 178+ background-color:inherit;
 179+ border:none;
 180+ }
 181+ #reflected .rf_comment_summary button.add_bullet {
 182+ border: 1px solid #777;
 183+ color:#111;
 184+ background-color:#f2f2f2;
 185+ padding: 2px 10px;
 186+ font: bold 105% arial;
 187+ letter-spacing: -1px;
 188+ text-align: left;
 189+
 190+ }
 191+
 192+ #reflected .rf_comment_summary button.add_bullet:hover {
 193+ background-color:#ddd;
 194+ cursor:pointer;
 195+ }
 196+
 197+
 198+ #reflected .rf_comment_summary table.reflect {
 199+
 200+ }
 201+
 202+ #reflected .rf_comment_summary table.new_bullet_wrapper {
 203+ width:97%;
 204+ }
 205+
 206+
 207+ #reflected .rf_comment_summary td.connect_directions {
 208+ width: 98%;
 209+ /*border: 3px solid #004080 !important;
 210+ color: #004080;*/
 211+ font-size: 110%;
 212+ padding: 10px;
 213+ text-align:center;
 214+ }
 215+
 216+ #reflected .rf_comment_summary td.new_bullet_text_wrap {
 217+ }
 218+
 219+
 220+ #reflected .rf_comment_summary textarea.new_bullet_text {
 221+ height: 60px;
 222+ font-size: 135%;
 223+ padding: 4px 2px;
 224+ width:100%;
 225+ }
 226+
 227+ #reflected .rf_comment_summary tr.submit_footer {
 228+ width:100%;
 229+ padding-bottom: 5px;
 230+ }
 231+
 232+ #reflected .rf_comment_summary tr.submit_footer a {
 233+ color:inherit;
 234+ }
 235+
 236+ #reflected .rf_comment_summary tr.submit_footer a:hover {
 237+ background-color:inherit;
 238+ color:inherit;
 239+ }
 240+
 241+ #reflected .rf_comment_summary tr.submit_footer li {
 242+ display:inline-block;
 243+ }
 244+
 245+ #reflected .rf_comment_summary tr.submit_footer li.submit{
 246+ margin-right: 15px;
 247+ }
 248+
 249+ #reflected .rf_comment_summary tr.submit_footer li.be_neutral{
 250+ float:right;
 251+ }
 252+
 253+ #reflected .rf_comment_summary span.big_word {
 254+ text-decoration:underline;
 255+ }
 256+
 257+ #reflected .rf_comment_summary td.submit_buttons {
 258+ z-index: 50;
 259+ position:absolute;
 260+ padding:0;
 261+ left: 98%;
 262+ }
 263+
 264+ #reflected .rf_comment_summary td.submit_buttons button {
 265+ border: none;
 266+ background-color:inherit;
 267+ cursor:pointer;
 268+ padding:0;
 269+ }
 270+ #reflected .rf_comment_summary button.bullet_submit {
 271+
 272+
 273+ }
 274+
 275+ #reflected .rf_comment_summary button.cancel_bullet img{
 276+ width: 15px;
 277+ }
 278+
 279+
 280+
 281+/* TYPE BASED */
 282+
 283+#reflected button {
 284+ border: 1px outset;
 285+ font-weight:bold;
 286+}
 287+#reflected .rf_comment_wrapper a:hover,
 288+#reflected .rf_comment_summary a:hover{
 289+ color:inherit;
 290+ text-decoration:none;
 291+ background-color:inherit;
 292+
 293+}
 294+
 295+#reflected a.sentence{
 296+ text-decoration:none;
 297+}
 298+#reflected a{
 299+ cursor:pointer;
 300+}
 301+
 302+#reflected a.sentence,
 303+#reflected a.sentence:hover,
 304+#reflected .rf_comment_summary a:hover{
 305+ color:inherit;
 306+
 307+}
 308+#reflected a.sentence {
 309+ cursor:text;
 310+}
 311+
 312+#reflected .rf_comment_summary textarea {
 313+ padding: 3px 5px;
 314+ font-size:120%;
 315+}
 316+
 317+#reflected .highlight_state a.sentence {
 318+ cursor:pointer;
 319+ text-decoration:none
 320+}
 321+
 322+#reflected .highlight_state a.sentence:hover {
 323+ text-decoration:underline !important;
 324+}
 325+
 326+#reflected span.highlight,
 327+#reflected a.highlight {
 328+ background-color: #FFFF88;
 329+ color: #000;
 330+}
 331+
 332+
 333+#reflected a.highlight:hover {
 334+ background-color: #fffc29;
 335+ color: #000;
 336+}
 337+
 338+.fr {
 339+ float:right;
 340+}
 341+
 342+
 343+/* unorganized */
 344+
 345+#reflected .rf_comment_summary .response_dialog table.reflect {
 346+ position:static;
 347+}
 348+
 349+
 350+
 351+#reflected .rf_comment_summary .response table.new_bullet_wrapper {
 352+ position:relative;
 353+
 354+}
 355+
 356+#reflected .rf_comment_summary .bullet ul.rebutt_list li {
 357+ display:inline;
 358+
 359+}
 360+
 361+
 362+#reflected ul.response_eval {
 363+ display:inline;
 364+}
 365+
 366+#reflected ul.response_eval li {
 367+ display:inline;
 368+ margin-right: 3px;
 369+ font-size: 85%;
 370+}
 371+
 372+#reflected ul.response_eval li input{
 373+ margin: 5px 2px;
 374+}
 375+
 376+#reflected .response_footer_wrapper img,
 377+#reflected .bullet_footer_wrapper img{
 378+ width:15px;
 379+}
 380+
 381+#reflected .bullet .responses .response_def{
 382+
 383+}
 384+
 385+#reflected .response.new button.cancel_bullet {
 386+ display:none;
 387+}
 388+
 389+#reflected .responses {
 390+ margin-left: 8px;
 391+}
 392+
 393+#reflected .response_dialog {
 394+ display: none;
 395+}
 396+
 397+#reflected .responses .response_dialog textarea {
 398+ height:30px;
 399+}
 400+#reflected .response_def .prompt {
 401+ padding: 5px;
 402+ font-weight:bold;
 403+}
 404+
 405+#reflected .rebutt_list li.img img {
 406+ padding:2px 2px 0 0px;
 407+ width: 12px;
 408+}
 409+
 410+#reflected .rf_comment_summary .bullet_main {
 411+
 412+}
 413+
 414+ #reflected .rf_comment_summary .bullet_main .bullet_main_wrapper li{
 415+ list-style-type: none;
 416+ }
 417+ #reflected .rf_comment_summary .bullet_main .bullet_main_wrapper li.bullet_text{
 418+ width: 90%;
 419+ float:left;
 420+ min-height:38px;
 421+ }
 422+
 423+ #reflected .rf_comment_summary ul.rebutt_list {
 424+ color: #777;
 425+ width:75%;
 426+ float:left;
 427+ }
 428+ #reflected .rf_comment_summary .bullet_main .bullet_main_wrapper li.bullet_footer_wrapper{
 429+ width:10%;
 430+ }
 431+ #reflected .rf_comment_summary .response_footer_wrapper {
 432+ width:20%;
 433+ height:15px;
 434+
 435+ }
 436+
 437+ #reflected .rf_comment_summary .bullet_main .bullet_main_wrapper li.bullet_footer_wrapper,
 438+ #reflected .rf_comment_summary .response_footer_wrapper {
 439+ float:right;
 440+ }
 441+
 442+#reflected .rebutt_txt {
 443+ font-size: 85%;
 444+}
 445+
 446+#reflected .response_yes {
 447+ color:green;
 448+}
 449+
 450+#reflected .response_no {
 451+ color:red;
 452+}
 453+
 454+#reflected .response_maybe {
 455+ color:goldenRod;
 456+}
 457+
 458+#reflected .response_yes,
 459+#reflected .response_no,
 460+#reflected .response_maybe {
 461+ font-size: 125%;
 462+}
 463+
 464+#reflected .rf_comment_summary .responses li.response{
 465+
 466+}
 467+
 468+#reflected div.new_bullet_prompt {
 469+ position:absolute;
 470+ top:-7px;
 471+ z-index:50;
 472+ width:92%;
 473+ margin-left:3px;
 474+}
 475+#reflected div.new_bullet_prompt li {
 476+ display:inline;
 477+}
 478+#reflected div.new_bullet_prompt li.elicitation {
 479+ font-size:85%;
 480+ font-weight:bold;
 481+}
 482+#reflected div.new_bullet_prompt li.count {
 483+ float:right;
 484+ font-size: 125%;
 485+ color: #555;
 486+ text-decoration:none;
 487+
 488+}
 489+
 490+
 491+#reflected .highlight_state .bullet_footer_wrapper {
 492+ display:none;
 493+}
 494+
 495+#reflected .response_footer_wrapper,
 496+#reflected .response_footer_wrapper li {
 497+ display:inline;
 498+}
 499+
 500+#reflected .response_def .response_prompt{
 501+ background-color: #FFE5E5;
 502+}
\ No newline at end of file
Property changes on: trunk/extensions/Reflect/client/css/reflect.css
___________________________________________________________________
Added: svn:eol-style
1503 + native
Index: trunk/extensions/Reflect/client/css/reflect.liquidthreads.css
@@ -0,0 +1,16 @@
 2+#reflected div.rf_comment_text_wrapper {
 3+ width: 52%;
 4+}
 5+
 6+#reflected div.rf_comment_summary {
 7+ width: 40%;
 8+ margin-top: 5px;
 9+}
 10+
 11+#reflected .lqt-post-wrapper {
 12+ overflow:visible;
 13+}
 14+
 15+#reflected .rf_comment_summary textarea.new_bullet_text {
 16+ font-size: 110%;
 17+}
Property changes on: trunk/extensions/Reflect/client/css/reflect.liquidthreads.css
___________________________________________________________________
Added: svn:eol-style
118 + native
Index: trunk/extensions/Reflect/client/js/reflect.js
@@ -0,0 +1,1599 @@
 2+/* Copyright (c) 2010 Travis Kriplean (http://www.cs.washington.edu/homes/travis/)
 3+ * Licensed under the MIT License:
 4+ * http://www.opensource.org/licenses/mit-license.php
 5+ * Website: http://www.cs.washington.edu/homes/travis/reflect
 6+ *
 7+ *
 8+ * The core Reflect engine.
 9+ *
 10+ * Powers implementations of Reflect for Wordpress, Greasemonkey, and
 11+ * Mediawiki (with LiquidThreads).
 12+ *
 13+ * Applications need to define the DOM elements that Reflect needs to know about
 14+ * in order for this engine to wrap the basic Reflect comment summarization elements
 15+ * around desired text blocks. Each application should define a reflect.{APPLICATION}.js
 16+ * file where this configuration takes place.
 17+ *
 18+ * The script can take it from there.
 19+ *
 20+ * Current browser compatability:
 21+ *
 22+ * firefox : best
 23+ * safari : good
 24+ * chrome : good
 25+ * opera : untested
 26+ * IE6 : unusable
 27+ * IE7 : ugly as hell
 28+ * IE8 : ugly
 29+ *
 30+ */
 31+
 32+var $j = jQuery.noConflict();
 33+
 34+
 35+/**
 36+* Top-level enclosure. Structure:
 37+*
 38+* Reflect
 39+* .config : default configuration options
 40+* .Contract : base Class for implementing Reflect contract
 41+* .api : base Class and methods for interacting with server
 42+* .bind : attach event handlers to relevant objects before/after state transition
 43+* .handle : methods for responding to events
 44+* .transitions : methods implementing logic for handling state transitions
 45+* .templates : contains templates for dynamically adding HTML
 46+* .enforce_contract : takes a contract and existing DOM and wraps Reflect elements around it
 47+* .init : fetches data from server, downloads templates, enforces contract, other init-y things
 48+* .utils : misc methods used throughout
 49+*/
 50+
 51+var Reflect = {
 52+
 53+ /**
 54+ * Basic settings. Usually overriden per implementation.
 55+ */
 56+ config : {
 57+ api : {
 58+ /* Reflect API server */
 59+ server_loc : '',
 60+ /* location where media is served from */
 61+ media_dir : '',
 62+ /* unique identifier for this application */
 63+ domain : ''
 64+ },
 65+ contract : {
 66+ /* components is an array of objects, each of which defines key attributes of
 67+ * each DOM element which should be wrapped with Reflect text summarization.
 68+ *
 69+ * The attributes of each component are:
 70+ * comment_identifier : jquery selector for the comment element
 71+ * comment_offset : offset within the comment element's ID field where the ID begins
 72+ * comment_text : jquery selector for the text of the comment
 73+ * get_commenter_name : function that returns the name of the commenter, given a comment ID
 74+ */
 75+ components : []
 76+ },
 77+ study : false
 78+ },
 79+
 80+ /**
 81+ * Contract implements methods for identifying key DOM elements, as well as modifying
 82+ * the served DOM, that is necessary for wrapping Reflect elements around comments.
 83+ *
 84+ * This is the base class. Reflect implementations should replace Contract with
 85+ * a child class in reflect.{APPLICATION}.js.
 86+ */
 87+ Contract : Class.extend( {
 88+
 89+ /* jquery selector or function for getting the logged in user */
 90+ user_name_selector : null,
 91+
 92+ init : function ( config ) {
 93+ this.components = config.components;
 94+ },
 95+ /* Function that is executed BEFORE the Reflect contract is enforced.
 96+ * This is where the served DOM is whipped into shape (if it isn't already).*/
 97+ modifier : function () {
 98+ },
 99+ /* Returns a jquery element representing the comment list.*/
 100+ get_comment_thread : function () {
 101+ },
 102+ /* Some applications need to add css in the client. Call _addStyleSheet if needed.*/
 103+ add_css : function () {
 104+ },
 105+ _addStyleSheet : function ( style ) {
 106+ $j( 'head' ).append( '<style type="text/css">' + style + '</style>' );
 107+ }
 108+ } ),
 109+
 110+ /**
 111+ * Methods for communicating with a generic Reflect API. Reflect applications
 112+ * should override the base api.DataInterface class in order to implement the
 113+ * specific application-specific server calls to the Reflect API.
 114+ */
 115+ api : {
 116+ /**
 117+ * This is a base class. Reflect implementations should replace DataInterface with
 118+ * a child class in reflect.{APPLICATION}.js.
 119+ */
 120+ DataInterface : Class.extend( {
 121+ init : function ( config ) {
 122+ this.server_loc = config.server_loc;
 123+ this.media_dir = config.media_dir;
 124+ this.domain = config.domain;
 125+ },
 126+ post_bullet : function ( settings ) {
 127+ throw 'not implemented';
 128+ },
 129+ post_response : function ( settings ) {
 130+ throw 'not implemented';
 131+ },
 132+ post_survey_bullets : function ( settings ) {
 133+ throw 'not implemented';
 134+ },
 135+ get_data : function ( params, callback ) {
 136+ throw 'not implemented';
 137+ },
 138+ get_current_user : function () {
 139+ return 'Anonymous';
 140+ },
 141+ get_templates : function ( callback ) {
 142+ throw 'not implemented';
 143+ },
 144+ is_admin : function () {
 145+ return false;
 146+ }
 147+ } ),
 148+
 149+ /* Ajax posting of bullet to Reflect API. */
 150+ post_bullet : function () {
 151+ var bullet_obj = $j.data( $j( this )
 152+ .parents( '.bullet' )[0], 'bullet' ),
 153+ text = bullet_obj.elements.bullet_text.html(),
 154+ highlights = new Array(),
 155+ modify = bullet_obj.id;
 156+
 157+ text = jQuery.trim(
 158+ text.substring( 0,
 159+ text.indexOf( "<span class=\"username\">" ) ) );
 160+ function add_highlights () {
 161+ var el_id = $j( this ).attr( 'id' ).substring( 9 );
 162+ highlights.push( {
 163+ eid : el_id
 164+ } );
 165+ }
 166+ bullet_obj.comment.elements.comment_text.find( '.highlight' )
 167+ .each( add_highlights );
 168+
 169+ var params = {
 170+ comment_id : bullet_obj.comment.id,
 171+ text : text,
 172+ user : Reflect.utils.get_logged_in_user(),
 173+ highlights : JSON.stringify( highlights )
 174+ };
 175+
 176+ bullet_obj.options.highlights = highlights;
 177+ if ( bullet_obj.id ) {
 178+ params.bullet_id = bullet_obj.id;
 179+ params.bullet_rev = bullet_obj.rev;
 180+ }
 181+ function post_bullet_callback ( data ) {
 182+ if ( data ) {
 183+ if ( !bullet_obj.id ) {
 184+ bullet_obj.set_id( data.insert_id, data.rev_id );
 185+ }
 186+ Reflect.data[bullet_obj.comment.id][bullet_obj.id] = params;
 187+ if ( Reflect.config.study && !modify ) {
 188+ Reflect.study.new_bullet_survey(
 189+ bullet_obj, bullet_obj.comment, bullet_obj.$elem );
 190+ }
 191+ }
 192+ }
 193+
 194+ Reflect.api.server.post_bullet( {
 195+ params : params,
 196+ success : post_bullet_callback,
 197+ error : function ( data ) {
 198+ }
 199+ } );
 200+ Reflect.transitions.from_highlight( bullet_obj, false );
 201+ Reflect.transitions.to_base( bullet_obj.comment.id );
 202+ },
 203+
 204+ /* Ajax posting of a response to Reflect API. */
 205+ post_response : function ( response_obj ) {
 206+
 207+ function ajax_callback ( data ) {
 208+ var modify = response_obj.id;
 209+
 210+ if ( data && !modify ) {
 211+ response_obj.set_id( data.insert_id, data.rev_id );
 212+ }
 213+
 214+ if ( Reflect.config.study && !modify ) {
 215+ Reflect.study.new_bullet_reaction_survey(
 216+ bullet_obj, bullet_obj.comment,
 217+ bullet_obj.$elem );
 218+ }
 219+ }
 220+ var bullet_obj = response_obj.bullet,
 221+ text = bullet_obj.$elem
 222+ .find( 'textarea.new_bullet_text' ).val(),
 223+ user = Reflect.utils.get_logged_in_user();
 224+
 225+ if ( text.length == 0 ) {
 226+ return;
 227+ }
 228+
 229+ var input_sel = "input[name='accurate-"
 230+ + response_obj.bullet.id + "']:checked",
 231+ signal = bullet_obj.$elem.find( input_sel ).val();
 232+
 233+ var params = {
 234+ bullet_id : bullet_obj.id,
 235+ comment_id : bullet_obj.comment.id,
 236+ bullet_rev : bullet_obj.rev,
 237+ text : text,
 238+ signal : signal,
 239+ response : true,
 240+ user : user
 241+ };
 242+ if ( response_obj.id ) {
 243+ params.response_id = response_obj.id;
 244+ params.response_rev = response_obj.rev;
 245+ }
 246+ var vals = {
 247+ params : params,
 248+ success : ajax_callback,
 249+ error : function ( data ) {
 250+ }
 251+ };
 252+
 253+ Reflect.api.server.post_response( vals );
 254+ }
 255+
 256+ },
 257+
 258+ /**
 259+ * Methods for attaching event handlers to Bullets and Responses as they
 260+ * move from state to state.
 261+ */
 262+ bind : {
 263+ /* Establishes default state for a bullet */
 264+ bullet : function ( bullet_obj ) {
 265+
 266+ bullet_obj.elements.bullet_main
 267+ .hover( Reflect.handle.bullet_mouseover,
 268+ Reflect.handle.bullet_mouseout );
 269+
 270+ var footer = bullet_obj.elements.bullet_footer_wrapper;
 271+
 272+ footer
 273+ .find( '.dispute_operation' )
 274+ .hover( Reflect.handle.bullet_problem_mouseover,
 275+ Reflect.handle.bullet_problem_mouseout );
 276+
 277+ footer
 278+ .find( '.delete,.modify' )
 279+ .hover( Reflect.handle.operation_mouseover,
 280+ Reflect.handle.operation_mouseout );
 281+
 282+ footer
 283+ .find( '.delete' )
 284+ .bind( 'click', Reflect.handle.bullet_delete );
 285+
 286+ footer.find( '.bullet_report_problem .flag' )
 287+ .bind( 'click', Reflect.handle.bullet_flag );
 288+
 289+ footer.css( {
 290+ opacity : 0,
 291+ display : 'none'
 292+ } );
 293+
 294+ // set modify bullet action
 295+ if ( bullet_obj.user == Reflect.utils.get_logged_in_user() ) {
 296+ bullet_obj.elements.bullet_text
 297+ .click( Reflect.transitions.to_bullet );
 298+ footer.find( '.modify' )
 299+ .click( Reflect.transitions.to_bullet );
 300+ }
 301+ bullet_obj.$elem.find( '.response' ).each( function () {
 302+ var response_obj = $j.data( this, 'response' );
 303+ if ( $j( this ).hasClass( 'new' ) ) {
 304+ Reflect.bind.new_response( response_obj );
 305+ } else {
 306+ Reflect.bind.response( response_obj.bullet, response_obj );
 307+ }
 308+ } );
 309+ },
 310+
 311+ /* Establishes default state for a response */
 312+ response : function ( bullet_obj, response_obj ) {
 313+ response_obj.$elem
 314+ .hover( Reflect.handle.response_mouseover,
 315+ Reflect.handle.response_mouseout );
 316+
 317+ response_obj.$elem
 318+ .find( '.dispute_operation' )
 319+ .hover( Reflect.handle.response_problem_mouseover,
 320+ Reflect.handle.response_problem_mouseout );
 321+
 322+ response_obj.$elem
 323+ .find( '.delete,.modify' )
 324+ .hover( Reflect.handle.operation_mouseover,
 325+ Reflect.handle.operation_mouseout );
 326+
 327+ response_obj.$elem.find( '.delete' )
 328+ .bind( 'click', Reflect.handle.response_delete );
 329+
 330+ response_obj.$elem.find( '.response_footer_wrapper' ).css( {
 331+ opacity : 0,
 332+ display : 'none'
 333+ } );
 334+
 335+ var accurate_sel = 'input[name="accurate-' + response_obj.bullet.id + '"]';
 336+ response_obj.$elem
 337+ .find( accurate_sel )
 338+ .click( Reflect.handle.accurate_clicked );
 339+
 340+ if ( response_obj.user == Reflect.utils.get_logged_in_user() ) {
 341+ response_obj.$elem.find( '.rebutt_txt' )
 342+ .click( Reflect.transitions.to_response );
 343+ response_obj.$elem.find( '.modify' )
 344+ .click( Reflect.transitions.to_response );
 345+ }
 346+ },
 347+
 348+ /* Establishes dialog state for a response */
 349+ new_response : function ( response_obj ) {
 350+ response_obj.$elem.find( '.bullet_submit' ).bind( 'click', {
 351+ canceled : false
 352+ }, Reflect.transitions.from_response );
 353+
 354+ response_obj.$elem.find( '.cancel_bullet' ).bind( 'click', {
 355+ canceled : true
 356+ }, Reflect.transitions.from_response );
 357+
 358+ var settings = {
 359+ on_negative : Reflect.handle.negative_count,
 360+ on_positive : Reflect.handle.positive_count,
 361+ max_chars : 140
 362+ };
 363+
 364+ var text_area = response_obj.$elem.find( 'textarea' ),
 365+ count_sel = '#bullet-'
 366+ + response_obj.bullet.id
 367+ + ' .responses .new li.count';
 368+ text_area.NobleCount( count_sel, settings );
 369+
 370+ // wont work in GM
 371+ try {
 372+ text_area.focus();
 373+ } catch ( err ) {
 374+ }
 375+
 376+ response_obj.$elem
 377+ .find( 'input[name=\'accurate-' + response_obj.bullet.id + '\']' )
 378+ .click( Reflect.handle.accurate_clicked );
 379+ }
 380+
 381+ },
 382+
 383+ /**
 384+ * Boatload of event handlers. Naming convention is to have [noun]_[action|event].
 385+ */
 386+ handle : {
 387+ bullet_delete : function ( event ) {
 388+ var bullet_obj = $j.data( $j( this ).parents( '.bullet' )[0], 'bullet' ),
 389+ dialog = $j( '<div id="dialog-confirm">' );
 390+
 391+ $j( dialog ).dialog( {
 392+ resizable : false,
 393+ height : 'auto',
 394+ minHeight : 10,
 395+ position : [ 'right', 'center' ],
 396+ modal : true,
 397+ title : 'Do you really want to delete this bullet?',
 398+ buttons : {
 399+ 'Yes' : function () {
 400+ // TODO: this call should be moved to Reflect.api
 401+ var params = {
 402+ 'delete' : true,
 403+ comment_id : bullet_obj.comment.id,
 404+ bullet_id : bullet_obj.id,
 405+ bullet_rev : bullet_obj.rev
 406+ };
 407+ var call = {
 408+ params : params,
 409+ success : function ( data ) {
 410+ },
 411+ error : function ( data ) {
 412+ }
 413+ };
 414+
 415+ Reflect.api.server.post_bullet( call );
 416+
 417+ bullet_obj.comment.elements.comment_text.find( '.highlight' )
 418+ .removeClass( 'highlight' );
 419+ bullet_obj.$elem.remove();
 420+ $j( this ).dialog( 'close' );
 421+ },
 422+ 'No' : function () {
 423+ $j( this ).dialog( 'close' );
 424+ }
 425+ }
 426+ } );
 427+ },
 428+ bullet_mouseover : function ( event ) {
 429+
 430+ var bullet_obj = $j
 431+ .data( $j( this ).parents( '.bullet' )[0], 'bullet' );
 432+
 433+ if ( bullet_obj.comment.$elem.hasClass( 'highlight_state' )
 434+ || bullet_obj.comment.$elem.hasClass( 'bullet_state' ) ) {
 435+ // if a different bullet is in highlight state, don't do anything...
 436+ return;
 437+ }
 438+
 439+ var user = Reflect.utils.get_logged_in_user(),
 440+ footer = bullet_obj.elements.bullet_footer_wrapper;
 441+
 442+ var admin = Reflect.api.server.is_admin();
 443+
 444+ if ( user == bullet_obj.user ) {
 445+ footer.find( '.dispute_operation' ).hide();
 446+ footer.find( '.modify_operation' ).show();
 447+ footer.find( '.delete_operation' ).show();
 448+ } else if ( Reflect.api.server.is_admin() ) {
 449+ footer.find( '.modify_operation' ).hide();
 450+ footer.find( '.dispute_operation' ).show();
 451+ footer.find( '.delete_operation' ).show();
 452+ } else if ( user == bullet_obj.comment.user ) {
 453+ footer.find( '.dispute_operation' ).show();
 454+ footer.find( '.modify_operation' ).hide();
 455+ footer.find( '.delete_operation' ).hide();
 456+ } else {
 457+ footer.find( '.modify_operation' ).hide();
 458+ footer.find( '.delete_operation' ).hide();
 459+ footer.find( '.dispute_operation' ).show();
 460+ }
 461+
 462+ footer.animate( {
 463+ opacity : 1
 464+ }, 300 ).show();
 465+
 466+ for ( var h in bullet_obj.highlights) {
 467+ bullet_obj.comment.elements.comment_text
 468+ .find( '#sentence-' + bullet_obj.highlights[h].eid )
 469+ .addClass( 'highlight' );
 470+ }
 471+
 472+ function color_convert ( color ) {
 473+ if ( color > 128 ) {
 474+ return color - 8;
 475+ } else {
 476+ return color + 8;
 477+ }
 478+ }
 479+ $j( this ).css( 'background-color', Reflect.utils
 480+ .get_inverted_background_color( $j( this ), color_convert ) );
 481+
 482+ },
 483+
 484+ bullet_mouseout : function ( event ) {
 485+ var comment = $j( this ).parents( '.rf_comment_wrapper' );
 486+ if ( comment.hasClass( 'highlight_state' )
 487+ || comment.hasClass( 'bullet_state' ) ) {
 488+ // if a different bullet is in highlight state, don't do anything...
 489+ return;
 490+ }
 491+
 492+ $j( this ).find( '.bullet_footer_wrapper' ).animate( {
 493+ opacity : 0
 494+ }, 300, function () {
 495+ } );
 496+
 497+ $j( this ).find( '.bullet_footer_wrapper' ).hide();
 498+
 499+ comment.find( '.highlight' ).removeClass( 'highlight' );
 500+ $j( this ).css( 'background-color', 'transparent' );
 501+ },
 502+
 503+ bullet_problem_mouseover : function ( event ) {
 504+ $j( this ).find( '.bullet_report_problem' ).show();
 505+ $j( this ).find( '.bullet_report_problem' ).animate( {
 506+ opacity : 1
 507+ }, 300 );
 508+ $j( this ).find( 'img.hover' ).css( 'display', 'inline' );
 509+ $j( this ).find( 'img.base' ).hide();
 510+ },
 511+
 512+ bullet_problem_mouseout : function ( event ) {
 513+ $j( this ).find( '.bullet_report_problem' ).animate( {
 514+ opacity : 0
 515+ }, 300 );
 516+ $j( this ).find( 'img.hover' ).hide();
 517+ $j( this ).find( 'img.base' ).css( 'display', 'inline' );
 518+ },
 519+
 520+ bullet_flag : function ( event ) {
 521+ var bullet_obj = $j.data( $j( this ).parents( '.bullet' )[0], 'bullet' ),
 522+ flags = bullet_obj.flags,
 523+ flag = $j( this ).attr( 'name' );
 524+
 525+ if ( flags[flag] && flags[flag] > 0 ) {
 526+ flags[flag] = -1;
 527+ $j( this ).removeClass( 'set' );
 528+ } else {
 529+ flags[flag] = 1;
 530+ $j( this ).addClass( 'set' );
 531+ }
 532+
 533+ },
 534+ operation_mouseover : function ( event ) {
 535+ $j( this ).find( 'img.hover' ).css( 'display', 'inline' );
 536+ $j( this ).find( 'img.base' ).hide();
 537+ },
 538+
 539+ operation_mouseout : function ( event ) {
 540+ $j( this ).find( 'img.hover' ).hide();
 541+ $j( this ).find( 'img.base' ).css( 'display', 'inline' );
 542+ },
 543+
 544+ response_delete : function ( event ) {
 545+ var response_obj = $j.data( $j( this )
 546+ .parents( '.response' )[0], 'response' );
 547+
 548+ // TODO: move this to Reflect.api
 549+ var params = {
 550+ 'delete' : true,
 551+ response : true,
 552+ response_id : response_obj.id,
 553+ bullet_id : response_obj.bullet.id,
 554+ bullet_rev : response_obj.bullet.rev,
 555+ comment_id : response_obj.bullet.comment.id
 556+ };
 557+
 558+ var vals = {
 559+ success : function ( data ) {
 560+ },
 561+ error : function ( data ) {
 562+ },
 563+ params : params
 564+ };
 565+
 566+ Reflect.api.server.post_response( vals );
 567+
 568+ response_obj.response_delete();
 569+ Reflect.bind.new_response( response_obj );
 570+ },
 571+
 572+ response_mouseover : function ( event ) {
 573+ var response_obj = $j.data( this, 'response' ),
 574+ user = Reflect.utils.get_logged_in_user();
 575+
 576+ if ( user == response_obj.user ) {
 577+ response_obj.$elem.find( '.dispute_operation' ).hide();
 578+ } else if ( Reflect.api.server.is_admin() ) {
 579+ response_obj.$elem.find( '.modify_operation' ).hide();
 580+ response_obj.$elem.find( '.dispute_operation' ).hide();
 581+ } else {
 582+ response_obj.$elem.find( '.delete_operation' ).hide();
 583+ response_obj.$elem.find( '.modify_operation' ).hide();
 584+ response_obj.$elem.find( '.dispute_operation' ).hide();
 585+ }
 586+ response_obj.$elem.find( '.response_footer_wrapper' ).show()
 587+ .animate( {
 588+ opacity : 1
 589+ }, 300 );
 590+
 591+ function color_convert ( color ) {
 592+ if ( color > 128 ) {
 593+ return color - 8;
 594+ } else {
 595+ return color + 8;
 596+ }
 597+ }
 598+ $j( this ).css( 'background-color', Reflect.utils
 599+ .get_inverted_background_color( $j( this ), color_convert ) );
 600+ },
 601+
 602+ response_mouseout : function ( event ) {
 603+ var footer_wrapper = $j( this ).find( '.response_footer_wrapper' );
 604+ footer_wrapper.animate( {
 605+ opacity : 0
 606+ }, 300, function () {
 607+ } );
 608+ footer_wrapper.hide();
 609+ $j( this ).css( 'background', 'transparent' );
 610+ },
 611+
 612+ response_problem_mouseover : function ( event ) {
 613+ $j( this ).find( '.bullet_report_problem' ).show();
 614+ $j( this ).find( '.bullet_report_problem' ).animate( {
 615+ opacity : 1
 616+ }, 300 );
 617+ $j( this ).find( 'img.hover' ).css( 'display', 'inline' );
 618+ $j( this ).find( 'img.base' ).hide();
 619+ },
 620+
 621+ response_problem_mouseout : function ( event ) {
 622+ $j( this ).find( '.bullet_report_problem' ).animate( {
 623+ opacity : 0
 624+ }, 300 );
 625+ $j( this ).find( 'img.hover' ).hide();
 626+ $j( this ).find( 'img.base' ).css( 'display', 'inline' );
 627+ },
 628+
 629+ comment_mouseover : function ( event ) {
 630+ },
 631+ comment_mouseout : function ( event ) {
 632+ },
 633+
 634+ negative_count : function ( t_obj, char_area, c_settings, char_rem ) {
 635+ if ( !char_area.hasClass( 'too_many_chars' ) ) {
 636+ char_area.addClass( 'too_many_chars' ).css( {
 637+ 'font-weight' : 'bold',
 638+ 'font-size' : '200%'
 639+ } );
 640+
 641+ t_obj.parents( '.new_bullet_wrapper' ).find( '.bullet_submit' )
 642+ .animate( {
 643+ opacity : .25,
 644+ duration : 50
 645+ } ).attr( 'disabled', true ).css( 'cursor', 'default' );
 646+ t_obj.data( 'disabled', true );
 647+
 648+ }
 649+ },
 650+ positive_count : function ( t_obj, char_area, c_settings, char_rem ) {
 651+ if ( char_area.hasClass( 'too_many_chars' ) ) {
 652+ char_area.removeClass( 'too_many_chars' ).css( {
 653+ 'font-weight' : 'normal',
 654+ 'font-size' : '125%'
 655+ } );
 656+
 657+ t_obj.parents( '.new_bullet_wrapper' ).find( '.bullet_submit' )
 658+ .animate( {
 659+ opacity : 1,
 660+ duration : 50
 661+ } ).attr( 'disabled', false ).css( 'cursor', 'pointer' );
 662+ t_obj.data( 'disabled', false );
 663+ } else if ( char_rem < 140 && $j( t_obj ).data( 'disabled' ) ) {
 664+ t_obj.data( 'disabled', false );
 665+ t_obj.parents( 'li' ).find( '.submit button' )
 666+ .attr( 'disabled', false );
 667+ } else if ( char_rem == 140 ) {
 668+ t_obj.data( 'disabled', true );
 669+ t_obj.parents( 'li' ).find( '.submit button' )
 670+ .attr( 'disabled', true );
 671+ }
 672+ },
 673+ sentence_click : function ( event ) {
 674+ var parent = $j( this ).parents( '.rf_comment' ),
 675+ comment = $j.data( parent[0], 'comment' );
 676+
 677+ if ( parent.hasClass( 'highlight_state' ) ) {
 678+ var bullet = parent.find( '.connect_directions' )
 679+ .parents( '.bullet' ).data( 'bullet' ),
 680+ submit = bullet.elements.submit_button;
 681+ if ( submit.length == 0 ) {
 682+ submit = parent.find( '.bullet.modify button.bullet_submit' );
 683+ }
 684+
 685+ if ( $j( this ).hasClass( 'highlight' ) ) {
 686+ $j( this ).removeClass( 'highlight' );
 687+ if ( parent.find( '.rf_comment_text .highlight' ).length == 0 ) {
 688+ submit.attr( 'disabled', true );
 689+ }
 690+ } else {
 691+ $j( this ).addClass( 'highlight' );
 692+ if ( submit.attr( 'disabled' ) == true ) {
 693+ submit.attr( 'disabled', false );
 694+ }
 695+ }
 696+ }
 697+ },
 698+
 699+ accurate_clicked : function () {
 700+ var response_obj = $j.data( $j( this )
 701+ .parents( '.response' )[0], 'response' );
 702+
 703+ response_obj.$elem.find( '.response_dialog' ).slideDown();
 704+ var accurate_sel = 'input[name=\'accurate-'
 705+ + response_obj.bullet.id
 706+ + '\']:checked',
 707+ val = response_obj.$elem.find( accurate_sel ).val();
 708+ response_obj.$elem.find( '.submit button' ).removeAttr( 'disabled' );
 709+
 710+ var ta = response_obj.$elem.find( 'textarea' ),
 711+ txt = ta.val();
 712+ if ( txt == ''
 713+ || txt == "Actually, I meant that..."
 714+ || txt == "Thanks, that is what I was saying"
 715+ || txt == "On the right track" )
 716+ {
 717+ switch ( val ) {
 718+ case "0":
 719+ ta.val( "Actually, I meant that..." );
 720+ break;
 721+ case "1":
 722+ ta.val( "On the right track" );
 723+ break;
 724+ case "2":
 725+ ta.val( "Thanks, that is what I was saying" );
 726+ break;
 727+ }
 728+
 729+ // doesn't work in GM
 730+ try {
 731+ ta.trigger( 'change' );
 732+ } catch ( err ) {
 733+ }
 734+ }
 735+ }
 736+
 737+ },
 738+
 739+ /**
 740+ * Collection of methods for transitioning Bullets and Responses to / from
 741+ * different states.
 742+ *
 743+ * Bullets can be in dialog state (bullet), highlight state, and base state.
 744+ * Responses can be in dialog state and base state.
 745+ */
 746+ transitions : {
 747+ to_base : function ( comment_id ) {
 748+ var comment = $j.data( $j( '#summary-' + comment_id )
 749+ .parents( '.rf_comment' )[0], 'comment' ),
 750+ logged_in_user = Reflect.utils.get_logged_in_user();
 751+
 752+ if ( comment.user == logged_in_user ) {
 753+ return;
 754+ }
 755+
 756+ if ( comment.$elem.find( '.new_bullet' ).length == 0 ) {
 757+ var new_bullet = comment.add_bullet_prompt();
 758+ new_bullet.$elem.children( 'button' )
 759+ .bind( 'click', Reflect.transitions.to_bullet, false );
 760+ }
 761+ },
 762+
 763+ to_bullet : function () {
 764+ // TODO: much of this should be moved to Reflect.bind.new_bullet
 765+
 766+ var bullet_obj = $j.data( $j( this )
 767+ .parents( '.bullet' )[0], 'bullet' );
 768+
 769+ bullet_obj.enter_edit_state();
 770+ bullet_obj.$elem.find( '.bullet_submit' ).bind( 'click', {
 771+ canceled : false,
 772+ bullet_obj : bullet_obj
 773+ }, function ( event ) {
 774+ Reflect.transitions.from_bullet( event );
 775+ Reflect.transitions.to_highlight( event );
 776+ } );
 777+
 778+ bullet_obj.$elem.find( '.cancel_bullet' ).bind( 'click', {
 779+ canceled : true,
 780+ bullet_obj : bullet_obj
 781+ }, Reflect.transitions.from_bullet );
 782+
 783+ bullet_obj.comment.$elem.addClass( 'bullet_state' );
 784+
 785+ var settings = {
 786+ on_negative : Reflect.handle.negative_count,
 787+ on_positive : Reflect.handle.positive_count,
 788+ max_chars : 140
 789+ }, text_area = bullet_obj.$elem.find( 'textarea' );
 790+
 791+ var count_sel = '#rf_comment_wrapper-' +
 792+ bullet_obj.comment.id + ' .bullet.modify li.count';
 793+ text_area.NobleCount(count_sel , settings );
 794+
 795+ // wont work in Greasemonkey
 796+ try {
 797+ text_area.focus();
 798+ } catch ( err ) {
 799+ }
 800+
 801+ cur_text = text_area.text();
 802+ if ( !cur_text || cur_text.length == 0 ) {
 803+ bullet_obj.elements.submit_button.attr( 'disabled', 'true' );
 804+ }
 805+
 806+ },
 807+
 808+ from_bullet : function ( event ) {
 809+ var canceled = event.data.canceled,
 810+ bullet_obj = event.data.bullet_obj;
 811+
 812+ bullet_obj.comment.$elem.removeClass( 'bullet_state' );
 813+
 814+ var params = {};
 815+ if ( !canceled ) {
 816+ params = {
 817+ bullet_text : bullet_obj.elements.new_bullet_text.val(),
 818+ user : Reflect.utils.get_logged_in_user()
 819+ };
 820+ if ( params.bullet_text.length == 0 ) {
 821+ return;
 822+ }
 823+ }
 824+
 825+ bullet_obj.exit_edit_state( params, canceled );
 826+
 827+ if ( !canceled && !bullet_obj.id ) {
 828+ bullet_obj.elements.bullet_text.animate( {
 829+ backgroundColor : '#FFFFaa'
 830+ }, {
 831+ duration : 1000
 832+ } );
 833+ } else if ( canceled && !bullet_obj.id ) {
 834+ bullet_obj.$elem.children( 'button' )
 835+ .bind( 'click', Reflect.transitions.to_bullet, false );
 836+ } else if ( canceled && bullet_obj.id ) {
 837+ Reflect.bind.bullet( bullet_obj );
 838+ }
 839+
 840+ },
 841+
 842+ to_highlight : function ( event ) {
 843+ var bullet_obj = event.data.bullet_obj;
 844+
 845+ bullet_obj.comment.$elem.addClass( 'highlight_state' );
 846+
 847+ var highlight = bullet_obj.enter_highlight_state();
 848+
 849+ highlight.find( 'td:first' ).addClass( 'connect_directions' )
 850+ .text( 'Please click the relevant sentences' )
 851+ .css( 'color', Reflect.utils.get_background_color( highlight ) )
 852+ .css( 'background-color', Reflect.utils
 853+ .get_inverted_background_color( highlight, function ( c ) {
 854+ return 255 - c;
 855+ } ) );
 856+
 857+ bullet_obj.elements.submit_button
 858+ .bind( 'click', Reflect.api.post_bullet );
 859+
 860+ highlight.find( '.cancel_bullet' ).bind( 'click', function () {
 861+ Reflect.transitions.from_highlight( bullet_obj, true );
 862+ } ).bind( 'click', function () {
 863+ Reflect.transitions.to_base( bullet_obj.comment.id );
 864+ } );
 865+
 866+ if ( bullet_obj.comment.$elem.find( '.highlight' ).length == 0 ) {
 867+ bullet_obj.elements.submit_button.attr( 'disabled', true );
 868+ }
 869+
 870+ var ctext = bullet_obj.comment.elements.comment_text;
 871+
 872+ function cc ( color ) {
 873+ if ( color > 128 ) {
 874+ return color - 60;
 875+ } else {
 876+ return color + 60;
 877+ }
 878+ }
 879+
 880+ try {
 881+ ctext
 882+ .pulse( {
 883+ backgroundColor : [
 884+ Reflect.utils
 885+ .get_background_color( ctext ),
 886+ Reflect.utils
 887+ .get_inverted_background_color( ctext, cc ) ]
 888+ }, 200, 4, 'linear', function () {
 889+ $j( this ).attr( 'style', '' );
 890+ } );
 891+ } catch ( err ) {
 892+ }
 893+
 894+ },
 895+ from_highlight : function ( bullet_obj, canceled ) {
 896+ var comment = bullet_obj.comment,
 897+ modified = bullet_obj.id;
 898+
 899+ comment.$elem.removeClass( 'highlight_state' );
 900+
 901+ bullet_obj.exit_highlight_state( canceled );
 902+ if ( !canceled ) {
 903+ Reflect.bind.bullet( bullet_obj );
 904+
 905+ var bullet_text = bullet_obj.elements.bullet_text,
 906+ bg = Reflect.utils.get_background_color( bullet_text );
 907+ bullet_text.animate( {
 908+ backgroundColor : bg
 909+ }, {
 910+ duration : 1500,
 911+ complete : function () {
 912+ $j( this ).removeAttr( 'style' );
 913+ }
 914+ } );
 915+
 916+ } else if ( modified ) {
 917+ Reflect.bind.bullet( bullet_obj );
 918+ } else {
 919+ bullet_obj.$elem.children( 'button' )
 920+ .bind( 'click', Reflect.transitions.to_bullet, false );
 921+ }
 922+
 923+ },
 924+
 925+ to_response : function () {
 926+ var response_obj = $j.data( $j( this )
 927+ .parents( '.response' )[0], 'response' );
 928+ response_obj.enter_edit_state();
 929+ Reflect.bind.new_response( response_obj );
 930+ },
 931+
 932+ from_response : function ( event ) {
 933+ var response_obj = $j.data( $j( this )
 934+ .parents( '.response' )[0], 'response' ),
 935+ bullet_obj = response_obj.bullet,
 936+ canceled = event.data.canceled;
 937+
 938+ params = {
 939+ media_dir : Reflect.api.server.media_dir,
 940+ user : Reflect.utils.get_logged_in_user()
 941+ };
 942+
 943+ if ( !canceled ) {
 944+ var accurate_sel = "input[name='accurate-" +
 945+ response_obj.bullet.id + "']:checked";
 946+ params.text = response_obj.elements.new_response_text.val();
 947+ params.sig = response_obj.$elem.find( accurate_sel ).val();
 948+ Reflect.api.post_response( response_obj );
 949+ }
 950+ response_obj.exit_dialog( params, canceled );
 951+
 952+ if ( !canceled || response_id ) {
 953+ Reflect.bind.response( bullet_obj, response_obj );
 954+ }
 955+
 956+ }
 957+
 958+ },
 959+
 960+ /**
 961+ * Your standard misc collection of functions.
 962+ */
 963+ utils : {
 964+ /* escape the string */
 965+ escape : function (str) {
 966+ if ( str ) {
 967+ return $j('<div/>')
 968+ .text(str)
 969+ .html();
 970+ } else {
 971+ return '';
 972+ }
 973+ },
 974+
 975+ get_logged_in_user : function () {
 976+ if ( typeof Reflect.current_user == 'undefined' ) {
 977+ //jquery.text escapes the html
 978+ Reflect.current_user = $j( '#rf_user_name' ).text();
 979+ }
 980+ return Reflect.current_user;
 981+ },
 982+
 983+ get_background_color : function ( node ) {
 984+ var current_p = $j( node ),
 985+ rgbString = "transparent";
 986+ while ( current_p
 987+ && (rgbString == "transparent"
 988+ || rgbString == "initial"
 989+ || rgbString == 'rgba(0, 0, 0, 0)') )
 990+ {
 991+ rgbString = current_p.parent().css( 'background-color' );
 992+ current_p = current_p.parent();
 993+ }
 994+ if ( !rgbString ) {
 995+ rgbString = 'rgb(0, 0, 0)';
 996+ }
 997+ return rgbString;
 998+ },
 999+
 1000+ get_inverted_background_color : function ( node, color_convert ) {
 1001+ try {
 1002+ var rgbString = Reflect.utils.get_background_color( node ),
 1003+ parts = rgbString.match( /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/ ),
 1004+ res = '#';
 1005+ for ( var i = 1; i <= 3; ++i) {
 1006+ var color = parseInt( parts[i] ),
 1007+ new_color = color_convert( color );
 1008+ parts[i] = new_color.toString( 16 );
 1009+ if ( parts[i].length == 1 ) {
 1010+ parts[i] = '0' + parts[i];
 1011+ }
 1012+ res += parts[i];
 1013+ }
 1014+ return res;
 1015+ } catch ( err ) {
 1016+ return '#555';
 1017+ }
 1018+ }
 1019+ },
 1020+
 1021+ /**
 1022+ * Object classes representing important object types:
 1023+ * Comment, Bullet, and Response.
 1024+ *
 1025+ * Instantiations of each object class are attached to their respective DOM
 1026+ * elements via jquery.data. And each object maintains reference to DOM
 1027+ * element reference.
 1028+ *
 1029+ * Object instances know how to transform their own DOM given state changes.
 1030+ * More than meets the eye.
 1031+ *
 1032+ * They also know how to manage adding children. For example, Comment knows
 1033+ * how to add Bullets.
 1034+ *
 1035+ * Instantiation is accomplished via jquery.plugin, enabling
 1036+ * e.g. $j('#comment').comment(). Plugin registration accomplished in
 1037+ * Reflect.init.
 1038+ */
 1039+ entities : {
 1040+
 1041+ Comment : {
 1042+ init : function ( options, elem ) {
 1043+ this.options = $j.extend( {}, this.options, options );
 1044+
 1045+ this.elem = elem;
 1046+ this.$elem = $j( elem );
 1047+ this.elements = {};
 1048+
 1049+ this.id = this.$elem.attr( 'id' )
 1050+ .substring( this.options.initializer.comment_offset );
 1051+ this.user = this.options.initializer.get_commenter_name( this.id );
 1052+ if ( this.user == '' || this.user == null ) {
 1053+ this.user = 'Anonymous';
 1054+ }
 1055+ if ( this.user.indexOf( ' ' ) > -1 ) {
 1056+ this.user_short = this.user.split( ' ' )[0];
 1057+ } else {
 1058+ this.user_short = this.user;
 1059+ }
 1060+
 1061+ this.bullets = [];
 1062+
 1063+ this._build();
 1064+ return this;
 1065+ },
 1066+ options : {},
 1067+ _build : function () {
 1068+ var comment_text = this.$elem
 1069+ .find( this.options.initializer.comment_text );
 1070+ this.$elem.addClass( 'rf_comment' );
 1071+
 1072+ var wrapper = $j( ''
 1073+ + '<div id="rf_comment_text_wrapper-'
 1074+ + this.id + '" class="rf_comment_text_wrapper">'
 1075+ + '<div class=rf_comment_text />' + '</div>' );
 1076+
 1077+ var summary_block = $j( ''
 1078+ + '<div id="rf_comment_summary-'
 1079+ + this.id + '" class="rf_comment_summary">'
 1080+ + '<div class="summary" id="summary-' + this.id + '">'
 1081+ + '<ul class="bullet_list" />' + '</div>' + '</div>' );
 1082+
 1083+ var author_block = $j( '<span class="rf_comment_author">'
 1084+ + this.user + '</span>' );
 1085+
 1086+ comment_text
 1087+ .wrapInner( wrapper )
 1088+ .append( summary_block )
 1089+ .append( author_block )
 1090+ .append( $j( '<div style="clear:both" />' ) )
 1091+ .wrapInner( $j( '<div id="rf_comment_wrapper-'
 1092+ + this.id + '" class="rf_comment_wrapper" />' ) );
 1093+
 1094+ this.elements = {
 1095+ bullet_list : comment_text.find( '.bullet_list' ),
 1096+ comment_text : this.$elem.find( '.rf_comment_text' ),
 1097+ text_wrapper : this.$elem.find( '.rf_comment_text_wrapper' )
 1098+ };
 1099+
 1100+ },
 1101+ _add_bullet : function ( params ) {
 1102+ var bullet = $j( '<li />' ).bullet( params );
 1103+
 1104+ this.elements.bullet_list.append( bullet );
 1105+
 1106+ var bullet_obj = $j.data( bullet[0], 'bullet' );
 1107+ this.bullets.push( bullet_obj );
 1108+ return bullet_obj;
 1109+ },
 1110+ add_bullet : function ( bullet_info ) {
 1111+ var bullet_text = bullet_info.txt,
 1112+ bullet_id = bullet_info.id,
 1113+ responses = '';
 1114+ params = {
 1115+ is_prompt : false,
 1116+ user : bullet_info.u,
 1117+ bullet_text : bullet_text,
 1118+ bullet_id : bullet_id,
 1119+ bullet_rev : bullet_info.rev,
 1120+ commenter : this.user,
 1121+ responses : responses,
 1122+ comment : this,
 1123+ highlights : bullet_info.highlights
 1124+ };
 1125+ return this._add_bullet( params );
 1126+ },
 1127+ add_bullet_prompt : function () {
 1128+ params = {
 1129+ is_prompt : true,
 1130+ commenter : this.user_short,
 1131+ comment : this
 1132+ };
 1133+
 1134+ var bullet_obj = this._add_bullet( params );
 1135+ return bullet_obj;
 1136+ },
 1137+ clear_text : function () {
 1138+ this.elements.text_wrapper.unbind().find( '.highlight' )
 1139+ .removeClass( 'highlight' );
 1140+ }
 1141+
 1142+ },
 1143+
 1144+ Bullet : {
 1145+ init : function ( options, elem ) {
 1146+ this.options = $j.extend( {}, this.options, options );
 1147+ this.options.media_dir = Reflect.api.server.media_dir;
 1148+
 1149+ // Save the element reference, both as a jQuery
 1150+ // reference and a normal reference
 1151+ this.elem = elem;
 1152+ this.$elem = $j( elem );
 1153+ this.elements = {};
 1154+
 1155+ this.set_attributes();
 1156+ this.responses = [];
 1157+ this.flags = {};
 1158+
 1159+ // Build the dom initial structure
 1160+ if ( this.options.is_prompt ) {
 1161+ this._build_prompt();
 1162+ } else {
 1163+ this._build();
 1164+ }
 1165+ return this;
 1166+
 1167+ },
 1168+ set_attributes : function () {
 1169+ if ( !this.id ) {
 1170+ this.id = this.options.bullet_id;
 1171+ this.rev = this.options.bullet_rev;
 1172+ }
 1173+ if ( !this.user ) {
 1174+ this.user = this.options.user;
 1175+ }
 1176+ if ( !this.comment ) {
 1177+ this.comment = this.options.comment;
 1178+ }
 1179+ this.highlights = this.options.highlights;
 1180+ },
 1181+ options : {},
 1182+ _build : function () {
 1183+ var template_vars = {
 1184+ bullet_text : Reflect.utils.escape( this.options.bullet_text ),
 1185+ user : Reflect.utils.escape( this.options.user ),
 1186+ media_dir : Reflect.config.api.media_dir,
 1187+ commenter : Reflect.utils.escape( this.options.commenter )
 1188+ };
 1189+ this.$elem
 1190+ .addClass( 'bullet' )
 1191+ .html( $j.jqote( Reflect.templates.bullet, template_vars ) )
 1192+ .css( {
 1193+ 'background' : 'url('
 1194+ + Reflect.api.server.media_dir
 1195+ + 'bullet.png) left top no-repeat'
 1196+ } );
 1197+
 1198+ if ( this.id ) {
 1199+ this.set_id( this.id, this.rev );
 1200+ }
 1201+
 1202+ this.elements = {
 1203+ response_list : this.$elem.find( '.responses ul' ),
 1204+ bullet_text : this.$elem.find( '.bullet_text' ),
 1205+ bullet_main : this.$elem.find( '.bullet_main' ),
 1206+ bullet_footer_wrapper : this.$elem
 1207+ .find( '.bullet_footer_wrapper' )
 1208+ };
 1209+ },
 1210+ _build_prompt : function () {
 1211+ var template_vars = {
 1212+ commenter : Reflect.utils.escape( this.options.commenter )
 1213+ };
 1214+ this.$elem
 1215+ .addClass( 'bullet' )
 1216+ .addClass( 'new_bullet' )
 1217+ .html( $j.jqote( Reflect.templates.new_bullet_prompt,
 1218+ template_vars ) )
 1219+ .css( {
 1220+ 'background' : 'url('
 1221+ + Reflect.api.server.media_dir
 1222+ + 'bullet.png) left top no-repeat'
 1223+ } );
 1224+
 1225+ this.elements = {};
 1226+ },
 1227+ set_id : function ( id, rev ) {
 1228+ this.id = parseInt(id);
 1229+ this.rev = parseInt(rev);
 1230+ this.$elem.attr( 'id', 'bullet-' + this.id );
 1231+ },
 1232+ enter_edit_state : function () {
 1233+ var text = '',
 1234+ modify = this.id;
 1235+
 1236+ if ( modify ) {
 1237+ text = this.elements.bullet_text.html();
 1238+ text = $j.trim( text.substring( 0, text
 1239+ .indexOf( "<span class=\"username\">" ) ) );
 1240+ }
 1241+
 1242+ var template_vars = {
 1243+ media_dir : Reflect.api.server.media_dir,
 1244+ bullet_id : this.id,
 1245+ txt : Reflect.utils.escape( text ),
 1246+ commenter : this.comment.user_short
 1247+ };
 1248+ this.$elem.addClass( 'modify' ).unbind( 'click' )
 1249+ .unbind( 'mouseover' ).unbind( 'mouseout' )
 1250+ .html(
 1251+ $j.jqote( Reflect.templates.new_bullet_dialog, template_vars ) );
 1252+
 1253+ this.elements = {
 1254+ new_bullet_text : this.$elem.find( '.new_bullet_text' ),
 1255+ bullet_text : this.$elem.find( '.bullet_text' ),
 1256+ submit_button : this.$elem.find( '.submit button' )
 1257+ };
 1258+
 1259+ },
 1260+ exit_edit_state : function ( params, canceled ) {
 1261+ if ( canceled && !this.id ) {
 1262+ this._build_prompt();
 1263+ } else {
 1264+ this.options = $j.extend( {}, this.options, params );
 1265+ this.set_attributes();
 1266+ this._build();
 1267+ this.$elem.removeClass( 'modify' );
 1268+ }
 1269+ },
 1270+ enter_highlight_state : function () {
 1271+ var highlight = $j( '<table />' ).addClass( 'new_bullet_wrapper' )
 1272+ .html( $j.jqote( Reflect.templates.bullet_highlight, {
 1273+ media_dir : Reflect.api.server.media_dir
 1274+ } ) );
 1275+
 1276+ this.$elem.append( highlight );
 1277+ this.elements.submit_button = this.$elem.find( '.submit button' );
 1278+ return highlight;
 1279+
 1280+ },
 1281+ exit_highlight_state : function ( canceled ) {
 1282+ if ( canceled && !this.id ) {
 1283+ this._build_prompt();
 1284+ } else {
 1285+ this.$elem.removeClass( 'new_bullet' ).removeClass( 'modify' )
 1286+ .find( '.new_bullet_wrapper' ).remove();
 1287+ this.set_attributes();
 1288+ }
 1289+ this.comment.clear_text();
 1290+ },
 1291+ _add_response : function ( params ) {
 1292+ var response = $j( '<li />' ).response( params );
 1293+ this.elements.response_list.append( response );
 1294+ this.responses.push( response );
 1295+ return $j.data( response[0], 'response' );
 1296+ },
 1297+ add_response : function ( response_info ) {
 1298+ params = {
 1299+ media_dir : Reflect.api.server.media_dir,
 1300+ user : response_info.u,
 1301+ text : response_info.txt,
 1302+ id : response_info.id,
 1303+ rev : response_info.response_rev,
 1304+ sig : response_info.sig,
 1305+ is_prompt : false,
 1306+ bullet : this
 1307+ };
 1308+ return this._add_response( params );
 1309+ },
 1310+ add_response_dialog : function () {
 1311+ var params = {
 1312+ media_dir : Reflect.api.server.media_dir,
 1313+ is_prompt : true,
 1314+ bullet : this
 1315+ };
 1316+ return this._add_response( params );
 1317+ },
 1318+ set_flag : function () {
 1319+
 1320+ }
 1321+
 1322+ },
 1323+
 1324+ Response : {
 1325+ init : function ( options, elem ) {
 1326+ this.options = $j.extend( {}, this.options, options );
 1327+
 1328+ this.elem = elem;
 1329+ this.$elem = $j( elem );
 1330+
 1331+ this.set_attributes();
 1332+ this.elements = {};
 1333+
 1334+ if ( this.options.is_prompt ) {
 1335+ this._build_prompt();
 1336+ } else {
 1337+ this._build();
 1338+ }
 1339+
 1340+ return this;
 1341+
 1342+ },
 1343+ options : {},
 1344+ set_attributes : function () {
 1345+ this.id = parseInt(this.options.id);
 1346+ this.rev = parseInt(this.options.rev);
 1347+ this.bullet = this.options.bullet;
 1348+ this.user = this.options.user;
 1349+ },
 1350+ _build : function () {
 1351+ var template_vars = {
 1352+ text : Reflect.utils.escape( this.options.text ),
 1353+ sig : Reflect.utils.escape( this.options.sig ),
 1354+ user : Reflect.utils.escape( this.options.user ),
 1355+ media_dir : Reflect.api.server.media_dir
 1356+ };
 1357+ this.$elem.addClass( 'response' ).html(
 1358+ $j.jqote( Reflect.templates.new_response, template_vars ) );
 1359+ if ( this.id ) {
 1360+ this.set_id( this.id, this.rev );
 1361+ }
 1362+
 1363+ this.elements = {
 1364+ response_text : this.$elem.find( '.rebutt_txt' )
 1365+ };
 1366+
 1367+ },
 1368+ _build_prompt : function () {
 1369+ var template_vars = {
 1370+ bullet_id : this.bullet.id,
 1371+ text : Reflect.utils.escape( this.options.text ),
 1372+ sig : Reflect.utils.escape( this.options.sig ),
 1373+ user : Reflect.utils.escape( this.options.user ),
 1374+ media_dir : Reflect.api.server.media_dir
 1375+ };
 1376+ this.$elem.addClass( 'response' ).addClass( 'new' ).html(
 1377+ $j.jqote( Reflect.templates.response_dialog, template_vars ) );
 1378+ this.elements = {
 1379+ new_response_text : this.$elem.find( '.new_bullet_text' )
 1380+ };
 1381+
 1382+ },
 1383+ set_id : function ( id, rev ) {
 1384+ this.id = id;
 1385+ this.rev = rev;
 1386+ this.$elem.attr( 'id', 'response-' + this.id );
 1387+ },
 1388+ exit_dialog : function ( params, canceled ) {
 1389+ this.options = $j.extend( {}, this.options, params );
 1390+ if ( !canceled || this.id ) {
 1391+ this._build();
 1392+ this.set_attributes();
 1393+ } else if ( canceled ) {
 1394+ this._build_prompt();
 1395+ }
 1396+ },
 1397+ enter_edit_state : function () {
 1398+ var text = '', modify = this.id;
 1399+
 1400+ if ( modify ) {
 1401+ var text = this.elements.response_text.html();
 1402+ this.options.text = $j.trim( text.substring( 0, text
 1403+ .indexOf( "<span class=\"username\">" ) ) );
 1404+ }
 1405+
 1406+ this._build_prompt();
 1407+
 1408+ this.elements = {
 1409+ new_response_text : this.$elem.find( '.new_bullet_text' ),
 1410+ submit_button : this.$elem.find( '.submit button' )
 1411+ };
 1412+
 1413+ },
 1414+ response_delete : function () {
 1415+ this.options.text = null;
 1416+ this.options.sig = null;
 1417+ this.options.id = null;
 1418+ this.set_attributes();
 1419+ this._build_prompt();
 1420+ }
 1421+ }
 1422+
 1423+ },
 1424+
 1425+ /**
 1426+ * HTML templates so that we don't have to have long, ugly HTML snippets
 1427+ * managed via javascript. Use jquery.jqote2 to implement html templating.
 1428+ * HTML file full of scripts is fetched from server. Each script simply
 1429+ * contains HTML along with some templating methods. These scripts can
 1430+ * then be created as parameterized HTML via jqote2.
 1431+ *
 1432+ * Reflect.templates stores compiled HTML templates at the ready.
 1433+ */
 1434+ templates : {
 1435+ init : function ( templates_from_server ) {
 1436+ $j( 'body' ).append( templates_from_server );
 1437+
 1438+ $j.extend( Reflect.templates, {
 1439+ new_bullet_dialog : $j
 1440+ .jqotec( '#reflect_template_new_bullet_dialog' ),
 1441+ new_response : $j.jqotec( '#reflect_template_new_response' ),
 1442+ new_bullet_prompt : $j
 1443+ .jqotec( '#reflect_template_new_bullet_prompt' ),
 1444+ response_dialog : $j.jqotec( '#reflect_template_response_dialog' ),
 1445+ bullet : $j.jqotec( '#reflect_template_bullet' ),
 1446+ bullet_highlight : $j.jqotec( '#reflect_template_bullet_highlight' )
 1447+ } );
 1448+ }
 1449+ },
 1450+
 1451+ /**
 1452+ * Take the current DOM and wrap Reflect elements where appropriated, guided
 1453+ * by the Reflect.contract.
 1454+ */
 1455+ enforce_contract : function () {
 1456+ $j( Reflect.contract.get_comment_thread() )
 1457+ .wrapInner( '<div id=reflected />' );
 1458+
 1459+ if ( typeof Reflect.contract.user_name_selector == 'function' ) {
 1460+ var user = $j( Reflect.contract.user_name_selector() ).text();
 1461+ } else {
 1462+ var user = $j( Reflect.contract.user_name_selector ).text();
 1463+ }
 1464+
 1465+ if ( user == '' || user == null ) {
 1466+ user = Reflect.api.server.get_current_user();
 1467+ }
 1468+
 1469+ var user_el = '<span id="rf_user_name" style="display:none">' + user + '</span>';
 1470+ $j( '#reflected' ).append( user_el );
 1471+
 1472+ for (i = 0; i < Reflect.contract.components.length; i++) {
 1473+ var component = Reflect.contract.components[i];
 1474+
 1475+ $j( component.comment_identifier )
 1476+ .each( function ( index ) {
 1477+ params = {
 1478+ initializer : component
 1479+ };
 1480+ $j( this ).comment( params );
 1481+ var comment = $j.data( this, 'comment' );
 1482+
 1483+ if ( Reflect.data ) {
 1484+ bullets = [];
 1485+ for ( var j in Reflect.data[comment.id])
 1486+ bullets.push( Reflect.data[comment.id][j] );
 1487+
 1488+ // rank order of bullets in list
 1489+ bullets = bullets.sort( function ( a, b ) {
 1490+ var a_tot = 0.0, b_tot = 0.0;
 1491+ for ( var j in a.highlights)
 1492+ a_tot += parseFloat( a.highlights[j].eid );
 1493+ for ( var j in b.highlights)
 1494+ b_tot += parseFloat( b.highlights[j].eid );
 1495+ a_score = a_tot / a.highlights.length;
 1496+ b_score = b_tot / b.highlights.length;
 1497+ return a_score - b_score;
 1498+ } );
 1499+
 1500+ for ( var j in bullets) {
 1501+
 1502+ var bullet_info = bullets[j],
 1503+ bullet = comment.add_bullet( bullet_info ),
 1504+ responses = bullet_info.responses,
 1505+ has_response = false;
 1506+
 1507+ for ( var k in responses) {
 1508+ has_response = true;
 1509+ break;
 1510+ }
 1511+
 1512+ if ( has_response ) {
 1513+ for ( var k in responses) {
 1514+ var response_obj = bullet
 1515+ .add_response( responses[k] );
 1516+ }
 1517+ } else if ( comment.user == user ) {
 1518+ bullet.add_response_dialog();
 1519+ }
 1520+
 1521+ Reflect.bind.bullet( bullet );
 1522+
 1523+ }
 1524+
 1525+ // segment sentences we can index them during highlighting
 1526+ comment.elements.comment_text.wrap_sentences();
 1527+ comment.$elem.find( '.sentence' )
 1528+ .each( function ( index ) {
 1529+ $j( this ).attr( 'id', 'sentence-' + index )
 1530+ .click( Reflect.handle.sentence_click );
 1531+ } );
 1532+
 1533+ }
 1534+ Reflect.transitions.to_base( comment.id );
 1535+
 1536+ } );
 1537+ }
 1538+ },
 1539+
 1540+ /**
 1541+ * Get Reflect moving.
 1542+ *
 1543+ * Fetches data and templates from the server, enforces the contract.
 1544+ */
 1545+ init : function () {
 1546+ // register the bridges
 1547+ $j.plugin( 'bullet', Reflect.entities.Bullet );
 1548+ $j.plugin( 'comment', Reflect.entities.Comment );
 1549+ $j.plugin( 'response', Reflect.entities.Response );
 1550+ // ////////
 1551+
 1552+ // instantiate the classes that may have been overridden
 1553+ Reflect.contract = new Reflect.Contract( Reflect.config.contract );
 1554+ Reflect.api.server = new Reflect.api.DataInterface( Reflect.config.api );
 1555+ // ////////
 1556+
 1557+ // handle additional refactoring required for Reflect contract
 1558+ Reflect.contract.add_css();
 1559+ Reflect.contract.modifier();
 1560+ // ////////
 1561+
 1562+ // ////////
 1563+ // figure out which comments are present on the page so that we
 1564+ // can ask the server for the respective bullets
 1565+ var loaded_comments = [];
 1566+ for (i = 0; i < Reflect.contract.components.length; i++) {
 1567+ var component = Reflect.contract.components[i];
 1568+ $j( component.comment_identifier ).each( function () {
 1569+ var comment_id = $j( this ).attr( 'id' )
 1570+ .substring( component.comment_offset );
 1571+ loaded_comments.push( comment_id );
 1572+ } );
 1573+ }
 1574+ loaded_comments = JSON.stringify( loaded_comments );
 1575+ // //////////////////
 1576+
 1577+ Reflect.api.server.get_templates(
 1578+ // TODO: fetch data & templates @ the same time
 1579+ function ( data ) {
 1580+ Reflect.templates.init( data );
 1581+
 1582+ Reflect.api.server.get_data( {
 1583+ comments : loaded_comments
 1584+ },
 1585+ function ( data ) {
 1586+ Reflect.data = data;
 1587+ Reflect.enforce_contract();
 1588+
 1589+ if ( Reflect.config.study ) {
 1590+ Reflect.study.load_surveys();
 1591+ }
 1592+
 1593+ } );
 1594+ } );
 1595+ }
 1596+};
 1597+
 1598+$j( document ).ready( function () {
 1599+ Reflect.init();
 1600+} );
Property changes on: trunk/extensions/Reflect/client/js/reflect.js
___________________________________________________________________
Added: svn:eol-style
11601 + native
Index: trunk/extensions/Reflect/client/js/reflect.liquidthreads.js
@@ -0,0 +1,207 @@
 2+/* Copyright (c) 2010 Travis Kriplean (http://www.cs.washington.edu/homes/travis/)
 3+ * Licensed under the MIT License:
 4+ * http://www.opensource.org/licenses/mit-license.php
 5+ *
 6+ *
 7+ * Overrides default Reflect options & classes to support MediaWiki/LiquidThreads.
 8+ *
 9+ */
 10+
 11+
 12+if ( typeof liquidThreads != 'undefined' ) {
 13+ Reflect.config.study = wgReflectStudyEnabled;
 14+
 15+ /* see documentation about components in Reflect.js */
 16+ $j.extend( Reflect.config.contract, {
 17+ components : [ {
 18+ comment_identifier : '.lqt-post-wrapper',
 19+ comment_offset : 8,
 20+ comment_text : '.lqt_post',
 21+ get_commenter_name : function ( comment_id ) {
 22+ var sel = '#comment-' + comment_id
 23+ + ' .lqt-thread-user-signature:first a';
 24+ return $j( sel )
 25+ .text();
 26+ }
 27+ } ]
 28+ } );
 29+
 30+ /* see documentation about Contract in Reflect.js */
 31+ Reflect.Contract = Reflect.Contract.extend( {
 32+ init : function ( config ) {
 33+ this._super( config );
 34+ this.components = config.components;
 35+ this.domain = config.domain;
 36+ },
 37+ user_name_selector : function () {
 38+ if ( $j( '#pt-userpage a' ).length > 0 ) {
 39+ return '#pt-userpage a';
 40+ } else {
 41+ return '#pt-anonuserpage a';
 42+ }
 43+ },
 44+ modifier : function () {
 45+ $j( '.lqt-post-wrapper' ).each( function () {
 46+ $j( this ).attr( 'id', 'comment-'
 47+ + $j( this ).parent()
 48+ .attr( 'id' ).substring( 14 ) );
 49+ } );
 50+ },
 51+ get_comment_thread : function () {
 52+ return $j( '#bodyContent' );
 53+ }
 54+ } );
 55+
 56+ $j.extend( Reflect.config.api, {
 57+ domain : 'liquidthreads',
 58+ server_loc : wgScriptPath + '/api.php',
 59+ media_dir : wgScriptPath + '/extensions/Reflect/client/media/'
 60+ } );
 61+
 62+ /* Interfaces directly with Mediawiki server API.
 63+ *
 64+ * All gets/posts request a token from the server before
 65+ * making the request in order to protect against CSRF attacks.
 66+ * */
 67+ Reflect.api.DataInterface = Reflect.api.DataInterface.extend( {
 68+
 69+ get_templates : function ( callback ) {
 70+ $j.get( wgScriptPath
 71+ + '/extensions/Reflect/client/templates/templates.html',
 72+ callback );
 73+ },
 74+ get_current_user : function () {
 75+ return wgUser;
 76+ },
 77+ is_admin : function () {
 78+ return wgIsAdmin;
 79+ },
 80+ post_bullet : function ( params ) {
 81+ var me = this;
 82+ liquidThreads.getToken( function ( token ) {
 83+ params.params.action = 'reflectaction';
 84+ params.params.format = 'json';
 85+ params.params.reflectaction = 'post_bullet';
 86+ params.params.token = token;
 87+
 88+ $j.ajax( {
 89+ url : me.server_loc,
 90+ type : 'POST',
 91+ data : params.params,
 92+ error : function ( data ) {
 93+ if ( typeof data == "string" ) {
 94+ data = JSON.parse( data );
 95+ }
 96+ params.error( data['reflectaction'] );
 97+ },
 98+ success : function ( data ) {
 99+ if ( typeof data == "string" ) {
 100+ data = JSON.parse( data );
 101+ }
 102+ params.success( data['reflectaction'] );
 103+ }
 104+ } );
 105+ } );
 106+ },
 107+ post_response : function ( params ) {
 108+ var me = this;
 109+ liquidThreads.getToken( function ( token ) {
 110+ params.params.action = 'reflectaction';
 111+ params.params.format = 'json';
 112+ params.params.reflectaction = 'post_response';
 113+ params.params.token = token;
 114+
 115+ $j.ajax( {
 116+ url : me.server_loc,
 117+ type : 'POST',
 118+ data : params.params,
 119+ error : function ( data ) {
 120+ if ( typeof data == "string" ) {
 121+ data = JSON.parse( data );
 122+ }
 123+ params.error( data['reflectaction'] );
 124+ },
 125+ success : function ( data ) {
 126+ if ( typeof data == "string" ) {
 127+ data = JSON.parse( data );
 128+ }
 129+ params.success( data['reflectaction'] );
 130+ }
 131+ } );
 132+ } );
 133+ },
 134+
 135+ get_data : function ( params, callback ) {
 136+ var me = this;
 137+ liquidThreads.getToken( function ( token ) {
 138+ params.action = 'reflectaction';
 139+ params.format = 'json';
 140+ params.reflectaction = 'get_data';
 141+ params.token = token;
 142+
 143+ $j.getJSON( me.server_loc, params, function ( data ) {
 144+ if ( data ) {
 145+ callback( data['reflectaction'] );
 146+ } else {
 147+ callback( data );
 148+ }
 149+ } );
 150+ } );
 151+ },
 152+
 153+ /***************************************************************
 154+ * Research study API
 155+ *
 156+ * These really should go in a separate file
 157+ * like reflect.study.liquidthreads.js. Maybe reflect.study.js?
 158+ */
 159+ post_survey_bullets : function ( params ) {
 160+ var me = this;
 161+ liquidThreads.getToken( function ( token ) {
 162+ params.params.action = 'reflectstudyaction';
 163+ params.params.format = 'json';
 164+ params.params.reflectstudyaction = 'post_survey_bullets';
 165+ params.params.token = token;
 166+
 167+ $j.ajax( {
 168+ url : me.server_loc,
 169+ type : 'POST',
 170+ data : params.params,
 171+ error : function ( data ) {
 172+ if ( typeof data == "string" ) {
 173+ data = JSON.parse( data );
 174+ }
 175+ params.error( data['reflectstudyaction'] );
 176+ },
 177+ success : function ( data ) {
 178+ if ( typeof data == "string" ) {
 179+ data = JSON.parse( data );
 180+ }
 181+ params.success( data['reflectstudyaction'] );
 182+ }
 183+ } );
 184+ } );
 185+
 186+ },
 187+ get_survey_bullets : function ( params, callback ) {
 188+ var me = this;
 189+ liquidThreads.getToken( function ( token ) {
 190+ params.action = 'reflectstudyaction';
 191+ params.format = 'json';
 192+ params.reflectstudyaction = 'get_survey_responses';
 193+ params.token = token;
 194+ $j.getJSON( me.server_loc, params, function ( data ) {
 195+ if ( data ) {
 196+ callback( data['reflectstudyaction'] );
 197+ } else {
 198+ callback( data );
 199+ }
 200+ } );
 201+
 202+ }
 203+
 204+ );
 205+ }
 206+
 207+ } );
 208+}
\ No newline at end of file
Property changes on: trunk/extensions/Reflect/client/js/reflect.liquidthreads.js
___________________________________________________________________
Added: svn:eol-style
1209 + native
Index: trunk/extensions/Reflect/client/js/reflect.study.js
@@ -0,0 +1,236 @@
 2+/* Copyright (c) 2010 Travis Kriplean (http://www.cs.washington.edu/homes/travis/)
 3+ * Licensed under the MIT License:
 4+ * http://www.opensource.org/licenses/mit-license.php
 5+ *
 6+ * DOM manipulations for the Reflect research surveys. Basically drop in
 7+ * a short survey when the user takes specific actions (like adding bullet).
 8+ *
 9+ * See server/api/ApiReflectStudyAction for high level about research study.
 10+ */
 11+
 12+
 13+/////////////////////
 14+//enclosure
 15+if ( typeof Reflect == 'undefined' ) {
 16+ Reflect = {};
 17+ // ///////////////////
 18+}
 19+
 20+var $j = jQuery.noConflict();
 21+
 22+Reflect.study = {
 23+
 24+ load_surveys : function () {
 25+ var bullets = [],
 26+ user = Reflect.utils.get_logged_in_user();
 27+ // in a but not in b
 28+ function relative_complement ( a, b ) {
 29+ return a.filter( function ( elem ) {
 30+ return b.indexOf( elem ) == -1;
 31+ } );
 32+ }
 33+ $j( '.bullet' ).each( function () {
 34+ var bullet = $j( this ).data( 'bullet' );
 35+ if ( bullet.id
 36+ && (bullet.user == user || bullet.comment.user == user) )
 37+ {
 38+ bullets.push( bullet.id );
 39+ }
 40+ } );
 41+ Reflect.api.server.get_survey_bullets( {
 42+ bullets : JSON.stringify( bullets )
 43+ }, function ( data ) {
 44+ // for each candidate bullet NOT in data, lay down
 45+ // appropriate survey
 46+ var needs_surveys = relative_complement( bullets, data );
 47+ for ( var i in needs_surveys) {
 48+ var bullet = $j( '#bullet-' + needs_surveys[i] )
 49+ .data( 'bullet' );
 50+ if ( bullet.comment.user == user
 51+ && bullet.responses.length > 0
 52+ && bullet.responses[0].data( 'response' ).id ) {
 53+ Reflect.study.new_bullet_reaction_survey(
 54+ bullet, bullet.comment, bullet.$elem );
 55+ } else if ( bullet.user == user ) {
 56+ Reflect.study.new_bullet_survey(
 57+ bullet, bullet.comment, bullet.$elem );
 58+ }
 59+ }
 60+
 61+ } );
 62+ },
 63+ _bullet_survey_base : function ( comment, bullet, title, checkbox_name,
 64+ checkboxes, survey_id, element )
 65+ {
 66+ if ( Reflect.data[comment.id][bullet.id]
 67+ && Reflect.data[comment.id][bullet.id].survey_responses ) {
 68+ return;
 69+ }
 70+
 71+ fields = '';
 72+ for ( var i in checkboxes) {
 73+ var box = checkboxes[i];
 74+ if ( box == 'other' ) {
 75+ fields += '<input type="checkbox" name="'
 76+ + checkbox_name + '-' + bullet.id + '" id="other-' + bullet.id
 77+ + '" value="' + i
 78+ + '" class="other survey_check" /><label for="other-' + bullet.id
 79+ + '">other</label> <input type="text" class="other_text" name="other_text" /><br>';
 80+ } else {
 81+ fields += '<input type="checkbox" name="' + checkbox_name + '-'
 82+ + bullet.id + '" id="' + box + '-' + bullet.id
 83+ + '" value="' + i + '" class="survey_check" />'
 84+ + '<label for="' + box + '-' + bullet.id + '">' + box
 85+ + '</label><br>';
 86+ }
 87+ }
 88+
 89+ // TODO: move this to html template
 90+ var prompt = $j( ''
 91+ + '<div class="survey_prompt">'
 92+ + ' <div class="survey_intro">'
 93+ + ' <ul>'
 94+ + ' <li class="survey_label"><span>'
 95+ + title
 96+ + '</span></li>'
 97+ + ' <li class="cancel_survey"><button class="skip"><img title="Skip this survey" src="'
 98+ + Reflect.api.server.media_dir
 99+ + '/cancel_black.png" ></button></li>'
 100+ + ' <li style="clear:both"></li>'
 101+ + ' </ul>'
 102+ + ' </div>'
 103+ + ' <div class="survey_detail">'
 104+ + ' <p class="validateTips">Check all that apply. Your response will not be shown to others.</p>'
 105+ + ' <form>' + ' <fieldset>' + fields + '</fieldset>'
 106+ + '<button class="done" type="button">Done</button>'
 107+ + '<button class="skip" type="button">Skip</button>'
 108+ + ' </form>' + ' </div>' + '</div>' );
 109+
 110+ prompt.find( '.survey_detail' ).hide();
 111+ prompt.find( '.done' ).attr( 'disabled', true );
 112+ prompt.find( 'input' ).click( function () {
 113+ prompt.find( '.done' )
 114+ .attr( 'disabled', prompt.find( 'input:checked' ).length == 0 );
 115+ } );
 116+
 117+ function open () {
 118+ $j( this ).parents( '.survey_prompt' ).find( '.survey_detail' )
 119+ .slideDown();
 120+ $j( this ).unbind( 'click' );
 121+ $j( this ).click( close );
 122+ }
 123+ function close () {
 124+ $j( this ).parents( '.survey_prompt' ).find( '.survey_detail' )
 125+ .slideUp();
 126+ $j( this ).unbind( 'click' );
 127+ $j( this ).click( open );
 128+ }
 129+ prompt.find( '.survey_label' ).click( open );
 130+
 131+ prompt.find( '.done' ).click( function () {
 132+ prompt.find( ':checkbox:checked' ).each( function () {
 133+ var response_id = $j( this ).val();
 134+ if ( $j( this ).attr( 'id' ) == 'other' ) {
 135+ var text = prompt.find( 'input:text' ).val();
 136+ } else {
 137+ var text = '';
 138+ }
 139+
 140+ var params = {
 141+ bullet_id : bullet.id,
 142+ comment_id : comment.id,
 143+ text : text,
 144+ survey_id : survey_id,
 145+ response_id : response_id,
 146+ bullet_rev : bullet.rev
 147+ };
 148+ var vals = {
 149+ params : params,
 150+ success : function ( data ) {
 151+ },
 152+ error : function ( data ) {
 153+ }
 154+ };
 155+
 156+ Reflect.api.server.post_survey_bullets( vals );
 157+
 158+ } );
 159+
 160+ prompt.fadeTo( "slow", 0.01, function () { // fade
 161+ prompt.slideUp( "slow", function () { // slide up
 162+ prompt.remove(); // then remove from the DOM
 163+ } );
 164+ } );
 165+
 166+ } );
 167+ prompt.find( '.skip' ).click( function () {
 168+ var response_id = $j( this ).val();
 169+ if ( $j( this ).attr( 'id' ) == 'other' ) {
 170+ var text = prompt.find( 'input:text' ).val();
 171+ } else {
 172+ var text = '';
 173+ }
 174+
 175+ var params = {
 176+ bullet_id : bullet.id,
 177+ bullet_rev : bullet.rev,
 178+ comment_id : comment.id,
 179+ text : text,
 180+ survey_id : survey_id,
 181+ response_id : -1
 182+ };
 183+ var vals = {
 184+ params : params,
 185+ success : function ( data ) {
 186+ },
 187+ error : function ( data ) {
 188+ }
 189+ };
 190+
 191+ Reflect.api.server.post_survey_bullets( vals );
 192+
 193+ prompt.fadeTo( "slow", 0.01, function () { // fade
 194+ prompt.slideUp( "slow", function () { // slide up
 195+ prompt.remove(); // then remove from the DOM
 196+ } );
 197+ } );
 198+ } );
 199+ prompt.hide();
 200+ element.append( prompt );
 201+ prompt.fadeIn( 'slow' );
 202+
 203+ },
 204+ new_bullet_survey : function ( bullet, comment, element ) {
 205+ var commenter = comment.user_short,
 206+ checkboxes = [
 207+ 'make sure other people will see the point',
 208+ 'teach ' + comment.user_short + ' something',
 209+ 'show other readers that you understand',
 210+ 'show ' + comment.user_short + ' that you understand',
 211+ 'help you understand the comment better', 'other' ],
 212+ title = 'Why did you add this point?',
 213+ checkbox_name = 'point_reaction',
 214+ survey_id = 1;
 215+
 216+ Reflect.study._bullet_survey_base(
 217+ comment, bullet, title, checkbox_name,
 218+ checkboxes, survey_id, element );
 219+ },
 220+
 221+ new_bullet_reaction_survey : function ( bullet, comment, element ) {
 222+
 223+ var checkboxes = [ 'I guess someone heard what I said',
 224+ 'I need to, or don\'t need to, clarify',
 225+ 'I had not thought of phrasing my point that way',
 226+ 'thanks, ' + bullet.user,
 227+ 'Other people will now find this point more easily',
 228+ 'Other people will understand my point better now', 'other' ],
 229+ title = 'What do you think of this summary?',
 230+ checkbox_name = 'adding_point',
 231+ survey_id = 2;
 232+
 233+ Reflect.study._bullet_survey_base(
 234+ comment, bullet, title, checkbox_name,
 235+ checkboxes, survey_id, element );
 236+ }
 237+};
Property changes on: trunk/extensions/Reflect/client/js/reflect.study.js
___________________________________________________________________
Added: svn:eol-style
1238 + native
Index: trunk/extensions/Reflect/client/js/third_party/jquery.jqote2.min.js
@@ -0,0 +1,18 @@
 2+/*
 3+* jQote2 - client-side Javascript templating engine
 4+* Copyright (C) 2010, aefxx
 5+* http://aefxx.com/
 6+*
 7+* Dual licensed under the WTFPL v2 or MIT (X11) licenses
 8+* WTFPL v2 Copyright (C) 2004, Sam Hocevar
 9+*
 10+* Date: Sat, Jun 29th, 2010
 11+* Version: 0.9.5
 12+*/
 13+(function($){var _=false,E1="UndefinedTemplateError",E2="TemplateCompilationError",E3="TemplateExecutionError",A="[object Array]",S="[object String]",F="[object Function]",n=1,c="%",q=/^[^<]*(<[\w\W]+>)[^>]*$/,ts=Object.prototype.toString;function r(e,x){throw $.extend(e,x),e;}function dns(f){var a=[];if(ts.call(f)!==A)return _;for(var i=0,l=f.length;i<l;i++)a[i]=f[i].id;return a.length?a.sort().join(".").replace(/(\b\d+\b)\.(?:\1(\.|$))+/g,"$1$2"):_}function l(s,t){var f,g=[],t=t||c,x=ts.call(s);
 14+if(x===F)return s.jqote_id?[s]:_;if(x!==A)return[$.jqotec(s,t)];return g.length?g:_}$.fn.extend({jqote:function(x,y){var x=ts.call(x)===A?x:[x],d="";this.each(function(i){var f=$.jqotec(this,y);for(var j=0;j<x.length;j++)d+=f.call(x[j],i,j,x,f)});return d}});$.each({app:"append",pre:"prepend",sub:"html"},function(x,y){$.fn["jqote"+x]=function(e,d,t){var p,r,s=$.jqote(e,d,t),$$=!q.test(s)?function(s){return $(document.createTextNode(s))}:$;if(!!(p=dns(l(e))))r=new RegExp("(^|\\.)"+p.split(".").join("\\.(.*)?")+
 15+"(\\.|$)");return this.each(function(){var z=$$(s);$(this)[y](z);(z[0].nodeType===3?$(this):z).trigger("jqote."+x,[z,r])})}});$.extend({jqote:function(e,d,t){var s="",t=t||c,f=l(e);if(f===_)r(new Error("Empty or undefined template passed to $.jqote"),{type:E1});d=ts.call(d)!==A?[d]:d;for(var i=0,m=f.length;i<m;i++)for(var j=0;j<d.length;j++)s+=f[i].call(d[j],i,j,d,f[i]);return s},jqotec:function(x,t){var h,e,y,t=t||c,z=ts.call(x);if(z===S&&q.test(x)){e=y=x;if(h=$.jqotecache[x])return h}else{e=z===
 16+S||x.nodeType?$(x):x instanceof jQuery?x:null;if(!e[0]||!(y=e[0].innerHTML))r(new Error("Empty or undefined template passed to $.jqotec"),{type:E1});if(h=$.jqotecache[$.data(e[0],"jqote_id")])return h}var s="",i,a=y.replace(/\s*<!\[CDATA\[\s*|\s*\]\]>\s*|[\r\n\t]/g,"").split("<"+t).join(t+">\u001b").split(t+">");for(var m=0,k=a.length;m<k;m++)s+=a[m].charAt(0)!=="\u001b"?"out+='"+a[m].replace(/([^\\])?(["'])/g,"$1\\$2")+"'":a[m].charAt(1)==="="?";out+=("+a[m].substr(2)+");":";"+a[m].substr(1);s="try{"+
 17+('var out="";'+s+";return out;").split("out+='';").join("").split('var out="";out+=').join("var out=")+'}catch(e){e.type="'+E3+'";e.args=arguments;e.template=arguments.callee.toString();throw e;}';try{var f=new Function("i, j, data, fn",s)}catch(e){r(e,{type:E2})}i=e instanceof jQuery?$.data(e[0],"jqote_id",n):e;return $.jqotecache[i]=(f.jqote_id=n++,f)},jqotefn:function(e){var t=ts.call(e),i=t===S&&q.test(e)?e:$.data($(e)[0],"jqote_id");return $.jqotecache[i]||_},jqotetag:function(s){c=s},jqotecache:{}});
 18+$.event.special.jqote={add:function(o){var n,h=o.handler,d=!o.data?[]:ts.call(o.data)!==A?[o.data]:o.data;if(!d.length||!(n=dns(l(d))))return}}})(jQuery);
 19+
Property changes on: trunk/extensions/Reflect/client/js/third_party/jquery.jqote2.min.js
___________________________________________________________________
Added: svn:eol-style
120 + native
Index: trunk/extensions/Reflect/client/js/third_party/jquery.highlight.js
@@ -0,0 +1,75 @@
 2+/*
 3+ * jQuery Highlight plugin
 4+ *
 5+ * Modified version of Bartek Szopka's jQuery Highlight (http://bartaz.github.com/sandbox.js/jquery.highlight.html)
 6+ * Copyright (c) 2009 Bartek Szopka
 7+ *
 8+ * Licensed under MIT license.
 9+ *
 10+ */
 11+
 12+RegExp.escape = function(str){
 13+ var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
 14+ return str.replace(specials, "\\$&");
 15+};
 16+
 17+jQuery.extend({
 18+ _wrap_sentences: function (node, re, nodeName, className) {
 19+
 20+ if (node.nodeType === 3) {
 21+ var match = node.data.match(re);
 22+ if (match) {
 23+ var wordNode = node.splitText(match.index);
 24+ wordNode.splitText(match[0].length);
 25+
 26+ }else if(jQuery.trim(node.nodeValue).length == 0){
 27+ return 0;
 28+ }else{
 29+ var wordNode = node.splitText(0);
 30+ //wordNode.splitText(wordNode.length);
 31+ }
 32+
 33+ var highlight = document.createElement(nodeName || 'span');
 34+ highlight.className = className || 'highlight';
 35+
 36+ var wordClone = wordNode.cloneNode(true);
 37+ highlight.appendChild(wordClone);
 38+ wordNode.parentNode.replaceChild(highlight, wordNode);
 39+
 40+ return 1; //skip added node in parent
 41+
 42+ } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
 43+ !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
 44+ !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
 45+ for (var i = 0; i < node.childNodes.length; i++) {
 46+ i += jQuery._wrap_sentences(node.childNodes[i], re, nodeName, className);
 47+ }
 48+ }
 49+ return 0;
 50+
 51+ }
 52+});
 53+
 54+jQuery.fn.wrap_sentences = function (words, options) {
 55+ var settings = { className: 'sentence', element: 'a',
 56+ caseSensitive: false, wordsOnly: false };
 57+ jQuery.extend(settings, options);
 58+
 59+ //var pattern = "(\S.+?[.!?])(?=\s+|$)";
 60+ var pattern = "[^\.\?!]+[\.\?!]";
 61+
 62+ var re = new RegExp(pattern);
 63+ re.escape;
 64+ return jQuery._wrap_sentences(this[0], re, settings.element, settings.className);
 65+};
 66+
 67+jQuery.fn.de_sentence = function (options) {
 68+ var settings = { className: 'sentence', element: 'a' };
 69+ jQuery.extend(settings, options);
 70+
 71+ return this.find(settings.element + "." + settings.className).each(function () {
 72+ var parent = this.parentNode;
 73+ parent.replaceChild(this.firstChild, this);
 74+ parent.normalize();
 75+ }).end();
 76+};
\ No newline at end of file
Property changes on: trunk/extensions/Reflect/client/js/third_party/jquery.highlight.js
___________________________________________________________________
Added: svn:eol-style
177 + native
Index: trunk/extensions/Reflect/client/js/third_party/jquery.pulse.js
@@ -0,0 +1,86 @@
 2+/**
 3+* Pulse plugin for jQuery
 4+* ---
 5+* @author James Padolsey (http://james.padolsey.com)
 6+* @version 0.1
 7+* @updated 16-DEC-09
 8+* ---
 9+* Note: In order to animate color properties, you need
 10+* the color plugin from here: http://plugins.jquery.com/project/color
 11+* ---
 12+* @info http://james.padolsey.com/javascript/simple-pulse-plugin-for-jquery/
 13+*
 14+* * Copyright (c) 2010 James Padolsey
 15+* -------------------------------------------------------
 16+* Dual licensed under the MIT and GPL licenses.
 17+* - http://www.opensource.org/licenses/mit-license.php
 18+* - http://www.gnu.org/copyleft/gpl.html
 19+*/
 20+
 21+jQuery.fn.pulse = function( prop, speed, times, easing, callback ) {
 22+
 23+ if ( isNaN(times) ) {
 24+ callback = easing;
 25+ easing = times;
 26+ times = 1;
 27+ }
 28+
 29+ var optall = jQuery.speed(speed, easing, callback),
 30+ queue = optall.queue !== false,
 31+ largest = 0;
 32+
 33+ for (var p in prop) {
 34+ largest = Math.max(prop[p].length, largest);
 35+ }
 36+
 37+ optall.times = optall.times || times;
 38+
 39+ return this[queue?'queue':'each'](function(){
 40+
 41+ var counts = {},
 42+ opt = jQuery.extend({}, optall),
 43+ self = jQuery(this);
 44+
 45+ pulse();
 46+
 47+ function pulse() {
 48+
 49+ var propsSingle = {},
 50+ doAnimate = false;
 51+
 52+ for (var p in prop) {
 53+
 54+ // Make sure counter is setup for current prop
 55+ counts[p] = counts[p] || {runs:0,cur:-1};
 56+
 57+ // Set "cur" to reflect new position in pulse array
 58+ if ( counts[p].cur < prop[p].length - 1 ) {
 59+ ++counts[p].cur;
 60+ } else {
 61+ // Reset to beginning of pulse array
 62+ counts[p].cur = 0;
 63+ ++counts[p].runs;
 64+ }
 65+
 66+ if ( prop[p].length === largest ) {
 67+ doAnimate = opt.times > counts[p].runs;
 68+ }
 69+
 70+ propsSingle[p] = prop[p][counts[p].cur];
 71+
 72+ }
 73+
 74+ opt.complete = pulse;
 75+ opt.queue = false;
 76+
 77+ if (doAnimate) {
 78+ self.animate(propsSingle, opt);
 79+ } else {
 80+ optall.complete.call(self[0]);
 81+ }
 82+
 83+ }
 84+
 85+ });
 86+
 87+};
\ No newline at end of file
Property changes on: trunk/extensions/Reflect/client/js/third_party/jquery.pulse.js
___________________________________________________________________
Added: svn:eol-style
188 + native
Index: trunk/extensions/Reflect/client/js/third_party/jquery.noblecount.min.js
@@ -0,0 +1,3 @@
 2+/* jQuery.NobleCount v 1.0 http://tpgblog.com/noblecount/
 3+compiled by http://yui.2clics.net/ */
 4+(function(c){c.fn.NobleCount=function(i,h){var j;var g=false;if(typeof i=="string"){j=c.extend({},c.fn.NobleCount.settings,h);if(typeof h!="undefined"){g=((typeof h.max_chars=="number")?true:false)}return this.each(function(){var k=c(this);f(k,i,j,g)})}return this};c.fn.NobleCount.settings={on_negative:null,on_positive:null,on_update:null,max_chars:140,block_negative:false,cloak:false,in_dom:false};function f(g,m,n,h){var l=n.max_chars;var j=c(m);if(!h){var k=j.text();var i=(/^[1-9]\d*$/).test(k);if(i){l=k}}b(g,j,n,l,true);c(g).keydown(function(o){b(g,j,n,l,false);if(a(o,g,n,l)==false){return false}});c(g).keyup(function(o){b(g,j,n,l,false);if(a(o,g,n,l)==false){return false}})}function a(k,g,l,j){if(l.block_negative){var h=k.which;var i;if(typeof document.selection!="undefined"){i=(document.selection.createRange().text.length>0)}else{i=(g[0].selectionStart!=g[0].selectionEnd)}if((!((e(g,j)<1)&&(h>47||h==32||h==0||h==13)&&!k.ctrlKey&&!k.altKey&&!i))==false){return false}}return true}function e(g,h){return h-(c(g).val()).length}function b(g,i,l,j,h){var k=e(g,j);if(k<0){d(l.on_negative,l.on_positive,g,i,l,k)}else{d(l.on_positive,l.on_negative,g,i,l,k)}if(l.cloak){if(l.in_dom){i.attr("data-noblecount",k)}}else{i.text(k)}if(!h&&jQuery.isFunction(l.on_update)){l.on_update(g,i,l,k)}}function d(i,g,h,j,l,k){if(i!=null){if(typeof i=="string"){j.addClass(i)}else{if(jQuery.isFunction(i)){i(h,j,l,k)}}}if(g!=null){if(typeof g=="string"){j.removeClass(g)}}}})(jQuery);
\ No newline at end of file
Property changes on: trunk/extensions/Reflect/client/js/third_party/jquery.noblecount.min.js
___________________________________________________________________
Added: svn:eol-style
15 + native
Index: trunk/extensions/Reflect/client/js/third_party/inheritance.js
@@ -0,0 +1,106 @@
 2+try {
 3+ GM_log('inheritance');
 4+}catch(err){
 5+
 6+}
 7+
 8+/* Simple JavaScript Inheritance
 9+ * By John Resig http://ejohn.org/
 10+ * MIT Licensed.
 11+ */
 12+// Inspired by base2 and Prototype
 13+(function(){
 14+ var initializing = false;
 15+ var fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
 16+
 17+ // The base Class implementation (does nothing)
 18+ this.Class = function(){};
 19+
 20+ // Create a new Class that inherits from this class
 21+ Class.extend = function(prop) {
 22+ var _super = this.prototype;
 23+
 24+ // Instantiate a base class (but only create the instance,
 25+ // don't run the init constructor)
 26+ initializing = true;
 27+ var prototype = new this();
 28+ initializing = false;
 29+
 30+ // Copy the properties over onto the new prototype
 31+ for (var name in prop) {
 32+ // Check if we're overwriting an existing function
 33+ prototype[name] = typeof prop[name] == "function" &&
 34+ typeof _super[name] == "function" && fnTest.test(prop[name]) ?
 35+ (function(name, fn){
 36+ return function() {
 37+ var tmp = this._super;
 38+
 39+ // Add a new ._super() method that is the same method
 40+ // but on the super-class
 41+ this._super = _super[name];
 42+
 43+ // The method only need to be bound temporarily, so we
 44+ // remove it when we're done executing
 45+ var ret = fn.apply(this, arguments);
 46+ this._super = tmp;
 47+
 48+ return ret;
 49+ };
 50+ })(name, prop[name]) :
 51+ prop[name];
 52+ }
 53+
 54+ // The dummy class constructor
 55+ function Class() {
 56+ // All construction is actually done in the init method
 57+ if ( !initializing && this.init )
 58+ this.init.apply(this, arguments);
 59+ }
 60+
 61+ // Populate our constructed prototype object
 62+ Class.prototype = prototype;
 63+
 64+ // Enforce the constructor to be what we expect
 65+ Class.constructor = Class;
 66+
 67+ // And make this class extendable
 68+ Class.extend = arguments.callee;
 69+
 70+ return Class;
 71+ };
 72+})();
 73+
 74+/********
 75+ *
 76+ * The following code comes from Alex Sexton at http://alexsexton.com/?p=51.
 77+ * The code appears to be unlicensed.
 78+ *
 79+ */
 80+
 81+//Make sure Object.create is available in the browser (for our prototypal inheritance)
 82+//Courtesy of Papa Crockford
 83+if (typeof Object.create !== 'function') {
 84+ Object.create = function (o) {
 85+ function F() {}
 86+ F.prototype = o;
 87+ return new F();
 88+ };
 89+}
 90+(function($){
 91+ $.plugin = function(name, object) {
 92+ $.fn[name] = function(options) {
 93+ var args = Array.prototype.slice.call(arguments, 1);
 94+ return this.each(function() {
 95+ var instance = $.data(this, name);
 96+ if (instance) {
 97+ instance[options].apply(instance, args);
 98+ } else {
 99+ instance = $.data(this, name, Object.create(object).init(options, this));
 100+ }
 101+ });
 102+ };
 103+ };
 104+
 105+})(jQuery);
 106+
 107+/************ END ALEX'S CODE *************/
Property changes on: trunk/extensions/Reflect/client/js/third_party/inheritance.js
___________________________________________________________________
Added: svn:eol-style
1108 + native
Index: trunk/extensions/Reflect/client/js/third_party/json2.js
@@ -0,0 +1,24 @@
 2+/* json2.js
 3+ * 2008-01-17
 4+ * Public Domain
 5+ * No warranty expressed or implied. Use at your own risk.
 6+ * See http://www.JSON.org/js.html
 7+*/
 8+if(!this.JSON){JSON=function(){function f(n){return n<10?'0'+n:n;}
 9+Date.prototype.toJSON=function(){return this.getUTCFullYear()+'-'+
 10+f(this.getUTCMonth()+1)+'-'+
 11+f(this.getUTCDate())+'T'+
 12+f(this.getUTCHours())+':'+
 13+f(this.getUTCMinutes())+':'+
 14+f(this.getUTCSeconds())+'Z';};var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};function stringify(value,whitelist){var a,i,k,l,r=/["\\\x00-\x1f\x7f-\x9f]/g,v;switch(typeof value){case'string':return r.test(value)?'"'+value.replace(r,function(a){var c=m[a];if(c){return c;}
 15+c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+
 16+(c%16).toString(16);})+'"':'"'+value+'"';case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
 17+if(typeof value.toJSON==='function'){return stringify(value.toJSON());}
 18+a=[];if(typeof value.length==='number'&&!(value.propertyIsEnumerable('length'))){l=value.length;for(i=0;i<l;i+=1){a.push(stringify(value[i],whitelist)||'null');}
 19+return'['+a.join(',')+']';}
 20+if(whitelist){l=whitelist.length;for(i=0;i<l;i+=1){k=whitelist[i];if(typeof k==='string'){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+':'+v);}}}}else{for(k in value){if(typeof k==='string'){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+':'+v);}}}}
 21+return'{'+a.join(',')+'}';}}
 22+return{stringify:stringify,parse:function(text,filter){var j;function walk(k,v){var i,n;if(v&&typeof v==='object'){for(i in v){if(Object.prototype.hasOwnProperty.apply(v,[i])){n=walk(i,v[i]);if(n!==undefined){v[i]=n;}}}}
 23+return filter(k,v);}
 24+if(/^[\],:{}\s]*$/.test(text.replace(/\\./g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof filter==='function'?walk('',j):j;}
 25+throw new SyntaxError('parseJSON');}};}();}
\ No newline at end of file
Property changes on: trunk/extensions/Reflect/client/js/third_party/json2.js
___________________________________________________________________
Added: svn:eol-style
126 + native
Index: trunk/extensions/Reflect/client/js/third_party/jquery.color.js
@@ -0,0 +1,126 @@
 2+/*
 3+ * jQuery Color Animations
 4+ * Copyright 2007 John Resig
 5+ * Released under the MIT and GPL licenses.
 6+ */
 7+
 8+(function(jQuery){
 9+
 10+ // We override the animation for all of these color styles
 11+ jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
 12+ jQuery.fx.step[attr] = function(fx){
 13+ if ( fx.state == 0 ) {
 14+ fx.start = getColor( fx.elem, attr );
 15+ fx.end = getRGB( fx.end );
 16+ }
 17+
 18+ fx.elem.style[attr] = "rgb(" + [
 19+ Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0),
 20+ Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0),
 21+ Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0)
 22+ ].join(",") + ")";
 23+ }
 24+ });
 25+
 26+ // Color Conversion functions from highlightFade
 27+ // By Blair Mitchelmore
 28+ // http://jquery.offput.ca/highlightFade/
 29+
 30+ // Parse strings looking for color tuples [255,255,255]
 31+ function getRGB(color) {
 32+ var result;
 33+
 34+ // Check if we're already dealing with an array of colors
 35+ if ( color && color.constructor == Array && color.length == 3 )
 36+ return color;
 37+
 38+ // Look for rgb(num,num,num)
 39+ if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
 40+ return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];
 41+
 42+ // Look for rgba(num,num,num,num)
 43+ if (result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\,\s*([0-9]{1,3})\s*\)/.exec(color))
 44+ return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];
 45+
 46+ // Look for rgb(num%,num%,num%)
 47+ if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
 48+ return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
 49+
 50+ // Look for #a0b1c2
 51+ if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
 52+ return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
 53+
 54+ // Look for #fff
 55+ if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
 56+ return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
 57+
 58+ // Otherwise, we're most likely dealing with a named color
 59+ return colors[jQuery.trim(color).toLowerCase()];
 60+ }
 61+
 62+ function getColor(elem, attr) {
 63+ var color;
 64+
 65+ do {
 66+ color = jQuery.curCSS(elem, attr);
 67+ // Keep going until we find an element that has color, or we hit the body
 68+ if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") )
 69+ break;
 70+
 71+ attr = "backgroundColor";
 72+ } while ( elem = elem.parentNode );
 73+
 74+ return getRGB(color);
 75+ };
 76+
 77+ // Some named colors to work with
 78+ // From Interface by Stefan Petre
 79+ // http://interface.eyecon.ro/
 80+
 81+ var colors = {
 82+ aqua:[0,255,255],
 83+ azure:[240,255,255],
 84+ beige:[245,245,220],
 85+ black:[0,0,0],
 86+ blue:[0,0,255],
 87+ brown:[165,42,42],
 88+ cyan:[0,255,255],
 89+ darkblue:[0,0,139],
 90+ darkcyan:[0,139,139],
 91+ darkgrey:[169,169,169],
 92+ darkgreen:[0,100,0],
 93+ darkkhaki:[189,183,107],
 94+ darkmagenta:[139,0,139],
 95+ darkolivegreen:[85,107,47],
 96+ darkorange:[255,140,0],
 97+ darkorchid:[153,50,204],
 98+ darkred:[139,0,0],
 99+ darksalmon:[233,150,122],
 100+ darkviolet:[148,0,211],
 101+ fuchsia:[255,0,255],
 102+ gold:[255,215,0],
 103+ green:[0,128,0],
 104+ indigo:[75,0,130],
 105+ khaki:[240,230,140],
 106+ lightblue:[173,216,230],
 107+ lightcyan:[224,255,255],
 108+ lightgreen:[144,238,144],
 109+ lightgrey:[211,211,211],
 110+ lightpink:[255,182,193],
 111+ lightyellow:[255,255,224],
 112+ lime:[0,255,0],
 113+ magenta:[255,0,255],
 114+ maroon:[128,0,0],
 115+ navy:[0,0,128],
 116+ olive:[128,128,0],
 117+ orange:[255,165,0],
 118+ pink:[255,192,203],
 119+ purple:[128,0,128],
 120+ violet:[128,0,128],
 121+ red:[255,0,0],
 122+ silver:[192,192,192],
 123+ white:[255,255,255],
 124+ yellow:[255,255,0]
 125+ };
 126+
 127+})(jQuery);
Property changes on: trunk/extensions/Reflect/client/js/third_party/jquery.color.js
___________________________________________________________________
Added: svn:eol-style
1128 + native
Index: trunk/extensions/Reflect/client/js/third_party/jquery-1.4.2.js
@@ -0,0 +1,6250 @@
 2+/*!
 3+ * jQuery JavaScript Library v1.4.2
 4+ * http://jquery.com/
 5+ *
 6+ * Copyright 2010, John Resig
 7+ * Dual licensed under the MIT or GPL Version 2 licenses.
 8+ * http://jquery.org/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: Sat Feb 13 22:33:48 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+ // The body element only exists once, optimize finding it
 92+ if ( selector === "body" && !context ) {
 93+ this.context = document;
 94+ this[0] = document.body;
 95+ this.selector = "body";
 96+ this.length = 1;
 97+ return this;
 98+ }
 99+
 100+ // Handle HTML strings
 101+ if ( typeof selector === "string" ) {
 102+ // Are we dealing with HTML string or an ID?
 103+ match = quickExpr.exec( selector );
 104+
 105+ // Verify a match, and that no context was specified for #id
 106+ if ( match && (match[1] || !context) ) {
 107+
 108+ // HANDLE: $(html) -> $(array)
 109+ if ( match[1] ) {
 110+ doc = (context ? context.ownerDocument || context : document);
 111+
 112+ // If a single string is passed in and it's a single tag
 113+ // just do a createElement and skip the rest
 114+ ret = rsingleTag.exec( selector );
 115+
 116+ if ( ret ) {
 117+ if ( jQuery.isPlainObject( context ) ) {
 118+ selector = [ document.createElement( ret[1] ) ];
 119+ jQuery.fn.attr.call( selector, context, true );
 120+
 121+ } else {
 122+ selector = [ doc.createElement( ret[1] ) ];
 123+ }
 124+
 125+ } else {
 126+ ret = buildFragment( [ match[1] ], [ doc ] );
 127+ selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;
 128+ }
 129+
 130+ return jQuery.merge( this, selector );
 131+
 132+ // HANDLE: $("#id")
 133+ } else {
 134+ elem = document.getElementById( match[2] );
 135+
 136+ if ( elem ) {
 137+ // Handle the case where IE and Opera return items
 138+ // by name instead of ID
 139+ if ( elem.id !== match[2] ) {
 140+ return rootjQuery.find( selector );
 141+ }
 142+
 143+ // Otherwise, we inject the element directly into the jQuery object
 144+ this.length = 1;
 145+ this[0] = elem;
 146+ }
 147+
 148+ this.context = document;
 149+ this.selector = selector;
 150+ return this;
 151+ }
 152+
 153+ // HANDLE: $("TAG")
 154+ } else if ( !context && /^\w+$/.test( selector ) ) {
 155+ this.selector = selector;
 156+ this.context = document;
 157+ selector = document.getElementsByTagName( selector );
 158+ return jQuery.merge( this, selector );
 159+
 160+ // HANDLE: $(expr, $(...))
 161+ } else if ( !context || context.jquery ) {
 162+ return (context || rootjQuery).find( selector );
 163+
 164+ // HANDLE: $(expr, context)
 165+ // (which is just equivalent to: $(context).find(expr)
 166+ } else {
 167+ return jQuery( context ).find( selector );
 168+ }
 169+
 170+ // HANDLE: $(function)
 171+ // Shortcut for document ready
 172+ } else if ( jQuery.isFunction( selector ) ) {
 173+ return rootjQuery.ready( selector );
 174+ }
 175+
 176+ if (selector.selector !== undefined) {
 177+ this.selector = selector.selector;
 178+ this.context = selector.context;
 179+ }
 180+
 181+ return jQuery.makeArray( selector, this );
 182+ },
 183+
 184+ // Start with an empty selector
 185+ selector: "",
 186+
 187+ // The current version of jQuery being used
 188+ jquery: "1.4.2",
 189+
 190+ // The default length of a jQuery object is 0
 191+ length: 0,
 192+
 193+ // The number of elements contained in the matched element set
 194+ size: function() {
 195+ return this.length;
 196+ },
 197+
 198+ toArray: function() {
 199+ return slice.call( this, 0 );
 200+ },
 201+
 202+ // Get the Nth element in the matched element set OR
 203+ // Get the whole matched element set as a clean array
 204+ get: function( num ) {
 205+ return num == null ?
 206+
 207+ // Return a 'clean' array
 208+ this.toArray() :
 209+
 210+ // Return just the object
 211+ ( num < 0 ? this.slice(num)[ 0 ] : this[ num ] );
 212+ },
 213+
 214+ // Take an array of elements and push it onto the stack
 215+ // (returning the new matched element set)
 216+ pushStack: function( elems, name, selector ) {
 217+ // Build a new jQuery matched element set
 218+ var ret = jQuery();
 219+
 220+ if ( jQuery.isArray( elems ) ) {
 221+ push.apply( ret, elems );
 222+
 223+ } else {
 224+ jQuery.merge( ret, elems );
 225+ }
 226+
 227+ // Add the old object onto the stack (as a reference)
 228+ ret.prevObject = this;
 229+
 230+ ret.context = this.context;
 231+
 232+ if ( name === "find" ) {
 233+ ret.selector = this.selector + (this.selector ? " " : "") + selector;
 234+ } else if ( name ) {
 235+ ret.selector = this.selector + "." + name + "(" + selector + ")";
 236+ }
 237+
 238+ // Return the newly-formed element set
 239+ return ret;
 240+ },
 241+
 242+ // Execute a callback for every element in the matched set.
 243+ // (You can seed the arguments with an array of args, but this is
 244+ // only used internally.)
 245+ each: function( callback, args ) {
 246+ return jQuery.each( this, callback, args );
 247+ },
 248+
 249+ ready: function( fn ) {
 250+ // Attach the listeners
 251+ jQuery.bindReady();
 252+
 253+ // If the DOM is already ready
 254+ if ( jQuery.isReady ) {
 255+ // Execute the function immediately
 256+ fn.call( document, jQuery );
 257+
 258+ // Otherwise, remember the function for later
 259+ } else if ( readyList ) {
 260+ // Add the function to the wait list
 261+ readyList.push( fn );
 262+ }
 263+
 264+ return this;
 265+ },
 266+
 267+ eq: function( i ) {
 268+ return i === -1 ?
 269+ this.slice( i ) :
 270+ this.slice( i, +i + 1 );
 271+ },
 272+
 273+ first: function() {
 274+ return this.eq( 0 );
 275+ },
 276+
 277+ last: function() {
 278+ return this.eq( -1 );
 279+ },
 280+
 281+ slice: function() {
 282+ return this.pushStack( slice.apply( this, arguments ),
 283+ "slice", slice.call(arguments).join(",") );
 284+ },
 285+
 286+ map: function( callback ) {
 287+ return this.pushStack( jQuery.map(this, function( elem, i ) {
 288+ return callback.call( elem, i, elem );
 289+ }));
 290+ },
 291+
 292+ end: function() {
 293+ return this.prevObject || jQuery(null);
 294+ },
 295+
 296+ // For internal use only.
 297+ // Behaves like an Array's method, not like a jQuery method.
 298+ push: push,
 299+ sort: [].sort,
 300+ splice: [].splice
 301+};
 302+
 303+// Give the init function the jQuery prototype for later instantiation
 304+jQuery.fn.init.prototype = jQuery.fn;
 305+
 306+jQuery.extend = jQuery.fn.extend = function() {
 307+ // copy reference to target object
 308+ var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;
 309+
 310+ // Handle a deep copy situation
 311+ if ( typeof target === "boolean" ) {
 312+ deep = target;
 313+ target = arguments[1] || {};
 314+ // skip the boolean and the target
 315+ i = 2;
 316+ }
 317+
 318+ // Handle case when target is a string or something (possible in deep copy)
 319+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
 320+ target = {};
 321+ }
 322+
 323+ // extend jQuery itself if only one argument is passed
 324+ if ( length === i ) {
 325+ target = this;
 326+ --i;
 327+ }
 328+
 329+ for ( ; i < length; i++ ) {
 330+ // Only deal with non-null/undefined values
 331+ if ( (options = arguments[ i ]) != null ) {
 332+ // Extend the base object
 333+ for ( name in options ) {
 334+ src = target[ name ];
 335+ copy = options[ name ];
 336+
 337+ // Prevent never-ending loop
 338+ if ( target === copy ) {
 339+ continue;
 340+ }
 341+
 342+ // Recurse if we're merging object literal values or arrays
 343+ if ( deep && copy && ( jQuery.isPlainObject(copy) || jQuery.isArray(copy) ) ) {
 344+ var clone = src && ( jQuery.isPlainObject(src) || jQuery.isArray(src) ) ? src
 345+ : jQuery.isArray(copy) ? [] : {};
 346+
 347+ // Never move original objects, clone them
 348+ target[ name ] = jQuery.extend( deep, clone, copy );
 349+
 350+ // Don't bring in undefined values
 351+ } else if ( copy !== undefined ) {
 352+ target[ name ] = copy;
 353+ }
 354+ }
 355+ }
 356+ }
 357+
 358+ // Return the modified object
 359+ return target;
 360+};
 361+
 362+jQuery.extend({
 363+ noConflict: function( deep ) {
 364+ window.$ = _$;
 365+
 366+ if ( deep ) {
 367+ window.jQuery = _jQuery;
 368+ }
 369+
 370+ return jQuery;
 371+ },
 372+
 373+ // Is the DOM ready to be used? Set to true once it occurs.
 374+ isReady: false,
 375+
 376+ // Handle when the DOM is ready
 377+ ready: function() {
 378+ // Make sure that the DOM is not already loaded
 379+ if ( !jQuery.isReady ) {
 380+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
 381+ if ( !document.body ) {
 382+ return setTimeout( jQuery.ready, 13 );
 383+ }
 384+
 385+ // Remember that the DOM is ready
 386+ jQuery.isReady = true;
 387+
 388+ // If there are functions bound, to execute
 389+ if ( readyList ) {
 390+ // Execute all of them
 391+ var fn, i = 0;
 392+ while ( (fn = readyList[ i++ ]) ) {
 393+ fn.call( document, jQuery );
 394+ }
 395+
 396+ // Reset the list of functions
 397+ readyList = null;
 398+ }
 399+
 400+ // Trigger any bound ready events
 401+ if ( jQuery.fn.triggerHandler ) {
 402+ jQuery( document ).triggerHandler( "ready" );
 403+ }
 404+ }
 405+ },
 406+
 407+ bindReady: function() {
 408+ if ( readyBound ) {
 409+ return;
 410+ }
 411+
 412+ readyBound = true;
 413+
 414+ // Catch cases where $(document).ready() is called after the
 415+ // browser event has already occurred.
 416+ if ( document.readyState === "complete" ) {
 417+ return jQuery.ready();
 418+ }
 419+
 420+ // Mozilla, Opera and webkit nightlies currently support this event
 421+ if ( document.addEventListener ) {
 422+ // Use the handy event callback
 423+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 424+
 425+ // A fallback to window.onload, that will always work
 426+ window.addEventListener( "load", jQuery.ready, false );
 427+
 428+ // If IE event model is used
 429+ } else if ( document.attachEvent ) {
 430+ // ensure firing before onload,
 431+ // maybe late but safe also for iframes
 432+ document.attachEvent("onreadystatechange", DOMContentLoaded);
 433+
 434+ // A fallback to window.onload, that will always work
 435+ window.attachEvent( "onload", jQuery.ready );
 436+
 437+ // If IE and not a frame
 438+ // continually check to see if the document is ready
 439+ var toplevel = false;
 440+
 441+ try {
 442+ toplevel = window.frameElement == null;
 443+ } catch(e) {}
 444+
 445+ if ( document.documentElement.doScroll && toplevel ) {
 446+ doScrollCheck();
 447+ }
 448+ }
 449+ },
 450+
 451+ // See test/unit/core.js for details concerning isFunction.
 452+ // Since version 1.3, DOM methods and functions like alert
 453+ // aren't supported. They return false on IE (#2968).
 454+ isFunction: function( obj ) {
 455+ return toString.call(obj) === "[object Function]";
 456+ },
 457+
 458+ isArray: function( obj ) {
 459+ return toString.call(obj) === "[object Array]";
 460+ },
 461+
 462+ isPlainObject: function( obj ) {
 463+ // Must be an Object.
 464+ // Because of IE, we also have to check the presence of the constructor property.
 465+ // Make sure that DOM nodes and window objects don't pass through, as well
 466+ if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
 467+ return false;
 468+ }
 469+
 470+ // Not own constructor property must be Object
 471+ if ( obj.constructor
 472+ && !hasOwnProperty.call(obj, "constructor")
 473+ && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
 474+ return false;
 475+ }
 476+
 477+ // Own properties are enumerated firstly, so to speed up,
 478+ // if last one is own, then all properties are own.
 479+
 480+ var key;
 481+ for ( key in obj ) {}
 482+
 483+ return key === undefined || hasOwnProperty.call( obj, key );
 484+ },
 485+
 486+ isEmptyObject: function( obj ) {
 487+ for ( var name in obj ) {
 488+ return false;
 489+ }
 490+ return true;
 491+ },
 492+
 493+ error: function( msg ) {
 494+ throw msg;
 495+ },
 496+
 497+ parseJSON: function( data ) {
 498+ if ( typeof data !== "string" || !data ) {
 499+ return null;
 500+ }
 501+
 502+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
 503+ data = jQuery.trim( data );
 504+
 505+ // Make sure the incoming data is actual JSON
 506+ // Logic borrowed from http://json.org/json2.js
 507+ if ( /^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
 508+ .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
 509+ .replace(/(?:^|:|,)(?:\s*\[)+/g, "")) ) {
 510+
 511+ // Try to use the native JSON parser first
 512+ return window.JSON && window.JSON.parse ?
 513+ window.JSON.parse( data ) :
 514+ (new Function("return " + data))();
 515+
 516+ } else {
 517+ jQuery.error( "Invalid JSON: " + data );
 518+ }
 519+ },
 520+
 521+ noop: function() {},
 522+
 523+ // Evalulates a script in a global context
 524+ globalEval: function( data ) {
 525+ if ( data && rnotwhite.test(data) ) {
 526+ // Inspired by code by Andrea Giammarchi
 527+ // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
 528+ var head = document.getElementsByTagName("head")[0] || document.documentElement,
 529+ script = document.createElement("script");
 530+
 531+ script.type = "text/javascript";
 532+
 533+ if ( jQuery.support.scriptEval ) {
 534+ script.appendChild( document.createTextNode( data ) );
 535+ } else {
 536+ script.text = data;
 537+ }
 538+
 539+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
 540+ // This arises when a base node is used (#2709).
 541+ head.insertBefore( script, head.firstChild );
 542+ head.removeChild( script );
 543+ }
 544+ },
 545+
 546+ nodeName: function( elem, name ) {
 547+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
 548+ },
 549+
 550+ // args is for internal usage only
 551+ each: function( object, callback, args ) {
 552+ var name, i = 0,
 553+ length = object.length,
 554+ isObj = length === undefined || jQuery.isFunction(object);
 555+
 556+ if ( args ) {
 557+ if ( isObj ) {
 558+ for ( name in object ) {
 559+ if ( callback.apply( object[ name ], args ) === false ) {
 560+ break;
 561+ }
 562+ }
 563+ } else {
 564+ for ( ; i < length; ) {
 565+ if ( callback.apply( object[ i++ ], args ) === false ) {
 566+ break;
 567+ }
 568+ }
 569+ }
 570+
 571+ // A special, fast, case for the most common use of each
 572+ } else {
 573+ if ( isObj ) {
 574+ for ( name in object ) {
 575+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
 576+ break;
 577+ }
 578+ }
 579+ } else {
 580+ for ( var value = object[0];
 581+ i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}
 582+ }
 583+ }
 584+
 585+ return object;
 586+ },
 587+
 588+ trim: function( text ) {
 589+ return (text || "").replace( rtrim, "" );
 590+ },
 591+
 592+ // results is for internal usage only
 593+ makeArray: function( array, results ) {
 594+ var ret = results || [];
 595+
 596+ if ( array != null ) {
 597+ // The window, strings (and functions) also have 'length'
 598+ // The extra typeof function check is to prevent crashes
 599+ // in Safari 2 (See: #3039)
 600+ if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {
 601+ push.call( ret, array );
 602+ } else {
 603+ jQuery.merge( ret, array );
 604+ }
 605+ }
 606+
 607+ return ret;
 608+ },
 609+
 610+ inArray: function( elem, array ) {
 611+ if ( array.indexOf ) {
 612+ return array.indexOf( elem );
 613+ }
 614+
 615+ for ( var i = 0, length = array.length; i < length; i++ ) {
 616+ if ( array[ i ] === elem ) {
 617+ return i;
 618+ }
 619+ }
 620+
 621+ return -1;
 622+ },
 623+
 624+ merge: function( first, second ) {
 625+ var i = first.length, j = 0;
 626+
 627+ if ( typeof second.length === "number" ) {
 628+ for ( var l = second.length; j < l; j++ ) {
 629+ first[ i++ ] = second[ j ];
 630+ }
 631+
 632+ } else {
 633+ while ( second[j] !== undefined ) {
 634+ first[ i++ ] = second[ j++ ];
 635+ }
 636+ }
 637+
 638+ first.length = i;
 639+
 640+ return first;
 641+ },
 642+
 643+ grep: function( elems, callback, inv ) {
 644+ var ret = [];
 645+
 646+ // Go through the array, only saving the items
 647+ // that pass the validator function
 648+ for ( var i = 0, length = elems.length; i < length; i++ ) {
 649+ if ( !inv !== !callback( elems[ i ], i ) ) {
 650+ ret.push( elems[ i ] );
 651+ }
 652+ }
 653+
 654+ return ret;
 655+ },
 656+
 657+ // arg is for internal usage only
 658+ map: function( elems, callback, arg ) {
 659+ var ret = [], value;
 660+
 661+ // Go through the array, translating each of the items to their
 662+ // new value (or values).
 663+ for ( var i = 0, length = elems.length; i < length; i++ ) {
 664+ value = callback( elems[ i ], i, arg );
 665+
 666+ if ( value != null ) {
 667+ ret[ ret.length ] = value;
 668+ }
 669+ }
 670+
 671+ return ret.concat.apply( [], ret );
 672+ },
 673+
 674+ // A global GUID counter for objects
 675+ guid: 1,
 676+
 677+ proxy: function( fn, proxy, thisObject ) {
 678+ if ( arguments.length === 2 ) {
 679+ if ( typeof proxy === "string" ) {
 680+ thisObject = fn;
 681+ fn = thisObject[ proxy ];
 682+ proxy = undefined;
 683+
 684+ } else if ( proxy && !jQuery.isFunction( proxy ) ) {
 685+ thisObject = proxy;
 686+ proxy = undefined;
 687+ }
 688+ }
 689+
 690+ if ( !proxy && fn ) {
 691+ proxy = function() {
 692+ return fn.apply( thisObject || this, arguments );
 693+ };
 694+ }
 695+
 696+ // Set the guid of unique handler to the same of original handler, so it can be removed
 697+ if ( fn ) {
 698+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
 699+ }
 700+
 701+ // So proxy can be declared as an argument
 702+ return proxy;
 703+ },
 704+
 705+ // Use of jQuery.browser is frowned upon.
 706+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
 707+ uaMatch: function( ua ) {
 708+ ua = ua.toLowerCase();
 709+
 710+ var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
 711+ /(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
 712+ /(msie) ([\w.]+)/.exec( ua ) ||
 713+ !/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
 714+ [];
 715+
 716+ return { browser: match[1] || "", version: match[2] || "0" };
 717+ },
 718+
 719+ browser: {}
 720+});
 721+
 722+browserMatch = jQuery.uaMatch( userAgent );
 723+if ( browserMatch.browser ) {
 724+ jQuery.browser[ browserMatch.browser ] = true;
 725+ jQuery.browser.version = browserMatch.version;
 726+}
 727+
 728+// Deprecated, use jQuery.browser.webkit instead
 729+if ( jQuery.browser.webkit ) {
 730+ jQuery.browser.safari = true;
 731+}
 732+
 733+if ( indexOf ) {
 734+ jQuery.inArray = function( elem, array ) {
 735+ return indexOf.call( array, elem );
 736+ };
 737+}
 738+
 739+// All jQuery objects should point back to these
 740+rootjQuery = jQuery(document);
 741+
 742+// Cleanup functions for the document ready method
 743+if ( document.addEventListener ) {
 744+ DOMContentLoaded = function() {
 745+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 746+ jQuery.ready();
 747+ };
 748+
 749+} else if ( document.attachEvent ) {
 750+ DOMContentLoaded = function() {
 751+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
 752+ if ( document.readyState === "complete" ) {
 753+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
 754+ jQuery.ready();
 755+ }
 756+ };
 757+}
 758+
 759+// The DOM ready check for Internet Explorer
 760+function doScrollCheck() {
 761+ if ( jQuery.isReady ) {
 762+ return;
 763+ }
 764+
 765+ try {
 766+ // If IE is used, use the trick by Diego Perini
 767+ // http://javascript.nwbox.com/IEContentLoaded/
 768+ document.documentElement.doScroll("left");
 769+ } catch( error ) {
 770+ setTimeout( doScrollCheck, 1 );
 771+ return;
 772+ }
 773+
 774+ // and execute any waiting functions
 775+ jQuery.ready();
 776+}
 777+
 778+function evalScript( i, elem ) {
 779+ if ( elem.src ) {
 780+ jQuery.ajax({
 781+ url: elem.src,
 782+ async: false,
 783+ dataType: "script"
 784+ });
 785+ } else {
 786+ jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
 787+ }
 788+
 789+ if ( elem.parentNode ) {
 790+ elem.parentNode.removeChild( elem );
 791+ }
 792+}
 793+
 794+// Mutifunctional method to get and set values to a collection
 795+// The value/s can be optionally by executed if its a function
 796+function access( elems, key, value, exec, fn, pass ) {
 797+ var length = elems.length;
 798+
 799+ // Setting many attributes
 800+ if ( typeof key === "object" ) {
 801+ for ( var k in key ) {
 802+ access( elems, k, key[k], exec, fn, value );
 803+ }
 804+ return elems;
 805+ }
 806+
 807+ // Setting one attribute
 808+ if ( value !== undefined ) {
 809+ // Optionally, function values get executed if exec is true
 810+ exec = !pass && exec && jQuery.isFunction(value);
 811+
 812+ for ( var i = 0; i < length; i++ ) {
 813+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
 814+ }
 815+
 816+ return elems;
 817+ }
 818+
 819+ // Getting an attribute
 820+ return length ? fn( elems[0], key ) : undefined;
 821+}
 822+
 823+function now() {
 824+ return (new Date).getTime();
 825+}
 826+(function() {
 827+
 828+ jQuery.support = {};
 829+
 830+ var root = document.documentElement,
 831+ script = document.createElement("script"),
 832+ div = document.createElement("div"),
 833+ id = "script" + now();
 834+
 835+ div.style.display = "none";
 836+ div.innerHTML = " <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
 837+
 838+ var all = div.getElementsByTagName("*"),
 839+ a = div.getElementsByTagName("a")[0];
 840+
 841+ // Can't get basic test support
 842+ if ( !all || !all.length || !a ) {
 843+ return;
 844+ }
 845+
 846+ jQuery.support = {
 847+ // IE strips leading whitespace when .innerHTML is used
 848+ leadingWhitespace: div.firstChild.nodeType === 3,
 849+
 850+ // Make sure that tbody elements aren't automatically inserted
 851+ // IE will insert them into empty tables
 852+ tbody: !div.getElementsByTagName("tbody").length,
 853+
 854+ // Make sure that link elements get serialized correctly by innerHTML
 855+ // This requires a wrapper element in IE
 856+ htmlSerialize: !!div.getElementsByTagName("link").length,
 857+
 858+ // Get the style information from getAttribute
 859+ // (IE uses .cssText insted)
 860+ style: /red/.test( a.getAttribute("style") ),
 861+
 862+ // Make sure that URLs aren't manipulated
 863+ // (IE normalizes it by default)
 864+ hrefNormalized: a.getAttribute("href") === "/a",
 865+
 866+ // Make sure that element opacity exists
 867+ // (IE uses filter instead)
 868+ // Use a regex to work around a WebKit issue. See #5145
 869+ opacity: /^0.55$/.test( a.style.opacity ),
 870+
 871+ // Verify style float existence
 872+ // (IE uses styleFloat instead of cssFloat)
 873+ cssFloat: !!a.style.cssFloat,
 874+
 875+ // Make sure that if no value is specified for a checkbox
 876+ // that it defaults to "on".
 877+ // (WebKit defaults to "" instead)
 878+ checkOn: div.getElementsByTagName("input")[0].value === "on",
 879+
 880+ // Make sure that a selected-by-default option has a working selected property.
 881+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
 882+ optSelected: document.createElement("select").appendChild( document.createElement("option") ).selected,
 883+
 884+ parentNode: div.removeChild( div.appendChild( document.createElement("div") ) ).parentNode === null,
 885+
 886+ // Will be defined later
 887+ deleteExpando: true,
 888+ checkClone: false,
 889+ scriptEval: false,
 890+ noCloneEvent: true,
 891+ boxModel: null
 892+ };
 893+
 894+ script.type = "text/javascript";
 895+ try {
 896+ script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
 897+ } catch(e) {}
 898+
 899+ root.insertBefore( script, root.firstChild );
 900+
 901+ // Make sure that the execution of code works by injecting a script
 902+ // tag with appendChild/createTextNode
 903+ // (IE doesn't support this, fails, and uses .text instead)
 904+ if ( window[ id ] ) {
 905+ jQuery.support.scriptEval = true;
 906+ delete window[ id ];
 907+ }
 908+
 909+ // Test to see if it's possible to delete an expando from an element
 910+ // Fails in Internet Explorer
 911+ try {
 912+ delete script.test;
 913+
 914+ } catch(e) {
 915+ jQuery.support.deleteExpando = false;
 916+ }
 917+
 918+ root.removeChild( script );
 919+
 920+ if ( div.attachEvent && div.fireEvent ) {
 921+ div.attachEvent("onclick", function click() {
 922+ // Cloning a node shouldn't copy over any
 923+ // bound event handlers (IE does this)
 924+ jQuery.support.noCloneEvent = false;
 925+ div.detachEvent("onclick", click);
 926+ });
 927+ div.cloneNode(true).fireEvent("onclick");
 928+ }
 929+
 930+ div = document.createElement("div");
 931+ div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";
 932+
 933+ var fragment = document.createDocumentFragment();
 934+ fragment.appendChild( div.firstChild );
 935+
 936+ // WebKit doesn't clone checked state correctly in fragments
 937+ jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;
 938+
 939+ // Figure out if the W3C box model works as expected
 940+ // document.body must exist before we can do this
 941+ jQuery(function() {
 942+ var div = document.createElement("div");
 943+ div.style.width = div.style.paddingLeft = "1px";
 944+
 945+ document.body.appendChild( div );
 946+ jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;
 947+ document.body.removeChild( div ).style.display = 'none';
 948+
 949+ div = null;
 950+ });
 951+
 952+ // Technique from Juriy Zaytsev
 953+ // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
 954+ var eventSupported = function( eventName ) {
 955+ var el = document.createElement("div");
 956+ eventName = "on" + eventName;
 957+ var isSupported = false;
 958+ try {
 959+ isSupported = (eventName in el);
 960+ } catch(e) {
 961+ isSupported = el.wrappedJSObject && (eventName in el.wrappedJSObject);
 962+ }
 963+ if ( !isSupported ) {
 964+ el.setAttribute(eventName, "return;");
 965+ try {
 966+ isSupported = typeof el[eventName] === "function";
 967+ } catch(e) {
 968+ isSupported = el.wrappedJSObject && typeof el.wrappedJSObject[eventName] === "function";
 969+ }
 970+ }
 971+ el = null;
 972+ return isSupported;
 973+ };
 974+
 975+
 976+
 977+ jQuery.support.submitBubbles = eventSupported("submit");
 978+ jQuery.support.changeBubbles = eventSupported("change");
 979+
 980+ // release memory in IE
 981+ root = script = div = all = a = null;
 982+})();
 983+
 984+jQuery.props = {
 985+ "for": "htmlFor",
 986+ "class": "className",
 987+ readonly: "readOnly",
 988+ maxlength: "maxLength",
 989+ cellspacing: "cellSpacing",
 990+ rowspan: "rowSpan",
 991+ colspan: "colSpan",
 992+ tabindex: "tabIndex",
 993+ usemap: "useMap",
 994+ frameborder: "frameBorder"
 995+};
 996+var expando = "jQuery" + now(), uuid = 0, windowData = {};
 997+
 998+jQuery.extend({
 999+ cache: {},
 1000+
 1001+ expando:expando,
 1002+
 1003+ // The following elements throw uncatchable exceptions if you
 1004+ // attempt to add expando properties to them.
 1005+ noData: {
 1006+ "embed": true,
 1007+ "object": true,
 1008+ "applet": true
 1009+ },
 1010+
 1011+ data: function( elem, name, data ) {
 1012+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
 1013+ return;
 1014+ }
 1015+
 1016+ elem = elem == window ?
 1017+ windowData :
 1018+ elem;
 1019+
 1020+ var id = elem[ expando ], cache = jQuery.cache, thisCache;
 1021+
 1022+ if ( !id && typeof name === "string" && data === undefined ) {
 1023+ return null;
 1024+ }
 1025+
 1026+ // Compute a unique ID for the element
 1027+ if ( !id ) {
 1028+ id = ++uuid;
 1029+ }
 1030+
 1031+ // Avoid generating a new cache unless none exists and we
 1032+ // want to manipulate it.
 1033+ if ( typeof name === "object" ) {
 1034+ elem[ expando ] = id;
 1035+ thisCache = cache[ id ] = jQuery.extend(true, {}, name);
 1036+
 1037+ } else if ( !cache[ id ] ) {
 1038+ elem[ expando ] = id;
 1039+ cache[ id ] = {};
 1040+ }
 1041+
 1042+ thisCache = cache[ id ];
 1043+
 1044+ // Prevent overriding the named cache with undefined values
 1045+ if ( data !== undefined ) {
 1046+ thisCache[ name ] = data;
 1047+ }
 1048+
 1049+ return typeof name === "string" ? thisCache[ name ] : thisCache;
 1050+ },
 1051+
 1052+ removeData: function( elem, name ) {
 1053+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
 1054+ return;
 1055+ }
 1056+
 1057+ elem = elem == window ?
 1058+ windowData :
 1059+ elem;
 1060+
 1061+ var id = elem[ expando ], cache = jQuery.cache, thisCache = cache[ id ];
 1062+
 1063+ // If we want to remove a specific section of the element's data
 1064+ if ( name ) {
 1065+ if ( thisCache ) {
 1066+ // Remove the section of cache data
 1067+ delete thisCache[ name ];
 1068+
 1069+ // If we've removed all the data, remove the element's cache
 1070+ if ( jQuery.isEmptyObject(thisCache) ) {
 1071+ jQuery.removeData( elem );
 1072+ }
 1073+ }
 1074+
 1075+ // Otherwise, we want to remove all of the element's data
 1076+ } else {
 1077+ if ( jQuery.support.deleteExpando ) {
 1078+ delete elem[ jQuery.expando ];
 1079+
 1080+ } else if ( elem.removeAttribute ) {
 1081+ elem.removeAttribute( jQuery.expando );
 1082+ }
 1083+
 1084+ // Completely remove the data cache
 1085+ delete cache[ id ];
 1086+ }
 1087+ }
 1088+});
 1089+
 1090+jQuery.fn.extend({
 1091+ data: function( key, value ) {
 1092+ if ( typeof key === "undefined" && this.length ) {
 1093+ return jQuery.data( this[0] );
 1094+
 1095+ } else if ( typeof key === "object" ) {
 1096+ return this.each(function() {
 1097+ jQuery.data( this, key );
 1098+ });
 1099+ }
 1100+
 1101+ var parts = key.split(".");
 1102+ parts[1] = parts[1] ? "." + parts[1] : "";
 1103+
 1104+ if ( value === undefined ) {
 1105+ var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
 1106+
 1107+ if ( data === undefined && this.length ) {
 1108+ data = jQuery.data( this[0], key );
 1109+ }
 1110+ return data === undefined && parts[1] ?
 1111+ this.data( parts[0] ) :
 1112+ data;
 1113+ } else {
 1114+ return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function() {
 1115+ jQuery.data( this, key, value );
 1116+ });
 1117+ }
 1118+ },
 1119+
 1120+ removeData: function( key ) {
 1121+ return this.each(function() {
 1122+ jQuery.removeData( this, key );
 1123+ });
 1124+ }
 1125+});
 1126+jQuery.extend({
 1127+ queue: function( elem, type, data ) {
 1128+ if ( !elem ) {
 1129+ return;
 1130+ }
 1131+
 1132+ type = (type || "fx") + "queue";
 1133+ var q = jQuery.data( elem, type );
 1134+
 1135+ // Speed up dequeue by getting out quickly if this is just a lookup
 1136+ if ( !data ) {
 1137+ return q || [];
 1138+ }
 1139+
 1140+ if ( !q || jQuery.isArray(data) ) {
 1141+ q = jQuery.data( elem, type, jQuery.makeArray(data) );
 1142+
 1143+ } else {
 1144+ q.push( data );
 1145+ }
 1146+
 1147+ return q;
 1148+ },
 1149+
 1150+ dequeue: function( elem, type ) {
 1151+ type = type || "fx";
 1152+
 1153+ var queue = jQuery.queue( elem, type ), fn = queue.shift();
 1154+
 1155+ // If the fx queue is dequeued, always remove the progress sentinel
 1156+ if ( fn === "inprogress" ) {
 1157+ fn = queue.shift();
 1158+ }
 1159+
 1160+ if ( fn ) {
 1161+ // Add a progress sentinel to prevent the fx queue from being
 1162+ // automatically dequeued
 1163+ if ( type === "fx" ) {
 1164+ queue.unshift("inprogress");
 1165+ }
 1166+
 1167+ fn.call(elem, function() {
 1168+ jQuery.dequeue(elem, type);
 1169+ });
 1170+ }
 1171+ }
 1172+});
 1173+
 1174+jQuery.fn.extend({
 1175+ queue: function( type, data ) {
 1176+ if ( typeof type !== "string" ) {
 1177+ data = type;
 1178+ type = "fx";
 1179+ }
 1180+
 1181+ if ( data === undefined ) {
 1182+ return jQuery.queue( this[0], type );
 1183+ }
 1184+ return this.each(function( i, elem ) {
 1185+ var queue = jQuery.queue( this, type, data );
 1186+
 1187+ if ( type === "fx" && queue[0] !== "inprogress" ) {
 1188+ jQuery.dequeue( this, type );
 1189+ }
 1190+ });
 1191+ },
 1192+ dequeue: function( type ) {
 1193+ return this.each(function() {
 1194+ jQuery.dequeue( this, type );
 1195+ });
 1196+ },
 1197+
 1198+ // Based off of the plugin by Clint Helfers, with permission.
 1199+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
 1200+ delay: function( time, type ) {
 1201+ time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
 1202+ type = type || "fx";
 1203+
 1204+ return this.queue( type, function() {
 1205+ var elem = this;
 1206+ setTimeout(function() {
 1207+ jQuery.dequeue( elem, type );
 1208+ }, time );
 1209+ });
 1210+ },
 1211+
 1212+ clearQueue: function( type ) {
 1213+ return this.queue( type || "fx", [] );
 1214+ }
 1215+});
 1216+var rclass = /[\n\t]/g,
 1217+ rspace = /\s+/,
 1218+ rreturn = /\r/g,
 1219+ rspecialurl = /href|src|style/,
 1220+ rtype = /(button|input)/i,
 1221+ rfocusable = /(button|input|object|select|textarea)/i,
 1222+ rclickable = /^(a|area)$/i,
 1223+ rradiocheck = /radio|checkbox/;
 1224+
 1225+jQuery.fn.extend({
 1226+ attr: function( name, value ) {
 1227+ return access( this, name, value, true, jQuery.attr );
 1228+ },
 1229+
 1230+ removeAttr: function( name, fn ) {
 1231+ return this.each(function(){
 1232+ jQuery.attr( this, name, "" );
 1233+ if ( this.nodeType === 1 ) {
 1234+ this.removeAttribute( name );
 1235+ }
 1236+ });
 1237+ },
 1238+
 1239+ addClass: function( value ) {
 1240+ if ( jQuery.isFunction(value) ) {
 1241+ return this.each(function(i) {
 1242+ var self = jQuery(this);
 1243+ self.addClass( value.call(this, i, self.attr("class")) );
 1244+ });
 1245+ }
 1246+
 1247+ if ( value && typeof value === "string" ) {
 1248+ var classNames = (value || "").split( rspace );
 1249+
 1250+ for ( var i = 0, l = this.length; i < l; i++ ) {
 1251+ var elem = this[i];
 1252+
 1253+ if ( elem.nodeType === 1 ) {
 1254+ if ( !elem.className ) {
 1255+ elem.className = value;
 1256+
 1257+ } else {
 1258+ var className = " " + elem.className + " ", setClass = elem.className;
 1259+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
 1260+ if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
 1261+ setClass += " " + classNames[c];
 1262+ }
 1263+ }
 1264+ elem.className = jQuery.trim( setClass );
 1265+ }
 1266+ }
 1267+ }
 1268+ }
 1269+
 1270+ return this;
 1271+ },
 1272+
 1273+ removeClass: function( value ) {
 1274+ if ( jQuery.isFunction(value) ) {
 1275+ return this.each(function(i) {
 1276+ var self = jQuery(this);
 1277+ self.removeClass( value.call(this, i, self.attr("class")) );
 1278+ });
 1279+ }
 1280+
 1281+ if ( (value && typeof value === "string") || value === undefined ) {
 1282+ var classNames = (value || "").split(rspace);
 1283+
 1284+ for ( var i = 0, l = this.length; i < l; i++ ) {
 1285+ var elem = this[i];
 1286+
 1287+ if ( elem.nodeType === 1 && elem.className ) {
 1288+ if ( value ) {
 1289+ var className = (" " + elem.className + " ").replace(rclass, " ");
 1290+ for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
 1291+ className = className.replace(" " + classNames[c] + " ", " ");
 1292+ }
 1293+ elem.className = jQuery.trim( className );
 1294+
 1295+ } else {
 1296+ elem.className = "";
 1297+ }
 1298+ }
 1299+ }
 1300+ }
 1301+
 1302+ return this;
 1303+ },
 1304+
 1305+ toggleClass: function( value, stateVal ) {
 1306+ var type = typeof value, isBool = typeof stateVal === "boolean";
 1307+
 1308+ if ( jQuery.isFunction( value ) ) {
 1309+ return this.each(function(i) {
 1310+ var self = jQuery(this);
 1311+ self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
 1312+ });
 1313+ }
 1314+
 1315+ return this.each(function() {
 1316+ if ( type === "string" ) {
 1317+ // toggle individual class names
 1318+ var className, i = 0, self = jQuery(this),
 1319+ state = stateVal,
 1320+ classNames = value.split( rspace );
 1321+
 1322+ while ( (className = classNames[ i++ ]) ) {
 1323+ // check each className given, space seperated list
 1324+ state = isBool ? state : !self.hasClass( className );
 1325+ self[ state ? "addClass" : "removeClass" ]( className );
 1326+ }
 1327+
 1328+ } else if ( type === "undefined" || type === "boolean" ) {
 1329+ if ( this.className ) {
 1330+ // store className if set
 1331+ jQuery.data( this, "__className__", this.className );
 1332+ }
 1333+
 1334+ // toggle whole className
 1335+ this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
 1336+ }
 1337+ });
 1338+ },
 1339+
 1340+ hasClass: function( selector ) {
 1341+ var className = " " + selector + " ";
 1342+ for ( var i = 0, l = this.length; i < l; i++ ) {
 1343+ if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
 1344+ return true;
 1345+ }
 1346+ }
 1347+
 1348+ return false;
 1349+ },
 1350+
 1351+ val: function( value ) {
 1352+ if ( value === undefined ) {
 1353+ var elem = this[0];
 1354+
 1355+ if ( elem ) {
 1356+ if ( jQuery.nodeName( elem, "option" ) ) {
 1357+ return (elem.attributes.value || {}).specified ? elem.value : elem.text;
 1358+ }
 1359+
 1360+ // We need to handle select boxes special
 1361+ if ( jQuery.nodeName( elem, "select" ) ) {
 1362+ var index = elem.selectedIndex,
 1363+ values = [],
 1364+ options = elem.options,
 1365+ one = elem.type === "select-one";
 1366+
 1367+ // Nothing was selected
 1368+ if ( index < 0 ) {
 1369+ return null;
 1370+ }
 1371+
 1372+ // Loop through all the selected options
 1373+ for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
 1374+ var option = options[ i ];
 1375+
 1376+ if ( option.selected ) {
 1377+ // Get the specifc value for the option
 1378+ value = jQuery(option).val();
 1379+
 1380+ // We don't need an array for one selects
 1381+ if ( one ) {
 1382+ return value;
 1383+ }
 1384+
 1385+ // Multi-Selects return an array
 1386+ values.push( value );
 1387+ }
 1388+ }
 1389+
 1390+ return values;
 1391+ }
 1392+
 1393+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
 1394+ if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
 1395+ return elem.getAttribute("value") === null ? "on" : elem.value;
 1396+ }
 1397+
 1398+
 1399+ // Everything else, we just grab the value
 1400+ return (elem.value || "").replace(rreturn, "");
 1401+
 1402+ }
 1403+
 1404+ return undefined;
 1405+ }
 1406+
 1407+ var isFunction = jQuery.isFunction(value);
 1408+
 1409+ return this.each(function(i) {
 1410+ var self = jQuery(this), val = value;
 1411+
 1412+ if ( this.nodeType !== 1 ) {
 1413+ return;
 1414+ }
 1415+
 1416+ if ( isFunction ) {
 1417+ val = value.call(this, i, self.val());
 1418+ }
 1419+
 1420+ // Typecast each time if the value is a Function and the appended
 1421+ // value is therefore different each time.
 1422+ if ( typeof val === "number" ) {
 1423+ val += "";
 1424+ }
 1425+
 1426+ if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
 1427+ this.checked = jQuery.inArray( self.val(), val ) >= 0;
 1428+
 1429+ } else if ( jQuery.nodeName( this, "select" ) ) {
 1430+ var values = jQuery.makeArray(val);
 1431+
 1432+ jQuery( "option", this ).each(function() {
 1433+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
 1434+ });
 1435+
 1436+ if ( !values.length ) {
 1437+ this.selectedIndex = -1;
 1438+ }
 1439+
 1440+ } else {
 1441+ this.value = val;
 1442+ }
 1443+ });
 1444+ }
 1445+});
 1446+
 1447+jQuery.extend({
 1448+ attrFn: {
 1449+ val: true,
 1450+ css: true,
 1451+ html: true,
 1452+ text: true,
 1453+ data: true,
 1454+ width: true,
 1455+ height: true,
 1456+ offset: true
 1457+ },
 1458+
 1459+ attr: function( elem, name, value, pass ) {
 1460+ // don't set attributes on text and comment nodes
 1461+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
 1462+ return undefined;
 1463+ }
 1464+
 1465+ if ( pass && name in jQuery.attrFn ) {
 1466+ return jQuery(elem)[name](value);
 1467+ }
 1468+
 1469+ var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
 1470+ // Whether we are setting (or getting)
 1471+ set = value !== undefined;
 1472+
 1473+ // Try to normalize/fix the name
 1474+ name = notxml && jQuery.props[ name ] || name;
 1475+
 1476+ // Only do all the following if this is a node (faster for style)
 1477+ if ( elem.nodeType === 1 ) {
 1478+ // These attributes require special treatment
 1479+ var special = rspecialurl.test( name );
 1480+
 1481+ // Safari mis-reports the default selected property of an option
 1482+ // Accessing the parent's selectedIndex property fixes it
 1483+ if ( name === "selected" && !jQuery.support.optSelected ) {
 1484+ var parent = elem.parentNode;
 1485+ if ( parent ) {
 1486+ parent.selectedIndex;
 1487+
 1488+ // Make sure that it also works with optgroups, see #5701
 1489+ if ( parent.parentNode ) {
 1490+ parent.parentNode.selectedIndex;
 1491+ }
 1492+ }
 1493+ }
 1494+
 1495+ // If applicable, access the attribute via the DOM 0 way
 1496+ if ( name in elem && notxml && !special ) {
 1497+ if ( set ) {
 1498+ // We can't allow the type property to be changed (since it causes problems in IE)
 1499+ if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
 1500+ jQuery.error( "type property can't be changed" );
 1501+ }
 1502+
 1503+ elem[ name ] = value;
 1504+ }
 1505+
 1506+ // browsers index elements by id/name on forms, give priority to attributes.
 1507+ if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
 1508+ return elem.getAttributeNode( name ).nodeValue;
 1509+ }
 1510+
 1511+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
 1512+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
 1513+ if ( name === "tabIndex" ) {
 1514+ var attributeNode = elem.getAttributeNode( "tabIndex" );
 1515+
 1516+ return attributeNode && attributeNode.specified ?
 1517+ attributeNode.value :
 1518+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
 1519+ 0 :
 1520+ undefined;
 1521+ }
 1522+
 1523+ return elem[ name ];
 1524+ }
 1525+
 1526+ if ( !jQuery.support.style && notxml && name === "style" ) {
 1527+ if ( set ) {
 1528+ elem.style.cssText = "" + value;
 1529+ }
 1530+
 1531+ return elem.style.cssText;
 1532+ }
 1533+
 1534+ if ( set ) {
 1535+ // convert the value to a string (all browsers do this but IE) see #1070
 1536+ elem.setAttribute( name, "" + value );
 1537+ }
 1538+
 1539+ var attr = !jQuery.support.hrefNormalized && notxml && special ?
 1540+ // Some attributes require a special call on IE
 1541+ elem.getAttribute( name, 2 ) :
 1542+ elem.getAttribute( name );
 1543+
 1544+ // Non-existent attributes return null, we normalize to undefined
 1545+ return attr === null ? undefined : attr;
 1546+ }
 1547+
 1548+ // elem is actually elem.style ... set the style
 1549+ // Using attr for specific style information is now deprecated. Use style instead.
 1550+ return jQuery.style( elem, name, value );
 1551+ }
 1552+});
 1553+var rnamespaces = /\.(.*)$/,
 1554+ fcleanup = function( nm ) {
 1555+ return nm.replace(/[^\w\s\.\|`]/g, function( ch ) {
 1556+ return "\\" + ch;
 1557+ });
 1558+ };
 1559+
 1560+/*
 1561+ * A number of helper functions used for managing events.
 1562+ * Many of the ideas behind this code originated from
 1563+ * Dean Edwards' addEvent library.
 1564+ */
 1565+jQuery.event = {
 1566+
 1567+ // Bind an event to an element
 1568+ // Original by Dean Edwards
 1569+ add: function( elem, types, handler, data ) {
 1570+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
 1571+ return;
 1572+ }
 1573+
 1574+ // For whatever reason, IE has trouble passing the window object
 1575+ // around, causing it to be cloned in the process
 1576+ if ( elem.setInterval && ( elem !== window && !elem.frameElement ) ) {
 1577+ elem = window;
 1578+ }
 1579+
 1580+ var handleObjIn, handleObj;
 1581+
 1582+ if ( handler.handler ) {
 1583+ handleObjIn = handler;
 1584+ handler = handleObjIn.handler;
 1585+ }
 1586+
 1587+ // Make sure that the function being executed has a unique ID
 1588+ if ( !handler.guid ) {
 1589+ handler.guid = jQuery.guid++;
 1590+ }
 1591+
 1592+ // Init the element's event structure
 1593+ var elemData = jQuery.data( elem );
 1594+
 1595+ // If no elemData is found then we must be trying to bind to one of the
 1596+ // banned noData elements
 1597+ if ( !elemData ) {
 1598+ return;
 1599+ }
 1600+
 1601+ var events = elemData.events = elemData.events || {},
 1602+ eventHandle = elemData.handle, eventHandle;
 1603+
 1604+ if ( !eventHandle ) {
 1605+ elemData.handle = eventHandle = function() {
 1606+ // Handle the second event of a trigger and when
 1607+ // an event is called after a page has unloaded
 1608+ return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
 1609+ jQuery.event.handle.apply( eventHandle.elem, arguments ) :
 1610+ undefined;
 1611+ };
 1612+ }
 1613+
 1614+ // Add elem as a property of the handle function
 1615+ // This is to prevent a memory leak with non-native events in IE.
 1616+ eventHandle.elem = elem;
 1617+
 1618+ // Handle multiple events separated by a space
 1619+ // jQuery(...).bind("mouseover mouseout", fn);
 1620+ types = types.split(" ");
 1621+
 1622+ var type, i = 0, namespaces;
 1623+
 1624+ while ( (type = types[ i++ ]) ) {
 1625+ handleObj = handleObjIn ?
 1626+ jQuery.extend({}, handleObjIn) :
 1627+ { handler: handler, data: data };
 1628+
 1629+ // Namespaced event handlers
 1630+ if ( type.indexOf(".") > -1 ) {
 1631+ namespaces = type.split(".");
 1632+ type = namespaces.shift();
 1633+ handleObj.namespace = namespaces.slice(0).sort().join(".");
 1634+
 1635+ } else {
 1636+ namespaces = [];
 1637+ handleObj.namespace = "";
 1638+ }
 1639+
 1640+ handleObj.type = type;
 1641+ handleObj.guid = handler.guid;
 1642+
 1643+ // Get the current list of functions bound to this event
 1644+ var handlers = events[ type ],
 1645+ special = jQuery.event.special[ type ] || {};
 1646+
 1647+ // Init the event handler queue
 1648+ if ( !handlers ) {
 1649+ handlers = events[ type ] = [];
 1650+
 1651+ // Check for a special event handler
 1652+ // Only use addEventListener/attachEvent if the special
 1653+ // events handler returns false
 1654+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
 1655+ // Bind the global event handler to the element
 1656+ if ( elem.addEventListener ) {
 1657+ elem.addEventListener( type, eventHandle, false );
 1658+
 1659+ } else if ( elem.attachEvent ) {
 1660+ elem.attachEvent( "on" + type, eventHandle );
 1661+ }
 1662+ }
 1663+ }
 1664+
 1665+ if ( special.add ) {
 1666+ special.add.call( elem, handleObj );
 1667+
 1668+ if ( !handleObj.handler.guid ) {
 1669+ handleObj.handler.guid = handler.guid;
 1670+ }
 1671+ }
 1672+
 1673+ // Add the function to the element's handler list
 1674+ handlers.push( handleObj );
 1675+
 1676+ // Keep track of which events have been used, for global triggering
 1677+ jQuery.event.global[ type ] = true;
 1678+ }
 1679+
 1680+ // Nullify elem to prevent memory leaks in IE
 1681+ elem = null;
 1682+ },
 1683+
 1684+ global: {},
 1685+
 1686+ // Detach an event or set of events from an element
 1687+ remove: function( elem, types, handler, pos ) {
 1688+ // don't do events on text and comment nodes
 1689+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
 1690+ return;
 1691+ }
 1692+
 1693+ var ret, type, fn, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
 1694+ elemData = jQuery.data( elem ),
 1695+ events = elemData && elemData.events;
 1696+
 1697+ if ( !elemData || !events ) {
 1698+ return;
 1699+ }
 1700+
 1701+ // types is actually an event object here
 1702+ if ( types && types.type ) {
 1703+ handler = types.handler;
 1704+ types = types.type;
 1705+ }
 1706+
 1707+ // Unbind all events for the element
 1708+ if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
 1709+ types = types || "";
 1710+
 1711+ for ( type in events ) {
 1712+ jQuery.event.remove( elem, type + types );
 1713+ }
 1714+
 1715+ return;
 1716+ }
 1717+
 1718+ // Handle multiple events separated by a space
 1719+ // jQuery(...).unbind("mouseover mouseout", fn);
 1720+ types = types.split(" ");
 1721+
 1722+ while ( (type = types[ i++ ]) ) {
 1723+ origType = type;
 1724+ handleObj = null;
 1725+ all = type.indexOf(".") < 0;
 1726+ namespaces = [];
 1727+
 1728+ if ( !all ) {
 1729+ // Namespaced event handlers
 1730+ namespaces = type.split(".");
 1731+ type = namespaces.shift();
 1732+
 1733+ namespace = new RegExp("(^|\\.)" +
 1734+ jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)")
 1735+ }
 1736+
 1737+ eventType = events[ type ];
 1738+
 1739+ if ( !eventType ) {
 1740+ continue;
 1741+ }
 1742+
 1743+ if ( !handler ) {
 1744+ for ( var j = 0; j < eventType.length; j++ ) {
 1745+ handleObj = eventType[ j ];
 1746+
 1747+ if ( all || namespace.test( handleObj.namespace ) ) {
 1748+ jQuery.event.remove( elem, origType, handleObj.handler, j );
 1749+ eventType.splice( j--, 1 );
 1750+ }
 1751+ }
 1752+
 1753+ continue;
 1754+ }
 1755+
 1756+ special = jQuery.event.special[ type ] || {};
 1757+
 1758+ for ( var j = pos || 0; j < eventType.length; j++ ) {
 1759+ handleObj = eventType[ j ];
 1760+
 1761+ if ( handler.guid === handleObj.guid ) {
 1762+ // remove the given handler for the given type
 1763+ if ( all || namespace.test( handleObj.namespace ) ) {
 1764+ if ( pos == null ) {
 1765+ eventType.splice( j--, 1 );
 1766+ }
 1767+
 1768+ if ( special.remove ) {
 1769+ special.remove.call( elem, handleObj );
 1770+ }
 1771+ }
 1772+
 1773+ if ( pos != null ) {
 1774+ break;
 1775+ }
 1776+ }
 1777+ }
 1778+
 1779+ // remove generic event handler if no more handlers exist
 1780+ if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
 1781+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
 1782+ removeEvent( elem, type, elemData.handle );
 1783+ }
 1784+
 1785+ ret = null;
 1786+ delete events[ type ];
 1787+ }
 1788+ }
 1789+
 1790+ // Remove the expando if it's no longer used
 1791+ if ( jQuery.isEmptyObject( events ) ) {
 1792+ var handle = elemData.handle;
 1793+ if ( handle ) {
 1794+ handle.elem = null;
 1795+ }
 1796+
 1797+ delete elemData.events;
 1798+ delete elemData.handle;
 1799+
 1800+ if ( jQuery.isEmptyObject( elemData ) ) {
 1801+ jQuery.removeData( elem );
 1802+ }
 1803+ }
 1804+ },
 1805+
 1806+ // bubbling is internal
 1807+ trigger: function( event, data, elem /*, bubbling */ ) {
 1808+ // Event object or event type
 1809+ var type = event.type || event,
 1810+ bubbling = arguments[3];
 1811+
 1812+ if ( !bubbling ) {
 1813+ event = typeof event === "object" ?
 1814+ // jQuery.Event object
 1815+ event[expando] ? event :
 1816+ // Object literal
 1817+ jQuery.extend( jQuery.Event(type), event ) :
 1818+ // Just the event type (string)
 1819+ jQuery.Event(type);
 1820+
 1821+ if ( type.indexOf("!") >= 0 ) {
 1822+ event.type = type = type.slice(0, -1);
 1823+ event.exclusive = true;
 1824+ }
 1825+
 1826+ // Handle a global trigger
 1827+ if ( !elem ) {
 1828+ // Don't bubble custom events when global (to avoid too much overhead)
 1829+ event.stopPropagation();
 1830+
 1831+ // Only trigger if we've ever bound an event for it
 1832+ if ( jQuery.event.global[ type ] ) {
 1833+ jQuery.each( jQuery.cache, function() {
 1834+ if ( this.events && this.events[type] ) {
 1835+ jQuery.event.trigger( event, data, this.handle.elem );
 1836+ }
 1837+ });
 1838+ }
 1839+ }
 1840+
 1841+ // Handle triggering a single element
 1842+
 1843+ // don't do events on text and comment nodes
 1844+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
 1845+ return undefined;
 1846+ }
 1847+
 1848+ // Clean up in case it is reused
 1849+ event.result = undefined;
 1850+ event.target = elem;
 1851+
 1852+ // Clone the incoming data, if any
 1853+ data = jQuery.makeArray( data );
 1854+ data.unshift( event );
 1855+ }
 1856+
 1857+ event.currentTarget = elem;
 1858+
 1859+ // Trigger the event, it is assumed that "handle" is a function
 1860+ var handle = jQuery.data( elem, "handle" );
 1861+ if ( handle ) {
 1862+ handle.apply( elem, data );
 1863+ }
 1864+
 1865+ var parent = elem.parentNode || elem.ownerDocument;
 1866+
 1867+ // Trigger an inline bound script
 1868+ try {
 1869+ if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
 1870+ if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
 1871+ event.result = false;
 1872+ }
 1873+ }
 1874+
 1875+ // prevent IE from throwing an error for some elements with some event types, see #3533
 1876+ } catch (e) {}
 1877+
 1878+ if ( !event.isPropagationStopped() && parent ) {
 1879+ jQuery.event.trigger( event, data, parent, true );
 1880+
 1881+ } else if ( !event.isDefaultPrevented() ) {
 1882+ var target = event.target, old,
 1883+ isClick = jQuery.nodeName(target, "a") && type === "click",
 1884+ special = jQuery.event.special[ type ] || {};
 1885+
 1886+ if ( (!special._default || special._default.call( elem, event ) === false) &&
 1887+ !isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {
 1888+
 1889+ try {
 1890+ if ( target[ type ] ) {
 1891+ // Make sure that we don't accidentally re-trigger the onFOO events
 1892+ old = target[ "on" + type ];
 1893+
 1894+ if ( old ) {
 1895+ target[ "on" + type ] = null;
 1896+ }
 1897+
 1898+ jQuery.event.triggered = true;
 1899+ target[ type ]();
 1900+ }
 1901+
 1902+ // prevent IE from throwing an error for some elements with some event types, see #3533
 1903+ } catch (e) {}
 1904+
 1905+ if ( old ) {
 1906+ target[ "on" + type ] = old;
 1907+ }
 1908+
 1909+ jQuery.event.triggered = false;
 1910+ }
 1911+ }
 1912+ },
 1913+
 1914+ handle: function( event ) {
 1915+ var all, handlers, namespaces, namespace, events;
 1916+
 1917+ event = arguments[0] = jQuery.event.fix( event || window.event );
 1918+ event.currentTarget = this;
 1919+
 1920+ // Namespaced event handlers
 1921+ all = event.type.indexOf(".") < 0 && !event.exclusive;
 1922+
 1923+ if ( !all ) {
 1924+ namespaces = event.type.split(".");
 1925+ event.type = namespaces.shift();
 1926+ namespace = new RegExp("(^|\\.)" + namespaces.slice(0).sort().join("\\.(?:.*\\.)?") + "(\\.|$)");
 1927+ }
 1928+
 1929+ var events = jQuery.data(this, "events"), handlers = events[ event.type ];
 1930+
 1931+ if ( events && handlers ) {
 1932+ // Clone the handlers to prevent manipulation
 1933+ handlers = handlers.slice(0);
 1934+
 1935+ for ( var j = 0, l = handlers.length; j < l; j++ ) {
 1936+ var handleObj = handlers[ j ];
 1937+
 1938+ // Filter the functions by class
 1939+ if ( all || namespace.test( handleObj.namespace ) ) {
 1940+ // Pass in a reference to the handler function itself
 1941+ // So that we can later remove it
 1942+ event.handler = handleObj.handler;
 1943+ event.data = handleObj.data;
 1944+ event.handleObj = handleObj;
 1945+
 1946+ var ret = handleObj.handler.apply( this, arguments );
 1947+
 1948+ if ( ret !== undefined ) {
 1949+ event.result = ret;
 1950+ if ( ret === false ) {
 1951+ event.preventDefault();
 1952+ event.stopPropagation();
 1953+ }
 1954+ }
 1955+
 1956+ if ( event.isImmediatePropagationStopped() ) {
 1957+ break;
 1958+ }
 1959+ }
 1960+ }
 1961+ }
 1962+
 1963+ return event.result;
 1964+ },
 1965+
 1966+ 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(" "),
 1967+
 1968+ fix: function( event ) {
 1969+ if ( event[ expando ] ) {
 1970+ return event;
 1971+ }
 1972+
 1973+ // store a copy of the original event object
 1974+ // and "clone" to set read-only properties
 1975+ var originalEvent = event;
 1976+ event = jQuery.Event( originalEvent );
 1977+
 1978+ for ( var i = this.props.length, prop; i; ) {
 1979+ prop = this.props[ --i ];
 1980+ event[ prop ] = originalEvent[ prop ];
 1981+ }
 1982+
 1983+ // Fix target property, if necessary
 1984+ if ( !event.target ) {
 1985+ event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
 1986+ }
 1987+
 1988+ // check if target is a textnode (safari)
 1989+ if ( event.target.nodeType === 3 ) {
 1990+ event.target = event.target.parentNode;
 1991+ }
 1992+
 1993+ // Add relatedTarget, if necessary
 1994+ if ( !event.relatedTarget && event.fromElement ) {
 1995+ event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
 1996+ }
 1997+
 1998+ // Calculate pageX/Y if missing and clientX/Y available
 1999+ if ( event.pageX == null && event.clientX != null ) {
 2000+ var doc = document.documentElement, body = document.body;
 2001+ event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
 2002+ event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
 2003+ }
 2004+
 2005+ // Add which for key events
 2006+ if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) ) {
 2007+ event.which = event.charCode || event.keyCode;
 2008+ }
 2009+
 2010+ // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
 2011+ if ( !event.metaKey && event.ctrlKey ) {
 2012+ event.metaKey = event.ctrlKey;
 2013+ }
 2014+
 2015+ // Add which for click: 1 === left; 2 === middle; 3 === right
 2016+ // Note: button is not normalized, so don't use it
 2017+ if ( !event.which && event.button !== undefined ) {
 2018+ event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
 2019+ }
 2020+
 2021+ return event;
 2022+ },
 2023+
 2024+ // Deprecated, use jQuery.guid instead
 2025+ guid: 1E8,
 2026+
 2027+ // Deprecated, use jQuery.proxy instead
 2028+ proxy: jQuery.proxy,
 2029+
 2030+ special: {
 2031+ ready: {
 2032+ // Make sure the ready event is setup
 2033+ setup: jQuery.bindReady,
 2034+ teardown: jQuery.noop
 2035+ },
 2036+
 2037+ live: {
 2038+ add: function( handleObj ) {
 2039+ jQuery.event.add( this, handleObj.origType, jQuery.extend({}, handleObj, {handler: liveHandler}) );
 2040+ },
 2041+
 2042+ remove: function( handleObj ) {
 2043+ var remove = true,
 2044+ type = handleObj.origType.replace(rnamespaces, "");
 2045+
 2046+ jQuery.each( jQuery.data(this, "events").live || [], function() {
 2047+ if ( type === this.origType.replace(rnamespaces, "") ) {
 2048+ remove = false;
 2049+ return false;
 2050+ }
 2051+ });
 2052+
 2053+ if ( remove ) {
 2054+ jQuery.event.remove( this, handleObj.origType, liveHandler );
 2055+ }
 2056+ }
 2057+
 2058+ },
 2059+
 2060+ beforeunload: {
 2061+ setup: function( data, namespaces, eventHandle ) {
 2062+ // We only want to do this special case on windows
 2063+ if ( this.setInterval ) {
 2064+ this.onbeforeunload = eventHandle;
 2065+ }
 2066+
 2067+ return false;
 2068+ },
 2069+ teardown: function( namespaces, eventHandle ) {
 2070+ if ( this.onbeforeunload === eventHandle ) {
 2071+ this.onbeforeunload = null;
 2072+ }
 2073+ }
 2074+ }
 2075+ }
 2076+};
 2077+
 2078+var removeEvent = document.removeEventListener ?
 2079+ function( elem, type, handle ) {
 2080+ elem.removeEventListener( type, handle, false );
 2081+ } :
 2082+ function( elem, type, handle ) {
 2083+ elem.detachEvent( "on" + type, handle );
 2084+ };
 2085+
 2086+jQuery.Event = function( src ) {
 2087+ // Allow instantiation without the 'new' keyword
 2088+ if ( !this.preventDefault ) {
 2089+ return new jQuery.Event( src );
 2090+ }
 2091+
 2092+ // Event object
 2093+ if ( src && src.type ) {
 2094+ this.originalEvent = src;
 2095+ this.type = src.type;
 2096+ // Event type
 2097+ } else {
 2098+ this.type = src;
 2099+ }
 2100+
 2101+ // timeStamp is buggy for some events on Firefox(#3843)
 2102+ // So we won't rely on the native value
 2103+ this.timeStamp = now();
 2104+
 2105+ // Mark it as fixed
 2106+ this[ expando ] = true;
 2107+};
 2108+
 2109+function returnFalse() {
 2110+ return false;
 2111+}
 2112+function returnTrue() {
 2113+ return true;
 2114+}
 2115+
 2116+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
 2117+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
 2118+jQuery.Event.prototype = {
 2119+ preventDefault: function() {
 2120+ this.isDefaultPrevented = returnTrue;
 2121+
 2122+ var e = this.originalEvent;
 2123+ if ( !e ) {
 2124+ return;
 2125+ }
 2126+
 2127+ // if preventDefault exists run it on the original event
 2128+ if ( e.preventDefault ) {
 2129+ e.preventDefault();
 2130+ }
 2131+ // otherwise set the returnValue property of the original event to false (IE)
 2132+ e.returnValue = false;
 2133+ },
 2134+ stopPropagation: function() {
 2135+ this.isPropagationStopped = returnTrue;
 2136+
 2137+ var e = this.originalEvent;
 2138+ if ( !e ) {
 2139+ return;
 2140+ }
 2141+ // if stopPropagation exists run it on the original event
 2142+ if ( e.stopPropagation ) {
 2143+ e.stopPropagation();
 2144+ }
 2145+ // otherwise set the cancelBubble property of the original event to true (IE)
 2146+ e.cancelBubble = true;
 2147+ },
 2148+ stopImmediatePropagation: function() {
 2149+ this.isImmediatePropagationStopped = returnTrue;
 2150+ this.stopPropagation();
 2151+ },
 2152+ isDefaultPrevented: returnFalse,
 2153+ isPropagationStopped: returnFalse,
 2154+ isImmediatePropagationStopped: returnFalse
 2155+};
 2156+
 2157+// Checks if an event happened on an element within another element
 2158+// Used in jQuery.event.special.mouseenter and mouseleave handlers
 2159+var withinElement = function( event ) {
 2160+ // Check if mouse(over|out) are still within the same parent element
 2161+ var parent = event.relatedTarget;
 2162+
 2163+ // Firefox sometimes assigns relatedTarget a XUL element
 2164+ // which we cannot access the parentNode property of
 2165+ try {
 2166+ // Traverse up the tree
 2167+ while ( parent && parent !== this ) {
 2168+ parent = parent.parentNode;
 2169+ }
 2170+
 2171+ if ( parent !== this ) {
 2172+ // set the correct event type
 2173+ event.type = event.data;
 2174+
 2175+ // handle event if we actually just moused on to a non sub-element
 2176+ jQuery.event.handle.apply( this, arguments );
 2177+ }
 2178+
 2179+ // assuming we've left the element since we most likely mousedover a xul element
 2180+ } catch(e) { }
 2181+},
 2182+
 2183+// In case of event delegation, we only need to rename the event.type,
 2184+// liveHandler will take care of the rest.
 2185+delegate = function( event ) {
 2186+ event.type = event.data;
 2187+ jQuery.event.handle.apply( this, arguments );
 2188+};
 2189+
 2190+// Create mouseenter and mouseleave events
 2191+jQuery.each({
 2192+ mouseenter: "mouseover",
 2193+ mouseleave: "mouseout"
 2194+}, function( orig, fix ) {
 2195+ jQuery.event.special[ orig ] = {
 2196+ setup: function( data ) {
 2197+ jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
 2198+ },
 2199+ teardown: function( data ) {
 2200+ jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
 2201+ }
 2202+ };
 2203+});
 2204+
 2205+// submit delegation
 2206+if ( !jQuery.support.submitBubbles ) {
 2207+
 2208+ jQuery.event.special.submit = {
 2209+ setup: function( data, namespaces ) {
 2210+ if ( this.nodeName.toLowerCase() !== "form" ) {
 2211+ jQuery.event.add(this, "click.specialSubmit", function( e ) {
 2212+ var elem = e.target, type = elem.type;
 2213+
 2214+ if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
 2215+ return trigger( "submit", this, arguments );
 2216+ }
 2217+ });
 2218+
 2219+ jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
 2220+ var elem = e.target, type = elem.type;
 2221+
 2222+ if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
 2223+ return trigger( "submit", this, arguments );
 2224+ }
 2225+ });
 2226+
 2227+ } else {
 2228+ return false;
 2229+ }
 2230+ },
 2231+
 2232+ teardown: function( namespaces ) {
 2233+ jQuery.event.remove( this, ".specialSubmit" );
 2234+ }
 2235+ };
 2236+
 2237+}
 2238+
 2239+// change delegation, happens here so we have bind.
 2240+if ( !jQuery.support.changeBubbles ) {
 2241+
 2242+ var formElems = /textarea|input|select/i,
 2243+
 2244+ changeFilters,
 2245+
 2246+ getVal = function( elem ) {
 2247+ var type = elem.type, val = elem.value;
 2248+
 2249+ if ( type === "radio" || type === "checkbox" ) {
 2250+ val = elem.checked;
 2251+
 2252+ } else if ( type === "select-multiple" ) {
 2253+ val = elem.selectedIndex > -1 ?
 2254+ jQuery.map( elem.options, function( elem ) {
 2255+ return elem.selected;
 2256+ }).join("-") :
 2257+ "";
 2258+
 2259+ } else if ( elem.nodeName.toLowerCase() === "select" ) {
 2260+ val = elem.selectedIndex;
 2261+ }
 2262+
 2263+ return val;
 2264+ },
 2265+
 2266+ testChange = function testChange( e ) {
 2267+ var elem = e.target, data, val;
 2268+
 2269+ if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
 2270+ return;
 2271+ }
 2272+
 2273+ data = jQuery.data( elem, "_change_data" );
 2274+ val = getVal(elem);
 2275+
 2276+ // the current data will be also retrieved by beforeactivate
 2277+ if ( e.type !== "focusout" || elem.type !== "radio" ) {
 2278+ jQuery.data( elem, "_change_data", val );
 2279+ }
 2280+
 2281+ if ( data === undefined || val === data ) {
 2282+ return;
 2283+ }
 2284+
 2285+ if ( data != null || val ) {
 2286+ e.type = "change";
 2287+ return jQuery.event.trigger( e, arguments[1], elem );
 2288+ }
 2289+ };
 2290+
 2291+ jQuery.event.special.change = {
 2292+ filters: {
 2293+ focusout: testChange,
 2294+
 2295+ click: function( e ) {
 2296+ var elem = e.target, type = elem.type;
 2297+
 2298+ if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
 2299+ return testChange.call( this, e );
 2300+ }
 2301+ },
 2302+
 2303+ // Change has to be called before submit
 2304+ // Keydown will be called before keypress, which is used in submit-event delegation
 2305+ keydown: function( e ) {
 2306+ var elem = e.target, type = elem.type;
 2307+
 2308+ if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
 2309+ (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
 2310+ type === "select-multiple" ) {
 2311+ return testChange.call( this, e );
 2312+ }
 2313+ },
 2314+
 2315+ // Beforeactivate happens also before the previous element is blurred
 2316+ // with this event you can't trigger a change event, but you can store
 2317+ // information/focus[in] is not needed anymore
 2318+ beforeactivate: function( e ) {
 2319+ var elem = e.target;
 2320+ jQuery.data( elem, "_change_data", getVal(elem) );
 2321+ }
 2322+ },
 2323+
 2324+ setup: function( data, namespaces ) {
 2325+ if ( this.type === "file" ) {
 2326+ return false;
 2327+ }
 2328+
 2329+ for ( var type in changeFilters ) {
 2330+ jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
 2331+ }
 2332+
 2333+ return formElems.test( this.nodeName );
 2334+ },
 2335+
 2336+ teardown: function( namespaces ) {
 2337+ jQuery.event.remove( this, ".specialChange" );
 2338+
 2339+ return formElems.test( this.nodeName );
 2340+ }
 2341+ };
 2342+
 2343+ changeFilters = jQuery.event.special.change.filters;
 2344+}
 2345+
 2346+function trigger( type, elem, args ) {
 2347+ args[0].type = type;
 2348+ return jQuery.event.handle.apply( elem, args );
 2349+}
 2350+
 2351+// Create "bubbling" focus and blur events
 2352+if ( document.addEventListener ) {
 2353+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
 2354+ jQuery.event.special[ fix ] = {
 2355+ setup: function() {
 2356+ this.addEventListener( orig, handler, true );
 2357+ },
 2358+ teardown: function() {
 2359+ this.removeEventListener( orig, handler, true );
 2360+ }
 2361+ };
 2362+
 2363+ function handler( e ) {
 2364+ e = jQuery.event.fix( e );
 2365+ e.type = fix;
 2366+ return jQuery.event.handle.call( this, e );
 2367+ }
 2368+ });
 2369+}
 2370+
 2371+jQuery.each(["bind", "one"], function( i, name ) {
 2372+ jQuery.fn[ name ] = function( type, data, fn ) {
 2373+ // Handle object literals
 2374+ if ( typeof type === "object" ) {
 2375+ for ( var key in type ) {
 2376+ this[ name ](key, data, type[key], fn);
 2377+ }
 2378+ return this;
 2379+ }
 2380+
 2381+ if ( jQuery.isFunction( data ) ) {
 2382+ fn = data;
 2383+ data = undefined;
 2384+ }
 2385+
 2386+ var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
 2387+ jQuery( this ).unbind( event, handler );
 2388+ return fn.apply( this, arguments );
 2389+ }) : fn;
 2390+
 2391+ if ( type === "unload" && name !== "one" ) {
 2392+ this.one( type, data, fn );
 2393+
 2394+ } else {
 2395+ for ( var i = 0, l = this.length; i < l; i++ ) {
 2396+ jQuery.event.add( this[i], type, handler, data );
 2397+ }
 2398+ }
 2399+
 2400+ return this;
 2401+ };
 2402+});
 2403+
 2404+jQuery.fn.extend({
 2405+ unbind: function( type, fn ) {
 2406+ // Handle object literals
 2407+ if ( typeof type === "object" && !type.preventDefault ) {
 2408+ for ( var key in type ) {
 2409+ this.unbind(key, type[key]);
 2410+ }
 2411+
 2412+ } else {
 2413+ for ( var i = 0, l = this.length; i < l; i++ ) {
 2414+ jQuery.event.remove( this[i], type, fn );
 2415+ }
 2416+ }
 2417+
 2418+ return this;
 2419+ },
 2420+
 2421+ delegate: function( selector, types, data, fn ) {
 2422+ return this.live( types, data, fn, selector );
 2423+ },
 2424+
 2425+ undelegate: function( selector, types, fn ) {
 2426+ if ( arguments.length === 0 ) {
 2427+ return this.unbind( "live" );
 2428+
 2429+ } else {
 2430+ return this.die( types, null, fn, selector );
 2431+ }
 2432+ },
 2433+
 2434+ trigger: function( type, data ) {
 2435+ return this.each(function() {
 2436+ jQuery.event.trigger( type, data, this );
 2437+ });
 2438+ },
 2439+
 2440+ triggerHandler: function( type, data ) {
 2441+ if ( this[0] ) {
 2442+ var event = jQuery.Event( type );
 2443+ event.preventDefault();
 2444+ event.stopPropagation();
 2445+ jQuery.event.trigger( event, data, this[0] );
 2446+ return event.result;
 2447+ }
 2448+ },
 2449+
 2450+ toggle: function( fn ) {
 2451+ // Save reference to arguments for access in closure
 2452+ var args = arguments, i = 1;
 2453+
 2454+ // link all the functions, so any of them can unbind this click handler
 2455+ while ( i < args.length ) {
 2456+ jQuery.proxy( fn, args[ i++ ] );
 2457+ }
 2458+
 2459+ return this.click( jQuery.proxy( fn, function( event ) {
 2460+ // Figure out which function to execute
 2461+ var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
 2462+ jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
 2463+
 2464+ // Make sure that clicks stop
 2465+ event.preventDefault();
 2466+
 2467+ // and execute the function
 2468+ return args[ lastToggle ].apply( this, arguments ) || false;
 2469+ }));
 2470+ },
 2471+
 2472+ hover: function( fnOver, fnOut ) {
 2473+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
 2474+ }
 2475+});
 2476+
 2477+var liveMap = {
 2478+ focus: "focusin",
 2479+ blur: "focusout",
 2480+ mouseenter: "mouseover",
 2481+ mouseleave: "mouseout"
 2482+};
 2483+
 2484+jQuery.each(["live", "die"], function( i, name ) {
 2485+ jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
 2486+ var type, i = 0, match, namespaces, preType,
 2487+ selector = origSelector || this.selector,
 2488+ context = origSelector ? this : jQuery( this.context );
 2489+
 2490+ if ( jQuery.isFunction( data ) ) {
 2491+ fn = data;
 2492+ data = undefined;
 2493+ }
 2494+
 2495+ types = (types || "").split(" ");
 2496+
 2497+ while ( (type = types[ i++ ]) != null ) {
 2498+ match = rnamespaces.exec( type );
 2499+ namespaces = "";
 2500+
 2501+ if ( match ) {
 2502+ namespaces = match[0];
 2503+ type = type.replace( rnamespaces, "" );
 2504+ }
 2505+
 2506+ if ( type === "hover" ) {
 2507+ types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
 2508+ continue;
 2509+ }
 2510+
 2511+ preType = type;
 2512+
 2513+ if ( type === "focus" || type === "blur" ) {
 2514+ types.push( liveMap[ type ] + namespaces );
 2515+ type = type + namespaces;
 2516+
 2517+ } else {
 2518+ type = (liveMap[ type ] || type) + namespaces;
 2519+ }
 2520+
 2521+ if ( name === "live" ) {
 2522+ // bind live handler
 2523+ context.each(function(){
 2524+ jQuery.event.add( this, liveConvert( type, selector ),
 2525+ { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
 2526+ });
 2527+
 2528+ } else {
 2529+ // unbind live handler
 2530+ context.unbind( liveConvert( type, selector ), fn );
 2531+ }
 2532+ }
 2533+
 2534+ return this;
 2535+ }
 2536+});
 2537+
 2538+function liveHandler( event ) {
 2539+ var stop, elems = [], selectors = [], args = arguments,
 2540+ related, match, handleObj, elem, j, i, l, data,
 2541+ events = jQuery.data( this, "events" );
 2542+
 2543+ // Make sure we avoid non-left-click bubbling in Firefox (#3861)
 2544+ if ( event.liveFired === this || !events || !events.live || event.button && event.type === "click" ) {
 2545+ return;
 2546+ }
 2547+
 2548+ event.liveFired = this;
 2549+
 2550+ var live = events.live.slice(0);
 2551+
 2552+ for ( j = 0; j < live.length; j++ ) {
 2553+ handleObj = live[j];
 2554+
 2555+ if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
 2556+ selectors.push( handleObj.selector );
 2557+
 2558+ } else {
 2559+ live.splice( j--, 1 );
 2560+ }
 2561+ }
 2562+
 2563+ match = jQuery( event.target ).closest( selectors, event.currentTarget );
 2564+
 2565+ for ( i = 0, l = match.length; i < l; i++ ) {
 2566+ for ( j = 0; j < live.length; j++ ) {
 2567+ handleObj = live[j];
 2568+
 2569+ if ( match[i].selector === handleObj.selector ) {
 2570+ elem = match[i].elem;
 2571+ related = null;
 2572+
 2573+ // Those two events require additional checking
 2574+ if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
 2575+ related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
 2576+ }
 2577+
 2578+ if ( !related || related !== elem ) {
 2579+ elems.push({ elem: elem, handleObj: handleObj });
 2580+ }
 2581+ }
 2582+ }
 2583+ }
 2584+
 2585+ for ( i = 0, l = elems.length; i < l; i++ ) {
 2586+ match = elems[i];
 2587+ event.currentTarget = match.elem;
 2588+ event.data = match.handleObj.data;
 2589+ event.handleObj = match.handleObj;
 2590+
 2591+ if ( match.handleObj.origHandler.apply( match.elem, args ) === false ) {
 2592+ stop = false;
 2593+ break;
 2594+ }
 2595+ }
 2596+
 2597+ return stop;
 2598+}
 2599+
 2600+function liveConvert( type, selector ) {
 2601+ return "live." + (type && type !== "*" ? type + "." : "") + selector.replace(/\./g, "`").replace(/ /g, "&");
 2602+}
 2603+
 2604+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
 2605+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
 2606+ "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
 2607+
 2608+ // Handle event binding
 2609+ jQuery.fn[ name ] = function( fn ) {
 2610+ return fn ? this.bind( name, fn ) : this.trigger( name );
 2611+ };
 2612+
 2613+ if ( jQuery.attrFn ) {
 2614+ jQuery.attrFn[ name ] = true;
 2615+ }
 2616+});
 2617+
 2618+// Prevent memory leaks in IE
 2619+// Window isn't included so as not to unbind existing unload events
 2620+// More info:
 2621+// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
 2622+if ( window.attachEvent && !window.addEventListener ) {
 2623+ window.attachEvent("onunload", function() {
 2624+ for ( var id in jQuery.cache ) {
 2625+ if ( jQuery.cache[ id ].handle ) {
 2626+ // Try/Catch is to handle iframes being unloaded, see #4280
 2627+ try {
 2628+ jQuery.event.remove( jQuery.cache[ id ].handle.elem );
 2629+ } catch(e) {}
 2630+ }
 2631+ }
 2632+ });
 2633+}
 2634+/*!
 2635+ * Sizzle CSS Selector Engine - v1.0
 2636+ * Copyright 2009, The Dojo Foundation
 2637+ * Released under the MIT, BSD, and GPL Licenses.
 2638+ * More information: http://sizzlejs.com/
 2639+ */
 2640+(function(){
 2641+
 2642+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
 2643+ done = 0,
 2644+ toString = Object.prototype.toString,
 2645+ hasDuplicate = false,
 2646+ baseHasDuplicate = true;
 2647+
 2648+// Here we check if the JavaScript engine is using some sort of
 2649+// optimization where it does not always call our comparision
 2650+// function. If that is the case, discard the hasDuplicate value.
 2651+// Thus far that includes Google Chrome.
 2652+[0, 0].sort(function(){
 2653+ baseHasDuplicate = false;
 2654+ return 0;
 2655+});
 2656+
 2657+var Sizzle = function(selector, context, results, seed) {
 2658+ results = results || [];
 2659+ var origContext = context = context || document;
 2660+
 2661+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
 2662+ return [];
 2663+ }
 2664+
 2665+ if ( !selector || typeof selector !== "string" ) {
 2666+ return results;
 2667+ }
 2668+
 2669+ var parts = [], m, set, checkSet, extra, prune = true, contextXML = isXML(context),
 2670+ soFar = selector;
 2671+
 2672+ // Reset the position of the chunker regexp (start from head)
 2673+ while ( (chunker.exec(""), m = chunker.exec(soFar)) !== null ) {
 2674+ soFar = m[3];
 2675+
 2676+ parts.push( m[1] );
 2677+
 2678+ if ( m[2] ) {
 2679+ extra = m[3];
 2680+ break;
 2681+ }
 2682+ }
 2683+
 2684+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
 2685+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
 2686+ set = posProcess( parts[0] + parts[1], context );
 2687+ } else {
 2688+ set = Expr.relative[ parts[0] ] ?
 2689+ [ context ] :
 2690+ Sizzle( parts.shift(), context );
 2691+
 2692+ while ( parts.length ) {
 2693+ selector = parts.shift();
 2694+
 2695+ if ( Expr.relative[ selector ] ) {
 2696+ selector += parts.shift();
 2697+ }
 2698+
 2699+ set = posProcess( selector, set );
 2700+ }
 2701+ }
 2702+ } else {
 2703+ // Take a shortcut and set the context if the root selector is an ID
 2704+ // (but not if it'll be faster if the inner selector is an ID)
 2705+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
 2706+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
 2707+ var ret = Sizzle.find( parts.shift(), context, contextXML );
 2708+ context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0];
 2709+ }
 2710+
 2711+ if ( context ) {
 2712+ var ret = seed ?
 2713+ { expr: parts.pop(), set: makeArray(seed) } :
 2714+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
 2715+ set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set;
 2716+
 2717+ if ( parts.length > 0 ) {
 2718+ checkSet = makeArray(set);
 2719+ } else {
 2720+ prune = false;
 2721+ }
 2722+
 2723+ while ( parts.length ) {
 2724+ var cur = parts.pop(), pop = cur;
 2725+
 2726+ if ( !Expr.relative[ cur ] ) {
 2727+ cur = "";
 2728+ } else {
 2729+ pop = parts.pop();
 2730+ }
 2731+
 2732+ if ( pop == null ) {
 2733+ pop = context;
 2734+ }
 2735+
 2736+ Expr.relative[ cur ]( checkSet, pop, contextXML );
 2737+ }
 2738+ } else {
 2739+ checkSet = parts = [];
 2740+ }
 2741+ }
 2742+
 2743+ if ( !checkSet ) {
 2744+ checkSet = set;
 2745+ }
 2746+
 2747+ if ( !checkSet ) {
 2748+ Sizzle.error( cur || selector );
 2749+ }
 2750+
 2751+ if ( toString.call(checkSet) === "[object Array]" ) {
 2752+ if ( !prune ) {
 2753+ results.push.apply( results, checkSet );
 2754+ } else if ( context && context.nodeType === 1 ) {
 2755+ for ( var i = 0; checkSet[i] != null; i++ ) {
 2756+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {
 2757+ results.push( set[i] );
 2758+ }
 2759+ }
 2760+ } else {
 2761+ for ( var i = 0; checkSet[i] != null; i++ ) {
 2762+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
 2763+ results.push( set[i] );
 2764+ }
 2765+ }
 2766+ }
 2767+ } else {
 2768+ makeArray( checkSet, results );
 2769+ }
 2770+
 2771+ if ( extra ) {
 2772+ Sizzle( extra, origContext, results, seed );
 2773+ Sizzle.uniqueSort( results );
 2774+ }
 2775+
 2776+ return results;
 2777+};
 2778+
 2779+Sizzle.uniqueSort = function(results){
 2780+ if ( sortOrder ) {
 2781+ hasDuplicate = baseHasDuplicate;
 2782+ results.sort(sortOrder);
 2783+
 2784+ if ( hasDuplicate ) {
 2785+ for ( var i = 1; i < results.length; i++ ) {
 2786+ if ( results[i] === results[i-1] ) {
 2787+ results.splice(i--, 1);
 2788+ }
 2789+ }
 2790+ }
 2791+ }
 2792+
 2793+ return results;
 2794+};
 2795+
 2796+Sizzle.matches = function(expr, set){
 2797+ return Sizzle(expr, null, null, set);
 2798+};
 2799+
 2800+Sizzle.find = function(expr, context, isXML){
 2801+ var set, match;
 2802+
 2803+ if ( !expr ) {
 2804+ return [];
 2805+ }
 2806+
 2807+ for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
 2808+ var type = Expr.order[i], match;
 2809+
 2810+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
 2811+ var left = match[1];
 2812+ match.splice(1,1);
 2813+
 2814+ if ( left.substr( left.length - 1 ) !== "\\" ) {
 2815+ match[1] = (match[1] || "").replace(/\\/g, "");
 2816+ set = Expr.find[ type ]( match, context, isXML );
 2817+ if ( set != null ) {
 2818+ expr = expr.replace( Expr.match[ type ], "" );
 2819+ break;
 2820+ }
 2821+ }
 2822+ }
 2823+ }
 2824+
 2825+ if ( !set ) {
 2826+ set = context.getElementsByTagName("*");
 2827+ }
 2828+
 2829+ return {set: set, expr: expr};
 2830+};
 2831+
 2832+Sizzle.filter = function(expr, set, inplace, not){
 2833+ var old = expr, result = [], curLoop = set, match, anyFound,
 2834+ isXMLFilter = set && set[0] && isXML(set[0]);
 2835+
 2836+ while ( expr && set.length ) {
 2837+ for ( var type in Expr.filter ) {
 2838+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
 2839+ var filter = Expr.filter[ type ], found, item, left = match[1];
 2840+ anyFound = false;
 2841+
 2842+ match.splice(1,1);
 2843+
 2844+ if ( left.substr( left.length - 1 ) === "\\" ) {
 2845+ continue;
 2846+ }
 2847+
 2848+ if ( curLoop === result ) {
 2849+ result = [];
 2850+ }
 2851+
 2852+ if ( Expr.preFilter[ type ] ) {
 2853+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
 2854+
 2855+ if ( !match ) {
 2856+ anyFound = found = true;
 2857+ } else if ( match === true ) {
 2858+ continue;
 2859+ }
 2860+ }
 2861+
 2862+ if ( match ) {
 2863+ for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
 2864+ if ( item ) {
 2865+ found = filter( item, match, i, curLoop );
 2866+ var pass = not ^ !!found;
 2867+
 2868+ if ( inplace && found != null ) {
 2869+ if ( pass ) {
 2870+ anyFound = true;
 2871+ } else {
 2872+ curLoop[i] = false;
 2873+ }
 2874+ } else if ( pass ) {
 2875+ result.push( item );
 2876+ anyFound = true;
 2877+ }
 2878+ }
 2879+ }
 2880+ }
 2881+
 2882+ if ( found !== undefined ) {
 2883+ if ( !inplace ) {
 2884+ curLoop = result;
 2885+ }
 2886+
 2887+ expr = expr.replace( Expr.match[ type ], "" );
 2888+
 2889+ if ( !anyFound ) {
 2890+ return [];
 2891+ }
 2892+
 2893+ break;
 2894+ }
 2895+ }
 2896+ }
 2897+
 2898+ // Improper expression
 2899+ if ( expr === old ) {
 2900+ if ( anyFound == null ) {
 2901+ Sizzle.error( expr );
 2902+ } else {
 2903+ break;
 2904+ }
 2905+ }
 2906+
 2907+ old = expr;
 2908+ }
 2909+
 2910+ return curLoop;
 2911+};
 2912+
 2913+Sizzle.error = function( msg ) {
 2914+ throw "Syntax error, unrecognized expression: " + msg;
 2915+};
 2916+
 2917+var Expr = Sizzle.selectors = {
 2918+ order: [ "ID", "NAME", "TAG" ],
 2919+ match: {
 2920+ ID: /#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
 2921+ CLASS: /\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
 2922+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,
 2923+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,
 2924+ TAG: /^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,
 2925+ CHILD: /:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,
 2926+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,
 2927+ PSEUDO: /:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
 2928+ },
 2929+ leftMatch: {},
 2930+ attrMap: {
 2931+ "class": "className",
 2932+ "for": "htmlFor"
 2933+ },
 2934+ attrHandle: {
 2935+ href: function(elem){
 2936+ return elem.getAttribute("href");
 2937+ }
 2938+ },
 2939+ relative: {
 2940+ "+": function(checkSet, part){
 2941+ var isPartStr = typeof part === "string",
 2942+ isTag = isPartStr && !/\W/.test(part),
 2943+ isPartStrNotTag = isPartStr && !isTag;
 2944+
 2945+ if ( isTag ) {
 2946+ part = part.toLowerCase();
 2947+ }
 2948+
 2949+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
 2950+ if ( (elem = checkSet[i]) ) {
 2951+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
 2952+
 2953+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
 2954+ elem || false :
 2955+ elem === part;
 2956+ }
 2957+ }
 2958+
 2959+ if ( isPartStrNotTag ) {
 2960+ Sizzle.filter( part, checkSet, true );
 2961+ }
 2962+ },
 2963+ ">": function(checkSet, part){
 2964+ var isPartStr = typeof part === "string";
 2965+
 2966+ if ( isPartStr && !/\W/.test(part) ) {
 2967+ part = part.toLowerCase();
 2968+
 2969+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 2970+ var elem = checkSet[i];
 2971+ if ( elem ) {
 2972+ var parent = elem.parentNode;
 2973+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
 2974+ }
 2975+ }
 2976+ } else {
 2977+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 2978+ var elem = checkSet[i];
 2979+ if ( elem ) {
 2980+ checkSet[i] = isPartStr ?
 2981+ elem.parentNode :
 2982+ elem.parentNode === part;
 2983+ }
 2984+ }
 2985+
 2986+ if ( isPartStr ) {
 2987+ Sizzle.filter( part, checkSet, true );
 2988+ }
 2989+ }
 2990+ },
 2991+ "": function(checkSet, part, isXML){
 2992+ var doneName = done++, checkFn = dirCheck;
 2993+
 2994+ if ( typeof part === "string" && !/\W/.test(part) ) {
 2995+ var nodeCheck = part = part.toLowerCase();
 2996+ checkFn = dirNodeCheck;
 2997+ }
 2998+
 2999+ checkFn("parentNode", part, doneName, checkSet, nodeCheck, isXML);
 3000+ },
 3001+ "~": function(checkSet, part, isXML){
 3002+ var doneName = done++, checkFn = dirCheck;
 3003+
 3004+ if ( typeof part === "string" && !/\W/.test(part) ) {
 3005+ var nodeCheck = part = part.toLowerCase();
 3006+ checkFn = dirNodeCheck;
 3007+ }
 3008+
 3009+ checkFn("previousSibling", part, doneName, checkSet, nodeCheck, isXML);
 3010+ }
 3011+ },
 3012+ find: {
 3013+ ID: function(match, context, isXML){
 3014+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
 3015+ var m = context.getElementById(match[1]);
 3016+ return m ? [m] : [];
 3017+ }
 3018+ },
 3019+ NAME: function(match, context){
 3020+ if ( typeof context.getElementsByName !== "undefined" ) {
 3021+ var ret = [], results = context.getElementsByName(match[1]);
 3022+
 3023+ for ( var i = 0, l = results.length; i < l; i++ ) {
 3024+ if ( results[i].getAttribute("name") === match[1] ) {
 3025+ ret.push( results[i] );
 3026+ }
 3027+ }
 3028+
 3029+ return ret.length === 0 ? null : ret;
 3030+ }
 3031+ },
 3032+ TAG: function(match, context){
 3033+ return context.getElementsByTagName(match[1]);
 3034+ }
 3035+ },
 3036+ preFilter: {
 3037+ CLASS: function(match, curLoop, inplace, result, not, isXML){
 3038+ match = " " + match[1].replace(/\\/g, "") + " ";
 3039+
 3040+ if ( isXML ) {
 3041+ return match;
 3042+ }
 3043+
 3044+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
 3045+ if ( elem ) {
 3046+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n]/g, " ").indexOf(match) >= 0) ) {
 3047+ if ( !inplace ) {
 3048+ result.push( elem );
 3049+ }
 3050+ } else if ( inplace ) {
 3051+ curLoop[i] = false;
 3052+ }
 3053+ }
 3054+ }
 3055+
 3056+ return false;
 3057+ },
 3058+ ID: function(match){
 3059+ return match[1].replace(/\\/g, "");
 3060+ },
 3061+ TAG: function(match, curLoop){
 3062+ return match[1].toLowerCase();
 3063+ },
 3064+ CHILD: function(match){
 3065+ if ( match[1] === "nth" ) {
 3066+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
 3067+ var test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
 3068+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
 3069+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
 3070+
 3071+ // calculate the numbers (first)n+(last) including if they are negative
 3072+ match[2] = (test[1] + (test[2] || 1)) - 0;
 3073+ match[3] = test[3] - 0;
 3074+ }
 3075+
 3076+ // TODO: Move to normal caching system
 3077+ match[0] = done++;
 3078+
 3079+ return match;
 3080+ },
 3081+ ATTR: function(match, curLoop, inplace, result, not, isXML){
 3082+ var name = match[1].replace(/\\/g, "");
 3083+
 3084+ if ( !isXML && Expr.attrMap[name] ) {
 3085+ match[1] = Expr.attrMap[name];
 3086+ }
 3087+
 3088+ if ( match[2] === "~=" ) {
 3089+ match[4] = " " + match[4] + " ";
 3090+ }
 3091+
 3092+ return match;
 3093+ },
 3094+ PSEUDO: function(match, curLoop, inplace, result, not){
 3095+ if ( match[1] === "not" ) {
 3096+ // If we're dealing with a complex expression, or a simple one
 3097+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
 3098+ match[3] = Sizzle(match[3], null, null, curLoop);
 3099+ } else {
 3100+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
 3101+ if ( !inplace ) {
 3102+ result.push.apply( result, ret );
 3103+ }
 3104+ return false;
 3105+ }
 3106+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
 3107+ return true;
 3108+ }
 3109+
 3110+ return match;
 3111+ },
 3112+ POS: function(match){
 3113+ match.unshift( true );
 3114+ return match;
 3115+ }
 3116+ },
 3117+ filters: {
 3118+ enabled: function(elem){
 3119+ return elem.disabled === false && elem.type !== "hidden";
 3120+ },
 3121+ disabled: function(elem){
 3122+ return elem.disabled === true;
 3123+ },
 3124+ checked: function(elem){
 3125+ return elem.checked === true;
 3126+ },
 3127+ selected: function(elem){
 3128+ // Accessing this property makes selected-by-default
 3129+ // options in Safari work properly
 3130+ elem.parentNode.selectedIndex;
 3131+ return elem.selected === true;
 3132+ },
 3133+ parent: function(elem){
 3134+ return !!elem.firstChild;
 3135+ },
 3136+ empty: function(elem){
 3137+ return !elem.firstChild;
 3138+ },
 3139+ has: function(elem, i, match){
 3140+ return !!Sizzle( match[3], elem ).length;
 3141+ },
 3142+ header: function(elem){
 3143+ return /h\d/i.test( elem.nodeName );
 3144+ },
 3145+ text: function(elem){
 3146+ return "text" === elem.type;
 3147+ },
 3148+ radio: function(elem){
 3149+ return "radio" === elem.type;
 3150+ },
 3151+ checkbox: function(elem){
 3152+ return "checkbox" === elem.type;
 3153+ },
 3154+ file: function(elem){
 3155+ return "file" === elem.type;
 3156+ },
 3157+ password: function(elem){
 3158+ return "password" === elem.type;
 3159+ },
 3160+ submit: function(elem){
 3161+ return "submit" === elem.type;
 3162+ },
 3163+ image: function(elem){
 3164+ return "image" === elem.type;
 3165+ },
 3166+ reset: function(elem){
 3167+ return "reset" === elem.type;
 3168+ },
 3169+ button: function(elem){
 3170+ return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
 3171+ },
 3172+ input: function(elem){
 3173+ return /input|select|textarea|button/i.test(elem.nodeName);
 3174+ }
 3175+ },
 3176+ setFilters: {
 3177+ first: function(elem, i){
 3178+ return i === 0;
 3179+ },
 3180+ last: function(elem, i, match, array){
 3181+ return i === array.length - 1;
 3182+ },
 3183+ even: function(elem, i){
 3184+ return i % 2 === 0;
 3185+ },
 3186+ odd: function(elem, i){
 3187+ return i % 2 === 1;
 3188+ },
 3189+ lt: function(elem, i, match){
 3190+ return i < match[3] - 0;
 3191+ },
 3192+ gt: function(elem, i, match){
 3193+ return i > match[3] - 0;
 3194+ },
 3195+ nth: function(elem, i, match){
 3196+ return match[3] - 0 === i;
 3197+ },
 3198+ eq: function(elem, i, match){
 3199+ return match[3] - 0 === i;
 3200+ }
 3201+ },
 3202+ filter: {
 3203+ PSEUDO: function(elem, match, i, array){
 3204+ var name = match[1], filter = Expr.filters[ name ];
 3205+
 3206+ if ( filter ) {
 3207+ return filter( elem, i, match, array );
 3208+ } else if ( name === "contains" ) {
 3209+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
 3210+ } else if ( name === "not" ) {
 3211+ var not = match[3];
 3212+
 3213+ for ( var i = 0, l = not.length; i < l; i++ ) {
 3214+ if ( not[i] === elem ) {
 3215+ return false;
 3216+ }
 3217+ }
 3218+
 3219+ return true;
 3220+ } else {
 3221+ Sizzle.error( "Syntax error, unrecognized expression: " + name );
 3222+ }
 3223+ },
 3224+ CHILD: function(elem, match){
 3225+ var type = match[1], node = elem;
 3226+ switch (type) {
 3227+ case 'only':
 3228+ case 'first':
 3229+ while ( (node = node.previousSibling) ) {
 3230+ if ( node.nodeType === 1 ) {
 3231+ return false;
 3232+ }
 3233+ }
 3234+ if ( type === "first" ) {
 3235+ return true;
 3236+ }
 3237+ node = elem;
 3238+ case 'last':
 3239+ while ( (node = node.nextSibling) ) {
 3240+ if ( node.nodeType === 1 ) {
 3241+ return false;
 3242+ }
 3243+ }
 3244+ return true;
 3245+ case 'nth':
 3246+ var first = match[2], last = match[3];
 3247+
 3248+ if ( first === 1 && last === 0 ) {
 3249+ return true;
 3250+ }
 3251+
 3252+ var doneName = match[0],
 3253+ parent = elem.parentNode;
 3254+
 3255+ if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
 3256+ var count = 0;
 3257+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
 3258+ if ( node.nodeType === 1 ) {
 3259+ node.nodeIndex = ++count;
 3260+ }
 3261+ }
 3262+ parent.sizcache = doneName;
 3263+ }
 3264+
 3265+ var diff = elem.nodeIndex - last;
 3266+ if ( first === 0 ) {
 3267+ return diff === 0;
 3268+ } else {
 3269+ return ( diff % first === 0 && diff / first >= 0 );
 3270+ }
 3271+ }
 3272+ },
 3273+ ID: function(elem, match){
 3274+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
 3275+ },
 3276+ TAG: function(elem, match){
 3277+ return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
 3278+ },
 3279+ CLASS: function(elem, match){
 3280+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
 3281+ .indexOf( match ) > -1;
 3282+ },
 3283+ ATTR: function(elem, match){
 3284+ var name = match[1],
 3285+ result = Expr.attrHandle[ name ] ?
 3286+ Expr.attrHandle[ name ]( elem ) :
 3287+ elem[ name ] != null ?
 3288+ elem[ name ] :
 3289+ elem.getAttribute( name ),
 3290+ value = result + "",
 3291+ type = match[2],
 3292+ check = match[4];
 3293+
 3294+ return result == null ?
 3295+ type === "!=" :
 3296+ type === "=" ?
 3297+ value === check :
 3298+ type === "*=" ?
 3299+ value.indexOf(check) >= 0 :
 3300+ type === "~=" ?
 3301+ (" " + value + " ").indexOf(check) >= 0 :
 3302+ !check ?
 3303+ value && result !== false :
 3304+ type === "!=" ?
 3305+ value !== check :
 3306+ type === "^=" ?
 3307+ value.indexOf(check) === 0 :
 3308+ type === "$=" ?
 3309+ value.substr(value.length - check.length) === check :
 3310+ type === "|=" ?
 3311+ value === check || value.substr(0, check.length + 1) === check + "-" :
 3312+ false;
 3313+ },
 3314+ POS: function(elem, match, i, array){
 3315+ var name = match[2], filter = Expr.setFilters[ name ];
 3316+
 3317+ if ( filter ) {
 3318+ return filter( elem, i, match, array );
 3319+ }
 3320+ }
 3321+ }
 3322+};
 3323+
 3324+var origPOS = Expr.match.POS;
 3325+
 3326+for ( var type in Expr.match ) {
 3327+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + /(?![^\[]*\])(?![^\(]*\))/.source );
 3328+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, function(all, num){
 3329+ return "\\" + (num - 0 + 1);
 3330+ }));
 3331+}
 3332+
 3333+var makeArray = function(array, results) {
 3334+ array = Array.prototype.slice.call( array, 0 );
 3335+
 3336+ if ( results ) {
 3337+ results.push.apply( results, array );
 3338+ return results;
 3339+ }
 3340+
 3341+ return array;
 3342+};
 3343+
 3344+// Perform a simple check to determine if the browser is capable of
 3345+// converting a NodeList to an array using builtin methods.
 3346+// Also verifies that the returned array holds DOM nodes
 3347+// (which is not the case in the Blackberry browser)
 3348+try {
 3349+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
 3350+
 3351+// Provide a fallback method if it does not work
 3352+} catch(e){
 3353+ makeArray = function(array, results) {
 3354+ var ret = results || [];
 3355+
 3356+ if ( toString.call(array) === "[object Array]" ) {
 3357+ Array.prototype.push.apply( ret, array );
 3358+ } else {
 3359+ if ( typeof array.length === "number" ) {
 3360+ for ( var i = 0, l = array.length; i < l; i++ ) {
 3361+ ret.push( array[i] );
 3362+ }
 3363+ } else {
 3364+ for ( var i = 0; array[i]; i++ ) {
 3365+ ret.push( array[i] );
 3366+ }
 3367+ }
 3368+ }
 3369+
 3370+ return ret;
 3371+ };
 3372+}
 3373+
 3374+var sortOrder;
 3375+
 3376+if ( document.documentElement.compareDocumentPosition ) {
 3377+ sortOrder = function( a, b ) {
 3378+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
 3379+ if ( a == b ) {
 3380+ hasDuplicate = true;
 3381+ }
 3382+ return a.compareDocumentPosition ? -1 : 1;
 3383+ }
 3384+
 3385+ var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
 3386+ if ( ret === 0 ) {
 3387+ hasDuplicate = true;
 3388+ }
 3389+ return ret;
 3390+ };
 3391+} else if ( "sourceIndex" in document.documentElement ) {
 3392+ sortOrder = function( a, b ) {
 3393+ if ( !a.sourceIndex || !b.sourceIndex ) {
 3394+ if ( a == b ) {
 3395+ hasDuplicate = true;
 3396+ }
 3397+ return a.sourceIndex ? -1 : 1;
 3398+ }
 3399+
 3400+ var ret = a.sourceIndex - b.sourceIndex;
 3401+ if ( ret === 0 ) {
 3402+ hasDuplicate = true;
 3403+ }
 3404+ return ret;
 3405+ };
 3406+} else if ( document.createRange ) {
 3407+ sortOrder = function( a, b ) {
 3408+ if ( !a.ownerDocument || !b.ownerDocument ) {
 3409+ if ( a == b ) {
 3410+ hasDuplicate = true;
 3411+ }
 3412+ return a.ownerDocument ? -1 : 1;
 3413+ }
 3414+
 3415+ var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
 3416+ aRange.setStart(a, 0);
 3417+ aRange.setEnd(a, 0);
 3418+ bRange.setStart(b, 0);
 3419+ bRange.setEnd(b, 0);
 3420+ var ret = aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
 3421+ if ( ret === 0 ) {
 3422+ hasDuplicate = true;
 3423+ }
 3424+ return ret;
 3425+ };
 3426+}
 3427+
 3428+// Utility function for retreiving the text value of an array of DOM nodes
 3429+function getText( elems ) {
 3430+ var ret = "", elem;
 3431+
 3432+ for ( var i = 0; elems[i]; i++ ) {
 3433+ elem = elems[i];
 3434+
 3435+ // Get the text from text nodes and CDATA nodes
 3436+ if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
 3437+ ret += elem.nodeValue;
 3438+
 3439+ // Traverse everything else, except comment nodes
 3440+ } else if ( elem.nodeType !== 8 ) {
 3441+ ret += getText( elem.childNodes );
 3442+ }
 3443+ }
 3444+
 3445+ return ret;
 3446+}
 3447+
 3448+// Check to see if the browser returns elements by name when
 3449+// querying by getElementById (and provide a workaround)
 3450+(function(){
 3451+ // We're going to inject a fake input element with a specified name
 3452+ var form = document.createElement("div"),
 3453+ id = "script" + (new Date).getTime();
 3454+ form.innerHTML = "<a name='" + id + "'/>";
 3455+
 3456+ // Inject it into the root element, check its status, and remove it quickly
 3457+ var root = document.documentElement;
 3458+ root.insertBefore( form, root.firstChild );
 3459+
 3460+ // The workaround has to do additional checks after a getElementById
 3461+ // Which slows things down for other browsers (hence the branching)
 3462+ if ( document.getElementById( id ) ) {
 3463+ Expr.find.ID = function(match, context, isXML){
 3464+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
 3465+ var m = context.getElementById(match[1]);
 3466+ return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : [];
 3467+ }
 3468+ };
 3469+
 3470+ Expr.filter.ID = function(elem, match){
 3471+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
 3472+ return elem.nodeType === 1 && node && node.nodeValue === match;
 3473+ };
 3474+ }
 3475+
 3476+ root.removeChild( form );
 3477+ root = form = null; // release memory in IE
 3478+})();
 3479+
 3480+(function(){
 3481+ // Check to see if the browser returns only elements
 3482+ // when doing getElementsByTagName("*")
 3483+
 3484+ // Create a fake element
 3485+ var div = document.createElement("div");
 3486+ div.appendChild( document.createComment("") );
 3487+
 3488+ // Make sure no comments are found
 3489+ if ( div.getElementsByTagName("*").length > 0 ) {
 3490+ Expr.find.TAG = function(match, context){
 3491+ var results = context.getElementsByTagName(match[1]);
 3492+
 3493+ // Filter out possible comments
 3494+ if ( match[1] === "*" ) {
 3495+ var tmp = [];
 3496+
 3497+ for ( var i = 0; results[i]; i++ ) {
 3498+ if ( results[i].nodeType === 1 ) {
 3499+ tmp.push( results[i] );
 3500+ }
 3501+ }
 3502+
 3503+ results = tmp;
 3504+ }
 3505+
 3506+ return results;
 3507+ };
 3508+ }
 3509+
 3510+ // Check to see if an attribute returns normalized href attributes
 3511+ div.innerHTML = "<a href='#'></a>";
 3512+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
 3513+ div.firstChild.getAttribute("href") !== "#" ) {
 3514+ Expr.attrHandle.href = function(elem){
 3515+ return elem.getAttribute("href", 2);
 3516+ };
 3517+ }
 3518+
 3519+ div = null; // release memory in IE
 3520+})();
 3521+
 3522+if ( document.querySelectorAll ) {
 3523+ (function(){
 3524+ var oldSizzle = Sizzle, div = document.createElement("div");
 3525+ div.innerHTML = "<p class='TEST'></p>";
 3526+
 3527+ // Safari can't handle uppercase or unicode characters when
 3528+ // in quirks mode.
 3529+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
 3530+ return;
 3531+ }
 3532+
 3533+ Sizzle = function(query, context, extra, seed){
 3534+ context = context || document;
 3535+
 3536+ // Only use querySelectorAll on non-XML documents
 3537+ // (ID selectors don't work in non-HTML documents)
 3538+ if ( !seed && context.nodeType === 9 && !isXML(context) ) {
 3539+ try {
 3540+ return makeArray( context.querySelectorAll(query), extra );
 3541+ } catch(e){}
 3542+ }
 3543+
 3544+ return oldSizzle(query, context, extra, seed);
 3545+ };
 3546+
 3547+ for ( var prop in oldSizzle ) {
 3548+ Sizzle[ prop ] = oldSizzle[ prop ];
 3549+ }
 3550+
 3551+ div = null; // release memory in IE
 3552+ })();
 3553+}
 3554+
 3555+(function(){
 3556+ var div = document.createElement("div");
 3557+
 3558+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
 3559+
 3560+ // Opera can't find a second classname (in 9.6)
 3561+ // Also, make sure that getElementsByClassName actually exists
 3562+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
 3563+ return;
 3564+ }
 3565+
 3566+ // Safari caches class attributes, doesn't catch changes (in 3.2)
 3567+ div.lastChild.className = "e";
 3568+
 3569+ if ( div.getElementsByClassName("e").length === 1 ) {
 3570+ return;
 3571+ }
 3572+
 3573+ Expr.order.splice(1, 0, "CLASS");
 3574+ Expr.find.CLASS = function(match, context, isXML) {
 3575+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
 3576+ return context.getElementsByClassName(match[1]);
 3577+ }
 3578+ };
 3579+
 3580+ div = null; // release memory in IE
 3581+})();
 3582+
 3583+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
 3584+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 3585+ var elem = checkSet[i];
 3586+ if ( elem ) {
 3587+ elem = elem[dir];
 3588+ var match = false;
 3589+
 3590+ while ( elem ) {
 3591+ if ( elem.sizcache === doneName ) {
 3592+ match = checkSet[elem.sizset];
 3593+ break;
 3594+ }
 3595+
 3596+ if ( elem.nodeType === 1 && !isXML ){
 3597+ elem.sizcache = doneName;
 3598+ elem.sizset = i;
 3599+ }
 3600+
 3601+ if ( elem.nodeName.toLowerCase() === cur ) {
 3602+ match = elem;
 3603+ break;
 3604+ }
 3605+
 3606+ elem = elem[dir];
 3607+ }
 3608+
 3609+ checkSet[i] = match;
 3610+ }
 3611+ }
 3612+}
 3613+
 3614+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
 3615+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
 3616+ var elem = checkSet[i];
 3617+ if ( elem ) {
 3618+ elem = elem[dir];
 3619+ var match = false;
 3620+
 3621+ while ( elem ) {
 3622+ if ( elem.sizcache === doneName ) {
 3623+ match = checkSet[elem.sizset];
 3624+ break;
 3625+ }
 3626+
 3627+ if ( elem.nodeType === 1 ) {
 3628+ if ( !isXML ) {
 3629+ elem.sizcache = doneName;
 3630+ elem.sizset = i;
 3631+ }
 3632+ if ( typeof cur !== "string" ) {
 3633+ if ( elem === cur ) {
 3634+ match = true;
 3635+ break;
 3636+ }
 3637+
 3638+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
 3639+ match = elem;
 3640+ break;
 3641+ }
 3642+ }
 3643+
 3644+ elem = elem[dir];
 3645+ }
 3646+
 3647+ checkSet[i] = match;
 3648+ }
 3649+ }
 3650+}
 3651+
 3652+var contains = document.compareDocumentPosition ? function(a, b){
 3653+ return !!(a.compareDocumentPosition(b) & 16);
 3654+} : function(a, b){
 3655+ return a !== b && (a.contains ? a.contains(b) : true);
 3656+};
 3657+
 3658+var isXML = function(elem){
 3659+ // documentElement is verified for cases where it doesn't yet exist
 3660+ // (such as loading iframes in IE - #4833)
 3661+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
 3662+ return documentElement ? documentElement.nodeName !== "HTML" : false;
 3663+};
 3664+
 3665+var posProcess = function(selector, context){
 3666+ var tmpSet = [], later = "", match,
 3667+ root = context.nodeType ? [context] : context;
 3668+
 3669+ // Position selectors must be done after the filter
 3670+ // And so must :not(positional) so we move all PSEUDOs to the end
 3671+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
 3672+ later += match[0];
 3673+ selector = selector.replace( Expr.match.PSEUDO, "" );
 3674+ }
 3675+
 3676+ selector = Expr.relative[selector] ? selector + "*" : selector;
 3677+
 3678+ for ( var i = 0, l = root.length; i < l; i++ ) {
 3679+ Sizzle( selector, root[i], tmpSet );
 3680+ }
 3681+
 3682+ return Sizzle.filter( later, tmpSet );
 3683+};
 3684+
 3685+// EXPOSE
 3686+jQuery.find = Sizzle;
 3687+jQuery.expr = Sizzle.selectors;
 3688+jQuery.expr[":"] = jQuery.expr.filters;
 3689+jQuery.unique = Sizzle.uniqueSort;
 3690+jQuery.text = getText;
 3691+jQuery.isXMLDoc = isXML;
 3692+jQuery.contains = contains;
 3693+
 3694+return;
 3695+
 3696+window.Sizzle = Sizzle;
 3697+
 3698+})();
 3699+var runtil = /Until$/,
 3700+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
 3701+ // Note: This RegExp should be improved, or likely pulled from Sizzle
 3702+ rmultiselector = /,/,
 3703+ slice = Array.prototype.slice;
 3704+
 3705+// Implement the identical functionality for filter and not
 3706+var winnow = function( elements, qualifier, keep ) {
 3707+ if ( jQuery.isFunction( qualifier ) ) {
 3708+ return jQuery.grep(elements, function( elem, i ) {
 3709+ return !!qualifier.call( elem, i, elem ) === keep;
 3710+ });
 3711+
 3712+ } else if ( qualifier.nodeType ) {
 3713+ return jQuery.grep(elements, function( elem, i ) {
 3714+ return (elem === qualifier) === keep;
 3715+ });
 3716+
 3717+ } else if ( typeof qualifier === "string" ) {
 3718+ var filtered = jQuery.grep(elements, function( elem ) {
 3719+ return elem.nodeType === 1;
 3720+ });
 3721+
 3722+ if ( isSimple.test( qualifier ) ) {
 3723+ return jQuery.filter(qualifier, filtered, !keep);
 3724+ } else {
 3725+ qualifier = jQuery.filter( qualifier, filtered );
 3726+ }
 3727+ }
 3728+
 3729+ return jQuery.grep(elements, function( elem, i ) {
 3730+ return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
 3731+ });
 3732+};
 3733+
 3734+jQuery.fn.extend({
 3735+ find: function( selector ) {
 3736+ var ret = this.pushStack( "", "find", selector ), length = 0;
 3737+
 3738+ for ( var i = 0, l = this.length; i < l; i++ ) {
 3739+ length = ret.length;
 3740+ jQuery.find( selector, this[i], ret );
 3741+
 3742+ if ( i > 0 ) {
 3743+ // Make sure that the results are unique
 3744+ for ( var n = length; n < ret.length; n++ ) {
 3745+ for ( var r = 0; r < length; r++ ) {
 3746+ if ( ret[r] === ret[n] ) {
 3747+ ret.splice(n--, 1);
 3748+ break;
 3749+ }
 3750+ }
 3751+ }
 3752+ }
 3753+ }
 3754+
 3755+ return ret;
 3756+ },
 3757+
 3758+ has: function( target ) {
 3759+ var targets = jQuery( target );
 3760+ return this.filter(function() {
 3761+ for ( var i = 0, l = targets.length; i < l; i++ ) {
 3762+ if ( jQuery.contains( this, targets[i] ) ) {
 3763+ return true;
 3764+ }
 3765+ }
 3766+ });
 3767+ },
 3768+
 3769+ not: function( selector ) {
 3770+ return this.pushStack( winnow(this, selector, false), "not", selector);
 3771+ },
 3772+
 3773+ filter: function( selector ) {
 3774+ return this.pushStack( winnow(this, selector, true), "filter", selector );
 3775+ },
 3776+
 3777+ is: function( selector ) {
 3778+ return !!selector && jQuery.filter( selector, this ).length > 0;
 3779+ },
 3780+
 3781+ closest: function( selectors, context ) {
 3782+ if ( jQuery.isArray( selectors ) ) {
 3783+ var ret = [], cur = this[0], match, matches = {}, selector;
 3784+
 3785+ if ( cur && selectors.length ) {
 3786+ for ( var i = 0, l = selectors.length; i < l; i++ ) {
 3787+ selector = selectors[i];
 3788+
 3789+ if ( !matches[selector] ) {
 3790+ matches[selector] = jQuery.expr.match.POS.test( selector ) ?
 3791+ jQuery( selector, context || this.context ) :
 3792+ selector;
 3793+ }
 3794+ }
 3795+
 3796+ while ( cur && cur.ownerDocument && cur !== context ) {
 3797+ for ( selector in matches ) {
 3798+ match = matches[selector];
 3799+
 3800+ if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
 3801+ ret.push({ selector: selector, elem: cur });
 3802+ delete matches[selector];
 3803+ }
 3804+ }
 3805+ cur = cur.parentNode;
 3806+ }
 3807+ }
 3808+
 3809+ return ret;
 3810+ }
 3811+
 3812+ var pos = jQuery.expr.match.POS.test( selectors ) ?
 3813+ jQuery( selectors, context || this.context ) : null;
 3814+
 3815+ return this.map(function( i, cur ) {
 3816+ while ( cur && cur.ownerDocument && cur !== context ) {
 3817+ if ( pos ? pos.index(cur) > -1 : jQuery(cur).is(selectors) ) {
 3818+ return cur;
 3819+ }
 3820+ cur = cur.parentNode;
 3821+ }
 3822+ return null;
 3823+ });
 3824+ },
 3825+
 3826+ // Determine the position of an element within
 3827+ // the matched set of elements
 3828+ index: function( elem ) {
 3829+ if ( !elem || typeof elem === "string" ) {
 3830+ return jQuery.inArray( this[0],
 3831+ // If it receives a string, the selector is used
 3832+ // If it receives nothing, the siblings are used
 3833+ elem ? jQuery( elem ) : this.parent().children() );
 3834+ }
 3835+ // Locate the position of the desired element
 3836+ return jQuery.inArray(
 3837+ // If it receives a jQuery object, the first element is used
 3838+ elem.jquery ? elem[0] : elem, this );
 3839+ },
 3840+
 3841+ add: function( selector, context ) {
 3842+ var set = typeof selector === "string" ?
 3843+ jQuery( selector, context || this.context ) :
 3844+ jQuery.makeArray( selector ),
 3845+ all = jQuery.merge( this.get(), set );
 3846+
 3847+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
 3848+ all :
 3849+ jQuery.unique( all ) );
 3850+ },
 3851+
 3852+ andSelf: function() {
 3853+ return this.add( this.prevObject );
 3854+ }
 3855+});
 3856+
 3857+// A painfully simple check to see if an element is disconnected
 3858+// from a document (should be improved, where feasible).
 3859+function isDisconnected( node ) {
 3860+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
 3861+}
 3862+
 3863+jQuery.each({
 3864+ parent: function( elem ) {
 3865+ var parent = elem.parentNode;
 3866+ return parent && parent.nodeType !== 11 ? parent : null;
 3867+ },
 3868+ parents: function( elem ) {
 3869+ return jQuery.dir( elem, "parentNode" );
 3870+ },
 3871+ parentsUntil: function( elem, i, until ) {
 3872+ return jQuery.dir( elem, "parentNode", until );
 3873+ },
 3874+ next: function( elem ) {
 3875+ return jQuery.nth( elem, 2, "nextSibling" );
 3876+ },
 3877+ prev: function( elem ) {
 3878+ return jQuery.nth( elem, 2, "previousSibling" );
 3879+ },
 3880+ nextAll: function( elem ) {
 3881+ return jQuery.dir( elem, "nextSibling" );
 3882+ },
 3883+ prevAll: function( elem ) {
 3884+ return jQuery.dir( elem, "previousSibling" );
 3885+ },
 3886+ nextUntil: function( elem, i, until ) {
 3887+ return jQuery.dir( elem, "nextSibling", until );
 3888+ },
 3889+ prevUntil: function( elem, i, until ) {
 3890+ return jQuery.dir( elem, "previousSibling", until );
 3891+ },
 3892+ siblings: function( elem ) {
 3893+ return jQuery.sibling( elem.parentNode.firstChild, elem );
 3894+ },
 3895+ children: function( elem ) {
 3896+ return jQuery.sibling( elem.firstChild );
 3897+ },
 3898+ contents: function( elem ) {
 3899+ return jQuery.nodeName( elem, "iframe" ) ?
 3900+ elem.contentDocument || elem.contentWindow.document :
 3901+ jQuery.makeArray( elem.childNodes );
 3902+ }
 3903+}, function( name, fn ) {
 3904+ jQuery.fn[ name ] = function( until, selector ) {
 3905+ var ret = jQuery.map( this, fn, until );
 3906+
 3907+ if ( !runtil.test( name ) ) {
 3908+ selector = until;
 3909+ }
 3910+
 3911+ if ( selector && typeof selector === "string" ) {
 3912+ ret = jQuery.filter( selector, ret );
 3913+ }
 3914+
 3915+ ret = this.length > 1 ? jQuery.unique( ret ) : ret;
 3916+
 3917+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
 3918+ ret = ret.reverse();
 3919+ }
 3920+
 3921+ return this.pushStack( ret, name, slice.call(arguments).join(",") );
 3922+ };
 3923+});
 3924+
 3925+jQuery.extend({
 3926+ filter: function( expr, elems, not ) {
 3927+ if ( not ) {
 3928+ expr = ":not(" + expr + ")";
 3929+ }
 3930+
 3931+ return jQuery.find.matches(expr, elems);
 3932+ },
 3933+
 3934+ dir: function( elem, dir, until ) {
 3935+ var matched = [], cur = elem[dir];
 3936+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
 3937+ if ( cur.nodeType === 1 ) {
 3938+ matched.push( cur );
 3939+ }
 3940+ cur = cur[dir];
 3941+ }
 3942+ return matched;
 3943+ },
 3944+
 3945+ nth: function( cur, result, dir, elem ) {
 3946+ result = result || 1;
 3947+ var num = 0;
 3948+
 3949+ for ( ; cur; cur = cur[dir] ) {
 3950+ if ( cur.nodeType === 1 && ++num === result ) {
 3951+ break;
 3952+ }
 3953+ }
 3954+
 3955+ return cur;
 3956+ },
 3957+
 3958+ sibling: function( n, elem ) {
 3959+ var r = [];
 3960+
 3961+ for ( ; n; n = n.nextSibling ) {
 3962+ if ( n.nodeType === 1 && n !== elem ) {
 3963+ r.push( n );
 3964+ }
 3965+ }
 3966+
 3967+ return r;
 3968+ }
 3969+});
 3970+var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
 3971+ rleadingWhitespace = /^\s+/,
 3972+ rxhtmlTag = /(<([\w:]+)[^>]*?)\/>/g,
 3973+ rselfClosing = /^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,
 3974+ rtagName = /<([\w:]+)/,
 3975+ rtbody = /<tbody/i,
 3976+ rhtml = /<|&#?\w+;/,
 3977+ rnocache = /<script|<object|<embed|<option|<style/i,
 3978+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, // checked="checked" or checked (html5)
 3979+ fcloseTag = function( all, front, tag ) {
 3980+ return rselfClosing.test( tag ) ?
 3981+ all :
 3982+ front + "></" + tag + ">";
 3983+ },
 3984+ wrapMap = {
 3985+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
 3986+ legend: [ 1, "<fieldset>", "</fieldset>" ],
 3987+ thead: [ 1, "<table>", "</table>" ],
 3988+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
 3989+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
 3990+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
 3991+ area: [ 1, "<map>", "</map>" ],
 3992+ _default: [ 0, "", "" ]
 3993+ };
 3994+
 3995+wrapMap.optgroup = wrapMap.option;
 3996+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
 3997+wrapMap.th = wrapMap.td;
 3998+
 3999+// IE can't serialize <link> and <script> tags normally
 4000+if ( !jQuery.support.htmlSerialize ) {
 4001+ wrapMap._default = [ 1, "div<div>", "</div>" ];
 4002+}
 4003+
 4004+jQuery.fn.extend({
 4005+ text: function( text ) {
 4006+ if ( jQuery.isFunction(text) ) {
 4007+ return this.each(function(i) {
 4008+ var self = jQuery(this);
 4009+ self.text( text.call(this, i, self.text()) );
 4010+ });
 4011+ }
 4012+
 4013+ if ( typeof text !== "object" && text !== undefined ) {
 4014+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
 4015+ }
 4016+
 4017+ return jQuery.text( this );
 4018+ },
 4019+
 4020+ wrapAll: function( html ) {
 4021+ if ( jQuery.isFunction( html ) ) {
 4022+ return this.each(function(i) {
 4023+ jQuery(this).wrapAll( html.call(this, i) );
 4024+ });
 4025+ }
 4026+
 4027+ if ( this[0] ) {
 4028+ // The elements to wrap the target around
 4029+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
 4030+
 4031+ if ( this[0].parentNode ) {
 4032+ wrap.insertBefore( this[0] );
 4033+ }
 4034+
 4035+ wrap.map(function() {
 4036+ var elem = this;
 4037+
 4038+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
 4039+ elem = elem.firstChild;
 4040+ }
 4041+
 4042+ return elem;
 4043+ }).append(this);
 4044+ }
 4045+
 4046+ return this;
 4047+ },
 4048+
 4049+ wrapInner: function( html ) {
 4050+ if ( jQuery.isFunction( html ) ) {
 4051+ return this.each(function(i) {
 4052+ jQuery(this).wrapInner( html.call(this, i) );
 4053+ });
 4054+ }
 4055+
 4056+ return this.each(function() {
 4057+ var self = jQuery( this ), contents = self.contents();
 4058+
 4059+ if ( contents.length ) {
 4060+ contents.wrapAll( html );
 4061+
 4062+ } else {
 4063+ self.append( html );
 4064+ }
 4065+ });
 4066+ },
 4067+
 4068+ wrap: function( html ) {
 4069+ return this.each(function() {
 4070+ jQuery( this ).wrapAll( html );
 4071+ });
 4072+ },
 4073+
 4074+ unwrap: function() {
 4075+ return this.parent().each(function() {
 4076+ if ( !jQuery.nodeName( this, "body" ) ) {
 4077+ jQuery( this ).replaceWith( this.childNodes );
 4078+ }
 4079+ }).end();
 4080+ },
 4081+
 4082+ append: function() {
 4083+ return this.domManip(arguments, true, function( elem ) {
 4084+ if ( this.nodeType === 1 ) {
 4085+ this.appendChild( elem );
 4086+ }
 4087+ });
 4088+ },
 4089+
 4090+ prepend: function() {
 4091+ return this.domManip(arguments, true, function( elem ) {
 4092+ if ( this.nodeType === 1 ) {
 4093+ this.insertBefore( elem, this.firstChild );
 4094+ }
 4095+ });
 4096+ },
 4097+
 4098+ before: function() {
 4099+ if ( this[0] && this[0].parentNode ) {
 4100+ return this.domManip(arguments, false, function( elem ) {
 4101+ this.parentNode.insertBefore( elem, this );
 4102+ });
 4103+ } else if ( arguments.length ) {
 4104+ var set = jQuery(arguments[0]);
 4105+ set.push.apply( set, this.toArray() );
 4106+ return this.pushStack( set, "before", arguments );
 4107+ }
 4108+ },
 4109+
 4110+ after: function() {
 4111+ if ( this[0] && this[0].parentNode ) {
 4112+ return this.domManip(arguments, false, function( elem ) {
 4113+ this.parentNode.insertBefore( elem, this.nextSibling );
 4114+ });
 4115+ } else if ( arguments.length ) {
 4116+ var set = this.pushStack( this, "after", arguments );
 4117+ set.push.apply( set, jQuery(arguments[0]).toArray() );
 4118+ return set;
 4119+ }
 4120+ },
 4121+
 4122+ // keepData is for internal use only--do not document
 4123+ remove: function( selector, keepData ) {
 4124+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
 4125+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
 4126+ if ( !keepData && elem.nodeType === 1 ) {
 4127+ jQuery.cleanData( elem.getElementsByTagName("*") );
 4128+ jQuery.cleanData( [ elem ] );
 4129+ }
 4130+
 4131+ if ( elem.parentNode ) {
 4132+ elem.parentNode.removeChild( elem );
 4133+ }
 4134+ }
 4135+ }
 4136+
 4137+ return this;
 4138+ },
 4139+
 4140+ empty: function() {
 4141+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
 4142+ // Remove element nodes and prevent memory leaks
 4143+ if ( elem.nodeType === 1 ) {
 4144+ jQuery.cleanData( elem.getElementsByTagName("*") );
 4145+ }
 4146+
 4147+ // Remove any remaining nodes
 4148+ while ( elem.firstChild ) {
 4149+ elem.removeChild( elem.firstChild );
 4150+ }
 4151+ }
 4152+
 4153+ return this;
 4154+ },
 4155+
 4156+ clone: function( events ) {
 4157+ // Do the clone
 4158+ var ret = this.map(function() {
 4159+ if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
 4160+ // IE copies events bound via attachEvent when
 4161+ // using cloneNode. Calling detachEvent on the
 4162+ // clone will also remove the events from the orignal
 4163+ // In order to get around this, we use innerHTML.
 4164+ // Unfortunately, this means some modifications to
 4165+ // attributes in IE that are actually only stored
 4166+ // as properties will not be copied (such as the
 4167+ // the name attribute on an input).
 4168+ var html = this.outerHTML, ownerDocument = this.ownerDocument;
 4169+ if ( !html ) {
 4170+ var div = ownerDocument.createElement("div");
 4171+ div.appendChild( this.cloneNode(true) );
 4172+ html = div.innerHTML;
 4173+ }
 4174+
 4175+ return jQuery.clean([html.replace(rinlinejQuery, "")
 4176+ // Handle the case in IE 8 where action=/test/> self-closes a tag
 4177+ .replace(/=([^="'>\s]+\/)>/g, '="$1">')
 4178+ .replace(rleadingWhitespace, "")], ownerDocument)[0];
 4179+ } else {
 4180+ return this.cloneNode(true);
 4181+ }
 4182+ });
 4183+
 4184+ // Copy the events from the original to the clone
 4185+ if ( events === true ) {
 4186+ cloneCopyEvent( this, ret );
 4187+ cloneCopyEvent( this.find("*"), ret.find("*") );
 4188+ }
 4189+
 4190+ // Return the cloned set
 4191+ return ret;
 4192+ },
 4193+
 4194+ html: function( value ) {
 4195+ if ( value === undefined ) {
 4196+ return this[0] && this[0].nodeType === 1 ?
 4197+ this[0].innerHTML.replace(rinlinejQuery, "") :
 4198+ null;
 4199+
 4200+ // See if we can take a shortcut and just use innerHTML
 4201+ } else if ( typeof value === "string" && !rnocache.test( value ) &&
 4202+ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
 4203+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
 4204+
 4205+ value = value.replace(rxhtmlTag, fcloseTag);
 4206+
 4207+ try {
 4208+ for ( var i = 0, l = this.length; i < l; i++ ) {
 4209+ // Remove element nodes and prevent memory leaks
 4210+ if ( this[i].nodeType === 1 ) {
 4211+ jQuery.cleanData( this[i].getElementsByTagName("*") );
 4212+ this[i].innerHTML = value;
 4213+ }
 4214+ }
 4215+
 4216+ // If using innerHTML throws an exception, use the fallback method
 4217+ } catch(e) {
 4218+ this.empty().append( value );
 4219+ }
 4220+
 4221+ } else if ( jQuery.isFunction( value ) ) {
 4222+ this.each(function(i){
 4223+ var self = jQuery(this), old = self.html();
 4224+ self.empty().append(function(){
 4225+ return value.call( this, i, old );
 4226+ });
 4227+ });
 4228+
 4229+ } else {
 4230+ this.empty().append( value );
 4231+ }
 4232+
 4233+ return this;
 4234+ },
 4235+
 4236+ replaceWith: function( value ) {
 4237+ if ( this[0] && this[0].parentNode ) {
 4238+ // Make sure that the elements are removed from the DOM before they are inserted
 4239+ // this can help fix replacing a parent with child elements
 4240+ if ( jQuery.isFunction( value ) ) {
 4241+ return this.each(function(i) {
 4242+ var self = jQuery(this), old = self.html();
 4243+ self.replaceWith( value.call( this, i, old ) );
 4244+ });
 4245+ }
 4246+
 4247+ if ( typeof value !== "string" ) {
 4248+ value = jQuery(value).detach();
 4249+ }
 4250+
 4251+ return this.each(function() {
 4252+ var next = this.nextSibling, parent = this.parentNode;
 4253+
 4254+ jQuery(this).remove();
 4255+
 4256+ if ( next ) {
 4257+ jQuery(next).before( value );
 4258+ } else {
 4259+ jQuery(parent).append( value );
 4260+ }
 4261+ });
 4262+ } else {
 4263+ return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
 4264+ }
 4265+ },
 4266+
 4267+ detach: function( selector ) {
 4268+ return this.remove( selector, true );
 4269+ },
 4270+
 4271+ domManip: function( args, table, callback ) {
 4272+ var results, first, value = args[0], scripts = [], fragment, parent;
 4273+
 4274+ // We can't cloneNode fragments that contain checked, in WebKit
 4275+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
 4276+ return this.each(function() {
 4277+ jQuery(this).domManip( args, table, callback, true );
 4278+ });
 4279+ }
 4280+
 4281+ if ( jQuery.isFunction(value) ) {
 4282+ return this.each(function(i) {
 4283+ var self = jQuery(this);
 4284+ args[0] = value.call(this, i, table ? self.html() : undefined);
 4285+ self.domManip( args, table, callback );
 4286+ });
 4287+ }
 4288+
 4289+ if ( this[0] ) {
 4290+ parent = value && value.parentNode;
 4291+
 4292+ // If we're in a fragment, just use that instead of building a new one
 4293+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
 4294+ results = { fragment: parent };
 4295+
 4296+ } else {
 4297+ results = buildFragment( args, this, scripts );
 4298+ }
 4299+
 4300+ fragment = results.fragment;
 4301+
 4302+ if ( fragment.childNodes.length === 1 ) {
 4303+ first = fragment = fragment.firstChild;
 4304+ } else {
 4305+ first = fragment.firstChild;
 4306+ }
 4307+
 4308+ if ( first ) {
 4309+ table = table && jQuery.nodeName( first, "tr" );
 4310+
 4311+ for ( var i = 0, l = this.length; i < l; i++ ) {
 4312+ callback.call(
 4313+ table ?
 4314+ root(this[i], first) :
 4315+ this[i],
 4316+ i > 0 || results.cacheable || this.length > 1 ?
 4317+ fragment.cloneNode(true) :
 4318+ fragment
 4319+ );
 4320+ }
 4321+ }
 4322+
 4323+ if ( scripts.length ) {
 4324+ jQuery.each( scripts, evalScript );
 4325+ }
 4326+ }
 4327+
 4328+ return this;
 4329+
 4330+ function root( elem, cur ) {
 4331+ return jQuery.nodeName(elem, "table") ?
 4332+ (elem.getElementsByTagName("tbody")[0] ||
 4333+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
 4334+ elem;
 4335+ }
 4336+ }
 4337+});
 4338+
 4339+function cloneCopyEvent(orig, ret) {
 4340+ var i = 0;
 4341+
 4342+ ret.each(function() {
 4343+ if ( this.nodeName !== (orig[i] && orig[i].nodeName) ) {
 4344+ return;
 4345+ }
 4346+
 4347+ var oldData = jQuery.data( orig[i++] ), curData = jQuery.data( this, oldData ), events = oldData && oldData.events;
 4348+
 4349+ if ( events ) {
 4350+ delete curData.handle;
 4351+ curData.events = {};
 4352+
 4353+ for ( var type in events ) {
 4354+ for ( var handler in events[ type ] ) {
 4355+ jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
 4356+ }
 4357+ }
 4358+ }
 4359+ });
 4360+}
 4361+
 4362+function buildFragment( args, nodes, scripts ) {
 4363+ var fragment, cacheable, cacheresults,
 4364+ doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
 4365+
 4366+ // Only cache "small" (1/2 KB) strings that are associated with the main document
 4367+ // Cloning options loses the selected state, so don't cache them
 4368+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
 4369+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
 4370+ if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
 4371+ !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
 4372+
 4373+ cacheable = true;
 4374+ cacheresults = jQuery.fragments[ args[0] ];
 4375+ if ( cacheresults ) {
 4376+ if ( cacheresults !== 1 ) {
 4377+ fragment = cacheresults;
 4378+ }
 4379+ }
 4380+ }
 4381+
 4382+ if ( !fragment ) {
 4383+ fragment = doc.createDocumentFragment();
 4384+ jQuery.clean( args, doc, fragment, scripts );
 4385+ }
 4386+
 4387+ if ( cacheable ) {
 4388+ jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
 4389+ }
 4390+
 4391+ return { fragment: fragment, cacheable: cacheable };
 4392+}
 4393+
 4394+jQuery.fragments = {};
 4395+
 4396+jQuery.each({
 4397+ appendTo: "append",
 4398+ prependTo: "prepend",
 4399+ insertBefore: "before",
 4400+ insertAfter: "after",
 4401+ replaceAll: "replaceWith"
 4402+}, function( name, original ) {
 4403+ jQuery.fn[ name ] = function( selector ) {
 4404+ var ret = [], insert = jQuery( selector ),
 4405+ parent = this.length === 1 && this[0].parentNode;
 4406+
 4407+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
 4408+ insert[ original ]( this[0] );
 4409+ return this;
 4410+
 4411+ } else {
 4412+ for ( var i = 0, l = insert.length; i < l; i++ ) {
 4413+ var elems = (i > 0 ? this.clone(true) : this).get();
 4414+ jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
 4415+ ret = ret.concat( elems );
 4416+ }
 4417+
 4418+ return this.pushStack( ret, name, insert.selector );
 4419+ }
 4420+ };
 4421+});
 4422+
 4423+jQuery.extend({
 4424+ clean: function( elems, context, fragment, scripts ) {
 4425+ context = context || document;
 4426+
 4427+ // !context.createElement fails in IE with an error but returns typeof 'object'
 4428+ if ( typeof context.createElement === "undefined" ) {
 4429+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
 4430+ }
 4431+
 4432+ var ret = [];
 4433+
 4434+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
 4435+ if ( typeof elem === "number" ) {
 4436+ elem += "";
 4437+ }
 4438+
 4439+ if ( !elem ) {
 4440+ continue;
 4441+ }
 4442+
 4443+ // Convert html string into DOM nodes
 4444+ if ( typeof elem === "string" && !rhtml.test( elem ) ) {
 4445+ elem = context.createTextNode( elem );
 4446+
 4447+ } else if ( typeof elem === "string" ) {
 4448+ // Fix "XHTML"-style tags in all browsers
 4449+ elem = elem.replace(rxhtmlTag, fcloseTag);
 4450+
 4451+ // Trim whitespace, otherwise indexOf won't work as expected
 4452+ var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
 4453+ wrap = wrapMap[ tag ] || wrapMap._default,
 4454+ depth = wrap[0],
 4455+ div = context.createElement("div");
 4456+
 4457+ // Go to html and back, then peel off extra wrappers
 4458+ div.innerHTML = wrap[1] + elem + wrap[2];
 4459+
 4460+ // Move to the right depth
 4461+ while ( depth-- ) {
 4462+ div = div.lastChild;
 4463+ }
 4464+
 4465+ // Remove IE's autoinserted <tbody> from table fragments
 4466+ if ( !jQuery.support.tbody ) {
 4467+
 4468+ // String was a <table>, *may* have spurious <tbody>
 4469+ var hasBody = rtbody.test(elem),
 4470+ tbody = tag === "table" && !hasBody ?
 4471+ div.firstChild && div.firstChild.childNodes :
 4472+
 4473+ // String was a bare <thead> or <tfoot>
 4474+ wrap[1] === "<table>" && !hasBody ?
 4475+ div.childNodes :
 4476+ [];
 4477+
 4478+ for ( var j = tbody.length - 1; j >= 0 ; --j ) {
 4479+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
 4480+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
 4481+ }
 4482+ }
 4483+
 4484+ }
 4485+
 4486+ // IE completely kills leading whitespace when innerHTML is used
 4487+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
 4488+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
 4489+ }
 4490+
 4491+ elem = div.childNodes;
 4492+ }
 4493+
 4494+ if ( elem.nodeType ) {
 4495+ ret.push( elem );
 4496+ } else {
 4497+ ret = jQuery.merge( ret, elem );
 4498+ }
 4499+ }
 4500+
 4501+ if ( fragment ) {
 4502+ for ( var i = 0; ret[i]; i++ ) {
 4503+ if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
 4504+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
 4505+
 4506+ } else {
 4507+ if ( ret[i].nodeType === 1 ) {
 4508+ ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
 4509+ }
 4510+ fragment.appendChild( ret[i] );
 4511+ }
 4512+ }
 4513+ }
 4514+
 4515+ return ret;
 4516+ },
 4517+
 4518+ cleanData: function( elems ) {
 4519+ var data, id, cache = jQuery.cache,
 4520+ special = jQuery.event.special,
 4521+ deleteExpando = jQuery.support.deleteExpando;
 4522+
 4523+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
 4524+ id = elem[ jQuery.expando ];
 4525+
 4526+ if ( id ) {
 4527+ data = cache[ id ];
 4528+
 4529+ if ( data.events ) {
 4530+ for ( var type in data.events ) {
 4531+ if ( special[ type ] ) {
 4532+ jQuery.event.remove( elem, type );
 4533+
 4534+ } else {
 4535+ removeEvent( elem, type, data.handle );
 4536+ }
 4537+ }
 4538+ }
 4539+
 4540+ if ( deleteExpando ) {
 4541+ delete elem[ jQuery.expando ];
 4542+
 4543+ } else if ( elem.removeAttribute ) {
 4544+ elem.removeAttribute( jQuery.expando );
 4545+ }
 4546+
 4547+ delete cache[ id ];
 4548+ }
 4549+ }
 4550+ }
 4551+});
 4552+// exclude the following css properties to add px
 4553+var rexclude = /z-?index|font-?weight|opacity|zoom|line-?height/i,
 4554+ ralpha = /alpha\([^)]*\)/,
 4555+ ropacity = /opacity=([^)]*)/,
 4556+ rfloat = /float/i,
 4557+ rdashAlpha = /-([a-z])/ig,
 4558+ rupper = /([A-Z])/g,
 4559+ rnumpx = /^-?\d+(?:px)?$/i,
 4560+ rnum = /^-?\d/,
 4561+
 4562+ cssShow = { position: "absolute", visibility: "hidden", display:"block" },
 4563+ cssWidth = [ "Left", "Right" ],
 4564+ cssHeight = [ "Top", "Bottom" ],
 4565+
 4566+ // cache check for defaultView.getComputedStyle
 4567+ getComputedStyle = document.defaultView && document.defaultView.getComputedStyle,
 4568+ // normalize float css property
 4569+ styleFloat = jQuery.support.cssFloat ? "cssFloat" : "styleFloat",
 4570+ fcamelCase = function( all, letter ) {
 4571+ return letter.toUpperCase();
 4572+ };
 4573+
 4574+jQuery.fn.css = function( name, value ) {
 4575+ return access( this, name, value, true, function( elem, name, value ) {
 4576+ if ( value === undefined ) {
 4577+ return jQuery.curCSS( elem, name );
 4578+ }
 4579+
 4580+ if ( typeof value === "number" && !rexclude.test(name) ) {
 4581+ value += "px";
 4582+ }
 4583+
 4584+ jQuery.style( elem, name, value );
 4585+ });
 4586+};
 4587+
 4588+jQuery.extend({
 4589+ style: function( elem, name, value ) {
 4590+ // don't set styles on text and comment nodes
 4591+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
 4592+ return undefined;
 4593+ }
 4594+
 4595+ // ignore negative width and height values #1599
 4596+ if ( (name === "width" || name === "height") && parseFloat(value) < 0 ) {
 4597+ value = undefined;
 4598+ }
 4599+
 4600+ var style = elem.style || elem, set = value !== undefined;
 4601+
 4602+ // IE uses filters for opacity
 4603+ if ( !jQuery.support.opacity && name === "opacity" ) {
 4604+ if ( set ) {
 4605+ // IE has trouble with opacity if it does not have layout
 4606+ // Force it by setting the zoom level
 4607+ style.zoom = 1;
 4608+
 4609+ // Set the alpha filter to set the opacity
 4610+ var opacity = parseInt( value, 10 ) + "" === "NaN" ? "" : "alpha(opacity=" + value * 100 + ")";
 4611+ var filter = style.filter || jQuery.curCSS( elem, "filter" ) || "";
 4612+ style.filter = ralpha.test(filter) ? filter.replace(ralpha, opacity) : opacity;
 4613+ }
 4614+
 4615+ return style.filter && style.filter.indexOf("opacity=") >= 0 ?
 4616+ (parseFloat( ropacity.exec(style.filter)[1] ) / 100) + "":
 4617+ "";
 4618+ }
 4619+
 4620+ // Make sure we're using the right name for getting the float value
 4621+ if ( rfloat.test( name ) ) {
 4622+ name = styleFloat;
 4623+ }
 4624+
 4625+ name = name.replace(rdashAlpha, fcamelCase);
 4626+
 4627+ if ( set ) {
 4628+ style[ name ] = value;
 4629+ }
 4630+
 4631+ return style[ name ];
 4632+ },
 4633+
 4634+ css: function( elem, name, force, extra ) {
 4635+ if ( name === "width" || name === "height" ) {
 4636+ var val, props = cssShow, which = name === "width" ? cssWidth : cssHeight;
 4637+
 4638+ function getWH() {
 4639+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
 4640+
 4641+ if ( extra === "border" ) {
 4642+ return;
 4643+ }
 4644+
 4645+ jQuery.each( which, function() {
 4646+ if ( !extra ) {
 4647+ val -= parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
 4648+ }
 4649+
 4650+ if ( extra === "margin" ) {
 4651+ val += parseFloat(jQuery.curCSS( elem, "margin" + this, true)) || 0;
 4652+ } else {
 4653+ val -= parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
 4654+ }
 4655+ });
 4656+ }
 4657+
 4658+ if ( elem.offsetWidth !== 0 ) {
 4659+ getWH();
 4660+ } else {
 4661+ jQuery.swap( elem, props, getWH );
 4662+ }
 4663+
 4664+ return Math.max(0, Math.round(val));
 4665+ }
 4666+
 4667+ return jQuery.curCSS( elem, name, force );
 4668+ },
 4669+
 4670+ curCSS: function( elem, name, force ) {
 4671+ var ret, style = elem.style, filter;
 4672+
 4673+ // IE uses filters for opacity
 4674+ if ( !jQuery.support.opacity && name === "opacity" && elem.currentStyle ) {
 4675+ ret = ropacity.test(elem.currentStyle.filter || "") ?
 4676+ (parseFloat(RegExp.$1) / 100) + "" :
 4677+ "";
 4678+
 4679+ return ret === "" ?
 4680+ "1" :
 4681+ ret;
 4682+ }
 4683+
 4684+ // Make sure we're using the right name for getting the float value
 4685+ if ( rfloat.test( name ) ) {
 4686+ name = styleFloat;
 4687+ }
 4688+
 4689+ if ( !force && style && style[ name ] ) {
 4690+ ret = style[ name ];
 4691+
 4692+ } else if ( getComputedStyle ) {
 4693+
 4694+ // Only "float" is needed here
 4695+ if ( rfloat.test( name ) ) {
 4696+ name = "float";
 4697+ }
 4698+
 4699+ name = name.replace( rupper, "-$1" ).toLowerCase();
 4700+
 4701+ var defaultView = elem.ownerDocument.defaultView;
 4702+
 4703+ if ( !defaultView ) {
 4704+ return null;
 4705+ }
 4706+
 4707+ var computedStyle = defaultView.getComputedStyle( elem, null );
 4708+
 4709+ if ( computedStyle ) {
 4710+ ret = computedStyle.getPropertyValue( name );
 4711+ }
 4712+
 4713+ // We should always get a number back from opacity
 4714+ if ( name === "opacity" && ret === "" ) {
 4715+ ret = "1";
 4716+ }
 4717+
 4718+ } else if ( elem.currentStyle ) {
 4719+ var camelCase = name.replace(rdashAlpha, fcamelCase);
 4720+
 4721+ ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];
 4722+
 4723+ // From the awesome hack by Dean Edwards
 4724+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
 4725+
 4726+ // If we're not dealing with a regular pixel number
 4727+ // but a number that has a weird ending, we need to convert it to pixels
 4728+ if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
 4729+ // Remember the original values
 4730+ var left = style.left, rsLeft = elem.runtimeStyle.left;
 4731+
 4732+ // Put in the new values to get a computed value out
 4733+ elem.runtimeStyle.left = elem.currentStyle.left;
 4734+ style.left = camelCase === "fontSize" ? "1em" : (ret || 0);
 4735+ ret = style.pixelLeft + "px";
 4736+
 4737+ // Revert the changed values
 4738+ style.left = left;
 4739+ elem.runtimeStyle.left = rsLeft;
 4740+ }
 4741+ }
 4742+
 4743+ return ret;
 4744+ },
 4745+
 4746+ // A method for quickly swapping in/out CSS properties to get correct calculations
 4747+ swap: function( elem, options, callback ) {
 4748+ var old = {};
 4749+
 4750+ // Remember the old values, and insert the new ones
 4751+ for ( var name in options ) {
 4752+ old[ name ] = elem.style[ name ];
 4753+ elem.style[ name ] = options[ name ];
 4754+ }
 4755+
 4756+ callback.call( elem );
 4757+
 4758+ // Revert the old values
 4759+ for ( var name in options ) {
 4760+ elem.style[ name ] = old[ name ];
 4761+ }
 4762+ }
 4763+});
 4764+
 4765+if ( jQuery.expr && jQuery.expr.filters ) {
 4766+ jQuery.expr.filters.hidden = function( elem ) {
 4767+ var width = elem.offsetWidth, height = elem.offsetHeight,
 4768+ skip = elem.nodeName.toLowerCase() === "tr";
 4769+
 4770+ return width === 0 && height === 0 && !skip ?
 4771+ true :
 4772+ width > 0 && height > 0 && !skip ?
 4773+ false :
 4774+ jQuery.curCSS(elem, "display") === "none";
 4775+ };
 4776+
 4777+ jQuery.expr.filters.visible = function( elem ) {
 4778+ return !jQuery.expr.filters.hidden( elem );
 4779+ };
 4780+}
 4781+var jsc = now(),
 4782+ rscript = /<script(.|\s)*?\/script>/gi,
 4783+ rselectTextarea = /select|textarea/i,
 4784+ rinput = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,
 4785+ jsre = /=\?(&|$)/,
 4786+ rquery = /\?/,
 4787+ rts = /(\?|&)_=.*?(&|$)/,
 4788+ rurl = /^(\w+:)?\/\/([^\/?#]+)/,
 4789+ r20 = /%20/g,
 4790+
 4791+ // Keep a copy of the old load method
 4792+ _load = jQuery.fn.load;
 4793+
 4794+jQuery.fn.extend({
 4795+ load: function( url, params, callback ) {
 4796+ if ( typeof url !== "string" ) {
 4797+ return _load.call( this, url );
 4798+
 4799+ // Don't do a request if no elements are being requested
 4800+ } else if ( !this.length ) {
 4801+ return this;
 4802+ }
 4803+
 4804+ var off = url.indexOf(" ");
 4805+ if ( off >= 0 ) {
 4806+ var selector = url.slice(off, url.length);
 4807+ url = url.slice(0, off);
 4808+ }
 4809+
 4810+ // Default to a GET request
 4811+ var type = "GET";
 4812+
 4813+ // If the second parameter was provided
 4814+ if ( params ) {
 4815+ // If it's a function
 4816+ if ( jQuery.isFunction( params ) ) {
 4817+ // We assume that it's the callback
 4818+ callback = params;
 4819+ params = null;
 4820+
 4821+ // Otherwise, build a param string
 4822+ } else if ( typeof params === "object" ) {
 4823+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
 4824+ type = "POST";
 4825+ }
 4826+ }
 4827+
 4828+ var self = this;
 4829+
 4830+ // Request the remote document
 4831+ jQuery.ajax({
 4832+ url: url,
 4833+ type: type,
 4834+ dataType: "html",
 4835+ data: params,
 4836+ complete: function( res, status ) {
 4837+ // If successful, inject the HTML into all the matched elements
 4838+ if ( status === "success" || status === "notmodified" ) {
 4839+ // See if a selector was specified
 4840+ self.html( selector ?
 4841+ // Create a dummy div to hold the results
 4842+ jQuery("<div />")
 4843+ // inject the contents of the document in, removing the scripts
 4844+ // to avoid any 'Permission Denied' errors in IE
 4845+ .append(res.responseText.replace(rscript, ""))
 4846+
 4847+ // Locate the specified elements
 4848+ .find(selector) :
 4849+
 4850+ // If not, just inject the full result
 4851+ res.responseText );
 4852+ }
 4853+
 4854+ if ( callback ) {
 4855+ self.each( callback, [res.responseText, status, res] );
 4856+ }
 4857+ }
 4858+ });
 4859+
 4860+ return this;
 4861+ },
 4862+
 4863+ serialize: function() {
 4864+ return jQuery.param(this.serializeArray());
 4865+ },
 4866+ serializeArray: function() {
 4867+ return this.map(function() {
 4868+ return this.elements ? jQuery.makeArray(this.elements) : this;
 4869+ })
 4870+ .filter(function() {
 4871+ return this.name && !this.disabled &&
 4872+ (this.checked || rselectTextarea.test(this.nodeName) ||
 4873+ rinput.test(this.type));
 4874+ })
 4875+ .map(function( i, elem ) {
 4876+ var val = jQuery(this).val();
 4877+
 4878+ return val == null ?
 4879+ null :
 4880+ jQuery.isArray(val) ?
 4881+ jQuery.map( val, function( val, i ) {
 4882+ return { name: elem.name, value: val };
 4883+ }) :
 4884+ { name: elem.name, value: val };
 4885+ }).get();
 4886+ }
 4887+});
 4888+
 4889+// Attach a bunch of functions for handling common AJAX events
 4890+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function( i, o ) {
 4891+ jQuery.fn[o] = function( f ) {
 4892+ return this.bind(o, f);
 4893+ };
 4894+});
 4895+
 4896+jQuery.extend({
 4897+
 4898+ get: function( url, data, callback, type ) {
 4899+ // shift arguments if data argument was omited
 4900+ if ( jQuery.isFunction( data ) ) {
 4901+ type = type || callback;
 4902+ callback = data;
 4903+ data = null;
 4904+ }
 4905+
 4906+ return jQuery.ajax({
 4907+ type: "GET",
 4908+ url: url,
 4909+ data: data,
 4910+ success: callback,
 4911+ dataType: type
 4912+ });
 4913+ },
 4914+
 4915+ getScript: function( url, callback ) {
 4916+ return jQuery.get(url, null, callback, "script");
 4917+ },
 4918+
 4919+ getJSON: function( url, data, callback ) {
 4920+ return jQuery.get(url, data, callback, "json");
 4921+ },
 4922+
 4923+ post: function( url, data, callback, type ) {
 4924+ // shift arguments if data argument was omited
 4925+ if ( jQuery.isFunction( data ) ) {
 4926+ type = type || callback;
 4927+ callback = data;
 4928+ data = {};
 4929+ }
 4930+
 4931+ return jQuery.ajax({
 4932+ type: "POST",
 4933+ url: url,
 4934+ data: data,
 4935+ success: callback,
 4936+ dataType: type
 4937+ });
 4938+ },
 4939+
 4940+ ajaxSetup: function( settings ) {
 4941+ jQuery.extend( jQuery.ajaxSettings, settings );
 4942+ },
 4943+
 4944+ ajaxSettings: {
 4945+ url: location.href,
 4946+ global: true,
 4947+ type: "GET",
 4948+ contentType: "application/x-www-form-urlencoded",
 4949+ processData: true,
 4950+ async: true,
 4951+ /*
 4952+ timeout: 0,
 4953+ data: null,
 4954+ username: null,
 4955+ password: null,
 4956+ traditional: false,
 4957+ */
 4958+ // Create the request object; Microsoft failed to properly
 4959+ // implement the XMLHttpRequest in IE7 (can't request local files),
 4960+ // so we use the ActiveXObject when it is available
 4961+ // This function can be overriden by calling jQuery.ajaxSetup
 4962+ xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
 4963+ function() {
 4964+ return new window.XMLHttpRequest();
 4965+ } :
 4966+ function() {
 4967+ try {
 4968+ return new window.ActiveXObject("Microsoft.XMLHTTP");
 4969+ } catch(e) {}
 4970+ },
 4971+ accepts: {
 4972+ xml: "application/xml, text/xml",
 4973+ html: "text/html",
 4974+ script: "text/javascript, application/javascript",
 4975+ json: "application/json, text/javascript",
 4976+ text: "text/plain",
 4977+ _default: "*/*"
 4978+ }
 4979+ },
 4980+
 4981+ // Last-Modified header cache for next request
 4982+ lastModified: {},
 4983+ etag: {},
 4984+
 4985+ ajax: function( origSettings ) {
 4986+ var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
 4987+
 4988+ var jsonp, status, data,
 4989+ callbackContext = origSettings && origSettings.context || s,
 4990+ type = s.type.toUpperCase();
 4991+
 4992+ // convert data if not already a string
 4993+ if ( s.data && s.processData && typeof s.data !== "string" ) {
 4994+ s.data = jQuery.param( s.data, s.traditional );
 4995+ }
 4996+
 4997+ // Handle JSONP Parameter Callbacks
 4998+ if ( s.dataType === "jsonp" ) {
 4999+ if ( type === "GET" ) {
 5000+ if ( !jsre.test( s.url ) ) {
 5001+ s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
 5002+ }
 5003+ } else if ( !s.data || !jsre.test(s.data) ) {
 5004+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
 5005+ }
 5006+ s.dataType = "json";
 5007+ }
 5008+
 5009+ // Build temporary JSONP function
 5010+ if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
 5011+ jsonp = s.jsonpCallback || ("jsonp" + jsc++);
 5012+
 5013+ // Replace the =? sequence both in the query string and the data
 5014+ if ( s.data ) {
 5015+ s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
 5016+ }
 5017+
 5018+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
 5019+
 5020+ // We need to make sure
 5021+ // that a JSONP style response is executed properly
 5022+ s.dataType = "script";
 5023+
 5024+ // Handle JSONP-style loading
 5025+ window[ jsonp ] = window[ jsonp ] || function( tmp ) {
 5026+ data = tmp;
 5027+ success();
 5028+ complete();
 5029+ // Garbage collect
 5030+ window[ jsonp ] = undefined;
 5031+
 5032+ try {
 5033+ delete window[ jsonp ];
 5034+ } catch(e) {}
 5035+
 5036+ if ( head ) {
 5037+ head.removeChild( script );
 5038+ }
 5039+ };
 5040+ }
 5041+
 5042+ if ( s.dataType === "script" && s.cache === null ) {
 5043+ s.cache = false;
 5044+ }
 5045+
 5046+ if ( s.cache === false && type === "GET" ) {
 5047+ var ts = now();
 5048+
 5049+ // try replacing _= if it is there
 5050+ var ret = s.url.replace(rts, "$1_=" + ts + "$2");
 5051+
 5052+ // if nothing was replaced, add timestamp to the end
 5053+ s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
 5054+ }
 5055+
 5056+ // If data is available, append data to url for get requests
 5057+ if ( s.data && type === "GET" ) {
 5058+ s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
 5059+ }
 5060+
 5061+ // Watch for a new set of requests
 5062+ if ( s.global && ! jQuery.active++ ) {
 5063+ jQuery.event.trigger( "ajaxStart" );
 5064+ }
 5065+
 5066+ // Matches an absolute URL, and saves the domain
 5067+ var parts = rurl.exec( s.url ),
 5068+ remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
 5069+
 5070+ // If we're requesting a remote document
 5071+ // and trying to load JSON or Script with a GET
 5072+ if ( s.dataType === "script" && type === "GET" && remote ) {
 5073+ var head = document.getElementsByTagName("head")[0] || document.documentElement;
 5074+ var script = document.createElement("script");
 5075+ script.src = s.url;
 5076+ if ( s.scriptCharset ) {
 5077+ script.charset = s.scriptCharset;
 5078+ }
 5079+
 5080+ // Handle Script loading
 5081+ if ( !jsonp ) {
 5082+ var done = false;
 5083+
 5084+ // Attach handlers for all browsers
 5085+ script.onload = script.onreadystatechange = function() {
 5086+ if ( !done && (!this.readyState ||
 5087+ this.readyState === "loaded" || this.readyState === "complete") ) {
 5088+ done = true;
 5089+ success();
 5090+ complete();
 5091+
 5092+ // Handle memory leak in IE
 5093+ script.onload = script.onreadystatechange = null;
 5094+ if ( head && script.parentNode ) {
 5095+ head.removeChild( script );
 5096+ }
 5097+ }
 5098+ };
 5099+ }
 5100+
 5101+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
 5102+ // This arises when a base node is used (#2709 and #4378).
 5103+ head.insertBefore( script, head.firstChild );
 5104+
 5105+ // We handle everything using the script element injection
 5106+ return undefined;
 5107+ }
 5108+
 5109+ var requestDone = false;
 5110+
 5111+ // Create the request object
 5112+ var xhr = s.xhr();
 5113+
 5114+ if ( !xhr ) {
 5115+ return;
 5116+ }
 5117+
 5118+ // Open the socket
 5119+ // Passing null username, generates a login popup on Opera (#2865)
 5120+ if ( s.username ) {
 5121+ xhr.open(type, s.url, s.async, s.username, s.password);
 5122+ } else {
 5123+ xhr.open(type, s.url, s.async);
 5124+ }
 5125+
 5126+ // Need an extra try/catch for cross domain requests in Firefox 3
 5127+ try {
 5128+ // Set the correct header, if data is being sent
 5129+ if ( s.data || origSettings && origSettings.contentType ) {
 5130+ xhr.setRequestHeader("Content-Type", s.contentType);
 5131+ }
 5132+
 5133+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
 5134+ if ( s.ifModified ) {
 5135+ if ( jQuery.lastModified[s.url] ) {
 5136+ xhr.setRequestHeader("If-Modified-Since", jQuery.lastModified[s.url]);
 5137+ }
 5138+
 5139+ if ( jQuery.etag[s.url] ) {
 5140+ xhr.setRequestHeader("If-None-Match", jQuery.etag[s.url]);
 5141+ }
 5142+ }
 5143+
 5144+ // Set header so the called script knows that it's an XMLHttpRequest
 5145+ // Only send the header if it's not a remote XHR
 5146+ if ( !remote ) {
 5147+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
 5148+ }
 5149+
 5150+ // Set the Accepts header for the server, depending on the dataType
 5151+ xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
 5152+ s.accepts[ s.dataType ] + ", */*" :
 5153+ s.accepts._default );
 5154+ } catch(e) {}
 5155+
 5156+ // Allow custom headers/mimetypes and early abort
 5157+ if ( s.beforeSend && s.beforeSend.call(callbackContext, xhr, s) === false ) {
 5158+ // Handle the global AJAX counter
 5159+ if ( s.global && ! --jQuery.active ) {
 5160+ jQuery.event.trigger( "ajaxStop" );
 5161+ }
 5162+
 5163+ // close opended socket
 5164+ xhr.abort();
 5165+ return false;
 5166+ }
 5167+
 5168+ if ( s.global ) {
 5169+ trigger("ajaxSend", [xhr, s]);
 5170+ }
 5171+
 5172+ // Wait for a response to come back
 5173+ var onreadystatechange = xhr.onreadystatechange = function( isTimeout ) {
 5174+ // The request was aborted
 5175+ if ( !xhr || xhr.readyState === 0 || isTimeout === "abort" ) {
 5176+ // Opera doesn't call onreadystatechange before this point
 5177+ // so we simulate the call
 5178+ if ( !requestDone ) {
 5179+ complete();
 5180+ }
 5181+
 5182+ requestDone = true;
 5183+ if ( xhr ) {
 5184+ xhr.onreadystatechange = jQuery.noop;
 5185+ }
 5186+
 5187+ // The transfer is complete and the data is available, or the request timed out
 5188+ } else if ( !requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout") ) {
 5189+
 5190+ requestDone = true;
 5191+ xhr.onreadystatechange = jQuery.noop;
 5192+
 5193+ status = isTimeout === "timeout" ?
 5194+ "timeout" :
 5195+ !jQuery.httpSuccess( xhr ) ?
 5196+ "error" :
 5197+ s.ifModified && jQuery.httpNotModified( xhr, s.url ) ?
 5198+ "notmodified" :
 5199+ "success";
 5200+
 5201+ var errMsg;
 5202+
 5203+ if ( status === "success" ) {
 5204+ // Watch for, and catch, XML document parse errors
 5205+ try {
 5206+ // process the data (runs the xml through httpData regardless of callback)
 5207+ data = jQuery.httpData( xhr, s.dataType, s );
 5208+ } catch(err) {
 5209+ status = "parsererror";
 5210+ errMsg = err;
 5211+ }
 5212+ }
 5213+
 5214+ // Make sure that the request was successful or notmodified
 5215+ if ( status === "success" || status === "notmodified" ) {
 5216+ // JSONP handles its own success callback
 5217+ if ( !jsonp ) {
 5218+ success();
 5219+ }
 5220+ } else {
 5221+ jQuery.handleError(s, xhr, status, errMsg);
 5222+ }
 5223+
 5224+ // Fire the complete handlers
 5225+ complete();
 5226+
 5227+ if ( isTimeout === "timeout" ) {
 5228+ xhr.abort();
 5229+ }
 5230+
 5231+ // Stop memory leaks
 5232+ if ( s.async ) {
 5233+ xhr = null;
 5234+ }
 5235+ }
 5236+ };
 5237+
 5238+ // Override the abort handler, if we can (IE doesn't allow it, but that's OK)
 5239+ // Opera doesn't fire onreadystatechange at all on abort
 5240+ try {
 5241+ var oldAbort = xhr.abort;
 5242+ xhr.abort = function() {
 5243+ if ( xhr ) {
 5244+ oldAbort.call( xhr );
 5245+ }
 5246+
 5247+ onreadystatechange( "abort" );
 5248+ };
 5249+ } catch(e) { }
 5250+
 5251+ // Timeout checker
 5252+ if ( s.async && s.timeout > 0 ) {
 5253+ setTimeout(function() {
 5254+ // Check to see if the request is still happening
 5255+ if ( xhr && !requestDone ) {
 5256+ onreadystatechange( "timeout" );
 5257+ }
 5258+ }, s.timeout);
 5259+ }
 5260+
 5261+ // Send the data
 5262+ try {
 5263+ xhr.send( type === "POST" || type === "PUT" || type === "DELETE" ? s.data : null );
 5264+ } catch(e) {
 5265+ jQuery.handleError(s, xhr, null, e);
 5266+ // Fire the complete handlers
 5267+ complete();
 5268+ }
 5269+
 5270+ // firefox 1.5 doesn't fire statechange for sync requests
 5271+ if ( !s.async ) {
 5272+ onreadystatechange();
 5273+ }
 5274+
 5275+ function success() {
 5276+ // If a local callback was specified, fire it and pass it the data
 5277+ if ( s.success ) {
 5278+ s.success.call( callbackContext, data, status, xhr );
 5279+ }
 5280+
 5281+ // Fire the global callback
 5282+ if ( s.global ) {
 5283+ trigger( "ajaxSuccess", [xhr, s] );
 5284+ }
 5285+ }
 5286+
 5287+ function complete() {
 5288+ // Process result
 5289+ if ( s.complete ) {
 5290+ s.complete.call( callbackContext, xhr, status);
 5291+ }
 5292+
 5293+ // The request was completed
 5294+ if ( s.global ) {
 5295+ trigger( "ajaxComplete", [xhr, s] );
 5296+ }
 5297+
 5298+ // Handle the global AJAX counter
 5299+ if ( s.global && ! --jQuery.active ) {
 5300+ jQuery.event.trigger( "ajaxStop" );
 5301+ }
 5302+ }
 5303+
 5304+ function trigger(type, args) {
 5305+ (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
 5306+ }
 5307+
 5308+ // return XMLHttpRequest to allow aborting the request etc.
 5309+ return xhr;
 5310+ },
 5311+
 5312+ handleError: function( s, xhr, status, e ) {
 5313+ // If a local callback was specified, fire it
 5314+ if ( s.error ) {
 5315+ s.error.call( s.context || s, xhr, status, e );
 5316+ }
 5317+
 5318+ // Fire the global callback
 5319+ if ( s.global ) {
 5320+ (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
 5321+ }
 5322+ },
 5323+
 5324+ // Counter for holding the number of active queries
 5325+ active: 0,
 5326+
 5327+ // Determines if an XMLHttpRequest was successful or not
 5328+ httpSuccess: function( xhr ) {
 5329+ try {
 5330+ // IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
 5331+ return !xhr.status && location.protocol === "file:" ||
 5332+ // Opera returns 0 when status is 304
 5333+ ( xhr.status >= 200 && xhr.status < 300 ) ||
 5334+ xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
 5335+ } catch(e) {}
 5336+
 5337+ return false;
 5338+ },
 5339+
 5340+ // Determines if an XMLHttpRequest returns NotModified
 5341+ httpNotModified: function( xhr, url ) {
 5342+ var lastModified = xhr.getResponseHeader("Last-Modified"),
 5343+ etag = xhr.getResponseHeader("Etag");
 5344+
 5345+ if ( lastModified ) {
 5346+ jQuery.lastModified[url] = lastModified;
 5347+ }
 5348+
 5349+ if ( etag ) {
 5350+ jQuery.etag[url] = etag;
 5351+ }
 5352+
 5353+ // Opera returns 0 when status is 304
 5354+ return xhr.status === 304 || xhr.status === 0;
 5355+ },
 5356+
 5357+ httpData: function( xhr, type, s ) {
 5358+ var ct = xhr.getResponseHeader("content-type") || "",
 5359+ xml = type === "xml" || !type && ct.indexOf("xml") >= 0,
 5360+ data = xml ? xhr.responseXML : xhr.responseText;
 5361+
 5362+ if ( xml && data.documentElement.nodeName === "parsererror" ) {
 5363+ jQuery.error( "parsererror" );
 5364+ }
 5365+
 5366+ // Allow a pre-filtering function to sanitize the response
 5367+ // s is checked to keep backwards compatibility
 5368+ if ( s && s.dataFilter ) {
 5369+ data = s.dataFilter( data, type );
 5370+ }
 5371+
 5372+ // The filter can actually parse the response
 5373+ if ( typeof data === "string" ) {
 5374+ // Get the JavaScript object, if JSON is used.
 5375+ if ( type === "json" || !type && ct.indexOf("json") >= 0 ) {
 5376+ data = jQuery.parseJSON( data );
 5377+
 5378+ // If the type is "script", eval it in global context
 5379+ } else if ( type === "script" || !type && ct.indexOf("javascript") >= 0 ) {
 5380+ jQuery.globalEval( data );
 5381+ }
 5382+ }
 5383+
 5384+ return data;
 5385+ },
 5386+
 5387+ // Serialize an array of form elements or a set of
 5388+ // key/values into a query string
 5389+ param: function( a, traditional ) {
 5390+ var s = [];
 5391+
 5392+ // Set traditional to true for jQuery <= 1.3.2 behavior.
 5393+ if ( traditional === undefined ) {
 5394+ traditional = jQuery.ajaxSettings.traditional;
 5395+ }
 5396+
 5397+ // If an array was passed in, assume that it is an array of form elements.
 5398+ if ( jQuery.isArray(a) || a.jquery ) {
 5399+ // Serialize the form elements
 5400+ jQuery.each( a, function() {
 5401+ add( this.name, this.value );
 5402+ });
 5403+
 5404+ } else {
 5405+ // If traditional, encode the "old" way (the way 1.3.2 or older
 5406+ // did it), otherwise encode params recursively.
 5407+ for ( var prefix in a ) {
 5408+ buildParams( prefix, a[prefix] );
 5409+ }
 5410+ }
 5411+
 5412+ // Return the resulting serialization
 5413+ return s.join("&").replace(r20, "+");
 5414+
 5415+ function buildParams( prefix, obj ) {
 5416+ if ( jQuery.isArray(obj) ) {
 5417+ // Serialize array item.
 5418+ jQuery.each( obj, function( i, v ) {
 5419+ if ( traditional || /\[\]$/.test( prefix ) ) {
 5420+ // Treat each array item as a scalar.
 5421+ add( prefix, v );
 5422+ } else {
 5423+ // If array item is non-scalar (array or object), encode its
 5424+ // numeric index to resolve deserialization ambiguity issues.
 5425+ // Note that rack (as of 1.0.0) can't currently deserialize
 5426+ // nested arrays properly, and attempting to do so may cause
 5427+ // a server error. Possible fixes are to modify rack's
 5428+ // deserialization algorithm or to provide an option or flag
 5429+ // to force array serialization to be shallow.
 5430+ buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v );
 5431+ }
 5432+ });
 5433+
 5434+ } else if ( !traditional && obj != null && typeof obj === "object" ) {
 5435+ // Serialize object item.
 5436+ jQuery.each( obj, function( k, v ) {
 5437+ buildParams( prefix + "[" + k + "]", v );
 5438+ });
 5439+
 5440+ } else {
 5441+ // Serialize scalar item.
 5442+ add( prefix, obj );
 5443+ }
 5444+ }
 5445+
 5446+ function add( key, value ) {
 5447+ // If value is a function, invoke it and return its value
 5448+ value = jQuery.isFunction(value) ? value() : value;
 5449+ s[ s.length ] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
 5450+ }
 5451+ }
 5452+});
 5453+var elemdisplay = {},
 5454+ rfxtypes = /toggle|show|hide/,
 5455+ rfxnum = /^([+-]=)?([\d+-.]+)(.*)$/,
 5456+ timerId,
 5457+ fxAttrs = [
 5458+ // height animations
 5459+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
 5460+ // width animations
 5461+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
 5462+ // opacity animations
 5463+ [ "opacity" ]
 5464+ ];
 5465+
 5466+jQuery.fn.extend({
 5467+ show: function( speed, callback ) {
 5468+ if ( speed || speed === 0) {
 5469+ return this.animate( genFx("show", 3), speed, callback);
 5470+
 5471+ } else {
 5472+ for ( var i = 0, l = this.length; i < l; i++ ) {
 5473+ var old = jQuery.data(this[i], "olddisplay");
 5474+
 5475+ this[i].style.display = old || "";
 5476+
 5477+ if ( jQuery.css(this[i], "display") === "none" ) {
 5478+ var nodeName = this[i].nodeName, display;
 5479+
 5480+ if ( elemdisplay[ nodeName ] ) {
 5481+ display = elemdisplay[ nodeName ];
 5482+
 5483+ } else {
 5484+ var elem = jQuery("<" + nodeName + " />").appendTo("body");
 5485+
 5486+ display = elem.css("display");
 5487+
 5488+ if ( display === "none" ) {
 5489+ display = "block";
 5490+ }
 5491+
 5492+ elem.remove();
 5493+
 5494+ elemdisplay[ nodeName ] = display;
 5495+ }
 5496+
 5497+ jQuery.data(this[i], "olddisplay", display);
 5498+ }
 5499+ }
 5500+
 5501+ // Set the display of the elements in a second loop
 5502+ // to avoid the constant reflow
 5503+ for ( var j = 0, k = this.length; j < k; j++ ) {
 5504+ this[j].style.display = jQuery.data(this[j], "olddisplay") || "";
 5505+ }
 5506+
 5507+ return this;
 5508+ }
 5509+ },
 5510+
 5511+ hide: function( speed, callback ) {
 5512+ if ( speed || speed === 0 ) {
 5513+ return this.animate( genFx("hide", 3), speed, callback);
 5514+
 5515+ } else {
 5516+ for ( var i = 0, l = this.length; i < l; i++ ) {
 5517+ var old = jQuery.data(this[i], "olddisplay");
 5518+ if ( !old && old !== "none" ) {
 5519+ jQuery.data(this[i], "olddisplay", jQuery.css(this[i], "display"));
 5520+ }
 5521+ }
 5522+
 5523+ // Set the display of the elements in a second loop
 5524+ // to avoid the constant reflow
 5525+ for ( var j = 0, k = this.length; j < k; j++ ) {
 5526+ this[j].style.display = "none";
 5527+ }
 5528+
 5529+ return this;
 5530+ }
 5531+ },
 5532+
 5533+ // Save the old toggle function
 5534+ _toggle: jQuery.fn.toggle,
 5535+
 5536+ toggle: function( fn, fn2 ) {
 5537+ var bool = typeof fn === "boolean";
 5538+
 5539+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
 5540+ this._toggle.apply( this, arguments );
 5541+
 5542+ } else if ( fn == null || bool ) {
 5543+ this.each(function() {
 5544+ var state = bool ? fn : jQuery(this).is(":hidden");
 5545+ jQuery(this)[ state ? "show" : "hide" ]();
 5546+ });
 5547+
 5548+ } else {
 5549+ this.animate(genFx("toggle", 3), fn, fn2);
 5550+ }
 5551+
 5552+ return this;
 5553+ },
 5554+
 5555+ fadeTo: function( speed, to, callback ) {
 5556+ return this.filter(":hidden").css("opacity", 0).show().end()
 5557+ .animate({opacity: to}, speed, callback);
 5558+ },
 5559+
 5560+ animate: function( prop, speed, easing, callback ) {
 5561+ var optall = jQuery.speed(speed, easing, callback);
 5562+
 5563+ if ( jQuery.isEmptyObject( prop ) ) {
 5564+ return this.each( optall.complete );
 5565+ }
 5566+
 5567+ return this[ optall.queue === false ? "each" : "queue" ](function() {
 5568+ var opt = jQuery.extend({}, optall), p,
 5569+ hidden = this.nodeType === 1 && jQuery(this).is(":hidden"),
 5570+ self = this;
 5571+
 5572+ for ( p in prop ) {
 5573+ var name = p.replace(rdashAlpha, fcamelCase);
 5574+
 5575+ if ( p !== name ) {
 5576+ prop[ name ] = prop[ p ];
 5577+ delete prop[ p ];
 5578+ p = name;
 5579+ }
 5580+
 5581+ if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
 5582+ return opt.complete.call(this);
 5583+ }
 5584+
 5585+ if ( ( p === "height" || p === "width" ) && this.style ) {
 5586+ // Store display property
 5587+ opt.display = jQuery.css(this, "display");
 5588+
 5589+ // Make sure that nothing sneaks out
 5590+ opt.overflow = this.style.overflow;
 5591+ }
 5592+
 5593+ if ( jQuery.isArray( prop[p] ) ) {
 5594+ // Create (if needed) and add to specialEasing
 5595+ (opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
 5596+ prop[p] = prop[p][0];
 5597+ }
 5598+ }
 5599+
 5600+ if ( opt.overflow != null ) {
 5601+ this.style.overflow = "hidden";
 5602+ }
 5603+
 5604+ opt.curAnim = jQuery.extend({}, prop);
 5605+
 5606+ jQuery.each( prop, function( name, val ) {
 5607+ var e = new jQuery.fx( self, opt, name );
 5608+
 5609+ if ( rfxtypes.test(val) ) {
 5610+ e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );
 5611+
 5612+ } else {
 5613+ var parts = rfxnum.exec(val),
 5614+ start = e.cur(true) || 0;
 5615+
 5616+ if ( parts ) {
 5617+ var end = parseFloat( parts[2] ),
 5618+ unit = parts[3] || "px";
 5619+
 5620+ // We need to compute starting value
 5621+ if ( unit !== "px" ) {
 5622+ self.style[ name ] = (end || 1) + unit;
 5623+ start = ((end || 1) / e.cur(true)) * start;
 5624+ self.style[ name ] = start + unit;
 5625+ }
 5626+
 5627+ // If a +=/-= token was provided, we're doing a relative animation
 5628+ if ( parts[1] ) {
 5629+ end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
 5630+ }
 5631+
 5632+ e.custom( start, end, unit );
 5633+
 5634+ } else {
 5635+ e.custom( start, val, "" );
 5636+ }
 5637+ }
 5638+ });
 5639+
 5640+ // For JS strict compliance
 5641+ return true;
 5642+ });
 5643+ },
 5644+
 5645+ stop: function( clearQueue, gotoEnd ) {
 5646+ var timers = jQuery.timers;
 5647+
 5648+ if ( clearQueue ) {
 5649+ this.queue([]);
 5650+ }
 5651+
 5652+ this.each(function() {
 5653+ // go in reverse order so anything added to the queue during the loop is ignored
 5654+ for ( var i = timers.length - 1; i >= 0; i-- ) {
 5655+ if ( timers[i].elem === this ) {
 5656+ if (gotoEnd) {
 5657+ // force the next step to be the last
 5658+ timers[i](true);
 5659+ }
 5660+
 5661+ timers.splice(i, 1);
 5662+ }
 5663+ }
 5664+ });
 5665+
 5666+ // start the next in the queue if the last step wasn't forced
 5667+ if ( !gotoEnd ) {
 5668+ this.dequeue();
 5669+ }
 5670+
 5671+ return this;
 5672+ }
 5673+
 5674+});
 5675+
 5676+// Generate shortcuts for custom animations
 5677+jQuery.each({
 5678+ slideDown: genFx("show", 1),
 5679+ slideUp: genFx("hide", 1),
 5680+ slideToggle: genFx("toggle", 1),
 5681+ fadeIn: { opacity: "show" },
 5682+ fadeOut: { opacity: "hide" }
 5683+}, function( name, props ) {
 5684+ jQuery.fn[ name ] = function( speed, callback ) {
 5685+ return this.animate( props, speed, callback );
 5686+ };
 5687+});
 5688+
 5689+jQuery.extend({
 5690+ speed: function( speed, easing, fn ) {
 5691+ var opt = speed && typeof speed === "object" ? speed : {
 5692+ complete: fn || !fn && easing ||
 5693+ jQuery.isFunction( speed ) && speed,
 5694+ duration: speed,
 5695+ easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
 5696+ };
 5697+
 5698+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
 5699+ jQuery.fx.speeds[opt.duration] || jQuery.fx.speeds._default;
 5700+
 5701+ // Queueing
 5702+ opt.old = opt.complete;
 5703+ opt.complete = function() {
 5704+ if ( opt.queue !== false ) {
 5705+ jQuery(this).dequeue();
 5706+ }
 5707+ if ( jQuery.isFunction( opt.old ) ) {
 5708+ opt.old.call( this );
 5709+ }
 5710+ };
 5711+
 5712+ return opt;
 5713+ },
 5714+
 5715+ easing: {
 5716+ linear: function( p, n, firstNum, diff ) {
 5717+ return firstNum + diff * p;
 5718+ },
 5719+ swing: function( p, n, firstNum, diff ) {
 5720+ return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
 5721+ }
 5722+ },
 5723+
 5724+ timers: [],
 5725+
 5726+ fx: function( elem, options, prop ) {
 5727+ this.options = options;
 5728+ this.elem = elem;
 5729+ this.prop = prop;
 5730+
 5731+ if ( !options.orig ) {
 5732+ options.orig = {};
 5733+ }
 5734+ }
 5735+
 5736+});
 5737+
 5738+jQuery.fx.prototype = {
 5739+ // Simple function for setting a style value
 5740+ update: function() {
 5741+ if ( this.options.step ) {
 5742+ this.options.step.call( this.elem, this.now, this );
 5743+ }
 5744+
 5745+ (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
 5746+
 5747+ // Set display property to block for height/width animations
 5748+ if ( ( this.prop === "height" || this.prop === "width" ) && this.elem.style ) {
 5749+ this.elem.style.display = "block";
 5750+ }
 5751+ },
 5752+
 5753+ // Get the current size
 5754+ cur: function( force ) {
 5755+ if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
 5756+ return this.elem[ this.prop ];
 5757+ }
 5758+
 5759+ var r = parseFloat(jQuery.css(this.elem, this.prop, force));
 5760+ return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
 5761+ },
 5762+
 5763+ // Start an animation from one number to another
 5764+ custom: function( from, to, unit ) {
 5765+ this.startTime = now();
 5766+ this.start = from;
 5767+ this.end = to;
 5768+ this.unit = unit || this.unit || "px";
 5769+ this.now = this.start;
 5770+ this.pos = this.state = 0;
 5771+
 5772+ var self = this;
 5773+ function t( gotoEnd ) {
 5774+ return self.step(gotoEnd);
 5775+ }
 5776+
 5777+ t.elem = this.elem;
 5778+
 5779+ if ( t() && jQuery.timers.push(t) && !timerId ) {
 5780+ timerId = setInterval(jQuery.fx.tick, 13);
 5781+ }
 5782+ },
 5783+
 5784+ // Simple 'show' function
 5785+ show: function() {
 5786+ // Remember where we started, so that we can go back to it later
 5787+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
 5788+ this.options.show = true;
 5789+
 5790+ // Begin the animation
 5791+ // Make sure that we start at a small width/height to avoid any
 5792+ // flash of content
 5793+ this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
 5794+
 5795+ // Start by showing the element
 5796+ jQuery( this.elem ).show();
 5797+ },
 5798+
 5799+ // Simple 'hide' function
 5800+ hide: function() {
 5801+ // Remember where we started, so that we can go back to it later
 5802+ this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
 5803+ this.options.hide = true;
 5804+
 5805+ // Begin the animation
 5806+ this.custom(this.cur(), 0);
 5807+ },
 5808+
 5809+ // Each step of an animation
 5810+ step: function( gotoEnd ) {
 5811+ var t = now(), done = true;
 5812+
 5813+ if ( gotoEnd || t >= this.options.duration + this.startTime ) {
 5814+ this.now = this.end;
 5815+ this.pos = this.state = 1;
 5816+ this.update();
 5817+
 5818+ this.options.curAnim[ this.prop ] = true;
 5819+
 5820+ for ( var i in this.options.curAnim ) {
 5821+ if ( this.options.curAnim[i] !== true ) {
 5822+ done = false;
 5823+ }
 5824+ }
 5825+
 5826+ if ( done ) {
 5827+ if ( this.options.display != null ) {
 5828+ // Reset the overflow
 5829+ this.elem.style.overflow = this.options.overflow;
 5830+
 5831+ // Reset the display
 5832+ var old = jQuery.data(this.elem, "olddisplay");
 5833+ this.elem.style.display = old ? old : this.options.display;
 5834+
 5835+ if ( jQuery.css(this.elem, "display") === "none" ) {
 5836+ this.elem.style.display = "block";
 5837+ }
 5838+ }
 5839+
 5840+ // Hide the element if the "hide" operation was done
 5841+ if ( this.options.hide ) {
 5842+ jQuery(this.elem).hide();
 5843+ }
 5844+
 5845+ // Reset the properties, if the item has been hidden or shown
 5846+ if ( this.options.hide || this.options.show ) {
 5847+ for ( var p in this.options.curAnim ) {
 5848+ jQuery.style(this.elem, p, this.options.orig[p]);
 5849+ }
 5850+ }
 5851+
 5852+ // Execute the complete function
 5853+ this.options.complete.call( this.elem );
 5854+ }
 5855+
 5856+ return false;
 5857+
 5858+ } else {
 5859+ var n = t - this.startTime;
 5860+ this.state = n / this.options.duration;
 5861+
 5862+ // Perform the easing function, defaults to swing
 5863+ var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
 5864+ var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
 5865+ this.pos = jQuery.easing[specialEasing || defaultEasing](this.state, n, 0, 1, this.options.duration);
 5866+ this.now = this.start + ((this.end - this.start) * this.pos);
 5867+
 5868+ // Perform the next step of the animation
 5869+ this.update();
 5870+ }
 5871+
 5872+ return true;
 5873+ }
 5874+};
 5875+
 5876+jQuery.extend( jQuery.fx, {
 5877+ tick: function() {
 5878+ var timers = jQuery.timers;
 5879+
 5880+ for ( var i = 0; i < timers.length; i++ ) {
 5881+ if ( !timers[i]() ) {
 5882+ timers.splice(i--, 1);
 5883+ }
 5884+ }
 5885+
 5886+ if ( !timers.length ) {
 5887+ jQuery.fx.stop();
 5888+ }
 5889+ },
 5890+
 5891+ stop: function() {
 5892+ clearInterval( timerId );
 5893+ timerId = null;
 5894+ },
 5895+
 5896+ speeds: {
 5897+ slow: 600,
 5898+ fast: 200,
 5899+ // Default speed
 5900+ _default: 400
 5901+ },
 5902+
 5903+ step: {
 5904+ opacity: function( fx ) {
 5905+ jQuery.style(fx.elem, "opacity", fx.now);
 5906+ },
 5907+
 5908+ _default: function( fx ) {
 5909+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
 5910+ fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
 5911+ } else {
 5912+ fx.elem[ fx.prop ] = fx.now;
 5913+ }
 5914+ }
 5915+ }
 5916+});
 5917+
 5918+if ( jQuery.expr && jQuery.expr.filters ) {
 5919+ jQuery.expr.filters.animated = function( elem ) {
 5920+ return jQuery.grep(jQuery.timers, function( fn ) {
 5921+ return elem === fn.elem;
 5922+ }).length;
 5923+ };
 5924+}
 5925+
 5926+function genFx( type, num ) {
 5927+ var obj = {};
 5928+
 5929+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
 5930+ obj[ this ] = type;
 5931+ });
 5932+
 5933+ return obj;
 5934+}
 5935+if ( "getBoundingClientRect" in document.documentElement ) {
 5936+ jQuery.fn.offset = function( options ) {
 5937+ var elem = this[0];
 5938+
 5939+ if ( options ) {
 5940+ return this.each(function( i ) {
 5941+ jQuery.offset.setOffset( this, options, i );
 5942+ });
 5943+ }
 5944+
 5945+ if ( !elem || !elem.ownerDocument ) {
 5946+ return null;
 5947+ }
 5948+
 5949+ if ( elem === elem.ownerDocument.body ) {
 5950+ return jQuery.offset.bodyOffset( elem );
 5951+ }
 5952+
 5953+ var box = elem.getBoundingClientRect(), doc = elem.ownerDocument, body = doc.body, docElem = doc.documentElement,
 5954+ clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
 5955+ top = box.top + (self.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop ) - clientTop,
 5956+ left = box.left + (self.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft) - clientLeft;
 5957+
 5958+ return { top: top, left: left };
 5959+ };
 5960+
 5961+} else {
 5962+ jQuery.fn.offset = function( options ) {
 5963+ var elem = this[0];
 5964+
 5965+ if ( options ) {
 5966+ return this.each(function( i ) {
 5967+ jQuery.offset.setOffset( this, options, i );
 5968+ });
 5969+ }
 5970+
 5971+ if ( !elem || !elem.ownerDocument ) {
 5972+ return null;
 5973+ }
 5974+
 5975+ if ( elem === elem.ownerDocument.body ) {
 5976+ return jQuery.offset.bodyOffset( elem );
 5977+ }
 5978+
 5979+ jQuery.offset.initialize();
 5980+
 5981+ var offsetParent = elem.offsetParent, prevOffsetParent = elem,
 5982+ doc = elem.ownerDocument, computedStyle, docElem = doc.documentElement,
 5983+ body = doc.body, defaultView = doc.defaultView,
 5984+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
 5985+ top = elem.offsetTop, left = elem.offsetLeft;
 5986+
 5987+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
 5988+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
 5989+ break;
 5990+ }
 5991+
 5992+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
 5993+ top -= elem.scrollTop;
 5994+ left -= elem.scrollLeft;
 5995+
 5996+ if ( elem === offsetParent ) {
 5997+ top += elem.offsetTop;
 5998+ left += elem.offsetLeft;
 5999+
 6000+ if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && /^t(able|d|h)$/i.test(elem.nodeName)) ) {
 6001+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
 6002+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
 6003+ }
 6004+
 6005+ prevOffsetParent = offsetParent, offsetParent = elem.offsetParent;
 6006+ }
 6007+
 6008+ if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
 6009+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
 6010+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
 6011+ }
 6012+
 6013+ prevComputedStyle = computedStyle;
 6014+ }
 6015+
 6016+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
 6017+ top += body.offsetTop;
 6018+ left += body.offsetLeft;
 6019+ }
 6020+
 6021+ if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
 6022+ top += Math.max( docElem.scrollTop, body.scrollTop );
 6023+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
 6024+ }
 6025+
 6026+ return { top: top, left: left };
 6027+ };
 6028+}
 6029+
 6030+jQuery.offset = {
 6031+ initialize: function() {
 6032+ var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0,
 6033+ 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>";
 6034+
 6035+ jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
 6036+
 6037+ container.innerHTML = html;
 6038+ body.insertBefore( container, body.firstChild );
 6039+ innerDiv = container.firstChild;
 6040+ checkDiv = innerDiv.firstChild;
 6041+ td = innerDiv.nextSibling.firstChild.firstChild;
 6042+
 6043+ this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
 6044+ this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
 6045+
 6046+ checkDiv.style.position = "fixed", checkDiv.style.top = "20px";
 6047+ // safari subtracts parent border width here which is 5px
 6048+ this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
 6049+ checkDiv.style.position = checkDiv.style.top = "";
 6050+
 6051+ innerDiv.style.overflow = "hidden", innerDiv.style.position = "relative";
 6052+ this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
 6053+
 6054+ this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
 6055+
 6056+ body.removeChild( container );
 6057+ body = container = innerDiv = checkDiv = table = td = null;
 6058+ jQuery.offset.initialize = jQuery.noop;
 6059+ },
 6060+
 6061+ bodyOffset: function( body ) {
 6062+ var top = body.offsetTop, left = body.offsetLeft;
 6063+
 6064+ jQuery.offset.initialize();
 6065+
 6066+ if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
 6067+ top += parseFloat( jQuery.curCSS(body, "marginTop", true) ) || 0;
 6068+ left += parseFloat( jQuery.curCSS(body, "marginLeft", true) ) || 0;
 6069+ }
 6070+
 6071+ return { top: top, left: left };
 6072+ },
 6073+
 6074+ setOffset: function( elem, options, i ) {
 6075+ // set position first, in-case top/left are set even on static elem
 6076+ if ( /static/.test( jQuery.curCSS( elem, "position" ) ) ) {
 6077+ elem.style.position = "relative";
 6078+ }
 6079+ var curElem = jQuery( elem ),
 6080+ curOffset = curElem.offset(),
 6081+ curTop = parseInt( jQuery.curCSS( elem, "top", true ), 10 ) || 0,
 6082+ curLeft = parseInt( jQuery.curCSS( elem, "left", true ), 10 ) || 0;
 6083+
 6084+ if ( jQuery.isFunction( options ) ) {
 6085+ options = options.call( elem, i, curOffset );
 6086+ }
 6087+
 6088+ var props = {
 6089+ top: (options.top - curOffset.top) + curTop,
 6090+ left: (options.left - curOffset.left) + curLeft
 6091+ };
 6092+
 6093+ if ( "using" in options ) {
 6094+ options.using.call( elem, props );
 6095+ } else {
 6096+ curElem.css( props );
 6097+ }
 6098+ }
 6099+};
 6100+
 6101+
 6102+jQuery.fn.extend({
 6103+ position: function() {
 6104+ if ( !this[0] ) {
 6105+ return null;
 6106+ }
 6107+
 6108+ var elem = this[0],
 6109+
 6110+ // Get *real* offsetParent
 6111+ offsetParent = this.offsetParent(),
 6112+
 6113+ // Get correct offsets
 6114+ offset = this.offset(),
 6115+ parentOffset = /^body|html$/i.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
 6116+
 6117+ // Subtract element margins
 6118+ // note: when an element has margin: auto the offsetLeft and marginLeft
 6119+ // are the same in Safari causing offset.left to incorrectly be 0
 6120+ offset.top -= parseFloat( jQuery.curCSS(elem, "marginTop", true) ) || 0;
 6121+ offset.left -= parseFloat( jQuery.curCSS(elem, "marginLeft", true) ) || 0;
 6122+
 6123+ // Add offsetParent borders
 6124+ parentOffset.top += parseFloat( jQuery.curCSS(offsetParent[0], "borderTopWidth", true) ) || 0;
 6125+ parentOffset.left += parseFloat( jQuery.curCSS(offsetParent[0], "borderLeftWidth", true) ) || 0;
 6126+
 6127+ // Subtract the two offsets
 6128+ return {
 6129+ top: offset.top - parentOffset.top,
 6130+ left: offset.left - parentOffset.left
 6131+ };
 6132+ },
 6133+
 6134+ offsetParent: function() {
 6135+ return this.map(function() {
 6136+ var offsetParent = this.offsetParent || document.body;
 6137+ while ( offsetParent && (!/^body|html$/i.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
 6138+ offsetParent = offsetParent.offsetParent;
 6139+ }
 6140+ return offsetParent;
 6141+ });
 6142+ }
 6143+});
 6144+
 6145+
 6146+// Create scrollLeft and scrollTop methods
 6147+jQuery.each( ["Left", "Top"], function( i, name ) {
 6148+ var method = "scroll" + name;
 6149+
 6150+ jQuery.fn[ method ] = function(val) {
 6151+ var elem = this[0], win;
 6152+
 6153+ if ( !elem ) {
 6154+ return null;
 6155+ }
 6156+
 6157+ if ( val !== undefined ) {
 6158+ // Set the scroll offset
 6159+ return this.each(function() {
 6160+ win = getWindow( this );
 6161+
 6162+ if ( win ) {
 6163+ win.scrollTo(
 6164+ !i ? val : jQuery(win).scrollLeft(),
 6165+ i ? val : jQuery(win).scrollTop()
 6166+ );
 6167+
 6168+ } else {
 6169+ this[ method ] = val;
 6170+ }
 6171+ });
 6172+ } else {
 6173+ win = getWindow( elem );
 6174+
 6175+ // Return the scroll offset
 6176+ return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
 6177+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
 6178+ win.document.body[ method ] :
 6179+ elem[ method ];
 6180+ }
 6181+ };
 6182+});
 6183+
 6184+function getWindow( elem ) {
 6185+ return ("scrollTo" in elem && elem.document) ?
 6186+ elem :
 6187+ elem.nodeType === 9 ?
 6188+ elem.defaultView || elem.parentWindow :
 6189+ false;
 6190+}
 6191+// Create innerHeight, innerWidth, outerHeight and outerWidth methods
 6192+jQuery.each([ "Height", "Width" ], function( i, name ) {
 6193+
 6194+ var type = name.toLowerCase();
 6195+
 6196+ // innerHeight and innerWidth
 6197+ jQuery.fn["inner" + name] = function() {
 6198+ return this[0] ?
 6199+ jQuery.css( this[0], type, false, "padding" ) :
 6200+ null;
 6201+ };
 6202+
 6203+ // outerHeight and outerWidth
 6204+ jQuery.fn["outer" + name] = function( margin ) {
 6205+ return this[0] ?
 6206+ jQuery.css( this[0], type, false, margin ? "margin" : "border" ) :
 6207+ null;
 6208+ };
 6209+
 6210+ jQuery.fn[ type ] = function( size ) {
 6211+ // Get window width or height
 6212+ var elem = this[0];
 6213+ if ( !elem ) {
 6214+ return size == null ? null : this;
 6215+ }
 6216+
 6217+ if ( jQuery.isFunction( size ) ) {
 6218+ return this.each(function( i ) {
 6219+ var self = jQuery( this );
 6220+ self[ type ]( size.call( this, i, self[ type ]() ) );
 6221+ });
 6222+ }
 6223+
 6224+ return ("scrollTo" in elem && elem.document) ? // does it walk and quack like a window?
 6225+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
 6226+ elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] ||
 6227+ elem.document.body[ "client" + name ] :
 6228+
 6229+ // Get document width or height
 6230+ (elem.nodeType === 9) ? // is it a document
 6231+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
 6232+ Math.max(
 6233+ elem.documentElement["client" + name],
 6234+ elem.body["scroll" + name], elem.documentElement["scroll" + name],
 6235+ elem.body["offset" + name], elem.documentElement["offset" + name]
 6236+ ) :
 6237+
 6238+ // Get or set width or height on the element
 6239+ size === undefined ?
 6240+ // Get width or height on the element
 6241+ jQuery.css( elem, type ) :
 6242+
 6243+ // Set the width or height on the element (default to pixels if value is unitless)
 6244+ this.css( type, typeof size === "string" ? size : size + "px" );
 6245+ };
 6246+
 6247+});
 6248+// Expose jQuery to the global object
 6249+window.jQuery = window.$ = jQuery;
 6250+
 6251+})(window);
Property changes on: trunk/extensions/Reflect/client/js/third_party/jquery-1.4.2.js
___________________________________________________________________
Added: svn:eol-style
16252 + native
Index: trunk/extensions/Reflect/client/templates/templates.html
@@ -0,0 +1,210 @@
 2+<script type="text/html" id="reflect_template_new_bullet_dialog">
 3+<![CDATA[
 4+ <div class="new_bullet_prompt">
 5+ <ul>
 6+ <li class=elicitation>Add a point that <%= this.commenter %> makes...</li>
 7+ <li class=count>
 8+ <a title="Please limit your bullet to 140 characters or less."><span class=count></span></a>
 9+ </li>
 10+ </ul>
 11+ </div>
 12+ <table class="new_bullet_wrapper reflect">
 13+ <tr>
 14+ <td class=new_bullet_text_wrap>
 15+ <textarea class=new_bullet_text><% if (this.txt) %><%= this.txt %></textarea>
 16+ </td>
 17+ <td class=submit_buttons>
 18+ <div><button class="cancel_bullet"><img src="<%= this.media_dir %>/cancel2.png" ></button></div>
 19+ </td>
 20+ </tr>
 21+ <tr class=submit_footer>
 22+ <td>
 23+ <ul>
 24+ <li class=submit>
 25+ <button class="bullet_submit">Done</button>
 26+ </li>
 27+ <li class=be_neutral>
 28+ <a title="Someone else reading your summary bullet point should not be able to tell whether YOU agree or disagree it.">
 29+ don't respond, <span class="big_word">summarize</span>
 30+ </a>
 31+ </li>
 32+ </ul>
 33+ </td>
 34+ </tr>
 35+ </table>
 36+
 37+]]>
 38+</script>
 39+
 40+<script type="text/html" id="reflect_template_bullet_highlight">
 41+<![CDATA[
 42+ <tbody>
 43+ <tr>
 44+ <td class="new_bullet_text_wrap connect_directions">Please click the relevant sentences</td>
 45+ <td class="submit_buttons">
 46+ <div>
 47+ <button class="cancel_bullet">
 48+ <img src="<%= this.media_dir %>/cancel2.png">
 49+ </button>
 50+ </div>
 51+ </td>
 52+ </tr>
 53+ <tr class="submit_footer">
 54+ <td>
 55+ <ul>
 56+ <li class="submit">
 57+ <button class="bullet_submit">Done</button>
 58+ </li>
 59+ </ul>
 60+ </td>
 61+ </tr>
 62+ </tbody>
 63+]]>
 64+</script>
 65+
 66+<script type="text/html" id="reflect_template_new_response">
 67+<![CDATA[
 68+ <ul class="rebutt_list" >
 69+ <li class=img>
 70+ <% if(this.sig == "2") { %>
 71+ <span class="response_yes">+</span>
 72+ <% } else if(this.sig == "1") { %>
 73+ <span class="response_maybe">!</span>
 74+ <% } else if (this.sig == "0"){ %>
 75+ <span class="response_no">-</span>
 76+ <% } %>
 77+ </li>
 78+ <li class=rebutt_txt><%= this.text %> <span class=username><a class=user><%= this.user %></a></span></li>
 79+ </ul>
 80+ <ul class=response_footer_wrapper>
 81+ <li class=modify_operation>
 82+ <button class="modify">
 83+ <a title="modify">
 84+ <img class="base" src="<%= this.media_dir %>/edit.png">
 85+ <img title="Modify" class="hover" src="<%= this.media_dir %>/edit_hover.png">
 86+ </a>
 87+ </button>
 88+ </li>
 89+ <li class="delete_operation">
 90+ <button class="delete">
 91+ <img class=base src="<%= this.media_dir %>/delete_gray.png">
 92+ <img title="Delete" class=hover src="<%= this.media_dir %>/delete_red.png">
 93+ </button>
 94+ </li>
 95+ <li class="dispute_operation">
 96+ <span class="base">
 97+ <img class="base" src="<%= this.media_dir %>/comment-flag.png">
 98+ <img class=hover src="<%= this.media_dir %>/comment-flag-hover.png">
 99+ </span>
 100+ <ul class=bullet_report_problem>
 101+ <li>not written neutrally</li>
 102+ </ul>
 103+ </li>
 104+ </ul>
 105+ <div style="clear:both"></div>
 106+]]>
 107+</script>
 108+
 109+
 110+
 111+<script type="text/html" id="reflect_template_new_bullet_prompt">
 112+<![CDATA[
 113+ <button class="add_bullet" type="button">
 114+ Add a point that <%= this.commenter %> makes
 115+ </button>
 116+]]>
 117+</script>
 118+
 119+<script type="text/html" id="reflect_template_response_dialog">
 120+<![CDATA[
 121+ <ul class="response_def">
 122+ <li class="response_prompt">
 123+ <label class="prompt">Did you make this point?</label>
 124+ <ul class=response_eval>
 125+ <li><input type="radio" name="accurate-<%=this.bullet_id %>" value="2" <% if(this.sig == "2"){ %> CHECKED <% } %>>Yes</li>
 126+ <li><input type="radio" name="accurate-<%=this.bullet_id %>" value="1" <% if(this.sig == "1"){ %> CHECKED <% } %>>Kind of...</li>
 127+ <li><input type="radio" name="accurate-<%=this.bullet_id %>" value="0" <% if(this.sig == "0"){ %> CHECKED <% } %>>No</li>
 128+ </ul>
 129+ </li>
 130+ <li class=response_dialog>
 131+ <table class="new_bullet_wrapper reflect">
 132+ <tr>
 133+ <td class=new_bullet_text_wrap>
 134+ <textarea class="new_bullet_text"><% if(this.text) %><%= this.text %></textarea>
 135+ </td>
 136+ <td class=submit_buttons>
 137+ <div>
 138+ <button class="cancel_bullet">
 139+ <img src="<%= this.media_dir %>/cancel2.png">
 140+ </button>
 141+ </div>
 142+ </td>
 143+ </tr>
 144+ <tr class=submit_footer>
 145+ <td>
 146+ <ul>
 147+ <li class=submit>
 148+ <button class="bullet_submit">Done</button>
 149+ </li>
 150+ <li class=count>
 151+ <a title="Please limit your response to 140 characters or less.">
 152+ <span class="count"></span>
 153+ </a>
 154+ </li>
 155+ </ul>
 156+ </td>
 157+ </tr>
 158+ </table>
 159+ </li>
 160+ </ul>
 161+
 162+]]>
 163+</script>
 164+
 165+<script type="text/html" id="reflect_template_bullet">
 166+<![CDATA[
 167+ <div class="bullet_main">
 168+ <ul class="bullet_main_wrapper">
 169+ <li class="bullet_text">
 170+ <%= this.bullet_text %> <span class="username"><a class="user"><%= this.user %></a></span>
 171+ </li>
 172+ <li class="bullet_footer_wrapper">
 173+ <ul class=bullet_operations>
 174+ <li class=modify_operation>
 175+ <button class=modify>
 176+ <a title="modify">
 177+ <img class=base src="<%= this.media_dir %>/edit.png"></img>
 178+ <img title="Modify" class=hover src="<%= this.media_dir %>/edit_hover.png"></img>
 179+ </a>
 180+ </button>
 181+ </li>
 182+ <li class=delete_operation>
 183+ <button class=delete>
 184+ <a title="delete">
 185+ <img class=base src="<%= this.media_dir %>/delete_gray.png"></img>
 186+ <img title="Delete" class=hover src="<%= this.media_dir %>/delete_red.png"></img>
 187+ </a>
 188+ </button>
 189+ </li>
 190+ <li class=dispute_operation>
 191+ <span class="bullet_prompt_problem">
 192+ <img class=base src="<%= this.media_dir %>/comment-flag.png"></img>
 193+ <img class=hover src="<%= this.media_dir %>/comment-flag-hover.png"></img>
 194+ </span>
 195+ <ul class=bullet_report_problem>
 196+ <li class="flag" name="input">not a summary</li>
 197+ <li class="flag" name="neutral">not written neutrally</li>
 198+ <li class="flag" name="accurate"><a class=user><%= this.commenter %></a> didn't say this</li>
 199+ <li class="flag" name="duplicate">duplicate bullet</li>
 200+ </ul>
 201+ </li>
 202+ </ul>
 203+ </li>
 204+ </ul>
 205+ <div class="cl"></div>
 206+ </div>
 207+ <div class="responses"><ul /></div>
 208+]]>
 209+</script>
 210+
 211+

Comments

#Comment by Reedy (talk | contribs)   03:45, 24 August 2010

You're missing svn:keywords Id from the API stuff at least

#Comment by Tkriplean (talk | contribs)   17:38, 24 August 2010

(reposting as I didn't see the "reply" button...)

Ok, i added svn:keywords Id to all files in svn Reflect repo

Thanks!

#Comment by Reedy (talk | contribs)   17:52, 24 August 2010

Doesn't matter too much. I've commented on the thread, so still get pinged an email. That and I'd noticed it on IRC ;)

#Comment by Tkriplean (talk | contribs)   17:37, 24 August 2010

Ok, i added svn:keywords Id to all files in svn Reflect repo

Thanks!

Status & tagging log