\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/templates/list.html b/common/src/main/webapp/framework/browser/templates/list.html
new file mode 100644
index 0000000..ede8b83
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/templates/list.html
@@ -0,0 +1,47 @@
+
+
+
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/templates/management.html b/common/src/main/webapp/framework/browser/templates/management.html
new file mode 100644
index 0000000..d6fbcb2
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/templates/management.html
@@ -0,0 +1,130 @@
+
+
+
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/templates/table.html b/common/src/main/webapp/framework/browser/templates/table.html
new file mode 100644
index 0000000..603c13a
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/templates/table.html
@@ -0,0 +1,39 @@
+
+
+
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/templates/textarea.html b/common/src/main/webapp/framework/browser/templates/textarea.html
new file mode 100644
index 0000000..6f263f9
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/templates/textarea.html
@@ -0,0 +1,121 @@
+
+
+
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/thirdparty/License.txt b/common/src/main/webapp/framework/browser/thirdparty/License.txt
new file mode 100644
index 0000000..8e698ec
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/thirdparty/License.txt
@@ -0,0 +1,362 @@
+THIS LICENSE FILE CONTAINS THE LICENSE APPLICABLE DEPENDING ON THE TYPE OF CONTRIBUTIONS.
+
+APACHE LICENSE 2 IS APPLICABLE FOR SOURCE CODE, CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL FOR DOCUMENTATION
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+Apache License Version 2.0, January 2004 http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Attribution 4.0 International
+
+https://creativecommons.org/licenses/by/4.0/legalcode
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More_considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+ c. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+ d. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+ e. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+ f. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+ g. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+ h. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+ i. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+ j. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+ k. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+Section 2 -- Scope.
+
+ a. License grant.
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+ b. produce, reproduce, and Share Adapted Material.
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+ 5. Downstream recipients.
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+ b. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+ b. Other rights.
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the following conditions.
+
+ a. Attribution.
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+ ii. a copyright notice;
+ iii. a notice that refers to this Public License;
+ iv. a notice that refers to the disclaimer of
+ warranties;
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+ 4. If You Share Adapted Material You produce, the Adapter's
+ License You apply must not prevent recipients of the Adapted
+ Material from complying with this Public License.
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material; and
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+ 2. upon express reinstatement by the Licensor.
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/bootstrap.min.css b/common/src/main/webapp/framework/browser/thirdparty/css/bootstrap.min.css
new file mode 100644
index 0000000..2574229
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/thirdparty/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v3.1.1 (http://getbootstrap.com)
+ * Copyright 2011-2014 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#F5F5F5}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}input[type=date]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:400;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:50px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857143;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.42857143px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}@media print{.hidden-print{display:none!important}}
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/Thumbs.db b/common/src/main/webapp/framework/browser/thirdparty/css/img/Thumbs.db
new file mode 100644
index 0000000..7eb0d3d
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/Thumbs.db differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/1_close.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/1_close.png
new file mode 100644
index 0000000..68ccb3c
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/1_close.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/1_open.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/1_open.png
new file mode 100644
index 0000000..d6ff36d
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/1_open.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/2.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/2.png
new file mode 100644
index 0000000..9eff506
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/2.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/3.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/3.png
new file mode 100644
index 0000000..d7ba6d0
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/3.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/4.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/4.png
new file mode 100644
index 0000000..753e2bf
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/4.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/5.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/5.png
new file mode 100644
index 0000000..0c5eccd
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/5.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/6.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/6.png
new file mode 100644
index 0000000..070b835
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/6.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/7.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/7.png
new file mode 100644
index 0000000..532b037
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/7.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/8.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/8.png
new file mode 100644
index 0000000..a8f3a86
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/8.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/9.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/9.png
new file mode 100644
index 0000000..4db73cd
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/diy/9.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/line_conn.gif b/common/src/main/webapp/framework/browser/thirdparty/css/img/line_conn.gif
new file mode 100644
index 0000000..d561d36
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/line_conn.gif differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/loading.gif b/common/src/main/webapp/framework/browser/thirdparty/css/img/loading.gif
new file mode 100644
index 0000000..e8c2892
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/loading.gif differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/zTreeStandard.gif b/common/src/main/webapp/framework/browser/thirdparty/css/img/zTreeStandard.gif
new file mode 100644
index 0000000..50c94fd
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/zTreeStandard.gif differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/img/zTreeStandard.png b/common/src/main/webapp/framework/browser/thirdparty/css/img/zTreeStandard.png
new file mode 100644
index 0000000..ffda01e
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/css/img/zTreeStandard.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/magic-check.css b/common/src/main/webapp/framework/browser/thirdparty/css/magic-check.css
new file mode 100644
index 0000000..4a4ccf7
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/thirdparty/css/magic-check.css
@@ -0,0 +1,123 @@
+@keyframes hover-color {
+ from {
+ border-color: #c0c0c0; }
+ to {
+ border-color: #3e97eb; } }
+
+.magic-radio,
+.magic-checkbox {
+ position: absolute;
+ display: none; }
+
+.magic-radio[disabled],
+.magic-checkbox[disabled] {
+ cursor: not-allowed; }
+
+.magic-radio + label,
+.magic-checkbox + label {
+ position: relative;
+ display: block;
+ padding-left: 30px;
+ cursor: pointer;
+ vertical-align: middle;
+ font-weight:normal;
+ text-align: left;}
+.magic-radio + label:hover:before,
+.magic-checkbox + label:hover:before {
+ animation-duration: 0.4s;
+ animation-fill-mode: both;
+ animation-name: hover-color; }
+.magic-radio + label:before,
+.magic-checkbox + label:before {
+ position: absolute;
+ top: 0;
+ left: 0;
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ content: '';
+ border: 1px solid #4ac9ff; }
+.magic-radio + label:after,
+.magic-checkbox + label:after {
+ position: absolute;
+ display: none;
+ content: ''; }
+
+.magic-radio[disabled] + label,
+.magic-checkbox[disabled] + label {
+ cursor: not-allowed;
+ color: #e4e4e4; }
+.magic-radio[disabled] + label:hover, .magic-radio[disabled] + label:before, .magic-radio[disabled] + label:after,
+.magic-checkbox[disabled] + label:hover,
+.magic-checkbox[disabled] + label:before,
+.magic-checkbox[disabled] + label:after {
+ cursor: not-allowed; }
+.magic-radio[disabled] + label:hover:before,
+.magic-checkbox[disabled] + label:hover:before {
+ border: 1px solid #e4e4e4;
+ animation-name: none; }
+.magic-radio[disabled] + label:before,
+.magic-checkbox[disabled] + label:before {
+ border-color: #e4e4e4; }
+
+.magic-radio:checked + label:before,
+.magic-checkbox:checked + label:before {
+ animation-name: none; }
+
+.magic-radio:checked + label:after,
+.magic-checkbox:checked + label:after {
+ display: block; }
+
+.magic-radio + label:before {
+ border-radius: 50%; }
+
+.magic-radio + label:after {
+ top: 6px;
+ left: 6px;
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: #3e97eb; }
+
+.magic-radio:checked + label:before {
+ border: 1px solid #3e97eb; }
+
+.magic-radio:checked[disabled] + label:before {
+ border: 1px solid #c9e2f9; }
+
+.magic-radio:checked[disabled] + label:after {
+ background: #c9e2f9; }
+
+.magic-checkbox + label:before {
+ border-radius: 3px; }
+
+.magic-checkbox + label:after {
+ top: 2px;
+ left: 7px;
+ box-sizing: border-box;
+ width: 6px;
+ height: 12px;
+ transform: rotate(45deg);
+ border-width: 2px;
+ border-style: solid;
+ border-color: #fff;
+ border-top: 0;
+ border-left: 0; }
+
+.magic-checkbox:checked + label:before {
+ border: #3e97eb;
+ background: #3e97eb; }
+
+.magic-checkbox:checked[disabled] + label:before {
+ border: #c9e2f9;
+ background: #c9e2f9; }
+
+.radio-toolbar label {
+ background:Red;
+ border:1px solid green;
+ padding:2px 10px;
+}
+
+.magic-radio:checked + label {
+ font-weight: bold;
+}
diff --git a/common/src/main/webapp/framework/browser/thirdparty/css/zTreeStyle.css b/common/src/main/webapp/framework/browser/thirdparty/css/zTreeStyle.css
new file mode 100644
index 0000000..4a1705b
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/thirdparty/css/zTreeStyle.css
@@ -0,0 +1,97 @@
+/*-------------------------------------
+zTree Style
+
+version: 3.5.19
+author: Hunter.z
+email: hunter.z@263.net
+website: http://code.google.com/p/jquerytree/
+
+-------------------------------------*/
+
+.ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif}
+.ztree {margin:0; padding:5px; color:#333}
+.ztree li{padding:0; margin:0; list-style:none; line-height:14px; text-align:left; white-space:nowrap; outline:0}
+.ztree li ul{ margin:0; padding:0 0 0 18px}
+.ztree li ul.line{ background:url(./img/line_conn.gif) 0 0 repeat-y;}
+
+.ztree li a {padding:1px 3px 0 0; margin:0; cursor:pointer; height:17px; color:#333; background-color: transparent;
+ text-decoration:none; vertical-align:top; display: inline-block}
+.ztree li a:hover {text-decoration:underline}
+.ztree li a.curSelectedNode {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;}
+.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;}
+.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#316AC5; color:white; height:16px; border:1px #316AC5 solid;
+ opacity:0.8; filter:alpha(opacity=80)}
+.ztree li a.tmpTargetNode_prev {}
+.ztree li a.tmpTargetNode_next {}
+.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0;
+ font-size:12px; border:1px #7EC4CC solid; *border:0px}
+.ztree li span {line-height:16px; margin-right:2px}
+.ztree li span.button {line-height:0; margin:0; width:16px; height:16px; display: inline-block; vertical-align:middle;
+ border:0 none; cursor: pointer;outline:none;
+ background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
+ background-image:url("./img/zTreeStandard.png"); *background-image:url("./img/zTreeStandard.gif")}
+
+.ztree li span.button.chk {width:13px; height:13px; margin:0 3px 0 0; cursor: auto}
+.ztree li span.button.chk.checkbox_false_full {background-position:0 0}
+.ztree li span.button.chk.checkbox_false_full_focus {background-position:0 -14px}
+.ztree li span.button.chk.checkbox_false_part {background-position:0 -28px}
+.ztree li span.button.chk.checkbox_false_part_focus {background-position:0 -42px}
+.ztree li span.button.chk.checkbox_false_disable {background-position:0 -56px}
+.ztree li span.button.chk.checkbox_true_full {background-position:-14px 0}
+.ztree li span.button.chk.checkbox_true_full_focus {background-position:-14px -14px}
+.ztree li span.button.chk.checkbox_true_part {background-position:-14px -28px}
+.ztree li span.button.chk.checkbox_true_part_focus {background-position:-14px -42px}
+.ztree li span.button.chk.checkbox_true_disable {background-position:-14px -56px}
+.ztree li span.button.chk.radio_false_full {background-position:-28px 0}
+.ztree li span.button.chk.radio_false_full_focus {background-position:-28px -14px}
+.ztree li span.button.chk.radio_false_part {background-position:-28px -28px}
+.ztree li span.button.chk.radio_false_part_focus {background-position:-28px -42px}
+.ztree li span.button.chk.radio_false_disable {background-position:-28px -56px}
+.ztree li span.button.chk.radio_true_full {background-position:-42px 0}
+.ztree li span.button.chk.radio_true_full_focus {background-position:-42px -14px}
+.ztree li span.button.chk.radio_true_part {background-position:-42px -28px}
+.ztree li span.button.chk.radio_true_part_focus {background-position:-42px -42px}
+.ztree li span.button.chk.radio_true_disable {background-position:-42px -56px}
+
+.ztree li span.button.switch {width:18px; height:18px}
+.ztree li span.button.root_open{background-position:-92px -54px}
+.ztree li span.button.root_close{background-position:-74px -54px}
+.ztree li span.button.roots_open{background-position:-92px 0}
+.ztree li span.button.roots_close{background-position:-74px 0}
+.ztree li span.button.center_open{background-position:-92px -18px}
+.ztree li span.button.center_close{background-position:-74px -18px}
+.ztree li span.button.bottom_open{background-position:-92px -36px}
+.ztree li span.button.bottom_close{background-position:-74px -36px}
+.ztree li span.button.noline_open{background-position:-92px -72px}
+.ztree li span.button.noline_close{background-position:-74px -72px}
+.ztree li span.button.root_docu{ background:none;}
+.ztree li span.button.roots_docu{background-position:-56px 0}
+.ztree li span.button.center_docu{background-position:-56px -18px}
+.ztree li span.button.bottom_docu{background-position:-56px -36px}
+.ztree li span.button.noline_docu{ background:none;}
+
+.ztree li span.button.ico_open{margin-right:2px; background-position:-110px -16px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.ico_close{margin-right:2px; background-position:-110px 0; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.ico_docu{margin-right:2px; background-position:-110px -32px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.edit {margin-right:2px; background-position:-110px -48px; vertical-align:top; *vertical-align:middle}
+.ztree li span.button.remove {margin-right:2px; background-position:-110px -64px; vertical-align:top; *vertical-align:middle}
+
+.ztree li span.button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}
+
+ul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}
+
+span.tmpzTreeMove_arrow {width:16px; height:16px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;
+ background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;
+ background-position:-110px -80px; background-image:url("./img/zTreeStandard.png"); *background-image:url("./img/zTreeStandard.gif")}
+
+ul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)}
+.zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute}
+
+/* level style*/
+/*.ztree li span.button.level0 {
+ display:none;
+}
+.ztree li ul.level0 {
+ padding:0;
+ background:none;
+}*/
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.eot b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.eot
new file mode 100644
index 0000000..b93a495
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.eot differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.svg b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.svg
new file mode 100644
index 0000000..94fb549
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.svg
@@ -0,0 +1,288 @@
+
+
+
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.ttf b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.ttf
new file mode 100644
index 0000000..1413fc6
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.ttf differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.woff b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.woff
new file mode 100644
index 0000000..9e61285
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.woff differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.woff2 b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.woff2
new file mode 100644
index 0000000..64539b5
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/fonts/glyphicons-halflings-regular.woff2 differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/images/collapse_arrow.png b/common/src/main/webapp/framework/browser/thirdparty/images/collapse_arrow.png
new file mode 100644
index 0000000..8830741
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/images/collapse_arrow.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/images/delete.png b/common/src/main/webapp/framework/browser/thirdparty/images/delete.png
new file mode 100644
index 0000000..737f879
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/images/delete.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/images/edit.png b/common/src/main/webapp/framework/browser/thirdparty/images/edit.png
new file mode 100644
index 0000000..68d7625
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/images/edit.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/images/expand_arrow.png b/common/src/main/webapp/framework/browser/thirdparty/images/expand_arrow.png
new file mode 100644
index 0000000..f8935e1
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/images/expand_arrow.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/images/openo.png b/common/src/main/webapp/framework/browser/thirdparty/images/openo.png
new file mode 100644
index 0000000..328b735
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/images/openo.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/images/searchicon.png b/common/src/main/webapp/framework/browser/thirdparty/images/searchicon.png
new file mode 100644
index 0000000..960dea1
Binary files /dev/null and b/common/src/main/webapp/framework/browser/thirdparty/images/searchicon.png differ
diff --git a/common/src/main/webapp/framework/browser/thirdparty/js/angular-ui-router.min.js b/common/src/main/webapp/framework/browser/thirdparty/js/angular-ui-router.min.js
new file mode 100644
index 0000000..ef1e08e
--- /dev/null
+++ b/common/src/main/webapp/framework/browser/thirdparty/js/angular-ui-router.min.js
@@ -0,0 +1,8 @@
+/**
+ * State-based routing for AngularJS
+ * @version v0.3.1
+ * @link http://angular-ui.github.com/
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="ui.router"),function(a,b,c){"use strict";function d(a,b){return R(new(R(function(){},{prototype:a})),b)}function e(a){return Q(arguments,function(b){b!==a&&Q(b,function(b,c){a.hasOwnProperty(c)||(a[c]=b)})}),a}function f(a,b){var c=[];for(var d in a.path){if(a.path[d]!==b.path[d])break;c.push(a.path[d])}return c}function g(a){if(Object.keys)return Object.keys(a);var b=[];return Q(a,function(a,c){b.push(c)}),b}function h(a,b){if(Array.prototype.indexOf)return a.indexOf(b,Number(arguments[2])||0);var c=a.length>>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function i(a,b,c,d){var e,i=f(c,d),j={},k=[];for(var l in i)if(i[l]&&i[l].params&&(e=g(i[l].params),e.length))for(var m in e)h(k,e[m])>=0||(k.push(e[m]),j[e[m]]=a[e[m]]);return R({},j,b)}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(s[c]=d,N(a))q.push(c,[function(){return b.get(a)}],j);else{var e=b.annotate(a);Q(e,function(a){a!==c&&i.hasOwnProperty(a)&&n(i[a],a)}),q.push(c,a,e)}r.pop(),s[c]=f}}function o(a){return O(a)&&a.then&&a.$$promises}if(!O(i))throw new Error("'invocables' must be an object");var p=g(i||{}),q=[],r=[],s={};return Q(i,n),i=r=s=null,function(d,f,g){function h(){--u||(v||e(t,f.$$values),r.$$values=t,r.$$promises=r.$$promises||!0,delete r.$$inheritedValues,n.resolve(t))}function i(a){r.$$failure=a,n.reject(a)}function j(c,e,f){function j(a){l.reject(a),i(a)}function k(){if(!L(r.$$failure))try{l.resolve(b.invoke(e,g,t)),l.promise.then(function(a){t[c]=a,h()},j)}catch(a){j(a)}}var l=a.defer(),m=0;Q(f,function(a){s.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,s[a].then(function(b){t[a]=b,--m||k()},j))}),m||k(),s[c]=l.promise}if(o(d)&&g===c&&(g=f,f=d,d=null),d){if(!O(d))throw new Error("'locals' must be an object")}else d=k;if(f){if(!o(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=l;var n=a.defer(),r=n.promise,s=r.$$promises={},t=R({},d),u=1+q.length/3,v=!1;if(L(f.$$failure))return i(f.$$failure),r;f.$$inheritedValues&&e(t,m(f.$$inheritedValues,p)),R(s,f.$$promises),f.$$values?(v=e(t,m(f.$$values,p)),r.$$inheritedValues=m(f.$$values,p),h()):(f.$$inheritedValues&&(r.$$inheritedValues=m(f.$$inheritedValues,p)),f.then(h,i));for(var w=0,x=q.length;x>w;w+=3)d.hasOwnProperty(q[w])?h():j(q[w],q[w+1],q[w+2]);return r}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function q(a,b,c){this.fromConfig=function(a,b,c){return L(a.template)?this.fromString(a.template,b):L(a.templateUrl)?this.fromUrl(a.templateUrl,b):L(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return M(a)?a(b):a},this.fromUrl=function(c,d){return M(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b,headers:{Accept:"text/html"}}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function r(a,b,e){function f(b,c,d,e){if(q.push(b),o[b])return o[b];if(!/^\w+([-.]+\w+)*(?:\[\])?$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(p[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");return p[b]=new U.Param(b,c,d,e),p[b]}function g(a,b,c,d){var e=["",""],f=a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&");if(!b)return f;switch(c){case!1:e=["(",")"+(d?"?":"")];break;case!0:f=f.replace(/\/$/,""),e=["(?:/(",")|/)?"];break;default:e=["("+c+"|",")?"]}return f+e[0]+b+e[1]}function h(e,f){var g,h,i,j,k;return g=e[2]||e[3],k=b.params[g],i=a.substring(m,e.index),h=f?e[4]:e[4]||("*"==e[1]?".*":null),h&&(j=U.type(h)||d(U.type("string"),{pattern:new RegExp(h,b.caseInsensitive?"i":c)})),{id:g,regexp:h,segment:i,type:j,cfg:k}}b=R({params:{}},O(b)?b:{});var i,j=/([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,k=/([:]?)([\w\[\].-]+)|\{([\w\[\].-]+)(?:\:\s*((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,l="^",m=0,n=this.segments=[],o=e?e.params:{},p=this.params=e?e.params.$$new():new U.ParamSet,q=[];this.source=a;for(var r,s,t;(i=j.exec(a))&&(r=h(i,!1),!(r.segment.indexOf("?")>=0));)s=f(r.id,r.type,r.cfg,"path"),l+=g(r.segment,s.type.pattern.source,s.squash,s.isOptional),n.push(r.segment),m=j.lastIndex;t=a.substring(m);var u=t.indexOf("?");if(u>=0){var v=this.sourceSearch=t.substring(u);if(t=t.substring(0,u),this.sourcePath=a.substring(0,m+u),v.length>0)for(m=0;i=k.exec(v);)r=h(i,!0),s=f(r.id,r.type,r.cfg,"search"),m=j.lastIndex}else this.sourcePath=a,this.sourceSearch="";l+=g(t)+(b.strict===!1?"/?":"")+"$",n.push(t),this.regexp=new RegExp(l,b.caseInsensitive?"i":c),this.prefix=n[0],this.$$paramNames=q}function s(a){R(this,a)}function t(){function a(a){return null!=a?a.toString().replace(/~/g,"~~").replace(/\//g,"~2F"):a}function e(a){return null!=a?a.toString().replace(/~2F/g,"/").replace(/~~/g,"~"):a}function f(){return{strict:p,caseInsensitive:m}}function i(a){return M(a)||P(a)&&M(a[a.length-1])}function j(){for(;w.length;){var a=w.shift();if(a.pattern)throw new Error("You cannot override a type's .pattern at runtime.");b.extend(u[a.name],l.invoke(a.def))}}function k(a){R(this,a||{})}U=this;var l,m=!1,p=!0,q=!1,u={},v=!0,w=[],x={string:{encode:a,decode:e,is:function(a){return null==a||!L(a)||"string"==typeof a},pattern:/[^\/]*/},"int":{encode:a,decode:function(a){return parseInt(a,10)},is:function(a){return L(a)&&this.decode(a.toString())===a},pattern:/\d+/},bool:{encode:function(a){return a?1:0},decode:function(a){return 0!==parseInt(a,10)},is:function(a){return a===!0||a===!1},pattern:/0|1/},date:{encode:function(a){return this.is(a)?[a.getFullYear(),("0"+(a.getMonth()+1)).slice(-2),("0"+a.getDate()).slice(-2)].join("-"):c},decode:function(a){if(this.is(a))return a;var b=this.capture.exec(a);return b?new Date(b[1],b[2]-1,b[3]):c},is:function(a){return a instanceof Date&&!isNaN(a.valueOf())},equals:function(a,b){return this.is(a)&&this.is(b)&&a.toISOString()===b.toISOString()},pattern:/[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,capture:/([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/},json:{encode:b.toJson,decode:b.fromJson,is:b.isObject,equals:b.equals,pattern:/[^\/]*/},any:{encode:b.identity,decode:b.identity,equals:b.equals,pattern:/.*/}};t.$$getDefaultValue=function(a){if(!i(a.value))return a.value;if(!l)throw new Error("Injectable functions cannot be called at configuration time");return l.invoke(a.value)},this.caseInsensitive=function(a){return L(a)&&(m=a),m},this.strictMode=function(a){return L(a)&&(p=a),p},this.defaultSquashPolicy=function(a){if(!L(a))return q;if(a!==!0&&a!==!1&&!N(a))throw new Error("Invalid squash policy: "+a+". Valid policies: false, true, arbitrary-string");return q=a,a},this.compile=function(a,b){return new r(a,R(f(),b))},this.isMatcher=function(a){if(!O(a))return!1;var b=!0;return Q(r.prototype,function(c,d){M(c)&&(b=b&&L(a[d])&&M(a[d]))}),b},this.type=function(a,b,c){if(!L(b))return u[a];if(u.hasOwnProperty(a))throw new Error("A type named '"+a+"' has already been defined.");return u[a]=new s(R({name:a},b)),c&&(w.push({name:a,def:c}),v||j()),this},Q(x,function(a,b){u[b]=new s(R({name:b},a))}),u=d(u,{}),this.$get=["$injector",function(a){return l=a,v=!1,j(),Q(x,function(a,b){u[b]||(u[b]=new s(a))}),this}],this.Param=function(a,d,e,f){function j(a){var b=O(a)?g(a):[],c=-1===h(b,"value")&&-1===h(b,"type")&&-1===h(b,"squash")&&-1===h(b,"array");return c&&(a={value:a}),a.$$fn=i(a.value)?a.value:function(){return a.value},a}function k(c,d,e){if(c.type&&d)throw new Error("Param '"+a+"' has two type configurations.");return d?d:c.type?b.isString(c.type)?u[c.type]:c.type instanceof s?c.type:new s(c.type):"config"===e?u.any:u.string}function m(){var b={array:"search"===f?"auto":!1},c=a.match(/\[\]$/)?{array:!0}:{};return R(b,c,e).array}function p(a,b){var c=a.squash;if(!b||c===!1)return!1;if(!L(c)||null==c)return q;if(c===!0||N(c))return c;throw new Error("Invalid squash policy: '"+c+"'. Valid policies: false, true, or arbitrary string")}function r(a,b,d,e){var f,g,i=[{from:"",to:d||b?c:""},{from:null,to:d||b?c:""}];return f=P(a.replace)?a.replace:[],N(e)&&f.push({from:e,to:c}),g=o(f,function(a){return a.from}),n(i,function(a){return-1===h(g,a.from)}).concat(f)}function t(){if(!l)throw new Error("Injectable functions cannot be called at configuration time");var a=l.invoke(e.$$fn);if(null!==a&&a!==c&&!x.type.is(a))throw new Error("Default value ("+a+") for parameter '"+x.id+"' is not an instance of Type ("+x.type.name+")");return a}function v(a){function b(a){return function(b){return b.from===a}}function c(a){var c=o(n(x.replace,b(a)),function(a){return a.to});return c.length?c[0]:a}return a=c(a),L(a)?x.type.$normalize(a):t()}function w(){return"{Param:"+a+" "+d+" squash: '"+A+"' optional: "+z+"}"}var x=this;e=j(e),d=k(e,d,f);var y=m();d=y?d.$asArray(y,"search"===f):d,"string"!==d.name||y||"path"!==f||e.value!==c||(e.value="");var z=e.value!==c,A=p(e,z),B=r(e,y,z,A);R(this,{id:a,type:d,location:f,array:y,squash:A,replace:B,isOptional:z,value:v,dynamic:c,config:e,toString:w})},k.prototype={$$new:function(){return d(this,R(new k,{$$parent:this}))},$$keys:function(){for(var a=[],b=[],c=this,d=g(k.prototype);c;)b.push(c),c=c.$$parent;return b.reverse(),Q(b,function(b){Q(g(b),function(b){-1===h(a,b)&&-1===h(d,b)&&a.push(b)})}),a},$$values:function(a){var b={},c=this;return Q(c.$$keys(),function(d){b[d]=c[d].value(a&&a[d])}),b},$$equals:function(a,b){var c=!0,d=this;return Q(d.$$keys(),function(e){var f=a&&a[e],g=b&&b[e];d[e].type.equals(f,g)||(c=!1)}),c},$$validates:function(a){var d,e,f,g,h,i=this.$$keys();for(d=0;de;e++)if(b(j[e]))return;k&&b(k)}}function o(){return i=i||e.$on("$locationChangeSuccess",n)}var p,q=g.baseHref(),r=d.url();return l||o(),{sync:function(){n()},listen:function(){return o()},update:function(a){return a?void(r=d.url()):void(d.url()!==r&&(d.url(r),d.replace()))},push:function(a,b,e){var f=a.format(b||{});null!==f&&b&&b["#"]&&(f+="#"+b["#"]),d.url(f),p=e&&e.$$avoidResync?d.url():c,e&&e.replace&&d.replace()},href:function(c,e,f){if(!c.validates(e))return null;var g=a.html5Mode();b.isObject(g)&&(g=g.enabled),g=g&&h.history;var i=c.format(e);if(f=f||{},g||null===i||(i="#"+a.hashPrefix()+i),null!==i&&e&&e["#"]&&(i+="#"+e["#"]),i=m(i,g,f.absolute),!f.absolute||!i)return i;var j=!g&&i?"/":"",k=d.port();return k=80===k||443===k?"":":"+k,[d.protocol(),"://",d.host(),k,j,i].join("")}}}var i,j=[],k=null,l=!1;this.rule=function(a){if(!M(a))throw new Error("'rule' must be a function");return j.push(a),this},this.otherwise=function(a){if(N(a)){var b=a;a=function(){return b}}else if(!M(a))throw new Error("'rule' must be a function");return k=a,this},this.when=function(a,b){var c,h=N(b);if(N(a)&&(a=d.compile(a)),!h&&!M(b)&&!P(b))throw new Error("invalid 'handler' in when()");var i={matcher:function(a,b){return h&&(c=d.compile(b),b=["$match",function(a){return c.format(a)}]),R(function(c,d){return g(c,b,a.exec(d.path(),d.search()))},{prefix:N(a.prefix)?a.prefix:""})},regex:function(a,b){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(c=b,b=["$match",function(a){return f(c,a)}]),R(function(c,d){return g(c,b,a.exec(d.path()))},{prefix:e(a)})}},j={matcher:d.isMatcher(a),regex:a instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](a,b));throw new Error("invalid 'what' in when()")},this.deferIntercept=function(a){a===c&&(a=!0),l=a},this.$get=h,h.$inject=["$location","$rootScope","$injector","$browser","$sniffer"]}function v(a,e){function f(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function m(a,b){if(!a)return c;var d=N(a),e=d?a:a.name,g=f(e);if(g){if(!b)throw new Error("No reference point given for path '"+e+"'");b=m(b);for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=z[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function n(a,b){A[a]||(A[a]=[]),A[a].push(b)}function p(a){for(var b=A[a]||[];b.length;)q(b.shift())}function q(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!N(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(z.hasOwnProperty(c))throw new Error("State '"+c+"' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):N(b.parent)?b.parent:O(b.parent)&&N(b.parent.name)?b.parent.name:"";if(e&&!z[e])return n(e,b.self);for(var f in C)M(C[f])&&(b[f]=C[f](b,C.$delegates[f]));return z[c]=b,!b[B]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){y.$current.navigable==b&&j(a,c)||y.transitionTo(b,a,{inherit:!0,location:!1})}]),p(c),b}function r(a){return a.indexOf("*")>-1}function s(a){for(var b=a.split("."),c=y.$current.name.split("."),d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return"**"===b[0]&&(c=c.slice(h(c,b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(h(c,b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length?!1:c.join("")===b.join("")}function t(a,b){return N(a)&&!L(b)?C[a]:M(b)&&N(a)?(C[a]&&!C.$delegates[a]&&(C.$delegates[a]=C[a]),C[a]=b,this):this}function u(a,b){return O(a)?b=a:b.name=a,q(b),this}function v(a,e,f,h,l,n,p,q,t){function u(b,c,d,f){var g=a.$broadcast("$stateNotFound",b,c,d);if(g.defaultPrevented)return p.update(),D;if(!g.retry)return null;if(f.$retry)return p.update(),E;var h=y.transition=e.when(g.retry);return h.then(function(){return h!==y.transition?A:(b.options.$retry=!0,y.transitionTo(b.to,b.toParams,b.options))},function(){return D}),p.update(),h}function v(a,c,d,g,i,j){function m(){var c=[];return Q(a.views,function(d,e){var g=d.resolve&&d.resolve!==a.resolve?d.resolve:{};g.$template=[function(){return f.load(e,{view:d,locals:i.globals,params:n,notify:j.notify})||""}],c.push(l.resolve(g,i.globals,i.resolve,a).then(function(c){if(M(d.controllerProvider)||P(d.controllerProvider)){var f=b.extend({},g,i.globals);c.$$controller=h.invoke(d.controllerProvider,null,f)}else c.$$controller=d.controller;c.$$state=a,c.$$controllerAs=d.controllerAs,c.$$resolveAs=d.resolveAs,i[e]=c}))}),e.all(c).then(function(){return i.globals})}var n=d?c:k(a.params.$$keys(),c),o={$stateParams:n};i.resolve=l.resolve(a.resolve,o,i.resolve,a);var p=[i.resolve.then(function(a){i.globals=a})];return g&&p.push(g),e.all(p).then(m).then(function(a){return i})}var A=e.reject(new Error("transition superseded")),C=e.reject(new Error("transition prevented")),D=e.reject(new Error("transition aborted")),E=e.reject(new Error("transition failed"));return x.locals={resolve:null,globals:{$stateParams:{}}},y={params:{},current:x.self,$current:x,transition:null},y.reload=function(a){return y.transitionTo(y.current,n,{reload:a||!0,inherit:!1,notify:!0})},y.go=function(a,b,c){return y.transitionTo(a,b,R({inherit:!0,relative:y.$current},c))},y.transitionTo=function(b,c,f){c=c||{},f=R({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,j=y.$current,l=y.params,o=j.path,q=m(b,f.relative),r=c["#"];if(!L(q)){var s={to:b,toParams:c,options:f},t=u(s,j.self,l,f);if(t)return t;if(b=s.to,c=s.toParams,f=s.options,q=m(b,f.relative),!L(q)){if(!f.relative)throw new Error("No such state '"+b+"'");throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'")}}if(q[B])throw new Error("Cannot transition to abstract state '"+b+"'");if(f.inherit&&(c=i(n,c||{},y.$current,q)),!q.params.$$validates(c))return E;c=q.params.$$values(c),b=q;var z=b.path,D=0,F=z[D],G=x.locals,H=[];if(f.reload){if(N(f.reload)||O(f.reload)){if(O(f.reload)&&!f.reload.name)throw new Error("Invalid reload state object");var I=f.reload===!0?o[0]:m(f.reload);if(f.reload&&!I)throw new Error("No such reload state '"+(N(f.reload)?f.reload:f.reload.name)+"'");for(;F&&F===o[D]&&F!==I;)G=H[D]=F.locals,D++,F=z[D]}}else for(;F&&F===o[D]&&F.ownParams.$$equals(c,l);)G=H[D]=F.locals,D++,F=z[D];if(w(b,c,j,l,G,f))return r&&(c["#"]=r),y.params=c,S(y.params,n),S(k(b.params.$$keys(),n),b.locals.globals.$stateParams),f.location&&b.navigable&&b.navigable.url&&(p.push(b.navigable.url,c,{$$avoidResync:!0,replace:"replace"===f.location}),p.update(!0)),y.transition=null,e.when(y.current);if(c=k(b.params.$$keys(),c||{}),r&&(c["#"]=r),f.notify&&a.$broadcast("$stateChangeStart",b.self,c,j.self,l,f).defaultPrevented)return a.$broadcast("$stateChangeCancel",b.self,c,j.self,l),null==y.transition&&p.update(),C;for(var J=e.when(G),K=D;K=D;d--)g=o[d],g.self.onExit&&h.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=D;d2?k.enter(a,null,c).then(d):k.enter(a,null,c,d)},leave:function(a,c){b.version.minor>2?k.leave(a).then(c):k.leave(a,c)}};if(j){var e=j&&j(c,a);return{enter:function(a,b,c){e.enter(a,null,b),c()},leave:function(a,b){e.leave(a),b()}}}return d()}var i=g(),j=i("$animator"),k=i("$animate"),l={restrict:"ECA",terminal:!0,priority:400,transclude:"element",compile:function(c,g,i){return function(c,g,j){function k(){if(m&&(m.remove(),m=null),o&&(o.$destroy(),o=null),n){var a=n.data("$uiViewAnim");s.leave(n,function(){a.$$animLeave.resolve(),m=null}),m=n,n=null}}function l(h){var l,m=A(c,j,g,e),t=m&&a.$current&&a.$current.locals[m];if(h||t!==p){l=c.$new(),p=a.$current.locals[m],l.$emit("$viewContentLoading",m);var u=i(l,function(a){var e=f.defer(),h=f.defer(),i={$animEnter:e.promise,$animLeave:h.promise,$$animLeave:h};a.data("$uiViewAnim",i),s.enter(a,g,function(){e.resolve(),o&&o.$emit("$viewContentAnimationEnded"),(b.isDefined(r)&&!r||c.$eval(r))&&d(a)}),k()});n=u,o=l,o.$emit("$viewContentLoaded",m),o.$eval(q)}}var m,n,o,p,q=j.onload||"",r=j.autoscroll,s=h(j,c);g.inheritedData("$uiView");c.$on("$stateChangeSuccess",function(){l(!1)}),l(!0)}}};return l}function z(a,c,d,e){return{restrict:"ECA",priority:-400,compile:function(f){var g=f.html();return function(f,h,i){var j=d.$current,k=A(f,i,h,e),l=j&&j.locals[k];if(l){h.data("$uiView",{name:k,state:l.$$state}),h.html(l.$template?l.$template:g);var m=b.extend({},l);f[l.$$resolveAs]=m;var n=a(h.contents());if(l.$$controller){l.$scope=f,l.$element=h;var o=c(l.$$controller,l);l.$$controllerAs&&(f[l.$$controllerAs]=o,f[l.$$controllerAs][l.$$resolveAs]=m),M(o.$onInit)&&o.$onInit(),h.data("$ngControllerController",o),h.children().data("$ngControllerController",o)}n(f)}}}}}function A(a,b,c,d){var e=d(b.uiView||b.name||"")(a),f=c.inheritedData("$uiView");return e.indexOf("@")>=0?e:e+"@"+(f?f.state.name:"")}function B(a,b){var c,d=a.match(/^\s*({[^}]*})\s*$/);if(d&&(a=b+"("+d[1]+")"),c=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/),!c||4!==c.length)throw new Error("Invalid state ref '"+a+"'");return{state:c[1],paramExpr:c[3]||null}}function C(a){var b=a.parent().inheritedData("$uiView");return b&&b.state&&b.state.name?b.state:void 0}function D(a){var b="[object SVGAnimatedString]"===Object.prototype.toString.call(a.prop("href")),c="FORM"===a[0].nodeName;return{attr:c?"action":b?"xlink:href":"href",isAnchor:"A"===a.prop("tagName").toUpperCase(),clickable:!c}}function E(a,b,c,d,e){return function(f){var g=f.which||f.button,h=e();if(!(g>1||f.ctrlKey||f.metaKey||f.shiftKey||a.attr("target"))){var i=c(function(){b.go(h.state,h.params,h.options)});f.preventDefault();var j=d.isAnchor&&!h.href?1:0;f.preventDefault=function(){j--<=0&&c.cancel(i)}}}}function F(a,b){return{relative:C(a)||b.$current,inherit:!0}}function G(a,c){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(d,e,f,g){var h,i=B(f.uiSref,a.current.name),j={state:i.state,href:null,params:null},k=D(e),l=g[1]||g[0],m=null;j.options=R(F(e,a),f.uiSrefOpts?d.$eval(f.uiSrefOpts):{});var n=function(c){c&&(j.params=b.copy(c)),j.href=a.href(i.state,j.params,j.options),m&&m(),l&&(m=l.$$addStateInfo(i.state,j.params)),null!==j.href&&f.$set(k.attr,j.href)};i.paramExpr&&(d.$watch(i.paramExpr,function(a){a!==j.params&&n(a)},!0),j.params=b.copy(d.$eval(i.paramExpr))),n(),k.clickable&&(h=E(e,a,c,k,function(){return j}),e.bind("click",h),d.$on("$destroy",function(){e.unbind("click",h)}))}}}function H(a,b){return{restrict:"A",require:["?^uiSrefActive","?^uiSrefActiveEq"],link:function(c,d,e,f){function g(b){m.state=b[0],m.params=b[1],m.options=b[2],m.href=a.href(m.state,m.params,m.options),n&&n(),j&&(n=j.$$addStateInfo(m.state,m.params)),m.href&&e.$set(i.attr,m.href)}var h,i=D(d),j=f[1]||f[0],k=[e.uiState,e.uiStateParams||null,e.uiStateOpts||null],l="["+k.map(function(a){return a||"null"}).join(", ")+"]",m={state:null,params:null,options:null,href:null},n=null;c.$watch(l,g,!0),g(c.$eval(l)),i.clickable&&(h=E(d,a,b,i,function(){return m}),d.bind("click",h),c.$on("$destroy",function(){d.unbind("click",h)}))}}}function I(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs","$timeout",function(b,d,e,f){function g(b,c,e){var f=a.get(b,C(d)),g=h(b,c),i={state:f||{name:b},params:c,hash:g};return p.push(i),q[g]=e,function(){var a=p.indexOf(i);-1!==a&&p.splice(a,1)}}function h(a,c){if(!N(a))throw new Error("state should be a string");return O(c)?a+T(c):(c=b.$eval(c),O(c)?a+T(c):a)}function i(){for(var a=0;a0)){var c=g(a,b,o);return i(),c}},b.$on("$stateChangeSuccess",i),i()}]}}function J(a){var b=function(b,c){return a.is(b,c)};return b.$stateful=!0,b}function K(a){var b=function(b,c,d){return a.includes(b,c,d)};return b.$stateful=!0,b}var L=b.isDefined,M=b.isFunction,N=b.isString,O=b.isObject,P=b.isArray,Q=b.forEach,R=b.extend,S=b.copy,T=b.toJson;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),p.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",p),q.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",q);var U;r.prototype.concat=function(a,b){var c={caseInsensitive:U.caseInsensitive(),strict:U.strictMode(),squash:U.defaultSquashPolicy()};return new r(this.sourcePath+a+this.sourceSearch,R(c,b),this)},r.prototype.toString=function(){return this.source},r.prototype.exec=function(a,b){function c(a){function b(a){return a.split("").reverse().join("")}function c(a){return a.replace(/\\-/g,"-")}var d=b(a).split(/-(?!\\)/),e=o(d,b);return o(e,c).reverse()}var d=this.regexp.exec(a);if(!d)return null;b=b||{};var e,f,g,h=this.parameters(),i=h.length,j=this.segments.length-1,k={};if(j!==d.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");var l,m;for(e=0;j>e;e++){for(g=h[e],l=this.params[g],m=d[e+1],f=0;fe;e++){for(g=h[e],k[g]=this.params[g].value(b[g]),l=this.params[g],m=b[g],f=0;ff;f++){var k=h>f,l=d[f],m=e[l],n=m.value(a[l]),p=m.isOptional&&m.type.equals(m.value(),n),q=p?m.squash:!1,r=m.type.encode(n);if(k){var s=c[f+1],t=f+1===h;if(q===!1)null!=r&&(j+=P(r)?o(r,b).join("-"):encodeURIComponent(r)),j+=s;else if(q===!0){var u=j.match(/\/$/)?/\/?(.*)/:/(.*)/;j+=s.match(u)[1]}else N(q)&&(j+=q+s);t&&m.squash===!0&&"/"===j.slice(-1)&&(j=j.slice(0,-1))}else{if(null==r||p&&q!==!1)continue;if(P(r)||(r=[r]),0===r.length)continue;r=o(r,encodeURIComponent).join("&"+l+"="),j+=(g?"&":"?")+(l+"="+r),g=!0}}return j},s.prototype.is=function(a,b){return!0},s.prototype.encode=function(a,b){return a},s.prototype.decode=function(a,b){return a},s.prototype.equals=function(a,b){return a==b},s.prototype.$subPattern=function(){var a=this.pattern.toString();return a.substr(1,a.length-2)},s.prototype.pattern=/.*/,s.prototype.toString=function(){return"{Type:"+this.name+"}"},s.prototype.$normalize=function(a){return this.is(a)?a:this.decode(a)},s.prototype.$asArray=function(a,b){function d(a,b){function d(a,b){return function(){return a[b].apply(a,arguments)}}function e(a){return P(a)?a:L(a)?[a]:[]}function f(a){switch(a.length){case 0:return c;case 1:return"auto"===b?a[0]:a;default:return a}}function g(a){return!a}function h(a,b){return function(c){if(P(c)&&0===c.length)return c;c=e(c);var d=o(c,a);return b===!0?0===n(d,g).length:f(d)}}function i(a){return function(b,c){var d=e(b),f=e(c);if(d.length!==f.length)return!1;for(var g=0;g").append(a).html();try{return a[0].nodeType===Na?F(d):d.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+F(b)})}catch(c){return F(d)}}function wc(a){try{return decodeURIComponent(a)}catch(b){}}
+ function xc(a){var b={};n((a||"").split("&"),function(a){var c,e,f;a&&(e=a=a.replace(/\+/g,"%20"),c=a.indexOf("="),-1!==c&&(e=a.substring(0,c),f=a.substring(c+1)),e=wc(e),y(e)&&(f=y(f)?wc(f):!0,qa.call(b,e)?I(b[e])?b[e].push(f):b[e]=[b[e],f]:b[e]=f))});return b}function Qb(a){var b=[];n(a,function(a,c){I(a)?n(a,function(a){b.push(ja(c,!0)+(!0===a?"":"="+ja(a,!0)))}):b.push(ja(c,!0)+(!0===a?"":"="+ja(a,!0)))});return b.length?b.join("&"):""}function ob(a){return ja(a,!0).replace(/%26/gi,"&").replace(/%3D/gi,
+ "=").replace(/%2B/gi,"+")}function ja(a,b){return encodeURIComponent(a).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,b?"%20":"+")}function Yd(a,b){var d,c,e=Oa.length;for(c=0;c/,">"));}b=b||[];b.unshift(["$provide",function(b){b.value("$rootElement",a)}]);d.debugInfoEnabled&&b.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);b.unshift("ng");c=eb(b,d.strictDi);c.invoke(["$rootScope",
+ "$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;S&&e.test(S.name)&&(d.debugInfoEnabled=!0,S.name=S.name.replace(e,""));if(S&&!f.test(S.name))return c();S.name=S.name.replace(f,"");fa.resumeBootstrap=function(a){n(a,function(a){b.push(a)});return c()};z(fa.resumeDeferredBootstrap)&&fa.resumeDeferredBootstrap()}function $d(){S.name="NG_ENABLE_DEBUG_INFO!"+S.name;S.location.reload()}
+ function ae(a){a=fa.element(a).injector();if(!a)throw Aa("test");return a.get("$$testability")}function zc(a,b){b=b||"_";return a.replace(be,function(a,c){return(c?b:"")+a.toLowerCase()})}function ce(){var a;if(!Ac){var b=pb();(oa=q(b)?S.jQuery:b?S[b]:u)&&oa.fn.on?(B=oa,M(oa.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),a=oa.cleanData,oa.cleanData=function(b){var c;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=b[e]);e++)(c=
+ oa._data(f,"events"))&&c.$destroy&&oa(f).triggerHandler("$destroy");a(b)}):B=N;fa.element=B;Ac=!0}}function qb(a,b,d){if(!a)throw Aa("areq",b||"?",d||"required");return a}function Qa(a,b,d){d&&I(a)&&(a=a[a.length-1]);qb(z(a),b,"not a function, got "+(a&&"object"===typeof a?a.constructor.name||"Object":typeof a));return a}function Ra(a,b){if("hasOwnProperty"===a)throw Aa("badname",b);}function Bc(a,b,d){if(!b)return a;b=b.split(".");for(var c,e=a,f=b.length,g=0;g$2>")+c[2];for(c=c[0];c--;)d=d.lastChild;f=cb(f,d.childNodes);d=e.firstChild;d.textContent=""}else f.push(b.createTextNode(a));e.textContent="";e.innerHTML="";n(f,function(a){e.appendChild(a)});return e}function N(a){if(a instanceof N)return a;var b;E(a)&&(a=U(a),
+ b=!0);if(!(this instanceof N)){if(b&&"<"!=a.charAt(0))throw Ub("nosel");return new N(a)}if(b){b=X;var d;a=(d=Ef.exec(a))?[b.createElement(d[1])]:(d=Lc(a,b))?d.childNodes:[]}Mc(this,a)}function Vb(a){return a.cloneNode(!0)}function ub(a,b){b||vb(a);if(a.querySelectorAll)for(var d=a.querySelectorAll("*"),c=0,e=d.length;cl&&this.remove(t.key);return b}},get:function(a){if(l").parent()[0])});var f=O(a,b,a,c,d,e);K.$$addScopeClass(a);var g=null;return function(b,c,d){qb(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var h=d.parentBoundTranscludeFn,k=d.transcludeControllers;d=d.futureParentElement;h&&h.$$boundTransclude&&(h=h.$$boundTransclude);g||(g=(d=
+ d&&d[0])?"foreignobject"!==ta(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?B(Yb(g,B("
"!==m[1]||ha.test(g)?0:i:i.firstChild,f=g&&g.childNodes.length;while(f--)n.nodeName(k=g.childNodes[f],"tbody")&&!k.childNodes.length&&g.removeChild(k)}n.merge(q,i.childNodes),i.textContent="";while(i.firstChild)i.removeChild(i.firstChild);i=p.lastChild}else q.push(b.createTextNode(g));i&&p.removeChild(i),l.appendChecked||n.grep(ea(q,"input"),ia),r=0;while(g=q[r++])if(d&&n.inArray(g,d)>-1)e&&e.push(g);else if(h=n.contains(g.ownerDocument,g),i=ea(p.appendChild(g),"script"),h&&fa(i),c){f=0;while(g=i[f++])_.test(g.type||"")&&c.push(g)}return i=null,p}!function(){var b,c,e=d.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b]=c in a)||(e.setAttribute(c,"t"),l[b]=e.attributes[c].expando===!1);e=null}();var ka=/^(?:input|select|textarea)$/i,la=/^key/,ma=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,na=/^(?:focusinfocus|focusoutblur)$/,oa=/^([^.]*)(?:\.(.+)|)/;function pa(){return!0}function qa(){return!1}function ra(){try{return d.activeElement}catch(a){}}function sa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)sa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=qa;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return"undefined"==typeof n||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(G)||[""],h=b.length;while(h--)f=oa.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=oa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(i=m=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!na.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),h=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),l=n.event.special[q]||{},f||!l.trigger||l.trigger.apply(e,c)!==!1)){if(!f&&!l.noBubble&&!n.isWindow(e)){for(j=l.delegateType||q,na.test(j+q)||(i=i.parentNode);i;i=i.parentNode)p.push(i),m=i;m===(e.ownerDocument||d)&&p.push(m.defaultView||m.parentWindow||a)}o=0;while((i=p[o++])&&!b.isPropagationStopped())b.type=o>1?j:l.bindType||q,g=(n._data(i,"events")||{})[b.type]&&n._data(i,"handle"),g&&g.apply(i,c),g=h&&i[h],g&&g.apply&&M(i)&&(b.result=g.apply(i,c),b.result===!1&&b.preventDefault());if(b.type=q,!f&&!b.isDefaultPrevented()&&(!l._default||l._default.apply(p.pop(),c)===!1)&&M(e)&&h&&e[q]&&!n.isWindow(e)){m=e[h],m&&(e[h]=null),n.event.triggered=q;try{e[q]()}catch(s){}n.event.triggered=void 0,m&&(e[h]=m)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]","i"),va=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,wa=/
+
+
+
+
+
+
+
diff --git a/common/src/main/webapp/framework/templateContainer.html b/common/src/main/webapp/framework/templateContainer.html
new file mode 100644
index 0000000..ef6f01c
--- /dev/null
+++ b/common/src/main/webapp/framework/templateContainer.html
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/templateFunctional.html b/common/src/main/webapp/framework/templateFunctional.html
new file mode 100644
index 0000000..ff2f53f
--- /dev/null
+++ b/common/src/main/webapp/framework/templateFunctional.html
@@ -0,0 +1,82 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/templateNotification.html b/common/src/main/webapp/framework/templateNotification.html
new file mode 100644
index 0000000..97f26e3
--- /dev/null
+++ b/common/src/main/webapp/framework/templateNotification.html
@@ -0,0 +1,48 @@
+
+
+
+
\ No newline at end of file
diff --git a/common/src/main/webapp/framework/templateWidget.html b/common/src/main/webapp/framework/templateWidget.html
new file mode 100644
index 0000000..fcba217
--- /dev/null
+++ b/common/src/main/webapp/framework/templateWidget.html
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common/src/main/webapp/thirdparty/License.txt b/common/src/main/webapp/thirdparty/License.txt
new file mode 100644
index 0000000..8e698ec
--- /dev/null
+++ b/common/src/main/webapp/thirdparty/License.txt
@@ -0,0 +1,362 @@
+THIS LICENSE FILE CONTAINS THE LICENSE APPLICABLE DEPENDING ON THE TYPE OF CONTRIBUTIONS.
+
+APACHE LICENSE 2 IS APPLICABLE FOR SOURCE CODE, CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL FOR DOCUMENTATION
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+Apache License Version 2.0, January 2004 http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Attribution 4.0 International
+
+https://creativecommons.org/licenses/by/4.0/legalcode
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More_considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+ c. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+ d. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+ e. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+ f. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+ g. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+ h. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+ i. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+ j. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+ k. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+Section 2 -- Scope.
+
+ a. License grant.
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+ b. produce, reproduce, and Share Adapted Material.
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+ 5. Downstream recipients.
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+ b. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+ b. Other rights.
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the following conditions.
+
+ a. Attribution.
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+ ii. a copyright notice;
+ iii. a notice that refers to this Public License;
+ iv. a notice that refers to the disclaimer of
+ warranties;
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+ 4. If You Share Adapted Material You produce, the Adapter's
+ License You apply must not prevent recipients of the Adapted
+ Material from complying with this Public License.
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material; and
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+ 2. upon express reinstatement by the Licensor.
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the "Licensor." The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
\ No newline at end of file
diff --git a/common/src/main/webapp/thirdparty/animate/animate.min.css b/common/src/main/webapp/thirdparty/animate/animate.min.css
new file mode 100644
index 0000000..88b94d5
--- /dev/null
+++ b/common/src/main/webapp/thirdparty/animate/animate.min.css
@@ -0,0 +1,6 @@
+@charset "UTF-8";/*!
+Animate.css - http://daneden.me/animate
+Licensed under the MIT license - http://opensource.org/licenses/MIT
+
+Copyright (c) 2014 Daniel Eden
+*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}@-webkit-keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-30px,0);-ms-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-15px,0);-ms-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);-ms-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;-ms-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);-ms-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(0.75,1.25,1);transform:scale3d(0.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);-ms-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(0.75,1.25,1);-ms-transform:scale3d(0.75,1.25,1);transform:scale3d(0.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);-ms-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);-ms-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);-ms-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);-ms-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);-ms-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}@keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);-ms-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);-ms-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);-ms-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);-ms-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);-ms-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}.swing{-webkit-transform-origin:top center;-ms-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes tada{0%{-webkit-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);-ms-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);-ms-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);-ms-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}@keyframes wobble{0%{-webkit-transform:none;-ms-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);-ms-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);-ms-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);-ms-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);-ms-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);-ms-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;-ms-transform:none;transform:none}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);-ms-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);-ms-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);-ms-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);-ms-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);-ms-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);-ms-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn;-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);-ms-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);-ms-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);-ms-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);-ms-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;-ms-transform:none;transform:none}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);-ms-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);-ms-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);-ms-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);-ms-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;-ms-transform:none;transform:none}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);-ms-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);-ms-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);-ms-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);-ms-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;-ms-transform:none;transform:none}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);-ms-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);-ms-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);-ms-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);-ms-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);-ms-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);-ms-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);-ms-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut;-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);-ms-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);-ms-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);-ms-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);-ms-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);-ms-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);-ms-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);-ms-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);-ms-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);-ms-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);-ms-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);-ms-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);-ms-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);-ms-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);-ms-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);-ms-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);-ms-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);-ms-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);-ms-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);-ms-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);-ms-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);-ms-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-ms-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-ms-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);-ms-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);-ms-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;-ms-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);-ms-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);-ms-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);-ms-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);-ms-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);-ms-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);-ms-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);-ms-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);-ms-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);-ms-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);-ms-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px);-ms-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);-ms-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);-ms-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-animation-duration:.75s;animation-duration:.75s;-webkit-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px);-ms-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);-ms-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);-ms-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;-ms-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY;-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}@keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);-ms-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);-ms-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);-ms-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;-ms-transform:none;transform:none;opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}@keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);-ms-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateIn{0%{-webkit-transform-origin:center;-ms-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);-ms-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;-ms-transform-origin:center;transform-origin:center;-webkit-transform:none;-ms-transform:none;transform:none;opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);-ms-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;-ms-transform:none;transform:none;opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);-ms-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;-ms-transform:none;transform:none;opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);-ms-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;-ms-transform:none;transform:none;opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);-ms-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;-ms-transform:none;transform:none;opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}@keyframes rotateOut{0%{-webkit-transform-origin:center;-ms-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;-ms-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);-ms-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0,0,1,45deg);transform:rotate(0,0,1,45deg);opacity:0}}@keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate(0,0,1,45deg);-ms-transform:rotate(0,0,1,45deg);transform:rotate(0,0,1,45deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);-ms-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;-ms-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);-ms-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}@keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;-ms-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);-ms-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}@keyframes hinge{0%{-webkit-transform-origin:top left;-ms-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);-ms-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;-ms-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);-ms-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;-ms-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);-ms-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);-ms-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}@keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);-ms-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);-ms-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-ms-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-ms-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-ms-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-ms-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-ms-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-ms-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-ms-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-ms-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);-ms-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-ms-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-ms-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;-ms-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);-ms-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);-ms-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;-ms-transform-origin:left center;transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);-ms-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);-ms-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;-ms-transform-origin:right center;transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-ms-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-ms-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;-ms-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}
\ No newline at end of file
diff --git a/common/src/main/webapp/thirdparty/avalon/avalon.js b/common/src/main/webapp/thirdparty/avalon/avalon.js
new file mode 100644
index 0000000..a22bb7d
--- /dev/null
+++ b/common/src/main/webapp/thirdparty/avalon/avalon.js
@@ -0,0 +1,5819 @@
+/*==================================================
+ Copyright (c) 2013-2015 司徒正美 and other contributors
+ http://www.cnblogs.com/rubylouvre/
+ https://github.com/RubyLouvre
+ http://weibo.com/jslouvre/
+
+ Released under the MIT license
+ avalon.js 1.45 built in 2015.7.17
+ support IE6+ and other browsers
+ ==================================================*/
+(function(global, factory) {
+
+ if (typeof module === "object" && typeof module.exports === "object") {
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get avalon.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var avalon = require("avalon")(window);
+ module.exports = global.document ? factory(global, true) : function(w) {
+ if (!w.document) {
+ throw new Error("Avalon requires a window with a document")
+ }
+ return factory(w)
+ }
+ } else {
+ factory(global)
+ }
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function(window, noGlobal){
+
+/*********************************************************************
+ * 全局变量及方法 *
+ **********************************************************************/
+var expose = new Date() - 0
+//http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function
+var DOC = window.document
+var head = DOC.getElementsByTagName("head")[0] //HEAD元素
+var ifGroup = head.insertBefore(document.createElement("avalon"), head.firstChild) //避免IE6 base标签BUG
+ifGroup.innerHTML = "X"
+ifGroup.setAttribute("ms-skip", "1")
+ifGroup.className = "avalonHide"
+var rnative = /\[native code\]/ //判定是否原生函数
+function log() {
+ if (window.console && avalon.config.debug) {
+ // http://stackoverflow.com/questions/8785624/how-to-safely-wrap-console-log
+ Function.apply.call(console.log, console, arguments)
+ }
+}
+
+
+var subscribers = "$" + expose
+var otherRequire = window.require
+var otherDefine = window.define
+var innerRequire
+var stopRepeatAssign = false
+var rword = /[^, ]+/g //切割字符串为一个个小块,以空格或豆号分开它们,结合replace实现字符串的forEach
+var rcomplexType = /^(?:object|array)$/
+var rsvg = /^\[object SVG\w*Element\]$/
+var rwindow = /^\[object (?:Window|DOMWindow|global)\]$/
+var oproto = Object.prototype
+var ohasOwn = oproto.hasOwnProperty
+var serialize = oproto.toString
+var ap = Array.prototype
+var aslice = ap.slice
+var Registry = {} //将函数曝光到此对象上,方便访问器收集依赖
+var W3C = window.dispatchEvent
+var root = DOC.documentElement
+var avalonFragment = DOC.createDocumentFragment()
+var cinerator = DOC.createElement("div")
+var class2type = {}
+"Boolean Number String Function Array Date RegExp Object Error".replace(rword, function (name) {
+ class2type["[object " + name + "]"] = name.toLowerCase()
+})
+
+
+function noop() {
+}
+
+
+function oneObject(array, val) {
+ if (typeof array === "string") {
+ array = array.match(rword) || []
+ }
+ var result = {},
+ value = val !== void 0 ? val : 1
+ for (var i = 0, n = array.length; i < n; i++) {
+ result[array[i]] = value
+ }
+ return result
+}
+
+//生成UUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
+var generateID = function (prefix) {
+ prefix = prefix || "avalon"
+ return String(Math.random() + Math.random()).replace(/\d\.\d{4}/, prefix)
+}
+function IE() {
+ if (window.VBArray) {
+ var mode = document.documentMode
+ return mode ? mode : window.XMLHttpRequest ? 7 : 6
+ } else {
+ return NaN
+ }
+}
+var IEVersion = IE()
+
+avalon = function (el) { //创建jQuery式的无new 实例化结构
+ return new avalon.init(el)
+}
+
+avalon.profile = function () {
+ if (window.console && avalon.config.profile) {
+ Function.apply.call(console.log, console, arguments)
+ }
+}
+
+/*视浏览器情况采用最快的异步回调*/
+avalon.nextTick = new function () {// jshint ignore:line
+ var tickImmediate = window.setImmediate
+ var tickObserver = window.MutationObserver
+ var tickPost = W3C && window.postMessage
+ if (tickImmediate) {
+ return tickImmediate.bind(window)
+ }
+
+ var queue = []
+ function callback() {
+ var n = queue.length
+ for (var i = 0; i < n; i++) {
+ queue[i]()
+ }
+ queue = queue.slice(n)
+ }
+
+ if (tickObserver) {
+ var node = document.createTextNode("avalon")
+ new tickObserver(callback).observe(node, {characterData: true})// jshint ignore:line
+ return function (fn) {
+ queue.push(fn)
+ node.data = Math.random()
+ }
+ }
+
+ if (tickPost) {
+ window.addEventListener("message", function (e) {
+ var source = e.source
+ if ((source === window || source === null) && e.data === "process-tick") {
+ e.stopPropagation()
+ callback()
+ }
+ })
+
+ return function (fn) {
+ queue.push(fn)
+ window.postMessage('process-tick', '*')
+ }
+ }
+
+ return function (fn) {
+ setTimeout(fn, 0)
+ }
+}// jshint ignore:line
+/*********************************************************************
+ * avalon的静态方法定义区 *
+ **********************************************************************/
+avalon.init = function (el) {
+ this[0] = this.element = el
+}
+avalon.fn = avalon.prototype = avalon.init.prototype
+
+avalon.type = function (obj) { //取得目标的类型
+ if (obj == null) {
+ return String(obj)
+ }
+ // 早期的webkit内核浏览器实现了已废弃的ecma262v4标准,可以将正则字面量当作函数使用,因此typeof在判定正则时会返回function
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[serialize.call(obj)] || "object" :
+ typeof obj
+}
+
+var isFunction = typeof alert === "object" ? function (fn) {
+ try {
+ return /^\s*\bfunction\b/.test(fn + "")
+ } catch (e) {
+ return false
+ }
+} : function (fn) {
+ return serialize.call(fn) === "[object Function]"
+}
+avalon.isFunction = isFunction
+
+avalon.isWindow = function (obj) {
+ if (!obj)
+ return false
+ // 利用IE678 window == document为true,document == window竟然为false的神奇特性
+ // 标准浏览器及IE9,IE10等使用 正则检测
+ return obj == obj.document && obj.document != obj //jshint ignore:line
+}
+
+function isWindow(obj) {
+ return rwindow.test(serialize.call(obj))
+}
+if (isWindow(window)) {
+ avalon.isWindow = isWindow
+}
+var enu
+for (enu in avalon({})) {
+ break
+}
+var enumerateBUG = enu !== "0" //IE6下为true, 其他为false
+/*判定是否是一个朴素的javascript对象(Object),不是DOM对象,不是BOM对象,不是自定义类的实例*/
+avalon.isPlainObject = function (obj, key) {
+ if (!obj || avalon.type(obj) !== "object" || obj.nodeType || avalon.isWindow(obj)) {
+ return false;
+ }
+ try { //IE内置对象没有constructor
+ if (obj.constructor && !ohasOwn.call(obj, "constructor") && !ohasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
+ return false;
+ }
+ } catch (e) { //IE8 9会在这里抛错
+ return false;
+ }
+ if (enumerateBUG) {
+ for (key in obj) {
+ return ohasOwn.call(obj, key)
+ }
+ }
+ for (key in obj) {
+ }
+ return key === void 0 || ohasOwn.call(obj, key)
+}
+if (rnative.test(Object.getPrototypeOf)) {
+ avalon.isPlainObject = function (obj) {
+ // 简单的 typeof obj === "object"检测,会致使用isPlainObject(window)在opera下通不过
+ return serialize.call(obj) === "[object Object]" && Object.getPrototypeOf(obj) === oproto
+ }
+}
+//与jQuery.extend方法,可用于浅拷贝,深拷贝
+avalon.mix = avalon.fn.mix = function () {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false
+
+ // 如果第一个参数为布尔,判定是否深拷贝
+ if (typeof target === "boolean") {
+ deep = target
+ target = arguments[1] || {}
+ i++
+ }
+
+ //确保接受方为一个复杂的数据类型
+ if (typeof target !== "object" && !isFunction(target)) {
+ target = {}
+ }
+
+ //如果只有一个参数,那么新成员添加于mix所在的对象上
+ if (i === length) {
+ target = this
+ i--
+ }
+
+ for (; i < length; i++) {
+ //只处理非空参数
+ if ((options = arguments[i]) != null) {
+ for (name in options) {
+ src = target[name]
+ try {
+ copy = options[name] //当options为VBS对象时报错
+ } catch (e) {
+ continue
+ }
+
+ // 防止环引用
+ if (target === copy) {
+ continue
+ }
+ if (deep && copy && (avalon.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) {
+
+ if (copyIsArray) {
+ copyIsArray = false
+ clone = src && Array.isArray(src) ? src : []
+
+ } else {
+ clone = src && avalon.isPlainObject(src) ? src : {}
+ }
+
+ target[name] = avalon.mix(deep, clone, copy)
+ } else if (copy !== void 0) {
+ target[name] = copy
+ }
+ }
+ }
+ }
+ return target
+}
+
+function _number(a, len) { //用于模拟slice, splice的效果
+ a = Math.floor(a) || 0
+ return a < 0 ? Math.max(len + a, 0) : Math.min(a, len);
+}
+avalon.mix({
+ rword: rword,
+ subscribers: subscribers,
+ version: 1.45,
+ ui: {},
+ log: log,
+ slice: W3C ? function (nodes, start, end) {
+ return aslice.call(nodes, start, end)
+ } : function (nodes, start, end) {
+ var ret = []
+ var len = nodes.length
+ if (end === void 0)
+ end = len
+ if (typeof end === "number" && isFinite(end)) {
+ start = _number(start, len)
+ end = _number(end, len)
+ for (var i = start; i < end; ++i) {
+ ret[i - start] = nodes[i]
+ }
+ }
+ return ret
+ },
+ noop: noop,
+ /*如果不用Error对象封装一下,str在控制台下可能会乱码*/
+ error: function (str, e) {
+ throw (e || Error)(str)
+ },
+ /*将一个以空格或逗号隔开的字符串或数组,转换成一个键值都为1的对象*/
+ oneObject: oneObject,
+ /* avalon.range(10)
+ => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ avalon.range(1, 11)
+ => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ avalon.range(0, 30, 5)
+ => [0, 5, 10, 15, 20, 25]
+ avalon.range(0, -10, -1)
+ => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
+ avalon.range(0)
+ => []*/
+ range: function (start, end, step) { // 用于生成整数数组
+ step || (step = 1)
+ if (end == null) {
+ end = start || 0
+ start = 0
+ }
+ var index = -1,
+ length = Math.max(0, Math.ceil((end - start) / step)),
+ result = new Array(length)
+ while (++index < length) {
+ result[index] = start
+ start += step
+ }
+ return result
+ },
+ eventHooks: [],
+ /*绑定事件*/
+ bind: function(el, type, fn, phase) {
+ var hooks = avalon.eventHooks
+ var hook = hooks[type]
+ if (typeof hook === "object") {
+ type = hook.type
+ if (hook.deel) {
+ fn = hook.deel(el, type, fn, phase)
+ }
+ }
+ var callback = W3C ? fn : function(e) {
+ fn.call(el, fixEvent(e));
+ }
+ if (W3C) {
+ el.addEventListener(type, callback, !!phase)
+ } else {
+ el.attachEvent("on" + type, callback)
+ }
+ return callback
+ },
+ /*卸载事件*/
+ unbind: function(el, type, fn, phase) {
+ var hooks = avalon.eventHooks
+ var hook = hooks[type]
+ var callback = fn || noop
+ if (typeof hook === "object") {
+ type = hook.type
+ if (hook.deel) {
+ fn = hook.deel(el, type, fn, false)
+ }
+ }
+ if (W3C) {
+ el.removeEventListener(type, callback, !!phase)
+ } else {
+ el.detachEvent("on" + type, callback)
+ }
+ },
+ /*读写删除元素节点的样式*/
+ css: function (node, name, value) {
+ if (node instanceof avalon) {
+ node = node[0]
+ }
+ var prop = /[_-]/.test(name) ? camelize(name) : name, fn
+ name = avalon.cssName(prop) || prop
+ if (value === void 0 || typeof value === "boolean") { //获取样式
+ fn = cssHooks[prop + ":get"] || cssHooks["@:get"]
+ if (name === "background") {
+ name = "backgroundColor"
+ }
+ var val = fn(node, name)
+ return value === true ? parseFloat(val) || 0 : val
+ } else if (value === "") { //请除样式
+ node.style[name] = ""
+ } else { //设置样式
+ if (value == null || value !== value) {
+ return
+ }
+ if (isFinite(value) && !avalon.cssNumber[prop]) {
+ value += "px"
+ }
+ fn = cssHooks[prop + ":set"] || cssHooks["@:set"]
+ fn(node, name, value)
+ }
+ },
+ /*遍历数组与对象,回调的第一个参数为索引或键名,第二个或元素或键值*/
+ each: function (obj, fn) {
+ if (obj) { //排除null, undefined
+ var i = 0
+ if (isArrayLike(obj)) {
+ for (var n = obj.length; i < n; i++) {
+ if (fn(i, obj[i]) === false)
+ break
+ }
+ } else {
+ for (i in obj) {
+ if (obj.hasOwnProperty(i) && fn(i, obj[i]) === false) {
+ break
+ }
+ }
+ }
+ }
+ },
+ //收集元素的data-{{prefix}}-*属性,并转换为对象
+ getWidgetData: function (elem, prefix) {
+ var raw = avalon(elem).data()
+ var result = {}
+ for (var i in raw) {
+ if (i.indexOf(prefix) === 0) {
+ result[i.replace(prefix, "").replace(/\w/, function (a) {
+ return a.toLowerCase()
+ })] = raw[i]
+ }
+ }
+ return result
+ },
+ Array: {
+ /*只有当前数组不存在此元素时只添加它*/
+ ensure: function (target, item) {
+ if (target.indexOf(item) === -1) {
+ return target.push(item)
+ }
+ },
+ /*移除数组中指定位置的元素,返回布尔表示成功与否*/
+ removeAt: function (target, index) {
+ return !!target.splice(index, 1).length
+ },
+ /*移除数组中第一个匹配传参的那个元素,返回布尔表示成功与否*/
+ remove: function (target, item) {
+ var index = target.indexOf(item)
+ if (~index)
+ return avalon.Array.removeAt(target, index)
+ return false
+ }
+ }
+})
+
+var bindingHandlers = avalon.bindingHandlers = {}
+var bindingExecutors = avalon.bindingExecutors = {}
+
+/*判定是否类数组,如节点集合,纯数组,arguments与拥有非负整数的length属性的纯JS对象*/
+function isArrayLike(obj) {
+ if (!obj)
+ return false
+ var n = obj.length
+ if (n === (n >>> 0)) { //检测length属性是否为非负整数
+ var type = serialize.call(obj).slice(8, -1)
+ if (/(?:regexp|string|function|window|global)$/i.test(type))
+ return false
+ if (type === "Array")
+ return true
+ try {
+ if ({}.propertyIsEnumerable.call(obj, "length") === false) { //如果是原生对象
+ return /^\s?function/.test(obj.item || obj.callee)
+ }
+ return true
+ } catch (e) { //IE的NodeList直接抛错
+ return !obj.window //IE6-8 window
+ }
+ }
+ return false
+}
+
+
+// https://github.com/rsms/js-lru
+var Cache = new function() {// jshint ignore:line
+ function LRU(maxLength) {
+ this.size = 0
+ this.limit = maxLength
+ this.head = this.tail = void 0
+ this._keymap = {}
+ }
+
+ var p = LRU.prototype
+
+ p.put = function(key, value) {
+ var entry = {
+ key: key,
+ value: value
+ }
+ this._keymap[key] = entry
+ if (this.tail) {
+ this.tail.newer = entry
+ entry.older = this.tail
+ } else {
+ this.head = entry
+ }
+ this.tail = entry
+ if (this.size === this.limit) {
+ this.shift()
+ } else {
+ this.size++
+ }
+ return value
+ }
+
+ p.shift = function() {
+ var entry = this.head
+ if (entry) {
+ this.head = this.head.newer
+ this.head.older =
+ entry.newer =
+ entry.older =
+ this._keymap[entry.key] = void 0
+ }
+ }
+ p.get = function(key) {
+ var entry = this._keymap[key]
+ if (entry === void 0)
+ return
+ if (entry === this.tail) {
+ return entry.value
+ }
+ // HEAD--------------TAIL
+ // <.older .newer>
+ // <--- add direction --
+ // A B C E
+ if (entry.newer) {
+ if (entry === this.head) {
+ this.head = entry.newer
+ }
+ entry.newer.older = entry.older // C <-- E.
+ }
+ if (entry.older) {
+ entry.older.newer = entry.newer // C. --> E
+ }
+ entry.newer = void 0 // D --x
+ entry.older = this.tail // D. --> E
+ if (this.tail) {
+ this.tail.newer = entry // E. <-- D
+ }
+ this.tail = entry
+ return entry.value
+ }
+ return LRU
+}// jshint ignore:line
+
+/*********************************************************************
+ * javascript 底层补丁 *
+ **********************************************************************/
+if (!"司徒正美".trim) {
+ var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g
+ String.prototype.trim = function () {
+ return this.replace(rtrim, "")
+ }
+}
+var hasDontEnumBug = !({
+ 'toString': null
+}).propertyIsEnumerable('toString'),
+ hasProtoEnumBug = (function () {
+ }).propertyIsEnumerable('prototype'),
+ dontEnums = [
+ "toString",
+ "toLocaleString",
+ "valueOf",
+ "hasOwnProperty",
+ "isPrototypeOf",
+ "propertyIsEnumerable",
+ "constructor"
+ ],
+ dontEnumsLength = dontEnums.length;
+if (!Object.keys) {
+ Object.keys = function (object) { //ecma262v5 15.2.3.14
+ var theKeys = []
+ var skipProto = hasProtoEnumBug && typeof object === "function"
+ if (typeof object === "string" || (object && object.callee)) {
+ for (var i = 0; i < object.length; ++i) {
+ theKeys.push(String(i))
+ }
+ } else {
+ for (var name in object) {
+ if (!(skipProto && name === "prototype") && ohasOwn.call(object, name)) {
+ theKeys.push(String(name))
+ }
+ }
+ }
+
+ if (hasDontEnumBug) {
+ var ctor = object.constructor,
+ skipConstructor = ctor && ctor.prototype === object
+ for (var j = 0; j < dontEnumsLength; j++) {
+ var dontEnum = dontEnums[j]
+ if (!(skipConstructor && dontEnum === "constructor") && ohasOwn.call(object, dontEnum)) {
+ theKeys.push(dontEnum)
+ }
+ }
+ }
+ return theKeys
+ }
+}
+if (!Array.isArray) {
+ Array.isArray = function (a) {
+ return serialize.call(a) === "[object Array]"
+ }
+}
+
+if (!noop.bind) {
+ Function.prototype.bind = function (scope) {
+ if (arguments.length < 2 && scope === void 0)
+ return this
+ var fn = this,
+ argv = arguments
+ return function () {
+ var args = [],
+ i
+ for (i = 1; i < argv.length; i++)
+ args.push(argv[i])
+ for (i = 0; i < arguments.length; i++)
+ args.push(arguments[i])
+ return fn.apply(scope, args)
+ }
+ }
+}
+
+function iterator(vars, body, ret) {
+ var fun = 'for(var ' + vars + 'i=0,n = this.length; i < n; i++){' + body.replace('_', '((i in this) && fn.call(scope,this[i],i,this))') + '}' + ret
+ /* jshint ignore:start */
+ return Function("fn,scope", fun)
+ /* jshint ignore:end */
+}
+if (!rnative.test([].map)) {
+ avalon.mix(ap, {
+ //定位操作,返回数组中第一个等于给定参数的元素的索引值。
+ indexOf: function (item, index) {
+ var n = this.length,
+ i = ~~index
+ if (i < 0)
+ i += n
+ for (; i < n; i++)
+ if (this[i] === item)
+ return i
+ return -1
+ },
+ //定位操作,同上,不过是从后遍历。
+ lastIndexOf: function (item, index) {
+ var n = this.length,
+ i = index == null ? n - 1 : index
+ if (i < 0)
+ i = Math.max(0, n + i)
+ for (; i >= 0; i--)
+ if (this[i] === item)
+ return i
+ return -1
+ },
+ //迭代操作,将数组的元素挨个儿传入一个函数中执行。Prototype.js的对应名字为each。
+ forEach: iterator("", '_', ""),
+ //迭代类 在数组中的每个项上运行一个函数,如果此函数的值为真,则此元素作为新数组的元素收集起来,并返回新数组
+ filter: iterator('r=[],j=0,', 'if(_)r[j++]=this[i]', 'return r'),
+ //收集操作,将数组的元素挨个儿传入一个函数中执行,然后把它们的返回值组成一个新数组返回。Prototype.js的对应名字为collect。
+ map: iterator('r=[],', 'r[i]=_', 'return r'),
+ //只要数组中有一个元素满足条件(放进给定函数返回true),那么它就返回true。Prototype.js的对应名字为any。
+ some: iterator("", 'if(_)return true', 'return false'),
+ //只有数组中的元素都满足条件(放进给定函数返回true),它才返回true。Prototype.js的对应名字为all。
+ every: iterator("", 'if(!_)return false', 'return true')
+ })
+}
+/*********************************************************************
+ * DOM 底层补丁 *
+ **********************************************************************/
+
+function fixContains(root, el) {
+ try { //IE6-8,游离于DOM树外的文本节点,访问parentNode有时会抛错
+ while ((el = el.parentNode))
+ if (el === root)
+ return true
+ return false
+ } catch (e) {
+ return false
+ }
+}
+avalon.contains = fixContains
+//IE6-11的文档对象没有contains
+if (!DOC.contains) {
+ DOC.contains = function (b) {
+ return fixContains(DOC, b)
+ }
+}
+
+function outerHTML() {
+ return new XMLSerializer().serializeToString(this)
+}
+
+if (window.SVGElement) {
+ //safari5+是把contains方法放在Element.prototype上而不是Node.prototype
+ if (!DOC.createTextNode("x").contains) {
+ Node.prototype.contains = function (arg) {//IE6-8没有Node对象
+ return !!(this.compareDocumentPosition(arg) & 16)
+ }
+ }
+ var svgns = "http://www.w3.org/2000/svg"
+ var svg = DOC.createElementNS(svgns, "svg")
+ svg.innerHTML = ''
+ if (!rsvg.test(svg.firstChild)) { // #409
+ function enumerateNode(node, targetNode) {// jshint ignore:line
+ if (node && node.childNodes) {
+ var nodes = node.childNodes
+ for (var i = 0, el; el = nodes[i++]; ) {
+ if (el.tagName) {
+ var svg = DOC.createElementNS(svgns,
+ el.tagName.toLowerCase())
+ ap.forEach.call(el.attributes, function (attr) {
+ svg.setAttribute(attr.name, attr.value) //复制属性
+ })// jshint ignore:line
+ // 递归处理子节点
+ enumerateNode(el, svg)
+ targetNode.appendChild(svg)
+ }
+ }
+ }
+ }
+ Object.defineProperties(SVGElement.prototype, {
+ "outerHTML": {//IE9-11,firefox不支持SVG元素的innerHTML,outerHTML属性
+ enumerable: true,
+ configurable: true,
+ get: outerHTML,
+ set: function (html) {
+ var tagName = this.tagName.toLowerCase(),
+ par = this.parentNode,
+ frag = avalon.parseHTML(html)
+ // 操作的svg,直接插入
+ if (tagName === "svg") {
+ par.insertBefore(frag, this)
+ // svg节点的子节点类似
+ } else {
+ var newFrag = DOC.createDocumentFragment()
+ enumerateNode(frag, newFrag)
+ par.insertBefore(newFrag, this)
+ }
+ par.removeChild(this)
+ }
+ },
+ "innerHTML": {
+ enumerable: true,
+ configurable: true,
+ get: function () {
+ var s = this.outerHTML
+ var ropen = new RegExp("<" + this.nodeName + '\\b(?:(["\'])[^"]*?(\\1)|[^>])*>', "i")
+ var rclose = new RegExp("<\/" + this.nodeName + ">$", "i")
+ return s.replace(ropen, "").replace(rclose, "")
+ },
+ set: function (html) {
+ if (avalon.clearHTML) {
+ avalon.clearHTML(this)
+ var frag = avalon.parseHTML(html)
+ enumerateNode(frag, this)
+ }
+ }
+ }
+ })
+ }
+}
+if (!root.outerHTML && window.HTMLElement) { //firefox 到11时才有outerHTML
+ HTMLElement.prototype.__defineGetter__("outerHTML", outerHTML);
+}
+
+
+//============================= event binding =======================
+var rmouseEvent = /^(?:mouse|contextmenu|drag)|click/
+function fixEvent(event) {
+ var ret = {}
+ for (var i in event) {
+ ret[i] = event[i]
+ }
+ var target = ret.target = event.srcElement
+ if (event.type.indexOf("key") === 0) {
+ ret.which = event.charCode != null ? event.charCode : event.keyCode
+ } else if (rmouseEvent.test(event.type)) {
+ var doc = target.ownerDocument || DOC
+ var box = doc.compatMode === "BackCompat" ? doc.body : doc.documentElement
+ ret.pageX = event.clientX + (box.scrollLeft >> 0) - (box.clientLeft >> 0)
+ ret.pageY = event.clientY + (box.scrollTop >> 0) - (box.clientTop >> 0)
+ ret.wheelDeltaY = ret.wheelDelta
+ ret.wheelDeltaX = 0
+ }
+ ret.timeStamp = new Date() - 0
+ ret.originalEvent = event
+ ret.preventDefault = function () { //阻止默认行为
+ event.returnValue = false
+ }
+ ret.stopPropagation = function () { //阻止事件在DOM树中的传播
+ event.cancelBubble = true
+ }
+ return ret
+}
+
+var eventHooks = avalon.eventHooks
+//针对firefox, chrome修正mouseenter, mouseleave
+if (!("onmouseenter" in root)) {
+ avalon.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+ }, function (origType, fixType) {
+ eventHooks[origType] = {
+ type: fixType,
+ deel: function (elem, _, fn) {
+ return function (e) {
+ var t = e.relatedTarget
+ if (!t || (t !== elem && !(elem.compareDocumentPosition(t) & 16))) {
+ delete e.type
+ e.type = origType
+ return fn.call(elem, e)
+ }
+ }
+ }
+ }
+ })
+}
+//针对IE9+, w3c修正animationend
+avalon.each({
+ AnimationEvent: "animationend",
+ WebKitAnimationEvent: "webkitAnimationEnd"
+}, function (construct, fixType) {
+ if (window[construct] && !eventHooks.animationend) {
+ eventHooks.animationend = {
+ type: fixType
+ }
+ }
+})
+//针对IE6-8修正input
+if (!("oninput" in DOC.createElement("input"))) {
+ eventHooks.input = {
+ type: "propertychange",
+ deel: function (elem, _, fn) {
+ return function (e) {
+ if (e.propertyName === "value") {
+ e.type = "input"
+ return fn.call(elem, e)
+ }
+ }
+ }
+ }
+}
+if (DOC.onmousewheel === void 0) {
+ /* IE6-11 chrome mousewheel wheelDetla 下 -120 上 120
+ firefox DOMMouseScroll detail 下3 上-3
+ firefox wheel detlaY 下3 上-3
+ IE9-11 wheel deltaY 下40 上-40
+ chrome wheel deltaY 下100 上-100 */
+ var fixWheelType = DOC.onwheel !== void 0 ? "wheel" : "DOMMouseScroll"
+ var fixWheelDelta = fixWheelType === "wheel" ? "deltaY" : "detail"
+ eventHooks.mousewheel = {
+ type: fixWheelType,
+ deel: function (elem, _, fn) {
+ return function (e) {
+ e.wheelDeltaY = e.wheelDelta = e[fixWheelDelta] > 0 ? -120 : 120
+ e.wheelDeltaX = 0
+ if (Object.defineProperty) {
+ Object.defineProperty(e, "type", {
+ value: "mousewheel"
+ })
+ }
+ fn.call(elem, e)
+ }
+ }
+ }
+}
+
+
+
+/*********************************************************************
+ * 配置系统 *
+ **********************************************************************/
+
+function kernel(settings) {
+ for (var p in settings) {
+ if (!ohasOwn.call(settings, p))
+ continue
+ var val = settings[p]
+ if (typeof kernel.plugins[p] === "function") {
+ kernel.plugins[p](val)
+ } else if (typeof kernel[p] === "object") {
+ avalon.mix(kernel[p], val)
+ } else {
+ kernel[p] = val
+ }
+ }
+ return this
+}
+var openTag, closeTag, rexpr, rexprg, rbind, rregexp = /[-.*+?^${}()|[\]\/\\]/g
+
+function escapeRegExp(target) {
+ //http://stevenlevithan.com/regex/xregexp/
+ //将字符串安全格式化为正则表达式的源码
+ return (target + "").replace(rregexp, "\\$&")
+}
+
+var plugins = {
+ loader: function (builtin) {
+ var flag = innerRequire && builtin
+ window.require = flag ? innerRequire : otherRequire
+ window.define = flag ? innerRequire.define : otherDefine
+ },
+ interpolate: function (array) {
+ openTag = array[0]
+ closeTag = array[1]
+ if (openTag === closeTag) {
+ throw new SyntaxError("openTag!==closeTag")
+ var test = openTag + "test" + closeTag
+ cinerator.innerHTML = test
+ if (cinerator.innerHTML !== test && cinerator.innerHTML.indexOf("<") > -1) {
+ throw new SyntaxError("此定界符不合法")
+ }
+ cinerator.innerHTML = ""
+ }
+ var o = escapeRegExp(openTag),
+ c = escapeRegExp(closeTag)
+ rexpr = new RegExp(o + "(.*?)" + c)
+ rexprg = new RegExp(o + "(.*?)" + c, "g")
+ rbind = new RegExp(o + ".*?" + c + "|\\sms-")
+ }
+}
+
+kernel.debug = true
+kernel.plugins = plugins
+kernel.plugins['interpolate'](["{{", "}}"])
+kernel.paths = {}
+kernel.shim = {}
+kernel.maxRepeatSize = 100
+avalon.config = kernel
+var ravalon = /(\w+)\[(avalonctrl)="(\S+)"\]/
+var findNodes = DOC.querySelectorAll ? function(str) {
+ return DOC.querySelectorAll(str)
+} : function(str) {
+ var match = str.match(ravalon)
+ var all = DOC.getElementsByTagName(match[1])
+ var nodes = []
+ for (var i = 0, el; el = all[i++]; ) {
+ if (el.getAttribute(match[2]) === match[3]) {
+ nodes.push(el)
+ }
+ }
+ return nodes
+}
+/*********************************************************************
+ * 事件总线 *
+ **********************************************************************/
+var EventBus = {
+ $watch: function (type, callback) {
+ if (typeof callback === "function") {
+ var callbacks = this.$events[type]
+ if (callbacks) {
+ callbacks.push(callback)
+ } else {
+ this.$events[type] = [callback]
+ }
+ } else { //重新开始监听此VM的第一重简单属性的变动
+ this.$events = this.$watch.backup
+ }
+ return this
+ },
+ $unwatch: function (type, callback) {
+ var n = arguments.length
+ if (n === 0) { //让此VM的所有$watch回调无效化
+ this.$watch.backup = this.$events
+ this.$events = {}
+ } else if (n === 1) {
+ this.$events[type] = []
+ } else {
+ var callbacks = this.$events[type] || []
+ var i = callbacks.length
+ while (~--i < 0) {
+ if (callbacks[i] === callback) {
+ return callbacks.splice(i, 1)
+ }
+ }
+ }
+ return this
+ },
+ $fire: function (type) {
+ var special, i, v, callback
+ if (/^(\w+)!(\S+)$/.test(type)) {
+ special = RegExp.$1
+ type = RegExp.$2
+ }
+ var events = this.$events
+ if (!events)
+ return
+ var args = aslice.call(arguments, 1)
+ var detail = [type].concat(args)
+ if (special === "all") {
+ for (i in avalon.vmodels) {
+ v = avalon.vmodels[i]
+ if (v !== this) {
+ v.$fire.apply(v, detail)
+ }
+ }
+ } else if (special === "up" || special === "down") {
+ var elements = events.expr ? findNodes(events.expr) : []
+ if (elements.length === 0)
+ return
+ for (i in avalon.vmodels) {
+ v = avalon.vmodels[i]
+ if (v !== this) {
+ if (v.$events.expr) {
+ var eventNodes = findNodes(v.$events.expr)
+ if (eventNodes.length === 0) {
+ continue
+ }
+ //循环两个vmodel中的节点,查找匹配(向上匹配或者向下匹配)的节点并设置标识
+ /* jshint ignore:start */
+ ap.forEach.call(eventNodes, function (node) {
+ ap.forEach.call(elements, function (element) {
+ var ok = special === "down" ? element.contains(node) : //向下捕获
+ node.contains(element) //向上冒泡
+ if (ok) {
+ node._avalon = v //符合条件的加一个标识
+ }
+ });
+ })
+ /* jshint ignore:end */
+ }
+ }
+ }
+ var nodes = DOC.getElementsByTagName("*") //实现节点排序
+ var alls = []
+ ap.forEach.call(nodes, function (el) {
+ if (el._avalon) {
+ alls.push(el._avalon)
+ el._avalon = ""
+ el.removeAttribute("_avalon")
+ }
+ })
+ if (special === "up") {
+ alls.reverse()
+ }
+ for (i = 0; callback = alls[i++]; ) {
+ if (callback.$fire.apply(callback, detail) === false) {
+ break
+ }
+ }
+ } else {
+ var callbacks = events[type] || []
+ var all = events.$all || []
+ for (i = 0; callback = callbacks[i++]; ) {
+ if (isFunction(callback))
+ callback.apply(this, args)
+ }
+ for (i = 0; callback = all[i++]; ) {
+ if (isFunction(callback))
+ callback.apply(this, arguments)
+ }
+ }
+ }
+}
+
+/*********************************************************************
+ * modelFactory *
+ **********************************************************************/
+//avalon最核心的方法的两个方法之一(另一个是avalon.scan),返回一个ViewModel(VM)
+var VMODELS = avalon.vmodels = {} //所有vmodel都储存在这里
+avalon.define = function (id, factory) {
+ var $id = id.$id || id
+ if (!$id) {
+ log("warning: vm必须指定$id")
+ }
+ if (VMODELS[$id]) {
+ log("warning: " + $id + " 已经存在于avalon.vmodels中")
+ }
+ if (typeof id === "object") {
+ var model = modelFactory(id)
+ } else {
+ var scope = {
+ $watch: noop
+ }
+ factory(scope) //得到所有定义
+
+ model = modelFactory(scope) //偷天换日,将scope换为model
+ stopRepeatAssign = true
+ factory(model)
+ stopRepeatAssign = false
+ }
+ model.$id = $id
+ return VMODELS[$id] = model
+}
+
+//一些不需要被监听的属性
+var $$skipArray = String("$id,$watch,$unwatch,$fire,$events,$model,$skipArray,$proxy,$reinitialize,$propertyNames").match(rword)
+var defineProperty = Object.defineProperty
+var canHideOwn = true
+//如果浏览器不支持ecma262v5的Object.defineProperties或者存在BUG,比如IE8
+//标准浏览器使用__defineGetter__, __defineSetter__实现
+try {
+ defineProperty({}, "_", {
+ value: "x"
+ })
+ var defineProperties = Object.defineProperties
+} catch (e) {
+ canHideOwn = false
+}
+
+function modelFactory(source, $special, $model) {
+ if (Array.isArray(source)) {
+ var arr = source.concat()
+ source.length = 0
+ var collection = arrayFactory(source)
+ collection.pushArray(arr)
+ return collection
+ }
+ //0 null undefined || Node || VModel(fix IE6-8 createWithProxy $val: val引发的BUG)
+ if (!source || source.nodeType > 0 || (source.$id && source.$events)) {
+ return source
+ }
+ var $skipArray = Array.isArray(source.$skipArray) ? source.$skipArray : []
+ $skipArray.$special = $special || {} //强制要监听的属性
+ var $vmodel = {} //要返回的对象, 它在IE6-8下可能被偷龙转凤
+ $model = $model || {} //vmodels.$model属性
+ var $events = {} //vmodel.$events属性
+ var accessors = {} //监控属性
+ var computed = []
+ $$skipArray.forEach(function (name) {
+ delete source[name]
+ })
+ var names = Object.keys(source)
+ /* jshint ignore:start */
+ names.forEach(function (name, accessor) {
+ var val = source[name]
+ $model[name] = val
+ if (isObservable(name, val, $skipArray)) {
+ //总共产生三种accessor
+ $events[name] = []
+ var valueType = avalon.type(val)
+ //总共产生三种accessor
+ if (valueType === "object" && isFunction(val.get) && Object.keys(val).length <= 2) {
+ accessor = makeComputedAccessor(name, val)
+ computed.push(accessor)
+ } else if (rcomplexType.test(valueType)) {
+ accessor = makeComplexAccessor(name, val, valueType, $events[name])
+ } else {
+ accessor = makeSimpleAccessor(name, val)
+ }
+ accessors[name] = accessor
+ }
+ })
+ /* jshint ignore:end */
+
+ $vmodel = defineProperties($vmodel, descriptorFactory(accessors), source) //生成一个空的ViewModel
+ for (var i = 0; i < names.length; i++) {
+ var name = names[i]
+ if (!accessors[name]) {
+ $vmodel[name] = source[name]
+ }
+ }
+ //添加$id, $model, $events, $watch, $unwatch, $fire
+ $vmodel.$propertyNames = names.join("")
+ $vmodel.$id = generateID()
+ $vmodel.$model = $model
+ $vmodel.$events = $events
+ for (i in EventBus) {
+ var fn = EventBus[i]
+ if (!W3C) { //在IE6-8下,VB对象的方法里的this并不指向自身,需要用bind处理一下
+ fn = fn.bind($vmodel)
+ }
+ $vmodel[i] = fn
+ }
+ if (canHideOwn) {
+ Object.defineProperty($vmodel, "hasOwnProperty", hasOwnDescriptor)
+ } else {
+ /* jshint ignore:start */
+ $vmodel.hasOwnProperty = function (name) {
+ return name in $vmodel.$model
+ }
+ /* jshint ignore:end */
+ }
+
+ $vmodel.$reinitialize = function () {
+ computed.forEach(function (accessor) {
+ delete accessor._value
+ delete accessor.oldArgs
+ accessor.digest = function () {
+ accessor.call($vmodel)
+ }
+ dependencyDetection.begin({
+ callback: function (vm, dependency) {//dependency为一个accessor
+ var name = dependency._name
+ if (dependency !== accessor) {
+ var list = vm.$events[name]
+ injectDependency(list, accessor.digest)
+ }
+ }
+ })
+ try {
+ accessor.get.call($vmodel)
+ } finally {
+ dependencyDetection.end()
+ }
+ })
+ }
+ $vmodel.$reinitialize()
+ return $vmodel
+}
+
+var hasOwnDescriptor = {
+ value: function (name) {
+ return name in this.$model
+ },
+ writable: false,
+ enumerable: false,
+ configurable: true
+}
+//创建一个简单访问器
+function makeSimpleAccessor(name, value) {
+ function accessor(value) {
+ var oldValue = accessor._value
+ if (arguments.length > 0) {
+ if (!stopRepeatAssign && !isEqual(value, oldValue)) {
+ accessor.updateValue(this, value)
+ accessor.notify(this, value, oldValue)
+ }
+ return this
+ } else {
+ dependencyDetection.collectDependency(this, accessor)
+ return oldValue
+ }
+ }
+ accessorFactory(accessor, name)
+ accessor._value = value
+ return accessor;
+}
+
+//创建一个计算访问器
+function makeComputedAccessor(name, options) {
+ function accessor(value) {//计算属性
+ var oldValue = accessor._value
+ var init = ("_value" in accessor)
+ if (arguments.length > 0) {
+ if (stopRepeatAssign) {
+ return this
+ }
+ if (typeof accessor.set === "function") {
+ if (accessor.oldArgs !== value) {
+ accessor.oldArgs = value
+ var $events = this.$events
+ var lock = $events[name]
+ $events[name] = [] //清空回调,防止内部冒泡而触发多次$fire
+ accessor.set.call(this, value)
+ $events[name] = lock
+ value = accessor.get.call(this)
+ if (value !== oldValue) {
+ accessor.updateValue(this, value)
+ accessor.notify(this, value, oldValue) //触发$watch回调
+ }
+ }
+ }
+ return this
+ } else {
+ //将依赖于自己的高层访问器或视图刷新函数(以绑定对象形式)放到自己的订阅数组中
+ //将自己注入到低层访问器的订阅数组中
+ value = accessor.get.call(this)
+ accessor.updateValue(this, value)
+ if (init && oldValue !== value) {
+ accessor.notify(this, value, oldValue) //触发$watch回调
+ }
+ return value
+ }
+ }
+ accessor.set = options.set
+ accessor.get = options.get
+ accessorFactory(accessor, name)
+ return accessor
+}
+
+//创建一个复杂访问器
+function makeComplexAccessor(name, initValue, valueType, list) {
+ function accessor(value) {
+ var oldValue = accessor._value
+
+ var son = accessor._vmodel
+ if (arguments.length > 0) {
+ if (stopRepeatAssign) {
+ return this
+ }
+ if (valueType === "array") {
+ var a = son, b = value,
+ an = a.length,
+ bn = b.length
+ a.$lock = true
+ if (an > bn) {
+ a.splice(bn, an - bn)
+ } else if (bn > an) {
+ a.push.apply(a, b.slice(an))
+ }
+ var n = Math.min(an, bn)
+ for (var i = 0; i < n; i++) {
+ a.set(i, b[i])
+ }
+ delete a.$lock
+ a._fire("set")
+ } else if (valueType === "object") {
+ var newPropertyNames = Object.keys(value).join("")
+ if (son.$propertyNames === newPropertyNames) {
+ for (i in value) {
+ son[i] = value[i]
+ }
+ } else {
+ var sson = accessor._vmodel = modelFactory(value)
+ var sevent = sson.$events
+ var oevent = son.$events
+ for (var i in sevent) {
+ var arr = sevent[i]
+ if (Array.isArray(arr)) {
+ arr = arr.concat(oevent[i])
+ }
+ }
+ sevent[subscribers] = oevent[subscribers]
+ sson.$proxy = son.$proxy
+ son = sson
+ }
+ }
+ accessor.updateValue(this, son.$model)
+ accessor.notify(this, this._value, oldValue)
+ return this
+ } else {
+ dependencyDetection.collectDependency(this, accessor)
+ return son
+ }
+ }
+ accessorFactory(accessor, name)
+ var son = accessor._vmodel = modelFactory(initValue)
+ son.$events[subscribers] = list
+ return accessor
+}
+
+function globalUpdateValue(vmodel, value) {
+ vmodel.$model[this._name] = this._value = value
+}
+
+function globalNotify(vmodel, value, oldValue) {
+ var name = this._name
+ var array = vmodel.$events[name] //刷新值
+ if (array) {
+ fireDependencies(array) //同步视图
+ EventBus.$fire.call(vmodel, name, value, oldValue) //触发$watch回调
+ }
+}
+
+function accessorFactory(accessor, name) {
+ accessor._name = name
+ //同时更新_value与model
+ accessor.updateValue = globalUpdateValue
+ accessor.notify = globalNotify
+}
+
+//比较两个值是否相等
+var isEqual = Object.is || function (v1, v2) {
+ if (v1 === 0 && v2 === 0) {
+ return 1 / v1 === 1 / v2
+ } else if (v1 !== v1) {
+ return v2 !== v2
+ } else {
+ return v1 === v2
+ }
+}
+
+function isObservable(name, value, $skipArray) {
+ if (isFunction(value) || value && value.nodeType) {
+ return false
+ }
+ if ($skipArray.indexOf(name) !== -1) {
+ return false
+ }
+ var $special = $skipArray.$special
+ if (name && name.charAt(0) === "$" && !$special[name]) {
+ return false
+ }
+ return true
+}
+
+var descriptorFactory = W3C ? function (obj) {
+ var descriptors = {}
+ for (var i in obj) {
+ descriptors[i] = {
+ get: obj[i],
+ set: obj[i],
+ enumerable: true,
+ configurable: true
+ }
+ }
+ return descriptors
+} : function (a) {
+ return a
+}
+
+//===================修复浏览器对Object.defineProperties的支持=================
+if (!canHideOwn) {
+ if ("__defineGetter__" in avalon) {
+ defineProperty = function (obj, prop, desc) {
+ if ('value' in desc) {
+ obj[prop] = desc.value
+ }
+ if ("get" in desc) {
+ obj.__defineGetter__(prop, desc.get)
+ }
+ if ('set' in desc) {
+ obj.__defineSetter__(prop, desc.set)
+ }
+ return obj
+ }
+ defineProperties = function (obj, descs) {
+ for (var prop in descs) {
+ if (descs.hasOwnProperty(prop)) {
+ defineProperty(obj, prop, descs[prop])
+ }
+ }
+ return obj
+ }
+ }
+ if (IEVersion) {
+ var VBClassPool = {}
+ window.execScript([// jshint ignore:line
+ "Function parseVB(code)",
+ "\tExecuteGlobal(code)",
+ "End Function" //转换一段文本为VB代码
+ ].join("\n"), "VBScript")
+ function VBMediator(instance, accessors, name, value) {// jshint ignore:line
+ var accessor = accessors[name]
+ if (arguments.length === 4) {
+ accessor.call(instance, value)
+ } else {
+ return accessor.call(instance)
+ }
+ }
+ defineProperties = function (name, accessors, properties) {
+ // jshint ignore:line
+ var buffer = []
+ buffer.push(
+ "\r\n\tPrivate [__data__], [__proxy__]",
+ "\tPublic Default Function [__const__](d, p)",
+ "\t\tSet [__data__] = d: set [__proxy__] = p",
+ "\t\tSet [__const__] = Me", //链式调用
+ "\tEnd Function")
+ //添加普通属性,因为VBScript对象不能像JS那样随意增删属性,必须在这里预先定义好
+ for (name in properties) {
+ if (!accessors.hasOwnProperty(name)) {
+ buffer.push("\tPublic [" + name + "]")
+ }
+ }
+ $$skipArray.forEach(function (name) {
+ if (!accessors.hasOwnProperty(name)) {
+ buffer.push("\tPublic [" + name + "]")
+ }
+ })
+ buffer.push("\tPublic [" + 'hasOwnProperty' + "]")
+ //添加访问器属性
+ for (name in accessors) {
+ buffer.push(
+ //由于不知对方会传入什么,因此set, let都用上
+ "\tPublic Property Let [" + name + "](val" + expose + ")", //setter
+ "\t\tCall [__proxy__](Me,[__data__], \"" + name + "\", val" + expose + ")",
+ "\tEnd Property",
+ "\tPublic Property Set [" + name + "](val" + expose + ")", //setter
+ "\t\tCall [__proxy__](Me,[__data__], \"" + name + "\", val" + expose + ")",
+ "\tEnd Property",
+ "\tPublic Property Get [" + name + "]", //getter
+ "\tOn Error Resume Next", //必须优先使用set语句,否则它会误将数组当字符串返回
+ "\t\tSet[" + name + "] = [__proxy__](Me,[__data__],\"" + name + "\")",
+ "\tIf Err.Number <> 0 Then",
+ "\t\t[" + name + "] = [__proxy__](Me,[__data__],\"" + name + "\")",
+ "\tEnd If",
+ "\tOn Error Goto 0",
+ "\tEnd Property")
+
+ }
+
+ buffer.push("End Class")
+ var body = buffer.join("\r\n")
+ var className =VBClassPool[body]
+ if (!className) {
+ className = generateID("VBClass")
+ window.parseVB("Class " + className + body)
+ window.parseVB([
+ "Function " + className + "Factory(a, b)", //创建实例并传入两个关键的参数
+ "\tDim o",
+ "\tSet o = (New " + className + ")(a, b)",
+ "\tSet " + className + "Factory = o",
+ "End Function"
+ ].join("\r\n"))
+ VBClassPool[body] = className
+ }
+ var ret = window[className + "Factory"](accessors, VBMediator) //得到其产品
+ return ret //得到其产品
+ }
+ }
+}
+
+/*********************************************************************
+ * 监控数组(与ms-each, ms-repeat配合使用) *
+ **********************************************************************/
+
+function arrayFactory(model) {
+ var array = []
+ array.$id = generateID()
+ array.$model = model //数据模型
+ array.$events = {}
+ array.$events[subscribers] = []
+ array._ = modelFactory({
+ length: model.length
+ })
+ array._.$watch("length", function (a, b) {
+ array.$fire("length", a, b)
+ })
+ for (var i in EventBus) {
+ array[i] = EventBus[i]
+ }
+ avalon.mix(array, arrayPrototype)
+ return array
+}
+
+function mutateArray(method, pos, n, index, method2, pos2, n2) {
+ var oldLen = this.length, loop = 2
+ while (--loop) {
+ switch (method) {
+ case "add":
+ /* jshint ignore:start */
+ var array = this.$model.slice(pos, pos + n).map(function (el) {
+ if (rcomplexType.test(avalon.type(el))) {
+ return el.$id ? el : modelFactory(el, 0, el)
+ } else {
+ return el
+ }
+ })
+ /* jshint ignore:end */
+ _splice.apply(this, [pos, 0].concat(array))
+ this._fire("add", pos, n)
+ break
+ case "del":
+ var ret = this._splice(pos, n)
+ this._fire("del", pos, n)
+ break
+ }
+ if (method2) {
+ method = method2
+ pos = pos2
+ n = n2
+ loop = 2
+ method2 = 0
+ }
+ }
+ this._fire("index", index)
+ if (this.length !== oldLen) {
+ this._.length = this.length
+ }
+ return ret
+}
+
+var _splice = ap.splice
+var arrayPrototype = {
+ _splice: _splice,
+ _fire: function (method, a, b) {
+ fireDependencies(this.$events[subscribers], method, a, b)
+ },
+ size: function () { //取得数组长度,这个函数可以同步视图,length不能
+ return this._.length
+ },
+ pushArray: function (array) {
+ var m = array.length, n = this.length
+ if (m) {
+ ap.push.apply(this.$model, array)
+ mutateArray.call(this, "add", n, m, Math.max(0, n - 1))
+ }
+ return m + n
+ },
+ push: function () {
+ //http://jsperf.com/closure-with-arguments
+ var array = []
+ var i, n = arguments.length
+ for (i = 0; i < n; i++) {
+ array[i] = arguments[i]
+ }
+ return this.pushArray(array)
+ },
+ unshift: function () {
+ var m = arguments.length, n = this.length
+ if (m) {
+ ap.unshift.apply(this.$model, arguments)
+ mutateArray.call(this, "add", 0, m, 0)
+ }
+ return m + n //IE67的unshift不会返回长度
+ },
+ shift: function () {
+ if (this.length) {
+ var el = this.$model.shift()
+ mutateArray.call(this, "del", 0, 1, 0)
+ return el //返回被移除的元素
+ }
+ },
+ pop: function () {
+ var n = this.length
+ if (n) {
+ var el = this.$model.pop()
+ mutateArray.call(this, "del", n - 1, 1, Math.max(0, n - 2))
+ return el //返回被移除的元素
+ }
+ },
+ splice: function (start) {
+ var m = arguments.length, args = [], change
+ var removed = _splice.apply(this.$model, arguments)
+ if (removed.length) { //如果用户删掉了元素
+ args.push("del", start, removed.length, 0)
+ change = true
+ }
+ if (m > 2) { //如果用户添加了元素
+ if (change) {
+ args.splice(3, 1, 0, "add", start, m - 2)
+ } else {
+ args.push("add", start, m - 2, 0)
+ }
+ change = true
+ }
+ if (change) { //返回被移除的元素
+ return mutateArray.apply(this, args)
+ } else {
+ return []
+ }
+ },
+ contains: function (el) { //判定是否包含
+ return this.indexOf(el) !== -1
+ },
+ remove: function (el) { //移除第一个等于给定值的元素
+ return this.removeAt(this.indexOf(el))
+ },
+ removeAt: function (index) { //移除指定索引上的元素
+ if (index >= 0) {
+ this.$model.splice(index, 1)
+ return mutateArray.call(this, "del", index, 1, 0)
+ }
+ return []
+ },
+ clear: function () {
+ this.$model.length = this.length = this._.length = 0 //清空数组
+ this._fire("clear", 0)
+ return this
+ },
+ removeAll: function (all) { //移除N个元素
+ if (Array.isArray(all)) {
+ for (var i = this.length - 1; i >= 0; i--) {
+ if (all.indexOf(this[i]) !== -1) {
+ this.removeAt(i)
+ }
+ }
+ } else if (typeof all === "function") {
+ for ( i = this.length - 1; i >= 0; i--) {
+ var el = this[i]
+ if (all(el, i)) {
+ this.removeAt(i)
+ }
+ }
+ } else {
+ this.clear()
+ }
+ },
+ ensure: function (el) {
+ if (!this.contains(el)) { //只有不存在才push
+ this.push(el)
+ }
+ return this
+ },
+ set: function (index, val) {
+ if (index >= 0) {
+ var valueType = avalon.type(val)
+ if (val && val.$model) {
+ val = val.$model
+ }
+ var target = this[index]
+ if (valueType === "object") {
+ for (var i in val) {
+ if (target.hasOwnProperty(i)) {
+ target[i] = val[i]
+ }
+ }
+ } else if (valueType === "array") {
+ target.clear().push.apply(target, val)
+ } else if (target !== val) {
+ this[index] = val
+ this.$model[index] = val
+ this._fire("set", index, val)
+ }
+ }
+ return this
+ }
+}
+//相当于原来bindingExecutors.repeat 的index分支
+function resetIndex(array, pos) {
+ var last = array.length - 1
+ for (var el; el = array[pos]; pos++) {
+ el.$index = pos
+ el.$first = pos === 0
+ el.$last = pos === last
+ }
+}
+
+function sortByIndex(array, indexes) {
+ var map = {};
+ for (var i = 0, n = indexes.length; i < n; i++) {
+ map[i] = array[i] // preserve
+ var j = indexes[i]
+ if (j in map) {
+ array[i] = map[j]
+ delete map[j]
+ } else {
+ array[i] = array[j]
+ }
+ }
+}
+
+"sort,reverse".replace(rword, function (method) {
+ arrayPrototype[method] = function () {
+ var newArray = this.$model//这是要排序的新数组
+ var oldArray = newArray.concat() //保持原来状态的旧数组
+ var mask = Math.random()
+ var indexes = []
+ var hasSort
+ ap[method].apply(newArray, arguments) //排序
+ for (var i = 0, n = oldArray.length; i < n; i++) {
+ var neo = newArray[i]
+ var old = oldArray[i]
+ if (isEqual(neo, old)) {
+ indexes.push(i)
+ } else {
+ var index = oldArray.indexOf(neo)
+ indexes.push(index)//得到新数组的每个元素在旧数组对应的位置
+ oldArray[index] = mask //屏蔽已经找过的元素
+ hasSort = true
+ }
+ }
+ if (hasSort) {
+ sortByIndex(this, indexes)
+ // sortByIndex(this.$proxy, indexes)
+ this._fire("move", indexes)
+ this._fire("index", 0)
+ }
+ return this
+ }
+})
+
+
+/*********************************************************************
+ * 依赖调度系统 *
+ **********************************************************************/
+//检测两个对象间的依赖关系
+var dependencyDetection = (function () {
+ var outerFrames = []
+ var currentFrame
+ return {
+ begin: function (accessorObject) {
+ //accessorObject为一个拥有callback的对象
+ outerFrames.push(currentFrame)
+ currentFrame = accessorObject
+ },
+ end: function () {
+ currentFrame = outerFrames.pop()
+ },
+ collectDependency: function (vmodel, accessor) {
+ if (currentFrame) {
+ //被dependencyDetection.begin调用
+ currentFrame.callback(vmodel, accessor);
+ }
+ }
+ };
+})()
+//将绑定对象注入到其依赖项的订阅数组中
+var ronduplex = /^(duplex|on)$/
+avalon.injectBinding = function (data) {
+ var valueFn = data.evaluator
+ if (valueFn) { //如果是求值函数
+ dependencyDetection.begin({
+ callback: function (vmodel, dependency) {
+ injectDependency(vmodel.$events[dependency._name], data)
+ }
+ })
+ try {
+ var value = ronduplex.test(data.type) ? data : valueFn.apply(0, data.args)
+ if(value === void 0){
+ delete data.evaluator
+ }
+ data.handler(value, data.element, data)
+ } catch (e) {
+ //log("warning:exception throwed in [avalon.injectBinding] " + e)
+ delete data.evaluator
+ var node = data.element
+ if (node.nodeType === 3) {
+ var parent = node.parentNode
+ if (kernel.commentInterpolate) {
+ parent.replaceChild(DOC.createComment(data.value), node)
+ } else {
+ node.data = openTag + (data.oneTime ? "::" : "") + data.value + closeTag
+ }
+ }
+ } finally {
+ dependencyDetection.end()
+ }
+ }
+}
+
+//将依赖项(比它高层的访问器或构建视图刷新函数的绑定对象)注入到订阅者数组
+function injectDependency(list, data) {
+ if (data.oneTime)
+ return
+ if (list && avalon.Array.ensure(list, data) && data.element) {
+ injectDisposeQueue(data, list)
+ }
+}
+
+//通知依赖于这个访问器的订阅者更新自身
+function fireDependencies(list) {
+ if (list && list.length) {
+ if (new Date() - beginTime > 444 && typeof list[0] === "object") {
+ rejectDisposeQueue()
+ }
+ var args = aslice.call(arguments, 1)
+ for (var i = list.length, fn; fn = list[--i]; ) {
+ var el = fn.element
+ if (el && el.parentNode) {
+ try {
+ var valueFn = fn.evaluator
+ if (fn.$repeat) {
+ fn.handler.apply(fn, args) //处理监控数组的方法
+ }else if("$repeat" in fn || !valueFn ){//如果没有eval,先eval
+ bindingHandlers[fn.type](fn, fn.vmodels)
+ } else if (fn.type !== "on") { //事件绑定只能由用户触发,不能由程序触发
+ var value = valueFn.apply(0, fn.args || [])
+ fn.handler(value, el, fn)
+ }
+ } catch (e) { }
+ }
+ }
+ }
+}
+/*********************************************************************
+ * 定时GC回收机制 *
+ **********************************************************************/
+var disposeCount = 0
+var disposeQueue = avalon.$$subscribers = []
+var beginTime = new Date()
+var oldInfo = {}
+var uuid2Node = {}
+function getUid(obj, makeID) { //IE9+,标准浏览器
+ if (!obj.uuid && !makeID) {
+ obj.uuid = ++disposeCount
+ uuid2Node[obj.uuid] = obj
+ }
+ return obj.uuid
+}
+function getNode(uuid) {
+ return uuid2Node[uuid]
+}
+//添加到回收列队中
+function injectDisposeQueue(data, list) {
+ var elem = data.element
+ if (!data.uuid) {
+ if (elem.nodeType !== 1) {
+ data.uuid = data.type + (data.pos || 0) + "-" + getUid(elem.parentNode)
+ } else {
+ data.uuid = data.name + "-" + getUid(elem)
+ }
+ }
+ var lists = data.lists || (data.lists = [])
+ avalon.Array.ensure(lists, list)
+ list.$uuid = list.$uuid || generateID()
+ if (!disposeQueue[data.uuid]) {
+ disposeQueue[data.uuid] = 1
+ disposeQueue.push(data)
+ }
+}
+
+function rejectDisposeQueue(data) {
+ if (avalon.optimize)
+ return
+ var i = disposeQueue.length
+ var n = i
+ var allTypes = []
+ var iffishTypes = {}
+ var newInfo = {}
+ //对页面上所有绑定对象进行分门别类, 只检测个数发生变化的类型
+ while (data = disposeQueue[--i]) {
+ var type = data.type
+ if (newInfo[type]) {
+ newInfo[type]++
+ } else {
+ newInfo[type] = 1
+ allTypes.push(type)
+ }
+ }
+ var diff = false
+ allTypes.forEach(function (type) {
+ if (oldInfo[type] !== newInfo[type]) {
+ iffishTypes[type] = 1
+ diff = true
+ }
+ })
+ i = n
+ if (diff) {
+ while (data = disposeQueue[--i]) {
+ if (!data.element)
+ continue
+ if (iffishTypes[data.type] && shouldDispose(data.element)) { //如果它没有在DOM树
+ disposeQueue.splice(i, 1)
+ delete disposeQueue[data.uuid]
+ delete uuid2Node[data.element.uuid]
+ var lists = data.lists
+ for (var k = 0, list; list = lists[k++]; ) {
+ avalon.Array.remove(lists, list)
+ avalon.Array.remove(list, data)
+ }
+ disposeData(data)
+ }
+ }
+ }
+ oldInfo = newInfo
+ beginTime = new Date()
+}
+
+function disposeData(data) {
+ data.element = null
+ data.rollback && data.rollback()
+ for (var key in data) {
+ data[key] = null
+ }
+}
+
+function shouldDispose(el) {
+ try {//IE下,如果文本节点脱离DOM树,访问parentNode会报错
+ if (!el.parentNode) {
+ return true
+ }
+ } catch (e) {
+ return true
+ }
+
+ return el.msRetain ? 0 : (el.nodeType === 1 ? !root.contains(el) : !avalon.contains(root, el))
+}
+
+/************************************************************************
+ * HTML处理(parseHTML, innerHTML, clearHTML) *
+ ************************************************************************/
+// We have to close these tags to support XHTML
+var tagHooks = {
+ area: [1, ""],
+ param: [1, ""],
+ col: [2, "
+ for (els = target.childNodes, i = 0; el = els[i++]; ) {
+ if (el.tagName === "TBODY" && !el.innerHTML) {
+ target.removeChild(el)
+ break
+ }
+ }
+ }
+ els = wrapper.getElementsByTagName("br")
+ var n = els.length
+ while (el = els[--n]) {
+ if (el.className === "msNoScope") {
+ el.parentNode.removeChild(el)
+ }
+ }
+ for (els = wrapper.all, i = 0; el = els[i++]; ) { //fix VML
+ if (isVML(el)) {
+ fixVML(el)
+ }
+ }
+ }
+ //移除我们为了符合套嵌关系而添加的标签
+ for (i = wrap[0]; i--; wrapper = wrapper.lastChild) {
+ }
+ while (firstChild = wrapper.firstChild) { // 将wrapper上的节点转移到文档碎片上!
+ fragment.appendChild(firstChild)
+ }
+ return fragment
+}
+
+function isVML(src) {
+ var nodeName = src.nodeName
+ return nodeName.toLowerCase() === nodeName && src.scopeName && src.outerText === ""
+}
+
+function fixVML(node) {
+ if (node.currentStyle.behavior !== "url(#default#VML)") {
+ node.style.behavior = "url(#default#VML)"
+ node.style.display = "inline-block"
+ node.style.zoom = 1 //hasLayout
+ }
+}
+avalon.innerHTML = function (node, html) {
+ if (!W3C && (!rcreate.test(html) && !rnest.test(html))) {
+ try {
+ node.innerHTML = html
+ return
+ } catch (e) {
+ }
+ }
+ var a = this.parseHTML(html)
+ this.clearHTML(node).appendChild(a)
+}
+avalon.clearHTML = function (node) {
+ node.textContent = ""
+ while (node.firstChild) {
+ node.removeChild(node.firstChild)
+ }
+ return node
+}
+
+/*********************************************************************
+ * avalon的原型方法定义区 *
+ **********************************************************************/
+
+function hyphen(target) {
+ //转换为连字符线风格
+ return target.replace(/([a-z\d])([A-Z]+)/g, "$1-$2").toLowerCase()
+}
+
+function camelize(target) {
+ //提前判断,提高getStyle等的效率
+ if (!target || target.indexOf("-") < 0 && target.indexOf("_") < 0) {
+ return target
+ }
+ //转换为驼峰风格
+ return target.replace(/[-_][^-_]/g, function(match) {
+ return match.charAt(1).toUpperCase()
+ })
+}
+
+var fakeClassListMethods = {
+ _toString: function() {
+ var node = this.node
+ var cls = node.className
+ var str = typeof cls === "string" ? cls : cls.baseVal
+ return str.split(/\s+/).join(" ")
+ },
+ _contains: function(cls) {
+ return (" " + this + " ").indexOf(" " + cls + " ") > -1
+ },
+ _add: function(cls) {
+ if (!this.contains(cls)) {
+ this._set(this + " " + cls)
+ }
+ },
+ _remove: function(cls) {
+ this._set((" " + this + " ").replace(" " + cls + " ", " "))
+ },
+ __set: function(cls) {
+ cls = cls.trim()
+ var node = this.node
+ if (rsvg.test(node)) {
+ //SVG元素的className是一个对象 SVGAnimatedString { baseVal="", animVal=""},只能通过set/getAttribute操作
+ node.setAttribute("class", cls)
+ } else {
+ node.className = cls
+ }
+ } //toggle存在版本差异,因此不使用它
+}
+
+ function fakeClassList(node) {
+ if (!("classList" in node)) {
+ node.classList = {
+ node: node
+ }
+ for (var k in fakeClassListMethods) {
+ node.classList[k.slice(1)] = fakeClassListMethods[k]
+ }
+ }
+ return node.classList
+ }
+
+
+ "add,remove".replace(rword, function(method) {
+ avalon.fn[method + "Class"] = function(cls) {
+ var el = this[0]
+ //https://developer.mozilla.org/zh-CN/docs/Mozilla/Firefox/Releases/26
+ if (cls && typeof cls === "string" && el && el.nodeType === 1) {
+ cls.replace(/\S+/g, function(c) {
+ fakeClassList(el)[method](c)
+ })
+ }
+ return this
+ }
+ })
+ avalon.fn.mix({
+ hasClass: function(cls) {
+ var el = this[0] || {}
+ return el.nodeType === 1 && fakeClassList(el).contains(cls)
+ },
+ toggleClass: function(value, stateVal) {
+ var className, i = 0
+ var classNames = String(value).split(/\s+/)
+ var isBool = typeof stateVal === "boolean"
+ while ((className = classNames[i++])) {
+ var state = isBool ? stateVal : !this.hasClass(className)
+ this[state ? "addClass" : "removeClass"](className)
+ }
+ return this
+ },
+ attr: function(name, value) {
+ if (arguments.length === 2) {
+ this[0].setAttribute(name, value)
+ return this
+ } else {
+ return this[0].getAttribute(name)
+ }
+ },
+ data: function(name, value) {
+ name = "data-" + hyphen(name || "")
+ switch (arguments.length) {
+ case 2:
+ this.attr(name, value)
+ return this
+ case 1:
+ var val = this.attr(name)
+ return parseData(val)
+ case 0:
+ var ret = {}
+ ap.forEach.call(this[0].attributes, function(attr) {
+ if (attr) {
+ name = attr.name
+ if (!name.indexOf("data-")) {
+ name = camelize(name.slice(5))
+ ret[name] = parseData(attr.value)
+ }
+ }
+ })
+ return ret
+ }
+ },
+ removeData: function(name) {
+ name = "data-" + hyphen(name)
+ this[0].removeAttribute(name)
+ return this
+ },
+ css: function(name, value) {
+ if (avalon.isPlainObject(name)) {
+ for (var i in name) {
+ avalon.css(this, i, name[i])
+ }
+ } else {
+ var ret = avalon.css(this, name, value)
+ }
+ return ret !== void 0 ? ret : this
+ },
+ position: function() {
+ var offsetParent, offset,
+ elem = this[0],
+ parentOffset = {
+ top: 0,
+ left: 0
+ }
+ if (!elem) {
+ return
+ }
+ if (this.css("position") === "fixed") {
+ offset = elem.getBoundingClientRect()
+ } else {
+ offsetParent = this.offsetParent() //得到真正的offsetParent
+ offset = this.offset() // 得到正确的offsetParent
+ if (offsetParent[0].tagName !== "HTML") {
+ parentOffset = offsetParent.offset()
+ }
+ parentOffset.top += avalon.css(offsetParent[0], "borderTopWidth", true)
+ parentOffset.left += avalon.css(offsetParent[0], "borderLeftWidth", true)
+
+ // Subtract offsetParent scroll positions
+ parentOffset.top -= offsetParent.scrollTop()
+ parentOffset.left -= offsetParent.scrollLeft()
+ }
+ return {
+ top: offset.top - parentOffset.top - avalon.css(elem, "marginTop", true),
+ left: offset.left - parentOffset.left - avalon.css(elem, "marginLeft", true)
+ }
+ },
+ offsetParent: function() {
+ var offsetParent = this[0].offsetParent
+ while (offsetParent && avalon.css(offsetParent, "position") === "static") {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return avalon(offsetParent || root)
+ },
+ bind: function(type, fn, phase) {
+ if (this[0]) { //此方法不会链
+ return avalon.bind(this[0], type, fn, phase)
+ }
+ },
+ unbind: function(type, fn, phase) {
+ if (this[0]) {
+ avalon.unbind(this[0], type, fn, phase)
+ }
+ return this
+ },
+ val: function(value) {
+ var node = this[0]
+ if (node && node.nodeType === 1) {
+ var get = arguments.length === 0
+ var access = get ? ":get" : ":set"
+ var fn = valHooks[getValType(node) + access]
+ if (fn) {
+ var val = fn(node, value)
+ } else if (get) {
+ return (node.value || "").replace(/\r/g, "")
+ } else {
+ node.value = value
+ }
+ }
+ return get ? val : this
+ }
+ })
+
+ function parseData(data) {
+ try {
+ if (typeof data === "object")
+ return data
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null : +data + "" === data ? +data : rbrace.test(data) ? avalon.parseJSON(data) : data
+ } catch (e) {}
+ return data
+ }
+var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g
+avalon.parseJSON = window.JSON ? JSON.parse : function(data) {
+ if (typeof data === "string") {
+ data = data.trim();
+ if (data) {
+ if (rvalidchars.test(data.replace(rvalidescape, "@")
+ .replace(rvalidtokens, "]")
+ .replace(rvalidbraces, ""))) {
+ return (new Function("return " + data))() // jshint ignore:line
+ }
+ }
+ avalon.error("Invalid JSON: " + data)
+ }
+ return data
+}
+
+//生成avalon.fn.scrollLeft, avalon.fn.scrollTop方法
+avalon.each({
+ scrollLeft: "pageXOffset",
+ scrollTop: "pageYOffset"
+}, function(method, prop) {
+ avalon.fn[method] = function(val) {
+ var node = this[0] || {}, win = getWindow(node),
+ top = method === "scrollTop"
+ if (!arguments.length) {
+ return win ? (prop in win) ? win[prop] : root[method] : node[method]
+ } else {
+ if (win) {
+ win.scrollTo(!top ? val : avalon(win).scrollLeft(), top ? val : avalon(win).scrollTop())
+ } else {
+ node[method] = val
+ }
+ }
+ }
+})
+
+function getWindow(node) {
+ return node.window && node.document ? node : node.nodeType === 9 ? node.defaultView || node.parentWindow : false;
+}
+//=============================css相关=======================
+var cssHooks = avalon.cssHooks = {}
+var prefixes = ["", "-webkit-", "-o-", "-moz-", "-ms-"]
+var cssMap = {
+ "float": W3C ? "cssFloat" : "styleFloat"
+}
+avalon.cssNumber = oneObject("columnCount,order,fillOpacity,fontWeight,lineHeight,opacity,orphans,widows,zIndex,zoom")
+
+avalon.cssName = function(name, host, camelCase) {
+ if (cssMap[name]) {
+ return cssMap[name]
+ }
+ host = host || root.style
+ for (var i = 0, n = prefixes.length; i < n; i++) {
+ camelCase = camelize(prefixes[i] + name)
+ if (camelCase in host) {
+ return (cssMap[name] = camelCase)
+ }
+ }
+ return null
+}
+cssHooks["@:set"] = function(node, name, value) {
+ try { //node.style.width = NaN;node.style.width = "xxxxxxx";node.style.width = undefine 在旧式IE下会抛异常
+ node.style[name] = value
+ } catch (e) {}
+}
+if (window.getComputedStyle) {
+ cssHooks["@:get"] = function(node, name) {
+ if (!node || !node.style) {
+ throw new Error("getComputedStyle要求传入一个节点 " + node)
+ }
+ var ret, styles = getComputedStyle(node, null)
+ if (styles) {
+ ret = name === "filter" ? styles.getPropertyValue(name) : styles[name]
+ if (ret === "") {
+ ret = node.style[name] //其他浏览器需要我们手动取内联样式
+ }
+ }
+ return ret
+ }
+ cssHooks["opacity:get"] = function(node) {
+ var ret = cssHooks["@:get"](node, "opacity")
+ return ret === "" ? "1" : ret
+ }
+} else {
+ var rnumnonpx = /^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i
+ var rposition = /^(top|right|bottom|left)$/
+ var ralpha = /alpha\([^)]*\)/i
+ var ie8 = !! window.XDomainRequest
+ var salpha = "DXImageTransform.Microsoft.Alpha"
+ var border = {
+ thin: ie8 ? '1px' : '2px',
+ medium: ie8 ? '3px' : '4px',
+ thick: ie8 ? '5px' : '6px'
+ }
+ cssHooks["@:get"] = function(node, name) {
+ //取得精确值,不过它有可能是带em,pc,mm,pt,%等单位
+ var currentStyle = node.currentStyle
+ var ret = currentStyle[name]
+ if ((rnumnonpx.test(ret) && !rposition.test(ret))) {
+ //①,保存原有的style.left, runtimeStyle.left,
+ var style = node.style,
+ left = style.left,
+ rsLeft = node.runtimeStyle.left
+ //②由于③处的style.left = xxx会影响到currentStyle.left,
+ //因此把它currentStyle.left放到runtimeStyle.left,
+ //runtimeStyle.left拥有最高优先级,不会style.left影响
+ node.runtimeStyle.left = currentStyle.left
+ //③将精确值赋给到style.left,然后通过IE的另一个私有属性 style.pixelLeft
+ //得到单位为px的结果;fontSize的分支见http://bugs.jquery.com/ticket/760
+ style.left = name === 'fontSize' ? '1em' : (ret || 0)
+ ret = style.pixelLeft + "px"
+ //④还原 style.left,runtimeStyle.left
+ style.left = left
+ node.runtimeStyle.left = rsLeft
+ }
+ if (ret === "medium") {
+ name = name.replace("Width", "Style")
+ //border width 默认值为medium,即使其为0"
+ if (currentStyle[name] === "none") {
+ ret = "0px"
+ }
+ }
+ return ret === "" ? "auto" : border[ret] || ret
+ }
+ cssHooks["opacity:set"] = function(node, name, value) {
+ var style = node.style
+ var opacity = isFinite(value) && value <= 1 ? "alpha(opacity=" + value * 100 + ")" : ""
+ var filter = style.filter || "";
+ style.zoom = 1
+ //不能使用以下方式设置透明度
+ //node.filters.alpha.opacity = value * 100
+ style.filter = (ralpha.test(filter) ?
+ filter.replace(ralpha, opacity) :
+ filter + " " + opacity).trim()
+ if (!style.filter) {
+ style.removeAttribute("filter")
+ }
+ }
+ cssHooks["opacity:get"] = function(node) {
+ //这是最快的获取IE透明值的方式,不需要动用正则了!
+ var alpha = node.filters.alpha || node.filters[salpha],
+ op = alpha && alpha.enabled ? alpha.opacity : 100
+ return (op / 100) + "" //确保返回的是字符串
+ }
+}
+
+"top,left".replace(rword, function(name) {
+ cssHooks[name + ":get"] = function(node) {
+ var computed = cssHooks["@:get"](node, name)
+ return /px$/.test(computed) ? computed :
+ avalon(node).position()[name] + "px"
+ }
+})
+
+var cssShow = {
+ position: "absolute",
+ visibility: "hidden",
+ display: "block"
+}
+
+var rdisplayswap = /^(none|table(?!-c[ea]).+)/
+
+ function showHidden(node, array) {
+ //http://www.cnblogs.com/rubylouvre/archive/2012/10/27/2742529.html
+ if (node.offsetWidth <= 0) { //opera.offsetWidth可能小于0
+ if (rdisplayswap.test(cssHooks["@:get"](node, "display"))) {
+ var obj = {
+ node: node
+ }
+ for (var name in cssShow) {
+ obj[name] = node.style[name]
+ node.style[name] = cssShow[name]
+ }
+ array.push(obj)
+ }
+ var parent = node.parentNode
+ if (parent && parent.nodeType === 1) {
+ showHidden(parent, array)
+ }
+ }
+ }
+ "Width,Height".replace(rword, function(name) { //fix 481
+ var method = name.toLowerCase(),
+ clientProp = "client" + name,
+ scrollProp = "scroll" + name,
+ offsetProp = "offset" + name
+ cssHooks[method + ":get"] = function(node, which, override) {
+ var boxSizing = -4
+ if (typeof override === "number") {
+ boxSizing = override
+ }
+ which = name === "Width" ? ["Left", "Right"] : ["Top", "Bottom"]
+ var ret = node[offsetProp] // border-box 0
+ if (boxSizing === 2) { // margin-box 2
+ return ret + avalon.css(node, "margin" + which[0], true) + avalon.css(node, "margin" + which[1], true)
+ }
+ if (boxSizing < 0) { // padding-box -2
+ ret = ret - avalon.css(node, "border" + which[0] + "Width", true) - avalon.css(node, "border" + which[1] + "Width", true)
+ }
+ if (boxSizing === -4) { // content-box -4
+ ret = ret - avalon.css(node, "padding" + which[0], true) - avalon.css(node, "padding" + which[1], true)
+ }
+ return ret
+ }
+ cssHooks[method + "&get"] = function(node) {
+ var hidden = [];
+ showHidden(node, hidden);
+ var val = cssHooks[method + ":get"](node)
+ for (var i = 0, obj; obj = hidden[i++];) {
+ node = obj.node
+ for (var n in obj) {
+ if (typeof obj[n] === "string") {
+ node.style[n] = obj[n]
+ }
+ }
+ }
+ return val;
+ }
+ avalon.fn[method] = function(value) { //会忽视其display
+ var node = this[0]
+ if (arguments.length === 0) {
+ if (node.setTimeout) { //取得窗口尺寸,IE9后可以用node.innerWidth /innerHeight代替
+ return node["inner" + name] || node.document.documentElement[clientProp]
+ }
+ if (node.nodeType === 9) { //取得页面尺寸
+ var doc = node.documentElement
+ //FF chrome html.scrollHeight< body.scrollHeight
+ //IE 标准模式 : html.scrollHeight> body.scrollHeight
+ //IE 怪异模式 : html.scrollHeight 最大等于可视窗口多一点?
+ return Math.max(node.body[scrollProp], doc[scrollProp], node.body[offsetProp], doc[offsetProp], doc[clientProp])
+ }
+ return cssHooks[method + "&get"](node)
+ } else {
+ return this.css(method, value)
+ }
+ }
+ avalon.fn["inner" + name] = function() {
+ return cssHooks[method + ":get"](this[0], void 0, -2)
+ }
+ avalon.fn["outer" + name] = function(includeMargin) {
+ return cssHooks[method + ":get"](this[0], void 0, includeMargin === true ? 2 : 0)
+ }
+ })
+ avalon.fn.offset = function() { //取得距离页面左右角的坐标
+ var node = this[0],
+ box = {
+ left: 0,
+ top: 0
+ }
+ if (!node || !node.tagName || !node.ownerDocument) {
+ return box
+ }
+ var doc = node.ownerDocument,
+ body = doc.body,
+ root = doc.documentElement,
+ win = doc.defaultView || doc.parentWindow
+ if (!avalon.contains(root, node)) {
+ return box
+ }
+ //http://hkom.blog1.fc2.com/?mode=m&no=750 body的偏移量是不包含margin的
+ //我们可以通过getBoundingClientRect来获得元素相对于client的rect.
+ //http://msdn.microsoft.com/en-us/library/ms536433.aspx
+ if (node.getBoundingClientRect) {
+ box = node.getBoundingClientRect() // BlackBerry 5, iOS 3 (original iPhone)
+ }
+ //chrome/IE6: body.scrollTop, firefox/other: root.scrollTop
+ var clientTop = root.clientTop || body.clientTop,
+ clientLeft = root.clientLeft || body.clientLeft,
+ scrollTop = Math.max(win.pageYOffset || 0, root.scrollTop, body.scrollTop),
+ scrollLeft = Math.max(win.pageXOffset || 0, root.scrollLeft, body.scrollLeft)
+ // 把滚动距离加到left,top中去。
+ // IE一些版本中会自动为HTML元素加上2px的border,我们需要去掉它
+ // http://msdn.microsoft.com/en-us/library/ms533564(VS.85).aspx
+ return {
+ top: box.top + scrollTop - clientTop,
+ left: box.left + scrollLeft - clientLeft
+ }
+ }
+
+ //==================================val相关============================
+
+ function getValType(elem) {
+ var ret = elem.tagName.toLowerCase()
+ return ret === "input" && /checkbox|radio/.test(elem.type) ? "checked" : ret
+ }
+var roption = /^';
+ }
+ }
+ else
+ {
+ for ( i=0, iLen=aLengthMenu.length ; i'+aLengthMenu[i]+'';
+ }
+ }
+ sStdMenu += '';
+
+ var nLength = document.createElement( 'div' );
+ if ( !oSettings.aanFeatures.l )
+ {
+ nLength.id = oSettings.sTableId+'_length';
+ }
+ nLength.className = oSettings.oClasses.sLength;
+ nLength.innerHTML = '';
+
+ /*
+ * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
+ * and Stefan Skopnik for fixing the fix!
+ */
+ $('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true);
+
+ $('select', nLength).bind( 'change.DT', function(e) {
+ var iVal = $(this).val();
+
+ /* Update all other length options for the new display */
+ var n = oSettings.aanFeatures.l;
+ for ( i=0, iLen=n.length ; i oSettings.aiDisplay.length ||
+ oSettings._iDisplayLength == -1 )
+ {
+ oSettings._iDisplayEnd = oSettings.aiDisplay.length;
+ }
+ else
+ {
+ oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
+ }
+ }
+ }
+
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Note that most of the paging logic is done in
+ * DataTable.ext.oPagination
+ */
+
+ /**
+ * Generate the node required for default pagination
+ * @param {object} oSettings dataTables settings object
+ * @returns {node} Pagination feature node
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlPaginate ( oSettings )
+ {
+ if ( oSettings.oScroll.bInfinite )
+ {
+ return null;
+ }
+
+ var nPaginate = document.createElement( 'div' );
+ nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;
+
+ DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate,
+ function( oSettings ) {
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ }
+ );
+
+ /* Add a draw callback for the pagination on first instance, to update the paging display */
+ if ( !oSettings.aanFeatures.p )
+ {
+ oSettings.aoDrawCallback.push( {
+ "fn": function( oSettings ) {
+ DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ } );
+ },
+ "sName": "pagination"
+ } );
+ }
+ return nPaginate;
+ }
+
+
+ /**
+ * Alter the display settings to change the page
+ * @param {object} oSettings dataTables settings object
+ * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
+ * or page number to jump to (integer)
+ * @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1
+ * @memberof DataTable#oApi
+ */
+ function _fnPageChange ( oSettings, mAction )
+ {
+ var iOldStart = oSettings._iDisplayStart;
+
+ if ( typeof mAction === "number" )
+ {
+ oSettings._iDisplayStart = mAction * oSettings._iDisplayLength;
+ if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() )
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+ else if ( mAction == "first" )
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ else if ( mAction == "previous" )
+ {
+ oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ?
+ oSettings._iDisplayStart - oSettings._iDisplayLength :
+ 0;
+
+ /* Correct for under-run */
+ if ( oSettings._iDisplayStart < 0 )
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+ else if ( mAction == "next" )
+ {
+ if ( oSettings._iDisplayLength >= 0 )
+ {
+ /* Make sure we are not over running the display array */
+ if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
+ {
+ oSettings._iDisplayStart += oSettings._iDisplayLength;
+ }
+ }
+ else
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+ else if ( mAction == "last" )
+ {
+ if ( oSettings._iDisplayLength >= 0 )
+ {
+ var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;
+ oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;
+ }
+ else
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+ else
+ {
+ _fnLog( oSettings, 0, "Unknown paging action: "+mAction );
+ }
+ $(oSettings.oInstance).trigger('page', oSettings);
+
+ return iOldStart != oSettings._iDisplayStart;
+ }
+
+
+
+ /**
+ * Generate the node required for the processing node
+ * @param {object} oSettings dataTables settings object
+ * @returns {node} Processing element
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlProcessing ( oSettings )
+ {
+ var nProcessing = document.createElement( 'div' );
+
+ if ( !oSettings.aanFeatures.r )
+ {
+ nProcessing.id = oSettings.sTableId+'_processing';
+ }
+ nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
+ nProcessing.className = oSettings.oClasses.sProcessing;
+ oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );
+
+ return nProcessing;
+ }
+
+
+ /**
+ * Display or hide the processing indicator
+ * @param {object} oSettings dataTables settings object
+ * @param {bool} bShow Show the processing indicator (true) or not (false)
+ * @memberof DataTable#oApi
+ */
+ function _fnProcessingDisplay ( oSettings, bShow )
+ {
+ if ( oSettings.oFeatures.bProcessing )
+ {
+ var an = oSettings.aanFeatures.r;
+ for ( var i=0, iLen=an.length ; i 0 )
+ {
+ nCaption = nCaption[0];
+ if ( nCaption._captionSide === "top" )
+ {
+ nScrollHeadTable.appendChild( nCaption );
+ }
+ else if ( nCaption._captionSide === "bottom" && nTfoot )
+ {
+ nScrollFootTable.appendChild( nCaption );
+ }
+ }
+
+ /*
+ * Sizing
+ */
+ /* When x-scrolling add the width and a scroller to move the header with the body */
+ if ( oSettings.oScroll.sX !== "" )
+ {
+ nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX );
+ nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX );
+
+ if ( nTfoot !== null )
+ {
+ nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX );
+ }
+
+ /* When the body is scrolled, then we also want to scroll the headers */
+ $(nScrollBody).scroll( function (e) {
+ nScrollHead.scrollLeft = this.scrollLeft;
+
+ if ( nTfoot !== null )
+ {
+ nScrollFoot.scrollLeft = this.scrollLeft;
+ }
+ } );
+ }
+
+ /* When yscrolling, add the height */
+ if ( oSettings.oScroll.sY !== "" )
+ {
+ nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY );
+ }
+
+ /* Redraw - align columns across the tables */
+ oSettings.aoDrawCallback.push( {
+ "fn": _fnScrollDraw,
+ "sName": "scrolling"
+ } );
+
+ /* Infinite scrolling event handlers */
+ if ( oSettings.oScroll.bInfinite )
+ {
+ $(nScrollBody).scroll( function() {
+ /* Use a blocker to stop scrolling from loading more data while other data is still loading */
+ if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 )
+ {
+ /* Check if we should load the next data set */
+ if ( $(this).scrollTop() + $(this).height() >
+ $(oSettings.nTable).height() - oSettings.oScroll.iLoadGap )
+ {
+ /* Only do the redraw if we have to - we might be at the end of the data */
+ if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() )
+ {
+ _fnPageChange( oSettings, 'next' );
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ }
+ }
+ }
+ } );
+ }
+
+ oSettings.nScrollHead = nScrollHead;
+ oSettings.nScrollFoot = nScrollFoot;
+
+ return nScroller;
+ }
+
+
+ /**
+ * Update the various tables for resizing. It's a bit of a pig this function, but
+ * basically the idea to:
+ * 1. Re-create the table inside the scrolling div
+ * 2. Take live measurements from the DOM
+ * 3. Apply the measurements
+ * 4. Clean up
+ * @param {object} o dataTables settings object
+ * @returns {node} Node to add to the DOM
+ * @memberof DataTable#oApi
+ */
+ function _fnScrollDraw ( o )
+ {
+ var
+ nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
+ nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
+ nScrollBody = o.nTable.parentNode,
+ i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
+ nTheadSize, nTfootSize,
+ iWidth, aApplied=[], aAppliedFooter=[], iSanityWidth,
+ nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,
+ nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,
+ ie67 = o.oBrowser.bScrollOversize,
+ zeroOut = function(nSizer) {
+ oStyle = nSizer.style;
+ oStyle.paddingTop = "0";
+ oStyle.paddingBottom = "0";
+ oStyle.borderTopWidth = "0";
+ oStyle.borderBottomWidth = "0";
+ oStyle.height = 0;
+ };
+
+ /*
+ * 1. Re-create the table inside the scrolling div
+ */
+
+ /* Remove the old minimised thead and tfoot elements in the inner table */
+ $(o.nTable).children('thead, tfoot').remove();
+
+ /* Clone the current header and footer elements and then place it into the inner table */
+ nTheadSize = $(o.nTHead).clone()[0];
+ o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );
+ anHeadToSize = o.nTHead.getElementsByTagName('tr');
+ anHeadSizers = nTheadSize.getElementsByTagName('tr');
+
+ if ( o.nTFoot !== null )
+ {
+ nTfootSize = $(o.nTFoot).clone()[0];
+ o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );
+ anFootToSize = o.nTFoot.getElementsByTagName('tr');
+ anFootSizers = nTfootSize.getElementsByTagName('tr');
+ }
+
+ /*
+ * 2. Take live measurements from the DOM - do not alter the DOM itself!
+ */
+
+ /* Remove old sizing and apply the calculated column widths
+ * Get the unique column headers in the newly created (cloned) header. We want to apply the
+ * calculated sizes to this header
+ */
+ if ( o.oScroll.sX === "" )
+ {
+ nScrollBody.style.width = '100%';
+ nScrollHeadInner.parentNode.style.width = '100%';
+ }
+
+ var nThs = _fnGetUniqueThs( o, nTheadSize );
+ for ( i=0, iLen=nThs.length ; i nScrollBody.offsetHeight ||
+ $(nScrollBody).css('overflow-y') == "scroll") )
+ {
+ o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);
+ }
+ }
+ else
+ {
+ if ( o.oScroll.sXInner !== "" )
+ {
+ /* x scroll inner has been given - use it */
+ o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
+ }
+ else if ( iSanityWidth == $(nScrollBody).width() &&
+ $(nScrollBody).height() < $(o.nTable).height() )
+ {
+ /* There is y-scrolling - try to take account of the y scroll bar */
+ o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth );
+ if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth )
+ {
+ /* Not possible to take account of it */
+ o.nTable.style.width = _fnStringToCss( iSanityWidth );
+ }
+ }
+ else
+ {
+ /* All else fails */
+ o.nTable.style.width = _fnStringToCss( iSanityWidth );
+ }
+ }
+
+ /* Recalculate the sanity width - now that we've applied the required width, before it was
+ * a temporary variable. This is required because the column width calculation is done
+ * before this table DOM is created.
+ */
+ iSanityWidth = $(o.nTable).outerWidth();
+
+ /* We want the hidden header to have zero height, so remove padding and borders. Then
+ * set the width based on the real headers
+ */
+
+ // Apply all styles in one pass. Invalidates layout only once because we don't read any
+ // DOM properties.
+ _fnApplyToChildren( zeroOut, anHeadSizers );
+
+ // Read all widths in next pass. Forces layout only once because we do not change
+ // any DOM properties.
+ _fnApplyToChildren( function(nSizer) {
+ aApplied.push( _fnStringToCss( $(nSizer).width() ) );
+ }, anHeadSizers );
+
+ // Apply all widths in final pass. Invalidates layout only once because we do not
+ // read any DOM properties.
+ _fnApplyToChildren( function(nToSize, i) {
+ nToSize.style.width = aApplied[i];
+ }, anHeadToSize );
+
+ $(anHeadSizers).height(0);
+
+ /* Same again with the footer if we have one */
+ if ( o.nTFoot !== null )
+ {
+ _fnApplyToChildren( zeroOut, anFootSizers );
+
+ _fnApplyToChildren( function(nSizer) {
+ aAppliedFooter.push( _fnStringToCss( $(nSizer).width() ) );
+ }, anFootSizers );
+
+ _fnApplyToChildren( function(nToSize, i) {
+ nToSize.style.width = aAppliedFooter[i];
+ }, anFootToSize );
+
+ $(anFootSizers).height(0);
+ }
+
+ /*
+ * 3. Apply the measurements
+ */
+
+ /* "Hide" the header and footer that we used for the sizing. We want to also fix their width
+ * to what they currently are
+ */
+ _fnApplyToChildren( function(nSizer, i) {
+ nSizer.innerHTML = "";
+ nSizer.style.width = aApplied[i];
+ //fix column align
+ nSizer.style.minWidth =nSizer.style.width;
+ }, anHeadSizers );
+
+ if ( o.nTFoot !== null )
+ {
+ _fnApplyToChildren( function(nSizer, i) {
+ nSizer.innerHTML = "";
+ nSizer.style.width = aAppliedFooter[i];
+ }, anFootSizers );
+ }
+
+ /* Sanity check that the table is of a sensible width. If not then we are going to get
+ * misalignment - try to prevent this by not allowing the table to shrink below its min width
+ */
+ if ( $(o.nTable).outerWidth() < iSanityWidth )
+ {
+ /* The min width depends upon if we have a vertical scrollbar visible or not */
+ var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight ||
+ $(nScrollBody).css('overflow-y') == "scroll")) ?
+ iSanityWidth+o.oScroll.iBarWidth : iSanityWidth;
+
+ /* IE6/7 are a law unto themselves... */
+ if ( ie67 && (nScrollBody.scrollHeight >
+ nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll") )
+ {
+ o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth );
+ }
+
+ /* Apply the calculated minimum width to the table wrappers */
+ nScrollBody.style.width = _fnStringToCss( iCorrection );
+ o.nScrollHead.style.width = _fnStringToCss( iCorrection );
+
+ if ( o.nTFoot !== null )
+ {
+ o.nScrollFoot.style.width = _fnStringToCss( iCorrection );
+ }
+
+ /* And give the user a warning that we've stopped the table getting too small */
+ if ( o.oScroll.sX === "" )
+ {
+ _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
+ " misalignment. The table has been drawn at its minimum possible width." );
+ }
+ else if ( o.oScroll.sXInner !== "" )
+ {
+ _fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
+ " misalignment. Increase the sScrollXInner value or remove it to allow automatic"+
+ " calculation" );
+ }
+ }
+ else
+ {
+ nScrollBody.style.width = _fnStringToCss( '100%' );
+ o.nScrollHead.style.width = _fnStringToCss( '100%' );
+
+ if ( o.nTFoot !== null )
+ {
+ o.nScrollFoot.style.width = _fnStringToCss( '100%' );
+ }
+ }
+
+
+ /*
+ * 4. Clean up
+ */
+ if ( o.oScroll.sY === "" )
+ {
+ /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
+ * the scrollbar height from the visible display, rather than adding it on. We need to
+ * set the height in order to sort this. Don't want to do it in any other browsers.
+ */
+ if ( ie67 )
+ {
+ nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth );
+ }
+ }
+
+ if ( o.oScroll.sY !== "" && o.oScroll.bCollapse )
+ {
+ nScrollBody.style.height = _fnStringToCss( o.oScroll.sY );
+
+ var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
+ o.oScroll.iBarWidth : 0;
+ if ( o.nTable.offsetHeight < nScrollBody.offsetHeight )
+ {
+ nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra );
+ }
+ }
+
+ /* Finally set the width's of the header and footer tables */
+ var iOuterWidth = $(o.nTable).outerWidth();
+ nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
+ nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth );
+
+ // Figure out if there are scrollbar present - if so then we need a the header and footer to
+ // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
+ var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
+ nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
+
+ if ( o.nTFoot !== null )
+ {
+ nScrollFootTable.style.width = _fnStringToCss( iOuterWidth );
+ nScrollFootInner.style.width = _fnStringToCss( iOuterWidth );
+ nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
+ }
+
+ /* Adjust the position of the header in case we loose the y-scrollbar */
+ $(nScrollBody).scroll();
+
+ /* If sorting or filtering has occurred, jump the scrolling back to the top */
+ if ( o.bSorted || o.bFiltered )
+ {
+ nScrollBody.scrollTop = 0;
+ }
+ }
+
+
+ /**
+ * Apply a given function to the display child nodes of an element array (typically
+ * TD children of TR rows
+ * @param {function} fn Method to apply to the objects
+ * @param array {nodes} an1 List of elements to look through for display children
+ * @param array {nodes} an2 Another list (identical structure to the first) - optional
+ * @memberof DataTable#oApi
+ */
+ function _fnApplyToChildren( fn, an1, an2 )
+ {
+ var index=0, i=0, iLen=an1.length;
+ var nNode1, nNode2;
+
+ while ( i < iLen )
+ {
+ nNode1 = an1[i].firstChild;
+ nNode2 = an2 ? an2[i].firstChild : null;
+ while ( nNode1 )
+ {
+ if ( nNode1.nodeType === 1 )
+ {
+ if ( an2 )
+ {
+ fn( nNode1, nNode2, index );
+ }
+ else
+ {
+ fn( nNode1, index );
+ }
+ index++;
+ }
+ nNode1 = nNode1.nextSibling;
+ nNode2 = an2 ? nNode2.nextSibling : null;
+ }
+ i++;
+ }
+ }
+
+ /**
+ * Convert a CSS unit width to pixels (e.g. 2em)
+ * @param {string} sWidth width to be converted
+ * @param {node} nParent parent to get the with for (required for relative widths) - optional
+ * @returns {int} iWidth width in pixels
+ * @memberof DataTable#oApi
+ */
+ function _fnConvertToWidth ( sWidth, nParent )
+ {
+ if ( !sWidth || sWidth === null || sWidth === '' )
+ {
+ return 0;
+ }
+
+ if ( !nParent )
+ {
+ nParent = document.body;
+ }
+
+ var iWidth;
+ var nTmp = document.createElement( "div" );
+ nTmp.style.width = _fnStringToCss( sWidth );
+
+ nParent.appendChild( nTmp );
+ iWidth = nTmp.offsetWidth;
+ nParent.removeChild( nTmp );
+
+ return ( iWidth );
+ }
+
+
+ /**
+ * Calculate the width of columns for the table
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnCalculateColumnWidths ( oSettings )
+ {
+ var iTableWidth = oSettings.nTable.offsetWidth;
+ var iUserInputs = 0;
+ var iTmpWidth;
+ var iVisibleColumns = 0;
+ var iColums = oSettings.aoColumns.length;
+ var i, iIndex, iCorrector, iWidth;
+ var oHeaders = $('th', oSettings.nTHead);
+ var widthAttr = oSettings.nTable.getAttribute('width');
+ var nWrapper = oSettings.nTable.parentNode;
+
+ /* Convert any user input sizes into pixel sizes */
+ for ( i=0 ; itd', nCalcTmp);
+ }
+
+ /* Apply custom sizing to the cloned header */
+ var nThs = _fnGetUniqueThs( oSettings, nTheadClone );
+ iCorrector = 0;
+ for ( i=0 ; i 0 )
+ {
+ oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth );
+ }
+ iCorrector++;
+ }
+ }
+
+ var cssWidth = $(nCalcTmp).css('width');
+ oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?
+ cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() );
+ nCalcTmp.parentNode.removeChild( nCalcTmp );
+ }
+
+ if ( widthAttr )
+ {
+ oSettings.nTable.style.width = _fnStringToCss( widthAttr );
+ }
+ }
+
+
+ /**
+ * Adjust a table's width to take account of scrolling
+ * @param {object} oSettings dataTables settings object
+ * @param {node} n table node
+ * @memberof DataTable#oApi
+ */
+ function _fnScrollingWidthAdjust ( oSettings, n )
+ {
+ if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" )
+ {
+ /* When y-scrolling only, we want to remove the width of the scroll bar so the table
+ * + scroll bar will fit into the area avaialble.
+ */
+ var iOrigWidth = $(n).width();
+ n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth );
+ }
+ else if ( oSettings.oScroll.sX !== "" )
+ {
+ /* When x-scrolling both ways, fix the table at it's current size, without adjusting */
+ n.style.width = _fnStringToCss( $(n).outerWidth() );
+ }
+ }
+
+
+ /**
+ * Get the widest node
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iCol column of interest
+ * @returns {node} widest table node
+ * @memberof DataTable#oApi
+ */
+ function _fnGetWidestNode( oSettings, iCol )
+ {
+ var iMaxIndex = _fnGetMaxLenString( oSettings, iCol );
+ if ( iMaxIndex < 0 )
+ {
+ return null;
+ }
+
+ if ( oSettings.aoData[iMaxIndex].nTr === null )
+ {
+ var n = document.createElement('td');
+ n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' );
+ return n;
+ }
+ return _fnGetTdNodes(oSettings, iMaxIndex)[iCol];
+ }
+
+
+ /**
+ * Get the maximum strlen for each data column
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iCol column of interest
+ * @returns {string} max string length for each column
+ * @memberof DataTable#oApi
+ */
+ function _fnGetMaxLenString( oSettings, iCol )
+ {
+ var iMax = -1;
+ var iMaxIndex = -1;
+
+ for ( var i=0 ; i/g, "" );
+ if ( s.length > iMax )
+ {
+ iMax = s.length;
+ iMaxIndex = i;
+ }
+ }
+
+ return iMaxIndex;
+ }
+
+
+ /**
+ * Append a CSS unit (only if required) to a string
+ * @param {array} aArray1 first array
+ * @param {array} aArray2 second array
+ * @returns {int} 0 if match, 1 if length is different, 2 if no match
+ * @memberof DataTable#oApi
+ */
+ function _fnStringToCss( s )
+ {
+ if ( s === null )
+ {
+ return "0px";
+ }
+
+ if ( typeof s == 'number' )
+ {
+ if ( s < 0 )
+ {
+ return "0px";
+ }
+ return s+"px";
+ }
+
+ /* Check if the last character is not 0-9 */
+ var c = s.charCodeAt( s.length-1 );
+ if (c < 0x30 || c > 0x39)
+ {
+ return s;
+ }
+ return s+"px";
+ }
+
+
+ /**
+ * Get the width of a scroll bar in this browser being used
+ * @returns {int} width in pixels
+ * @memberof DataTable#oApi
+ */
+ function _fnScrollBarWidth ()
+ {
+ var inner = document.createElement('p');
+ var style = inner.style;
+ style.width = "100%";
+ style.height = "200px";
+ style.padding = "0px";
+
+ var outer = document.createElement('div');
+ style = outer.style;
+ style.position = "absolute";
+ style.top = "0px";
+ style.left = "0px";
+ style.visibility = "hidden";
+ style.width = "200px";
+ style.height = "150px";
+ style.padding = "0px";
+ style.overflow = "hidden";
+ outer.appendChild(inner);
+
+ document.body.appendChild(outer);
+ var w1 = inner.offsetWidth;
+ outer.style.overflow = 'scroll';
+ var w2 = inner.offsetWidth;
+ if ( w1 == w2 )
+ {
+ w2 = outer.clientWidth;
+ }
+
+ document.body.removeChild(outer);
+ return (w1 - w2);
+ }
+
+ /**
+ * Change the order of the table
+ * @param {object} oSettings dataTables settings object
+ * @param {bool} bApplyClasses optional - should we apply classes or not
+ * @memberof DataTable#oApi
+ */
+ function _fnSort ( oSettings, bApplyClasses )
+ {
+ var
+ i, iLen, j, jLen, k, kLen,
+ sDataType, nTh,
+ aaSort = [],
+ aiOrig = [],
+ oSort = DataTable.ext.oSort,
+ aoData = oSettings.aoData,
+ aoColumns = oSettings.aoColumns,
+ oAria = oSettings.oLanguage.oAria;
+
+ /* No sorting required if server-side or no sorting array */
+ if ( !oSettings.oFeatures.bServerSide &&
+ (oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) )
+ {
+ aaSort = ( oSettings.aaSortingFixed !== null ) ?
+ oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
+ oSettings.aaSorting.slice();
+
+ /* If there is a sorting data type, and a function belonging to it, then we need to
+ * get the data from the developer's function and apply it for this column
+ */
+ for ( i=0 ; i/g, "" );
+ nTh = aoColumns[i].nTh;
+ nTh.removeAttribute('aria-sort');
+ nTh.removeAttribute('aria-label');
+
+ /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
+ if ( aoColumns[i].bSortable )
+ {
+ if ( aaSort.length > 0 && aaSort[0][0] == i )
+ {
+ nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" );
+
+ var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ?
+ aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0];
+ nTh.setAttribute('aria-label', sTitle+
+ (nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
+ }
+ else
+ {
+ nTh.setAttribute('aria-label', sTitle+
+ (aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
+ }
+ }
+ else
+ {
+ nTh.setAttribute('aria-label', sTitle);
+ }
+ }
+
+ /* Tell the draw function that we have sorted the data */
+ oSettings.bSorted = true;
+ $(oSettings.oInstance).trigger('sort', oSettings);
+
+ /* Copy the master data into the draw array and re-draw */
+ if ( oSettings.oFeatures.bFilter )
+ {
+ /* _fnFilter() will redraw the table for us */
+ _fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
+ }
+ else
+ {
+ oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
+ oSettings._iDisplayStart = 0; /* reset display back to page 0 */
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ }
+ }
+
+
+ /**
+ * Attach a sort handler (click) to a node
+ * @param {object} oSettings dataTables settings object
+ * @param {node} nNode node to attach the handler to
+ * @param {int} iDataIndex column sorting index
+ * @param {function} [fnCallback] callback function
+ * @memberof DataTable#oApi
+ */
+ function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback )
+ {
+ _fnBindAction( nNode, {}, function (e) {
+ /* If the column is not sortable - don't to anything */
+ if ( oSettings.aoColumns[iDataIndex].bSortable === false )
+ {
+ return;
+ }
+
+ /*
+ * This is a little bit odd I admit... I declare a temporary function inside the scope of
+ * _fnBuildHead and the click handler in order that the code presented here can be used
+ * twice - once for when bProcessing is enabled, and another time for when it is
+ * disabled, as we need to perform slightly different actions.
+ * Basically the issue here is that the Javascript engine in modern browsers don't
+ * appear to allow the rendering engine to update the display while it is still executing
+ * it's thread (well - it does but only after long intervals). This means that the
+ * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
+ * I force an execution break by using setTimeout - but this breaks the expected
+ * thread continuation for the end-developer's point of view (their code would execute
+ * too early), so we only do it when we absolutely have to.
+ */
+ var fnInnerSorting = function () {
+ var iColumn, iNextSort;
+
+ /* If the shift key is pressed then we are multiple column sorting */
+ if ( e.shiftKey )
+ {
+ /* Are we already doing some kind of sort on this column? */
+ var bFound = false;
+ for ( var i=0 ; i 0 && sCurrentClass.indexOf(sNewClass) == -1 )
+ {
+ /* We need to add a class */
+ nTds[i].className = sCurrentClass + " " + sNewClass;
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * Save the state of a table in a cookie such that the page can be reloaded
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnSaveState ( oSettings )
+ {
+ if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )
+ {
+ return;
+ }
+
+ /* Store the interesting variables */
+ var i, iLen, bInfinite=oSettings.oScroll.bInfinite;
+ var oState = {
+ "iCreate": new Date().getTime(),
+ "iStart": (bInfinite ? 0 : oSettings._iDisplayStart),
+ "iEnd": (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd),
+ "iLength": oSettings._iDisplayLength,
+ "aaSorting": $.extend( true, [], oSettings.aaSorting ),
+ "oSearch": $.extend( true, {}, oSettings.oPreviousSearch ),
+ "aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ),
+ "abVisCols": []
+ };
+
+ for ( i=0, iLen=oSettings.aoColumns.length ; i 4096 ) /* Magic 10 for padding */
+ {
+ for ( var i=0, iLen=aCookies.length ; i 4096 ) {
+ if ( aOldCookies.length === 0 ) {
+ // Deleted all DT cookies and still not enough space. Can't state save
+ return;
+ }
+
+ var old = aOldCookies.pop();
+ document.cookie = old.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+
+ aParts.join('/') + "/";
+ }
+ }
+
+ document.cookie = sFullCookie;
+ }
+
+
+ /**
+ * Read an old cookie to get a cookie with an old table state
+ * @param {string} sName name of the cookie to read
+ * @returns {string} contents of the cookie - or null if no cookie with that name found
+ * @memberof DataTable#oApi
+ */
+ function _fnReadCookie ( sName )
+ {
+ var
+ aParts = window.location.pathname.split('/'),
+ sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=',
+ sCookieContents = document.cookie.split(';');
+
+ for( var i=0 ; i=0 ; i-- )
+ {
+ aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) );
+ }
+
+ if ( sTrigger !== null )
+ {
+ $(oSettings.oInstance).trigger(sTrigger, aArgs);
+ }
+
+ return aRet;
+ }
+
+
+ /**
+ * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other
+ * library, then we use that as it is fast, safe and accurate. If the function isn't
+ * available then we need to built it ourselves - the inspiration for this function comes
+ * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is
+ * not perfect and absolutely should not be used as a replacement to json2.js - but it does
+ * do what we need, without requiring a dependency for DataTables.
+ * @param {object} o JSON object to be converted
+ * @returns {string} JSON string
+ * @memberof DataTable#oApi
+ */
+ var _fnJsonString = (window.JSON) ? JSON.stringify : function( o )
+ {
+ /* Not an object or array */
+ var sType = typeof o;
+ if (sType !== "object" || o === null)
+ {
+ // simple data type
+ if (sType === "string")
+ {
+ o = '"'+o+'"';
+ }
+ return o+"";
+ }
+
+ /* If object or array, need to recurse over it */
+ var
+ sProp, mValue,
+ json = [],
+ bArr = $.isArray(o);
+
+ for (sProp in o)
+ {
+ mValue = o[sProp];
+ sType = typeof mValue;
+
+ if (sType === "string")
+ {
+ mValue = '"'+mValue+'"';
+ }
+ else if (sType === "object" && mValue !== null)
+ {
+ mValue = _fnJsonString(mValue);
+ }
+
+ json.push((bArr ? "" : '"'+sProp+'":') + mValue);
+ }
+
+ return (bArr ? "[" : "{") + json + (bArr ? "]" : "}");
+ };
+
+
+ /**
+ * From some browsers (specifically IE6/7) we need special handling to work around browser
+ * bugs - this function is used to detect when these workarounds are needed.
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnBrowserDetect( oSettings )
+ {
+ /* IE6/7 will oversize a width 100% element inside a scrolling element, to include the
+ * width of the scrollbar, while other browsers ensure the inner element is contained
+ * without forcing scrolling
+ */
+ var n = $(
+ '
'+
+ '
'+
+ ''+
+ '
'+
+ '
')[0];
+
+ document.body.appendChild( n );
+ oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false;
+ document.body.removeChild( n );
+ }
+
+
+ /**
+ * Perform a jQuery selector action on the table's TR elements (from the tbody) and
+ * return the resulting jQuery object.
+ * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
+ * @param {object} [oOpts] Optional parameters for modifying the rows to be included
+ * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
+ * criterion ("applied") or all TR elements (i.e. no filter).
+ * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
+ * Can be either 'current', whereby the current sorting of the table is used, or
+ * 'original' whereby the original order the data was read into the table is used.
+ * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
+ * ("current") or not ("all"). If 'current' is given, then order is assumed to be
+ * 'current' and filter is 'applied', regardless of what they might be given as.
+ * @returns {object} jQuery object, filtered by the given selector.
+ * @dtopt API
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Highlight every second row
+ * oTable.$('tr:odd').css('backgroundColor', 'blue');
+ * } );
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Filter to rows with 'Webkit' in them, add a background colour and then
+ * // remove the filter, thus highlighting the 'Webkit' rows only.
+ * oTable.fnFilter('Webkit');
+ * oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue');
+ * oTable.fnFilter('');
+ * } );
+ */
+ this.$ = function ( sSelector, oOpts )
+ {
+ var i, iLen, a = [], tr;
+ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
+ var aoData = oSettings.aoData;
+ var aiDisplay = oSettings.aiDisplay;
+ var aiDisplayMaster = oSettings.aiDisplayMaster;
+
+ if ( !oOpts )
+ {
+ oOpts = {};
+ }
+
+ oOpts = $.extend( {}, {
+ "filter": "none", // applied
+ "order": "current", // "original"
+ "page": "all" // current
+ }, oOpts );
+
+ // Current page implies that order=current and fitler=applied, since it is fairly
+ // senseless otherwise
+ if ( oOpts.page == 'current' )
+ {
+ for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i
+ *
1D array of data - add a single row with the data provided
+ *
2D array of arrays - add multiple rows in a single call
+ *
object - data object when using mData
+ *
array of objects - multiple data objects when using mData
+ *
+ * @param {bool} [bRedraw=true] redraw the table or not
+ * @returns {array} An array of integers, representing the list of indexes in
+ * aoData ({@link DataTable.models.oSettings}) that have been added to
+ * the table.
+ * @dtopt API
+ *
+ * @example
+ * // Global var for counter
+ * var giCount = 2;
+ *
+ * $(document).ready(function() {
+ * $('#example').dataTable();
+ * } );
+ *
+ * function fnClickAddRow() {
+ * $('#example').dataTable().fnAddData( [
+ * giCount+".1",
+ * giCount+".2",
+ * giCount+".3",
+ * giCount+".4" ]
+ * );
+ *
+ * giCount++;
+ * }
+ */
+ this.fnAddData = function( mData, bRedraw )
+ {
+ if ( mData.length === 0 )
+ {
+ return [];
+ }
+
+ var aiReturn = [];
+ var iTest;
+
+ /* Find settings from table node */
+ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
+
+ /* Check if we want to add multiple rows or not */
+ if ( typeof mData[0] === "object" && mData[0] !== null )
+ {
+ for ( var i=0 ; i= oSettings.fnRecordsDisplay() )
+ {
+ oSettings._iDisplayStart -= oSettings._iDisplayLength;
+ if ( oSettings._iDisplayStart < 0 )
+ {
+ oSettings._iDisplayStart = 0;
+ }
+ }
+
+ if ( bRedraw === undefined || bRedraw )
+ {
+ _fnCalculateEnd( oSettings );
+ _fnDraw( oSettings );
+ }
+
+ return oData;
+ };
+
+
+ /**
+ * Restore the table to it's original state in the DOM by removing all of DataTables
+ * enhancements, alterations to the DOM structure of the table and event listeners.
+ * @param {boolean} [bRemove=false] Completely remove the table from the DOM
+ * @dtopt API
+ *
+ * @example
+ * $(document).ready(function() {
+ * // This example is fairly pointless in reality, but shows how fnDestroy can be used
+ * var oTable = $('#example').dataTable();
+ * oTable.fnDestroy();
+ * } );
+ */
+ this.fnDestroy = function ( bRemove )
+ {
+ var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
+ var nOrig = oSettings.nTableWrapper.parentNode;
+ var nBody = oSettings.nTBody;
+ var i, iLen;
+
+ bRemove = (bRemove===undefined) ? false : bRemove;
+
+ /* Flag to note that the table is currently being destroyed - no action should be taken */
+ oSettings.bDestroying = true;
+
+ /* Fire off the destroy callbacks for plug-ins etc */
+ _fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] );
+
+ /* If the table is not being removed, restore the hidden columns */
+ if ( !bRemove )
+ {
+ for ( i=0, iLen=oSettings.aoColumns.length ; itr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
+
+ /* When scrolling we had to break the table up - restore it */
+ if ( oSettings.nTable != oSettings.nTHead.parentNode )
+ {
+ $(oSettings.nTable).children('thead').remove();
+ oSettings.nTable.appendChild( oSettings.nTHead );
+ }
+
+ if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode )
+ {
+ $(oSettings.nTable).children('tfoot').remove();
+ oSettings.nTable.appendChild( oSettings.nTFoot );
+ }
+
+ /* Remove the DataTables generated nodes, events and classes */
+ oSettings.nTable.parentNode.removeChild( oSettings.nTable );
+ $(oSettings.nTableWrapper).remove();
+
+ oSettings.aaSorting = [];
+ oSettings.aaSortingFixed = [];
+ _fnSortingClasses( oSettings );
+
+ $(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') );
+
+ $('th, td', oSettings.nTHead).removeClass( [
+ oSettings.oClasses.sSortable,
+ oSettings.oClasses.sSortableAsc,
+ oSettings.oClasses.sSortableDesc,
+ oSettings.oClasses.sSortableNone ].join(' ')
+ );
+ if ( oSettings.bJUI )
+ {
+ $('th span.'+oSettings.oClasses.sSortIcon
+ + ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();
+
+ $('th, td', oSettings.nTHead).each( function () {
+ var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this);
+ var kids = jqWrapper.contents();
+ $(this).append( kids );
+ jqWrapper.remove();
+ } );
+ }
+
+ /* Add the TR elements back into the table in their original order */
+ if ( !bRemove && oSettings.nTableReinsertBefore )
+ {
+ nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore );
+ }
+ else if ( !bRemove )
+ {
+ nOrig.appendChild( oSettings.nTable );
+ }
+
+ for ( i=0, iLen=oSettings.aoData.length ; i= _fnVisbleColumns( oSettings ));
+
+ /* Which coloumn should we be inserting before? */
+ if ( !bAppend )
+ {
+ for ( i=iCol ; i= oSettings.aoColumns.length )
+ {
+ oSettings.aaSorting[i][0] = 0;
+ }
+ var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
+
+ /* Add a default sorting index */
+ if ( oSettings.aaSorting[i][2] === undefined )
+ {
+ oSettings.aaSorting[i][2] = 0;
+ }
+
+ /* If aaSorting is not defined, then we use the first indicator in asSorting */
+ if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined )
+ {
+ oSettings.aaSorting[i][1] = oColumn.asSorting[0];
+ }
+
+ /* Set the current sorting index based on aoColumns.asSorting */
+ for ( j=0, jLen=oColumn.asSorting.length ; j 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
+ {
+ // If we are a scrolling table, and no footer has been given, then we need to create
+ // a tfoot element for the caption element to be appended to
+ tfoot = [ document.createElement( 'tfoot' ) ];
+ this.appendChild( tfoot[0] );
+ }
+
+ if ( tfoot.length > 0 )
+ {
+ oSettings.nTFoot = tfoot[0];
+ _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
+ }
+
+ /* Check if there is data passing into the constructor */
+ if ( bUsePassedData )
+ {
+ for ( i=0 ; i= parseInt(sThat, 10);
+ };
+
+
+ /**
+ * Check if a TABLE node is a DataTable table already or not.
+ * @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
+ * node types can be passed in, but will always return false).
+ * @returns {boolean} true the table given is a DataTable, or false otherwise
+ * @static
+ * @dtopt API-Static
+ *
+ * @example
+ * var ex = document.getElementById('example');
+ * if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
+ * $(ex).dataTable();
+ * }
+ */
+ DataTable.fnIsDataTable = function ( nTable )
+ {
+ var o = DataTable.settings;
+
+ for ( var i=0 ; i 0 ) {
+ * $(table).dataTable().fnAdjustColumnSizing();
+ * }
+ */
+ DataTable.fnTables = function ( bVisible )
+ {
+ var out = [];
+
+ jQuery.each( DataTable.settings, function (i, o) {
+ if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) )
+ {
+ out.push( o.nTable );
+ }
+ } );
+
+ return out;
+ };
+
+
+ /**
+ * Version string for plug-ins to check compatibility. Allowed format is
+ * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
+ * e are optional
+ * @member
+ * @type string
+ * @default Version number
+ */
+ DataTable.version = "1.9.4";
+
+ /**
+ * Private data store, containing all of the settings objects that are created for the
+ * tables on a given page.
+ *
+ * Note that the DataTable.settings object is aliased to jQuery.fn.dataTableExt
+ * through which it may be accessed and manipulated, or jQuery.fn.dataTable.settings.
+ * @member
+ * @type array
+ * @default []
+ * @private
+ */
+ DataTable.settings = [];
+
+ /**
+ * Object models container, for the various models that DataTables has available
+ * to it. These models define the objects that are used to hold the active state
+ * and configuration of the table.
+ * @namespace
+ */
+ DataTable.models = {};
+
+
+ /**
+ * DataTables extension options and plug-ins. This namespace acts as a collection "area"
+ * for plug-ins that can be used to extend the default DataTables behaviour - indeed many
+ * of the build in methods use this method to provide their own capabilities (sorting methods
+ * for example).
+ *
+ * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed
+ * and modified by plug-ins.
+ * @namespace
+ */
+ DataTable.models.ext = {
+ /**
+ * Plug-in filtering functions - this method of filtering is complimentary to the default
+ * type based filtering, and a lot more comprehensive as it allows you complete control
+ * over the filtering logic. Each element in this array is a function (parameters
+ * described below) that is called for every row in the table, and your logic decides if
+ * it should be included in the filtered data set or not.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
{array|object} Data for the row to be processed (same as the original format
+ * that was passed in as the data source, or an array from a DOM data source
+ *
{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can
+ * be useful to retrieve the TR element if you need DOM interaction.
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{boolean} Include the row in the filtered result set (true) or not (false)
+ *
+ *
+ *
+ * @type array
+ * @default []
+ *
+ * @example
+ * // The following example shows custom filtering being applied to the fourth column (i.e.
+ * // the aData[3] index) based on two input values from the end-user, matching the data in
+ * // a certain range.
+ * $.fn.dataTableExt.afnFiltering.push(
+ * function( oSettings, aData, iDataIndex ) {
+ * var iMin = document.getElementById('min').value * 1;
+ * var iMax = document.getElementById('max').value * 1;
+ * var iVersion = aData[3] == "-" ? 0 : aData[3]*1;
+ * if ( iMin == "" && iMax == "" ) {
+ * return true;
+ * }
+ * else if ( iMin == "" && iVersion < iMax ) {
+ * return true;
+ * }
+ * else if ( iMin < iVersion && "" == iMax ) {
+ * return true;
+ * }
+ * else if ( iMin < iVersion && iVersion < iMax ) {
+ * return true;
+ * }
+ * return false;
+ * }
+ * );
+ */
+ "afnFiltering": [],
+
+
+ /**
+ * Plug-in sorting functions - this method of sorting is complimentary to the default type
+ * based sorting that DataTables does automatically, allowing much greater control over the
+ * the data that is being used to sort a column. This is useful if you want to do sorting
+ * based on live data (for example the contents of an 'input' element) rather than just the
+ * static string that DataTables knows of. The way these plug-ins work is that you create
+ * an array of the values you wish to be sorted for the column in question and then return
+ * that array. Which pre-sorting function is run here depends on the sSortDataType parameter
+ * that is used for the column (if any). This is the corollary of ofnSearch for sort
+ * data.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
{int} Target column index
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{array} Data for the column to be sorted upon
+ *
+ *
+ *
+ *
+ * Note that as of v1.9, it is typically preferable to use mData to prepare data for
+ * the different uses that DataTables can put the data to. Specifically mData when
+ * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
+ * prepare the data as required for the different types. As such, this method is deprecated.
+ * @type array
+ * @default []
+ * @deprecated
+ *
+ * @example
+ * // Updating the cached sorting information with user entered values in HTML input elements
+ * jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
+ * {
+ * var aData = [];
+ * $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
+ * aData.push( this.value );
+ * } );
+ * return aData;
+ * }
+ */
+ "afnSortData": [],
+
+
+ /**
+ * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are
+ * available to DataTables. These feature plug-ins are accessible through the sDom initialisation
+ * option. As such, each feature plug-in must describe a function that is used to initialise
+ * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name
+ * of the feature (sFeature). Thus the objects attached to this method must provide:
+ *
+ *
{function} fnInit Initialisation of the plug-in
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{node|null} The element which contains your feature. Note that the return
+ * may also be void if your plug-in does not require to inject any DOM elements
+ * into DataTables control (sDom) - for example this might be useful when
+ * developing a plug-in which allows table control via keyboard entry.
+ *
+ *
+ *
+ *
+ *
{character} cFeature Character that will be matched in sDom - case sensitive
+ *
{string} sFeature Feature name
+ *
+ * @type array
+ * @default []
+ *
+ * @example
+ * // How TableTools initialises itself.
+ * $.fn.dataTableExt.aoFeatures.push( {
+ * "fnInit": function( oSettings ) {
+ * return new TableTools( { "oDTSettings": oSettings } );
+ * },
+ * "cFeature": "T",
+ * "sFeature": "TableTools"
+ * } );
+ */
+ "aoFeatures": [],
+
+
+ /**
+ * Type detection plug-in functions - DataTables utilises types to define how sorting and
+ * filtering behave, and types can be either be defined by the developer (sType for the
+ * column) or they can be automatically detected by the methods in this array. The functions
+ * defined in the array are quite simple, taking a single parameter (the data to analyse)
+ * and returning the type if it is a known type, or null otherwise.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{*} Data from the column cell to be analysed
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{string|null} Data type detected, or null if unknown (and thus pass it
+ * on to the other type detection functions.
+ *
+ *
+ *
+ * @type array
+ * @default []
+ *
+ * @example
+ * // Currency type detection plug-in:
+ * jQuery.fn.dataTableExt.aTypes.push(
+ * function ( sData ) {
+ * var sValidChars = "0123456789.-";
+ * var Char;
+ *
+ * // Check the numeric part
+ * for ( i=1 ; iafnSortData for filtering data.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{*} Data from the column cell to be prepared for filtering
+ *
+ *
+ *
+ * Function return:
+ *
+ *
{string|null} Formatted string that will be used for the filtering.
+ *
+ *
+ *
+ *
+ * Note that as of v1.9, it is typically preferable to use mData to prepare data for
+ * the different uses that DataTables can put the data to. Specifically mData when
+ * used as a function will give you a 'type' (sorting, filtering etc) that you can use to
+ * prepare the data as required for the different types. As such, this method is deprecated.
+ * @type object
+ * @default {}
+ * @deprecated
+ *
+ * @example
+ * $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {
+ * return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
+ * }
+ */
+ "ofnSearch": {},
+
+
+ /**
+ * Container for all private functions in DataTables so they can be exposed externally
+ * @type object
+ * @default {}
+ */
+ "oApi": {},
+
+
+ /**
+ * Storage for the various classes that DataTables uses
+ * @type object
+ * @default {}
+ */
+ "oStdClasses": {},
+
+
+ /**
+ * Storage for the various classes that DataTables uses - jQuery UI suitable
+ * @type object
+ * @default {}
+ */
+ "oJUIClasses": {},
+
+
+ /**
+ * Pagination plug-in methods - The style and controls of the pagination can significantly
+ * impact on how the end user interacts with the data in your table, and DataTables allows
+ * the addition of pagination controls by extending this object, which can then be enabled
+ * through the sPaginationType initialisation parameter. Each pagination type that
+ * is added is an object (the property name of which is what sPaginationType refers
+ * to) that has two properties, both methods that are used by DataTables to update the
+ * control's state.
+ *
+ *
+ * fnInit - Initialisation of the paging controls. Called only during initialisation
+ * of the table. It is expected that this function will add the required DOM elements
+ * to the page for the paging controls to work. The element pointer
+ * 'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging
+ * controls (note that this is a 2D array to allow for multiple instances of each
+ * DataTables DOM element). It is suggested that you add the controls to this element
+ * as children
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
{node} Container into which the pagination controls must be inserted
+ *
{function} Draw callback function - whenever the controls cause a page
+ * change, this method must be called to redraw the table.
+ *
+ *
+ *
+ * Function return:
+ *
+ *
No return required
+ *
+ *
+ *
+ *
+ *
+ * fnInit - This function is called whenever the paging status of the table changes and is
+ * typically used to update classes and/or text of the paging controls to reflex the new
+ * status.
+ *
+ *
+ * Function input parameters:
+ *
+ *
{object} DataTables settings object: see {@link DataTable.models.oSettings}.
+ *
{function} Draw callback function - in case you need to redraw the table again
+ * or attach new event listeners
{int} Sorting match: <0 if first parameter should be sorted lower than
+ * the second parameter, ===0 if the two parameters are equal and >0 if
+ * the first parameter should be sorted height than the second parameter.
+ *
+ *
+ *
+ * @type object
+ * @default {}
+ *
+ * @example
+ * // Case-sensitive string sorting, with no pre-formatting method
+ * $.extend( $.fn.dataTableExt.oSort, {
+ * "string-case-asc": function(x,y) {
+ * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ * },
+ * "string-case-desc": function(x,y) {
+ * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ * }
+ * } );
+ *
+ * @example
+ * // Case-insensitive string sorting, with pre-formatting
+ * $.extend( $.fn.dataTableExt.oSort, {
+ * "string-pre": function(x) {
+ * return x.toLowerCase();
+ * },
+ * "string-asc": function(x,y) {
+ * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ * },
+ * "string-desc": function(x,y) {
+ * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ * }
+ * } );
+ */
+ "oSort": {},
+
+
+ /**
+ * Version string for plug-ins to check compatibility. Allowed format is
+ * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
+ * e are optional
+ * @type string
+ * @default Version number
+ */
+ "sVersion": DataTable.version,
+
+
+ /**
+ * How should DataTables report an error. Can take the value 'alert' or 'throw'
+ * @type string
+ * @default alert
+ */
+ "sErrMode": "alert",
+
+
+ /**
+ * Store information for DataTables to access globally about other instances
+ * @namespace
+ * @private
+ */
+ "_oExternConfig": {
+ /* int:iNextUnique - next unique number for an instance */
+ "iNextUnique": 0
+ }
+ };
+
+
+
+
+ /**
+ * Template object for the way in which DataTables holds information about
+ * search information for the global filter and individual column filters.
+ * @namespace
+ */
+ DataTable.models.oSearch = {
+ /**
+ * Flag to indicate if the filtering should be case insensitive or not
+ * @type boolean
+ * @default true
+ */
+ "bCaseInsensitive": true,
+
+ /**
+ * Applied search term
+ * @type string
+ * @default Empty string
+ */
+ "sSearch": "",
+
+ /**
+ * Flag to indicate if the search term should be interpreted as a
+ * regular expression (true) or not (false) and therefore and special
+ * regex characters escaped.
+ * @type boolean
+ * @default false
+ */
+ "bRegex": false,
+
+ /**
+ * Flag to indicate if DataTables is to use its smart filtering or not.
+ * @type boolean
+ * @default true
+ */
+ "bSmart": true
+ };
+
+
+
+
+ /**
+ * Template object for the way in which DataTables holds information about
+ * each individual row. This is the object format used for the settings
+ * aoData array.
+ * @namespace
+ */
+ DataTable.models.oRow = {
+ /**
+ * TR element for the row
+ * @type node
+ * @default null
+ */
+ "nTr": null,
+
+ /**
+ * Data object from the original data source for the row. This is either
+ * an array if using the traditional form of DataTables, or an object if
+ * using mData options. The exact type will depend on the passed in
+ * data from the data source, or will be an array if using DOM a data
+ * source.
+ * @type array|object
+ * @default []
+ */
+ "_aData": [],
+
+ /**
+ * Sorting data cache - this array is ostensibly the same length as the
+ * number of columns (although each index is generated only as it is
+ * needed), and holds the data that is used for sorting each column in the
+ * row. We do this cache generation at the start of the sort in order that
+ * the formatting of the sort data need be done only once for each cell
+ * per sort. This array should not be read from or written to by anything
+ * other than the master sorting methods.
+ * @type array
+ * @default []
+ * @private
+ */
+ "_aSortData": [],
+
+ /**
+ * Array of TD elements that are cached for hidden rows, so they can be
+ * reinserted into the table if a column is made visible again (or to act
+ * as a store if a column is made hidden). Only hidden columns have a
+ * reference in the array. For non-hidden columns the value is either
+ * undefined or null.
+ * @type array nodes
+ * @default []
+ * @private
+ */
+ "_anHidden": [],
+
+ /**
+ * Cache of the class name that DataTables has applied to the row, so we
+ * can quickly look at this variable rather than needing to do a DOM check
+ * on className for the nTr property.
+ * @type string
+ * @default Empty string
+ * @private
+ */
+ "_sRowStripe": ""
+ };
+
+
+
+ /**
+ * Template object for the column information object in DataTables. This object
+ * is held in the settings aoColumns array and contains all the information that
+ * DataTables needs about each individual column.
+ *
+ * Note that this object is related to {@link DataTable.defaults.columns}
+ * but this one is the internal data store for DataTables's cache of columns.
+ * It should NOT be manipulated outside of DataTables. Any configuration should
+ * be done through the initialisation options.
+ * @namespace
+ */
+ DataTable.models.oColumn = {
+ /**
+ * A list of the columns that sorting should occur on when this column
+ * is sorted. That this property is an array allows multi-column sorting
+ * to be defined for a column (for example first name / last name columns
+ * would benefit from this). The values are integers pointing to the
+ * columns to be sorted on (typically it will be a single integer pointing
+ * at itself, but that doesn't need to be the case).
+ * @type array
+ */
+ "aDataSort": null,
+
+ /**
+ * Define the sorting directions that are applied to the column, in sequence
+ * as the column is repeatedly sorted upon - i.e. the first value is used
+ * as the sorting direction when the column if first sorted (clicked on).
+ * Sort it again (click again) and it will move on to the next index.
+ * Repeat until loop.
+ * @type array
+ */
+ "asSorting": null,
+
+ /**
+ * Flag to indicate if the column is searchable, and thus should be included
+ * in the filtering or not.
+ * @type boolean
+ */
+ "bSearchable": null,
+
+ /**
+ * Flag to indicate if the column is sortable or not.
+ * @type boolean
+ */
+ "bSortable": null,
+
+ /**
+ * Deprecated When using fnRender, you have two options for what
+ * to do with the data, and this property serves as the switch. Firstly, you
+ * can have the sorting and filtering use the rendered value (true - default),
+ * or you can have the sorting and filtering us the original value (false).
+ *
+ * Please note that this option has now been deprecated and will be removed
+ * in the next version of DataTables. Please use mRender / mData rather than
+ * fnRender.
+ * @type boolean
+ * @deprecated
+ */
+ "bUseRendered": null,
+
+ /**
+ * Flag to indicate if the column is currently visible in the table or not
+ * @type boolean
+ */
+ "bVisible": null,
+
+ /**
+ * Flag to indicate to the type detection method if the automatic type
+ * detection should be used, or if a column type (sType) has been specified
+ * @type boolean
+ * @default true
+ * @private
+ */
+ "_bAutoType": true,
+
+ /**
+ * Developer definable function that is called whenever a cell is created (Ajax source,
+ * etc) or processed for input (DOM source). This can be used as a compliment to mRender
+ * allowing you to modify the DOM element (add background colour for example) when the
+ * element is available.
+ * @type function
+ * @param {element} nTd The TD node that has been created
+ * @param {*} sData The Data for the cell
+ * @param {array|object} oData The data for the whole row
+ * @param {int} iRow The row index for the aoData data store
+ * @default null
+ */
+ "fnCreatedCell": null,
+
+ /**
+ * Function to get data from a cell in a column. You should never
+ * access data directly through _aData internally in DataTables - always use
+ * the method attached to this property. It allows mData to function as
+ * required. This function is automatically assigned by the column
+ * initialisation method
+ * @type function
+ * @param {array|object} oData The data array/object for the array
+ * (i.e. aoData[]._aData)
+ * @param {string} sSpecific The specific data type you want to get -
+ * 'display', 'type' 'filter' 'sort'
+ * @returns {*} The data for the cell from the given row's data
+ * @default null
+ */
+ "fnGetData": null,
+
+ /**
+ * Deprecated Custom display function that will be called for the
+ * display of each cell in this column.
+ *
+ * Please note that this option has now been deprecated and will be removed
+ * in the next version of DataTables. Please use mRender / mData rather than
+ * fnRender.
+ * @type function
+ * @param {object} o Object with the following parameters:
+ * @param {int} o.iDataRow The row in aoData
+ * @param {int} o.iDataColumn The column in question
+ * @param {array} o.aData The data for the row in question
+ * @param {object} o.oSettings The settings object for this DataTables instance
+ * @returns {string} The string you which to use in the display
+ * @default null
+ * @deprecated
+ */
+ "fnRender": null,
+
+ /**
+ * Function to set data for a cell in the column. You should never
+ * set the data directly to _aData internally in DataTables - always use
+ * this method. It allows mData to function as required. This function
+ * is automatically assigned by the column initialisation method
+ * @type function
+ * @param {array|object} oData The data array/object for the array
+ * (i.e. aoData[]._aData)
+ * @param {*} sValue Value to set
+ * @default null
+ */
+ "fnSetData": null,
+
+ /**
+ * Property to read the value for the cells in the column from the data
+ * source array / object. If null, then the default content is used, if a
+ * function is given then the return from the function is used.
+ * @type function|int|string|null
+ * @default null
+ */
+ "mData": null,
+
+ /**
+ * Partner property to mData which is used (only when defined) to get
+ * the data - i.e. it is basically the same as mData, but without the
+ * 'set' option, and also the data fed to it is the result from mData.
+ * This is the rendering method to match the data method of mData.
+ * @type function|int|string|null
+ * @default null
+ */
+ "mRender": null,
+
+ /**
+ * Unique header TH/TD element for this column - this is what the sorting
+ * listener is attached to (if sorting is enabled.)
+ * @type node
+ * @default null
+ */
+ "nTh": null,
+
+ /**
+ * Unique footer TH/TD element for this column (if there is one). Not used
+ * in DataTables as such, but can be used for plug-ins to reference the
+ * footer for each column.
+ * @type node
+ * @default null
+ */
+ "nTf": null,
+
+ /**
+ * The class to apply to all TD elements in the table's TBODY for the column
+ * @type string
+ * @default null
+ */
+ "sClass": null,
+
+ /**
+ * When DataTables calculates the column widths to assign to each column,
+ * it finds the longest string in each column and then constructs a
+ * temporary table and reads the widths from that. The problem with this
+ * is that "mmm" is much wider then "iiii", but the latter is a longer
+ * string - thus the calculation can go wrong (doing it properly and putting
+ * it into an DOM object and measuring that is horribly(!) slow). Thus as
+ * a "work around" we provide this option. It will append its value to the
+ * text that is found to be the longest string for the column - i.e. padding.
+ * @type string
+ */
+ "sContentPadding": null,
+
+ /**
+ * Allows a default value to be given for a column's data, and will be used
+ * whenever a null data source is encountered (this can be because mData
+ * is set to null, or because the data source itself is null).
+ * @type string
+ * @default null
+ */
+ "sDefaultContent": null,
+
+ /**
+ * Name for the column, allowing reference to the column by name as well as
+ * by index (needs a lookup to work by name).
+ * @type string
+ */
+ "sName": null,
+
+ /**
+ * Custom sorting data type - defines which of the available plug-ins in
+ * afnSortData the custom sorting will use - if any is defined.
+ * @type string
+ * @default std
+ */
+ "sSortDataType": 'std',
+
+ /**
+ * Class to be applied to the header element when sorting on this column
+ * @type string
+ * @default null
+ */
+ "sSortingClass": null,
+
+ /**
+ * Class to be applied to the header element when sorting on this column -
+ * when jQuery UI theming is used.
+ * @type string
+ * @default null
+ */
+ "sSortingClassJUI": null,
+
+ /**
+ * Title of the column - what is seen in the TH element (nTh).
+ * @type string
+ */
+ "sTitle": null,
+
+ /**
+ * Column sorting and filtering type
+ * @type string
+ * @default null
+ */
+ "sType": null,
+
+ /**
+ * Width of the column
+ * @type string
+ * @default null
+ */
+ "sWidth": null,
+
+ /**
+ * Width of the column when it was first "encountered"
+ * @type string
+ * @default null
+ */
+ "sWidthOrig": null
+ };
+
+
+
+ /**
+ * Initialisation options that can be given to DataTables at initialisation
+ * time.
+ * @namespace
+ */
+ DataTable.defaults = {
+ /**
+ * An array of data to use for the table, passed in at initialisation which
+ * will be used in preference to any data which is already in the DOM. This is
+ * particularly useful for constructing tables purely in Javascript, for
+ * example with a custom Ajax call.
+ * @type array
+ * @default null
+ * @dtopt Option
+ *
+ * @example
+ * // Using a 2D array data source
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "aaData": [
+ * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
+ * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
+ * ],
+ * "aoColumns": [
+ * { "sTitle": "Engine" },
+ * { "sTitle": "Browser" },
+ * { "sTitle": "Platform" },
+ * { "sTitle": "Version" },
+ * { "sTitle": "Grade" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using an array of objects as a data source (mData)
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "aaData": [
+ * {
+ * "engine": "Trident",
+ * "browser": "Internet Explorer 4.0",
+ * "platform": "Win 95+",
+ * "version": 4,
+ * "grade": "X"
+ * },
+ * {
+ * "engine": "Trident",
+ * "browser": "Internet Explorer 5.0",
+ * "platform": "Win 95+",
+ * "version": 5,
+ * "grade": "C"
+ * }
+ * ],
+ * "aoColumns": [
+ * { "sTitle": "Engine", "mData": "engine" },
+ * { "sTitle": "Browser", "mData": "browser" },
+ * { "sTitle": "Platform", "mData": "platform" },
+ * { "sTitle": "Version", "mData": "version" },
+ * { "sTitle": "Grade", "mData": "grade" }
+ * ]
+ * } );
+ * } );
+ */
+ "aaData": null,
+
+
+ /**
+ * If sorting is enabled, then DataTables will perform a first pass sort on
+ * initialisation. You can define which column(s) the sort is performed upon,
+ * and the sorting direction, with this variable. The aaSorting array should
+ * contain an array for each column to be sorted initially containing the
+ * column's index and a direction string ('asc' or 'desc').
+ * @type array
+ * @default [[0,'asc']]
+ * @dtopt Option
+ *
+ * @example
+ * // Sort by 3rd column first, and then 4th column
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aaSorting": [[2,'asc'], [3,'desc']]
+ * } );
+ * } );
+ *
+ * // No initial sorting
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aaSorting": []
+ * } );
+ * } );
+ */
+ "aaSorting": [[0,'asc']],
+
+
+ /**
+ * This parameter is basically identical to the aaSorting parameter, but
+ * cannot be overridden by user interaction with the table. What this means
+ * is that you could have a column (visible or hidden) which the sorting will
+ * always be forced on first - any sorting after that (from the user) will
+ * then be performed as required. This can be useful for grouping rows
+ * together.
+ * @type array
+ * @default null
+ * @dtopt Option
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aaSortingFixed": [[0,'asc']]
+ * } );
+ * } )
+ */
+ "aaSortingFixed": null,
+
+
+ /**
+ * This parameter allows you to readily specify the entries in the length drop
+ * down menu that DataTables shows when pagination is enabled. It can be
+ * either a 1D array of options which will be used for both the displayed
+ * option and the value, or a 2D array which will use the array in the first
+ * position as the value, and the array in the second position as the
+ * displayed options (useful for language strings such as 'All').
+ * @type array
+ * @default [ 10, 25, 50, 100 ]
+ * @dtopt Option
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
+ * } );
+ * } );
+ *
+ * @example
+ * // Setting the default display length as well as length menu
+ * // This is likely to be wanted if you remove the '10' option which
+ * // is the iDisplayLength default.
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "iDisplayLength": 25,
+ * "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
+ * } );
+ * } );
+ */
+ "aLengthMenu": [ 10, 25, 50, 100 ],
+
+
+ /**
+ * The aoColumns option in the initialisation parameter allows you to define
+ * details about the way individual columns behave. For a full list of
+ * column options that can be set, please see
+ * {@link DataTable.defaults.columns}. Note that if you use aoColumns to
+ * define your columns, you must have an entry in the array for every single
+ * column that you have in your table (these can be null if you don't which
+ * to specify any options).
+ * @member
+ */
+ "aoColumns": null,
+
+ /**
+ * Very similar to aoColumns, aoColumnDefs allows you to target a specific
+ * column, multiple columns, or all columns, using the aTargets property of
+ * each object in the array. This allows great flexibility when creating
+ * tables, as the aoColumnDefs arrays can be of any length, targeting the
+ * columns you specifically want. aoColumnDefs may use any of the column
+ * options available: {@link DataTable.defaults.columns}, but it _must_
+ * have aTargets defined in each object in the array. Values in the aTargets
+ * array may be:
+ *
+ *
a string - class name will be matched on the TH for the column
+ *
0 or a positive integer - column index counting from the left
+ *
a negative integer - column index counting from the right
+ *
the string "_all" - all columns (i.e. assign a default)
+ *
+ * @member
+ */
+ "aoColumnDefs": null,
+
+
+ /**
+ * Basically the same as oSearch, this parameter defines the individual column
+ * filtering state at initialisation time. The array must be of the same size
+ * as the number of columns, and each element be an object with the parameters
+ * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also
+ * accepted and the default will be used.
+ * @type array
+ * @default []
+ * @dtopt Option
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoSearchCols": [
+ * null,
+ * { "sSearch": "My filter" },
+ * null,
+ * { "sSearch": "^[0-9]", "bEscapeRegex": false }
+ * ]
+ * } );
+ * } )
+ */
+ "aoSearchCols": [],
+
+
+ /**
+ * An array of CSS classes that should be applied to displayed rows. This
+ * array may be of any length, and DataTables will apply each class
+ * sequentially, looping when required.
+ * @type array
+ * @default null Will take the values determined by the oClasses.sStripe*
+ * options
+ * @dtopt Option
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ]
+ * } );
+ * } )
+ */
+ "asStripeClasses": null,
+
+
+ /**
+ * Enable or disable automatic column width calculation. This can be disabled
+ * as an optimisation (it takes some time to calculate the widths) if the
+ * tables widths are passed in using aoColumns.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bAutoWidth": false
+ * } );
+ * } );
+ */
+ "bAutoWidth": true,
+
+
+ /**
+ * Deferred rendering can provide DataTables with a huge speed boost when you
+ * are using an Ajax or JS data source for the table. This option, when set to
+ * true, will cause DataTables to defer the creation of the table elements for
+ * each row until they are needed for a draw - saving a significant amount of
+ * time.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/arrays.txt",
+ * "bDeferRender": true
+ * } );
+ * } );
+ */
+ "bDeferRender": false,
+
+
+ /**
+ * Replace a DataTable which matches the given selector and replace it with
+ * one which has the properties of the new initialisation object passed. If no
+ * table matches the selector, then the new DataTable will be constructed as
+ * per normal.
+ * @type boolean
+ * @default false
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sScrollY": "200px",
+ * "bPaginate": false
+ * } );
+ *
+ * // Some time later....
+ * $('#example').dataTable( {
+ * "bFilter": false,
+ * "bDestroy": true
+ * } );
+ * } );
+ */
+ "bDestroy": false,
+
+
+ /**
+ * Enable or disable filtering of data. Filtering in DataTables is "smart" in
+ * that it allows the end user to input multiple words (space separated) and
+ * will match a row containing those words, even if not in the order that was
+ * specified (this allow matching across multiple columns). Note that if you
+ * wish to use filtering in DataTables this must remain 'true' - to remove the
+ * default filtering input box and retain filtering abilities, please use
+ * {@link DataTable.defaults.sDom}.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bFilter": false
+ * } );
+ * } );
+ */
+ "bFilter": true,
+
+
+ /**
+ * Enable or disable the table information display. This shows information
+ * about the data that is currently visible on the page, including information
+ * about filtered data if that action is being performed.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bInfo": false
+ * } );
+ * } );
+ */
+ "bInfo": true,
+
+
+ /**
+ * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
+ * slightly different and additional mark-up from what DataTables has
+ * traditionally used).
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bJQueryUI": true
+ * } );
+ * } );
+ */
+ "bJQueryUI": false,
+
+
+ /**
+ * Allows the end user to select the size of a formatted page from a select
+ * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate).
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bLengthChange": false
+ * } );
+ * } );
+ */
+ "bLengthChange": true,
+
+
+ /**
+ * Enable or disable pagination.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bPaginate": false
+ * } );
+ * } );
+ */
+ "bPaginate": true,
+
+
+ /**
+ * Enable or disable the display of a 'processing' indicator when the table is
+ * being processed (e.g. a sort). This is particularly useful for tables with
+ * large amounts of data where it can take a noticeable amount of time to sort
+ * the entries.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bProcessing": true
+ * } );
+ * } );
+ */
+ "bProcessing": false,
+
+
+ /**
+ * Retrieve the DataTables object for the given selector. Note that if the
+ * table has already been initialised, this parameter will cause DataTables
+ * to simply return the object that has already been set up - it will not take
+ * account of any changes you might have made to the initialisation object
+ * passed to DataTables (setting this parameter to true is an acknowledgement
+ * that you understand this). bDestroy can be used to reinitialise a table if
+ * you need.
+ * @type boolean
+ * @default false
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * initTable();
+ * tableActions();
+ * } );
+ *
+ * function initTable ()
+ * {
+ * return $('#example').dataTable( {
+ * "sScrollY": "200px",
+ * "bPaginate": false,
+ * "bRetrieve": true
+ * } );
+ * }
+ *
+ * function tableActions ()
+ * {
+ * var oTable = initTable();
+ * // perform API operations with oTable
+ * }
+ */
+ "bRetrieve": false,
+
+
+ /**
+ * Indicate if DataTables should be allowed to set the padding / margin
+ * etc for the scrolling header elements or not. Typically you will want
+ * this.
+ * @type boolean
+ * @default true
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bScrollAutoCss": false,
+ * "sScrollY": "200px"
+ * } );
+ * } );
+ */
+ "bScrollAutoCss": true,
+
+
+ /**
+ * When vertical (y) scrolling is enabled, DataTables will force the height of
+ * the table's viewport to the given height at all times (useful for layout).
+ * However, this can look odd when filtering data down to a small data set,
+ * and the footer is left "floating" further down. This parameter (when
+ * enabled) will cause DataTables to collapse the table's viewport down when
+ * the result set will fit within the given Y height.
+ * @type boolean
+ * @default false
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sScrollY": "200",
+ * "bScrollCollapse": true
+ * } );
+ * } );
+ */
+ "bScrollCollapse": false,
+
+
+ /**
+ * Enable infinite scrolling for DataTables (to be used in combination with
+ * sScrollY). Infinite scrolling means that DataTables will continually load
+ * data as a user scrolls through a table, which is very useful for large
+ * dataset. This cannot be used with pagination, which is automatically
+ * disabled. Note - the Scroller extra for DataTables is recommended in
+ * in preference to this option.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bScrollInfinite": true,
+ * "bScrollCollapse": true,
+ * "sScrollY": "200px"
+ * } );
+ * } );
+ */
+ "bScrollInfinite": false,
+
+
+ /**
+ * Configure DataTables to use server-side processing. Note that the
+ * sAjaxSource parameter must also be given in order to give DataTables a
+ * source to obtain the required data for each draw.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ * @dtopt Server-side
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bServerSide": true,
+ * "sAjaxSource": "xhr.php"
+ * } );
+ * } );
+ */
+ "bServerSide": false,
+
+
+ /**
+ * Enable or disable sorting of columns. Sorting of individual columns can be
+ * disabled by the "bSortable" option for each column.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bSort": false
+ * } );
+ * } );
+ */
+ "bSort": true,
+
+
+ /**
+ * Allows control over whether DataTables should use the top (true) unique
+ * cell that is found for a single column, or the bottom (false - default).
+ * This is useful when using complex headers.
+ * @type boolean
+ * @default false
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bSortCellsTop": true
+ * } );
+ * } );
+ */
+ "bSortCellsTop": false,
+
+
+ /**
+ * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and
+ * 'sorting_3' to the columns which are currently being sorted on. This is
+ * presented as a feature switch as it can increase processing time (while
+ * classes are removed and added) so for large data sets you might want to
+ * turn this off.
+ * @type boolean
+ * @default true
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bSortClasses": false
+ * } );
+ * } );
+ */
+ "bSortClasses": true,
+
+
+ /**
+ * Enable or disable state saving. When enabled a cookie will be used to save
+ * table display information such as pagination information, display length,
+ * filtering and sorting. As such when the end user reloads the page the
+ * display display will match what thy had previously set up.
+ * @type boolean
+ * @default false
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "bStateSave": true
+ * } );
+ * } );
+ */
+ "bStateSave": false,
+
+
+ /**
+ * Customise the cookie and / or the parameters being stored when using
+ * DataTables with state saving enabled. This function is called whenever
+ * the cookie is modified, and it expects a fully formed cookie string to be
+ * returned. Note that the data object passed in is a Javascript object which
+ * must be converted to a string (JSON.stringify for example).
+ * @type function
+ * @param {string} sName Name of the cookie defined by DataTables
+ * @param {object} oData Data to be stored in the cookie
+ * @param {string} sExpires Cookie expires string
+ * @param {string} sPath Path of the cookie to set
+ * @returns {string} Cookie formatted string (which should be encoded by
+ * using encodeURIComponent())
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "fnCookieCallback": function (sName, oData, sExpires, sPath) {
+ * // Customise oData or sName or whatever else here
+ * return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath;
+ * }
+ * } );
+ * } );
+ */
+ "fnCookieCallback": null,
+
+
+ /**
+ * This function is called when a TR element is created (and all TD child
+ * elements have been inserted), or registered if using a DOM source, allowing
+ * manipulation of the TR element (adding classes etc).
+ * @type function
+ * @param {node} nRow "TR" element for the current row
+ * @param {array} aData Raw data array for this row
+ * @param {int} iDataIndex The index of this row in aoData
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "fnCreatedRow": function( nRow, aData, iDataIndex ) {
+ * // Bold the grade for all 'A' grade browsers
+ * if ( aData[4] == "A" )
+ * {
+ * $('td:eq(4)', nRow).html( 'A' );
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnCreatedRow": null,
+
+
+ /**
+ * This function is called on every 'draw' event, and allows you to
+ * dynamically modify any aspect you want about the created DOM.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "fnDrawCallback": function( oSettings ) {
+ * alert( 'DataTables has redrawn the table' );
+ * }
+ * } );
+ * } );
+ */
+ "fnDrawCallback": null,
+
+
+ /**
+ * Identical to fnHeaderCallback() but for the table footer this function
+ * allows you to modify the table footer on every 'draw' even.
+ * @type function
+ * @param {node} nFoot "TR" element for the footer
+ * @param {array} aData Full table data (as derived from the original HTML)
+ * @param {int} iStart Index for the current display starting point in the
+ * display array
+ * @param {int} iEnd Index for the current display ending point in the
+ * display array
+ * @param {array int} aiDisplay Index array to translate the visual position
+ * to the full data array
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) {
+ * nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart;
+ * }
+ * } );
+ * } )
+ */
+ "fnFooterCallback": null,
+
+
+ /**
+ * When rendering large numbers in the information element for the table
+ * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
+ * to have a comma separator for the 'thousands' units (e.g. 1 million is
+ * rendered as "1,000,000") to help readability for the end user. This
+ * function will override the default method DataTables uses.
+ * @type function
+ * @member
+ * @param {int} iIn number to be formatted
+ * @returns {string} formatted string for DataTables to show the number
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "fnFormatNumber": function ( iIn ) {
+ * if ( iIn < 1000 ) {
+ * return iIn;
+ * } else {
+ * var
+ * s=(iIn+""),
+ * a=s.split(""), out="",
+ * iLen=s.length;
+ *
+ * for ( var i=0 ; i<iLen ; i++ ) {
+ * if ( i%3 === 0 && i !== 0 ) {
+ * out = "'"+out;
+ * }
+ * out = a[iLen-i-1]+out;
+ * }
+ * }
+ * return out;
+ * };
+ * } );
+ * } );
+ */
+ "fnFormatNumber": function ( iIn ) {
+ if ( iIn < 1000 )
+ {
+ // A small optimisation for what is likely to be the majority of use cases
+ return iIn;
+ }
+
+ var s=(iIn+""), a=s.split(""), out="", iLen=s.length;
+
+ for ( var i=0 ; iA' );
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnRowCallback": null,
+
+
+ /**
+ * This parameter allows you to override the default function which obtains
+ * the data from the server ($.getJSON) so something more suitable for your
+ * application. For example you could use POST data, or pull information from
+ * a Gears or AIR database.
+ * @type function
+ * @member
+ * @param {string} sSource HTTP source to obtain the data from (sAjaxSource)
+ * @param {array} aoData A key/value pair object containing the data to send
+ * to the server
+ * @param {function} fnCallback to be called on completion of the data get
+ * process that will draw the data on the page.
+ * @param {object} oSettings DataTables settings object
+ * @dtopt Callbacks
+ * @dtopt Server-side
+ *
+ * @example
+ * // POST data to server
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bProcessing": true,
+ * "bServerSide": true,
+ * "sAjaxSource": "xhr.php",
+ * "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
+ * oSettings.jqXHR = $.ajax( {
+ * "dataType": 'json',
+ * "type": "POST",
+ * "url": sSource,
+ * "data": aoData,
+ * "success": fnCallback
+ * } );
+ * }
+ * } );
+ * } );
+ */
+ "fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) {
+ oSettings.jqXHR = $.ajax( {
+ "url": sUrl,
+ "data": aoData,
+ "success": function (json) {
+ if ( json.sError ) {
+ oSettings.oApi._fnLog( oSettings, 0, json.sError );
+ }
+
+ $(oSettings.oInstance).trigger('xhr', [oSettings, json]);
+ fnCallback( json );
+ },
+ "dataType": "json",
+ "cache": false,
+ "type": oSettings.sServerMethod,
+ "error": function (xhr, error, thrown) {
+ if ( error == "parsererror" ) {
+ oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+
+ "server could not be parsed. This is caused by a JSON formatting error." );
+ }
+ }
+ } );
+ },
+
+
+ /**
+ * It is often useful to send extra data to the server when making an Ajax
+ * request - for example custom filtering information, and this callback
+ * function makes it trivial to send extra information to the server. The
+ * passed in parameter is the data set that has been constructed by
+ * DataTables, and you can add to this or modify it as you require.
+ * @type function
+ * @param {array} aoData Data array (array of objects which are name/value
+ * pairs) that has been constructed by DataTables and will be sent to the
+ * server. In the case of Ajax sourced data with server-side processing
+ * this will be an empty array, for server-side processing there will be a
+ * significant number of parameters!
+ * @returns {undefined} Ensure that you modify the aoData array passed in,
+ * as this is passed by reference.
+ * @dtopt Callbacks
+ * @dtopt Server-side
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bProcessing": true,
+ * "bServerSide": true,
+ * "sAjaxSource": "scripts/server_processing.php",
+ * "fnServerParams": function ( aoData ) {
+ * aoData.push( { "name": "more_data", "value": "my_value" } );
+ * }
+ * } );
+ * } );
+ */
+ "fnServerParams": null,
+
+
+ /**
+ * Load the table state. With this function you can define from where, and how, the
+ * state of a table is loaded. By default DataTables will load from its state saving
+ * cookie, but you might wish to use local storage (HTML5) or a server-side database.
+ * @type function
+ * @member
+ * @param {object} oSettings DataTables settings object
+ * @return {object} The DataTables state object to be loaded
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateLoad": function (oSettings) {
+ * var o;
+ *
+ * // Send an Ajax request to the server to get the data. Note that
+ * // this is a synchronous request.
+ * $.ajax( {
+ * "url": "/state_load",
+ * "async": false,
+ * "dataType": "json",
+ * "success": function (json) {
+ * o = json;
+ * }
+ * } );
+ *
+ * return o;
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoad": function ( oSettings ) {
+ var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance );
+ var oData;
+
+ try {
+ oData = (typeof $.parseJSON === 'function') ?
+ $.parseJSON(sData) : eval( '('+sData+')' );
+ } catch (e) {
+ oData = null;
+ }
+
+ return oData;
+ },
+
+
+ /**
+ * Callback which allows modification of the saved state prior to loading that state.
+ * This callback is called when the table is loading state from the stored data, but
+ * prior to the settings object being modified by the saved state. Note that for
+ * plug-in authors, you should use the 'stateLoadParams' event to load parameters for
+ * a plug-in.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @param {object} oData The state object that is to be loaded
+ * @dtopt Callbacks
+ *
+ * @example
+ * // Remove a saved filter, so filtering is never loaded
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateLoadParams": function (oSettings, oData) {
+ * oData.oSearch.sSearch = "";
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Disallow state loading by returning false
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateLoadParams": function (oSettings, oData) {
+ * return false;
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoadParams": null,
+
+
+ /**
+ * Callback that is called when the state has been loaded from the state saving method
+ * and the DataTables settings object has been modified as a result of the loaded state.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @param {object} oData The state object that was loaded
+ * @dtopt Callbacks
+ *
+ * @example
+ * // Show an alert with the filtering value that was saved
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateLoaded": function (oSettings, oData) {
+ * alert( 'Saved filter was: '+oData.oSearch.sSearch );
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoaded": null,
+
+
+ /**
+ * Save the table state. This function allows you to define where and how the state
+ * information for the table is stored - by default it will use a cookie, but you
+ * might want to use local storage (HTML5) or a server-side database.
+ * @type function
+ * @member
+ * @param {object} oSettings DataTables settings object
+ * @param {object} oData The state object to be saved
+ * @dtopt Callbacks
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateSave": function (oSettings, oData) {
+ * // Send an Ajax request to the server with the state object
+ * $.ajax( {
+ * "url": "/state_save",
+ * "data": oData,
+ * "dataType": "json",
+ * "method": "POST"
+ * "success": function () {}
+ * } );
+ * }
+ * } );
+ * } );
+ */
+ "fnStateSave": function ( oSettings, oData ) {
+ this.oApi._fnCreateCookie(
+ oSettings.sCookiePrefix+oSettings.sInstance,
+ this.oApi._fnJsonString(oData),
+ oSettings.iCookieDuration,
+ oSettings.sCookiePrefix,
+ oSettings.fnCookieCallback
+ );
+ },
+
+
+ /**
+ * Callback which allows modification of the state to be saved. Called when the table
+ * has changed state a new state save is required. This method allows modification of
+ * the state saving object prior to actually doing the save, including addition or
+ * other state properties or modification. Note that for plug-in authors, you should
+ * use the 'stateSaveParams' event to save parameters for a plug-in.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @param {object} oData The state object to be saved
+ * @dtopt Callbacks
+ *
+ * @example
+ * // Remove a saved filter, so filtering is never saved
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bStateSave": true,
+ * "fnStateSaveParams": function (oSettings, oData) {
+ * oData.oSearch.sSearch = "";
+ * }
+ * } );
+ * } );
+ */
+ "fnStateSaveParams": null,
+
+
+ /**
+ * Duration of the cookie which is used for storing session information. This
+ * value is given in seconds.
+ * @type int
+ * @default 7200 (2 hours)
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "iCookieDuration": 60*60*24; // 1 day
+ * } );
+ * } )
+ */
+ "iCookieDuration": 7200,
+
+
+ /**
+ * When enabled DataTables will not make a request to the server for the first
+ * page draw - rather it will use the data already on the page (no sorting etc
+ * will be applied to it), thus saving on an XHR at load time. iDeferLoading
+ * is used to indicate that deferred loading is required, but it is also used
+ * to tell DataTables how many records there are in the full table (allowing
+ * the information element and pagination to be displayed correctly). In the case
+ * where a filtering is applied to the table on initial load, this can be
+ * indicated by giving the parameter as an array, where the first element is
+ * the number of records available after filtering and the second element is the
+ * number of records without filtering (allowing the table information element
+ * to be shown correctly).
+ * @type int | array
+ * @default null
+ * @dtopt Options
+ *
+ * @example
+ * // 57 records available in the table, no filtering applied
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bServerSide": true,
+ * "sAjaxSource": "scripts/server_processing.php",
+ * "iDeferLoading": 57
+ * } );
+ * } );
+ *
+ * @example
+ * // 57 records after filtering, 100 without filtering (an initial filter applied)
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bServerSide": true,
+ * "sAjaxSource": "scripts/server_processing.php",
+ * "iDeferLoading": [ 57, 100 ],
+ * "oSearch": {
+ * "sSearch": "my_filter"
+ * }
+ * } );
+ * } );
+ */
+ "iDeferLoading": null,
+
+
+ /**
+ * Number of rows to display on a single page when using pagination. If
+ * feature enabled (bLengthChange) then the end user will be able to override
+ * this to a custom setting using a pop-up menu.
+ * @type int
+ * @default 10
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "iDisplayLength": 50
+ * } );
+ * } )
+ */
+ "iDisplayLength": 10,
+
+
+ /**
+ * Define the starting point for data display when using DataTables with
+ * pagination. Note that this parameter is the number of records, rather than
+ * the page number, so if you have 10 records per page and want to start on
+ * the third page, it should be "20".
+ * @type int
+ * @default 0
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "iDisplayStart": 20
+ * } );
+ * } )
+ */
+ "iDisplayStart": 0,
+
+
+ /**
+ * The scroll gap is the amount of scrolling that is left to go before
+ * DataTables will load the next 'page' of data automatically. You typically
+ * want a gap which is big enough that the scrolling will be smooth for the
+ * user, while not so large that it will load more data than need.
+ * @type int
+ * @default 100
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bScrollInfinite": true,
+ * "bScrollCollapse": true,
+ * "sScrollY": "200px",
+ * "iScrollLoadGap": 50
+ * } );
+ * } );
+ */
+ "iScrollLoadGap": 100,
+
+
+ /**
+ * By default DataTables allows keyboard navigation of the table (sorting, paging,
+ * and filtering) by adding a tabindex attribute to the required elements. This
+ * allows you to tab through the controls and press the enter key to activate them.
+ * The tabindex is default 0, meaning that the tab follows the flow of the document.
+ * You can overrule this using this parameter if you wish. Use a value of -1 to
+ * disable built-in keyboard navigation.
+ * @type int
+ * @default 0
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "iTabIndex": 1
+ * } );
+ * } );
+ */
+ "iTabIndex": 0,
+
+
+ /**
+ * All strings that DataTables uses in the user interface that it creates
+ * are defined in this object, allowing you to modified them individually or
+ * completely replace them all as required.
+ * @namespace
+ */
+ "oLanguage": {
+ /**
+ * Strings that are used for WAI-ARIA labels and controls only (these are not
+ * actually visible on the page, but will be read by screenreaders, and thus
+ * must be internationalised as well).
+ * @namespace
+ */
+ "oAria": {
+ /**
+ * ARIA label that is added to the table headers when the column may be
+ * sorted ascending by activing the column (click or return when focused).
+ * Note that the column header is prefixed to this string.
+ * @type string
+ * @default : activate to sort column ascending
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oAria": {
+ * "sSortAscending": " - click/return to sort ascending"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sSortAscending": ": activate to sort column ascending",
+
+ /**
+ * ARIA label that is added to the table headers when the column may be
+ * sorted descending by activing the column (click or return when focused).
+ * Note that the column header is prefixed to this string.
+ * @type string
+ * @default : activate to sort column ascending
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oAria": {
+ * "sSortDescending": " - click/return to sort descending"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sSortDescending": ": activate to sort column descending"
+ },
+
+ /**
+ * Pagination string used by DataTables for the two built-in pagination
+ * control types ("two_button" and "full_numbers")
+ * @namespace
+ */
+ "oPaginate": {
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the first page.
+ * @type string
+ * @default First
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oPaginate": {
+ * "sFirst": "First page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sFirst": "First",
+
+
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the last page.
+ * @type string
+ * @default Last
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oPaginate": {
+ * "sLast": "Last page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sLast": "Last",
+
+
+ /**
+ * Text to use for the 'next' pagination button (to take the user to the
+ * next page).
+ * @type string
+ * @default Next
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oPaginate": {
+ * "sNext": "Next page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sNext": "Next",
+
+
+ /**
+ * Text to use for the 'previous' pagination button (to take the user to
+ * the previous page).
+ * @type string
+ * @default Previous
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "oPaginate": {
+ * "sPrevious": "Previous page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sPrevious": "Previous"
+ },
+
+ /**
+ * This string is shown in preference to sZeroRecords when the table is
+ * empty of data (regardless of filtering). Note that this is an optional
+ * parameter - if it is not given, the value of sZeroRecords will be used
+ * instead (either the default or given value).
+ * @type string
+ * @default No data available in table
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sEmptyTable": "No data available in table"
+ * }
+ * } );
+ * } );
+ */
+ "sEmptyTable": "No data available in table",
+
+
+ /**
+ * This string gives information to the end user about the information that
+ * is current on display on the page. The _START_, _END_ and _TOTAL_
+ * variables are all dynamically replaced as the table display updates, and
+ * can be freely moved or removed as the language requirements change.
+ * @type string
+ * @default Showing _START_ to _END_ of _TOTAL_ entries
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)"
+ * }
+ * } );
+ * } );
+ */
+ "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
+
+
+ /**
+ * Display information string for when the table is empty. Typically the
+ * format of this string should match sInfo.
+ * @type string
+ * @default Showing 0 to 0 of 0 entries
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfoEmpty": "No entries to show"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoEmpty": "Showing 0 to 0 of 0 entries",
+
+
+ /**
+ * When a user filters the information in a table, this string is appended
+ * to the information (sInfo) to give an idea of how strong the filtering
+ * is. The variable _MAX_ is dynamically updated.
+ * @type string
+ * @default (filtered from _MAX_ total entries)
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfoFiltered": " - filtering from _MAX_ records"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoFiltered": "(filtered from _MAX_ total entries)",
+
+
+ /**
+ * If can be useful to append extra information to the info string at times,
+ * and this variable does exactly that. This information will be appended to
+ * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are
+ * being used) at all times.
+ * @type string
+ * @default Empty string
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfoPostFix": "All records shown are derived from real information."
+ * }
+ * } );
+ * } );
+ */
+ "sInfoPostFix": "",
+
+
+ /**
+ * DataTables has a build in number formatter (fnFormatNumber) which is used
+ * to format large numbers that are used in the table information. By
+ * default a comma is used, but this can be trivially changed to any
+ * character you wish with this parameter.
+ * @type string
+ * @default ,
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sInfoThousands": "'"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoThousands": ",",
+
+
+ /**
+ * Detail the action that will be taken when the drop down menu for the
+ * pagination length option is changed. The '_MENU_' variable is replaced
+ * with a default select list of 10, 25, 50 and 100, and can be replaced
+ * with a custom select box if required.
+ * @type string
+ * @default Show _MENU_ entries
+ * @dtopt Language
+ *
+ * @example
+ * // Language change only
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sLengthMenu": "Display _MENU_ records"
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Language and options change
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sLengthMenu": 'Display records'
+ * }
+ * } );
+ * } );
+ */
+ "sLengthMenu": "Show _MENU_ entries",
+
+
+ /**
+ * When using Ajax sourced data and during the first draw when DataTables is
+ * gathering the data, this message is shown in an empty row in the table to
+ * indicate to the end user the the data is being loaded. Note that this
+ * parameter is not used when loading data by server-side processing, just
+ * Ajax sourced data with client-side processing.
+ * @type string
+ * @default Loading...
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sLoadingRecords": "Please wait - loading..."
+ * }
+ * } );
+ * } );
+ */
+ "sLoadingRecords": "Loading...",
+
+
+ /**
+ * Text which is displayed when the table is processing a user action
+ * (usually a sort command or similar).
+ * @type string
+ * @default Processing...
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sProcessing": "DataTables is currently busy"
+ * }
+ * } );
+ * } );
+ */
+ "sProcessing": "Processing...",
+
+
+ /**
+ * Details the actions that will be taken when the user types into the
+ * filtering input text box. The variable "_INPUT_", if used in the string,
+ * is replaced with the HTML text box for the filtering input allowing
+ * control over where it appears in the string. If "_INPUT_" is not given
+ * then the input box is appended to the string automatically.
+ * @type string
+ * @default Search:
+ * @dtopt Language
+ *
+ * @example
+ * // Input text box will be appended at the end automatically
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sSearch": "Filter records:"
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Specify where the filter should appear
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sSearch": "Apply filter _INPUT_ to table"
+ * }
+ * } );
+ * } );
+ */
+ "sSearch": "Search:",
+
+
+ /**
+ * All of the language information can be stored in a file on the
+ * server-side, which DataTables will look up if this parameter is passed.
+ * It must store the URL of the language file, which is in a JSON format,
+ * and the object has the same properties as the oLanguage object in the
+ * initialiser object (i.e. the above parameters). Please refer to one of
+ * the example language files to see how this works in action.
+ * @type string
+ * @default Empty string - i.e. disabled
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt"
+ * }
+ * } );
+ * } );
+ */
+ "sUrl": "",
+
+
+ /**
+ * Text shown inside the table records when the is no information to be
+ * displayed after filtering. sEmptyTable is shown when there is simply no
+ * information in the table at all (regardless of filtering).
+ * @type string
+ * @default No matching records found
+ * @dtopt Language
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oLanguage": {
+ * "sZeroRecords": "No records to display"
+ * }
+ * } );
+ * } );
+ */
+ "sZeroRecords": "No matching records found"
+ },
+
+
+ /**
+ * This parameter allows you to have define the global filtering state at
+ * initialisation time. As an object the "sSearch" parameter must be
+ * defined, but all other parameters are optional. When "bRegex" is true,
+ * the search string will be treated as a regular expression, when false
+ * (default) it will be treated as a straight string. When "bSmart"
+ * DataTables will use it's smart filtering methods (to word match at
+ * any point in the data), when false this will not be done.
+ * @namespace
+ * @extends DataTable.models.oSearch
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "oSearch": {"sSearch": "Initial search"}
+ * } );
+ * } )
+ */
+ "oSearch": $.extend( {}, DataTable.models.oSearch ),
+
+
+ /**
+ * By default DataTables will look for the property 'aaData' when obtaining
+ * data from an Ajax source or for server-side processing - this parameter
+ * allows that property to be changed. You can use Javascript dotted object
+ * notation to get a data source for multiple levels of nesting.
+ * @type string
+ * @default aaData
+ * @dtopt Options
+ * @dtopt Server-side
+ *
+ * @example
+ * // Get data from { "data": [...] }
+ * $(document).ready( function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/data.txt",
+ * "sAjaxDataProp": "data"
+ * } );
+ * } );
+ *
+ * @example
+ * // Get data from { "data": { "inner": [...] } }
+ * $(document).ready( function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/data.txt",
+ * "sAjaxDataProp": "data.inner"
+ * } );
+ * } );
+ */
+ "sAjaxDataProp": "aaData",
+
+
+ /**
+ * You can instruct DataTables to load data from an external source using this
+ * parameter (use aData if you want to pass data in you already have). Simply
+ * provide a url a JSON object can be obtained from. This object must include
+ * the parameter 'aaData' which is the data source for the table.
+ * @type string
+ * @default null
+ * @dtopt Options
+ * @dtopt Server-side
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php"
+ * } );
+ * } )
+ */
+ "sAjaxSource": null,
+
+
+ /**
+ * This parameter can be used to override the default prefix that DataTables
+ * assigns to a cookie when state saving is enabled.
+ * @type string
+ * @default SpryMedia_DataTables_
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sCookiePrefix": "my_datatable_",
+ * } );
+ * } );
+ */
+ "sCookiePrefix": "SpryMedia_DataTables_",
+
+
+ /**
+ * This initialisation variable allows you to specify exactly where in the
+ * DOM you want DataTables to inject the various controls it adds to the page
+ * (for example you might want the pagination controls at the top of the
+ * table). DIV elements (with or without a custom class) can also be added to
+ * aid styling. The follow syntax is used:
+ *
+ *
+ * @type string
+ * @default lfrtip (when bJQueryUI is false)or
+ * <"H"lfr>t<"F"ip> (when bJQueryUI is true)
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sDom": '<"top"i>rt<"bottom"flp><"clear">'
+ * } );
+ * } );
+ */
+ "sDom": "lfrtip",
+
+
+ /**
+ * DataTables features two different built-in pagination interaction methods
+ * ('two_button' or 'full_numbers') which present different page controls to
+ * the end user. Further methods can be added using the API (see below).
+ * @type string
+ * @default two_button
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sPaginationType": "full_numbers"
+ * } );
+ * } )
+ */
+ "sPaginationType": "two_button",
+
+
+ /**
+ * Enable horizontal scrolling. When a table is too wide to fit into a certain
+ * layout, or you have a large number of columns in the table, you can enable
+ * x-scrolling to show the table in a viewport, which can be scrolled. This
+ * property can be any CSS unit, or a number (in which case it will be treated
+ * as a pixel measurement).
+ * @type string
+ * @default blank string - i.e. disabled
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sScrollX": "100%",
+ * "bScrollCollapse": true
+ * } );
+ * } );
+ */
+ "sScrollX": "",
+
+
+ /**
+ * This property can be used to force a DataTable to use more width than it
+ * might otherwise do when x-scrolling is enabled. For example if you have a
+ * table which requires to be well spaced, this parameter is useful for
+ * "over-sizing" the table, and thus forcing scrolling. This property can by
+ * any CSS unit, or a number (in which case it will be treated as a pixel
+ * measurement).
+ * @type string
+ * @default blank string - i.e. disabled
+ * @dtopt Options
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sScrollX": "100%",
+ * "sScrollXInner": "110%"
+ * } );
+ * } );
+ */
+ "sScrollXInner": "",
+
+
+ /**
+ * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
+ * to the given height, and enable scrolling for any data which overflows the
+ * current viewport. This can be used as an alternative to paging to display
+ * a lot of data in a small area (although paging and scrolling can both be
+ * enabled at the same time). This property can be any CSS unit, or a number
+ * (in which case it will be treated as a pixel measurement).
+ * @type string
+ * @default blank string - i.e. disabled
+ * @dtopt Features
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "sScrollY": "200px",
+ * "bPaginate": false
+ * } );
+ * } );
+ */
+ "sScrollY": "",
+
+
+ /**
+ * Set the HTTP method that is used to make the Ajax call for server-side
+ * processing or Ajax sourced data.
+ * @type string
+ * @default GET
+ * @dtopt Options
+ * @dtopt Server-side
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "bServerSide": true,
+ * "sAjaxSource": "scripts/post.php",
+ * "sServerMethod": "POST"
+ * } );
+ * } );
+ */
+ "sServerMethod": "GET"
+ };
+
+
+
+ /**
+ * Column options that can be given to DataTables at initialisation time.
+ * @namespace
+ */
+ DataTable.defaults.columns = {
+ /**
+ * Allows a column's sorting to take multiple columns into account when
+ * doing a sort. For example first name / last name columns make sense to
+ * do a multi-column sort over the two columns.
+ * @type array
+ * @default null Takes the value of the column index automatically
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] },
+ * { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] },
+ * { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "aDataSort": [ 0, 1 ] },
+ * { "aDataSort": [ 1, 0 ] },
+ * { "aDataSort": [ 2, 3, 4 ] },
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "aDataSort": null,
+
+
+ /**
+ * You can control the default sorting direction, and even alter the behaviour
+ * of the sort handler (i.e. only allow ascending sorting etc) using this
+ * parameter.
+ * @type array
+ * @default [ 'asc', 'desc' ]
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "asSorting": [ "asc" ], "aTargets": [ 1 ] },
+ * { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] },
+ * { "asSorting": [ "desc" ], "aTargets": [ 3 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * null,
+ * { "asSorting": [ "asc" ] },
+ * { "asSorting": [ "desc", "asc", "asc" ] },
+ * { "asSorting": [ "desc" ] },
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "asSorting": [ 'asc', 'desc' ],
+
+
+ /**
+ * Enable or disable filtering on the data in this column.
+ * @type boolean
+ * @default true
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "bSearchable": false, "aTargets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "bSearchable": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bSearchable": true,
+
+
+ /**
+ * Enable or disable sorting on this column.
+ * @type boolean
+ * @default true
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "bSortable": false, "aTargets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "bSortable": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bSortable": true,
+
+
+ /**
+ * Deprecated When using fnRender() for a column, you may wish
+ * to use the original data (before rendering) for sorting and filtering
+ * (the default is to used the rendered data that the user can see). This
+ * may be useful for dates etc.
+ *
+ * Please note that this option has now been deprecated and will be removed
+ * in the next version of DataTables. Please use mRender / mData rather than
+ * fnRender.
+ * @type boolean
+ * @default true
+ * @dtopt Columns
+ * @deprecated
+ */
+ "bUseRendered": true,
+
+
+ /**
+ * Enable or disable the display of this column.
+ * @type boolean
+ * @default true
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "bVisible": false, "aTargets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "bVisible": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bVisible": true,
+
+
+ /**
+ * Developer definable function that is called whenever a cell is created (Ajax source,
+ * etc) or processed for input (DOM source). This can be used as a compliment to mRender
+ * allowing you to modify the DOM element (add background colour for example) when the
+ * element is available.
+ * @type function
+ * @param {element} nTd The TD node that has been created
+ * @param {*} sData The Data for the cell
+ * @param {array|object} oData The data for the whole row
+ * @param {int} iRow The row index for the aoData data store
+ * @param {int} iCol The column index for aoColumns
+ * @dtopt Columns
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [ {
+ * "aTargets": [3],
+ * "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
+ * if ( sData == "1.7" ) {
+ * $(nTd).css('color', 'blue')
+ * }
+ * }
+ * } ]
+ * });
+ * } );
+ */
+ "fnCreatedCell": null,
+
+
+ /**
+ * Deprecated Custom display function that will be called for the
+ * display of each cell in this column.
+ *
+ * Please note that this option has now been deprecated and will be removed
+ * in the next version of DataTables. Please use mRender / mData rather than
+ * fnRender.
+ * @type function
+ * @param {object} o Object with the following parameters:
+ * @param {int} o.iDataRow The row in aoData
+ * @param {int} o.iDataColumn The column in question
+ * @param {array} o.aData The data for the row in question
+ * @param {object} o.oSettings The settings object for this DataTables instance
+ * @param {object} o.mDataProp The data property used for this column
+ * @param {*} val The current cell value
+ * @returns {string} The string you which to use in the display
+ * @dtopt Columns
+ * @deprecated
+ */
+ "fnRender": null,
+
+
+ /**
+ * The column index (starting from 0!) that you wish a sort to be performed
+ * upon when this column is selected for sorting. This can be used for sorting
+ * on hidden columns for example.
+ * @type int
+ * @default -1 Use automatically calculated column index
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "iDataSort": 1, "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "iDataSort": 1 },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "iDataSort": -1,
+
+
+ /**
+ * This parameter has been replaced by mData in DataTables to ensure naming
+ * consistency. mDataProp can still be used, as there is backwards compatibility
+ * in DataTables for this option, but it is strongly recommended that you use
+ * mData in preference to mDataProp.
+ * @name DataTable.defaults.columns.mDataProp
+ */
+
+
+ /**
+ * This property can be used to read data from any JSON data source property,
+ * including deeply nested objects / properties. mData can be given in a
+ * number of different ways which effect its behaviour:
+ *
+ *
integer - treated as an array index for the data source. This is the
+ * default that DataTables uses (incrementally increased for each column).
+ *
string - read an object property from the data source. Note that you can
+ * use Javascript dotted notation to read deep properties / arrays from the
+ * data source.
+ *
null - the sDefaultContent option will be used for the cell (null
+ * by default, so you will need to specify the default content you want -
+ * typically an empty string). This can be useful on generated columns such
+ * as edit / delete action columns.
+ *
function - the function given will be executed whenever DataTables
+ * needs to set or get the data for a cell in the column. The function
+ * takes three parameters:
+ *
+ *
{array|object} The data source for the row
+ *
{string} The type call data requested - this will be 'set' when
+ * setting data or 'filter', 'display', 'type', 'sort' or undefined when
+ * gathering data. Note that when undefined is given for the type
+ * DataTables expects to get the raw data for the object back
+ *
{*} Data to set when the second parameter is 'set'.
+ *
+ * The return value from the function is not required when 'set' is the type
+ * of call, but otherwise the return is what will be used for the data
+ * requested.
+ *
+ *
+ * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change
+ * reflects the flexibility of this property and is consistent with the naming of
+ * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as
+ * it automatically maps the old name to the new if required.
+ * @type string|int|function|null
+ * @default null Use automatically calculated column index
+ * @dtopt Columns
+ *
+ * @example
+ * // Read table data from objects
+ * $(document).ready( function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/deep.txt",
+ * "aoColumns": [
+ * { "mData": "engine" },
+ * { "mData": "browser" },
+ * { "mData": "platform.inner" },
+ * { "mData": "platform.details.0" },
+ * { "mData": "platform.details.1" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using mData as a function to provide different information for
+ * // sorting, filtering and display. In this case, currency (price)
+ * $(document).ready( function() {
+ * var oTable = $('#example').dataTable( {
+ * "aoColumnDefs": [ {
+ * "aTargets": [ 0 ],
+ * "mData": function ( source, type, val ) {
+ * if (type === 'set') {
+ * source.price = val;
+ * // Store the computed dislay and filter values for efficiency
+ * source.price_display = val=="" ? "" : "$"+numberFormat(val);
+ * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
+ * return;
+ * }
+ * else if (type === 'display') {
+ * return source.price_display;
+ * }
+ * else if (type === 'filter') {
+ * return source.price_filter;
+ * }
+ * // 'sort', 'type' and undefined all just use the integer
+ * return source.price;
+ * }
+ * } ]
+ * } );
+ * } );
+ */
+ "mData": null,
+
+
+ /**
+ * This property is the rendering partner to mData and it is suggested that
+ * when you want to manipulate data for display (including filtering, sorting etc)
+ * but not altering the underlying data for the table, use this property. mData
+ * can actually do everything this property can and more, but this parameter is
+ * easier to use since there is no 'set' option. Like mData is can be given
+ * in a number of different ways to effect its behaviour, with the addition of
+ * supporting array syntax for easy outputting of arrays (including arrays of
+ * objects):
+ *
+ *
integer - treated as an array index for the data source. This is the
+ * default that DataTables uses (incrementally increased for each column).
+ *
string - read an object property from the data source. Note that you can
+ * use Javascript dotted notation to read deep properties / arrays from the
+ * data source and also array brackets to indicate that the data reader should
+ * loop over the data source array. When characters are given between the array
+ * brackets, these characters are used to join the data source array together.
+ * For example: "accounts[, ].name" would result in a comma separated list with
+ * the 'name' value from the 'accounts' array of objects.
+ *
function - the function given will be executed whenever DataTables
+ * needs to set or get the data for a cell in the column. The function
+ * takes three parameters:
+ *
+ *
{array|object} The data source for the row (based on mData)
+ *
{string} The type call data requested - this will be 'filter', 'display',
+ * 'type' or 'sort'.
+ *
{array|object} The full data source for the row (not based on mData)
+ *
+ * The return value from the function is what will be used for the data
+ * requested.
+ *
+ * @type string|int|function|null
+ * @default null Use mData
+ * @dtopt Columns
+ *
+ * @example
+ * // Create a comma separated list from an array of objects
+ * $(document).ready( function() {
+ * var oTable = $('#example').dataTable( {
+ * "sAjaxSource": "sources/deep.txt",
+ * "aoColumns": [
+ * { "mData": "engine" },
+ * { "mData": "browser" },
+ * {
+ * "mData": "platform",
+ * "mRender": "[, ].name"
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Use as a function to create a link from the data source
+ * $(document).ready( function() {
+ * var oTable = $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * {
+ * "aTargets": [ 0 ],
+ * "mData": "download_link",
+ * "mRender": function ( data, type, full ) {
+ * return 'Download';
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "mRender": null,
+
+
+ /**
+ * Change the cell type created for the column - either TD cells or TH cells. This
+ * can be useful as TH cells have semantic meaning in the table body, allowing them
+ * to act as a header for a row (you may wish to add scope='row' to the TH elements).
+ * @type string
+ * @default td
+ * @dtopt Columns
+ *
+ * @example
+ * // Make the first column use TH cells
+ * $(document).ready( function() {
+ * var oTable = $('#example').dataTable( {
+ * "aoColumnDefs": [ {
+ * "aTargets": [ 0 ],
+ * "sCellType": "th"
+ * } ]
+ * } );
+ * } );
+ */
+ "sCellType": "td",
+
+
+ /**
+ * Class to give to each cell in this column.
+ * @type string
+ * @default Empty string
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sClass": "my_class", "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sClass": "my_class" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sClass": "",
+
+ /**
+ * When DataTables calculates the column widths to assign to each column,
+ * it finds the longest string in each column and then constructs a
+ * temporary table and reads the widths from that. The problem with this
+ * is that "mmm" is much wider then "iiii", but the latter is a longer
+ * string - thus the calculation can go wrong (doing it properly and putting
+ * it into an DOM object and measuring that is horribly(!) slow). Thus as
+ * a "work around" we provide this option. It will append its value to the
+ * text that is found to be the longest string for the column - i.e. padding.
+ * Generally you shouldn't need this, and it is not documented on the
+ * general DataTables.net documentation
+ * @type string
+ * @default Empty string
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * null,
+ * null,
+ * null,
+ * {
+ * "sContentPadding": "mmm"
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "sContentPadding": "",
+
+
+ /**
+ * Allows a default value to be given for a column's data, and will be used
+ * whenever a null data source is encountered (this can be because mData
+ * is set to null, or because the data source itself is null).
+ * @type string
+ * @default null
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * {
+ * "mData": null,
+ * "sDefaultContent": "Edit",
+ * "aTargets": [ -1 ]
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * null,
+ * null,
+ * null,
+ * {
+ * "mData": null,
+ * "sDefaultContent": "Edit"
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "sDefaultContent": null,
+
+
+ /**
+ * This parameter is only used in DataTables' server-side processing. It can
+ * be exceptionally useful to know what columns are being displayed on the
+ * client side, and to map these to database fields. When defined, the names
+ * also allow DataTables to reorder information from the server if it comes
+ * back in an unexpected order (i.e. if you switch your columns around on the
+ * client-side, your server-side code does not also need updating).
+ * @type string
+ * @default Empty string
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sName": "engine", "aTargets": [ 0 ] },
+ * { "sName": "browser", "aTargets": [ 1 ] },
+ * { "sName": "platform", "aTargets": [ 2 ] },
+ * { "sName": "version", "aTargets": [ 3 ] },
+ * { "sName": "grade", "aTargets": [ 4 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sName": "engine" },
+ * { "sName": "browser" },
+ * { "sName": "platform" },
+ * { "sName": "version" },
+ * { "sName": "grade" }
+ * ]
+ * } );
+ * } );
+ */
+ "sName": "",
+
+
+ /**
+ * Defines a data source type for the sorting which can be used to read
+ * real-time information from the table (updating the internally cached
+ * version) prior to sorting. This allows sorting to occur on user editable
+ * elements such as form inputs.
+ * @type string
+ * @default std
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] },
+ * { "sType": "numeric", "aTargets": [ 3 ] },
+ * { "sSortDataType": "dom-select", "aTargets": [ 4 ] },
+ * { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * null,
+ * null,
+ * { "sSortDataType": "dom-text" },
+ * { "sSortDataType": "dom-text", "sType": "numeric" },
+ * { "sSortDataType": "dom-select" },
+ * { "sSortDataType": "dom-checkbox" }
+ * ]
+ * } );
+ * } );
+ */
+ "sSortDataType": "std",
+
+
+ /**
+ * The title of this column.
+ * @type string
+ * @default null Derived from the 'TH' value for this column in the
+ * original HTML table.
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sTitle": "My column title", "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sTitle": "My column title" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sTitle": null,
+
+
+ /**
+ * The type allows you to specify how the data for this column will be sorted.
+ * Four types (string, numeric, date and html (which will strip HTML tags
+ * before sorting)) are currently available. Note that only date formats
+ * understood by Javascript's Date() object will be accepted as type date. For
+ * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric',
+ * 'date' or 'html' (by default). Further types can be adding through
+ * plug-ins.
+ * @type string
+ * @default null Auto-detected from raw data
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sType": "html", "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sType": "html" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sType": null,
+
+
+ /**
+ * Defining the width of the column, this parameter may take any CSS value
+ * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not
+ * been given a specific width through this interface ensuring that the table
+ * remains readable.
+ * @type string
+ * @default null Automatic
+ * @dtopt Columns
+ *
+ * @example
+ * // Using aoColumnDefs
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumnDefs": [
+ * { "sWidth": "20%", "aTargets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using aoColumns
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "aoColumns": [
+ * { "sWidth": "20%" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sWidth": null
+ };
+
+
+
+ /**
+ * DataTables settings object - this holds all the information needed for a
+ * given table, including configuration, data and current application of the
+ * table options. DataTables does not have a single instance for each DataTable
+ * with the settings attached to that instance, but rather instances of the
+ * DataTable "class" are created on-the-fly as needed (typically by a
+ * $().dataTable() call) and the settings object is then applied to that
+ * instance.
+ *
+ * Note that this object is related to {@link DataTable.defaults} but this
+ * one is the internal data store for DataTables's cache of columns. It should
+ * NOT be manipulated outside of DataTables. Any configuration should be done
+ * through the initialisation options.
+ * @namespace
+ * @todo Really should attach the settings object to individual instances so we
+ * don't need to create new instances on each $().dataTable() call (if the
+ * table already exists). It would also save passing oSettings around and
+ * into every single function. However, this is a very significant
+ * architecture change for DataTables and will almost certainly break
+ * backwards compatibility with older installations. This is something that
+ * will be done in 2.0.
+ */
+ DataTable.models.oSettings = {
+ /**
+ * Primary features of DataTables and their enablement state.
+ * @namespace
+ */
+ "oFeatures": {
+
+ /**
+ * Flag to say if DataTables should automatically try to calculate the
+ * optimum table and columns widths (true) or not (false).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bAutoWidth": null,
+
+ /**
+ * Delay the creation of TR and TD elements until they are actually
+ * needed by a driven page draw. This can give a significant speed
+ * increase for Ajax source and Javascript source data, but makes no
+ * difference at all fro DOM and server-side processing tables.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bDeferRender": null,
+
+ /**
+ * Enable filtering on the table or not. Note that if this is disabled
+ * then there is no filtering at all on the table, including fnFilter.
+ * To just remove the filtering input use sDom and remove the 'f' option.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bFilter": null,
+
+ /**
+ * Table information element (the 'Showing x of y records' div) enable
+ * flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bInfo": null,
+
+ /**
+ * Present a user control allowing the end user to change the page size
+ * when pagination is enabled.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bLengthChange": null,
+
+ /**
+ * Pagination enabled or not. Note that if this is disabled then length
+ * changing must also be disabled.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bPaginate": null,
+
+ /**
+ * Processing indicator enable flag whenever DataTables is enacting a
+ * user request - typically an Ajax request for server-side processing.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bProcessing": null,
+
+ /**
+ * Server-side processing enabled flag - when enabled DataTables will
+ * get all data from the server for every draw - there is no filtering,
+ * sorting or paging done on the client-side.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bServerSide": null,
+
+ /**
+ * Sorting enablement flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSort": null,
+
+ /**
+ * Apply a class to the columns which are being sorted to provide a
+ * visual highlight or not. This can slow things down when enabled since
+ * there is a lot of DOM interaction.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortClasses": null,
+
+ /**
+ * State saving enablement flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bStateSave": null
+ },
+
+
+ /**
+ * Scrolling settings for a table.
+ * @namespace
+ */
+ "oScroll": {
+ /**
+ * Indicate if DataTables should be allowed to set the padding / margin
+ * etc for the scrolling header elements or not. Typically you will want
+ * this.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bAutoCss": null,
+
+ /**
+ * When the table is shorter in height than sScrollY, collapse the
+ * table container down to the height of the table (when true).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bCollapse": null,
+
+ /**
+ * Infinite scrolling enablement flag. Now deprecated in favour of
+ * using the Scroller plug-in.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bInfinite": null,
+
+ /**
+ * Width of the scrollbar for the web-browser's platform. Calculated
+ * during table initialisation.
+ * @type int
+ * @default 0
+ */
+ "iBarWidth": 0,
+
+ /**
+ * Space (in pixels) between the bottom of the scrolling container and
+ * the bottom of the scrolling viewport before the next page is loaded
+ * when using infinite scrolling.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type int
+ */
+ "iLoadGap": null,
+
+ /**
+ * Viewport width for horizontal scrolling. Horizontal scrolling is
+ * disabled if an empty string.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sX": null,
+
+ /**
+ * Width to expand the table to when using x-scrolling. Typically you
+ * should not need to use this.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @deprecated
+ */
+ "sXInner": null,
+
+ /**
+ * Viewport height for vertical scrolling. Vertical scrolling is disabled
+ * if an empty string.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sY": null
+ },
+
+ /**
+ * Language information for the table.
+ * @namespace
+ * @extends DataTable.defaults.oLanguage
+ */
+ "oLanguage": {
+ /**
+ * Information callback function. See
+ * {@link DataTable.defaults.fnInfoCallback}
+ * @type function
+ * @default null
+ */
+ "fnInfoCallback": null
+ },
+
+ /**
+ * Browser support parameters
+ * @namespace
+ */
+ "oBrowser": {
+ /**
+ * Indicate if the browser incorrectly calculates width:100% inside a
+ * scrolling element (IE6/7)
+ * @type boolean
+ * @default false
+ */
+ "bScrollOversize": false
+ },
+
+ /**
+ * Array referencing the nodes which are used for the features. The
+ * parameters of this object match what is allowed by sDom - i.e.
+ *
+ *
'l' - Length changing
+ *
'f' - Filtering input
+ *
't' - The table!
+ *
'i' - Information
+ *
'p' - Pagination
+ *
'r' - pRocessing
+ *
+ * @type array
+ * @default []
+ */
+ "aanFeatures": [],
+
+ /**
+ * Store data information - see {@link DataTable.models.oRow} for detailed
+ * information.
+ * @type array
+ * @default []
+ */
+ "aoData": [],
+
+ /**
+ * Array of indexes which are in the current display (after filtering etc)
+ * @type array
+ * @default []
+ */
+ "aiDisplay": [],
+
+ /**
+ * Array of indexes for display - no filtering
+ * @type array
+ * @default []
+ */
+ "aiDisplayMaster": [],
+
+ /**
+ * Store information about each column that is in use
+ * @type array
+ * @default []
+ */
+ "aoColumns": [],
+
+ /**
+ * Store information about the table's header
+ * @type array
+ * @default []
+ */
+ "aoHeader": [],
+
+ /**
+ * Store information about the table's footer
+ * @type array
+ * @default []
+ */
+ "aoFooter": [],
+
+ /**
+ * Search data array for regular expression searching
+ * @type array
+ * @default []
+ */
+ "asDataSearch": [],
+
+ /**
+ * Store the applied global search information in case we want to force a
+ * research or compare the old search to a new one.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @namespace
+ * @extends DataTable.models.oSearch
+ */
+ "oPreviousSearch": {},
+
+ /**
+ * Store the applied search for each column - see
+ * {@link DataTable.models.oSearch} for the format that is used for the
+ * filtering information for each column.
+ * @type array
+ * @default []
+ */
+ "aoPreSearchCols": [],
+
+ /**
+ * Sorting that is applied to the table. Note that the inner arrays are
+ * used in the following manner:
+ *
+ *
Index 0 - column number
+ *
Index 1 - current sorting direction
+ *
Index 2 - index of asSorting for this column
+ *
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @todo These inner arrays should really be objects
+ */
+ "aaSorting": null,
+
+ /**
+ * Sorting that is always applied to the table (i.e. prefixed in front of
+ * aaSorting).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array|null
+ * @default null
+ */
+ "aaSortingFixed": null,
+
+ /**
+ * Classes to use for the striping of a table.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "asStripeClasses": null,
+
+ /**
+ * If restoring a table - we should restore its striping classes as well
+ * @type array
+ * @default []
+ */
+ "asDestroyStripes": [],
+
+ /**
+ * If restoring a table - we should restore its width
+ * @type int
+ * @default 0
+ */
+ "sDestroyWidth": 0,
+
+ /**
+ * Callback functions array for every time a row is inserted (i.e. on a draw).
+ * @type array
+ * @default []
+ */
+ "aoRowCallback": [],
+
+ /**
+ * Callback functions for the header on each draw.
+ * @type array
+ * @default []
+ */
+ "aoHeaderCallback": [],
+
+ /**
+ * Callback function for the footer on each draw.
+ * @type array
+ * @default []
+ */
+ "aoFooterCallback": [],
+
+ /**
+ * Array of callback functions for draw callback functions
+ * @type array
+ * @default []
+ */
+ "aoDrawCallback": [],
+
+ /**
+ * Array of callback functions for row created function
+ * @type array
+ * @default []
+ */
+ "aoRowCreatedCallback": [],
+
+ /**
+ * Callback functions for just before the table is redrawn. A return of
+ * false will be used to cancel the draw.
+ * @type array
+ * @default []
+ */
+ "aoPreDrawCallback": [],
+
+ /**
+ * Callback functions for when the table has been initialised.
+ * @type array
+ * @default []
+ */
+ "aoInitComplete": [],
+
+
+ /**
+ * Callbacks for modifying the settings to be stored for state saving, prior to
+ * saving state.
+ * @type array
+ * @default []
+ */
+ "aoStateSaveParams": [],
+
+ /**
+ * Callbacks for modifying the settings that have been stored for state saving
+ * prior to using the stored values to restore the state.
+ * @type array
+ * @default []
+ */
+ "aoStateLoadParams": [],
+
+ /**
+ * Callbacks for operating on the settings object once the saved state has been
+ * loaded
+ * @type array
+ * @default []
+ */
+ "aoStateLoaded": [],
+
+ /**
+ * Cache the table ID for quick access
+ * @type string
+ * @default Empty string
+ */
+ "sTableId": "",
+
+ /**
+ * The TABLE node for the main table
+ * @type node
+ * @default null
+ */
+ "nTable": null,
+
+ /**
+ * Permanent ref to the thead element
+ * @type node
+ * @default null
+ */
+ "nTHead": null,
+
+ /**
+ * Permanent ref to the tfoot element - if it exists
+ * @type node
+ * @default null
+ */
+ "nTFoot": null,
+
+ /**
+ * Permanent ref to the tbody element
+ * @type node
+ * @default null
+ */
+ "nTBody": null,
+
+ /**
+ * Cache the wrapper node (contains all DataTables controlled elements)
+ * @type node
+ * @default null
+ */
+ "nTableWrapper": null,
+
+ /**
+ * Indicate if when using server-side processing the loading of data
+ * should be deferred until the second draw.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ * @default false
+ */
+ "bDeferLoading": false,
+
+ /**
+ * Indicate if all required information has been read in
+ * @type boolean
+ * @default false
+ */
+ "bInitialised": false,
+
+ /**
+ * Information about open rows. Each object in the array has the parameters
+ * 'nTr' and 'nParent'
+ * @type array
+ * @default []
+ */
+ "aoOpenRows": [],
+
+ /**
+ * Dictate the positioning of DataTables' control elements - see
+ * {@link DataTable.model.oInit.sDom}.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default null
+ */
+ "sDom": null,
+
+ /**
+ * Which type of pagination should be used.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default two_button
+ */
+ "sPaginationType": "two_button",
+
+ /**
+ * The cookie duration (for bStateSave) in seconds.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type int
+ * @default 0
+ */
+ "iCookieDuration": 0,
+
+ /**
+ * The cookie name prefix.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default Empty string
+ */
+ "sCookiePrefix": "",
+
+ /**
+ * Callback function for cookie creation.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type function
+ * @default null
+ */
+ "fnCookieCallback": null,
+
+ /**
+ * Array of callback functions for state saving. Each array element is an
+ * object with the following parameters:
+ *
+ *
function:fn - function to call. Takes two parameters, oSettings
+ * and the JSON string to save that has been thus far created. Returns
+ * a JSON string to be inserted into a json object
+ * (i.e. '"param": [ 0, 1, 2]')
+ *
string:sName - name of callback
+ *
+ * @type array
+ * @default []
+ */
+ "aoStateSave": [],
+
+ /**
+ * Array of callback functions for state loading. Each array element is an
+ * object with the following parameters:
+ *
+ *
function:fn - function to call. Takes two parameters, oSettings
+ * and the object stored. May return false to cancel state loading
+ *
string:sName - name of callback
+ *
+ * @type array
+ * @default []
+ */
+ "aoStateLoad": [],
+
+ /**
+ * State that was loaded from the cookie. Useful for back reference
+ * @type object
+ * @default null
+ */
+ "oLoadedState": null,
+
+ /**
+ * Source url for AJAX data for the table.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default null
+ */
+ "sAjaxSource": null,
+
+ /**
+ * Property from a given object from which to read the table data from. This
+ * can be an empty string (when not server-side processing), in which case
+ * it is assumed an an array is given directly.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sAjaxDataProp": null,
+
+ /**
+ * Note if draw should be blocked while getting data
+ * @type boolean
+ * @default true
+ */
+ "bAjaxDataGet": true,
+
+ /**
+ * The last jQuery XHR object that was used for server-side data gathering.
+ * This can be used for working with the XHR information in one of the
+ * callbacks
+ * @type object
+ * @default null
+ */
+ "jqXHR": null,
+
+ /**
+ * Function to get the server-side data.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type function
+ */
+ "fnServerData": null,
+
+ /**
+ * Functions which are called prior to sending an Ajax request so extra
+ * parameters can easily be sent to the server
+ * @type array
+ * @default []
+ */
+ "aoServerParams": [],
+
+ /**
+ * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
+ * required).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sServerMethod": null,
+
+ /**
+ * Format numbers for display.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type function
+ */
+ "fnFormatNumber": null,
+
+ /**
+ * List of options that can be used for the user selectable length menu.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "aLengthMenu": null,
+
+ /**
+ * Counter for the draws that the table does. Also used as a tracker for
+ * server-side processing
+ * @type int
+ * @default 0
+ */
+ "iDraw": 0,
+
+ /**
+ * Indicate if a redraw is being done - useful for Ajax
+ * @type boolean
+ * @default false
+ */
+ "bDrawing": false,
+
+ /**
+ * Draw index (iDraw) of the last error when parsing the returned data
+ * @type int
+ * @default -1
+ */
+ "iDrawError": -1,
+
+ /**
+ * Paging display length
+ * @type int
+ * @default 10
+ */
+ "_iDisplayLength": 10,
+
+ /**
+ * Paging start point - aiDisplay index
+ * @type int
+ * @default 0
+ */
+ "_iDisplayStart": 0,
+
+ /**
+ * Paging end point - aiDisplay index. Use fnDisplayEnd rather than
+ * this property to get the end point
+ * @type int
+ * @default 10
+ * @private
+ */
+ "_iDisplayEnd": 10,
+
+ /**
+ * Server-side processing - number of records in the result set
+ * (i.e. before filtering), Use fnRecordsTotal rather than
+ * this property to get the value of the number of records, regardless of
+ * the server-side processing setting.
+ * @type int
+ * @default 0
+ * @private
+ */
+ "_iRecordsTotal": 0,
+
+ /**
+ * Server-side processing - number of records in the current display set
+ * (i.e. after filtering). Use fnRecordsDisplay rather than
+ * this property to get the value of the number of records, regardless of
+ * the server-side processing setting.
+ * @type boolean
+ * @default 0
+ * @private
+ */
+ "_iRecordsDisplay": 0,
+
+ /**
+ * Flag to indicate if jQuery UI marking and classes should be used.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bJUI": null,
+
+ /**
+ * The classes to use for the table
+ * @type object
+ * @default {}
+ */
+ "oClasses": {},
+
+ /**
+ * Flag attached to the settings object so you can check in the draw
+ * callback if filtering has been done in the draw. Deprecated in favour of
+ * events.
+ * @type boolean
+ * @default false
+ * @deprecated
+ */
+ "bFiltered": false,
+
+ /**
+ * Flag attached to the settings object so you can check in the draw
+ * callback if sorting has been done in the draw. Deprecated in favour of
+ * events.
+ * @type boolean
+ * @default false
+ * @deprecated
+ */
+ "bSorted": false,
+
+ /**
+ * Indicate that if multiple rows are in the header and there is more than
+ * one unique cell per column, if the top one (true) or bottom one (false)
+ * should be used for sorting / title by DataTables.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortCellsTop": null,
+
+ /**
+ * Initialisation object that is used for the table
+ * @type object
+ * @default null
+ */
+ "oInit": null,
+
+ /**
+ * Destroy callback functions - for plug-ins to attach themselves to the
+ * destroy so they can clean up markup and events.
+ * @type array
+ * @default []
+ */
+ "aoDestroyCallback": [],
+
+
+ /**
+ * Get the number of records in the current record set, before filtering
+ * @type function
+ */
+ "fnRecordsTotal": function ()
+ {
+ if ( this.oFeatures.bServerSide ) {
+ return parseInt(this._iRecordsTotal, 10);
+ } else {
+ return this.aiDisplayMaster.length;
+ }
+ },
+
+ /**
+ * Get the number of records in the current record set, after filtering
+ * @type function
+ */
+ "fnRecordsDisplay": function ()
+ {
+ if ( this.oFeatures.bServerSide ) {
+ return parseInt(this._iRecordsDisplay, 10);
+ } else {
+ return this.aiDisplay.length;
+ }
+ },
+
+ /**
+ * Set the display end point - aiDisplay index
+ * @type function
+ * @todo Should do away with _iDisplayEnd and calculate it on-the-fly here
+ */
+ "fnDisplayEnd": function ()
+ {
+ if ( this.oFeatures.bServerSide ) {
+ if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) {
+ return this._iDisplayStart+this.aiDisplay.length;
+ } else {
+ return Math.min( this._iDisplayStart+this._iDisplayLength,
+ this._iRecordsDisplay );
+ }
+ } else {
+ return this._iDisplayEnd;
+ }
+ },
+
+ /**
+ * The DataTables object for this table
+ * @type object
+ * @default null
+ */
+ "oInstance": null,
+
+ /**
+ * Unique identifier for each instance of the DataTables object. If there
+ * is an ID on the table node, then it takes that value, otherwise an
+ * incrementing internal counter is used.
+ * @type string
+ * @default null
+ */
+ "sInstance": null,
+
+ /**
+ * tabindex attribute value that is added to DataTables control elements, allowing
+ * keyboard navigation of the table and its controls.
+ */
+ "iTabIndex": 0,
+
+ /**
+ * DIV container for the footer scrolling table if scrolling
+ */
+ "nScrollHead": null,
+
+ /**
+ * DIV container for the footer scrolling table if scrolling
+ */
+ "nScrollFoot": null
+ };
+
+ /**
+ * Extension object for DataTables that is used to provide all extension options.
+ *
+ * Note that the DataTable.ext object is available through
+ * jQuery.fn.dataTable.ext where it may be accessed and manipulated. It is
+ * also aliased to jQuery.fn.dataTableExt for historic reasons.
+ * @namespace
+ * @extends DataTable.models.ext
+ */
+ DataTable.ext = $.extend( true, {}, DataTable.models.ext );
+
+ $.extend( DataTable.ext.oStdClasses, {
+ "sTable": "dataTable",
+
+ /* Two buttons buttons */
+ "sPagePrevEnabled": "paginate_enabled_previous",
+ "sPagePrevDisabled": "paginate_disabled_previous",
+ "sPageNextEnabled": "paginate_enabled_next",
+ "sPageNextDisabled": "paginate_disabled_next",
+ "sPageJUINext": "",
+ "sPageJUIPrev": "",
+
+ /* Full numbers paging buttons */
+ "sPageButton": "paginate_button",
+ "sPageButtonActive": "paginate_active",
+ "sPageButtonStaticDisabled": "paginate_button paginate_button_disabled",
+ "sPageFirst": "first",
+ "sPagePrevious": "previous",
+ "sPageNext": "next",
+ "sPageLast": "last",
+
+ /* Striping classes */
+ "sStripeOdd": "odd",
+ "sStripeEven": "even",
+
+ /* Empty row */
+ "sRowEmpty": "dataTables_empty",
+
+ /* Features */
+ "sWrapper": "dataTables_wrapper",
+ "sFilter": "dataTables_filter",
+ "sInfo": "dataTables_info",
+ "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
+ "sLength": "dataTables_length",
+ "sProcessing": "dataTables_processing",
+
+ /* Sorting */
+ "sSortAsc": "sorting_asc",
+ "sSortDesc": "sorting_desc",
+ "sSortable": "sorting", /* Sortable in both directions */
+ "sSortableAsc": "sorting_asc_disabled",
+ "sSortableDesc": "sorting_desc_disabled",
+ "sSortableNone": "sorting_disabled",
+ "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
+ "sSortJUIAsc": "",
+ "sSortJUIDesc": "",
+ "sSortJUI": "",
+ "sSortJUIAscAllowed": "",
+ "sSortJUIDescAllowed": "",
+ "sSortJUIWrapper": "",
+ "sSortIcon": "",
+
+ /* Scrolling */
+ "sScrollWrapper": "dataTables_scroll",
+ "sScrollHead": "dataTables_scrollHead",
+ "sScrollHeadInner": "dataTables_scrollHeadInner",
+ "sScrollBody": "dataTables_scrollBody",
+ "sScrollFoot": "dataTables_scrollFoot",
+ "sScrollFootInner": "dataTables_scrollFootInner",
+
+ /* Misc */
+ "sFooterTH": "",
+ "sJUIHeader": "",
+ "sJUIFooter": ""
+ } );
+
+
+ $.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {
+ /* Two buttons buttons */
+ "sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left",
+ "sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
+ "sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right",
+ "sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
+ "sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
+ "sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
+
+ /* Full numbers paging buttons */
+ "sPageButton": "fg-button ui-button ui-state-default",
+ "sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled",
+ "sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled",
+ "sPageFirst": "first ui-corner-tl ui-corner-bl",
+ "sPageLast": "last ui-corner-tr ui-corner-br",
+
+ /* Features */
+ "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
+ "ui-buttonset-multi paging_", /* Note that the type is postfixed */
+
+ /* Sorting */
+ "sSortAsc": "ui-state-default",
+ "sSortDesc": "ui-state-default",
+ "sSortable": "ui-state-default",
+ "sSortableAsc": "ui-state-default",
+ "sSortableDesc": "ui-state-default",
+ "sSortableNone": "ui-state-default",
+ "sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
+ "sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
+ "sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s",
+ "sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n",
+ "sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s",
+ "sSortJUIWrapper": "DataTables_sort_wrapper",
+ "sSortIcon": "DataTables_sort_icon",
+
+ /* Scrolling */
+ "sScrollHead": "dataTables_scrollHead ui-state-default",
+ "sScrollFoot": "dataTables_scrollFoot ui-state-default",
+
+ /* Misc */
+ "sFooterTH": "ui-state-default",
+ "sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",
+ "sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"
+ } );
+
+ /*
+ * Variable: oPagination
+ * Purpose:
+ * Scope: jQuery.fn.dataTableExt
+ */
+ $.extend( DataTable.ext.oPagination, {
+ /*
+ * Variable: two_button
+ * Purpose: Standard two button (forward/back) pagination
+ * Scope: jQuery.fn.dataTableExt.oPagination
+ */
+ "two_button": {
+ /*
+ * Function: oPagination.two_button.fnInit
+ * Purpose: Initialise dom elements required for pagination with forward/back buttons only
+ * Returns: -
+ * Inputs: object:oSettings - dataTables settings object
+ * node:nPaging - the DIV which contains this pagination control
+ * function:fnCallbackDraw - draw function which must be called on update
+ */
+ "fnInit": function ( oSettings, nPaging, fnCallbackDraw )
+ {
+ var oLang = oSettings.oLanguage.oPaginate;
+ var oClasses = oSettings.oClasses;
+ var fnClickHandler = function ( e ) {
+ if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
+ {
+ fnCallbackDraw( oSettings );
+ }
+ };
+
+ var sAppend = (!oSettings.bJUI) ?
+ ''+oLang.sPrevious+''+
+ ''+oLang.sNext+''
+ :
+ ''+
+ '';
+ $(nPaging).append( sAppend );
+
+ var els = $('a', nPaging);
+ var nPrevious = els[0],
+ nNext = els[1];
+
+ oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler );
+ oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
+
+ /* ID the first elements only */
+ if ( !oSettings.aanFeatures.p )
+ {
+ nPaging.id = oSettings.sTableId+'_paginate';
+ nPrevious.id = oSettings.sTableId+'_previous';
+ nNext.id = oSettings.sTableId+'_next';
+
+ nPrevious.setAttribute('aria-controls', oSettings.sTableId);
+ nNext.setAttribute('aria-controls', oSettings.sTableId);
+ }
+ },
+
+ /*
+ * Function: oPagination.two_button.fnUpdate
+ * Purpose: Update the two button pagination at the end of the draw
+ * Returns: -
+ * Inputs: object:oSettings - dataTables settings object
+ * function:fnCallbackDraw - draw function to call on page change
+ */
+ "fnUpdate": function ( oSettings, fnCallbackDraw )
+ {
+ if ( !oSettings.aanFeatures.p )
+ {
+ return;
+ }
+
+ var oClasses = oSettings.oClasses;
+ var an = oSettings.aanFeatures.p;
+ var nNode;
+
+ /* Loop over each instance of the pager */
+ for ( var i=0, iLen=an.length ; i'+oLang.sFirst+''+
+ ''+oLang.sPrevious+''+
+ ''+
+ ''+oLang.sNext+''+
+ ''+oLang.sLast+''
+ );
+ var els = $('a', nPaging);
+ var nFirst = els[0],
+ nPrev = els[1],
+ nNext = els[2],
+ nLast = els[3];
+
+ oSettings.oApi._fnBindAction( nFirst, {action: "first"}, fnClickHandler );
+ oSettings.oApi._fnBindAction( nPrev, {action: "previous"}, fnClickHandler );
+ oSettings.oApi._fnBindAction( nNext, {action: "next"}, fnClickHandler );
+ oSettings.oApi._fnBindAction( nLast, {action: "last"}, fnClickHandler );
+
+ /* ID the first elements only */
+ if ( !oSettings.aanFeatures.p )
+ {
+ nPaging.id = oSettings.sTableId+'_paginate';
+ nFirst.id =oSettings.sTableId+'_first';
+ nPrev.id =oSettings.sTableId+'_previous';
+ nNext.id =oSettings.sTableId+'_next';
+ nLast.id =oSettings.sTableId+'_last';
+ }
+ },
+
+ /*
+ * Function: oPagination.full_numbers.fnUpdate
+ * Purpose: Update the list of page buttons shows
+ * Returns: -
+ * Inputs: object:oSettings - dataTables settings object
+ * function:fnCallbackDraw - draw function to call on page change
+ */
+ "fnUpdate": function ( oSettings, fnCallbackDraw )
+ {
+ if ( !oSettings.aanFeatures.p )
+ {
+ return;
+ }
+
+ var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;
+ var iPageCountHalf = Math.floor(iPageCount / 2);
+ var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
+ var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
+ var sList = "";
+ var iStartButton, iEndButton, i, iLen;
+ var oClasses = oSettings.oClasses;
+ var anButtons, anStatic, nPaginateList, nNode;
+ var an = oSettings.aanFeatures.p;
+ var fnBind = function (j) {
+ oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) {
+ /* Use the information in the element to jump to the required page */
+ oSettings.oApi._fnPageChange( oSettings, e.data.page );
+ fnCallbackDraw( oSettings );
+ e.preventDefault();
+ } );
+ };
+
+ /* Pages calculation */
+ if ( oSettings._iDisplayLength === -1 )
+ {
+ iStartButton = 1;
+ iEndButton = 1;
+ iCurrentPage = 1;
+ }
+ else if (iPages < iPageCount)
+ {
+ iStartButton = 1;
+ iEndButton = iPages;
+ }
+ else if (iCurrentPage <= iPageCountHalf)
+ {
+ iStartButton = 1;
+ iEndButton = iPageCount;
+ }
+ else if (iCurrentPage >= (iPages - iPageCountHalf))
+ {
+ iStartButton = iPages - iPageCount + 1;
+ iEndButton = iPages;
+ }
+ else
+ {
+ iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
+ iEndButton = iStartButton + iPageCount - 1;
+ }
+
+
+ /* Build the dynamic list */
+ for ( i=iStartButton ; i<=iEndButton ; i++ )
+ {
+ sList += (iCurrentPage !== i) ?
+ ''+oSettings.fnFormatNumber(i)+'' :
+ ''+oSettings.fnFormatNumber(i)+'';
+ }
+
+ /* Loop over each instance of the pager */
+ for ( i=0, iLen=an.length ; i y) ? 1 : 0));
+ },
+
+ "string-desc": function ( x, y )
+ {
+ return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ },
+
+
+ /*
+ * html sorting (ignore html tags)
+ */
+ "html-pre": function ( a )
+ {
+ return a.replace( /<.*?>/g, "" ).toLowerCase();
+ },
+
+ "html-asc": function ( x, y )
+ {
+ return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ },
+
+ "html-desc": function ( x, y )
+ {
+ return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ },
+
+
+ /*
+ * date sorting
+ */
+ "date-pre": function ( a )
+ {
+ var x = Date.parse( a );
+
+ if ( isNaN(x) || x==="" )
+ {
+ x = Date.parse( "01/01/1970 00:00:00" );
+ }
+ return x;
+ },
+
+ "date-asc": function ( x, y )
+ {
+ return x - y;
+ },
+
+ "date-desc": function ( x, y )
+ {
+ return y - x;
+ },
+
+
+ /*
+ * numerical sorting
+ */
+ "numeric-pre": function ( a )
+ {
+ return (a=="-" || a==="") ? 0 : a*1;
+ },
+
+ "numeric-asc": function ( x, y )
+ {
+ return x - y;
+ },
+
+ "numeric-desc": function ( x, y )
+ {
+ return y - x;
+ }
+ } );
+
+
+ $.extend( DataTable.ext.aTypes, [
+ /*
+ * Function: -
+ * Purpose: Check to see if a string is numeric
+ * Returns: string:'numeric' or null
+ * Inputs: mixed:sText - string to check
+ */
+ function ( sData )
+ {
+ /* Allow zero length strings as a number */
+ if ( typeof sData === 'number' )
+ {
+ return 'numeric';
+ }
+ else if ( typeof sData !== 'string' )
+ {
+ return null;
+ }
+
+ var sValidFirstChars = "0123456789-";
+ var sValidChars = "0123456789.";
+ var Char;
+ var bDecimal = false;
+
+ /* Check for a valid first char (no period and allow negatives) */
+ Char = sData.charAt(0);
+ if (sValidFirstChars.indexOf(Char) == -1)
+ {
+ return null;
+ }
+
+ /* Check all the other characters are valid */
+ for ( var i=1 ; i') != -1 )
+ {
+ return 'html';
+ }
+ return null;
+ }
+ ] );
+
+
+ // jQuery aliases
+ $.fn.DataTable = DataTable;
+ $.fn.dataTable = DataTable;
+ $.fn.dataTableSettings = DataTable.settings;
+ $.fn.dataTableExt = DataTable.ext;
+
+
+ // Information about events fired by DataTables - for documentation.
+ /**
+ * Draw event, fired whenever the table is redrawn on the page, at the same point as
+ * fnDrawCallback. This may be useful for binding events or performing calculations when
+ * the table is altered at all.
+ * @name DataTable#draw
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Filter event, fired when the filtering applied to the table (using the build in global
+ * global filter, or column filters) is altered.
+ * @name DataTable#filter
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Page change event, fired when the paging of the table is altered.
+ * @name DataTable#page
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Sort event, fired when the sorting applied to the table is altered.
+ * @name DataTable#sort
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * DataTables initialisation complete event, fired when the table is fully drawn,
+ * including Ajax data loaded, if Ajax data is required.
+ * @name DataTable#init
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The JSON object request from the server - only
+ * present if client-side Ajax sourced data is used
+ */
+
+ /**
+ * State save event, fired when the table has changed state a new state save is required.
+ * This method allows modification of the state saving object prior to actually doing the
+ * save, including addition or other state properties (for plug-ins) or modification
+ * of a DataTables core property.
+ * @name DataTable#stateSaveParams
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The state information to be saved
+ */
+
+ /**
+ * State load event, fired when the table is loading state from the stored data, but
+ * prior to the settings object being modified by the saved state - allowing modification
+ * of the saved state is required or loading of state for a plug-in.
+ * @name DataTable#stateLoadParams
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The saved state information
+ */
+
+ /**
+ * State loaded event, fired when state has been loaded from stored data and the settings
+ * object has been modified by the loaded data.
+ * @name DataTable#stateLoaded
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The saved state information
+ */
+
+ /**
+ * Processing event, fired when DataTables is doing some kind of processing (be it,
+ * sort, filter or anything else). Can be used to indicate to the end user that
+ * there is something happening, or that something has finished.
+ * @name DataTable#processing
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {boolean} bShow Flag for if DataTables is doing processing or not
+ */
+
+ /**
+ * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to
+ * made to the server for new data (note that this trigger is called in fnServerData,
+ * if you override fnServerData and which to use this event, you need to trigger it in
+ * you success function).
+ * @name DataTable#xhr
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ * @param {object} json JSON returned from the server
+ */
+
+ /**
+ * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
+ * the bDestroy:true parameter in the initialisation object. This can be used to remove
+ * bound events, added DOM nodes, etc.
+ * @name DataTable#destroy
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+}));
+
+}(window, document));
+
diff --git a/common/src/main/webapp/thirdparty/data-tables/jquery.dataTables-1.9.4.min.js b/common/src/main/webapp/thirdparty/data-tables/jquery.dataTables-1.9.4.min.js
new file mode 100644
index 0000000..02694a4
--- /dev/null
+++ b/common/src/main/webapp/thirdparty/data-tables/jquery.dataTables-1.9.4.min.js
@@ -0,0 +1,155 @@
+/*
+ * File: jquery.dataTables.min.js
+ * Version: 1.9.4
+ * Author: Allan Jardine (www.sprymedia.co.uk)
+ * Info: www.datatables.net
+ *
+ * Copyright 2008-2012 Allan Jardine, all rights reserved.
+ *
+ * This source file is free software, under either the GPL v2 license or a
+ * BSD style license, available at:
+ * http://datatables.net/license_gpl2
+ * http://datatables.net/license_bsd
+ *
+ * This source file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
+ */
+(function(X,l,n){var L=function(h){var j=function(e){function o(a,b){var c=j.defaults.columns,d=a.aoColumns.length,c=h.extend({},j.models.oColumn,c,{sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,nTh:b?b:l.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.oDefaults:d});a.aoColumns.push(c);if(a.aoPreSearchCols[d]===n||null===a.aoPreSearchCols[d])a.aoPreSearchCols[d]=h.extend({},j.models.oSearch);else if(c=a.aoPreSearchCols[d],
+c.bRegex===n&&(c.bRegex=!0),c.bSmart===n&&(c.bSmart=!0),c.bCaseInsensitive===n)c.bCaseInsensitive=!0;m(a,d,null)}function m(a,b,c){var d=a.aoColumns[b];c!==n&&null!==c&&(c.mDataProp&&!c.mData&&(c.mData=c.mDataProp),c.sType!==n&&(d.sType=c.sType,d._bAutoType=!1),h.extend(d,c),p(d,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(d.aDataSort=[c.iDataSort]),p(d,c,"aDataSort"));var i=d.mRender?Q(d.mRender):null,f=Q(d.mData);d.fnGetData=function(a,b){var c=f(a,b);return d.mRender&&b&&""!==b?i(c,b,a):c};d.fnSetData=
+L(d.mData);a.oFeatures.bSort||(d.bSortable=!1);!d.bSortable||-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableNone,d.sSortingClassJUI=""):-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortable,d.sSortingClassJUI=a.oClasses.sSortJUI):-1!=h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableAsc,d.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed):-1==
+h.inArray("asc",d.asSorting)&&-1!=h.inArray("desc",d.asSorting)&&(d.sSortingClass=a.oClasses.sSortableDesc,d.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed)}function k(a){if(!1===a.oFeatures.bAutoWidth)return!1;da(a);for(var b=0,c=a.aoColumns.length;bj[f])d(a.aoColumns.length+j[f],b[i]);else if("string"===typeof j[f]){e=0;for(w=a.aoColumns.length;eb&&a[d]--; -1!=c&&a.splice(c,1)}function S(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mData},v(a,b,c,"display"))}function ea(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&&
+(c.nTr.className=c._aData.DT_RowClass);for(var i=0,f=a.aoColumns.length;i=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,y(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var g=
+a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(g=0,d=a.aoData.length);for(;g")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=h('')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),i,f,g,e,w,o,k,m=0;m")[0];w=d[m+
+1];if("'"==w||'"'==w){o="";for(k=2;d[m+k]!=w;)o+=d[m+k],k++;"H"==o?o=a.oClasses.sJUIHeader:"F"==o&&(o=a.oClasses.sJUIFooter);-1!=o.indexOf(".")?(w=o.split("."),e.id=w[0].substr(1,w[0].length-1),e.className=w[1]):"#"==o.charAt(0)?e.id=o.substr(1,o.length-1):e.className=o;m+=k}c.appendChild(e);c=e}else if(">"==g)c=c.parentNode;else if("l"==g&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)i=ya(a),f=1;else if("f"==g&&a.oFeatures.bFilter)i=za(a),f=1;else if("r"==g&&a.oFeatures.bProcessing)i=Aa(a),f=
+1;else if("t"==g)i=Ba(a),f=1;else if("i"==g&&a.oFeatures.bInfo)i=Ca(a),f=1;else if("p"==g&&a.oFeatures.bPaginate)i=Da(a),f=1;else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;k=0;for(w=e.length;k'):""===c?'':c+' ',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=h('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"""));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value,
+g=0,e=c.length;g=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||i.sSearch.length>b.length||1==c||0!==b.indexOf(i.sSearch)){a.aiDisplay.splice(0,
+a.aiDisplay.length);la(a,1);for(b=0;b").html(c).text());
+return c.replace(/[\n\r]/g," ")}function ma(a,b,c,d){if(c)return a=b?a.split(" "):oa(a).split(" "),a="^(?=.*?"+a.join(")(?=.*?")+").*$",RegExp(a,d?"i":"");a=b?a:oa(a);return RegExp(a,d?"i":"")}function Ja(a,b){return"function"===typeof j.ext.ofnSearch[b]?j.ext.ofnSearch[b](a):null===a?"":"html"==b?a.replace(/[\r\n]/g," ").replace(/<.*?>/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function oa(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),
+"\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ka,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ka(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),i=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),g;g=0===f?b.sInfoEmpty:b.sInfo;f!=i&&(g+=" "+b.sInfoFiltered);g+=b.sInfoPostFix;g=ja(a,g);
+null!==b.fnInfoCallback&&(g=b.fnInfoCallback.call(a.oInstance,a,c,d,i,f,g));a=a.aanFeatures.i;b=0;for(c=a.length;b",c,d,i=a.aLengthMenu;if(2==i.length&&"object"===typeof i[0]&&"object"===typeof i[1]){c=0;for(d=i[0].length;c'+i[1][c]+""}else{c=0;for(d=i.length;c'+i[c]+""}b+="";i=l.createElement("div");a.aanFeatures.l||
+(i.id=a.sTableId+"_length");i.className=a.oClasses.sLength;i.innerHTML="";h('select option[value="'+a._iDisplayLength+'"]',i).attr("selected",!0);h("select",i).bind("change.DT",function(){var b=h(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;ca.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;j.ext.oPagination[a.sPaginationType].fnInit(a,
+b,function(a){y(a);x(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){y(a);x(a)})},sName:"pagination"});return b}function qa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart=
+0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLengthh(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(h(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width=
+q(a.oScroll.sXInner):i==h(d).width()&&h(d).height()i-a.oScroll.iBarWidth&&(a.nTable.style.width=q(i))):a.nTable.style.width=q(i);i=h(a.nTable).outerWidth();C(s,e);C(function(a){p.push(q(h(a).width()))},e);C(function(a,b){a.style.width=p[b]},g);h(e).height(0);null!==a.nTFoot&&(C(s,j),C(function(a){n.push(q(h(a).width()))},j),C(function(a,b){a.style.width=n[b]},o),h(j).height(0));C(function(a,b){a.innerHTML=
+"";a.style.width=p[b]},e);null!==a.nTFoot&&C(function(a,b){a.innerHTML="";a.style.width=n[b]},j);if(h(a.nTable).outerWidth()d.offsetHeight||"scroll"==h(d).css("overflow-y")?i+a.oScroll.iBarWidth:i;if(r&&(d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(g-a.oScroll.iBarWidth);d.style.width=q(g);a.nScrollHead.style.width=q(g);null!==a.nTFoot&&(a.nScrollFoot.style.width=q(g));""===a.oScroll.sX?D(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."):
+""!==a.oScroll.sXInner&&D(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),a.nScrollHead.style.width=q("100%"),null!==a.nTFoot&&(a.nScrollFoot.style.width=q("100%"));""===a.oScroll.sY&&r&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),r=""!==a.oScroll.sX&&a.nTable.offsetWidth>
+d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeightd.clientHeight||"scroll"==h(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px";null!==a.nTFoot&&(R.style.width=q(r),l.style.width=q(r),l.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");h(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function C(a,b,c){for(var d=
+0,i=0,f=b.length,g,e;itd",b));j=N(a,f);for(f=d=0;fc)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=v(a,c,b,"");return d}return J(a,c)[b]}function Pa(a,b){for(var c=-1,d=-1,i=0;i/g,"");e.length>c&&(c=e.length,d=i)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1);
+return 48>b||57/g,""),i=q[c].nTh,i.removeAttribute("aria-sort"),i.removeAttribute("aria-label"),q[c].bSortable?0d&&d++;f=RegExp(f+"[123]");var o;b=0;for(c=a.length;b
';
+ nSizer.style.width = footerWidths[i];
+ }, footerSrcEls );
+ }
+
+ // Sanity check that the table is of a sensible width. If not then we are going to get
+ // misalignment - try to prevent this by not allowing the table to shrink below its min width
+ if ( table.outerWidth() < sanityWidth )
+ {
+ // The min width depends upon if we have a vertical scrollbar visible or not */
+ correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
+ divBody.css('overflow-y') == "scroll")) ?
+ sanityWidth+barWidth :
+ sanityWidth;
+
+ // IE6/7 are a law unto themselves...
+ if ( ie67 && (divBodyEl.scrollHeight >
+ divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
+ ) {
+ tableStyle.width = _fnStringToCss( correction-barWidth );
+ }
+
+ // And give the user a warning that we've stopped the table getting too small
+ if ( scrollX === "" || scrollXInner !== "" ) {
+ _fnLog( settings, 1, 'Possible column misalignment', 6 );
+ }
+ }
+ else
+ {
+ correction = '100%';
+ }
+
+ // Apply to the container elements
+ divBodyStyle.width = _fnStringToCss( correction );
+ divHeaderStyle.width = _fnStringToCss( correction );
+
+ if ( footer ) {
+ settings.nScrollFoot.style.width = _fnStringToCss( correction );
+ }
+
+
+ /*
+ * 4. Clean up
+ */
+ if ( ! scrollY ) {
+ /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
+ * the scrollbar height from the visible display, rather than adding it on. We need to
+ * set the height in order to sort this. Don't want to do it in any other browsers.
+ */
+ if ( ie67 ) {
+ divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
+ }
+ }
+
+ /* Finally set the width's of the header and footer tables */
+ var iOuterWidth = table.outerWidth();
+ divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
+ divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
+
+ // Figure out if there are scrollbar present - if so then we need a the header and footer to
+ // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
+ var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
+ var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
+ divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
+
+ if ( footer ) {
+ divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
+ divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
+ divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
+ }
+
+ // Correct DOM ordering for colgroup - comes before the thead
+ table.children('colgroup').insertBefore( table.children('thead') );
+
+ /* Adjust the position of the header in case we loose the y-scrollbar */
+ divBody.scroll();
+
+ // If sorting or filtering has occurred, jump the scrolling back to the top
+ // only if we aren't holding the position
+ if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
+ divBodyEl.scrollTop = 0;
+ }
+ }
+
+
+
+ /**
+ * Apply a given function to the display child nodes of an element array (typically
+ * TD children of TR rows
+ * @param {function} fn Method to apply to the objects
+ * @param array {nodes} an1 List of elements to look through for display children
+ * @param array {nodes} an2 Another list (identical structure to the first) - optional
+ * @memberof DataTable#oApi
+ */
+ function _fnApplyToChildren( fn, an1, an2 )
+ {
+ var index=0, i=0, iLen=an1.length;
+ var nNode1, nNode2;
+
+ while ( i < iLen ) {
+ nNode1 = an1[i].firstChild;
+ nNode2 = an2 ? an2[i].firstChild : null;
+
+ while ( nNode1 ) {
+ if ( nNode1.nodeType === 1 ) {
+ if ( an2 ) {
+ fn( nNode1, nNode2, index );
+ }
+ else {
+ fn( nNode1, index );
+ }
+
+ index++;
+ }
+
+ nNode1 = nNode1.nextSibling;
+ nNode2 = an2 ? nNode2.nextSibling : null;
+ }
+
+ i++;
+ }
+ }
+
+
+
+ var __re_html_remove = /<.*?>/g;
+
+
+ /**
+ * Calculate the width of columns for the table
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnCalculateColumnWidths ( oSettings )
+ {
+ var
+ table = oSettings.nTable,
+ columns = oSettings.aoColumns,
+ scroll = oSettings.oScroll,
+ scrollY = scroll.sY,
+ scrollX = scroll.sX,
+ scrollXInner = scroll.sXInner,
+ columnCount = columns.length,
+ visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
+ headerCells = $('th', oSettings.nTHead),
+ tableWidthAttr = table.getAttribute('width'), // from DOM element
+ tableContainer = table.parentNode,
+ userInputs = false,
+ i, column, columnIdx, width, outerWidth,
+ browser = oSettings.oBrowser,
+ ie67 = browser.bScrollOversize;
+
+ var styleWidth = table.style.width;
+ if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
+ tableWidthAttr = styleWidth;
+ }
+
+ /* Convert any user input sizes into pixel sizes */
+ for ( i=0 ; i').appendTo( tmpTable.find('tbody') );
+
+ // Clone the table header and footer - we can't use the header / footer
+ // from the cloned table, since if scrolling is active, the table's
+ // real header and footer are contained in different table tags
+ tmpTable.find('thead, tfoot').remove();
+ tmpTable
+ .append( $(oSettings.nTHead).clone() )
+ .append( $(oSettings.nTFoot).clone() );
+
+ // Remove any assigned widths from the footer (from scrolling)
+ tmpTable.find('tfoot th, tfoot td').css('width', '');
+
+ // Apply custom sizing to the cloned header
+ headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
+
+ for ( i=0 ; i').css( {
+ width: column.sWidthOrig,
+ margin: 0,
+ padding: 0,
+ border: 0,
+ height: 1
+ } ) );
+ }
+ }
+
+ // Find the widest cell for each column and put it into the table
+ if ( oSettings.aoData.length ) {
+ for ( i=0 ; i').css( scrollX || scrollY ?
+ {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ height: 1,
+ right: 0,
+ overflow: 'hidden'
+ } :
+ {}
+ )
+ .append( tmpTable )
+ .appendTo( tableContainer );
+
+ // When scrolling (X or Y) we want to set the width of the table as
+ // appropriate. However, when not scrolling leave the table width as it
+ // is. This results in slightly different, but I think correct behaviour
+ if ( scrollX && scrollXInner ) {
+ tmpTable.width( scrollXInner );
+ }
+ else if ( scrollX ) {
+ tmpTable.css( 'width', 'auto' );
+ tmpTable.removeAttr('width');
+
+ // If there is no width attribute or style, then allow the table to
+ // collapse
+ if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
+ tmpTable.width( tableContainer.clientWidth );
+ }
+ }
+ else if ( scrollY ) {
+ tmpTable.width( tableContainer.clientWidth );
+ }
+ else if ( tableWidthAttr ) {
+ tmpTable.width( tableWidthAttr );
+ }
+
+ // Get the width of each column in the constructed table - we need to
+ // know the inner width (so it can be assigned to the other table's
+ // cells) and the outer width so we can calculate the full width of the
+ // table. This is safe since DataTables requires a unique cell for each
+ // column, but if ever a header can span multiple columns, this will
+ // need to be modified.
+ var total = 0;
+ for ( i=0 ; i')
+ .css( 'width', _fnStringToCss( width ) )
+ .appendTo( parent || document.body );
+
+ var val = n[0].offsetWidth;
+ n.remove();
+
+ return val;
+ }
+
+
+ /**
+ * Get the widest node
+ * @param {object} settings dataTables settings object
+ * @param {int} colIdx column of interest
+ * @returns {node} widest table node
+ * @memberof DataTable#oApi
+ */
+ function _fnGetWidestNode( settings, colIdx )
+ {
+ var idx = _fnGetMaxLenString( settings, colIdx );
+ if ( idx < 0 ) {
+ return null;
+ }
+
+ var data = settings.aoData[ idx ];
+ return ! data.nTr ? // Might not have been created when deferred rendering
+ $('
').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
+ data.anCells[ colIdx ];
+ }
+
+
+ /**
+ * Get the maximum strlen for each data column
+ * @param {object} settings dataTables settings object
+ * @param {int} colIdx column of interest
+ * @returns {string} max string length for each column
+ * @memberof DataTable#oApi
+ */
+ function _fnGetMaxLenString( settings, colIdx )
+ {
+ var s, max=-1, maxIdx = -1;
+
+ for ( var i=0, ien=settings.aoData.length ; i max ) {
+ max = s.length;
+ maxIdx = i;
+ }
+ }
+
+ return maxIdx;
+ }
+
+
+ /**
+ * Append a CSS unit (only if required) to a string
+ * @param {string} value to css-ify
+ * @returns {string} value with css unit
+ * @memberof DataTable#oApi
+ */
+ function _fnStringToCss( s )
+ {
+ if ( s === null ) {
+ return '0px';
+ }
+
+ if ( typeof s == 'number' ) {
+ return s < 0 ?
+ '0px' :
+ s+'px';
+ }
+
+ // Check it has a unit character already
+ return s.match(/\d$/) ?
+ s+'px' :
+ s;
+ }
+
+
+
+ function _fnSortFlatten ( settings )
+ {
+ var
+ i, iLen, k, kLen,
+ aSort = [],
+ aiOrig = [],
+ aoColumns = settings.aoColumns,
+ aDataSort, iCol, sType, srcCol,
+ fixed = settings.aaSortingFixed,
+ fixedObj = $.isPlainObject( fixed ),
+ nestedSort = [],
+ add = function ( a ) {
+ if ( a.length && ! $.isArray( a[0] ) ) {
+ // 1D array
+ nestedSort.push( a );
+ }
+ else {
+ // 2D array
+ $.merge( nestedSort, a );
+ }
+ };
+
+ // Build the sort array, with pre-fix and post-fix options if they have been
+ // specified
+ if ( $.isArray( fixed ) ) {
+ add( fixed );
+ }
+
+ if ( fixedObj && fixed.pre ) {
+ add( fixed.pre );
+ }
+
+ add( settings.aaSorting );
+
+ if (fixedObj && fixed.post ) {
+ add( fixed.post );
+ }
+
+ for ( i=0 ; iy ? 1 : 0;
+ if ( test !== 0 ) {
+ return sort.dir === 'asc' ? test : -test;
+ }
+ }
+
+ x = aiOrig[a];
+ y = aiOrig[b];
+ return xy ? 1 : 0;
+ } );
+ }
+ else {
+ // Depreciated - remove in 1.11 (providing a plug-in option)
+ // Not all sort types have formatting methods, so we have to call their sorting
+ // methods.
+ displayMaster.sort( function ( a, b ) {
+ var
+ x, y, k, l, test, sort, fn,
+ len=aSort.length,
+ dataA = aoData[a]._aSortData,
+ dataB = aoData[b]._aSortData;
+
+ for ( k=0 ; ky ? 1 : 0;
+ } );
+ }
+ }
+
+ /* Tell the draw function that we have sorted the data */
+ oSettings.bSorted = true;
+ }
+
+
+ function _fnSortAria ( settings )
+ {
+ var label;
+ var nextSort;
+ var columns = settings.aoColumns;
+ var aSort = _fnSortFlatten( settings );
+ var oAria = settings.oLanguage.oAria;
+
+ // ARIA attributes - need to loop all columns, to update all (removing old
+ // attributes as needed)
+ for ( var i=0, iLen=columns.length ; i/g, "" );
+ var th = col.nTh;
+
+ // IE7 is throwing an error when setting these properties with jQuery's
+ // attr() and removeAttr() methods...
+ th.removeAttribute('aria-sort');
+
+ /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
+ if ( col.bSortable ) {
+ if ( aSort.length > 0 && aSort[0].col == i ) {
+ th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
+ nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
+ }
+ else {
+ nextSort = asSorting[0];
+ }
+
+ label = sTitle + ( nextSort === "asc" ?
+ oAria.sSortAscending :
+ oAria.sSortDescending
+ );
+ }
+ else {
+ label = sTitle;
+ }
+
+ th.setAttribute('aria-label', label);
+ }
+ }
+
+
+ /**
+ * Function to run on user sort request
+ * @param {object} settings dataTables settings object
+ * @param {node} attachTo node to attach the handler to
+ * @param {int} colIdx column sorting index
+ * @param {boolean} [append=false] Append the requested sort to the existing
+ * sort if true (i.e. multi-column sort)
+ * @param {function} [callback] callback function
+ * @memberof DataTable#oApi
+ */
+ function _fnSortListener ( settings, colIdx, append, callback )
+ {
+ var col = settings.aoColumns[ colIdx ];
+ var sorting = settings.aaSorting;
+ var asSorting = col.asSorting;
+ var nextSortIdx;
+ var next = function ( a, overflow ) {
+ var idx = a._idx;
+ if ( idx === undefined ) {
+ idx = $.inArray( a[1], asSorting );
+ }
+
+ return idx+1 < asSorting.length ?
+ idx+1 :
+ overflow ?
+ null :
+ 0;
+ };
+
+ // Convert to 2D array if needed
+ if ( typeof sorting[0] === 'number' ) {
+ sorting = settings.aaSorting = [ sorting ];
+ }
+
+ // If appending the sort then we are multi-column sorting
+ if ( append && settings.oFeatures.bSortMulti ) {
+ // Are we already doing some kind of sort on this column?
+ var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
+
+ if ( sortIdx !== -1 ) {
+ // Yes, modify the sort
+ nextSortIdx = next( sorting[sortIdx], true );
+
+ if ( nextSortIdx === null && sorting.length === 1 ) {
+ nextSortIdx = 0; // can't remove sorting completely
+ }
+
+ if ( nextSortIdx === null ) {
+ sorting.splice( sortIdx, 1 );
+ }
+ else {
+ sorting[sortIdx][1] = asSorting[ nextSortIdx ];
+ sorting[sortIdx]._idx = nextSortIdx;
+ }
+ }
+ else {
+ // No sort on this column yet
+ sorting.push( [ colIdx, asSorting[0], 0 ] );
+ sorting[sorting.length-1]._idx = 0;
+ }
+ }
+ else if ( sorting.length && sorting[0][0] == colIdx ) {
+ // Single column - already sorting on this column, modify the sort
+ nextSortIdx = next( sorting[0] );
+
+ sorting.length = 1;
+ sorting[0][1] = asSorting[ nextSortIdx ];
+ sorting[0]._idx = nextSortIdx;
+ }
+ else {
+ // Single column - sort only on this column
+ sorting.length = 0;
+ sorting.push( [ colIdx, asSorting[0] ] );
+ sorting[0]._idx = 0;
+ }
+
+ // Run the sort by calling a full redraw
+ _fnReDraw( settings );
+
+ // callback used for async user interaction
+ if ( typeof callback == 'function' ) {
+ callback( settings );
+ }
+ }
+
+
+ /**
+ * Attach a sort handler (click) to a node
+ * @param {object} settings dataTables settings object
+ * @param {node} attachTo node to attach the handler to
+ * @param {int} colIdx column sorting index
+ * @param {function} [callback] callback function
+ * @memberof DataTable#oApi
+ */
+ function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
+ {
+ var col = settings.aoColumns[ colIdx ];
+
+ _fnBindAction( attachTo, {}, function (e) {
+ /* If the column is not sortable - don't to anything */
+ if ( col.bSortable === false ) {
+ return;
+ }
+
+ // If processing is enabled use a timeout to allow the processing
+ // display to be shown - otherwise to it synchronously
+ if ( settings.oFeatures.bProcessing ) {
+ _fnProcessingDisplay( settings, true );
+
+ setTimeout( function() {
+ _fnSortListener( settings, colIdx, e.shiftKey, callback );
+
+ // In server-side processing, the draw callback will remove the
+ // processing display
+ if ( _fnDataSource( settings ) !== 'ssp' ) {
+ _fnProcessingDisplay( settings, false );
+ }
+ }, 0 );
+ }
+ else {
+ _fnSortListener( settings, colIdx, e.shiftKey, callback );
+ }
+ } );
+ }
+
+
+ /**
+ * Set the sorting classes on table's body, Note: it is safe to call this function
+ * when bSort and bSortClasses are false
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnSortingClasses( settings )
+ {
+ var oldSort = settings.aLastSort;
+ var sortClass = settings.oClasses.sSortColumn;
+ var sort = _fnSortFlatten( settings );
+ var features = settings.oFeatures;
+ var i, ien, colIdx;
+
+ if ( features.bSort && features.bSortClasses ) {
+ // Remove old sorting classes
+ for ( i=0, ien=oldSort.length ; i 0 && state.time < +new Date() - (duration*1000) ) {
+ return;
+ }
+
+ // Number of columns have changed - all bets are off, no restore of settings
+ if ( columns.length !== state.columns.length ) {
+ return;
+ }
+
+ // Store the saved state so it might be accessed at any time
+ settings.oLoadedState = $.extend( true, {}, state );
+
+ // Restore key features - todo - for 1.11 this needs to be done by
+ // subscribed events
+ if ( state.start !== undefined ) {
+ settings._iDisplayStart = state.start;
+ settings.iInitDisplayStart = state.start;
+ }
+ if ( state.length !== undefined ) {
+ settings._iDisplayLength = state.length;
+ }
+
+ // Order
+ if ( state.order !== undefined ) {
+ settings.aaSorting = [];
+ $.each( state.order, function ( i, col ) {
+ settings.aaSorting.push( col[0] >= columns.length ?
+ [ 0, col[1] ] :
+ col
+ );
+ } );
+ }
+
+ // Search
+ if ( state.search !== undefined ) {
+ $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
+ }
+
+ // Columns
+ for ( i=0, ien=state.columns.length ; i= end )
+ {
+ start = end - len;
+ }
+
+ // Keep the start record on the current page
+ start -= (start % len);
+
+ if ( len === -1 || start < 0 )
+ {
+ start = 0;
+ }
+
+ settings._iDisplayStart = start;
+ }
+
+
+ function _fnRenderer( settings, type )
+ {
+ var renderer = settings.renderer;
+ var host = DataTable.ext.renderer[type];
+
+ if ( $.isPlainObject( renderer ) && renderer[type] ) {
+ // Specific renderer for this type. If available use it, otherwise use
+ // the default.
+ return host[renderer[type]] || host._;
+ }
+ else if ( typeof renderer === 'string' ) {
+ // Common renderer - if there is one available for this type use it,
+ // otherwise use the default
+ return host[renderer] || host._;
+ }
+
+ // Use the default
+ return host._;
+ }
+
+
+ /**
+ * Detect the data source being used for the table. Used to simplify the code
+ * a little (ajax) and to make it compress a little smaller.
+ *
+ * @param {object} settings dataTables settings object
+ * @returns {string} Data source
+ * @memberof DataTable#oApi
+ */
+ function _fnDataSource ( settings )
+ {
+ if ( settings.oFeatures.bServerSide ) {
+ return 'ssp';
+ }
+ else if ( settings.ajax || settings.sAjaxSource ) {
+ return 'ajax';
+ }
+ return 'dom';
+ }
+
+
+ DataTable = function( options )
+ {
+ /**
+ * Perform a jQuery selector action on the table's TR elements (from the tbody) and
+ * return the resulting jQuery object.
+ * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
+ * @param {object} [oOpts] Optional parameters for modifying the rows to be included
+ * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
+ * criterion ("applied") or all TR elements (i.e. no filter).
+ * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
+ * Can be either 'current', whereby the current sorting of the table is used, or
+ * 'original' whereby the original order the data was read into the table is used.
+ * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
+ * ("current") or not ("all"). If 'current' is given, then order is assumed to be
+ * 'current' and filter is 'applied', regardless of what they might be given as.
+ * @returns {object} jQuery object, filtered by the given selector.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Highlight every second row
+ * oTable.$('tr:odd').css('backgroundColor', 'blue');
+ * } );
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Filter to rows with 'Webkit' in them, add a background colour and then
+ * // remove the filter, thus highlighting the 'Webkit' rows only.
+ * oTable.fnFilter('Webkit');
+ * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
+ * oTable.fnFilter('');
+ * } );
+ */
+ this.$ = function ( sSelector, oOpts )
+ {
+ return this.api(true).$( sSelector, oOpts );
+ };
+
+
+ /**
+ * Almost identical to $ in operation, but in this case returns the data for the matched
+ * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
+ * rather than any descendants, so the data can be obtained for the row/cell. If matching
+ * rows are found, the data returned is the original data array/object that was used to
+ * create the row (or a generated array if from a DOM source).
+ *
+ * This method is often useful in-combination with $ where both functions are given the
+ * same parameters and the array indexes will match identically.
+ * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
+ * @param {object} [oOpts] Optional parameters for modifying the rows to be included
+ * @param {string} [oOpts.filter=none] Select elements that meet the current filter
+ * criterion ("applied") or all elements (i.e. no filter).
+ * @param {string} [oOpts.order=current] Order of the data in the processed array.
+ * Can be either 'current', whereby the current sorting of the table is used, or
+ * 'original' whereby the original order the data was read into the table is used.
+ * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
+ * ("current") or not ("all"). If 'current' is given, then order is assumed to be
+ * 'current' and filter is 'applied', regardless of what they might be given as.
+ * @returns {array} Data for the matched elements. If any elements, as a result of the
+ * selector, were not TR, TD or TH elements in the DataTable, they will have a null
+ * entry in the array.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Get the data from the first row in the table
+ * var data = oTable._('tr:first');
+ *
+ * // Do something useful with the data
+ * alert( "First cell is: "+data[0] );
+ * } );
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Filter to 'Webkit' and get all data for
+ * oTable.fnFilter('Webkit');
+ * var data = oTable._('tr', {"search": "applied"});
+ *
+ * // Do something with the data
+ * alert( data.length+" rows matched the search" );
+ * } );
+ */
+ this._ = function ( sSelector, oOpts )
+ {
+ return this.api(true).rows( sSelector, oOpts ).data();
+ };
+
+
+ /**
+ * Create a DataTables Api instance, with the currently selected tables for
+ * the Api's context.
+ * @param {boolean} [traditional=false] Set the API instance's context to be
+ * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
+ * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
+ * or if all tables captured in the jQuery object should be used.
+ * @return {DataTables.Api}
+ */
+ this.api = function ( traditional )
+ {
+ return traditional ?
+ new _Api(
+ _fnSettingsFromNode( this[ _ext.iApiIndex ] )
+ ) :
+ new _Api( this );
+ };
+
+
+ /**
+ * Add a single new row or multiple rows of data to the table. Please note
+ * that this is suitable for client-side processing only - if you are using
+ * server-side processing (i.e. "bServerSide": true), then to add data, you
+ * must add it to the data source, i.e. the server-side, through an Ajax call.
+ * @param {array|object} data The data to be added to the table. This can be:
+ *
+ *
1D array of data - add a single row with the data provided
+ *
2D array of arrays - add multiple rows in a single call
+ *
object - data object when using mData
+ *
array of objects - multiple data objects when using mData
+ *
+ * @param {bool} [redraw=true] redraw the table or not
+ * @returns {array} An array of integers, representing the list of indexes in
+ * aoData ({@link DataTable.models.oSettings}) that have been added to
+ * the table.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * // Global var for counter
+ * var giCount = 2;
+ *
+ * $(document).ready(function() {
+ * $('#example').dataTable();
+ * } );
+ *
+ * function fnClickAddRow() {
+ * $('#example').dataTable().fnAddData( [
+ * giCount+".1",
+ * giCount+".2",
+ * giCount+".3",
+ * giCount+".4" ]
+ * );
+ *
+ * giCount++;
+ * }
+ */
+ this.fnAddData = function( data, redraw )
+ {
+ var api = this.api( true );
+
+ /* Check if we want to add multiple rows or not */
+ var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
+ api.rows.add( data ) :
+ api.row.add( data );
+
+ if ( redraw === undefined || redraw ) {
+ api.draw();
+ }
+
+ return rows.flatten().toArray();
+ };
+
+
+ /**
+ * This function will make DataTables recalculate the column sizes, based on the data
+ * contained in the table and the sizes applied to the columns (in the DOM, CSS or
+ * through the sWidth parameter). This can be useful when the width of the table's
+ * parent element changes (for example a window resize).
+ * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable( {
+ * "sScrollY": "200px",
+ * "bPaginate": false
+ * } );
+ *
+ * $(window).bind('resize', function () {
+ * oTable.fnAdjustColumnSizing();
+ * } );
+ * } );
+ */
+ this.fnAdjustColumnSizing = function ( bRedraw )
+ {
+ var api = this.api( true ).columns.adjust();
+ var settings = api.settings()[0];
+ var scroll = settings.oScroll;
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.draw( false );
+ }
+ else if ( scroll.sX !== "" || scroll.sY !== "" ) {
+ /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
+ _fnScrollDraw( settings );
+ }
+ };
+
+
+ /**
+ * Quickly and simply clear a table
+ * @param {bool} [bRedraw=true] redraw the table or not
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
+ * oTable.fnClearTable();
+ * } );
+ */
+ this.fnClearTable = function( bRedraw )
+ {
+ var api = this.api( true ).clear();
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.draw();
+ }
+ };
+
+
+ /**
+ * The exact opposite of 'opening' a row, this function will close any rows which
+ * are currently 'open'.
+ * @param {node} nTr the table row to 'close'
+ * @returns {int} 0 on success, or 1 if failed (can't find the row)
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable;
+ *
+ * // 'open' an information row when a row is clicked on
+ * $('#example tbody tr').click( function () {
+ * if ( oTable.fnIsOpen(this) ) {
+ * oTable.fnClose( this );
+ * } else {
+ * oTable.fnOpen( this, "Temporary row opened", "info_row" );
+ * }
+ * } );
+ *
+ * oTable = $('#example').dataTable();
+ * } );
+ */
+ this.fnClose = function( nTr )
+ {
+ this.api( true ).row( nTr ).child.hide();
+ };
+
+
+ /**
+ * Remove a row for the table
+ * @param {mixed} target The index of the row from aoData to be deleted, or
+ * the TR element you want to delete
+ * @param {function|null} [callBack] Callback function
+ * @param {bool} [redraw=true] Redraw the table or not
+ * @returns {array} The row that was deleted
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Immediately remove the first row
+ * oTable.fnDeleteRow( 0 );
+ * } );
+ */
+ this.fnDeleteRow = function( target, callback, redraw )
+ {
+ var api = this.api( true );
+ var rows = api.rows( target );
+ var settings = rows.settings()[0];
+ var data = settings.aoData[ rows[0][0] ];
+
+ rows.remove();
+
+ if ( callback ) {
+ callback.call( this, settings, data );
+ }
+
+ if ( redraw === undefined || redraw ) {
+ api.draw();
+ }
+
+ return data;
+ };
+
+
+ /**
+ * Restore the table to it's original state in the DOM by removing all of DataTables
+ * enhancements, alterations to the DOM structure of the table and event listeners.
+ * @param {boolean} [remove=false] Completely remove the table from the DOM
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * // This example is fairly pointless in reality, but shows how fnDestroy can be used
+ * var oTable = $('#example').dataTable();
+ * oTable.fnDestroy();
+ * } );
+ */
+ this.fnDestroy = function ( remove )
+ {
+ this.api( true ).destroy( remove );
+ };
+
+
+ /**
+ * Redraw the table
+ * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
+ * oTable.fnDraw();
+ * } );
+ */
+ this.fnDraw = function( complete )
+ {
+ // Note that this isn't an exact match to the old call to _fnDraw - it takes
+ // into account the new data, but can hold position.
+ this.api( true ).draw( complete );
+ };
+
+
+ /**
+ * Filter the input based on data
+ * @param {string} sInput String to filter the table on
+ * @param {int|null} [iColumn] Column to limit filtering to
+ * @param {bool} [bRegex=false] Treat as regular expression or not
+ * @param {bool} [bSmart=true] Perform smart filtering or not
+ * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
+ * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Sometime later - filter...
+ * oTable.fnFilter( 'test string' );
+ * } );
+ */
+ this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
+ {
+ var api = this.api( true );
+
+ if ( iColumn === null || iColumn === undefined ) {
+ api.search( sInput, bRegex, bSmart, bCaseInsensitive );
+ }
+ else {
+ api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
+ }
+
+ api.draw();
+ };
+
+
+ /**
+ * Get the data for the whole table, an individual row or an individual cell based on the
+ * provided parameters.
+ * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
+ * a TR node then the data source for the whole row will be returned. If given as a
+ * TD/TH cell node then iCol will be automatically calculated and the data for the
+ * cell returned. If given as an integer, then this is treated as the aoData internal
+ * data index for the row (see fnGetPosition) and the data for that row used.
+ * @param {int} [col] Optional column index that you want the data of.
+ * @returns {array|object|string} If mRow is undefined, then the data for all rows is
+ * returned. If mRow is defined, just data for that row, and is iCol is
+ * defined, only data for the designated cell is returned.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * // Row data
+ * $(document).ready(function() {
+ * oTable = $('#example').dataTable();
+ *
+ * oTable.$('tr').click( function () {
+ * var data = oTable.fnGetData( this );
+ * // ... do something with the array / object of data for the row
+ * } );
+ * } );
+ *
+ * @example
+ * // Individual cell data
+ * $(document).ready(function() {
+ * oTable = $('#example').dataTable();
+ *
+ * oTable.$('td').click( function () {
+ * var sData = oTable.fnGetData( this );
+ * alert( 'The cell clicked on had the value of '+sData );
+ * } );
+ * } );
+ */
+ this.fnGetData = function( src, col )
+ {
+ var api = this.api( true );
+
+ if ( src !== undefined ) {
+ var type = src.nodeName ? src.nodeName.toLowerCase() : '';
+
+ return col !== undefined || type == 'td' || type == 'th' ?
+ api.cell( src, col ).data() :
+ api.row( src ).data() || null;
+ }
+
+ return api.data().toArray();
+ };
+
+
+ /**
+ * Get an array of the TR nodes that are used in the table's body. Note that you will
+ * typically want to use the '$' API method in preference to this as it is more
+ * flexible.
+ * @param {int} [iRow] Optional row index for the TR element you want
+ * @returns {array|node} If iRow is undefined, returns an array of all TR elements
+ * in the table's body, or iRow is defined, just the TR element requested.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Get the nodes from the table
+ * var nNodes = oTable.fnGetNodes( );
+ * } );
+ */
+ this.fnGetNodes = function( iRow )
+ {
+ var api = this.api( true );
+
+ return iRow !== undefined ?
+ api.row( iRow ).node() :
+ api.rows().nodes().flatten().toArray();
+ };
+
+
+ /**
+ * Get the array indexes of a particular cell from it's DOM element
+ * and column index including hidden columns
+ * @param {node} node this can either be a TR, TD or TH in the table's body
+ * @returns {int} If nNode is given as a TR, then a single index is returned, or
+ * if given as a cell, an array of [row index, column index (visible),
+ * column index (all)] is given.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example tbody td').click( function () {
+ * // Get the position of the current data from the node
+ * var aPos = oTable.fnGetPosition( this );
+ *
+ * // Get the data array for this row
+ * var aData = oTable.fnGetData( aPos[0] );
+ *
+ * // Update the data array and return the value
+ * aData[ aPos[1] ] = 'clicked';
+ * this.innerHTML = 'clicked';
+ * } );
+ *
+ * // Init DataTables
+ * oTable = $('#example').dataTable();
+ * } );
+ */
+ this.fnGetPosition = function( node )
+ {
+ var api = this.api( true );
+ var nodeName = node.nodeName.toUpperCase();
+
+ if ( nodeName == 'TR' ) {
+ return api.row( node ).index();
+ }
+ else if ( nodeName == 'TD' || nodeName == 'TH' ) {
+ var cell = api.cell( node ).index();
+
+ return [
+ cell.row,
+ cell.columnVisible,
+ cell.column
+ ];
+ }
+ return null;
+ };
+
+
+ /**
+ * Check to see if a row is 'open' or not.
+ * @param {node} nTr the table row to check
+ * @returns {boolean} true if the row is currently open, false otherwise
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable;
+ *
+ * // 'open' an information row when a row is clicked on
+ * $('#example tbody tr').click( function () {
+ * if ( oTable.fnIsOpen(this) ) {
+ * oTable.fnClose( this );
+ * } else {
+ * oTable.fnOpen( this, "Temporary row opened", "info_row" );
+ * }
+ * } );
+ *
+ * oTable = $('#example').dataTable();
+ * } );
+ */
+ this.fnIsOpen = function( nTr )
+ {
+ return this.api( true ).row( nTr ).child.isShown();
+ };
+
+
+ /**
+ * This function will place a new row directly after a row which is currently
+ * on display on the page, with the HTML contents that is passed into the
+ * function. This can be used, for example, to ask for confirmation that a
+ * particular record should be deleted.
+ * @param {node} nTr The table row to 'open'
+ * @param {string|node|jQuery} mHtml The HTML to put into the row
+ * @param {string} sClass Class to give the new TD cell
+ * @returns {node} The row opened. Note that if the table row passed in as the
+ * first parameter, is not found in the table, this method will silently
+ * return.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable;
+ *
+ * // 'open' an information row when a row is clicked on
+ * $('#example tbody tr').click( function () {
+ * if ( oTable.fnIsOpen(this) ) {
+ * oTable.fnClose( this );
+ * } else {
+ * oTable.fnOpen( this, "Temporary row opened", "info_row" );
+ * }
+ * } );
+ *
+ * oTable = $('#example').dataTable();
+ * } );
+ */
+ this.fnOpen = function( nTr, mHtml, sClass )
+ {
+ return this.api( true )
+ .row( nTr )
+ .child( mHtml, sClass )
+ .show()
+ .child()[0];
+ };
+
+
+ /**
+ * Change the pagination - provides the internal logic for pagination in a simple API
+ * function. With this function you can have a DataTables table go to the next,
+ * previous, first or last pages.
+ * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
+ * or page number to jump to (integer), note that page 0 is the first page.
+ * @param {bool} [bRedraw=true] Redraw the table or not
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ * oTable.fnPageChange( 'next' );
+ * } );
+ */
+ this.fnPageChange = function ( mAction, bRedraw )
+ {
+ var api = this.api( true ).page( mAction );
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.draw(false);
+ }
+ };
+
+
+ /**
+ * Show a particular column
+ * @param {int} iCol The column whose display should be changed
+ * @param {bool} bShow Show (true) or hide (false) the column
+ * @param {bool} [bRedraw=true] Redraw the table or not
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Hide the second column after initialisation
+ * oTable.fnSetColumnVis( 1, false );
+ * } );
+ */
+ this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
+ {
+ var api = this.api( true ).column( iCol ).visible( bShow );
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.columns.adjust().draw();
+ }
+ };
+
+
+ /**
+ * Get the settings for a particular table for external manipulation
+ * @returns {object} DataTables settings object. See
+ * {@link DataTable.models.oSettings}
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ * var oSettings = oTable.fnSettings();
+ *
+ * // Show an example parameter from the settings
+ * alert( oSettings._iDisplayStart );
+ * } );
+ */
+ this.fnSettings = function()
+ {
+ return _fnSettingsFromNode( this[_ext.iApiIndex] );
+ };
+
+
+ /**
+ * Sort the table by a particular column
+ * @param {int} iCol the data index to sort on. Note that this will not match the
+ * 'display index' if you have hidden data entries
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Sort immediately with columns 0 and 1
+ * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
+ * } );
+ */
+ this.fnSort = function( aaSort )
+ {
+ this.api( true ).order( aaSort ).draw();
+ };
+
+
+ /**
+ * Attach a sort listener to an element for a given column
+ * @param {node} nNode the element to attach the sort listener to
+ * @param {int} iColumn the column that a click on this node will sort on
+ * @param {function} [fnCallback] callback function when sort is run
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Sort on column 1, when 'sorter' is clicked on
+ * oTable.fnSortListener( document.getElementById('sorter'), 1 );
+ * } );
+ */
+ this.fnSortListener = function( nNode, iColumn, fnCallback )
+ {
+ this.api( true ).order.listener( nNode, iColumn, fnCallback );
+ };
+
+
+ /**
+ * Update a table cell or row - this method will accept either a single value to
+ * update the cell with, an array of values with one element for each column or
+ * an object in the same format as the original data source. The function is
+ * self-referencing in order to make the multi column updates easier.
+ * @param {object|array|string} mData Data to update the cell/row with
+ * @param {node|int} mRow TR element you want to update or the aoData index
+ * @param {int} [iColumn] The column to update, give as null or undefined to
+ * update a whole row.
+ * @param {bool} [bRedraw=true] Redraw the table or not
+ * @param {bool} [bAction=true] Perform pre-draw actions or not
+ * @returns {int} 0 on success, 1 on error
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
+ * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
+ * } );
+ */
+ this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
+ {
+ var api = this.api( true );
+
+ if ( iColumn === undefined || iColumn === null ) {
+ api.row( mRow ).data( mData );
+ }
+ else {
+ api.cell( mRow, iColumn ).data( mData );
+ }
+
+ if ( bAction === undefined || bAction ) {
+ api.columns.adjust();
+ }
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.draw();
+ }
+ return 0;
+ };
+
+
+ /**
+ * Provide a common method for plug-ins to check the version of DataTables being used, in order
+ * to ensure compatibility.
+ * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
+ * formats "X" and "X.Y" are also acceptable.
+ * @returns {boolean} true if this version of DataTables is greater or equal to the required
+ * version, or false if this version of DataTales is not suitable
+ * @method
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ * alert( oTable.fnVersionCheck( '1.9.0' ) );
+ * } );
+ */
+ this.fnVersionCheck = _ext.fnVersionCheck;
+
+
+ var _that = this;
+ var emptyInit = options === undefined;
+ var len = this.length;
+
+ if ( emptyInit ) {
+ options = {};
+ }
+
+ this.oApi = this.internal = _ext.internal;
+
+ // Extend with old style plug-in API methods
+ for ( var fn in DataTable.ext.internal ) {
+ if ( fn ) {
+ this[fn] = _fnExternApiFunc(fn);
+ }
+ }
+
+ this.each(function() {
+ // For each initialisation we want to give it a clean initialisation
+ // object that can be bashed around
+ var o = {};
+ var oInit = len > 1 ? // optimisation for single table case
+ _fnExtend( o, options, true ) :
+ options;
+
+ /*global oInit,_that,emptyInit*/
+ var i=0, iLen, j, jLen, k, kLen;
+ var sId = this.getAttribute( 'id' );
+ var bInitHandedOff = false;
+ var defaults = DataTable.defaults;
+ var $this = $(this);
+
+
+ /* Sanity check */
+ if ( this.nodeName.toLowerCase() != 'table' )
+ {
+ _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
+ return;
+ }
+
+ /* Backwards compatibility for the defaults */
+ _fnCompatOpts( defaults );
+ _fnCompatCols( defaults.column );
+
+ /* Convert the camel-case defaults to Hungarian */
+ _fnCamelToHungarian( defaults, defaults, true );
+ _fnCamelToHungarian( defaults.column, defaults.column, true );
+
+ /* Setting up the initialisation object */
+ _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
+
+
+
+ /* Check to see if we are re-initialising a table */
+ var allSettings = DataTable.settings;
+ for ( i=0, iLen=allSettings.length ; i').appendTo(this);
+ }
+ oSettings.nTHead = thead[0];
+
+ var tbody = $this.children('tbody');
+ if ( tbody.length === 0 )
+ {
+ tbody = $('').appendTo(this);
+ }
+ oSettings.nTBody = tbody[0];
+
+ var tfoot = $this.children('tfoot');
+ if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
+ {
+ // If we are a scrolling table, and no footer has been given, then we need to create
+ // a tfoot element for the caption element to be appended to
+ tfoot = $('').appendTo(this);
+ }
+
+ if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
+ $this.addClass( oClasses.sNoFooter );
+ }
+ else if ( tfoot.length > 0 ) {
+ oSettings.nTFoot = tfoot[0];
+ _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
+ }
+
+ /* Check if there is data passing into the constructor */
+ if ( oInit.aaData )
+ {
+ for ( i=0 ; i idx ?
+ new _Api( ctx[idx], this[idx] ) :
+ null;
+ },
+
+
+ filter: function ( fn )
+ {
+ var a = [];
+
+ if ( __arrayProto.filter ) {
+ a = __arrayProto.filter.call( this, fn, this );
+ }
+ else {
+ // Compatibility for browsers without EMCA-252-5 (JS 1.6)
+ for ( var i=0, ien=this.length ; i 0 ) {
+ return ctx[0].json;
+ }
+
+ // else return undefined;
+ } );
+
+
+ /**
+ * Get the data submitted in the last Ajax request
+ */
+ _api_register( 'ajax.params()', function () {
+ var ctx = this.context;
+
+ if ( ctx.length > 0 ) {
+ return ctx[0].oAjaxData;
+ }
+
+ // else return undefined;
+ } );
+
+
+ /**
+ * Reload tables from the Ajax data source. Note that this function will
+ * automatically re-draw the table when the remote data has been loaded.
+ *
+ * @param {boolean} [reset=true] Reset (default) or hold the current paging
+ * position. A full re-sort and re-filter is performed when this method is
+ * called, which is why the pagination reset is the default action.
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
+ return this.iterator( 'table', function (settings) {
+ __reload( settings, resetPaging===false, callback );
+ } );
+ } );
+
+
+ /**
+ * Get the current Ajax URL. Note that this returns the URL from the first
+ * table in the current context.
+ *
+ * @return {string} Current Ajax source URL
+ *//**
+ * Set the Ajax URL. Note that this will set the URL for all tables in the
+ * current context.
+ *
+ * @param {string} url URL to set.
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'ajax.url()', function ( url ) {
+ var ctx = this.context;
+
+ if ( url === undefined ) {
+ // get
+ if ( ctx.length === 0 ) {
+ return undefined;
+ }
+ ctx = ctx[0];
+
+ return ctx.ajax ?
+ $.isPlainObject( ctx.ajax ) ?
+ ctx.ajax.url :
+ ctx.ajax :
+ ctx.sAjaxSource;
+ }
+
+ // set
+ return this.iterator( 'table', function ( settings ) {
+ if ( $.isPlainObject( settings.ajax ) ) {
+ settings.ajax.url = url;
+ }
+ else {
+ settings.ajax = url;
+ }
+ // No need to consider sAjaxSource here since DataTables gives priority
+ // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
+ // value of `sAjaxSource` redundant.
+ } );
+ } );
+
+
+ /**
+ * Load data from the newly set Ajax URL. Note that this method is only
+ * available when `ajax.url()` is used to set a URL. Additionally, this method
+ * has the same effect as calling `ajax.reload()` but is provided for
+ * convenience when setting a new URL. Like `ajax.reload()` it will
+ * automatically redraw the table once the remote data has been loaded.
+ *
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
+ // Same as a reload, but makes sense to present it for easy access after a
+ // url change
+ return this.iterator( 'table', function ( ctx ) {
+ __reload( ctx, resetPaging===false, callback );
+ } );
+ } );
+
+
+
+
+ var _selector_run = function ( type, selector, selectFn, settings, opts )
+ {
+ var
+ out = [], res,
+ a, i, ien, j, jen,
+ selectorType = typeof selector;
+
+ // Can't just check for isArray here, as an API or jQuery instance might be
+ // given with their array like look
+ if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
+ selector = [ selector ];
+ }
+
+ for ( i=0, ien=selector.length ; i 0 ) {
+ // Assign the first element to the first item in the instance
+ // and truncate the instance and context
+ inst[0] = inst[i];
+ inst[0].length = 1;
+ inst.length = 1;
+ inst.context = [ inst.context[i] ];
+
+ return inst;
+ }
+ }
+
+ // Not found - return an empty instance
+ inst.length = 0;
+ return inst;
+ };
+
+
+ var _selector_row_indexes = function ( settings, opts )
+ {
+ var
+ i, ien, tmp, a=[],
+ displayFiltered = settings.aiDisplay,
+ displayMaster = settings.aiDisplayMaster;
+
+ var
+ search = opts.search, // none, applied, removed
+ order = opts.order, // applied, current, index (original - compatibility with 1.9)
+ page = opts.page; // all, current
+
+ if ( _fnDataSource( settings ) == 'ssp' ) {
+ // In server-side processing mode, most options are irrelevant since
+ // rows not shown don't exist and the index order is the applied order
+ // Removed is a special case - for consistency just return an empty
+ // array
+ return search === 'removed' ?
+ [] :
+ _range( 0, displayMaster.length );
+ }
+ else if ( page == 'current' ) {
+ // Current page implies that order=current and fitler=applied, since it is
+ // fairly senseless otherwise, regardless of what order and search actually
+ // are
+ for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i= 0 && search == 'applied') )
+ {
+ a.push( i );
+ }
+ }
+ }
+ }
+
+ return a;
+ };
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Rows
+ *
+ * {} - no selector - use all available rows
+ * {integer} - row aoData index
+ * {node} - TR node
+ * {string} - jQuery selector to apply to the TR elements
+ * {array} - jQuery array of nodes, or simply an array of TR nodes
+ *
+ */
+
+
+ var __row_selector = function ( settings, selector, opts )
+ {
+ var run = function ( sel ) {
+ var selInt = _intVal( sel );
+ var i, ien;
+
+ // Short cut - selector is a number and no options provided (default is
+ // all records, so no need to check if the index is in there, since it
+ // must be - dev error if the index doesn't exist).
+ if ( selInt !== null && ! opts ) {
+ return [ selInt ];
+ }
+
+ var rows = _selector_row_indexes( settings, opts );
+
+ if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
+ // Selector - integer
+ return [ selInt ];
+ }
+ else if ( ! sel ) {
+ // Selector - none
+ return rows;
+ }
+
+ // Selector - function
+ if ( typeof sel === 'function' ) {
+ return $.map( rows, function (idx) {
+ var row = settings.aoData[ idx ];
+ return sel( idx, row._aData, row.nTr ) ? idx : null;
+ } );
+ }
+
+ // Get nodes in the order from the `rows` array with null values removed
+ var nodes = _removeEmpty(
+ _pluck_order( settings.aoData, rows, 'nTr' )
+ );
+
+ // Selector - node
+ if ( sel.nodeName ) {
+ if ( sel._DT_RowIndex !== undefined ) {
+ return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup
+ }
+ else if ( sel._DT_CellIndex ) {
+ return [ sel._DT_CellIndex.row ];
+ }
+ else {
+ var host = $(sel).closest('*[data-dt-row]');
+ return host.length ?
+ [ host.data('dt-row') ] :
+ [];
+ }
+ }
+
+ // ID selector. Want to always be able to select rows by id, regardless
+ // of if the tr element has been created or not, so can't rely upon
+ // jQuery here - hence a custom implementation. This does not match
+ // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
+ // but to select it using a CSS selector engine (like Sizzle or
+ // querySelect) it would need to need to be escaped for some characters.
+ // DataTables simplifies this for row selectors since you can select
+ // only a row. A # indicates an id any anything that follows is the id -
+ // unescaped.
+ if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
+ // get row index from id
+ var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
+ if ( rowObj !== undefined ) {
+ return [ rowObj.idx ];
+ }
+
+ // need to fall through to jQuery in case there is DOM id that
+ // matches
+ }
+
+ // Selector - jQuery selector string, array of nodes or jQuery object/
+ // As jQuery's .filter() allows jQuery objects to be passed in filter,
+ // it also allows arrays, so this will cope with all three options
+ return $(nodes)
+ .filter( sel )
+ .map( function () {
+ return this._DT_RowIndex;
+ } )
+ .toArray();
+ };
+
+ return _selector_run( 'row', selector, run, settings, opts );
+ };
+
+
+ _api_register( 'rows()', function ( selector, opts ) {
+ // argument shifting
+ if ( selector === undefined ) {
+ selector = '';
+ }
+ else if ( $.isPlainObject( selector ) ) {
+ opts = selector;
+ selector = '';
+ }
+
+ opts = _selector_opts( opts );
+
+ var inst = this.iterator( 'table', function ( settings ) {
+ return __row_selector( settings, selector, opts );
+ }, 1 );
+
+ // Want argument shifting here and in __row_selector?
+ inst.selector.rows = selector;
+ inst.selector.opts = opts;
+
+ return inst;
+ } );
+
+ _api_register( 'rows().nodes()', function () {
+ return this.iterator( 'row', function ( settings, row ) {
+ return settings.aoData[ row ].nTr || undefined;
+ }, 1 );
+ } );
+
+ _api_register( 'rows().data()', function () {
+ return this.iterator( true, 'rows', function ( settings, rows ) {
+ return _pluck_order( settings.aoData, rows, '_aData' );
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
+ return this.iterator( 'row', function ( settings, row ) {
+ var r = settings.aoData[ row ];
+ return type === 'search' ? r._aFilterData : r._aSortData;
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
+ return this.iterator( 'row', function ( settings, row ) {
+ _fnInvalidate( settings, row, src );
+ } );
+ } );
+
+ _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
+ return this.iterator( 'row', function ( settings, row ) {
+ return row;
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
+ var a = [];
+ var context = this.context;
+
+ // `iterator` will drop undefined values, but in this case we want them
+ for ( var i=0, ien=context.length ; i
').addClass( k );
+ $('td', created)
+ .addClass( k )
+ .html( r )
+ [0].colSpan = _fnVisbleColumns( ctx );
+
+ rows.push( created[0] );
+ }
+ };
+
+ addRow( data, klass );
+
+ if ( row._details ) {
+ row._details.remove();
+ }
+
+ row._details = $(rows);
+
+ // If the children were already shown, that state should be retained
+ if ( row._detailsShow ) {
+ row._details.insertAfter( row.nTr );
+ }
+ };
+
+
+ var __details_remove = function ( api, idx )
+ {
+ var ctx = api.context;
+
+ if ( ctx.length ) {
+ var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
+
+ if ( row && row._details ) {
+ row._details.remove();
+
+ row._detailsShow = undefined;
+ row._details = undefined;
+ }
+ }
+ };
+
+
+ var __details_display = function ( api, show ) {
+ var ctx = api.context;
+
+ if ( ctx.length && api.length ) {
+ var row = ctx[0].aoData[ api[0] ];
+
+ if ( row._details ) {
+ row._detailsShow = show;
+
+ if ( show ) {
+ row._details.insertAfter( row.nTr );
+ }
+ else {
+ row._details.detach();
+ }
+
+ __details_events( ctx[0] );
+ }
+ }
+ };
+
+
+ var __details_events = function ( settings )
+ {
+ var api = new _Api( settings );
+ var namespace = '.dt.DT_details';
+ var drawEvent = 'draw'+namespace;
+ var colvisEvent = 'column-visibility'+namespace;
+ var destroyEvent = 'destroy'+namespace;
+ var data = settings.aoData;
+
+ api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
+
+ if ( _pluck( data, '_details' ).length > 0 ) {
+ // On each draw, insert the required elements into the document
+ api.on( drawEvent, function ( e, ctx ) {
+ if ( settings !== ctx ) {
+ return;
+ }
+
+ api.rows( {page:'current'} ).eq(0).each( function (idx) {
+ // Internal data grab
+ var row = data[ idx ];
+
+ if ( row._detailsShow ) {
+ row._details.insertAfter( row.nTr );
+ }
+ } );
+ } );
+
+ // Column visibility change - update the colspan
+ api.on( colvisEvent, function ( e, ctx, idx, vis ) {
+ if ( settings !== ctx ) {
+ return;
+ }
+
+ // Update the colspan for the details rows (note, only if it already has
+ // a colspan)
+ var row, visible = _fnVisbleColumns( ctx );
+
+ for ( var i=0, ien=data.length ; i=0 count from left, <0 count from right)
+ * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
+ * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
+ * "{string}:name" - column name
+ * "{string}" - jQuery selector on column header nodes
+ *
+ */
+
+ // can be an array of these items, comma separated list, or an array of comma
+ // separated lists
+
+ var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
+
+
+ // r1 and r2 are redundant - but it means that the parameters match for the
+ // iterator callback in columns().data()
+ var __columnData = function ( settings, column, r1, r2, rows ) {
+ var a = [];
+ for ( var row=0, ien=rows.length ; row= 0 ?
+ selInt : // Count from left
+ columns.length + selInt // Count from right (+ because its a negative value)
+ ];
+ }
+
+ // Selector = function
+ if ( typeof s === 'function' ) {
+ var rows = _selector_row_indexes( settings, opts );
+
+ return $.map( columns, function (col, idx) {
+ return s(
+ idx,
+ __columnData( settings, idx, 0, 0, rows ),
+ nodes[ idx ]
+ ) ? idx : null;
+ } );
+ }
+
+ // jQuery or string selector
+ var match = typeof s === 'string' ?
+ s.match( __re_column_selector ) :
+ '';
+
+ if ( match ) {
+ switch( match[2] ) {
+ case 'visIdx':
+ case 'visible':
+ var idx = parseInt( match[1], 10 );
+ // Visible index given, convert to column index
+ if ( idx < 0 ) {
+ // Counting from the right
+ var visColumns = $.map( columns, function (col,i) {
+ return col.bVisible ? i : null;
+ } );
+ return [ visColumns[ visColumns.length + idx ] ];
+ }
+ // Counting from the left
+ return [ _fnVisibleToColumnIndex( settings, idx ) ];
+
+ case 'name':
+ // match by name. `names` is column index complete and in order
+ return $.map( names, function (name, i) {
+ return name === match[1] ? i : null;
+ } );
+
+ default:
+ return [];
+ }
+ }
+
+ // Cell in the table body
+ if ( s.nodeName && s._DT_CellIndex ) {
+ return [ s._DT_CellIndex.column ];
+ }
+
+ // jQuery selector on the TH elements for the columns
+ var jqResult = $( nodes )
+ .filter( s )
+ .map( function () {
+ return $.inArray( this, nodes ); // `nodes` is column index complete and in order
+ } )
+ .toArray();
+
+ if ( jqResult.length || ! s.nodeName ) {
+ return jqResult;
+ }
+
+ // Otherwise a node which might have a `dt-column` data attribute, or be
+ // a child or such an element
+ var host = $(s).closest('*[data-dt-column]');
+ return host.length ?
+ [ host.data('dt-column') ] :
+ [];
+ };
+
+ return _selector_run( 'column', selector, run, settings, opts );
+ };
+
+
+ var __setColumnVis = function ( settings, column, vis, recalc ) {
+ var
+ cols = settings.aoColumns,
+ col = cols[ column ],
+ data = settings.aoData,
+ row, cells, i, ien, tr;
+
+ // Get
+ if ( vis === undefined ) {
+ return col.bVisible;
+ }
+
+ // Set
+ // No change
+ if ( col.bVisible === vis ) {
+ return;
+ }
+
+ if ( vis ) {
+ // Insert column
+ // Need to decide if we should use appendChild or insertBefore
+ var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
+
+ for ( i=0, ien=data.length ; i iThat;
+ }
+
+ return true;
+ };
+
+
+ /**
+ * Check if a `
` node is a DataTable table already or not.
+ *
+ * @param {node|jquery|string} table Table node, jQuery object or jQuery
+ * selector for the table to test. Note that if more than more than one
+ * table is passed on, only the first will be checked
+ * @returns {boolean} true the table given is a DataTable, or false otherwise
+ * @static
+ * @dtopt API-Static
+ *
+ * @example
+ * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
+ * $('#example').dataTable();
+ * }
+ */
+ DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
+ {
+ var t = $(table).get(0);
+ var is = false;
+
+ $.each( DataTable.settings, function (i, o) {
+ var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
+ var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
+
+ if ( o.nTable === t || head === t || foot === t ) {
+ is = true;
+ }
+ } );
+
+ return is;
+ };
+
+
+ /**
+ * Get all DataTable tables that have been initialised - optionally you can
+ * select to get only currently visible tables.
+ *
+ * @param {boolean} [visible=false] Flag to indicate if you want all (default)
+ * or visible tables only.
+ * @returns {array} Array of `table` nodes (not DataTable instances) which are
+ * DataTables
+ * @static
+ * @dtopt API-Static
+ *
+ * @example
+ * $.each( $.fn.dataTable.tables(true), function () {
+ * $(table).DataTable().columns.adjust();
+ * } );
+ */
+ DataTable.tables = DataTable.fnTables = function ( visible )
+ {
+ var api = false;
+
+ if ( $.isPlainObject( visible ) ) {
+ api = visible.api;
+ visible = visible.visible;
+ }
+
+ var a = $.map( DataTable.settings, function (o) {
+ if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
+ return o.nTable;
+ }
+ } );
+
+ return api ?
+ new _Api( a ) :
+ a;
+ };
+
+
+ /**
+ * DataTables utility methods
+ *
+ * This namespace provides helper methods that DataTables uses internally to
+ * create a DataTable, but which are not exclusively used only for DataTables.
+ * These methods can be used by extension authors to save the duplication of
+ * code.
+ *
+ * @namespace
+ */
+ DataTable.util = {
+ /**
+ * Throttle the calls to a function. Arguments and context are maintained
+ * for the throttled function.
+ *
+ * @param {function} fn Function to be called
+ * @param {integer} freq Call frequency in mS
+ * @return {function} Wrapped function
+ */
+ throttle: _fnThrottle,
+
+
+ /**
+ * Escape a string such that it can be used in a regular expression
+ *
+ * @param {string} sVal string to escape
+ * @returns {string} escaped string
+ */
+ escapeRegex: _fnEscapeRegex
+ };
+
+
+ /**
+ * Convert from camel case parameters to Hungarian notation. This is made public
+ * for the extensions to provide the same ability as DataTables core to accept
+ * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
+ * parameters.
+ *
+ * @param {object} src The model object which holds all parameters that can be
+ * mapped.
+ * @param {object} user The object to convert from camel case to Hungarian.
+ * @param {boolean} force When set to `true`, properties which already have a
+ * Hungarian value in the `user` object will be overwritten. Otherwise they
+ * won't be.
+ */
+ DataTable.camelToHungarian = _fnCamelToHungarian;
+
+
+
+ /**
+ *
+ */
+ _api_register( '$()', function ( selector, opts ) {
+ var
+ rows = this.rows( opts ).nodes(), // Get all rows
+ jqRows = $(rows);
+
+ return $( [].concat(
+ jqRows.filter( selector ).toArray(),
+ jqRows.find( selector ).toArray()
+ ) );
+ } );
+
+
+ // jQuery functions to operate on the tables
+ $.each( [ 'on', 'one', 'off' ], function (i, key) {
+ _api_register( key+'()', function ( /* event, handler */ ) {
+ var args = Array.prototype.slice.call(arguments);
+
+ // Add the `dt` namespace automatically if it isn't already present
+ if ( ! args[0].match(/\.dt\b/) ) {
+ args[0] += '.dt';
+ }
+
+ var inst = $( this.tables().nodes() );
+ inst[key].apply( inst, args );
+ return this;
+ } );
+ } );
+
+
+ _api_register( 'clear()', function () {
+ return this.iterator( 'table', function ( settings ) {
+ _fnClearTable( settings );
+ } );
+ } );
+
+
+ _api_register( 'settings()', function () {
+ return new _Api( this.context, this.context );
+ } );
+
+
+ _api_register( 'init()', function () {
+ var ctx = this.context;
+ return ctx.length ? ctx[0].oInit : null;
+ } );
+
+
+ _api_register( 'data()', function () {
+ return this.iterator( 'table', function ( settings ) {
+ return _pluck( settings.aoData, '_aData' );
+ } ).flatten();
+ } );
+
+
+ _api_register( 'destroy()', function ( remove ) {
+ remove = remove || false;
+
+ return this.iterator( 'table', function ( settings ) {
+ var orig = settings.nTableWrapper.parentNode;
+ var classes = settings.oClasses;
+ var table = settings.nTable;
+ var tbody = settings.nTBody;
+ var thead = settings.nTHead;
+ var tfoot = settings.nTFoot;
+ var jqTable = $(table);
+ var jqTbody = $(tbody);
+ var jqWrapper = $(settings.nTableWrapper);
+ var rows = $.map( settings.aoData, function (r) { return r.nTr; } );
+ var i, ien;
+
+ // Flag to note that the table is currently being destroyed - no action
+ // should be taken
+ settings.bDestroying = true;
+
+ // Fire off the destroy callbacks for plug-ins etc
+ _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
+
+ // If not being removed from the document, make all columns visible
+ if ( ! remove ) {
+ new _Api( settings ).columns().visible( true );
+ }
+
+ // Blitz all `DT` namespaced events (these are internal events, the
+ // lowercase, `dt` events are user subscribed and they are responsible
+ // for removing them
+ jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
+ $(window).unbind('.DT-'+settings.sInstance);
+
+ // When scrolling we had to break the table up - restore it
+ if ( table != thead.parentNode ) {
+ jqTable.children('thead').detach();
+ jqTable.append( thead );
+ }
+
+ if ( tfoot && table != tfoot.parentNode ) {
+ jqTable.children('tfoot').detach();
+ jqTable.append( tfoot );
+ }
+
+ settings.aaSorting = [];
+ settings.aaSortingFixed = [];
+ _fnSortingClasses( settings );
+
+ $( rows ).removeClass( settings.asStripeClasses.join(' ') );
+
+ $('th, td', thead).removeClass( classes.sSortable+' '+
+ classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
+ );
+
+ if ( settings.bJUI ) {
+ $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
+ $('th, td', thead).each( function () {
+ var wrapper = $('div.'+classes.sSortJUIWrapper, this);
+ $(this).append( wrapper.contents() );
+ wrapper.detach();
+ } );
+ }
+
+ // Add the TR elements back into the table in their original order
+ jqTbody.children().detach();
+ jqTbody.append( rows );
+
+ // Remove the DataTables generated nodes, events and classes
+ var removedMethod = remove ? 'remove' : 'detach';
+ jqTable[ removedMethod ]();
+ jqWrapper[ removedMethod ]();
+
+ // If we need to reattach the table to the document
+ if ( ! remove && orig ) {
+ // insertBefore acts like appendChild if !arg[1]
+ orig.insertBefore( table, settings.nTableReinsertBefore );
+
+ // Restore the width of the original table - was read from the style property,
+ // so we can restore directly to that
+ jqTable
+ .css( 'width', settings.sDestroyWidth )
+ .removeClass( classes.sTable );
+
+ // If the were originally stripe classes - then we add them back here.
+ // Note this is not fool proof (for example if not all rows had stripe
+ // classes - but it's a good effort without getting carried away
+ ien = settings.asDestroyStripes.length;
+
+ if ( ien ) {
+ jqTbody.children().each( function (i) {
+ $(this).addClass( settings.asDestroyStripes[i % ien] );
+ } );
+ }
+ }
+
+ /* Remove the settings object from the settings array */
+ var idx = $.inArray( settings, DataTable.settings );
+ if ( idx !== -1 ) {
+ DataTable.settings.splice( idx, 1 );
+ }
+ } );
+ } );
+
+
+ // Add the `every()` method for rows, columns and cells in a compact form
+ $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
+ _api_register( type+'s().every()', function ( fn ) {
+ var opts = this.selector.opts;
+ var api = this;
+
+ return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
+ // Rows and columns:
+ // arg1 - index
+ // arg2 - table counter
+ // arg3 - loop counter
+ // arg4 - undefined
+ // Cells:
+ // arg1 - row index
+ // arg2 - column index
+ // arg3 - table counter
+ // arg4 - loop counter
+ fn.call(
+ api[ type ](
+ arg1,
+ type==='cell' ? arg2 : opts,
+ type==='cell' ? opts : undefined
+ ),
+ arg1, arg2, arg3, arg4
+ );
+ } );
+ } );
+ } );
+
+
+ // i18n method for extensions to be able to use the language object from the
+ // DataTable
+ _api_register( 'i18n()', function ( token, def, plural ) {
+ var ctx = this.context[0];
+ var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
+
+ if ( resolved === undefined ) {
+ resolved = def;
+ }
+
+ if ( plural !== undefined && $.isPlainObject( resolved ) ) {
+ resolved = resolved[ plural ] !== undefined ?
+ resolved[ plural ] :
+ resolved._;
+ }
+
+ return resolved.replace( '%d', plural ); // nb: plural might be undefined,
+ } );
+
+ /**
+ * Version string for plug-ins to check compatibility. Allowed format is
+ * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
+ * only for non-release builds. See http://semver.org/ for more information.
+ * @member
+ * @type string
+ * @default Version number
+ */
+ DataTable.version = "1.10.11";
+
+ /**
+ * Private data store, containing all of the settings objects that are
+ * created for the tables on a given page.
+ *
+ * Note that the `DataTable.settings` object is aliased to
+ * `jQuery.fn.dataTableExt` through which it may be accessed and
+ * manipulated, or `jQuery.fn.dataTable.settings`.
+ * @member
+ * @type array
+ * @default []
+ * @private
+ */
+ DataTable.settings = [];
+
+ /**
+ * Object models container, for the various models that DataTables has
+ * available to it. These models define the objects that are used to hold
+ * the active state and configuration of the table.
+ * @namespace
+ */
+ DataTable.models = {};
+
+
+
+ /**
+ * Template object for the way in which DataTables holds information about
+ * search information for the global filter and individual column filters.
+ * @namespace
+ */
+ DataTable.models.oSearch = {
+ /**
+ * Flag to indicate if the filtering should be case insensitive or not
+ * @type boolean
+ * @default true
+ */
+ "bCaseInsensitive": true,
+
+ /**
+ * Applied search term
+ * @type string
+ * @default Empty string
+ */
+ "sSearch": "",
+
+ /**
+ * Flag to indicate if the search term should be interpreted as a
+ * regular expression (true) or not (false) and therefore and special
+ * regex characters escaped.
+ * @type boolean
+ * @default false
+ */
+ "bRegex": false,
+
+ /**
+ * Flag to indicate if DataTables is to use its smart filtering or not.
+ * @type boolean
+ * @default true
+ */
+ "bSmart": true
+ };
+
+
+
+
+ /**
+ * Template object for the way in which DataTables holds information about
+ * each individual row. This is the object format used for the settings
+ * aoData array.
+ * @namespace
+ */
+ DataTable.models.oRow = {
+ /**
+ * TR element for the row
+ * @type node
+ * @default null
+ */
+ "nTr": null,
+
+ /**
+ * Array of TD elements for each row. This is null until the row has been
+ * created.
+ * @type array nodes
+ * @default []
+ */
+ "anCells": null,
+
+ /**
+ * Data object from the original data source for the row. This is either
+ * an array if using the traditional form of DataTables, or an object if
+ * using mData options. The exact type will depend on the passed in
+ * data from the data source, or will be an array if using DOM a data
+ * source.
+ * @type array|object
+ * @default []
+ */
+ "_aData": [],
+
+ /**
+ * Sorting data cache - this array is ostensibly the same length as the
+ * number of columns (although each index is generated only as it is
+ * needed), and holds the data that is used for sorting each column in the
+ * row. We do this cache generation at the start of the sort in order that
+ * the formatting of the sort data need be done only once for each cell
+ * per sort. This array should not be read from or written to by anything
+ * other than the master sorting methods.
+ * @type array
+ * @default null
+ * @private
+ */
+ "_aSortData": null,
+
+ /**
+ * Per cell filtering data cache. As per the sort data cache, used to
+ * increase the performance of the filtering in DataTables
+ * @type array
+ * @default null
+ * @private
+ */
+ "_aFilterData": null,
+
+ /**
+ * Filtering data cache. This is the same as the cell filtering cache, but
+ * in this case a string rather than an array. This is easily computed with
+ * a join on `_aFilterData`, but is provided as a cache so the join isn't
+ * needed on every search (memory traded for performance)
+ * @type array
+ * @default null
+ * @private
+ */
+ "_sFilterRow": null,
+
+ /**
+ * Cache of the class name that DataTables has applied to the row, so we
+ * can quickly look at this variable rather than needing to do a DOM check
+ * on className for the nTr property.
+ * @type string
+ * @default Empty string
+ * @private
+ */
+ "_sRowStripe": "",
+
+ /**
+ * Denote if the original data source was from the DOM, or the data source
+ * object. This is used for invalidating data, so DataTables can
+ * automatically read data from the original source, unless uninstructed
+ * otherwise.
+ * @type string
+ * @default null
+ * @private
+ */
+ "src": null,
+
+ /**
+ * Index in the aoData array. This saves an indexOf lookup when we have the
+ * object, but want to know the index
+ * @type integer
+ * @default -1
+ * @private
+ */
+ "idx": -1
+ };
+
+
+ /**
+ * Template object for the column information object in DataTables. This object
+ * is held in the settings aoColumns array and contains all the information that
+ * DataTables needs about each individual column.
+ *
+ * Note that this object is related to {@link DataTable.defaults.column}
+ * but this one is the internal data store for DataTables's cache of columns.
+ * It should NOT be manipulated outside of DataTables. Any configuration should
+ * be done through the initialisation options.
+ * @namespace
+ */
+ DataTable.models.oColumn = {
+ /**
+ * Column index. This could be worked out on-the-fly with $.inArray, but it
+ * is faster to just hold it as a variable
+ * @type integer
+ * @default null
+ */
+ "idx": null,
+
+ /**
+ * A list of the columns that sorting should occur on when this column
+ * is sorted. That this property is an array allows multi-column sorting
+ * to be defined for a column (for example first name / last name columns
+ * would benefit from this). The values are integers pointing to the
+ * columns to be sorted on (typically it will be a single integer pointing
+ * at itself, but that doesn't need to be the case).
+ * @type array
+ */
+ "aDataSort": null,
+
+ /**
+ * Define the sorting directions that are applied to the column, in sequence
+ * as the column is repeatedly sorted upon - i.e. the first value is used
+ * as the sorting direction when the column if first sorted (clicked on).
+ * Sort it again (click again) and it will move on to the next index.
+ * Repeat until loop.
+ * @type array
+ */
+ "asSorting": null,
+
+ /**
+ * Flag to indicate if the column is searchable, and thus should be included
+ * in the filtering or not.
+ * @type boolean
+ */
+ "bSearchable": null,
+
+ /**
+ * Flag to indicate if the column is sortable or not.
+ * @type boolean
+ */
+ "bSortable": null,
+
+ /**
+ * Flag to indicate if the column is currently visible in the table or not
+ * @type boolean
+ */
+ "bVisible": null,
+
+ /**
+ * Store for manual type assignment using the `column.type` option. This
+ * is held in store so we can manipulate the column's `sType` property.
+ * @type string
+ * @default null
+ * @private
+ */
+ "_sManualType": null,
+
+ /**
+ * Flag to indicate if HTML5 data attributes should be used as the data
+ * source for filtering or sorting. True is either are.
+ * @type boolean
+ * @default false
+ * @private
+ */
+ "_bAttrSrc": false,
+
+ /**
+ * Developer definable function that is called whenever a cell is created (Ajax source,
+ * etc) or processed for input (DOM source). This can be used as a compliment to mRender
+ * allowing you to modify the DOM element (add background colour for example) when the
+ * element is available.
+ * @type function
+ * @param {element} nTd The TD node that has been created
+ * @param {*} sData The Data for the cell
+ * @param {array|object} oData The data for the whole row
+ * @param {int} iRow The row index for the aoData data store
+ * @default null
+ */
+ "fnCreatedCell": null,
+
+ /**
+ * Function to get data from a cell in a column. You should never
+ * access data directly through _aData internally in DataTables - always use
+ * the method attached to this property. It allows mData to function as
+ * required. This function is automatically assigned by the column
+ * initialisation method
+ * @type function
+ * @param {array|object} oData The data array/object for the array
+ * (i.e. aoData[]._aData)
+ * @param {string} sSpecific The specific data type you want to get -
+ * 'display', 'type' 'filter' 'sort'
+ * @returns {*} The data for the cell from the given row's data
+ * @default null
+ */
+ "fnGetData": null,
+
+ /**
+ * Function to set data for a cell in the column. You should never
+ * set the data directly to _aData internally in DataTables - always use
+ * this method. It allows mData to function as required. This function
+ * is automatically assigned by the column initialisation method
+ * @type function
+ * @param {array|object} oData The data array/object for the array
+ * (i.e. aoData[]._aData)
+ * @param {*} sValue Value to set
+ * @default null
+ */
+ "fnSetData": null,
+
+ /**
+ * Property to read the value for the cells in the column from the data
+ * source array / object. If null, then the default content is used, if a
+ * function is given then the return from the function is used.
+ * @type function|int|string|null
+ * @default null
+ */
+ "mData": null,
+
+ /**
+ * Partner property to mData which is used (only when defined) to get
+ * the data - i.e. it is basically the same as mData, but without the
+ * 'set' option, and also the data fed to it is the result from mData.
+ * This is the rendering method to match the data method of mData.
+ * @type function|int|string|null
+ * @default null
+ */
+ "mRender": null,
+
+ /**
+ * Unique header TH/TD element for this column - this is what the sorting
+ * listener is attached to (if sorting is enabled.)
+ * @type node
+ * @default null
+ */
+ "nTh": null,
+
+ /**
+ * Unique footer TH/TD element for this column (if there is one). Not used
+ * in DataTables as such, but can be used for plug-ins to reference the
+ * footer for each column.
+ * @type node
+ * @default null
+ */
+ "nTf": null,
+
+ /**
+ * The class to apply to all TD elements in the table's TBODY for the column
+ * @type string
+ * @default null
+ */
+ "sClass": null,
+
+ /**
+ * When DataTables calculates the column widths to assign to each column,
+ * it finds the longest string in each column and then constructs a
+ * temporary table and reads the widths from that. The problem with this
+ * is that "mmm" is much wider then "iiii", but the latter is a longer
+ * string - thus the calculation can go wrong (doing it properly and putting
+ * it into an DOM object and measuring that is horribly(!) slow). Thus as
+ * a "work around" we provide this option. It will append its value to the
+ * text that is found to be the longest string for the column - i.e. padding.
+ * @type string
+ */
+ "sContentPadding": null,
+
+ /**
+ * Allows a default value to be given for a column's data, and will be used
+ * whenever a null data source is encountered (this can be because mData
+ * is set to null, or because the data source itself is null).
+ * @type string
+ * @default null
+ */
+ "sDefaultContent": null,
+
+ /**
+ * Name for the column, allowing reference to the column by name as well as
+ * by index (needs a lookup to work by name).
+ * @type string
+ */
+ "sName": null,
+
+ /**
+ * Custom sorting data type - defines which of the available plug-ins in
+ * afnSortData the custom sorting will use - if any is defined.
+ * @type string
+ * @default std
+ */
+ "sSortDataType": 'std',
+
+ /**
+ * Class to be applied to the header element when sorting on this column
+ * @type string
+ * @default null
+ */
+ "sSortingClass": null,
+
+ /**
+ * Class to be applied to the header element when sorting on this column -
+ * when jQuery UI theming is used.
+ * @type string
+ * @default null
+ */
+ "sSortingClassJUI": null,
+
+ /**
+ * Title of the column - what is seen in the TH element (nTh).
+ * @type string
+ */
+ "sTitle": null,
+
+ /**
+ * Column sorting and filtering type
+ * @type string
+ * @default null
+ */
+ "sType": null,
+
+ /**
+ * Width of the column
+ * @type string
+ * @default null
+ */
+ "sWidth": null,
+
+ /**
+ * Width of the column when it was first "encountered"
+ * @type string
+ * @default null
+ */
+ "sWidthOrig": null
+ };
+
+
+ /*
+ * Developer note: The properties of the object below are given in Hungarian
+ * notation, that was used as the interface for DataTables prior to v1.10, however
+ * from v1.10 onwards the primary interface is camel case. In order to avoid
+ * breaking backwards compatibility utterly with this change, the Hungarian
+ * version is still, internally the primary interface, but is is not documented
+ * - hence the @name tags in each doc comment. This allows a Javascript function
+ * to create a map from Hungarian notation to camel case (going the other direction
+ * would require each property to be listed, which would at around 3K to the size
+ * of DataTables, while this method is about a 0.5K hit.
+ *
+ * Ultimately this does pave the way for Hungarian notation to be dropped
+ * completely, but that is a massive amount of work and will break current
+ * installs (therefore is on-hold until v2).
+ */
+
+ /**
+ * Initialisation options that can be given to DataTables at initialisation
+ * time.
+ * @namespace
+ */
+ DataTable.defaults = {
+ /**
+ * An array of data to use for the table, passed in at initialisation which
+ * will be used in preference to any data which is already in the DOM. This is
+ * particularly useful for constructing tables purely in Javascript, for
+ * example with a custom Ajax call.
+ * @type array
+ * @default null
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.data
+ *
+ * @example
+ * // Using a 2D array data source
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "data": [
+ * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
+ * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
+ * ],
+ * "columns": [
+ * { "title": "Engine" },
+ * { "title": "Browser" },
+ * { "title": "Platform" },
+ * { "title": "Version" },
+ * { "title": "Grade" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using an array of objects as a data source (`data`)
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "data": [
+ * {
+ * "engine": "Trident",
+ * "browser": "Internet Explorer 4.0",
+ * "platform": "Win 95+",
+ * "version": 4,
+ * "grade": "X"
+ * },
+ * {
+ * "engine": "Trident",
+ * "browser": "Internet Explorer 5.0",
+ * "platform": "Win 95+",
+ * "version": 5,
+ * "grade": "C"
+ * }
+ * ],
+ * "columns": [
+ * { "title": "Engine", "data": "engine" },
+ * { "title": "Browser", "data": "browser" },
+ * { "title": "Platform", "data": "platform" },
+ * { "title": "Version", "data": "version" },
+ * { "title": "Grade", "data": "grade" }
+ * ]
+ * } );
+ * } );
+ */
+ "aaData": null,
+
+
+ /**
+ * If ordering is enabled, then DataTables will perform a first pass sort on
+ * initialisation. You can define which column(s) the sort is performed
+ * upon, and the sorting direction, with this variable. The `sorting` array
+ * should contain an array for each column to be sorted initially containing
+ * the column's index and a direction string ('asc' or 'desc').
+ * @type array
+ * @default [[0,'asc']]
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.order
+ *
+ * @example
+ * // Sort by 3rd column first, and then 4th column
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "order": [[2,'asc'], [3,'desc']]
+ * } );
+ * } );
+ *
+ * // No initial sorting
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "order": []
+ * } );
+ * } );
+ */
+ "aaSorting": [[0,'asc']],
+
+
+ /**
+ * This parameter is basically identical to the `sorting` parameter, but
+ * cannot be overridden by user interaction with the table. What this means
+ * is that you could have a column (visible or hidden) which the sorting
+ * will always be forced on first - any sorting after that (from the user)
+ * will then be performed as required. This can be useful for grouping rows
+ * together.
+ * @type array
+ * @default null
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.orderFixed
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "orderFixed": [[0,'asc']]
+ * } );
+ * } )
+ */
+ "aaSortingFixed": [],
+
+
+ /**
+ * DataTables can be instructed to load data to display in the table from a
+ * Ajax source. This option defines how that Ajax call is made and where to.
+ *
+ * The `ajax` property has three different modes of operation, depending on
+ * how it is defined. These are:
+ *
+ * * `string` - Set the URL from where the data should be loaded from.
+ * * `object` - Define properties for `jQuery.ajax`.
+ * * `function` - Custom data get function
+ *
+ * `string`
+ * --------
+ *
+ * As a string, the `ajax` property simply defines the URL from which
+ * DataTables will load data.
+ *
+ * `object`
+ * --------
+ *
+ * As an object, the parameters in the object are passed to
+ * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
+ * of the Ajax request. DataTables has a number of default parameters which
+ * you can override using this option. Please refer to the jQuery
+ * documentation for a full description of the options available, although
+ * the following parameters provide additional options in DataTables or
+ * require special consideration:
+ *
+ * * `data` - As with jQuery, `data` can be provided as an object, but it
+ * can also be used as a function to manipulate the data DataTables sends
+ * to the server. The function takes a single parameter, an object of
+ * parameters with the values that DataTables has readied for sending. An
+ * object may be returned which will be merged into the DataTables
+ * defaults, or you can add the items to the object that was passed in and
+ * not return anything from the function. This supersedes `fnServerParams`
+ * from DataTables 1.9-.
+ *
+ * * `dataSrc` - By default DataTables will look for the property `data` (or
+ * `aaData` for compatibility with DataTables 1.9-) when obtaining data
+ * from an Ajax source or for server-side processing - this parameter
+ * allows that property to be changed. You can use Javascript dotted
+ * object notation to get a data source for multiple levels of nesting, or
+ * it my be used as a function. As a function it takes a single parameter,
+ * the JSON returned from the server, which can be manipulated as
+ * required, with the returned value being that used by DataTables as the
+ * data source for the table. This supersedes `sAjaxDataProp` from
+ * DataTables 1.9-.
+ *
+ * * `success` - Should not be overridden it is used internally in
+ * DataTables. To manipulate / transform the data returned by the server
+ * use `ajax.dataSrc`, or use `ajax` as a function (see below).
+ *
+ * `function`
+ * ----------
+ *
+ * As a function, making the Ajax call is left up to yourself allowing
+ * complete control of the Ajax request. Indeed, if desired, a method other
+ * than Ajax could be used to obtain the required data, such as Web storage
+ * or an AIR database.
+ *
+ * The function is given four parameters and no return is required. The
+ * parameters are:
+ *
+ * 1. _object_ - Data to send to the server
+ * 2. _function_ - Callback function that must be executed when the required
+ * data has been obtained. That data should be passed into the callback
+ * as the only parameter
+ * 3. _object_ - DataTables settings object for the table
+ *
+ * Note that this supersedes `fnServerData` from DataTables 1.9-.
+ *
+ * @type string|object|function
+ * @default null
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.ajax
+ * @since 1.10.0
+ *
+ * @example
+ * // Get JSON data from a file via Ajax.
+ * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
+ * $('#example').dataTable( {
+ * "ajax": "data.json"
+ * } );
+ *
+ * @example
+ * // Get JSON data from a file via Ajax, using `dataSrc` to change
+ * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
+ * $('#example').dataTable( {
+ * "ajax": {
+ * "url": "data.json",
+ * "dataSrc": "tableData"
+ * }
+ * } );
+ *
+ * @example
+ * // Get JSON data from a file via Ajax, using `dataSrc` to read data
+ * // from a plain array rather than an array in an object
+ * $('#example').dataTable( {
+ * "ajax": {
+ * "url": "data.json",
+ * "dataSrc": ""
+ * }
+ * } );
+ *
+ * @example
+ * // Manipulate the data returned from the server - add a link to data
+ * // (note this can, should, be done using `render` for the column - this
+ * // is just a simple example of how the data can be manipulated).
+ * $('#example').dataTable( {
+ * "ajax": {
+ * "url": "data.json",
+ * "dataSrc": function ( json ) {
+ * for ( var i=0, ien=json.length ; i
+ *
a string - class name will be matched on the TH for the column
+ *
0 or a positive integer - column index counting from the left
+ *
a negative integer - column index counting from the right
+ *
the string "_all" - all columns (i.e. assign a default)
+ *
+ * @member
+ *
+ * @name DataTable.defaults.columnDefs
+ */
+ "aoColumnDefs": null,
+
+
+ /**
+ * Basically the same as `search`, this parameter defines the individual column
+ * filtering state at initialisation time. The array must be of the same size
+ * as the number of columns, and each element be an object with the parameters
+ * `search` and `escapeRegex` (the latter is optional). 'null' is also
+ * accepted and the default will be used.
+ * @type array
+ * @default []
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.searchCols
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "searchCols": [
+ * null,
+ * { "search": "My filter" },
+ * null,
+ * { "search": "^[0-9]", "escapeRegex": false }
+ * ]
+ * } );
+ * } )
+ */
+ "aoSearchCols": [],
+
+
+ /**
+ * An array of CSS classes that should be applied to displayed rows. This
+ * array may be of any length, and DataTables will apply each class
+ * sequentially, looping when required.
+ * @type array
+ * @default null Will take the values determined by the `oClasses.stripe*`
+ * options
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.stripeClasses
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
+ * } );
+ * } )
+ */
+ "asStripeClasses": null,
+
+
+ /**
+ * Enable or disable automatic column width calculation. This can be disabled
+ * as an optimisation (it takes some time to calculate the widths) if the
+ * tables widths are passed in using `columns`.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.autoWidth
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "autoWidth": false
+ * } );
+ * } );
+ */
+ "bAutoWidth": true,
+
+
+ /**
+ * Deferred rendering can provide DataTables with a huge speed boost when you
+ * are using an Ajax or JS data source for the table. This option, when set to
+ * true, will cause DataTables to defer the creation of the table elements for
+ * each row until they are needed for a draw - saving a significant amount of
+ * time.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.deferRender
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "ajax": "sources/arrays.txt",
+ * "deferRender": true
+ * } );
+ * } );
+ */
+ "bDeferRender": false,
+
+
+ /**
+ * Replace a DataTable which matches the given selector and replace it with
+ * one which has the properties of the new initialisation object passed. If no
+ * table matches the selector, then the new DataTable will be constructed as
+ * per normal.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.destroy
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "srollY": "200px",
+ * "paginate": false
+ * } );
+ *
+ * // Some time later....
+ * $('#example').dataTable( {
+ * "filter": false,
+ * "destroy": true
+ * } );
+ * } );
+ */
+ "bDestroy": false,
+
+
+ /**
+ * Enable or disable filtering of data. Filtering in DataTables is "smart" in
+ * that it allows the end user to input multiple words (space separated) and
+ * will match a row containing those words, even if not in the order that was
+ * specified (this allow matching across multiple columns). Note that if you
+ * wish to use filtering in DataTables this must remain 'true' - to remove the
+ * default filtering input box and retain filtering abilities, please use
+ * {@link DataTable.defaults.dom}.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.searching
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "searching": false
+ * } );
+ * } );
+ */
+ "bFilter": true,
+
+
+ /**
+ * Enable or disable the table information display. This shows information
+ * about the data that is currently visible on the page, including information
+ * about filtered data if that action is being performed.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.info
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "info": false
+ * } );
+ * } );
+ */
+ "bInfo": true,
+
+
+ /**
+ * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
+ * slightly different and additional mark-up from what DataTables has
+ * traditionally used).
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.jQueryUI
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "jQueryUI": true
+ * } );
+ * } );
+ */
+ "bJQueryUI": false,
+
+
+ /**
+ * Allows the end user to select the size of a formatted page from a select
+ * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.lengthChange
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "lengthChange": false
+ * } );
+ * } );
+ */
+ "bLengthChange": true,
+
+
+ /**
+ * Enable or disable pagination.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.paging
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "paging": false
+ * } );
+ * } );
+ */
+ "bPaginate": true,
+
+
+ /**
+ * Enable or disable the display of a 'processing' indicator when the table is
+ * being processed (e.g. a sort). This is particularly useful for tables with
+ * large amounts of data where it can take a noticeable amount of time to sort
+ * the entries.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.processing
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "processing": true
+ * } );
+ * } );
+ */
+ "bProcessing": false,
+
+
+ /**
+ * Retrieve the DataTables object for the given selector. Note that if the
+ * table has already been initialised, this parameter will cause DataTables
+ * to simply return the object that has already been set up - it will not take
+ * account of any changes you might have made to the initialisation object
+ * passed to DataTables (setting this parameter to true is an acknowledgement
+ * that you understand this). `destroy` can be used to reinitialise a table if
+ * you need.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.retrieve
+ *
+ * @example
+ * $(document).ready( function() {
+ * initTable();
+ * tableActions();
+ * } );
+ *
+ * function initTable ()
+ * {
+ * return $('#example').dataTable( {
+ * "scrollY": "200px",
+ * "paginate": false,
+ * "retrieve": true
+ * } );
+ * }
+ *
+ * function tableActions ()
+ * {
+ * var table = initTable();
+ * // perform API operations with oTable
+ * }
+ */
+ "bRetrieve": false,
+
+
+ /**
+ * When vertical (y) scrolling is enabled, DataTables will force the height of
+ * the table's viewport to the given height at all times (useful for layout).
+ * However, this can look odd when filtering data down to a small data set,
+ * and the footer is left "floating" further down. This parameter (when
+ * enabled) will cause DataTables to collapse the table's viewport down when
+ * the result set will fit within the given Y height.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.scrollCollapse
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "scrollY": "200",
+ * "scrollCollapse": true
+ * } );
+ * } );
+ */
+ "bScrollCollapse": false,
+
+
+ /**
+ * Configure DataTables to use server-side processing. Note that the
+ * `ajax` parameter must also be given in order to give DataTables a
+ * source to obtain the required data for each draw.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @dtopt Server-side
+ * @name DataTable.defaults.serverSide
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "serverSide": true,
+ * "ajax": "xhr.php"
+ * } );
+ * } );
+ */
+ "bServerSide": false,
+
+
+ /**
+ * Enable or disable sorting of columns. Sorting of individual columns can be
+ * disabled by the `sortable` option for each column.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.ordering
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "ordering": false
+ * } );
+ * } );
+ */
+ "bSort": true,
+
+
+ /**
+ * Enable or display DataTables' ability to sort multiple columns at the
+ * same time (activated by shift-click by the user).
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.orderMulti
+ *
+ * @example
+ * // Disable multiple column sorting ability
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "orderMulti": false
+ * } );
+ * } );
+ */
+ "bSortMulti": true,
+
+
+ /**
+ * Allows control over whether DataTables should use the top (true) unique
+ * cell that is found for a single column, or the bottom (false - default).
+ * This is useful when using complex headers.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.orderCellsTop
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "orderCellsTop": true
+ * } );
+ * } );
+ */
+ "bSortCellsTop": false,
+
+
+ /**
+ * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
+ * `sorting\_3` to the columns which are currently being sorted on. This is
+ * presented as a feature switch as it can increase processing time (while
+ * classes are removed and added) so for large data sets you might want to
+ * turn this off.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.orderClasses
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "orderClasses": false
+ * } );
+ * } );
+ */
+ "bSortClasses": true,
+
+
+ /**
+ * Enable or disable state saving. When enabled HTML5 `localStorage` will be
+ * used to save table display information such as pagination information,
+ * display length, filtering and sorting. As such when the end user reloads
+ * the page the display display will match what thy had previously set up.
+ *
+ * Due to the use of `localStorage` the default state saving is not supported
+ * in IE6 or 7. If state saving is required in those browsers, use
+ * `stateSaveCallback` to provide a storage solution such as cookies.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.stateSave
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "stateSave": true
+ * } );
+ * } );
+ */
+ "bStateSave": false,
+
+
+ /**
+ * This function is called when a TR element is created (and all TD child
+ * elements have been inserted), or registered if using a DOM source, allowing
+ * manipulation of the TR element (adding classes etc).
+ * @type function
+ * @param {node} row "TR" element for the current row
+ * @param {array} data Raw data array for this row
+ * @param {int} dataIndex The index of this row in the internal aoData array
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.createdRow
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "createdRow": function( row, data, dataIndex ) {
+ * // Bold the grade for all 'A' grade browsers
+ * if ( data[4] == "A" )
+ * {
+ * $('td:eq(4)', row).html( 'A' );
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnCreatedRow": null,
+
+
+ /**
+ * This function is called on every 'draw' event, and allows you to
+ * dynamically modify any aspect you want about the created DOM.
+ * @type function
+ * @param {object} settings DataTables settings object
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.drawCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "drawCallback": function( settings ) {
+ * alert( 'DataTables has redrawn the table' );
+ * }
+ * } );
+ * } );
+ */
+ "fnDrawCallback": null,
+
+
+ /**
+ * Identical to fnHeaderCallback() but for the table footer this function
+ * allows you to modify the table footer on every 'draw' event.
+ * @type function
+ * @param {node} foot "TR" element for the footer
+ * @param {array} data Full table data (as derived from the original HTML)
+ * @param {int} start Index for the current display starting point in the
+ * display array
+ * @param {int} end Index for the current display ending point in the
+ * display array
+ * @param {array int} display Index array to translate the visual position
+ * to the full data array
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.footerCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "footerCallback": function( tfoot, data, start, end, display ) {
+ * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
+ * }
+ * } );
+ * } )
+ */
+ "fnFooterCallback": null,
+
+
+ /**
+ * When rendering large numbers in the information element for the table
+ * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
+ * to have a comma separator for the 'thousands' units (e.g. 1 million is
+ * rendered as "1,000,000") to help readability for the end user. This
+ * function will override the default method DataTables uses.
+ * @type function
+ * @member
+ * @param {int} toFormat number to be formatted
+ * @returns {string} formatted string for DataTables to show the number
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.formatNumber
+ *
+ * @example
+ * // Format a number using a single quote for the separator (note that
+ * // this can also be done with the language.thousands option)
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "formatNumber": function ( toFormat ) {
+ * return toFormat.toString().replace(
+ * /\B(?=(\d{3})+(?!\d))/g, "'"
+ * );
+ * };
+ * } );
+ * } );
+ */
+ "fnFormatNumber": function ( toFormat ) {
+ return toFormat.toString().replace(
+ /\B(?=(\d{3})+(?!\d))/g,
+ this.oLanguage.sThousands
+ );
+ },
+
+
+ /**
+ * This function is called on every 'draw' event, and allows you to
+ * dynamically modify the header row. This can be used to calculate and
+ * display useful information about the table.
+ * @type function
+ * @param {node} head "TR" element for the header
+ * @param {array} data Full table data (as derived from the original HTML)
+ * @param {int} start Index for the current display starting point in the
+ * display array
+ * @param {int} end Index for the current display ending point in the
+ * display array
+ * @param {array int} display Index array to translate the visual position
+ * to the full data array
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.headerCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "fheaderCallback": function( head, data, start, end, display ) {
+ * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
+ * }
+ * } );
+ * } )
+ */
+ "fnHeaderCallback": null,
+
+
+ /**
+ * The information element can be used to convey information about the current
+ * state of the table. Although the internationalisation options presented by
+ * DataTables are quite capable of dealing with most customisations, there may
+ * be times where you wish to customise the string further. This callback
+ * allows you to do exactly that.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @param {int} start Starting position in data for the draw
+ * @param {int} end End position in data for the draw
+ * @param {int} max Total number of rows in the table (regardless of
+ * filtering)
+ * @param {int} total Total number of rows in the data set, after filtering
+ * @param {string} pre The string that DataTables has formatted using it's
+ * own rules
+ * @returns {string} The string to be displayed in the information element.
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.infoCallback
+ *
+ * @example
+ * $('#example').dataTable( {
+ * "infoCallback": function( settings, start, end, max, total, pre ) {
+ * return start +" to "+ end;
+ * }
+ * } );
+ */
+ "fnInfoCallback": null,
+
+
+ /**
+ * Called when the table has been initialised. Normally DataTables will
+ * initialise sequentially and there will be no need for this function,
+ * however, this does not hold true when using external language information
+ * since that is obtained using an async XHR call.
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @param {object} json The JSON object request from the server - only
+ * present if client-side Ajax sourced data is used
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.initComplete
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "initComplete": function(settings, json) {
+ * alert( 'DataTables has finished its initialisation.' );
+ * }
+ * } );
+ * } )
+ */
+ "fnInitComplete": null,
+
+
+ /**
+ * Called at the very start of each table draw and can be used to cancel the
+ * draw by returning false, any other return (including undefined) results in
+ * the full draw occurring).
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @returns {boolean} False will cancel the draw, anything else (including no
+ * return) will allow it to complete.
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.preDrawCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "preDrawCallback": function( settings ) {
+ * if ( $('#test').val() == 1 ) {
+ * return false;
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnPreDrawCallback": null,
+
+
+ /**
+ * This function allows you to 'post process' each row after it have been
+ * generated for each table draw, but before it is rendered on screen. This
+ * function might be used for setting the row class name etc.
+ * @type function
+ * @param {node} row "TR" element for the current row
+ * @param {array} data Raw data array for this row
+ * @param {int} displayIndex The display index for the current table draw
+ * @param {int} displayIndexFull The index of the data in the full list of
+ * rows (after filtering)
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.rowCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
+ * // Bold the grade for all 'A' grade browsers
+ * if ( data[4] == "A" ) {
+ * $('td:eq(4)', row).html( 'A' );
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnRowCallback": null,
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * This parameter allows you to override the default function which obtains
+ * the data from the server so something more suitable for your application.
+ * For example you could use POST data, or pull information from a Gears or
+ * AIR database.
+ * @type function
+ * @member
+ * @param {string} source HTTP source to obtain the data from (`ajax`)
+ * @param {array} data A key/value pair object containing the data to send
+ * to the server
+ * @param {function} callback to be called on completion of the data get
+ * process that will draw the data on the page.
+ * @param {object} settings DataTables settings object
+ *
+ * @dtopt Callbacks
+ * @dtopt Server-side
+ * @name DataTable.defaults.serverData
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "fnServerData": null,
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * It is often useful to send extra data to the server when making an Ajax
+ * request - for example custom filtering information, and this callback
+ * function makes it trivial to send extra information to the server. The
+ * passed in parameter is the data set that has been constructed by
+ * DataTables, and you can add to this or modify it as you require.
+ * @type function
+ * @param {array} data Data array (array of objects which are name/value
+ * pairs) that has been constructed by DataTables and will be sent to the
+ * server. In the case of Ajax sourced data with server-side processing
+ * this will be an empty array, for server-side processing there will be a
+ * significant number of parameters!
+ * @returns {undefined} Ensure that you modify the data array passed in,
+ * as this is passed by reference.
+ *
+ * @dtopt Callbacks
+ * @dtopt Server-side
+ * @name DataTable.defaults.serverParams
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "fnServerParams": null,
+
+
+ /**
+ * Load the table state. With this function you can define from where, and how, the
+ * state of a table is loaded. By default DataTables will load from `localStorage`
+ * but you might wish to use a server-side database or cookies.
+ * @type function
+ * @member
+ * @param {object} settings DataTables settings object
+ * @return {object} The DataTables state object to be loaded
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateLoadCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateLoadCallback": function (settings) {
+ * var o;
+ *
+ * // Send an Ajax request to the server to get the data. Note that
+ * // this is a synchronous request.
+ * $.ajax( {
+ * "url": "/state_load",
+ * "async": false,
+ * "dataType": "json",
+ * "success": function (json) {
+ * o = json;
+ * }
+ * } );
+ *
+ * return o;
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoadCallback": function ( settings ) {
+ try {
+ return JSON.parse(
+ (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
+ 'DataTables_'+settings.sInstance+'_'+location.pathname
+ )
+ );
+ } catch (e) {}
+ },
+
+
+ /**
+ * Callback which allows modification of the saved state prior to loading that state.
+ * This callback is called when the table is loading state from the stored data, but
+ * prior to the settings object being modified by the saved state. Note that for
+ * plug-in authors, you should use the `stateLoadParams` event to load parameters for
+ * a plug-in.
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @param {object} data The state object that is to be loaded
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateLoadParams
+ *
+ * @example
+ * // Remove a saved filter, so filtering is never loaded
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateLoadParams": function (settings, data) {
+ * data.oSearch.sSearch = "";
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Disallow state loading by returning false
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateLoadParams": function (settings, data) {
+ * return false;
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoadParams": null,
+
+
+ /**
+ * Callback that is called when the state has been loaded from the state saving method
+ * and the DataTables settings object has been modified as a result of the loaded state.
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @param {object} data The state object that was loaded
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateLoaded
+ *
+ * @example
+ * // Show an alert with the filtering value that was saved
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateLoaded": function (settings, data) {
+ * alert( 'Saved filter was: '+data.oSearch.sSearch );
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoaded": null,
+
+
+ /**
+ * Save the table state. This function allows you to define where and how the state
+ * information for the table is stored By default DataTables will use `localStorage`
+ * but you might wish to use a server-side database or cookies.
+ * @type function
+ * @member
+ * @param {object} settings DataTables settings object
+ * @param {object} data The state object to be saved
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateSaveCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateSaveCallback": function (settings, data) {
+ * // Send an Ajax request to the server with the state object
+ * $.ajax( {
+ * "url": "/state_save",
+ * "data": data,
+ * "dataType": "json",
+ * "method": "POST"
+ * "success": function () {}
+ * } );
+ * }
+ * } );
+ * } );
+ */
+ "fnStateSaveCallback": function ( settings, data ) {
+ try {
+ (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
+ 'DataTables_'+settings.sInstance+'_'+location.pathname,
+ JSON.stringify( data )
+ );
+ } catch (e) {}
+ },
+
+
+ /**
+ * Callback which allows modification of the state to be saved. Called when the table
+ * has changed state a new state save is required. This method allows modification of
+ * the state saving object prior to actually doing the save, including addition or
+ * other state properties or modification. Note that for plug-in authors, you should
+ * use the `stateSaveParams` event to save parameters for a plug-in.
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @param {object} data The state object to be saved
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateSaveParams
+ *
+ * @example
+ * // Remove a saved filter, so filtering is never saved
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateSaveParams": function (settings, data) {
+ * data.oSearch.sSearch = "";
+ * }
+ * } );
+ * } );
+ */
+ "fnStateSaveParams": null,
+
+
+ /**
+ * Duration for which the saved state information is considered valid. After this period
+ * has elapsed the state will be returned to the default.
+ * Value is given in seconds.
+ * @type int
+ * @default 7200 (2 hours)
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.stateDuration
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateDuration": 60*60*24; // 1 day
+ * } );
+ * } )
+ */
+ "iStateDuration": 7200,
+
+
+ /**
+ * When enabled DataTables will not make a request to the server for the first
+ * page draw - rather it will use the data already on the page (no sorting etc
+ * will be applied to it), thus saving on an XHR at load time. `deferLoading`
+ * is used to indicate that deferred loading is required, but it is also used
+ * to tell DataTables how many records there are in the full table (allowing
+ * the information element and pagination to be displayed correctly). In the case
+ * where a filtering is applied to the table on initial load, this can be
+ * indicated by giving the parameter as an array, where the first element is
+ * the number of records available after filtering and the second element is the
+ * number of records without filtering (allowing the table information element
+ * to be shown correctly).
+ * @type int | array
+ * @default null
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.deferLoading
+ *
+ * @example
+ * // 57 records available in the table, no filtering applied
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "serverSide": true,
+ * "ajax": "scripts/server_processing.php",
+ * "deferLoading": 57
+ * } );
+ * } );
+ *
+ * @example
+ * // 57 records after filtering, 100 without filtering (an initial filter applied)
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "serverSide": true,
+ * "ajax": "scripts/server_processing.php",
+ * "deferLoading": [ 57, 100 ],
+ * "search": {
+ * "search": "my_filter"
+ * }
+ * } );
+ * } );
+ */
+ "iDeferLoading": null,
+
+
+ /**
+ * Number of rows to display on a single page when using pagination. If
+ * feature enabled (`lengthChange`) then the end user will be able to override
+ * this to a custom setting using a pop-up menu.
+ * @type int
+ * @default 10
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.pageLength
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "pageLength": 50
+ * } );
+ * } )
+ */
+ "iDisplayLength": 10,
+
+
+ /**
+ * Define the starting point for data display when using DataTables with
+ * pagination. Note that this parameter is the number of records, rather than
+ * the page number, so if you have 10 records per page and want to start on
+ * the third page, it should be "20".
+ * @type int
+ * @default 0
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.displayStart
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "displayStart": 20
+ * } );
+ * } )
+ */
+ "iDisplayStart": 0,
+
+
+ /**
+ * By default DataTables allows keyboard navigation of the table (sorting, paging,
+ * and filtering) by adding a `tabindex` attribute to the required elements. This
+ * allows you to tab through the controls and press the enter key to activate them.
+ * The tabindex is default 0, meaning that the tab follows the flow of the document.
+ * You can overrule this using this parameter if you wish. Use a value of -1 to
+ * disable built-in keyboard navigation.
+ * @type int
+ * @default 0
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.tabIndex
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "tabIndex": 1
+ * } );
+ * } );
+ */
+ "iTabIndex": 0,
+
+
+ /**
+ * Classes that DataTables assigns to the various components and features
+ * that it adds to the HTML table. This allows classes to be configured
+ * during initialisation in addition to through the static
+ * {@link DataTable.ext.oStdClasses} object).
+ * @namespace
+ * @name DataTable.defaults.classes
+ */
+ "oClasses": {},
+
+
+ /**
+ * All strings that DataTables uses in the user interface that it creates
+ * are defined in this object, allowing you to modified them individually or
+ * completely replace them all as required.
+ * @namespace
+ * @name DataTable.defaults.language
+ */
+ "oLanguage": {
+ /**
+ * Strings that are used for WAI-ARIA labels and controls only (these are not
+ * actually visible on the page, but will be read by screenreaders, and thus
+ * must be internationalised as well).
+ * @namespace
+ * @name DataTable.defaults.language.aria
+ */
+ "oAria": {
+ /**
+ * ARIA label that is added to the table headers when the column may be
+ * sorted ascending by activing the column (click or return when focused).
+ * Note that the column header is prefixed to this string.
+ * @type string
+ * @default : activate to sort column ascending
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.aria.sortAscending
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "aria": {
+ * "sortAscending": " - click/return to sort ascending"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sSortAscending": ": activate to sort column ascending",
+
+ /**
+ * ARIA label that is added to the table headers when the column may be
+ * sorted descending by activing the column (click or return when focused).
+ * Note that the column header is prefixed to this string.
+ * @type string
+ * @default : activate to sort column ascending
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.aria.sortDescending
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "aria": {
+ * "sortDescending": " - click/return to sort descending"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sSortDescending": ": activate to sort column descending"
+ },
+
+ /**
+ * Pagination string used by DataTables for the built-in pagination
+ * control types.
+ * @namespace
+ * @name DataTable.defaults.language.paginate
+ */
+ "oPaginate": {
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the first page.
+ * @type string
+ * @default First
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.paginate.first
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "paginate": {
+ * "first": "First page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sFirst": "First",
+
+
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the last page.
+ * @type string
+ * @default Last
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.paginate.last
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "paginate": {
+ * "last": "Last page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sLast": "Last",
+
+
+ /**
+ * Text to use for the 'next' pagination button (to take the user to the
+ * next page).
+ * @type string
+ * @default Next
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.paginate.next
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "paginate": {
+ * "next": "Next page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sNext": "Next",
+
+
+ /**
+ * Text to use for the 'previous' pagination button (to take the user to
+ * the previous page).
+ * @type string
+ * @default Previous
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.paginate.previous
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "paginate": {
+ * "previous": "Previous page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sPrevious": "Previous"
+ },
+
+ /**
+ * This string is shown in preference to `zeroRecords` when the table is
+ * empty of data (regardless of filtering). Note that this is an optional
+ * parameter - if it is not given, the value of `zeroRecords` will be used
+ * instead (either the default or given value).
+ * @type string
+ * @default No data available in table
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.emptyTable
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "emptyTable": "No data available in table"
+ * }
+ * } );
+ * } );
+ */
+ "sEmptyTable": "No data available in table",
+
+
+ /**
+ * This string gives information to the end user about the information
+ * that is current on display on the page. The following tokens can be
+ * used in the string and will be dynamically replaced as the table
+ * display updates. This tokens can be placed anywhere in the string, or
+ * removed as needed by the language requires:
+ *
+ * * `\_START\_` - Display index of the first record on the current page
+ * * `\_END\_` - Display index of the last record on the current page
+ * * `\_TOTAL\_` - Number of records in the table after filtering
+ * * `\_MAX\_` - Number of records in the table without filtering
+ * * `\_PAGE\_` - Current page number
+ * * `\_PAGES\_` - Total number of pages of data in the table
+ *
+ * @type string
+ * @default Showing _START_ to _END_ of _TOTAL_ entries
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.info
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "info": "Showing page _PAGE_ of _PAGES_"
+ * }
+ * } );
+ * } );
+ */
+ "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
+
+
+ /**
+ * Display information string for when the table is empty. Typically the
+ * format of this string should match `info`.
+ * @type string
+ * @default Showing 0 to 0 of 0 entries
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.infoEmpty
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "infoEmpty": "No entries to show"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoEmpty": "Showing 0 to 0 of 0 entries",
+
+
+ /**
+ * When a user filters the information in a table, this string is appended
+ * to the information (`info`) to give an idea of how strong the filtering
+ * is. The variable _MAX_ is dynamically updated.
+ * @type string
+ * @default (filtered from _MAX_ total entries)
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.infoFiltered
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "infoFiltered": " - filtering from _MAX_ records"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoFiltered": "(filtered from _MAX_ total entries)",
+
+
+ /**
+ * If can be useful to append extra information to the info string at times,
+ * and this variable does exactly that. This information will be appended to
+ * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
+ * being used) at all times.
+ * @type string
+ * @default Empty string
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.infoPostFix
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "infoPostFix": "All records shown are derived from real information."
+ * }
+ * } );
+ * } );
+ */
+ "sInfoPostFix": "",
+
+
+ /**
+ * This decimal place operator is a little different from the other
+ * language options since DataTables doesn't output floating point
+ * numbers, so it won't ever use this for display of a number. Rather,
+ * what this parameter does is modify the sort methods of the table so
+ * that numbers which are in a format which has a character other than
+ * a period (`.`) as a decimal place will be sorted numerically.
+ *
+ * Note that numbers with different decimal places cannot be shown in
+ * the same table and still be sortable, the table must be consistent.
+ * However, multiple different tables on the page can use different
+ * decimal place characters.
+ * @type string
+ * @default
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.decimal
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "decimal": ","
+ * "thousands": "."
+ * }
+ * } );
+ * } );
+ */
+ "sDecimal": "",
+
+
+ /**
+ * DataTables has a build in number formatter (`formatNumber`) which is
+ * used to format large numbers that are used in the table information.
+ * By default a comma is used, but this can be trivially changed to any
+ * character you wish with this parameter.
+ * @type string
+ * @default ,
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.thousands
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "thousands": "'"
+ * }
+ * } );
+ * } );
+ */
+ "sThousands": ",",
+
+
+ /**
+ * Detail the action that will be taken when the drop down menu for the
+ * pagination length option is changed. The '_MENU_' variable is replaced
+ * with a default select list of 10, 25, 50 and 100, and can be replaced
+ * with a custom select box if required.
+ * @type string
+ * @default Show _MENU_ entries
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.lengthMenu
+ *
+ * @example
+ * // Language change only
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "lengthMenu": "Display _MENU_ records"
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Language and options change
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "lengthMenu": 'Display records'
+ * }
+ * } );
+ * } );
+ */
+ "sLengthMenu": "Show _MENU_ entries",
+
+
+ /**
+ * When using Ajax sourced data and during the first draw when DataTables is
+ * gathering the data, this message is shown in an empty row in the table to
+ * indicate to the end user the the data is being loaded. Note that this
+ * parameter is not used when loading data by server-side processing, just
+ * Ajax sourced data with client-side processing.
+ * @type string
+ * @default Loading...
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.loadingRecords
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "loadingRecords": "Please wait - loading..."
+ * }
+ * } );
+ * } );
+ */
+ "sLoadingRecords": "Loading...",
+
+
+ /**
+ * Text which is displayed when the table is processing a user action
+ * (usually a sort command or similar).
+ * @type string
+ * @default Processing...
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.processing
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "processing": "DataTables is currently busy"
+ * }
+ * } );
+ * } );
+ */
+ "sProcessing": "Processing...",
+
+
+ /**
+ * Details the actions that will be taken when the user types into the
+ * filtering input text box. The variable "_INPUT_", if used in the string,
+ * is replaced with the HTML text box for the filtering input allowing
+ * control over where it appears in the string. If "_INPUT_" is not given
+ * then the input box is appended to the string automatically.
+ * @type string
+ * @default Search:
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.search
+ *
+ * @example
+ * // Input text box will be appended at the end automatically
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "search": "Filter records:"
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Specify where the filter should appear
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "search": "Apply filter _INPUT_ to table"
+ * }
+ * } );
+ * } );
+ */
+ "sSearch": "Search:",
+
+
+ /**
+ * Assign a `placeholder` attribute to the search `input` element
+ * @type string
+ * @default
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.searchPlaceholder
+ */
+ "sSearchPlaceholder": "",
+
+
+ /**
+ * All of the language information can be stored in a file on the
+ * server-side, which DataTables will look up if this parameter is passed.
+ * It must store the URL of the language file, which is in a JSON format,
+ * and the object has the same properties as the oLanguage object in the
+ * initialiser object (i.e. the above parameters). Please refer to one of
+ * the example language files to see how this works in action.
+ * @type string
+ * @default Empty string - i.e. disabled
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.url
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
+ * }
+ * } );
+ * } );
+ */
+ "sUrl": "",
+
+
+ /**
+ * Text shown inside the table records when the is no information to be
+ * displayed after filtering. `emptyTable` is shown when there is simply no
+ * information in the table at all (regardless of filtering).
+ * @type string
+ * @default No matching records found
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.zeroRecords
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "zeroRecords": "No records to display"
+ * }
+ * } );
+ * } );
+ */
+ "sZeroRecords": "No matching records found"
+ },
+
+
+ /**
+ * This parameter allows you to have define the global filtering state at
+ * initialisation time. As an object the `search` parameter must be
+ * defined, but all other parameters are optional. When `regex` is true,
+ * the search string will be treated as a regular expression, when false
+ * (default) it will be treated as a straight string. When `smart`
+ * DataTables will use it's smart filtering methods (to word match at
+ * any point in the data), when false this will not be done.
+ * @namespace
+ * @extends DataTable.models.oSearch
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.search
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "search": {"search": "Initial search"}
+ * } );
+ * } )
+ */
+ "oSearch": $.extend( {}, DataTable.models.oSearch ),
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * By default DataTables will look for the property `data` (or `aaData` for
+ * compatibility with DataTables 1.9-) when obtaining data from an Ajax
+ * source or for server-side processing - this parameter allows that
+ * property to be changed. You can use Javascript dotted object notation to
+ * get a data source for multiple levels of nesting.
+ * @type string
+ * @default data
+ *
+ * @dtopt Options
+ * @dtopt Server-side
+ * @name DataTable.defaults.ajaxDataProp
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "sAjaxDataProp": "data",
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * You can instruct DataTables to load data from an external
+ * source using this parameter (use aData if you want to pass data in you
+ * already have). Simply provide a url a JSON object can be obtained from.
+ * @type string
+ * @default null
+ *
+ * @dtopt Options
+ * @dtopt Server-side
+ * @name DataTable.defaults.ajaxSource
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "sAjaxSource": null,
+
+
+ /**
+ * This initialisation variable allows you to specify exactly where in the
+ * DOM you want DataTables to inject the various controls it adds to the page
+ * (for example you might want the pagination controls at the top of the
+ * table). DIV elements (with or without a custom class) can also be added to
+ * aid styling. The follow syntax is used:
+ *
+ * @type string
+ * @default lfrtip (when `jQueryUI` is false)or
+ * <"H"lfr>t<"F"ip> (when `jQueryUI` is true)
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.dom
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "dom": '<"top"i>rt<"bottom"flp><"clear">'
+ * } );
+ * } );
+ */
+ "sDom": "lfrtip",
+
+
+ /**
+ * Search delay option. This will throttle full table searches that use the
+ * DataTables provided search input element (it does not effect calls to
+ * `dt-api search()`, providing a delay before the search is made.
+ * @type integer
+ * @default 0
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.searchDelay
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "searchDelay": 200
+ * } );
+ * } )
+ */
+ "searchDelay": null,
+
+
+ /**
+ * DataTables features four different built-in options for the buttons to
+ * display for pagination control:
+ *
+ * * `simple` - 'Previous' and 'Next' buttons only
+ * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
+ * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
+ * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
+ * page numbers
+ *
+ * Further methods can be added using {@link DataTable.ext.oPagination}.
+ * @type string
+ * @default simple_numbers
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.pagingType
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "pagingType": "full_numbers"
+ * } );
+ * } )
+ */
+ "sPaginationType": "simple_numbers",
+
+
+ /**
+ * Enable horizontal scrolling. When a table is too wide to fit into a
+ * certain layout, or you have a large number of columns in the table, you
+ * can enable x-scrolling to show the table in a viewport, which can be
+ * scrolled. This property can be `true` which will allow the table to
+ * scroll horizontally when needed, or any CSS unit, or a number (in which
+ * case it will be treated as a pixel measurement). Setting as simply `true`
+ * is recommended.
+ * @type boolean|string
+ * @default blank string - i.e. disabled
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.scrollX
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "scrollX": true,
+ * "scrollCollapse": true
+ * } );
+ * } );
+ */
+ "sScrollX": "",
+
+
+ /**
+ * This property can be used to force a DataTable to use more width than it
+ * might otherwise do when x-scrolling is enabled. For example if you have a
+ * table which requires to be well spaced, this parameter is useful for
+ * "over-sizing" the table, and thus forcing scrolling. This property can by
+ * any CSS unit, or a number (in which case it will be treated as a pixel
+ * measurement).
+ * @type string
+ * @default blank string - i.e. disabled
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.scrollXInner
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "scrollX": "100%",
+ * "scrollXInner": "110%"
+ * } );
+ * } );
+ */
+ "sScrollXInner": "",
+
+
+ /**
+ * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
+ * to the given height, and enable scrolling for any data which overflows the
+ * current viewport. This can be used as an alternative to paging to display
+ * a lot of data in a small area (although paging and scrolling can both be
+ * enabled at the same time). This property can be any CSS unit, or a number
+ * (in which case it will be treated as a pixel measurement).
+ * @type string
+ * @default blank string - i.e. disabled
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.scrollY
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "scrollY": "200px",
+ * "paginate": false
+ * } );
+ * } );
+ */
+ "sScrollY": "",
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * Set the HTTP method that is used to make the Ajax call for server-side
+ * processing or Ajax sourced data.
+ * @type string
+ * @default GET
+ *
+ * @dtopt Options
+ * @dtopt Server-side
+ * @name DataTable.defaults.serverMethod
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "sServerMethod": "GET",
+
+
+ /**
+ * DataTables makes use of renderers when displaying HTML elements for
+ * a table. These renderers can be added or modified by plug-ins to
+ * generate suitable mark-up for a site. For example the Bootstrap
+ * integration plug-in for DataTables uses a paging button renderer to
+ * display pagination buttons in the mark-up required by Bootstrap.
+ *
+ * For further information about the renderers available see
+ * DataTable.ext.renderer
+ * @type string|object
+ * @default null
+ *
+ * @name DataTable.defaults.renderer
+ *
+ */
+ "renderer": null,
+
+
+ /**
+ * Set the data property name that DataTables should use to get a row's id
+ * to set as the `id` property in the node.
+ * @type string
+ * @default DT_RowId
+ *
+ * @name DataTable.defaults.rowId
+ */
+ "rowId": "DT_RowId"
+ };
+
+ _fnHungarianMap( DataTable.defaults );
+
+
+
+ /*
+ * Developer note - See note in model.defaults.js about the use of Hungarian
+ * notation and camel case.
+ */
+
+ /**
+ * Column options that can be given to DataTables at initialisation time.
+ * @namespace
+ */
+ DataTable.defaults.column = {
+ /**
+ * Define which column(s) an order will occur on for this column. This
+ * allows a column's ordering to take multiple columns into account when
+ * doing a sort or use the data from a different column. For example first
+ * name / last name columns make sense to do a multi-column sort over the
+ * two columns.
+ * @type array|int
+ * @default null Takes the value of the column index automatically
+ *
+ * @name DataTable.defaults.column.orderData
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
+ * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
+ * { "orderData": 2, "targets": [ 2 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "orderData": [ 0, 1 ] },
+ * { "orderData": [ 1, 0 ] },
+ * { "orderData": 2 },
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "aDataSort": null,
+ "iDataSort": -1,
+
+
+ /**
+ * You can control the default ordering direction, and even alter the
+ * behaviour of the sort handler (i.e. only allow ascending ordering etc)
+ * using this parameter.
+ * @type array
+ * @default [ 'asc', 'desc' ]
+ *
+ * @name DataTable.defaults.column.orderSequence
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
+ * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
+ * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * null,
+ * { "orderSequence": [ "asc" ] },
+ * { "orderSequence": [ "desc", "asc", "asc" ] },
+ * { "orderSequence": [ "desc" ] },
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "asSorting": [ 'asc', 'desc' ],
+
+
+ /**
+ * Enable or disable filtering on the data in this column.
+ * @type boolean
+ * @default true
+ *
+ * @name DataTable.defaults.column.searchable
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "searchable": false, "targets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "searchable": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bSearchable": true,
+
+
+ /**
+ * Enable or disable ordering on this column.
+ * @type boolean
+ * @default true
+ *
+ * @name DataTable.defaults.column.orderable
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "orderable": false, "targets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "orderable": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bSortable": true,
+
+
+ /**
+ * Enable or disable the display of this column.
+ * @type boolean
+ * @default true
+ *
+ * @name DataTable.defaults.column.visible
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "visible": false, "targets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "visible": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bVisible": true,
+
+
+ /**
+ * Developer definable function that is called whenever a cell is created (Ajax source,
+ * etc) or processed for input (DOM source). This can be used as a compliment to mRender
+ * allowing you to modify the DOM element (add background colour for example) when the
+ * element is available.
+ * @type function
+ * @param {element} td The TD node that has been created
+ * @param {*} cellData The Data for the cell
+ * @param {array|object} rowData The data for the whole row
+ * @param {int} row The row index for the aoData data store
+ * @param {int} col The column index for aoColumns
+ *
+ * @name DataTable.defaults.column.createdCell
+ * @dtopt Columns
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [3],
+ * "createdCell": function (td, cellData, rowData, row, col) {
+ * if ( cellData == "1.7" ) {
+ * $(td).css('color', 'blue')
+ * }
+ * }
+ * } ]
+ * });
+ * } );
+ */
+ "fnCreatedCell": null,
+
+
+ /**
+ * This parameter has been replaced by `data` in DataTables to ensure naming
+ * consistency. `dataProp` can still be used, as there is backwards
+ * compatibility in DataTables for this option, but it is strongly
+ * recommended that you use `data` in preference to `dataProp`.
+ * @name DataTable.defaults.column.dataProp
+ */
+
+
+ /**
+ * This property can be used to read data from any data source property,
+ * including deeply nested objects / properties. `data` can be given in a
+ * number of different ways which effect its behaviour:
+ *
+ * * `integer` - treated as an array index for the data source. This is the
+ * default that DataTables uses (incrementally increased for each column).
+ * * `string` - read an object property from the data source. There are
+ * three 'special' options that can be used in the string to alter how
+ * DataTables reads the data from the source object:
+ * * `.` - Dotted Javascript notation. Just as you use a `.` in
+ * Javascript to read from nested objects, so to can the options
+ * specified in `data`. For example: `browser.version` or
+ * `browser.name`. If your object parameter name contains a period, use
+ * `\\` to escape it - i.e. `first\\.name`.
+ * * `[]` - Array notation. DataTables can automatically combine data
+ * from and array source, joining the data with the characters provided
+ * between the two brackets. For example: `name[, ]` would provide a
+ * comma-space separated list from the source array. If no characters
+ * are provided between the brackets, the original array source is
+ * returned.
+ * * `()` - Function notation. Adding `()` to the end of a parameter will
+ * execute a function of the name given. For example: `browser()` for a
+ * simple function on the data source, `browser.version()` for a
+ * function in a nested property or even `browser().version` to get an
+ * object property if the function called returns an object. Note that
+ * function notation is recommended for use in `render` rather than
+ * `data` as it is much simpler to use as a renderer.
+ * * `null` - use the original data source for the row rather than plucking
+ * data directly from it. This action has effects on two other
+ * initialisation options:
+ * * `defaultContent` - When null is given as the `data` option and
+ * `defaultContent` is specified for the column, the value defined by
+ * `defaultContent` will be used for the cell.
+ * * `render` - When null is used for the `data` option and the `render`
+ * option is specified for the column, the whole data source for the
+ * row is used for the renderer.
+ * * `function` - the function given will be executed whenever DataTables
+ * needs to set or get the data for a cell in the column. The function
+ * takes three parameters:
+ * * Parameters:
+ * * `{array|object}` The data source for the row
+ * * `{string}` The type call data requested - this will be 'set' when
+ * setting data or 'filter', 'display', 'type', 'sort' or undefined
+ * when gathering data. Note that when `undefined` is given for the
+ * type DataTables expects to get the raw data for the object back<
+ * * `{*}` Data to set when the second parameter is 'set'.
+ * * Return:
+ * * The return value from the function is not required when 'set' is
+ * the type of call, but otherwise the return is what will be used
+ * for the data requested.
+ *
+ * Note that `data` is a getter and setter option. If you just require
+ * formatting of data for output, you will likely want to use `render` which
+ * is simply a getter and thus simpler to use.
+ *
+ * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
+ * name change reflects the flexibility of this property and is consistent
+ * with the naming of mRender. If 'mDataProp' is given, then it will still
+ * be used by DataTables, as it automatically maps the old name to the new
+ * if required.
+ *
+ * @type string|int|function|null
+ * @default null Use automatically calculated column index
+ *
+ * @name DataTable.defaults.column.data
+ * @dtopt Columns
+ *
+ * @example
+ * // Read table data from objects
+ * // JSON structure for each row:
+ * // {
+ * // "engine": {value},
+ * // "browser": {value},
+ * // "platform": {value},
+ * // "version": {value},
+ * // "grade": {value}
+ * // }
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "ajaxSource": "sources/objects.txt",
+ * "columns": [
+ * { "data": "engine" },
+ * { "data": "browser" },
+ * { "data": "platform" },
+ * { "data": "version" },
+ * { "data": "grade" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Read information from deeply nested objects
+ * // JSON structure for each row:
+ * // {
+ * // "engine": {value},
+ * // "browser": {value},
+ * // "platform": {
+ * // "inner": {value}
+ * // },
+ * // "details": [
+ * // {value}, {value}
+ * // ]
+ * // }
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "ajaxSource": "sources/deep.txt",
+ * "columns": [
+ * { "data": "engine" },
+ * { "data": "browser" },
+ * { "data": "platform.inner" },
+ * { "data": "platform.details.0" },
+ * { "data": "platform.details.1" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `data` as a function to provide different information for
+ * // sorting, filtering and display. In this case, currency (price)
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": function ( source, type, val ) {
+ * if (type === 'set') {
+ * source.price = val;
+ * // Store the computed dislay and filter values for efficiency
+ * source.price_display = val=="" ? "" : "$"+numberFormat(val);
+ * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
+ * return;
+ * }
+ * else if (type === 'display') {
+ * return source.price_display;
+ * }
+ * else if (type === 'filter') {
+ * return source.price_filter;
+ * }
+ * // 'sort', 'type' and undefined all just use the integer
+ * return source.price;
+ * }
+ * } ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using default content
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": null,
+ * "defaultContent": "Click to edit"
+ * } ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using array notation - outputting a list from an array
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": "name[, ]"
+ * } ]
+ * } );
+ * } );
+ *
+ */
+ "mData": null,
+
+
+ /**
+ * This property is the rendering partner to `data` and it is suggested that
+ * when you want to manipulate data for display (including filtering,
+ * sorting etc) without altering the underlying data for the table, use this
+ * property. `render` can be considered to be the the read only companion to
+ * `data` which is read / write (then as such more complex). Like `data`
+ * this option can be given in a number of different ways to effect its
+ * behaviour:
+ *
+ * * `integer` - treated as an array index for the data source. This is the
+ * default that DataTables uses (incrementally increased for each column).
+ * * `string` - read an object property from the data source. There are
+ * three 'special' options that can be used in the string to alter how
+ * DataTables reads the data from the source object:
+ * * `.` - Dotted Javascript notation. Just as you use a `.` in
+ * Javascript to read from nested objects, so to can the options
+ * specified in `data`. For example: `browser.version` or
+ * `browser.name`. If your object parameter name contains a period, use
+ * `\\` to escape it - i.e. `first\\.name`.
+ * * `[]` - Array notation. DataTables can automatically combine data
+ * from and array source, joining the data with the characters provided
+ * between the two brackets. For example: `name[, ]` would provide a
+ * comma-space separated list from the source array. If no characters
+ * are provided between the brackets, the original array source is
+ * returned.
+ * * `()` - Function notation. Adding `()` to the end of a parameter will
+ * execute a function of the name given. For example: `browser()` for a
+ * simple function on the data source, `browser.version()` for a
+ * function in a nested property or even `browser().version` to get an
+ * object property if the function called returns an object.
+ * * `object` - use different data for the different data types requested by
+ * DataTables ('filter', 'display', 'type' or 'sort'). The property names
+ * of the object is the data type the property refers to and the value can
+ * defined using an integer, string or function using the same rules as
+ * `render` normally does. Note that an `_` option _must_ be specified.
+ * This is the default value to use if you haven't specified a value for
+ * the data type requested by DataTables.
+ * * `function` - the function given will be executed whenever DataTables
+ * needs to set or get the data for a cell in the column. The function
+ * takes three parameters:
+ * * Parameters:
+ * * {array|object} The data source for the row (based on `data`)
+ * * {string} The type call data requested - this will be 'filter',
+ * 'display', 'type' or 'sort'.
+ * * {array|object} The full data source for the row (not based on
+ * `data`)
+ * * Return:
+ * * The return value from the function is what will be used for the
+ * data requested.
+ *
+ * @type string|int|function|object|null
+ * @default null Use the data source value.
+ *
+ * @name DataTable.defaults.column.render
+ * @dtopt Columns
+ *
+ * @example
+ * // Create a comma separated list from an array of objects
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "ajaxSource": "sources/deep.txt",
+ * "columns": [
+ * { "data": "engine" },
+ * { "data": "browser" },
+ * {
+ * "data": "platform",
+ * "render": "[, ].name"
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Execute a function to obtain data
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": null, // Use the full data source object for the renderer's source
+ * "render": "browserName()"
+ * } ]
+ * } );
+ * } );
+ *
+ * @example
+ * // As an object, extracting different data for the different types
+ * // This would be used with a data source such as:
+ * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
+ * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
+ * // (which has both forms) is used for filtering for if a user inputs either format, while
+ * // the formatted phone number is the one that is shown in the table.
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": null, // Use the full data source object for the renderer's source
+ * "render": {
+ * "_": "phone",
+ * "filter": "phone_filter",
+ * "display": "phone_display"
+ * }
+ * } ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Use as a function to create a link from the data source
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": "download_link",
+ * "render": function ( data, type, full ) {
+ * return 'Download';
+ * }
+ * } ]
+ * } );
+ * } );
+ */
+ "mRender": null,
+
+
+ /**
+ * Change the cell type created for the column - either TD cells or TH cells. This
+ * can be useful as TH cells have semantic meaning in the table body, allowing them
+ * to act as a header for a row (you may wish to add scope='row' to the TH elements).
+ * @type string
+ * @default td
+ *
+ * @name DataTable.defaults.column.cellType
+ * @dtopt Columns
+ *
+ * @example
+ * // Make the first column use TH cells
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "cellType": "th"
+ * } ]
+ * } );
+ * } );
+ */
+ "sCellType": "td",
+
+
+ /**
+ * Class to give to each cell in this column.
+ * @type string
+ * @default Empty string
+ *
+ * @name DataTable.defaults.column.class
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "class": "my_class", "targets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "class": "my_class" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sClass": "",
+
+ /**
+ * When DataTables calculates the column widths to assign to each column,
+ * it finds the longest string in each column and then constructs a
+ * temporary table and reads the widths from that. The problem with this
+ * is that "mmm" is much wider then "iiii", but the latter is a longer
+ * string - thus the calculation can go wrong (doing it properly and putting
+ * it into an DOM object and measuring that is horribly(!) slow). Thus as
+ * a "work around" we provide this option. It will append its value to the
+ * text that is found to be the longest string for the column - i.e. padding.
+ * Generally you shouldn't need this!
+ * @type string
+ * @default Empty string
+ *
+ * @name DataTable.defaults.column.contentPadding
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * null,
+ * null,
+ * null,
+ * {
+ * "contentPadding": "mmm"
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "sContentPadding": "",
+
+
+ /**
+ * Allows a default value to be given for a column's data, and will be used
+ * whenever a null data source is encountered (this can be because `data`
+ * is set to null, or because the data source itself is null).
+ * @type string
+ * @default null
+ *
+ * @name DataTable.defaults.column.defaultContent
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * {
+ * "data": null,
+ * "defaultContent": "Edit",
+ * "targets": [ -1 ]
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * null,
+ * null,
+ * null,
+ * {
+ * "data": null,
+ * "defaultContent": "Edit"
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "sDefaultContent": null,
+
+
+ /**
+ * This parameter is only used in DataTables' server-side processing. It can
+ * be exceptionally useful to know what columns are being displayed on the
+ * client side, and to map these to database fields. When defined, the names
+ * also allow DataTables to reorder information from the server if it comes
+ * back in an unexpected order (i.e. if you switch your columns around on the
+ * client-side, your server-side code does not also need updating).
+ * @type string
+ * @default Empty string
+ *
+ * @name DataTable.defaults.column.name
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "name": "engine", "targets": [ 0 ] },
+ * { "name": "browser", "targets": [ 1 ] },
+ * { "name": "platform", "targets": [ 2 ] },
+ * { "name": "version", "targets": [ 3 ] },
+ * { "name": "grade", "targets": [ 4 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "name": "engine" },
+ * { "name": "browser" },
+ * { "name": "platform" },
+ * { "name": "version" },
+ * { "name": "grade" }
+ * ]
+ * } );
+ * } );
+ */
+ "sName": "",
+
+
+ /**
+ * Defines a data source type for the ordering which can be used to read
+ * real-time information from the table (updating the internally cached
+ * version) prior to ordering. This allows ordering to occur on user
+ * editable elements such as form inputs.
+ * @type string
+ * @default std
+ *
+ * @name DataTable.defaults.column.orderDataType
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
+ * { "type": "numeric", "targets": [ 3 ] },
+ * { "orderDataType": "dom-select", "targets": [ 4 ] },
+ * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * null,
+ * null,
+ * { "orderDataType": "dom-text" },
+ * { "orderDataType": "dom-text", "type": "numeric" },
+ * { "orderDataType": "dom-select" },
+ * { "orderDataType": "dom-checkbox" }
+ * ]
+ * } );
+ * } );
+ */
+ "sSortDataType": "std",
+
+
+ /**
+ * The title of this column.
+ * @type string
+ * @default null Derived from the 'TH' value for this column in the
+ * original HTML table.
+ *
+ * @name DataTable.defaults.column.title
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "title": "My column title", "targets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "title": "My column title" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sTitle": null,
+
+
+ /**
+ * The type allows you to specify how the data for this column will be
+ * ordered. Four types (string, numeric, date and html (which will strip
+ * HTML tags before ordering)) are currently available. Note that only date
+ * formats understood by Javascript's Date() object will be accepted as type
+ * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
+ * 'numeric', 'date' or 'html' (by default). Further types can be adding
+ * through plug-ins.
+ * @type string
+ * @default null Auto-detected from raw data
+ *
+ * @name DataTable.defaults.column.type
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "type": "html", "targets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "type": "html" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sType": null,
+
+
+ /**
+ * Defining the width of the column, this parameter may take any CSS value
+ * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
+ * been given a specific width through this interface ensuring that the table
+ * remains readable.
+ * @type string
+ * @default null Automatic
+ *
+ * @name DataTable.defaults.column.width
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "width": "20%", "targets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "width": "20%" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sWidth": null
+ };
+
+ _fnHungarianMap( DataTable.defaults.column );
+
+
+
+ /**
+ * DataTables settings object - this holds all the information needed for a
+ * given table, including configuration, data and current application of the
+ * table options. DataTables does not have a single instance for each DataTable
+ * with the settings attached to that instance, but rather instances of the
+ * DataTable "class" are created on-the-fly as needed (typically by a
+ * $().dataTable() call) and the settings object is then applied to that
+ * instance.
+ *
+ * Note that this object is related to {@link DataTable.defaults} but this
+ * one is the internal data store for DataTables's cache of columns. It should
+ * NOT be manipulated outside of DataTables. Any configuration should be done
+ * through the initialisation options.
+ * @namespace
+ * @todo Really should attach the settings object to individual instances so we
+ * don't need to create new instances on each $().dataTable() call (if the
+ * table already exists). It would also save passing oSettings around and
+ * into every single function. However, this is a very significant
+ * architecture change for DataTables and will almost certainly break
+ * backwards compatibility with older installations. This is something that
+ * will be done in 2.0.
+ */
+ DataTable.models.oSettings = {
+ /**
+ * Primary features of DataTables and their enablement state.
+ * @namespace
+ */
+ "oFeatures": {
+
+ /**
+ * Flag to say if DataTables should automatically try to calculate the
+ * optimum table and columns widths (true) or not (false).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bAutoWidth": null,
+
+ /**
+ * Delay the creation of TR and TD elements until they are actually
+ * needed by a driven page draw. This can give a significant speed
+ * increase for Ajax source and Javascript source data, but makes no
+ * difference at all fro DOM and server-side processing tables.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bDeferRender": null,
+
+ /**
+ * Enable filtering on the table or not. Note that if this is disabled
+ * then there is no filtering at all on the table, including fnFilter.
+ * To just remove the filtering input use sDom and remove the 'f' option.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bFilter": null,
+
+ /**
+ * Table information element (the 'Showing x of y records' div) enable
+ * flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bInfo": null,
+
+ /**
+ * Present a user control allowing the end user to change the page size
+ * when pagination is enabled.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bLengthChange": null,
+
+ /**
+ * Pagination enabled or not. Note that if this is disabled then length
+ * changing must also be disabled.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bPaginate": null,
+
+ /**
+ * Processing indicator enable flag whenever DataTables is enacting a
+ * user request - typically an Ajax request for server-side processing.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bProcessing": null,
+
+ /**
+ * Server-side processing enabled flag - when enabled DataTables will
+ * get all data from the server for every draw - there is no filtering,
+ * sorting or paging done on the client-side.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bServerSide": null,
+
+ /**
+ * Sorting enablement flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSort": null,
+
+ /**
+ * Multi-column sorting
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortMulti": null,
+
+ /**
+ * Apply a class to the columns which are being sorted to provide a
+ * visual highlight or not. This can slow things down when enabled since
+ * there is a lot of DOM interaction.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortClasses": null,
+
+ /**
+ * State saving enablement flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bStateSave": null
+ },
+
+
+ /**
+ * Scrolling settings for a table.
+ * @namespace
+ */
+ "oScroll": {
+ /**
+ * When the table is shorter in height than sScrollY, collapse the
+ * table container down to the height of the table (when true).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bCollapse": null,
+
+ /**
+ * Width of the scrollbar for the web-browser's platform. Calculated
+ * during table initialisation.
+ * @type int
+ * @default 0
+ */
+ "iBarWidth": 0,
+
+ /**
+ * Viewport width for horizontal scrolling. Horizontal scrolling is
+ * disabled if an empty string.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sX": null,
+
+ /**
+ * Width to expand the table to when using x-scrolling. Typically you
+ * should not need to use this.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @deprecated
+ */
+ "sXInner": null,
+
+ /**
+ * Viewport height for vertical scrolling. Vertical scrolling is disabled
+ * if an empty string.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sY": null
+ },
+
+ /**
+ * Language information for the table.
+ * @namespace
+ * @extends DataTable.defaults.oLanguage
+ */
+ "oLanguage": {
+ /**
+ * Information callback function. See
+ * {@link DataTable.defaults.fnInfoCallback}
+ * @type function
+ * @default null
+ */
+ "fnInfoCallback": null
+ },
+
+ /**
+ * Browser support parameters
+ * @namespace
+ */
+ "oBrowser": {
+ /**
+ * Indicate if the browser incorrectly calculates width:100% inside a
+ * scrolling element (IE6/7)
+ * @type boolean
+ * @default false
+ */
+ "bScrollOversize": false,
+
+ /**
+ * Determine if the vertical scrollbar is on the right or left of the
+ * scrolling container - needed for rtl language layout, although not
+ * all browsers move the scrollbar (Safari).
+ * @type boolean
+ * @default false
+ */
+ "bScrollbarLeft": false,
+
+ /**
+ * Flag for if `getBoundingClientRect` is fully supported or not
+ * @type boolean
+ * @default false
+ */
+ "bBounding": false,
+
+ /**
+ * Browser scrollbar width
+ * @type integer
+ * @default 0
+ */
+ "barWidth": 0
+ },
+
+
+ "ajax": null,
+
+
+ /**
+ * Array referencing the nodes which are used for the features. The
+ * parameters of this object match what is allowed by sDom - i.e.
+ *
+ *
'l' - Length changing
+ *
'f' - Filtering input
+ *
't' - The table!
+ *
'i' - Information
+ *
'p' - Pagination
+ *
'r' - pRocessing
+ *
+ * @type array
+ * @default []
+ */
+ "aanFeatures": [],
+
+ /**
+ * Store data information - see {@link DataTable.models.oRow} for detailed
+ * information.
+ * @type array
+ * @default []
+ */
+ "aoData": [],
+
+ /**
+ * Array of indexes which are in the current display (after filtering etc)
+ * @type array
+ * @default []
+ */
+ "aiDisplay": [],
+
+ /**
+ * Array of indexes for display - no filtering
+ * @type array
+ * @default []
+ */
+ "aiDisplayMaster": [],
+
+ /**
+ * Map of row ids to data indexes
+ * @type object
+ * @default {}
+ */
+ "aIds": {},
+
+ /**
+ * Store information about each column that is in use
+ * @type array
+ * @default []
+ */
+ "aoColumns": [],
+
+ /**
+ * Store information about the table's header
+ * @type array
+ * @default []
+ */
+ "aoHeader": [],
+
+ /**
+ * Store information about the table's footer
+ * @type array
+ * @default []
+ */
+ "aoFooter": [],
+
+ /**
+ * Store the applied global search information in case we want to force a
+ * research or compare the old search to a new one.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @namespace
+ * @extends DataTable.models.oSearch
+ */
+ "oPreviousSearch": {},
+
+ /**
+ * Store the applied search for each column - see
+ * {@link DataTable.models.oSearch} for the format that is used for the
+ * filtering information for each column.
+ * @type array
+ * @default []
+ */
+ "aoPreSearchCols": [],
+
+ /**
+ * Sorting that is applied to the table. Note that the inner arrays are
+ * used in the following manner:
+ *
+ *
Index 0 - column number
+ *
Index 1 - current sorting direction
+ *
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @todo These inner arrays should really be objects
+ */
+ "aaSorting": null,
+
+ /**
+ * Sorting that is always applied to the table (i.e. prefixed in front of
+ * aaSorting).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "aaSortingFixed": [],
+
+ /**
+ * Classes to use for the striping of a table.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "asStripeClasses": null,
+
+ /**
+ * If restoring a table - we should restore its striping classes as well
+ * @type array
+ * @default []
+ */
+ "asDestroyStripes": [],
+
+ /**
+ * If restoring a table - we should restore its width
+ * @type int
+ * @default 0
+ */
+ "sDestroyWidth": 0,
+
+ /**
+ * Callback functions array for every time a row is inserted (i.e. on a draw).
+ * @type array
+ * @default []
+ */
+ "aoRowCallback": [],
+
+ /**
+ * Callback functions for the header on each draw.
+ * @type array
+ * @default []
+ */
+ "aoHeaderCallback": [],
+
+ /**
+ * Callback function for the footer on each draw.
+ * @type array
+ * @default []
+ */
+ "aoFooterCallback": [],
+
+ /**
+ * Array of callback functions for draw callback functions
+ * @type array
+ * @default []
+ */
+ "aoDrawCallback": [],
+
+ /**
+ * Array of callback functions for row created function
+ * @type array
+ * @default []
+ */
+ "aoRowCreatedCallback": [],
+
+ /**
+ * Callback functions for just before the table is redrawn. A return of
+ * false will be used to cancel the draw.
+ * @type array
+ * @default []
+ */
+ "aoPreDrawCallback": [],
+
+ /**
+ * Callback functions for when the table has been initialised.
+ * @type array
+ * @default []
+ */
+ "aoInitComplete": [],
+
+
+ /**
+ * Callbacks for modifying the settings to be stored for state saving, prior to
+ * saving state.
+ * @type array
+ * @default []
+ */
+ "aoStateSaveParams": [],
+
+ /**
+ * Callbacks for modifying the settings that have been stored for state saving
+ * prior to using the stored values to restore the state.
+ * @type array
+ * @default []
+ */
+ "aoStateLoadParams": [],
+
+ /**
+ * Callbacks for operating on the settings object once the saved state has been
+ * loaded
+ * @type array
+ * @default []
+ */
+ "aoStateLoaded": [],
+
+ /**
+ * Cache the table ID for quick access
+ * @type string
+ * @default Empty string
+ */
+ "sTableId": "",
+
+ /**
+ * The TABLE node for the main table
+ * @type node
+ * @default null
+ */
+ "nTable": null,
+
+ /**
+ * Permanent ref to the thead element
+ * @type node
+ * @default null
+ */
+ "nTHead": null,
+
+ /**
+ * Permanent ref to the tfoot element - if it exists
+ * @type node
+ * @default null
+ */
+ "nTFoot": null,
+
+ /**
+ * Permanent ref to the tbody element
+ * @type node
+ * @default null
+ */
+ "nTBody": null,
+
+ /**
+ * Cache the wrapper node (contains all DataTables controlled elements)
+ * @type node
+ * @default null
+ */
+ "nTableWrapper": null,
+
+ /**
+ * Indicate if when using server-side processing the loading of data
+ * should be deferred until the second draw.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ * @default false
+ */
+ "bDeferLoading": false,
+
+ /**
+ * Indicate if all required information has been read in
+ * @type boolean
+ * @default false
+ */
+ "bInitialised": false,
+
+ /**
+ * Information about open rows. Each object in the array has the parameters
+ * 'nTr' and 'nParent'
+ * @type array
+ * @default []
+ */
+ "aoOpenRows": [],
+
+ /**
+ * Dictate the positioning of DataTables' control elements - see
+ * {@link DataTable.model.oInit.sDom}.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default null
+ */
+ "sDom": null,
+
+ /**
+ * Search delay (in mS)
+ * @type integer
+ * @default null
+ */
+ "searchDelay": null,
+
+ /**
+ * Which type of pagination should be used.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default two_button
+ */
+ "sPaginationType": "two_button",
+
+ /**
+ * The state duration (for `stateSave`) in seconds.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type int
+ * @default 0
+ */
+ "iStateDuration": 0,
+
+ /**
+ * Array of callback functions for state saving. Each array element is an
+ * object with the following parameters:
+ *
+ *
function:fn - function to call. Takes two parameters, oSettings
+ * and the JSON string to save that has been thus far created. Returns
+ * a JSON string to be inserted into a json object
+ * (i.e. '"param": [ 0, 1, 2]')
+ *
string:sName - name of callback
+ *
+ * @type array
+ * @default []
+ */
+ "aoStateSave": [],
+
+ /**
+ * Array of callback functions for state loading. Each array element is an
+ * object with the following parameters:
+ *
+ *
function:fn - function to call. Takes two parameters, oSettings
+ * and the object stored. May return false to cancel state loading