diff --git a/.classpath b/.classpath deleted file mode 100644 index 2454c8f20..000000000 --- a/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.gitignore b/.gitignore index db505a540..9ba6f8d6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,8 @@ # Package Files # -*.war -*.ear -build/* -./settings/* -*.swp -*.bak -*.log -bak -*.class -bin/ +out target -node_modules -_site +build +.idea +*.iml +.DS_Store +bak \ No newline at end of file diff --git a/.project b/.project deleted file mode 100644 index 864cf9274..000000000 --- a/.project +++ /dev/null @@ -1,48 +0,0 @@ - - - RAP - - - - - - org.eclipse.wst.jsdt.core.javascriptValidator - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.wst.common.project.facet.core.builder - - - - - org.eclipse.wst.validation.validationbuilder - - - - - com.genuitec.eclipse.ast.deploy.core.DeploymentBuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.m2e.core.maven2Nature - com.genuitec.eclipse.ast.deploy.core.deploymentnature - org.eclipse.jem.workbench.JavaEMFNature - org.eclipse.wst.common.modulecore.ModuleCoreNature - org.eclipse.wst.common.project.facet.core.nature - org.eclipse.jdt.core.javanature - org.eclipse.wst.jsdt.core.jsNature - - diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope deleted file mode 100644 index 49b9981e4..000000000 --- a/.settings/.jsdtscope +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/.settings/com.genuitec.eclipse.j2eedt.core.prefs b/.settings/com.genuitec.eclipse.j2eedt.core.prefs deleted file mode 100644 index e6772cc4c..000000000 --- a/.settings/com.genuitec.eclipse.j2eedt.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#Tue Dec 24 13:46:52 CST 2013 -defaultTldInfo=f\=http\://java.sun.com/jsf/core;http\://java.sun.com/jsf/html\=h;http\://struts.apache.org/tags-bean\=bean;http\://java.sun.com/jsp/jstl/fmt\=fmt;bean\=http\://struts.apache.org/tags-bean;nested\=http\://struts.apache.org/tags-nested;http\://java.sun.com/jsp/jstl/sql\=sql;fmt\=http\://java.sun.com/jsp/jstl/fmt;c\=http\://java.sun.com/jsp/jstl/core;http\://struts.apache.org/tags-logic\=logic;http\://java.sun.com/jsp/jstl/xml\=x;http\://java.sun.com/jsp/jstl/core\=c;logic\=http\://struts.apache.org/tags-logic;h\=http\://java.sun.com/jsf/html;http\://struts.apache.org/tags-tiles\=tiles;http\://java.sun.com/jsp/jstl/functions\=fn;tiles\=http\://struts.apache.org/tags-tiles;sql\=http\://java.sun.com/jsp/jstl/sql;http\://struts.apache.org/tags-html\=html;html\=http\://struts.apache.org/tags-html;http\://struts.apache.org/tags-nested\=nested;http\://java.sun.com/jsf/core\=f;fn\=http\://java.sun.com/jsp/jstl/functions;x\=http\://java.sun.com/jsp/jstl/xml -eclipse.preferences.version=1 -useAssemblyMapping=true diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 5cf2c6b09..000000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,5 +0,0 @@ -#Wed Apr 09 10:53:37 CST 2014 -eclipse.preferences.version=1 -encoding//WebContent/tcom/const.inc.vm=UTF-8 -encoding//src/database/test-data.sql=UTF-8 -encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 08b9d7437..000000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -#Thu Dec 12 15:44:46 CST 2013 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.6 -org.eclipse.jdt.core.compiler.debug.lineNumber=generate -org.eclipse.jdt.core.compiler.debug.localVariable=generate -org.eclipse.jdt.core.compiler.debug.sourceFile=generate -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.6 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index 7a46530f6..000000000 --- a/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,5 +0,0 @@ -#Thu Dec 12 15:44:43 CST 2013 -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component deleted file mode 100644 index 7cdbb139d..000000000 --- a/.settings/org.eclipse.wst.common.component +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml deleted file mode 100644 index 5c227556d..000000000 --- a/.settings/org.eclipse.wst.common.project.facet.core.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.container b/.settings/org.eclipse.wst.jsdt.ui.superType.container deleted file mode 100644 index 3bd5d0a48..000000000 --- a/.settings/org.eclipse.wst.jsdt.ui.superType.container +++ /dev/null @@ -1 +0,0 @@ -org.eclipse.wst.jsdt.launching.baseBrowserLibrary \ No newline at end of file diff --git a/.settings/org.eclipse.wst.jsdt.ui.superType.name b/.settings/org.eclipse.wst.jsdt.ui.superType.name deleted file mode 100644 index 05bd71b6e..000000000 --- a/.settings/org.eclipse.wst.jsdt.ui.superType.name +++ /dev/null @@ -1 +0,0 @@ -Window \ No newline at end of file diff --git a/.settings/org.eclipse.wst.ws.service.policy.prefs b/.settings/org.eclipse.wst.ws.service.policy.prefs deleted file mode 100644 index a2cc26e2d..000000000 --- a/.settings/org.eclipse.wst.ws.service.policy.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Thu Aug 05 13:37:25 CST 2010 -eclipse.preferences.version=1 -org.eclipse.wst.ws.service.policy.projectEnabled=false diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e1c877e11 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: java +branches: + only: + - master + - release \ No newline at end of file diff --git a/COPYING.txt b/COPYING.txt new file mode 100644 index 000000000..65c45c98a --- /dev/null +++ b/COPYING.txt @@ -0,0 +1,643 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + + +ADDITIONAL TERMS APPLICABLE TO THE DOOM 3 GPL SOURCE CODE. + + The following additional terms (�Additional Terms�) supplement and modify the GNU General Public License, Version 3 (�GPL�) applicable to the Doom 3 GPL Source Code (�Doom 3 Source Code�). In addition to the terms and conditions of the GPL, the Doom 3 Source Code is subject to the further restrictions below. + +1. Replacement of Section 15. Section 15 of the GPL shall be deleted in its entirety and replaced with the following: + +�15. Disclaimer of Warranty. + +THE PROGRAM IS PROVIDED WITHOUT ANY WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, TITLE AND MERCHANTABILITY. THE PROGRAM IS BEING DELIVERED OR MADE AVAILABLE �AS IS�, �WITH ALL FAULTS� AND WITHOUT WARRANTY OR REPRESENTATION. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.� + +2. Replacement of Section 16. Section 16 of the GPL shall be deleted in its entirety and replaced with the following: + +�16. LIMITATION OF LIABILITY. + +UNDER NO CIRCUMSTANCES SHALL ANY COPYRIGHT HOLDER OR ITS AFFILIATES, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, FOR ANY DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, DIRECT, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL OR PUNITIVE DAMAGES ARISING FROM, OUT OF OR IN CONNECTION WITH THE USE OR INABILITY TO USE THE PROGRAM OR OTHER DEALINGS WITH THE PROGRAM(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), WHETHER OR NOT ANY COPYRIGHT HOLDER OR SUCH OTHER PARTY RECEIVES NOTICE OF ANY SUCH DAMAGES AND WHETHER OR NOT SUCH DAMAGES COULD HAVE BEEN FORESEEN.� + +3. LEGAL NOTICES; NO TRADEMARK LICENSE; ORIGIN. You must reproduce faithfully all trademark, copyright and other proprietary and legal notices on any copies of the Program or any other required author attributions. This license does not grant you rights to use any copyright holder or any other party�s name, logo, or trademarks. Neither the name of the copyright holder or its affiliates, or any other party who modifies and/or conveys the Program may be used to endorse or promote products derived from this software without specific prior written permission. The origin of the Program must not be misrepresented; you must not claim that you wrote the original Program. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original Program. + +4. INDEMNIFICATION. IF YOU CONVEY A COVERED WORK AND AGREE WITH ANY RECIPIENT OF THAT COVERED WORK THAT YOU WILL ASSUME ANY LIABILITY FOR THAT COVERED WORK, YOU HEREBY AGREE TO INDEMNIFY, DEFEND AND HOLD HARMLESS THE OTHER LICENSORS AND AUTHORS OF THAT COVERED WORK FOR ANY DAMAEGS, DEMANDS, CLAIMS, LOSSES, CAUSES OF ACTION, LAWSUITS, JUDGMENTS EXPENSES (INCLUDING WITHOUT LIMITATION REASONABLE ATTORNEYS' FEES AND EXPENSES) OR ANY OTHER LIABLITY ARISING FROM, RELATED TO OR IN CONNECTION WITH YOUR ASSUMPTIONS OF LIABILITY. diff --git a/DATABASE_CHANGE.md b/DATABASE_CHANGE.md new file mode 100644 index 000000000..d7c248e13 --- /dev/null +++ b/DATABASE_CHANGE.md @@ -0,0 +1,73 @@ +### Database Change v0.11.5 + +详情见[v0.11.5设计文档](https://github.com/thx/RAP/wiki/v0.11.5) + +```sql +CREATE TABLE tb_corporation_and_user +( + user_id int(10) NOT NULL, + corporation_id int(10) NOT NULL, + role_id int(10) NOT NULL, + + PRIMARY KEY(user_id, corporation_id), + FOREIGN KEY(user_id) REFERENCES tb_user(id), + FOREIGN KEY(corporation_id) REFERENCES tb_corporation(id), + FOREIGN KEY(role_id) REFERENCES tb_role(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +ALTER TABLE tb_corporation + ADD COLUMN access_type TINYINT NOT NULL COMMENT '权限控制, 10普通, 20公开' + DEFAULT 10; + +ALTER TABLE tb_corporation + ADD COLUMN `desc` text NOT NULL COMMENT '备注'; + +ALTER TABLE tb_project + ADD COLUMN access_type TINYINT NOT NULL COMMENT '权限控制, 10普通, 0私有' + DEFAULT 10; + +CREATE TABLE tb_rule ( + action_id int(10) NOT NULL + PRIMARY KEY, + rules text NOT NULL, -- JSON规则 + update_time datetime NOT NULL + DEFAULT NOW(), -- 最近更新时间 + + FOREIGN KEY(action_id) REFERENCES tb_action(id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +-- 将老的团队全部设为公开 +UPDATE tb_corporation SET access_type = 20; + +``` + +### Database Change v0.11.1 +1. 增加了tb_module.name的长度,防止过长模块名报错 +2. 增加tb_action.disable_cache字段用于自动化禁用cache处理 + +```sql +ALTER TABLE `rap_db`.`tb_module` CHANGE COLUMN `name` `name` VARCHAR(256) NOT NULL ; +ALTER TABLE `rap_db`.`tb_action` ADD COLUMN disable_cache TINYINT NOT NULL DEFAULT 0; +``` + + + +### Database Change v0.11.0 + +add mock count Oct.15 2014 +增加了MOCK调用次数记录 2014-10-15 + +```sql +ALTER TABLE tb_project +ADD COLUMN mock_num int(10) NOT NULL + DEFAULT 0 +``` + +add employee id Oct.1 2014 +增加员工ID 2014-10-1 + +```sql +ALTER TABLE tb_user + ADD emp_id varchar(128) NULL +``` diff --git a/INTRO.md b/INTRO.md deleted file mode 100644 index 04812b825..000000000 --- a/INTRO.md +++ /dev/null @@ -1,88 +0,0 @@ -RAP v0.8 介绍 -=== - -你和你的小伙伴们还在用纯手工的方式小心翼翼的编写和维护接口文档么? - -你和你的小伙伴们还在手动的一条一条伪造自测数据么? - -你和你的小伙伴们还在联调时因接口格式不对而浪费大量宝贵时间么? - -如果是,RAP或许能够让你体验一次“鸟枪换炮”的快感。 - -## 概述 ## - -在前后端分离的WEB开发模式中,通常需定义接口文档来规范其接口形式,如接口地址、参数、类型、含义等。RAP 致力于提供方便的可视化工具录入并维护这些文档,并通过分析这些文档数据,重复利用,生成自测数据、校验真实数据,提升开发效率。 - -接口管理工作由来已久,传统管理方式无论用Word、Wiki或更高级的工具,最常遇到的问题是:“接口文档不全,更新不及时”。由于开发过程中持续的接口调整几乎无可避免,一旦接口文档不能及时同步,一切都是空谈!RAP工具改变了这一现状,任何接口的变化需要通过更新RAP内的接口文档来反馈给前端,而RAP通过接口规则生成的模拟数据则构成了整个前端开发环境的基础。因此,接口文档的全面性、实时性和正确性成为前后端开发过程中的强依赖,同时这也构成了RAP服务于后端单元测试和UI自动化测试的基石。在RAP成为前端开发过程的必经环节之后,这对RAP解决复杂response数据的结构化描述、 版本历史管理、 接口维护工具、易用性等问题时提出了更高的要求。 - -## 用户场景 ## - -RAP的主要目标用户群有四种: -- 前端,使用RAP制定接口,生成自测数据。 -- 后端,使用RAP制定接口,校验真实输出的格式。 -- 测试,使用RAP录制Mock规则,实现自动化测试。 -- 其它,各种角色,需要了解该系统接口情况的人。 - -## 使用数据 ## - -截至发稿时,目前RAP已为`112`名工程师提供服务,立项`49`个,定义了`445`个接口,完成了`上万`次动态数据MOCK。 - -## 解决的问题 ## - -### 一、接口编辑的便利性 ### - -RAP所解决的问题,主要集中于中大型的企业级项目,接口形式有一定的复杂度。比如一个报表的请求,可能嵌套较多的层级。传统的方式描述较多嵌套的层级结构会较为麻烦,复制、移动等修改都消耗大量时间,而RAP通过GUI工具和结构分析可以很好的解决这些问题。再复杂的嵌套参数,一键复制和移动。展开、折叠毫不费力。RAP专为接口编辑而设计,在用户体验和细节上做了大量处理,保证高效、方便的接口文档编辑。 - -RAP文档编辑区 - -### 二、手写模拟数据耗费时间 ### - -从设计阶段之后到联调之前,前端需要编写大量的自测数据来自测(尤其层级嵌套或CASE较多的情况会比较麻烦)。有了RAP告别手写自测数据,RAP会根据最新的接口文档动态实时的产生模拟数据,且结合MockJS支持深度定制的数据模拟规则。“一处写好,大家共享。”不管是自测、做DEMO,RAP在数据模拟上都可用最少时间,达到最大产出。对于前端,RAP模拟请求返回生成靠谱的自测数据,对于后端,RAP根据接口文档中定义的参数格式伪造实际请求以此测试后端实际接口的准确性。 - -### 三、有规范却不执行 ### - -这是实际常见到的问题,定义好了接口,联调的时候发现实际数据不符合规则或前端手写的自测数据错误导致前端未正确处理。RAP MOCK保证前端代码对接口正确的处理,同时,RAP会根据接口文档中的结构动态验证后端实际返回的正确性,在联调前扫清所有后端格式错误。 - -### 四、文档维护 & 实时性 ### - -传统的接口文档若不进行持续的维护,将会逐渐失效。没有实时性的文档很快将会变成废品,RAP集中式的文档编辑,实时生效的前后端工具将RAP中的接口文档变成强依赖。RAP中的接口文档一旦修改,所有的自动化功能都将受其影响,反之也保证了RAP中的文档始终是最新的。 - -## 特点介绍 ## - -### 一、方便快捷的创建、共享文档 ### - -RAP中对接口文档的编辑提供了一套可视化界面,编辑操作像Excel一样方便简单。比如您可以展开、收缩层级嵌套的参数结构,查看、切换不同历史版本,一键复制、移动参数(包括层级嵌套的复杂参数)。为方便离线查看,您也可以导出接口文档(Word文档)。在即将问世的v1.0新版RAP中,我们还会增加: -注入规范验证(强制接口命名规范)、接口模板等提升文档易用性的功能。 -针对RD、FE、QA不同的角色提供不同的视图及功能。比如后端更关注接口地址,前端更关心业务逻辑中划分的”页面“或”模块“。我们将持续提升产品易用性。RAP的核心是接口文档,因此文档编辑的用户体验是我们非常重视的,有了较好的文档编辑用户体验,用户才愿意用RAP去维护文档,并充分利用这些结构化的数据将更多工作自动化。 - -### 二:RAP MOCK,“设计阶段,所有服务全跑通” ### - -在设计阶段写好接口文档后,RAP会根据接口文档中的请求路径、接口数据自动生成所有的服务接口。在联调前,所有MOCK服务全部可跑通,并根据文档变化实时更新,前端自测将变得更加简单。 - -RAP的MOCK数据是动态生成的,默认数据会有自己的初始行为,您也能通过标签精细的控制数据生成的逻辑。这也为后续我们创建”响应参数“的数据创造基础。目前RAP支持[MockJS](http://mockjs.com)和RAP MOCK两种Mock规则,后续还会进行更多扩充 -。 -RAPv0.8请求流程 - -### 三:集合THX平台发挥更大的优势 ### - -RAP生成的数据通过跨平台Crox模板引擎可打通多平台,意味着RAP MOCK的用武之地不再局限于JSONP、JSON形式的接口,Velocity、Smarty等后端模板语言调用RAP MOCK服务依然可行,实现“一处编写、到处使用。” - -我们后续还将与THX其它产品做深度结合,发挥更多的作用。 - -## RAP发展历程 ## - -RAP第一版在2010年中完成开发,历经了3年多的实际应用,无论是文档编辑、前端MOCK服务、后端自测工具还是自动化测试等功能都较为成熟。我们在用户体验、操作细节上也做了很多的努力。 - -在文档结构化后再利用上,接口文档是第一个尝试,我们也在努力挖掘更多的可再利用文档,用以提升其它的重复劳动,我们也在努力让现有功能更加完善。无论你是前端、后端还是测试,有了RAP,文档共享和开发将更为方便。 - -## RAP v1.0 ## - -在即将到来的RAPv1.0版本中,我们会增加分布式的NodeJS客户端,支持Web服务器与RAP的深度结合,利用反向代理解决Mock服务跨域问题,支持离线存取,分散服务器Mock压力,并在客户端实现更多强大的功能。 - -RAPv1.0请求流程 - -RAPv1.0规则编辑和同步流程 - -## 关于RAP ## - -RAP由阿里妈妈用户体验部开发,属于[THX](http://thx.alibaba-inc.com)平台的产品之一。欢迎大家访问[RAP主站](http://rap.alibaba-inc.com),有任何疑问欢迎邮件至:[huoyong.msb@taobao.com](mailto:huoyong.msb@taobao.com)。RAP诚挚的期待您的光临! diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..ef7e7efc0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md index 3d7ab027b..5de5cf0c8 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,99 @@ -Rigel Automation Platform -=== +# RAP ![](https://api.travis-ci.org/thx/RAP.svg) - @version v0.8.1 - @author Bosn(霍雍), wangjeaf(思竹) - @weibo http://weibo.com/bosn, http://github.com/wangjeaf - @mail bosn@outlook.com, wangjeaf@gmail.com +### What is RAP? -什么是RAP? --------------------------------------- +RAP is a web tool that allows web applcation developers to rapidly define and document web APIs that are used in typical RESTful-API based web applications. RAP can also be used to generate API mock data and run API services to enable front-end developers in writing and testing their front-end code that makes consumpiont of the predefined web API loaded with mock data, hence reducing the dependency from the backend development work. Meanwhile, backend developers can implement their backend code according to the defintion of API on their own pace to meet the quality and timeline requirements. With RAP, you can really do more with less. -在前后端分离的开发模式下,我们通常需要定义一份`接口文档`来规范接口的具体信息。如一个请求的地址、有几个参数、参数名称及类型含义等等。`RAP` 首先方便团队录入、查看和管理这些接口文档,并通过分析结构化的文档数据,重复利用并生成自测数据、提供自测控制台等等... 大幅度提升开发效率。 +RAP通过GUI工具帮助WEB工程师更高效的管理接口文档,同时通过分析接口结构自动生成Mock数据、校验真实接口的正确性,使接口文档成为开发流程中的强依赖。有了结构化的API数据,RAP可以做的更多,而我们可以避免更多重复劳动。 -- [文档中心](http://thx.alibaba-inc.com/RAP/) + + + +### Why we use RAP? +* Enterprise-level application: 350+ corporations including Alibaba Group have adopted RAP to manage their important API Docs and development effort! +* Fast and responsive technical support with continuous update. Go to issues list to find out how active the community is! +* Free and open source: freedom is in your hand! + +### 为什么我们信赖RAP? +* 企业级应用,包括阿里集团在内得350多个企业都在使用RAP管理重要的接口文档。 +* 快速高效的技术支持,持续的更新,去Issues看一看就知道有多热闹。 +* 免费、开源,一切尽在掌握中! + +### 如何使用RAP +1. 直接访问由作者维护的[rap.taobao.org](http://rap.taobao.org) +2. 自己部署一个RAP服务器,参考最新Release部分 + +### 快速上手 quick guide +* English: [Quick Guide Manual](https://github.com/thx/RAP/wiki/quick_guide) at first. +* 中文:[Video Tutorial 视频教程](http://thx.github.io/RAP/study.html) + +### 分支说明 +* master: 最新代码会在master,所以master是最新的,但是不保证稳定。且有一些公司自用的东西,所以提交记录可以参考,但不能直接使用master分支。 +* release:是相对稳定的最新代码分支,也是RAP对外打包的分支 +* 其它分支:根据开发需要,大的版本会以版本号为分支名,打一些临时分支。 + +### 最新Release +* [Release](https://github.com/thx/RAP/releases) +* [如何部署RAP服务器](https://github.com/thx/RAP/wiki/deploy_manual_cn) +* [如何使用RAP编辑文档](https://github.com/thx/RAP/wiki/user_manual_cn) + +### 其它LINKS +* 我想大概了解RAP => [Official Site 官网](http://thx.github.io/RAP) +* 我想查找详细的文档资料 => [Wiki/Documents/Manual 文档/手册](http://github.com/thx/RAP/wiki) +* 我想快速了解什么是RAP => [视频介绍](http://vodcdn.video.taobao.com/player/ugc/tb_ugc_pieces_core_player_loader.swf?version=1.0.20150330&vid=11622279&uid=11051796&p=1&t=1&rid=&random=6666) +* 我想快速上手RAP使用方法 => [视频教程](http://thx.github.io/RAP/study.html) +* 我要反馈问题 => [Issues](http://github.com/thx/RAP/issues) + +### Architecture +* Frontend: Velocity + jQuery + qUnit +* Backend: Hibernate5 + Spring4 + Struts2 +* Data Store: MySQL5 + Redis3 +* Deployment: Tomcat + Docker +* CI: Travis + +## 订阅RAP更新? + +为了在有新Release、发现重大安全漏洞时能够及时的通知到各位管理员,请关注 [订阅帖](https://github.com/thx/RAP/issues/234) + + +## About + + @version v0.14.3 + @author @nuysoft @zhangmeng712 @bosn @wangjeaf + @director @limu @xinglie + @update Sep. 8th 2016 + @dependency MockJS(@nuysoft) + @license GPL + +## Contact + + @问题反馈 https://github.com/thx/RAP/issues (推荐) + @旺旺群聊 582755829 (找到小伙伴) + @作者微博 http://weibo.com/bosn (求粉:3 ) + +## Contributors List 贡献者 + +`belerweb`, `xinglie`, `nunnly`, `x03570227`, `jokefaker`, etc. + +[Contributors Details](https://github.com/thx/RAP/graphs/contributors) + +## 赞助商 +* 感谢[阿里云](http://www.aliyun.com)赞助服务器 + +## 其它链接 +* THX开源工具集: [http://thx.github.io/](http://thx.github.io/) +* 作者微博:[@Bosn](http://weibo.com/bosn) + +## RAP的客户 +* 阿里巴巴集团 +* 蚂蚁金服 +* Boss直聘 +* 苏州白鸽云信息技术有限公司 +* 厦门优优汇联信息科技有限公司 +* 杭州匠人网络科技有限公司 +* 深圳润民科技有限公司 +* 南京爱动信息技术有限公司 +* 智能云科信息科技有限公司 + + +您也在使用RAP?请 [在这里](https://github.com/thx/RAP/issues/272) 更新您的公司. diff --git a/WebContent/WEB-INF/lib/activation.jar b/WebContent/WEB-INF/lib/activation.jar deleted file mode 100644 index b7a4b4717..000000000 Binary files a/WebContent/WEB-INF/lib/activation.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/antlr-2.7.6.jar b/WebContent/WEB-INF/lib/antlr-2.7.6.jar deleted file mode 100644 index 3702b645f..000000000 Binary files a/WebContent/WEB-INF/lib/antlr-2.7.6.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/automaton.jar b/WebContent/WEB-INF/lib/automaton.jar deleted file mode 100644 index ba583b3c8..000000000 Binary files a/WebContent/WEB-INF/lib/automaton.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/axis.jar b/WebContent/WEB-INF/lib/axis.jar deleted file mode 100644 index 20b09a595..000000000 Binary files a/WebContent/WEB-INF/lib/axis.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/c3p0-0.9.1.2.jar b/WebContent/WEB-INF/lib/c3p0-0.9.1.2.jar deleted file mode 100644 index 0f42d60e3..000000000 Binary files a/WebContent/WEB-INF/lib/c3p0-0.9.1.2.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/cglib-nodep-2.1_3.jar b/WebContent/WEB-INF/lib/cglib-nodep-2.1_3.jar deleted file mode 100644 index e9b17ebf1..000000000 Binary files a/WebContent/WEB-INF/lib/cglib-nodep-2.1_3.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-beanutils.jar b/WebContent/WEB-INF/lib/commons-beanutils.jar deleted file mode 100644 index b1b89c9c9..000000000 Binary files a/WebContent/WEB-INF/lib/commons-beanutils.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-codec-1.3.jar b/WebContent/WEB-INF/lib/commons-codec-1.3.jar deleted file mode 100644 index 957b6752a..000000000 Binary files a/WebContent/WEB-INF/lib/commons-codec-1.3.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-collections.jar b/WebContent/WEB-INF/lib/commons-collections.jar deleted file mode 100644 index 75580be25..000000000 Binary files a/WebContent/WEB-INF/lib/commons-collections.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-digester-1.8.jar b/WebContent/WEB-INF/lib/commons-digester-1.8.jar deleted file mode 100644 index 1110f0aad..000000000 Binary files a/WebContent/WEB-INF/lib/commons-digester-1.8.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-digester.jar b/WebContent/WEB-INF/lib/commons-digester.jar deleted file mode 100644 index c2a7d9d3e..000000000 Binary files a/WebContent/WEB-INF/lib/commons-digester.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-discovery.jar b/WebContent/WEB-INF/lib/commons-discovery.jar deleted file mode 100644 index b88554847..000000000 Binary files a/WebContent/WEB-INF/lib/commons-discovery.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar b/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar deleted file mode 100644 index aa209b388..000000000 Binary files a/WebContent/WEB-INF/lib/commons-fileupload-1.2.1.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar b/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar deleted file mode 100644 index 7c59774ae..000000000 Binary files a/WebContent/WEB-INF/lib/commons-httpclient-3.1.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-io-1.4.jar b/WebContent/WEB-INF/lib/commons-io-1.4.jar deleted file mode 100644 index 133dc6cb3..000000000 Binary files a/WebContent/WEB-INF/lib/commons-io-1.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-lang-2.4.jar b/WebContent/WEB-INF/lib/commons-lang-2.4.jar deleted file mode 100644 index 532939eca..000000000 Binary files a/WebContent/WEB-INF/lib/commons-lang-2.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-logging-1.0.4.jar b/WebContent/WEB-INF/lib/commons-logging-1.0.4.jar deleted file mode 100644 index b73a80fab..000000000 Binary files a/WebContent/WEB-INF/lib/commons-logging-1.0.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-net-ftp-2.0.jar b/WebContent/WEB-INF/lib/commons-net-ftp-2.0.jar deleted file mode 100644 index f697534cf..000000000 Binary files a/WebContent/WEB-INF/lib/commons-net-ftp-2.0.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/commons-pool-1.5.4.jar b/WebContent/WEB-INF/lib/commons-pool-1.5.4.jar deleted file mode 100644 index 43edf9963..000000000 Binary files a/WebContent/WEB-INF/lib/commons-pool-1.5.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/derbyclient.jar b/WebContent/WEB-INF/lib/derbyclient.jar deleted file mode 100644 index 3e8097896..000000000 Binary files a/WebContent/WEB-INF/lib/derbyclient.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/dom4j-1.6.1.jar b/WebContent/WEB-INF/lib/dom4j-1.6.1.jar deleted file mode 100644 index c8c4dbb92..000000000 Binary files a/WebContent/WEB-INF/lib/dom4j-1.6.1.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/dozer-5.1.jar b/WebContent/WEB-INF/lib/dozer-5.1.jar deleted file mode 100644 index a559a8f04..000000000 Binary files a/WebContent/WEB-INF/lib/dozer-5.1.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/ehcache-1.6.0-beta4.jar b/WebContent/WEB-INF/lib/ehcache-1.6.0-beta4.jar deleted file mode 100644 index e8f204af3..000000000 Binary files a/WebContent/WEB-INF/lib/ehcache-1.6.0-beta4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/freemarker-2.3.8.jar b/WebContent/WEB-INF/lib/freemarker-2.3.8.jar deleted file mode 100644 index 737bfb592..000000000 Binary files a/WebContent/WEB-INF/lib/freemarker-2.3.8.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/gson-1.5-sources.jar b/WebContent/WEB-INF/lib/gson-1.5-sources.jar deleted file mode 100644 index 3977e2085..000000000 Binary files a/WebContent/WEB-INF/lib/gson-1.5-sources.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/gson-1.5.jar b/WebContent/WEB-INF/lib/gson-1.5.jar deleted file mode 100644 index e59483bbb..000000000 Binary files a/WebContent/WEB-INF/lib/gson-1.5.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/hessian-3.2.1.jar b/WebContent/WEB-INF/lib/hessian-3.2.1.jar deleted file mode 100644 index b7d90bae0..000000000 Binary files a/WebContent/WEB-INF/lib/hessian-3.2.1.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/hibernate-tools.jar b/WebContent/WEB-INF/lib/hibernate-tools.jar deleted file mode 100644 index 783947d6c..000000000 Binary files a/WebContent/WEB-INF/lib/hibernate-tools.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/hibernate3.jar b/WebContent/WEB-INF/lib/hibernate3.jar deleted file mode 100644 index b87dcb031..000000000 Binary files a/WebContent/WEB-INF/lib/hibernate3.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/jackson-asl-0.9.3.jar b/WebContent/WEB-INF/lib/jackson-asl-0.9.3.jar deleted file mode 100644 index 0a5f71f01..000000000 Binary files a/WebContent/WEB-INF/lib/jackson-asl-0.9.3.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/java.servlet-2.5.jar b/WebContent/WEB-INF/lib/java.servlet-2.5.jar deleted file mode 100644 index fb5249346..000000000 Binary files a/WebContent/WEB-INF/lib/java.servlet-2.5.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/jaxen-1.1-beta-9.jar b/WebContent/WEB-INF/lib/jaxen-1.1-beta-9.jar deleted file mode 100644 index 6402d3273..000000000 Binary files a/WebContent/WEB-INF/lib/jaxen-1.1-beta-9.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/jaxrpc.jar b/WebContent/WEB-INF/lib/jaxrpc.jar deleted file mode 100644 index fe0b047cb..000000000 Binary files a/WebContent/WEB-INF/lib/jaxrpc.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/js.jar b/WebContent/WEB-INF/lib/js.jar deleted file mode 100644 index 6f0dafbbc..000000000 Binary files a/WebContent/WEB-INF/lib/js.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/json-rpc.jar b/WebContent/WEB-INF/lib/json-rpc.jar deleted file mode 100644 index 7584a94c7..000000000 Binary files a/WebContent/WEB-INF/lib/json-rpc.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/jsonplugin-0.30.jar b/WebContent/WEB-INF/lib/jsonplugin-0.30.jar deleted file mode 100644 index a7f06a5c2..000000000 Binary files a/WebContent/WEB-INF/lib/jsonplugin-0.30.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/jta.jar b/WebContent/WEB-INF/lib/jta.jar deleted file mode 100644 index 40a2cbdf8..000000000 Binary files a/WebContent/WEB-INF/lib/jta.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/junit-4.4.jar b/WebContent/WEB-INF/lib/junit-4.4.jar deleted file mode 100644 index 649b0b327..000000000 Binary files a/WebContent/WEB-INF/lib/junit-4.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/jxl.jar b/WebContent/WEB-INF/lib/jxl.jar deleted file mode 100644 index c17560d91..000000000 Binary files a/WebContent/WEB-INF/lib/jxl.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/log4j-1.2.15.jar b/WebContent/WEB-INF/lib/log4j-1.2.15.jar deleted file mode 100644 index c930a6ab4..000000000 Binary files a/WebContent/WEB-INF/lib/log4j-1.2.15.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/mail.jar b/WebContent/WEB-INF/lib/mail.jar deleted file mode 100644 index aa357d4b9..000000000 Binary files a/WebContent/WEB-INF/lib/mail.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/mysql-connector-java-5.1.6-bin.jar b/WebContent/WEB-INF/lib/mysql-connector-java-5.1.6-bin.jar deleted file mode 100644 index 0539039f7..000000000 Binary files a/WebContent/WEB-INF/lib/mysql-connector-java-5.1.6-bin.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/nekohtml-1.9.13.jar b/WebContent/WEB-INF/lib/nekohtml-1.9.13.jar deleted file mode 100644 index a8081d294..000000000 Binary files a/WebContent/WEB-INF/lib/nekohtml-1.9.13.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/ognl-2.6.11.jar b/WebContent/WEB-INF/lib/ognl-2.6.11.jar deleted file mode 100644 index 19cd379aa..000000000 Binary files a/WebContent/WEB-INF/lib/ognl-2.6.11.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/ostermillerutils_1_07_00.jar b/WebContent/WEB-INF/lib/ostermillerutils_1_07_00.jar deleted file mode 100644 index a9931503c..000000000 Binary files a/WebContent/WEB-INF/lib/ostermillerutils_1_07_00.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/quartz-all-1.6.0.jar b/WebContent/WEB-INF/lib/quartz-all-1.6.0.jar deleted file mode 100644 index 14846679a..000000000 Binary files a/WebContent/WEB-INF/lib/quartz-all-1.6.0.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/saaj.jar b/WebContent/WEB-INF/lib/saaj.jar deleted file mode 100644 index 4ea696e74..000000000 Binary files a/WebContent/WEB-INF/lib/saaj.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/sitemesh-2.2.1.jar b/WebContent/WEB-INF/lib/sitemesh-2.2.1.jar deleted file mode 100644 index 964bc66ac..000000000 Binary files a/WebContent/WEB-INF/lib/sitemesh-2.2.1.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/slf4j-api-1.5.8.jar b/WebContent/WEB-INF/lib/slf4j-api-1.5.8.jar deleted file mode 100644 index 35502caae..000000000 Binary files a/WebContent/WEB-INF/lib/slf4j-api-1.5.8.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/slf4j-log4j12-1.5.8.jar b/WebContent/WEB-INF/lib/slf4j-log4j12-1.5.8.jar deleted file mode 100644 index b63bcdc74..000000000 Binary files a/WebContent/WEB-INF/lib/slf4j-log4j12-1.5.8.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/sourceforge.spring.modules.core-2.5.6.jar b/WebContent/WEB-INF/lib/sourceforge.spring.modules.core-2.5.6.jar deleted file mode 100644 index aafa33609..000000000 Binary files a/WebContent/WEB-INF/lib/sourceforge.spring.modules.core-2.5.6.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/spring-modules-cache.jar b/WebContent/WEB-INF/lib/spring-modules-cache.jar deleted file mode 100644 index d692fa9e2..000000000 Binary files a/WebContent/WEB-INF/lib/spring-modules-cache.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/spring.jar b/WebContent/WEB-INF/lib/spring.jar deleted file mode 100644 index 4767055eb..000000000 Binary files a/WebContent/WEB-INF/lib/spring.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/spy-2.4.jar b/WebContent/WEB-INF/lib/spy-2.4.jar deleted file mode 100644 index 3f037b23f..000000000 Binary files a/WebContent/WEB-INF/lib/spy-2.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/stringtree-json-2.0.5.jar b/WebContent/WEB-INF/lib/stringtree-json-2.0.5.jar deleted file mode 100644 index 06efba414..000000000 Binary files a/WebContent/WEB-INF/lib/stringtree-json-2.0.5.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/struts2-core-2.0.14.jar b/WebContent/WEB-INF/lib/struts2-core-2.0.14.jar deleted file mode 100644 index bd3f2db53..000000000 Binary files a/WebContent/WEB-INF/lib/struts2-core-2.0.14.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/struts2-sitemesh-plugin-2.0.14.jar b/WebContent/WEB-INF/lib/struts2-sitemesh-plugin-2.0.14.jar deleted file mode 100644 index 732008bb7..000000000 Binary files a/WebContent/WEB-INF/lib/struts2-sitemesh-plugin-2.0.14.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/struts2-spring-plugin-2.0.14.jar b/WebContent/WEB-INF/lib/struts2-spring-plugin-2.0.14.jar deleted file mode 100644 index 3eaf7af70..000000000 Binary files a/WebContent/WEB-INF/lib/struts2-spring-plugin-2.0.14.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/urlrewritefilter-4.0.3.jar b/WebContent/WEB-INF/lib/urlrewritefilter-4.0.3.jar deleted file mode 100644 index 08f6ba281..000000000 Binary files a/WebContent/WEB-INF/lib/urlrewritefilter-4.0.3.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/velocity-1.6.1-dep.jar b/WebContent/WEB-INF/lib/velocity-1.6.1-dep.jar deleted file mode 100644 index 8d8cfa313..000000000 Binary files a/WebContent/WEB-INF/lib/velocity-1.6.1-dep.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/velocity-1.6.1.jar b/WebContent/WEB-INF/lib/velocity-1.6.1.jar deleted file mode 100644 index 8a96a970f..000000000 Binary files a/WebContent/WEB-INF/lib/velocity-1.6.1.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/velocity-tools-1.4.jar b/WebContent/WEB-INF/lib/velocity-tools-1.4.jar deleted file mode 100644 index 2ff767235..000000000 Binary files a/WebContent/WEB-INF/lib/velocity-tools-1.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/velocity-tools-generic-1.4.jar b/WebContent/WEB-INF/lib/velocity-tools-generic-1.4.jar deleted file mode 100644 index 75b3ffd99..000000000 Binary files a/WebContent/WEB-INF/lib/velocity-tools-generic-1.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/velocity-tools-view-1.4.jar b/WebContent/WEB-INF/lib/velocity-tools-view-1.4.jar deleted file mode 100644 index 93693bc94..000000000 Binary files a/WebContent/WEB-INF/lib/velocity-tools-view-1.4.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/wddx.jar b/WebContent/WEB-INF/lib/wddx.jar deleted file mode 100644 index 906d65c54..000000000 Binary files a/WebContent/WEB-INF/lib/wddx.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/wsdl4j.jar b/WebContent/WEB-INF/lib/wsdl4j.jar deleted file mode 100644 index c6254ee69..000000000 Binary files a/WebContent/WEB-INF/lib/wsdl4j.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/xercesImpl-2.6.2.jar b/WebContent/WEB-INF/lib/xercesImpl-2.6.2.jar deleted file mode 100644 index 14c3162c0..000000000 Binary files a/WebContent/WEB-INF/lib/xercesImpl-2.6.2.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/xercesImpl.jar b/WebContent/WEB-INF/lib/xercesImpl.jar deleted file mode 100644 index 14c3162c0..000000000 Binary files a/WebContent/WEB-INF/lib/xercesImpl.jar and /dev/null differ diff --git a/WebContent/WEB-INF/lib/xwork-2.0.7.jar b/WebContent/WEB-INF/lib/xwork-2.0.7.jar deleted file mode 100644 index 312db8a39..000000000 Binary files a/WebContent/WEB-INF/lib/xwork-2.0.7.jar and /dev/null differ diff --git a/WebContent/WEB-INF/toolbox.xml b/WebContent/WEB-INF/toolbox.xml deleted file mode 100644 index 92fe92234..000000000 --- a/WebContent/WEB-INF/toolbox.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - version - 1.3 - - - utils - application - com.taobao.rigel.rap.common.StringUtils - - - dateUtils - application - com.taobao.rigel.rap.common.DateUtils - - diff --git a/WebContent/WEB-INF/urlrewrite.xml b/WebContent/WEB-INF/urlrewrite.xml deleted file mode 100644 index 52fa92059..000000000 --- a/WebContent/WEB-INF/urlrewrite.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - mock service - - ^/mock/(\d*?)/(.*)$ - /mock/createData.action?id=$1&pattern=/${escape:utf8:$2} - * - Origin, X-Requested-With, Content-Type, Accept - - - - mockjs service - - ^/mockjs/(\d*?)/(.*)$ - /mock/createRule.action?id=$1&pattern=/${escape:utf8:$2} - * - Origin, X-Requested-With, Content-Type, Accept - - - - mockjs result service - - ^/mockjsdata/(\d*?)/(.*)$ - /mock/createMockjsData.action?id=$1&pattern=/${escape:utf8:$2} - * - Origin, X-Requested-With, Content-Type, Accept - - - - mockjs plugin generator - - ^/rap.plugin.js(.*)$ - /mock/createPluginScript.action$1 - - \ No newline at end of file diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 2abd8ff3f..d2d64a8c4 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -1,7 +1,7 @@ rap @@ -12,30 +12,6 @@ contextConfigLocation classpath*:applicationContext.xml - - ssoFilter - com.alibaba.buc.sso.client.filter.SSOFilter - - APP_NAME - rapauto - - - SSO_CALLBACK_CLASS - com.alibaba.buc.sso.client.handler.impl.SimpleSSOCallback - - - SSO_SERVER_URL - https://login.alibaba-inc.com - - - CLIENT_KEY - 0e6f43d9-e380-4a7b-88ec-65b5568ce2ee - - - EXCLUSIONS - */stat/*,*/favicon.ico,/t/*,/crossdomain.xml,/*.htm,/*.html,*.md,*/mock/*,*/mockjs/*,*/mockjsdata/*,/rap.plugin.js - - UrlRewriteFilter org.tuckey.web.filters.urlrewrite.UrlRewriteFilter @@ -64,6 +40,18 @@ openSessionInViewFilter org.springframework.orm.hibernate3.support.OpenSessionInViewFilter + + encodingFilter + org.springframework.web.filter.CharacterEncodingFilter + + encoding + UTF-8 + + + forceEncoding + true + + SetCharacterEncoding com.taobao.rigel.rap.common.SetCharacterEncodingFilter @@ -72,18 +60,10 @@ utf-8 - - ssoFilter - /* - DelegatingFilterProxy /* - - authCheckFilter - /* - UrlRewriteFilter /* @@ -94,38 +74,13 @@ SetCharacterEncoding /* - - - velocity - - org.apache.velocity.tools.view.servlet.VelocityViewServlet - - - org.apache.velocity.toolbox - /WEB-INF/toolbox.xml - - - org.apache.velocity.properties - /WEB-INF/velocity.properties - - - - - - velocity - *.vm - struts-cleanup - org.apache.struts2.dispatcher.ActionContextCleanUp + org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter struts2 - org.apache.struts2.dispatcher.FilterDispatcher + org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter openSessionInViewFilter @@ -148,15 +103,13 @@ com.taobao.rigel.rap.common.SessionListener - - 404 - /notfound.html - - - 500 - /systembusy.html - + + + com.taobao.rigel.rap.common.RapServletContextListener + + + 60 - \ No newline at end of file + diff --git a/WebContent/account/login.vm b/WebContent/account/login.vm index b3f306f02..61bb4949b 100644 --- a/WebContent/account/login.vm +++ b/WebContent/account/login.vm @@ -1,42 +1,42 @@ - -#parse('/tcom/template.rap.vm') + - - - Login - #includeRapStatic - - - - #bodyStart -
- - - - - - - - - - - - - - - - - - #if ($errMsg && $errMsg != "") - - - - - #end -

登录

用户名:
密    码:
$!errMsg
-
- #bodyEnd - - + + + Login + #parse('/tcom/template.rap.vm') + #includeNewRapStatic + #if($returnUrlFirstSet) + #set($returnUrlEncoded = $!utils.escapeInU($returnUrl)) + #else + #set($returnUrlEncoded = $returnUrl) + #end + + + +
+ #bodyNewStart +
+ +
+ + +
+
+ + +
+ #if ($errMsg && $errMsg != "") +
+
+ $!errMsg +
+
+ #end + +
+ #bodyEnd +
+ + \ No newline at end of file diff --git a/WebContent/account/myAccount.vm b/WebContent/account/myAccount.vm deleted file mode 100644 index f1b21819e..000000000 --- a/WebContent/account/myAccount.vm +++ /dev/null @@ -1,106 +0,0 @@ - -#parse('/tcom/template.rap.vm') - - - - Manage Account - #includeNewRapStatic - - - - #bodyNewStart - #if($isEditMode) -
- #end - - - - - - - - - - - - - - #if($isEditMode) - - - - - - - - - - - - - #end - - - - - - - - - - - - - - - - - - - - -
用户名:$!curUser.account
名字: - #if($isEditMode) - - #else - $!curUser.name - #end -
Email: - #if($isEditMode) - - #else - $!curUser.email - #end -
旧密码: - * 若无需修改请忽略 -
新密码:
确认密码:
角色:$!curUser.roleListStr
注册时间:$!curUser.createDateStr
上次登录:$!curUser.lastLoginDateStr
- -
- #if($errMsg && $errMsg != "") - $!errMsg - #end -
- #if ($isEditMode) -
- #end - #bodyEnd - - - diff --git a/WebContent/account/register.vm b/WebContent/account/register.vm deleted file mode 100644 index 3677b4351..000000000 --- a/WebContent/account/register.vm +++ /dev/null @@ -1,45 +0,0 @@ - -#parse('/tcom/template.rap.vm') - - - - Register New Account - #includeRapStatic - - - #bodyStart -
-
-
-
-
用户名:
-
-
-
-
密码:
-
-
-
-
确认密码:
-
-
-
-
Email:
-
-
-
-
名字:
-
-
-
-
-
-
-
$!errMsg
-
-
-
-
- #bodyEnd - - diff --git a/WebContent/bcom/contentWithoutEscape.cb.vm b/WebContent/bcom/contentWithoutEscape.cb.vm deleted file mode 100644 index 39013f8ac..000000000 --- a/WebContent/bcom/contentWithoutEscape.cb.vm +++ /dev/null @@ -1 +0,0 @@ -$!content \ No newline at end of file diff --git a/WebContent/bcom/getModuleHtmlAjax.cb.vm b/WebContent/bcom/getModuleHtmlAjax.cb.vm deleted file mode 100644 index b4e29869b..000000000 --- a/WebContent/bcom/getModuleHtmlAjax.cb.vm +++ /dev/null @@ -1,17 +0,0 @@ -
-
- - #foreach ($page in $module.pageList) -
- - #foreach ($action in $page.actionList) - - #end -
add
-
- #end -
-
-
-
-
diff --git a/WebContent/common/blank.html b/WebContent/common/blank.html deleted file mode 100644 index b1aa3b317..000000000 --- a/WebContent/common/blank.html +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/WebContent/common/redirect.vm b/WebContent/common/redirect.vm deleted file mode 100644 index 64e7e0e81..000000000 --- a/WebContent/common/redirect.vm +++ /dev/null @@ -1,14 +0,0 @@ - - - - - RAP - 正在为您跳转 - - - 正在为您跳转... - - - - diff --git a/WebContent/demo/mock.plugin/data.json b/WebContent/demo/mock.plugin/data.json index 72d16091a..6d946c8b7 100644 --- a/WebContent/demo/mock.plugin/data.json +++ b/WebContent/demo/mock.plugin/data.json @@ -1 +1 @@ -{"a" : 1} +{"userId" : true, "isOk" : true} diff --git a/WebContent/demo/mock.plugin/data1.js b/WebContent/demo/mock.plugin/data1.js deleted file mode 100644 index 5c9761b84..000000000 --- a/WebContent/demo/mock.plugin/data1.js +++ /dev/null @@ -1 +0,0 @@ -{"a":1, "b":2} \ No newline at end of file diff --git a/WebContent/demo/mock.plugin/index.htm b/WebContent/demo/mock.plugin/index.htm deleted file mode 100644 index 8deba87b9..000000000 --- a/WebContent/demo/mock.plugin/index.htm +++ /dev/null @@ -1,39 +0,0 @@ - - - - -RAP Example - - - - - - - -

-    
-
-
diff --git a/WebContent/demo/mock.plugin/jquery-2.0.3.min.js b/WebContent/demo/mock.plugin/jquery-2.0.3.min.js
deleted file mode 100644
index 2be209dd2..000000000
--- a/WebContent/demo/mock.plugin/jquery-2.0.3.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*! jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
-//@ sourceMappingURL=jquery-2.0.3.min.map
-*/
-(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t) -};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*\s*$/g,ct={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("");C.push("");this._setReadyState(1);this.availableIframe();return C.join("")};A.prototype.availableIframe=function(){var B=document.getElementById("tangram_editor_iframe_"+this.guid);if(B){this.iframe=B;this._setReadyState(3)}else{var C=this;setTimeout(function(){C.availableIframe()},20)}};A.prototype.makeEditable=function(F){var D=this;var B=[baidu.editor.EditorConfig.docType];B.push("");if(baidu.editor.EditorConfig.skinCSS){var C=baidu.editor.EditorConfig.skinCSS+(baidu.ie?"":"?tmp="+new Date().getTime());B.push("")}B.push("");B.push(F||"");B.push("");D.window=D.iframe.contentWindow;var E=D.document=D.window.document;E.open();E.write(B.join(""));E.close();if(baidu.ie){E.body.disabled=true;E.body.contentEditable=true;E.body.removeAttribute("disabled");D._setReadyState(4)}else{setTimeout(function(){try{E.body.spellcheck=false;E.designMode="on";var J=false;try{E.execCommand("styleWithCSS",false,J)}catch(H){E.execCommand("useCSS",false,!J)}var I=false;var G=true;E.execCommand("enableObjectResizing",false,!I);E.execCommand("enableInlineTableEditing",false,!G)}catch(H){}D._setReadyState(4)},1)}};A.prototype.execCommand=function(G,D,E){var C=false,F=true;this.focus();if(this.__hasEnterdExecCommand){F=false}else{this.__hasEnterdExecCommand=true}this.dispatchEvent(new baidu.BaseEvent("onbeforeexeccommand",{command:G,topOpearation:F}));if(typeof G=="string"){var B=baidu.editor._commands;if(typeof B[G]=="function"){C=B[G].apply(null,[this].concat(Array.prototype.slice.call(arguments,1)))}else{C=this.document.execCommand(G,D,E)}}else{if(typeof G=="function"){C=G.apply(null,[this].concat(Array.prototype.slice.call(arguments,1)))}}if(F){this.__hasEnterdExecCommand=false}this.dispatchEvent(new baidu.BaseEvent("onafterexeccommand",{command:G,topOpearation:F}));this.selectionChangeHandler(null,true);return C};A.prototype.queryContextState=function(B){var C=baidu.editor._parser;if(typeof C[B]=="function"){return C[B](this)}};A.prototype.queryCommandState=function(D){var B=baidu.editor._queries;if(typeof B[D]=="function"){return B[D](this)}else{var C=navigator.userAgent;if(/(\d+\.\d)\s+safari/i.test(C)&&!/chrome/i.test(C)&&D.toLowerCase()=="paste"){return false}return this.document.queryCommandEnabled(D)&&this.document.queryCommandState(D)}};A.prototype.getContent=function(B){if(!B){var C=this.document.body.innerHTML;return C}else{var C=baidu.editor.EditorConfig.docType;C+="";C+=this.document.documentElement.innerHTML;C+="";return C}};A.prototype.setContent=function(C){var B=this;this.document.body.innerHTML=C;setTimeout(function(){B.dispatchEvent(new baidu.BaseEvent("onbeforeselectionchange"));B.dispatchEvent(new baidu.BaseEvent("onselectionchange"));B.dispatchEvent(new baidu.BaseEvent("onafterselectionchange"))},0)};A.prototype._bindEvent=function(){var D=this;function E(F){D.selectionChangeHandler(F)}function B(H){H=D.window.event||H;var G=H.keyCode||H.which,F;D.dispatchEvent(F=new baidu.BaseEvent("onbeforekeydown",H));if(F.returnValue==false){return }D.dispatchEvent(F=new baidu.BaseEvent("onkeydown",H));if(F.returnValue==false){return }if(G!=27&&G!=16&&G!=17&&G!=18){clearTimeout(B.timer);B.timer=setTimeout(function(){E()},500)}D.dispatchEvent(new baidu.BaseEvent("onafterkeydown",H))}function C(F){clearTimeout(C.timer);C.timer=setTimeout(function(){E()},20)}baidu.on(D.document,"mouseup",E);baidu.on(D.document,"keydown",B);baidu.on(D.document,"mousemove",C);baidu.on(D.window,"blur",function(){D.dispatchEvent(new baidu.BaseEvent("onblur"));D.isBlur=true});baidu.on(D.window,"focus",function(){D.dispatchEvent(new baidu.BaseEvent("onfocus"));D.isBlur=false});if(baidu.ie){setInterval(function(){if(!D.isBlur){D.ieBakRange=D.document.selection.createRange();D.ieBakRangeType=D.document.selection.type}},20)}this.dispatchEvent(new baidu.BaseEvent("onwysiwygready"))};A.prototype.selectionChangeHandler=function(H){var G=this.temp.scene;var C=this.document.body.innerHTML;if(this.temp.innerHTML!=C){this.temp.innerHTML=C;H=this.window.event||H;if(H&&H.type&&H.type.indexOf("key")>=0){var E=H.srcElement||H.target;if(E){if(E.nodeType==3){E=E.parentNode}var I=E.getElementsByTagName("*").length;if(E.tagName!="HTML"&&E==G.target&&I==G.count){return }G.target=E;G.count=I}}}else{if(window.getSelection){var B=this.window.getSelection().getRangeAt(0);if(B.startContainer==G.startContainer&&B.endContainer==G.endContainer){if(B.collapsed){return }else{if(B.startOffset==G.startOffset&&B.endOffset==G.endOffset){return }}}G.endOffset=B.endOffset;G.startOffset=B.startOffset;G.endContainer=B.endContainer;G.startContainer=B.startContainer}else{if(document.selection){var F=this.document.selection;var B=F.createRange();var D=F.type.toLowerCase();if(G.type==D){if(D=="control"&&B(0)==G.control){return }else{if(G.text==B.text&&G.parentElement==B.parentElement()){return }}}G.type=D;if(D=="control"){G.control=B(0)}else{G.text=B.text;G.parentElement=B.parentElement()}}}}this.dispatchEvent(new baidu.BaseEvent("onbeforeselectionchange"));this.dispatchEvent(new baidu.BaseEvent("onselectionchange"));this.dispatchEvent(new baidu.BaseEvent("onafterselectionchange"))};A.prototype._setReadyState=function(B){this.readyState=B;this.dispatchEvent(new baidu.BaseEvent("onreadystatechange",B))};A.prototype.addToolbarItem=function(B){if(B&&typeof B.initialize=="function"){B.initialize()}};baidu.editor.Editor=A})();baidu.editor.create=function(D,A){var E=new baidu.editor.Editor(D,A);if(typeof D=="string"){D=document.getElementById(D)}var C="";if(D&&D.tagName){if(D.tagName.toLowerCase()=="textarea"){C=D.value}else{C=D.innerHTML}}if(C==""&&A){C=A.content||""}if(!baidu.ie&&C==""){C="
"}var B=baidu.BaseClass.guid();E.addEventListener("onreadystatechange",function(H){var G=H.currentTarget;switch(G.readyState){case 3:G.makeEditable(C);break;case 4:for(var F=baidu.editor._register.length-1;F>=0;F--){baidu.editor._register[F](this)}G.removeEventListener("onreadystatechange",B);G._bindEvent();break}},B);return E};baidu.editor.Editor.prototype.focus=function(){this.window.focus();try{if(baidu.ie&&this.ieBakRange){this.ieBakRange.select()}}catch(A){}};baidu.dom=baidu.dom||{};baidu.isElement=function(A){if(A===undefined||A===null){return false}return A&&A.nodeName&&A.nodeType==1};baidu.isDocument=function(A){if(A===undefined||A===null){return false}return A&&A.nodeType==9};baidu.dom.getWindow=function(A){if(!baidu.isDocument(A)){throw new Error("[baidu.dom.getWindow] param must be Document")}return A.parentWindow?A.parentWindow:(A.defaultView?A.defaultView:null)};baidu.array=baidu.array||{};baidu.array.each=function(F,D){var C,E,B,A=F.length;if("function"==typeof D){for(B=0;B0&&B){B=B.childNodes[A.shift()]}}return B};baidu.dom.element.getName=function(B){var C=B.nodeName.toLowerCase();if(baidu.ie){var A=B.scopeName;if(A!="HTML"){C=A.toLowerCase()+":"+C}}return C};baidu.dom.element.is=function(C){var A=baidu.dom.element.getName(C);for(var B=0;B0){if(I>=V){O=baidu.dom.element.append(O,M.document.createTextNode(""));J=true}else{O=baidu.dom.element.getChild(O,I)}}}if(baidu.isText(Z)){baidu.dom.text.split(Z,T,this.document);if(Z===O){O=baidu.dom.getNext(Z)}}else{if(!T){Z=Z.insertBefore(M.document.createTextNode(""),Z.firstChild);Q=true}else{if(T>=baidu.dom.element.getChildCount(Z)){Z=baidu.dom.element.append(Z,M.document.createTextNode(""));Q=true}else{Z=baidu.dom.getPrevious(baidu.dom.element.getChild(Z,T))}}}var W=baidu.dom.getParents(Z);var E=baidu.dom.getParents(O);var U,a,Y;for(U=0;U0&&!(N===O)){L=baidu.dom.element.append(X,baidu.dom.clone(N))}if(!W[P]||N.parentNode!=W[P].parentNode){G=baidu.dom.getPrevious(N);while(G){if(G===W[P]||G===Z){break}K=baidu.dom.getPrevious(G);if(R==2){X.insertBefore(G.cloneNode(true),X.firstChild)}else{baidu.dom.element.remove(G,C);if(R==1){X.insertBefore(G,X.firstChild)}}G=K}}if(X){X=L}}if(R==2){var D=M.startContainer;if(baidu.isText(D)){D.data+=D.nextSibling.data;D.parentNode.removeChild(D.nextSibling)}var H=M.endContainer;if(baidu.isText(H)&&H.nextSibling){H.data+=H.nextSibling.data;H.parentNode.removeChild(H.nextSibling)}}else{if(a&&Y&&(Z.parentNode!=a.parentNode||O.parentNode!=Y.parentNode)){var F=baidu.dom.getIndex(Y);if(Q&&Y.parentNode==Z.parentNode){F--}M.setStart(baidu.dom.getParent(Y),F)}M.collapse(true)}if(Q){baidu.dom.element.remove(Z,C)}if(J&&O.parentNode){baidu.dom.element.remove(O,C)}};baidu.editor.Range.prototype={deleteContents:function(){var C=this.document.createDocumentFragment();if(this.collapsed){return }A(this,0,C)},cloneContents:function(){var C=this.document.createDocumentFragment();if(!this.collapsed){A(this,2,C)}return C},extractContents:function(){var C=this.document.createDocumentFragment();if(!this.collapsed){A(this,1,C)}return C},clone:function(){var C=new baidu.editor.Range(this.document);C.startContainer=this.startContainer;C.startOffset=this.startOffset;C.endContainer=this.endContainer;C.endOffset=this.endOffset;C.collapsed=this.collapsed;return C},collapse:function(C){if(C){this.endContainer=this.startContainer;this.endOffset=this.startOffset}else{this.startContainer=this.endContainer;this.startOffset=this.endOffset}this.collapsed=true},select:baidu.ie?function(){var G=this.collapsed;var C;var H;var K=this.createBookmark();var E=K.startNode;var I;if(!G){I=K.endNode}var D=this.document.body.createTextRange();D.moveToElementText(E);D.moveStart("character",1);if(I){var J=this.document.body.createTextRange();J.moveToElementText(I);D.setEndPoint("EndToEnd",J);D.moveEnd("character",-1)}else{H=this.document.createElement("span");H.innerHTML="";E.parentNode.insertBefore(H,E);var F=this.document.createTextNode("\ufeff");E.parentNode.insertBefore(F,E)}this.setStartBefore(E);baidu.dom.element.remove(E,this.document);if(G){D.moveStart("character",-1);D.select();this.document.selection.clear();baidu.dom.element.remove(H,this.document)}else{this.setEndBefore(I);baidu.dom.element.remove(I,this.document);D.select()}}:function(){var D=this.startContainer;if(this.collapsed&&baidu.isElement(D)&&!baidu.dom.element.getChildCount(D)){baidu.dom.element.append(D,this.document.createTextNode(""))}var E=this.document.createRange();E.setStart(D,this.startOffset);try{E.setEnd(this.endContainer,this.endOffset)}catch(F){if(F.toString().indexOf("NS_ERROR_ILLEGAL_VALUE")>=0){this.collapse(true);E.setEnd(this.endContainer,this.endOffset)}else{throw (F)}}var C=baidu.dom.getWindow(this.document).getSelection();C.removeAllRanges();C.addRange(E)},createBookmark:function(F){var E,C;var D;var G;E=this.document.createElement("span");baidu.dom.element.setAttr(E,"_BaiduEditor_bm",1);baidu.dom.element.setStyle(E,"display","none");E.innerHTML=" ";if(F){D="_BaiduEditor_bm"+Math.floor(Math.random()*2147483648).toString(36);baidu.dom.element.setAttr(E,"id",D+"S")}if(!this.collapsed){C=baidu.dom.clone(E);C.innerHTML=" ";if(F){baidu.dom.element.setAttr(C,"id",D+"E")}G=this.clone();G.collapse();G.insertNode(C)}G=this.clone();G.collapse(true);G.insertNode(E);if(C){this.setStartAfter(E);this.setEndBefore(C)}else{this.moveToPosition(E,POSITION_AFTER_END)}return{startNode:F?D+"S":E,endNode:F?D+"E":C,serializable:F}},moveToPosition:function(D,C){this.setStartAt(D,C);this.collapse(true)},createBookmark2:function(I){var G=this.startContainer,H=this.endContainer;var C=this.startOffset,E=this.endOffset;var J,F;if(!G||!H){return{start:0,end:0}}if(I){if(baidu.isElement(G)){J=baidu.dom.element.getChild(G,C);if(J&&baidu.isText(J)&&C>0&&baidu.isText(baidu.dom.getPrevious(J))){G=J;C=0}}while(baidu.isText(G)&&(F=baidu.dom.getPrevious(G))&&baidu.isText(F)){G=F;C+=baidu.dom.text.getLength(F)}if(!this.isCollapsed){if(baidu.isElement(H)){J=baidu.dom.element.getChild(H,E);if(J&&baidu.isText(J)&&E>0&&baidu.isText(baidu.dom.getPrevious(J))){H=J;E=0}}while(baidu.isText(H)&&(F=baidu.dom.getPrevious(H))&&baidu.isText(F)){H=F;E+=baidu.dom.text.getLength(F)}}}var D=baidu.dom.getAddress(G,this.document,I);return{start:D,end:this.isCollapsed?D:baidu.dom.getAddress(H,this.document,I),startOffset:C,endOffset:E,normalized:I,is2:true}},moveToBookmark:function(H){if(H.is2){var I=baidu.dom.getByAddress(this.document,H.start,H.normalized),D=H.startOffset;var J=H.end&&baidu.dom.getByAddress(this.document,H.end,H.normalized),F=H.endOffset;this.setStart(I,D);if(J){this.setEnd(J,F)}else{this.collapse(true)}}else{var G=H.serializable,E=G?this.document.getElementById(H.startNode):H.startNode,C=G?this.document.getElementById(H.endNode):H.endNode;this.setStartBefore(E);baidu.dom.element.remove(E,this.document);if(C){this.setEndBefore(C);baidu.dom.element.remove(C,this.document)}else{this.collapse(true)}}},setStart:function(D,C){this.startContainer=D;this.startOffset=C;if(!this.endContainer){this.endContainer=D;this.endOffset=C}B(this)},setEnd:function(C,D){this.endContainer=C;this.endOffset=D;if(!this.startContainer){this.startContainer=C;this.startOffset=D}B(this)},setStartBefore:function(C){this.setStart(baidu.dom.getParent(C),baidu.dom.getIndex(C))},setStartAfter:function(C){this.setStart(baidu.dom.getParent(C),baidu.dom.getIndex(C)+1)},setEndAfter:function(C){this.setEnd(baidu.dom.getParent(C),baidu.dom.getIndex(C)+1)},setEndBefore:function(C){this.setEnd(baidu.dom.getParent(C),baidu.dom.getIndex(C))},setStartAt:function(D,C){switch(C){case POSITION_AFTER_START:this.setStart(D,0);break;case POSITION_BEFORE_END:if(baidu.isText(D)){this.setStart(D,baidu.dom.text.getLength(D))}else{this.setStart(D,baidu.dom.element.getChildCount(D))}break;case POSITION_BEFORE_START:this.setStartBefore(D);break;case POSITION_AFTER_END:this.setStartAfter(D)}B(this)},setEndAt:function(D,C){switch(C){case POSITION_AFTER_START:this.setEnd(D,0);break;case POSITION_BEFORE_END:if(baidu.isText(D)){this.setEnd(D,baidu.dom.text.getLength(D))}else{this.setEnd(D,baidu.dom.element.getChildCount(D))}break;case POSITION_BEFORE_START:this.setEndBefore(D);break;case POSITION_AFTER_END:this.setEndAfter(D)}B(this)},getCommonAncestor:function(D,F){var G=this.startContainer,C=this.endContainer,E;if(G===C){if(D&&baidu.isElement(G)&&this.startOffset==this.endOffset-1){E=baidu.dom.element.getChild(G,this.startOffset)}else{E=G}}else{E=baidu.dom.getCommonAncestor(G,C)}return F&&!baidu.isElement(E)?baidu.dom.getParent(E):E},optimizeBookmark:function(){var D=this.startContainer,C=this.endContainer;if(baidu.isElement(D)&&baidu.dom.element.is(D,"span")&&baidu.dom.element.hasAttribute(D,"_BaiduEditor_bm")){this.setStartAt(D,POSITION_BEFORE_START)}if(C&&baidu.isElement(C)&&baidu.dom.element.is(C,"span")&&baidu.dom.element.hasAttribute(C,"_BaiduEditor_bm")){this.setEndAt(C,POSITION_AFTER_END)}},trim:function(F,I){var G=this.startContainer,C=this.startOffset,J=this.collapsed;if((!F||J)&&G&&baidu.isText(G)){if(!C){C=baidu.dom.getIndex(G);G=baidu.dom.getParent(G)}else{if(C>=baidu.dom.text.getLength(G)){C=baidu.dom.getIndex(G)+1;G=baidu.dom.getParent(G)}else{var E=baidu.dom.text.split(G,C,this.document);C=baidu.dom.getIndex(G)+1;G=baidu.dom.getParent(G);if(!J&&this.startContainer===this.endContainer){this.setEnd(E,this.endOffset-this.startOffset)}}}this.setStart(G,C);if(J){this.collapse(true)}}var H=this.endContainer;var D=this.endOffset;if(!(I||J)&&H&&baidu.isText(H)){if(!D){D=baidu.dom.getIndex(H);H=baidu.dom.getParent(H)}else{if(D>=baidu.dom.text.getLength(H)){D=baidu.dom.getIndex(H)+1;H=baidu.dom.getParent(H)}else{baidu.dom.text.split(H,D,this.document);D=baidu.dom.getIndex(H)+1;H=baidu.dom.getParent(H)}}this.setEnd(H,D)}},insertNode:function(F){this.optimizeBookmark();this.trim(false,true);var E=this.startContainer;var D=this.startOffset;var C=baidu.dom.element.getChild(E,D);if(C){C.parentNode.insertBefore(F,C)}else{E.appendChild(F)}if(baidu.dom.getParent(F)===this.endContainer){this.endOffset++}this.setStartBefore(F)},getTouchedStartNode:function(){var C=this.startContainer;if(this.collapsed||!baidu.isElement(C)){return C}return baidu.dom.element.getChild(C,this.startOffset)||C},getTouchedEndNode:function(){var C=this.endContainer;if(this.collapsed||!baidu.isElement(C)){return C}return baidu.dom.element.getChild(this.endOffset-1)||C},optimize:function(){var C=this.startContainer;var D=this.startOffset;if(!baidu.isElement(C)){if(!D){this.setStartBefore(C)}else{if(D>=baidu.dom.text.getLength(C)){this.setStartAfter(C)}}}C=this.endContainer;D=this.endOffset;if(!baidu.isElement(C)){if(!D){this.setEndBefore(C)}else{if(D>=baidu.dom.text.getLength(C)){this.setEndAfter(C)}}}},walk:function(L){var E=this.startContainer,H=this.startOffset,M=this.endContainer,I=this.endOffset,K=[{n:baidu.firefox&&this.startContainer.nodeName.toUpperCase()=="TR"?baidu.dom.getParent(this.getCommonAncestor(0,1)):this.getCommonAncestor(0,1),i:0}],G,J=false;function D(P,O,N){try{if(J==-1&&!baidu.dom.element.contains(P,E)){J=true}if(!J&&(baidu.dom.getParent(P)==E&&O==H)){J=true}if(baidu.isText(P)&&P==E){if(baidu.dom.text.getLength(P)==H){J=-1}else{if(!J){J=true}}}if(!N){return }if(baidu.isText(P)&&P==M&&I==0){J=false}if(J==true||(J==-2&&P==M)){L(P)}if(baidu.dom.getParent(P)==M&&O+1==I){J=-2}if(baidu.isText(P)&&P==M){J=false}}catch(Q){}}while(G=K.pop()){var C=G.n,F=cri=G.i;D(C,cri,false);while(C.childNodes[cri]!=undefined){K.push({n:C,i:cri});C=C.childNodes[cri];D(C,cri,false);F=cri;cri=0}D(C,F,true);if(K.length){K[K.length-1].i++}}},dispose:function(){for(var C in this){if(typeof this[C]!="function"){delete this[C]}}}}})();var SELECTION_NONE=0;var SELECTION_TEXT=2;var SELECTION_CONTROL=3;var styleObjectElements={img:1,hr:1,li:1,table:1,tr:1,td:1,embed:1,object:1,ol:1,ul:1,a:1,input:1,form:1,select:1,textarea:1,button:1,fieldset:1,th:1,thead:1,tfoot:1};baidu.editor.Editor.prototype.getSelection=function(){var B=this;if(!B.selection){var A=B.document;B.selection={getNative:baidu.ie?function(){return A.selection}:function(){return baidu.dom.getWindow(A).getSelection()},getNativeRange:function(){if(baidu.ie){var C=this.getNative(),D=C.createRange();if(C.type.toUpperCase()!="CONTROL"&&baidu.dom.getDocument(D.parentElement())!=B.document){range=B.ieBakRange;if(range){return range}}return D}else{throw new Error("[baidu.editor.selection.getNativeRange] only support ie now!")}},getType:baidu.ie?function(){var C=SELECTION_NONE;try{var E=this.getNative(),F=E.type;if(E.createRange().parentElement){C=SELECTION_TEXT}if(F.toUpperCase()!="CONTROL"&&baidu.dom.getDocument(E.createRange().parentElement())!=B.document){if(!B.ieBakRange){return SELECTION_NONE}F=B.ieBakRangeType}if(F=="Text"){C=SELECTION_TEXT}if(F=="Control"){C=SELECTION_CONTROL}}catch(D){}return C}:function(){var D=SELECTION_TEXT;var F=this.getNative();if(!F){D=SELECTION_NONE}else{if(F.rangeCount==1){var C=F.getRangeAt(0),E=C.startContainer;if(E==C.endContainer&&E.nodeType==1&&(C.endOffset-C.startOffset)==1&&styleObjectElements[E.childNodes[C.startOffset].nodeName.toLowerCase()]){D=SELECTION_CONTROL}}}return D},getRanges:baidu.ie?(function(){var C=function(I,E){I=I.duplicate();I.collapse(E);var K=I.parentElement();var F=K.firstChild;var G,H=0;while(F){if(F.nodeType==1){G=I.duplicate();G.moveToElementText(F);G.collapse();var L=G.compareEndPoints("StartToStart",I);if(L>0){break}else{if(L===0){return{container:K,offset:H}}}G=null}F=F.nextSibling;H++}if(!G){G=I.duplicate();G.moveToElementText(K);G.collapse(false)}G.setEndPoint("StartToStart",I);var D=G.text.length;var J=K.childNodes;while(D>0&&H--){F=J[H];D-=F.nodeValue?F.nodeValue.length:0}if(D===0){return{container:K,offset:H}}else{if(D>0){return{container:K,offset:0}}else{return{container:J[H],offset:-D}}}};return function(){var F=this.getNative(),K=F&&F.createRange(),L=this.getType(),J;if(!F){return[]}if(L!=SELECTION_CONTROL&&F.createRange().parentElement().ownerDocument!=B.document){K=B.ieBakRange;if(!K){return[]}L=B.ieBakRangeType.toUpperCase()=="CONTROL"?SELECTION_CONTROL:(B.ieBakRangeType.toUpperCase()=="TEXT"?SELECTION_TEXT:SELECTION_NONE)}if(L===SELECTION_TEXT){J=this.createRange();var D=C(K,true);J.setStart(D.container,D.offset);D=C(K);J.setEnd(D.container,D.offset);return[J]}else{if(L==SELECTION_CONTROL){var E=[];for(var H=0;H=0;D--){range.insertNode(F[D])}if(C){range.setStartBefore(F[F.length-1]);range.setEndAfter(F[0]);range.select()}else{E.setCursor(F[F.length-1],4)}},pasteElement:function(E,D){var F=this,C=F.getRanges()[0];C.deleteContents();C.insertNode(E);if(D){B.selection.selectElement(E)}else{F.setCursor(E,4)}},getText:function(C){if(baidu.ie){var D=B.document.selection.createRange(),E=C?D.text:baidu.trim(D.text);return E.replace("\r\n","")}else{var D=B.window.getSelection().getRangeAt(0),E=C?D.toString():baidu.trim(D.toString());return E.replace("\n","")}},getTextNodes:function(){var E=this;var C=E.getRanges();var F=[];for(var D=0;D=0;E--){if(D[E]){F.bookmarks.push(D[E].createBookmark2(true))}else{F.bookmarks.push(false)}}F.content=this.editor.getContent();return F};B.prototype.applyScene=function(G){if(!G){return }this.editor.setContent(G.content);var D=[];for(var F=G.bookmarks.length-1;F>=0;F--){if(G.bookmarks[F]){var E=this.editor.getSelection().createRange();E.moveToBookmark(G.bookmarks[F]);D.push(E)}}this.editor.getSelection().selectRanges(D);this.undoIndex=G.index;this.currentScene=G;this.fireChange()};B.prototype.save=function(E,G,H){var F=this.currentScene;if(!G){G=this.getScene()}if(E&&F&&F.content==G.content){return }this.undoList=this.undoList.slice(0,this.undoIndex+1);this.undoList.push(G);var D=this.undoList.length;if(D>baidu.editor.EditorConfig.maxUndoCount){this.undoList=this.undoList.slice(D-baidu.editor.EditorConfig.maxUndoCount,D)}this.undoIndex=this.undoList.length-1;this.currentScene=G;if(H!==false){this.fireChange()}return true};B.prototype.getNextScene=function(E){var D=this.undoList,G=this.currentScene,H,F;if(G){if(E){for(F=this.undoIndex-1;F>=0;F--){H=D[F];if(G.content!=H.content){H.index=F;return H}}}else{for(F=this.undoIndex+1;F25){E.save(true);E.modifiersCount=1}}else{if(!isReset){E.modifiersCount=0;E.typesCount++;if(E.typesCount>25){E.save(true);E.typesCount=1}}}E.typing=true}F.addEventListener("onkeydown",D,false);F.addEventListener("onbeforeexeccommand",function(G){if(!G.target.topOpearation||G.target.command=="Undo"||G.target.command=="Redo"){return }E.save(false)});F.addEventListener("onafterexeccommand",function(G){if(!G.target.topOpearation||G.target.command=="Undo"||G.target.command=="Redo"){return }E.save(false)});E.save(true)});function C(D){if(!D.undoMan.hasUndo){return }if(D.undoMan.undoIndex==D.undoMan.undoList.length-1){D.undoMan.save(false)}D.undoMan.applyScene(D.undoMan.getNextScene(true))}function A(D){if(!D.undoMan.hasRedo){return }if(D.undoMan.undoIndex==D.undoMan.undoList.length-1){return }D.undoMan.applyScene(D.undoMan.getNextScene(false))}baidu.editor.registCommand("Undo",function(D){C(D)});baidu.editor.registCommand("Redo",function(D){A(D)});baidu.editor.registQuery("Undo",function(D){return D.undoMan.hasUndo});baidu.editor.registQuery("Redo",function(D){return D.undoMan.hasRedo})})();baidu.editor.Editor.prototype.bold=function(){this.execCommand("Bold");this.dispatchEvent(new baidu.BaseEvent("onbold"))};(function(){var J={};var H=1,B=2,G=3,E=4,F=5,I=6;function K(N,M,L){var O=this;O.context=M,O.range=L;O.nodeInRange=function(P){O.context.contains.push(P);var Q=P.lastChild;while(Q){O.context.contains.push(Q);Q=Q.previousSibling}};O.nodePartlyInRange=function(P,Q){O.context.partlyContains.push(P);if(Q){var R=P.lastChild;while(R){if(O.process(R)==E){break}R=R.previousSibling}}else{var R=P.firstChild;while(R){if(O.process(R)==G){break}R=R.nextSibling}}};O.rangeInNode=function(T,U,Q){if(O.context.parents[0]!=T){O.context.parents.unshift(T)}var P=Math.floor((Q+U)/2);while(Q>=U){var S=T.childNodes[P],R=O.compareRangeWithNode(S,L);if(R==G){Q=P-1}else{if(R==E){U=P+1}else{if(R==I){O.rangeInNode(S,0,S.childNodes.length-1);break}else{if(R==F){O.nodeInRange(S);if(U<=P-1){O.rangeInNode(T,U,P-1)}if(P+1<=Q){O.rangeInNode(T,P+1,Q)}break}else{if(R==H){O.nodePartlyInRange(S,true);U=P+1}else{if(R==B){O.nodePartlyInRange(S,false);Q=P-1}}}}}}P=Math.floor((Q+U)/2)}};O.process=function(P){var Q=O.compareRangeWithNode(P,O.range);if(Q==F){O.nodeInRange(P)}else{if(Q==H||Q==B){O.nodePartlyInRange(P,Q==H)}else{if(Q==I){O.rangeInNode(P,0,P.childNodes.length-1)}}}return Q};O.compareRangeWithNode=function(U,Q){if(baidu.ie){var T=N.document.body.createTextRange();if(U.nodeType==1){T.moveToElementText(U)}else{var R=N.document.createElement("a");U.parentNode.insertBefore(R,U);var a=N.document.body.createTextRange();a.moveToElementText(R);R.parentNode.removeChild(R);T.setEndPoint("StartToStart",a);R=N.document.createElement("a");U.parentNode.insertBefore(R,U.nextSibling);var a=N.document.body.createTextRange();a.moveToElementText(R);R.parentNode.removeChild(R);T.setEndPoint("EndToStart",a)}var S=Q.compareEndPoints("StartToStart",T),Y=Q.compareEndPoints("EndToStart",T),P=Q.compareEndPoints("StartToEnd",T),V=Q.compareEndPoints("EndToEnd",T)}else{var Z=N.document.createRange();if(baidu.isText(U)&&U.parentNode.childNodes.length==1){U=U.parentNode}Z.selectNode(U);var X=N.document.createRange();X.selectNodeContents(U);var W;var S=(W=Q.compareBoundaryPoints(Range.START_TO_START,Z))==Q.compareBoundaryPoints(Range.START_TO_START,X)?W:0,P=(W=Q.compareBoundaryPoints(Range.END_TO_START,Z))==Q.compareBoundaryPoints(Range.END_TO_START,X)?W:0,Y=(W=Q.compareBoundaryPoints(Range.START_TO_END,Z))==Q.compareBoundaryPoints(Range.START_TO_END,X)?W:0,V=(W=Q.compareBoundaryPoints(Range.END_TO_END,Z))==Q.compareBoundaryPoints(Range.END_TO_END,X)?W:0}if(S<=0&&V>=0){return F}if(S>=0&&V<=0){return I}if(S*Y==-1){return B}if(P*V==-1){return H}if(S<=0&&Y<=0){return G}if(P>=0&&V>=0){return E}}}J.w3cParser=function(Q){function R(T){if(T.startContainer.nodeType==3&&T.startContainer.nodeValue.length==T.startOffset){T.setStartAfter(T.startContainer)}if(T.endContainer.nodeType==3&&T.endOffset==0){T.setEndBefore(T.endContainer)}return T}var S=new Array(),P=Q.window.getSelection();for(var N=0;N0){var Q=L.pop(),R=Q.lastChild;while(R){L.push(R);R=R.previousSibling}N.contains.push(Q)}return[N]}function A(M,L){var O=new Array();context={collapsed:false,parents:[],contains:[],partlyContains:[]};if(D(L)){context.collapsed=true}O.push(context);var N=L.parentElement();do{context.parents.push(N);N=N.parentNode}while(N.nodeName.toUpperCase()!="HTML");(new K(M,context,L)).process(L.parentElement());return O}function D(M){try{var L=M.duplicate(),O=M.duplicate();L.collapse(true);O.collapse(false);return L.inRange(O)}catch(N){return false}}baidu.editor.Editor.prototype.getContexts=function(){var N=this;if(!N.contextParserInit){function L(){var O;if(baidu.ie){O=J.ieParser(N)}else{O=J.w3cParser(N)}if(O){N.contextsInfo=O}}N.addEventListener("onbeforeselectionchange",function(O){L()});L();N.contextParserInit=true}if(!N.contextsObj){N.contextsObj={containNode:function(U,V){function O(g,a,c){var Y=[],f=-1;for(var Z=a.length-1;Z>=0;Z--){Y=Y.concat(a[Z])}a=Y;if(!a){return f}for(var Z=a.length-1;Z>=0;Z--){var b=a[Z];try{if(b.ownerDocument!=N.document){continue}}catch(d){continue}if(baidu.isText(b)){if(baidu.trim(b.nodeValue)){b=baidu.dom.getParent(b)}}if(!b){continue}if(c.toLowerCase().indexOf(","+b.nodeName.toLowerCase()+",")!=-1){continue}if(g.toLowerCase().indexOf(","+b.nodeName.toLowerCase()+",")==-1){if(f==1){return 2}f=0}else{if(f==0){return 2}f=1}}return f}U=","+U+",";V=","+V+",";var Q=this;var S=false,T=false;for(var R=Q.contains.length-1;R>=0;R--){if(Q.contains[R].length){S=true}if(Q.partlyContains[R].length){T=true}}if(S||T){var X=O(U,Q.contains,V),W=O(U,Q.partlyContains,V);if((W==2)&&(X==-1||X==0)){return 2}if((W!=-1||X!=-1)&&(X==1||X==-1)&&(W==1||W==-1)){return 1}if(W>0||X>0){return 2}}var P=O(U,Q.parents,V);if(P==2||P==1){return 3}return 0},walkTextNode:function(Q){var T=this,O=[];function P(W){for(var V=W.length-1;V>=0;V--){for(var U=W[V].length-1;U>=0;U--){if(baidu.isText(W[V][U])&&baidu.trim(W[V][U].nodeValue)){O.push(W[V][U])}}}}P(T.contains);P(T.partlyContains);for(var R=T.parents.length-1;R>=0;R--){try{if(T.parents[R][0].ownerDocument!=N.document){continue}}catch(S){continue}if(baidu.isText(T.parents[R][0])&&baidu.trim(T.parents[R][0].nodeValue)){O.push(T.parents[R][0])}}for(var R=O.length-1;R>=0;R--){Q(O[R])}}}}N.contextsObj.collapsed=[];N.contextsObj.parents=[];N.contextsObj.contains=[];N.contextsObj.partlyContains=[];for(var M=N.contextsInfo.length-1;M>=0;M--){N.contextsObj.collapsed.push(N.contextsInfo[M].collapsed);N.contextsObj.parents.push(N.contextsInfo[M].parents);N.contextsObj.contains.push(N.contextsInfo[M].contains);N.contextsObj.partlyContains.push(N.contextsInfo[M].partlyContains)}return N.contextsObj}})();baidu.getStyle=function(C,A){if(C=baidu.G(C)){var B=baidu.isString(A);A=B?[A]:A;var G=[];var H=function(M,N){return N.charAt(1).toUpperCase()};var J=function(M){var Q=M.split(",");var P="#",O;for(var N=0;O=Q[N];N++){O=O.replace(/[^\d]/gi,"");O=parseInt(O,10);O=O.toString(16);if(O.length==1){O="0"+O}P+=O}return P.toUpperCase()};for(var F=0,D;F=0?(parseFloat(L.match(/opacity=([^)]*)/)[1])/100)+"":"1"}if(D=C.style[E]){G[F]=D}else{if(C.currentStyle){D=C.currentStyle[E]}else{var I=C.nodeType==9?C:C.ownerDocument||C.document;if(I.defaultView&&I.defaultView.getComputedStyle){var K=I.defaultView.getComputedStyle(C,"");if(K){D=K[E]}}}}if(/color/i.test(E)&&D.indexOf("rgb(")!=-1){D=J(D)}G[F]=D}if(B){G=G[0]}return G}};baidu.editor.registParser("bold",function(A){var B=-1;A.getContexts().walkTextNode(function(C){var D=baidu.getStyle(baidu.dom.getParent(C),"font-weight");if(((parseInt(D)>400||D=="bold")&&(C.parentNode.tagName.indexOf("H")!==0))&&(B==-1||B==1)){B=1}else{B=0}});if(B==-1){B=0}return B});baidu.editor.Editor.prototype.italic=function(){this.execCommand("Italic");this.dispatchEvent(new baidu.BaseEvent("onitalic"))};baidu.editor.registParser("italic",function(A){var B=-1;A.getContexts().walkTextNode(function(C){var D=baidu.getStyle(baidu.dom.getParent(C),"font-style");if(D=="italic"&&(B==-1||B==1)){B=1}else{B=0}});if(B==-1){B=0}return B});baidu.editor.Editor.prototype.underline=function(){this.execCommand("Underline");this.dispatchEvent(new baidu.BaseEvent("onunderline"))};baidu.editor.registParser("underline",function(A){return A.getContexts().containNode("u")});baidu.editor.Editor.prototype.fontname=function(A){this.execCommand("FontName",false,A);this.dispatchEvent(new baidu.BaseEvent("onfontname"))};(function(){baidu.editor.Editor.prototype.queryFontname=function(){var I=this;var B=I.getSelection().getRanges();var H=[];if(B.length==1&&B[0].collapsed){var G=B[0];var F=G.startContainer;while(F.nodeType==3&&F.parentNode){F=F.parentNode}var E=baidu.getStyle(F,"font-family");return A(E)}for(var C=0;C=0){return D[C]}else{if(/^\d+/g.test(C)){return C}else{return B[C]}}}}})();baidu.editor.Editor.prototype.foreColor=function(A){this.execCommand("ForeColor",false,A);this.dispatchEvent(new baidu.BaseEvent("onforecolor"))};(function(){baidu.editor.Editor.prototype.queryForeColor=function(){var H=this,C=H.getSelection(),E=false,F=false,B=C.getRanges(),J=A||function(L){return L};function K(M){var L;while(M.parentNode&&!(L=J(baidu.getStyle(M,"color")))){M=M.parentNode}return L}if(B.length==1&&B[0].collapsed){var D=B[0].startContainer;if(baidu.isText(D)){D=baidu.dom.getParent(D)}E=K(D)}else{var I=C.getTextNodes();for(var G=0;G=H){var D;if(H==10){D=Fe.Dialog.alert("对不起,图片总数限制为"+H+"张:( !",{title:"提示",locked:true})}else{D=Fe.Dialog.alert("对不起,图片总数限制为"+H+"张:( !",{title:"提示",locked:true})}D.onopen=function(){document.body.focus()};D.onclose=function(){A.focus()};return }}var F;if(E){F=E.src}G.dialog=Fe.Dialog.open("../common/uploadRichTextImage.action"+(E!=null?"#imgUrlValue="+encodeURIComponent(F):""),{title:"添加或修改图片",width:"380px",height:"125px",buttonbar:true,buttonAccept:true,buttonCancel:true,locked:true,contentType:"HTMLUrl"});G.dialog.afterUpload=function(J){A.insertImage(J);G.dialog.close();B.uploadNum++};G.dialog.onaccept=function(K){var J=G.dialog.window,J=G.dialog.window=(!J)?G.dialog.getIframe().contentWindow:J,L=J.document;J.startUpload(G);K.returnValue=false};G.dialog.onclose=function(){A.focus()}});A.addEventListener("onselectionchange",function(E){var D=A.queryContextState("image");switch(D){case 0:C=false;break;case 1:C=true;break;case 2:C=false;break;case 3:C=true;break}});A.addEventListener("onbeforeselectionchange",function(D){A.tools.image.enable()});A.addEventListener("onafterselectionchange",function(D){if(C){B.button.highlight()}else{B.button.removeHighlight()}})};(function(){baidu.editor.Editor.prototype.getFilter=function(){var C=this;if(!C._filter){var B=C._filter=new (function(){var E={},F;this.add=function(H,G){G=G||"key_"+(new Date()).getTime();E[G]=H};this.remove=function(G){delete E[G]};var D=this.builder=new A(C);this.filter=function(H){D._process(H);for(var G in E){E[G](H)}};updateTagCount=function(G){F=C.document.getElementsByTagName("*").length};C.addEventListener("onafterexeccommand",updateTagCount);C.addEventListener("onwysiwygready",updateTagCount);C.addEventListener("onselectionchange",function(K){var G=C.document.getElementsByTagName("*").length,J,I,H;if(baidu.ie){J=C.document.selection.createRange()}else{J=C.window.getSelection().getRangeAt(0)}if(G==F){return }else{if(G<=F*0.8||G>=F*1.2){F=G;I=C.document.body}else{F=G;if(!baidu.ie){I=baidu.dom.getCommonAncestor(J.startContainer,J.endContainer)}else{H=C.document.selection;if(H.type.toUpperCase()!="CONTROL"){I=J.parentElement();if(baidu.dom.getDocument(I)!=C.document){I=C.document.body}}else{I=C.document.body}}}}B.filter(I)})})()}return C._filter};var A=function(E){var D={};var B={};var C=[];var G=function(){this.attribute={};this.allow={};this.except={};this.text=false;this.html=false;this.delegates=[]};var F=false;this.element=function(J){F=true;C=[];var I=J.split(",");for(var H=0;H=0;N--){var J=K[N];if(!L.attribute[J.name.toLowerCase()]){M.removeAttribute(J.name)}}if(M.className&&!L.attribute["class"]){M.className=""}var I=M.lastChild;while(I){var Q=I.previousSibling;switch(I.nodeType){case 1:var H=I.tagName.toLowerCase();if(((L.html&&D[H])||L.allow[H])&&!L.except[H]&&!B[H]){arguments.callee(I)}else{if(L.text&&!B[H]){var O=I.innerHTML;for(key in B){O=O.replace(new RegExp("<"+key+"[\\s\\S]*?>[\\s\\S]*?","ig"),"")}O=O.replace(/<[\s\S]*?>/ig,"").replace(/ /g," ").replace(/"/g,'"').replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&");M.insertBefore(E.document.createTextNode(O),I);M.removeChild(I)}else{M.removeChild(I)}}break;case 3:if(!L.text){M.removeChild(I)}break}I=Q}}}})();baidu.editor.register(function(A){A.getFilter().builder.element("body").attribute("contentEditable,style").html().text().element("span").attribute("style").html().text().element("pre").attribute("style").html().text().element("center").attribute("style").html().text().element("ul").attribute("style").html().text().element("ol").attribute("style").html().text().element("li").attribute("style").html().text().element("a").attribute("style, href, target").html().text().element("br").element("div").attribute("style, align").html().text().element("h1, h2, h3, h4, h5, h6").attribute("style, align").html().text().element("table").html("tbody, thead, tfoot, tr").attribute("style, cellpadding, cellspacing, border, align").element("tbody").html("thead, tfoot, tr").attribute("style").element("thead, tfoot").html("tr").attribute("style").element("tr").html("th","td").attribute("style").element("th, td").attribute("style, colspan, rowspan, align").html().text().element("b,strong").attribute("style").html().text().element("i,em").attribute("style").html().text().element("u").attribute("style").html().text().element("font").attribute("face, size, color, style").html().text().element("p").attribute("style,align").html().text().element("img").attribute("src, style, width, height").eliminate("script, style, object, embed, applet, select, input, textarea")});function ce(A){var B=document.createElement(A);B.style.MozUserSelect="none";B.unselectable="on";return B}function stopEvent(A){if(A){A.cancelBubble=true;if(A.stopPropagation){A.stopPropagation()}}}function preventDefault(A){A.returnValue=false;if(A.preventDefault){A.preventDefault()}}function Toolbar(B){var A=this;A.id=B;A.dom=baidu.G(B);A.create()}baidu.extend(Toolbar.prototype,{create:function(){this.dom.style.MozUserSelect="none";this.dom.unselectable="on"},addButton:function(A){if(A&&A.getDomObj){this.dom.appendChild(A.getDomObj())}},addBar:function(){var B=ce("div");var A=ce("span");baidu.addClass(A,"btn_bar");B.appendChild(A);A.style.MozUserSelect="none";A.unselectable="on";B.style.MozUserSelect="none";B.unselectable="on";this.dom.appendChild(B)}});Button.config={hover:"btn_hover",active:"btn_active",disabled:"btn_disabled",highlight:"btn_highlight",defaultClassName:"",textButton:"btn_text btn_default",idPrefix:"toolbar-button-"};var buttonCounter=0;function Button(A){var B=this;buttonCounter++;baidu.BaseClass.call(B);A=A||{};B.id=A.id||Button.config.idPrefix+buttonCounter;B.className=A.className||Button.config.defaultClassName;B._onclick=A.onclick;B.label=A.label;B.title=A.title;B.button=null;B.inner=null;B.isDisabled=false;B.isHighlight=false;B._createWraper()}baidu.inherits(Button,baidu.BaseClass,"Button");baidu.extend(Button.prototype,{_createWraper:function(){var D=this;var C=D.button=ce("div");C.id=D.id;if(D.label){baidu.addClass(C,Button.config.textButton)}var B=ce("div");var A=D.inner=ce("p");C.appendChild(B);B.appendChild(A);B.title=D.title;C.style.MozUserSelect="none";B.style.MozUserSelect="none";A.style.MozUserSelect="none";C.unselectable="on";B.unselectable="on";A.unselectable="on";D.createInner();D.registerHandlers();return D},createInner:function(){var B=this;var A=ce("span");baidu.addClass(A,B.className);A.style.MozUserSelect="none";A.unselectable="on";B.addContent(A);if(B.label){A.innerHTML=B.label}},addContent:function(A){this.inner.appendChild(A)},registerHandlers:function(){var B=this;var A=B.button;baidu.on(A,"mouseover",function(C){if(B.isDisabled){return }baidu.addClass(A,Button.config.hover)});baidu.on(A,"mouseout",function(C){if(B.isDisabled){return }baidu.removeClass(A,Button.config.hover);baidu.removeClass(A,Button.config.active)});baidu.on(A,"mousedown",function(C){if(B.isDisabled){return }baidu.addClass(A,Button.config.active)});baidu.on(A,"mouseup",function(C){if(B.isDisabled){return }baidu.removeClass(A,Button.config.active)});baidu.on(A,"click",function(C){if(B.isDisabled){return }if(B._onclick&&typeof B._onclick=="function"){B._onclick()}else{B.confirm()}})},getDomObj:function(){return this.button},highlight:function(){this.isHighlight=true;baidu.addClass(this.button,Button.config.highlight)},disable:function(){this.isDisabled=true;baidu.removeClass(this.button,Button.config.highlight);baidu.removeClass(this.button,Button.config.hover);baidu.addClass(this.button,Button.config.disabled)},removeHighlight:function(){this.isHighlight=false;baidu.removeClass(this.button,Button.config.highlight)},enable:function(){this.isDisabled=false;baidu.removeClass(this.button,Button.config.disabled)},confirm:function(){this.dispatchEvent(new baidu.BaseEvent("onconfirm"))}});Select.config={select:"editor-toolbar-select",caption:"editor-toolbar-select-caption",dropdown:"editor-toolbar-select-dropdown",inline:"editor-toolbar-select-inline"};var selectListCounter=0;baidu.extend(Select.config,Button.config);function Select(A){var B=this;A=A||{};B.caption=A.caption||"SELECT";B.options=A;if(A.list){B.list=A.list}else{if(A.items){B.list=new List({id:(B.id?"editor-select-list"+B.id:"editor-select-list"+selectListCounter++),items:A.items,listClassName:A.listClassName,itemClassName:A.itemClassName})}else{return false}}B.className=A.className;B._onchange=A.onchange;Button.call(B,A)}baidu.inherits(Select,Button,"Select");baidu.extend(Select.prototype,{createInner:function(){var B=this;baidu.addClass(B.button,Select.config.select);if(B.className){baidu.addClass(B.button,B.className)}var A=B.oCaption=ce("div");baidu.addClass(A,Select.config.inline);baidu.addClass(A,Select.config.caption);A.innerHTML=B.caption;var C=ce("div");baidu.addClass(C,Select.config.inline);baidu.addClass(C,Select.config.dropdown);C.innerHTML=" ";A.unselectable="on";C.unselectable="on";A.MozUserSelect="none";C.MozUserSelect="none";B.addContent(A);B.addContent(C);B._registerHanlders()},_registerHanlders:function(){var A=this;baidu.on(A.button,"mousedown",function(B){if(A.isDisabled){return }var C=baidu.getPosition(A.button);A.list.setPosition({left:C.left,top:(C.top+A.button.offsetHeight)});A.list.toggle();stopEvent(B)});baidu.on(A.button,"mouseup",function(B){if(A.isDisabled){return }stopEvent(B)});A.list._onclick=function(){A.list.hide();var B=A.list.getValue();A._setCaption(B)};A.list.addEventListener("onchange",function(){A.dispatchEvent(new baidu.BaseEvent("onchange"))})},_setCaption:function(B){var A=this;if(!B){return false}if(A.options._setCaption){A.options._setCaption(A.oCaption,B);return false}if(baidu.ie){this.oCaption.innerText=B?B:this.caption}else{this.oCaption.innerHTML=B?B:this.caption}},setValue:function(B,C){var A=this;A.list.setValue(B,C);A._setCaption(B)},getValue:function(){return this.list.getValue()}});List.config={wraper:"editor-toolbar-list",outer:"editor-toolbar-list-item",hover:"editor-toolbar-list-item-hover",selected:"editor-toolbar-list-item-selected",idPrefix:"editor-toolbar-list-"};List.lists=[];List.hideAll=function(){for(var B=0;B=0&&B-1&&/AppleWebKit\/([^\s]*)/.test(navigator.userAgent))?RegExp.$1:0;baidu.isOpera=(window.opera&&/Opera(\s|\/)(\d+(\.\d+)?)/.test(navigator.userAgent))?RegExp.$2:0;baidu.isSafari=(navigator.userAgent.indexOf("Safari")>-1&&/Version\/(\d+(\.\d+)?)/.test(navigator.userAgent))?RegExp.$1:0;baidu.isGecko=(navigator.userAgent.indexOf("Gecko")>-1&&navigator.userAgent.indexOf("KHTML")==-1&&/rv\:(\d+(\.\d+)?)/.test(navigator.userAgent))?RegExp.$1:0;baidu.isStrict=(document.compatMode=="CSS1Compat");baidu.css=function(C,G){if(!C||!G){return null}C=typeof C=="string"?document.getElementById(C):C;var B=!window.opera&&navigator.userAgent.indexOf("MSIE")!=-1;if(G=="float"){G=B?"styleFloat":"cssFloat"}G=G.replace(/(-[a-z])/gi,function(H,I){return I.charAt(1).toUpperCase()});if("opacity"==G&&B){var A=C.style.filter;return A&&A.indexOf("opacity=")>=0?(parseFloat(A.match(/opacity=([^)]*)/)[1])/100)+"":"1"}var F=null;if(F=C.style[G]){return F}if(C.currentStyle){return C.currentStyle[G]}else{var E=C.nodeType==9?C:C.ownerDocument||C.document;if(E.defaultView&&E.defaultView.getComputedStyle){var D=E.defaultView.getComputedStyle(C,"");if(D){return D[G]}}}return null};baidu.dom.getStyle=function(B,A){return baidu.css(B,A)};baidu.dom.getPosition=function(D){D=baidu.G(D);if(!baidu.isElement(D)){throw new Error("[baidu.dom.getPosition] param must be Element")}var G=baidu.dom.getDocument(D);var F=baidu.isGecko>0&&G.getBoxObjectFor&&baidu.dom.getStyle(D,"position")=="absolute"&&(D.style.top===""||D.style.left==="");var H={left:0,top:0};var B=(baidu.isIE&&!baidu.isStrict)?G.body:G.documentElement;if(D==B){return H}var C=null;var E;if(D.getBoundingClientRect){E=D.getBoundingClientRect();H.left=E.left+Math.max(G.documentElement.scrollLeft,G.body.scrollLeft);H.top=E.top+Math.max(G.documentElement.scrollTop,G.body.scrollTop);H.left-=G.documentElement.clientLeft;H.top-=G.documentElement.clientTop;if(baidu.isIE&&!baidu.isStrict){H.left-=2;H.top-=2}}else{if(G.getBoxObjectFor&&!F){E=G.getBoxObjectFor(D);var A=G.getBoxObjectFor(B);H.left=E.screenX-A.screenX;H.top=E.screenY-A.screenY}else{C=D;do{H.left+=C.offsetLeft;H.top+=C.offsetTop;if(baidu.isWebkit>0&&baidu.dom.getStyle(C,"position")=="fixed"){H.left+=G.body.scrollLeft;H.top+=G.body.scrollTop;break}C=C.offsetParent}while(C&&C!=D);if(baidu.isOpera>0||(baidu.isWebkit>0&&baidu.dom.getStyle(D,"position")=="absolute")){H.top-=G.body.offsetTop}C=D.offsetParent;while(C&&C!=G.body){H.left-=C.scrollLeft;if(!baidu.isOpera||C.tagName!="TR"){H.top-=C.scrollTop}C=C.offsetParent}}}return H};MenuButton.config={label:"toolbar-menu-button-label",dropdown:"toolbar-menu-button-dropdown",menubutton:"toolbar-menu-button"};baidu.extend(MenuButton.config,Button.config);function MenuButton(A){var B=this;A=A||{};B.label=A.label||"MenuButton";B.items=[];B.menu=new Menu();Button.call(B,A)}baidu.inherits(MenuButton,Button,"MenuButton");baidu.extend(MenuButton.prototype,{createInner:function(){var B=this;baidu.addClass(B.button,MenuButton.config.textButton);var A=ce("span");baidu.addClass(A,B.className);A.innerHTML=B.label;A.unselectable="on";A.MozUserSelect="none";B.addContent(A);B._registerHandlers()},_registerHandlers:function(){var A=this;baidu.on(A.button,"mousedown",function(B){if(A.isDisabled){return }var C=baidu.dom.getPosition(A.button);A.menu.setPosition({left:C.left,top:(C.top+A.button.offsetHeight)});A.menu.toggle();window.focus();stopEvent(B)});baidu.on(A.button,"mouseup",function(B){if(A.isDisabled){return }stopEvent(B)})},addMenuitem:function(A){this.menu.addMenuitem(A)}});var EditorTools=function(F){this.undo;this.redo;this.bold;this.italic;this.image;var E=new Toolbar(F);this.undo=new Button({className:"btn_undo",title:"撤销"});E.addButton(this.undo);this.redo=new Button({className:"btn_redo",title:"重做"});E.addButton(this.redo);E.addBar();this.bold=new Button({className:"btn_bold",title:"加粗"});E.addButton(this.bold);this.italic=new Button({className:"btn_italic",title:"斜体"});E.addButton(this.italic);this.underline=new Button({className:"btn_underline",title:"下划线"});E.addButton(this.underline);var L=[["黑色","black","000000"],["红色","red","FF0000"],["蓝色","blue","0000FF"],["绿色","green","008000"],["紫色","purple","800080"],["黄色","yellow","FFFF00"],["灰色","gray","808080"],["浅绿色","aqua","00FFFF"],["紫红色","fuchsia","FF00FF"],["褐紫色","maroon","800000"],["藏青色","navy","000080"],["黄褐色","olive","808000"],["银白色","silver","C0C0C0"]];var B={"000000":"黑色",FF0000:"红色","0000FF":"蓝色","008000":"绿色","800080":"紫色",FFFF00:"黄色","808080":"灰色","00FFFF":"浅绿色",FF00FF:"紫红色","800000":"褐紫色","000080":"藏青色","808000":"黄褐色",C0C0C0:"银白色"};var A=[];for(var J in B){var K={};K.value=J;K.content=''+B[J]+"";A.push(K)}this.forecolor=new Select({caption:"字体颜色",title:"字体颜色",className:"editor-toolbar-select-forecolor",items:A,listClassName:"editor-toolbar-forecolor-list",itemClassName:"editor-toolbar-forecolor-item",_setCaption:function(M,O){if(!O){return false}var O=O.replace("#","");O=O=="000"?"000000":O;var N=B[O];N=N||"字体颜色";baidu.ie?M.innerText=N:M.innerHTML=N}});E.addButton(this.forecolor);E.addBar();this.justifyleft=new Button({className:"btn_justifyleft",title:"居左"});E.addButton(this.justifyleft);this.justifycenter=new Button({className:"btn_justifycenter",title:"居中"});E.addButton(this.justifycenter);this.justifyright=new Button({className:"btn_justifyright",title:"居右"});E.addButton(this.justifyright);var H=["sans-serif","宋体","黑体","幼圆","楷体_GB2312","仿宋_GB2312","Arial","Comic Sans MS","Courier New","Tahoma","Times New Roman","Verdana"];var I=[];for(var C=0;C'+H[C]+"";I.push(K)}this.fontname=new Select({caption:"选择字体",title:"字体",className:"editor-toolbar-select-fontfamily",listClassName:"editor-toolbar-fontname-list",itemClassName:"editor-toolbar-fontname-item",items:I});E.addButton(this.fontname);var D={"1":"10","2":"13","3":"16","4":"18","5":"24","6":"32","7":"48"};var G=[];for(var J in D){var K={};K.value=J;K.content=''+D[J]+"";G.push(K)}this.fontsize=new Select({caption:"选择字号",title:"字号",className:"editor-toolbar-select-fontsize",items:G,listClassName:"editor-toolbar-fontsize-list",itemClassName:"editor-toolbar-fontsize-item",_setCaption:function(M,N){if(!N){return false}var O=D[N];O=O||"选择字号";baidu.ie?M.innerText=O:M.innerHTML=O}});E.addButton(this.fontsize);E.addBar();this.image=new Button({className:"btn_image",title:"插入/编辑图片"});E.addButton(this.image);this.buttonDisable()};EditorTools.prototype.buttonEnable=function(){this.bold.enable();this.italic.enable();this.image.enable();this.underline.enable();this.justifyleft.enable();this.justifycenter.enable();this.justifyright.enable();this.fontname.enable();this.fontsize.enable();this.forecolor.enable()};EditorTools.prototype.buttonDisable=function(){this.undo.disable();this.redo.disable();this.bold.disable();this.italic.disable();this.image.disable();this.underline.disable();this.justifyleft.disable();this.justifycenter.disable();this.justifyright.disable();this.fontname.disable();this.fontsize.disable();this.forecolor.disable()};function editorInit(A){var B=A.tools;A.addToolbarItem(new baidu.editor.toolbar.Undo(A,B.undo));A.addToolbarItem(new baidu.editor.toolbar.Redo(A,B.redo));A.addToolbarItem(new baidu.editor.toolbar.Bold(A,B.bold));A.addToolbarItem(new baidu.editor.toolbar.Italic(A,B.italic));A.addToolbarItem(new baidu.editor.toolbar.Underline(A,B.underline));A.addToolbarItem(new baidu.editor.toolbar.JustifyLeft(A,B.justifyleft));A.addToolbarItem(new baidu.editor.toolbar.JustifyCenter(A,B.justifycenter));A.addToolbarItem(new baidu.editor.toolbar.JustifyRight(A,B.justifyright));A.addToolbarItem(new baidu.editor.toolbar.Image(A,B.image));A.addToolbarItem(new baidu.editor.toolbar.FontName(A,B.fontname));A.addToolbarItem(new baidu.editor.toolbar.FontSize(A,B.fontsize));A.addToolbarItem(new baidu.editor.toolbar.ForeColor(A,B.forecolor))}(function(){baidu.getPosition=function(C){return{left:A(C),top:B(C)}};function A(D){var C=0;while(D!=null){C+=D.offsetLeft;D=D.offsetParent}return C}function B(D){var C=0;while(D!=null){C+=D.offsetTop;D=D.offsetParent}return C}})();(function(){baidu.getPointer=function(C){var B=document.documentElement,A=document.body||{scrollLeft:0,scrollTop:0};return{x:C.pageX||(C.clientX+(B.scrollLeft||A.scrollLeft)-(B.clientLeft||0)),y:C.pageY||(C.clientY+(B.scrollTop||A.scrollTop)-(B.clientTop||0))}}})(); \ No newline at end of file diff --git a/WebContent/stat/js/ui/floater/css/floater.css b/WebContent/stat/js/ui/floater/css/floater.css deleted file mode 100644 index 46662300f..000000000 --- a/WebContent/stat/js/ui/floater/css/floater.css +++ /dev/null @@ -1,9 +0,0 @@ -.floaterd {padding-top:3px;} -.floaterd-top {background: #3B5C55} -.floaterd-bottom {display:none} -.floater {position:absolute !important;} -.floater-title {border-right:1px solid #CBE9B7;border-left:1px solid #CBE9B7;border-top:1px solid #CBE9B7;cursor:move;position:absolute;left:0;top:0;height:23px;padding:4px 10px 0 18px;background:url(img/global_bg.png) 0 -150px repeat-x;font-size:12px;color:#E2FEC4;font-weight:bold;} -.floater-close {position:absolute;right:5px;top:5px;font-size:1px;border:0px;float:right;display:block;width:19px;height:19px;background:url(img/btn.gif) -83px -49px;cursor:pointer;} -.floater-content {padding:37px 18px 9px;border-right:1px solid #CBE9B7;border-left:1px solid #CBE9B7;border-bottom:1px solid #CBE9B7;background:#F3FBEC} -.floater-inner {overflow-y:auto;overflow-x:hidden} -.floater-corner {background: #fff} diff --git a/WebContent/stat/js/ui/foldable/css/foldable.css b/WebContent/stat/js/ui/foldable/css/foldable.css deleted file mode 100644 index dbba70641..000000000 --- a/WebContent/stat/js/ui/foldable/css/foldable.css +++ /dev/null @@ -1,14 +0,0 @@ -/*.ec-foldable {border:solid 1px #000}*/ -.ec-foldable-title {padding:2px 0 4px 20px;cursor:pointer;border-bottom:1px solid #DFF4CD;color:#356502;font-size:14px;} -/*.ec-foldable-title-over {background-color:#EEE}*/ -/*.ec-foldable-title-press {background-color:#CCC}*/ -.ec-foldable-handler {float:right;margin:3px 3px 0 0} -.ec-foldable-title-fold .ec-foldable-handler, .ec-foldable-title-unfold .ec-foldable-handler {width:16px;height:16px} -.ec-foldable-title-fold .ec-foldable-handler {background:url("img/remove.gif") no-repeat scroll 0 0 transparent;} -.ec-foldable-title-unfold .ec-foldable-handler {background:url("img/add.gif") no-repeat scroll 0 0 transparent;} -.icon-a .ec-foldable-title, .icon-b .ec-foldable-title, .icon-c .ec-foldable-title, .icon-d .ec-foldable-title, .icon-e .ec-foldable-title {background:url("img/icon.gif") no-repeat scroll 0 -145px transparent;} -.icon-b .ec-foldable-title {background-position:0 -170px;} -.icon-c .ec-foldable-title {background-position:0 -195px;} -.icon-d .ec-foldable-title {background-position:0 -248px;} -.icon-e .ec-foldable-title {background-position:0 -273px;} -.ec-foldable-content {margin:5px} diff --git a/WebContent/stat/js/ui/foldable/js/ecomui.foldable.js b/WebContent/stat/js/ui/foldable/js/ecomui.foldable.js deleted file mode 100644 index 23f8f5309..000000000 --- a/WebContent/stat/js/ui/foldable/js/ecomui.foldable.js +++ /dev/null @@ -1,66 +0,0 @@ -var ecomui = ecomui || {}; - -(function() { - var lib = baidu, - core = ecui, - dom = core.dom, - ui = core.ui, - util = core.util, - inherits = util.inherits, - copy = util.copy, - - children = dom.children, - createDom = dom.create, - $fastCreate = core.$fastCreate, - setText = dom.setText, - - DOCUMENT = document, - UI_CONTROL = ui.Control, - ECOM_FOLDABLE_CLASS; - - ecomui.Foldable = ui.Foldable = function(el, params) { - var typeClass = params.type, - contentEl = children(el)[0]; - titleEl = createDom(typeClass + "-title"), - handlerEl = createDom(typeClass + "-handler"); - - el.insertBefore(titleEl, contentEl); - setText(titleEl, params.title || ""); - titleEl.insertBefore(handlerEl, titleEl.firstChild); - - params.capture = false; - - UI_CONTROL.call(this, el, params); - - this._uTitle = $fastCreate(UI_CONTROL, titleEl, this); - this._uContent = $fastCreate(UI_CONTROL, contentEl, this, {capture: false}); - this._uHandler = $fastCreate(UI_CONTROL, handlerEl, this._uTitle, {capture: false}); - - this._uTitle["on" + (params.trigger || "click")] = ECOM_FOLDABLE_TITLECLICK; - - ECOM_FOLDABLE_TOGGLECONTENT.call(this._uTitle, params.initFold || false); - }; - - function ECOM_FOLDABLE_TITLECLICK() { - ECOM_FOLDABLE_TOGGLECONTENT.call(this); - } - - function ECOM_FOLDABLE_TOGGLECONTENT(fold) { - var control = this.getParent(), - content = control._uContent, - handler = control._uHandler, - handlerEl = handler.getBase(), - isShow = fold !== undefined ? fold : content.isShow(); - - isShow ? content.hide() : content.show(); - handlerEl.setAttribute("title", isShow ? "点击展开" : "点击折叠"); - - this.$alterClass(isShow ? "unfold" : "fold"); - this.$alterClass(isShow ? "fold" : "unfold", true); - - control.$resize(); - } - - ECOM_FOLDABLE_CLASS = inherits(ui.Foldable, UI_CONTROL); - - })(); diff --git a/WebContent/stat/js/ui/popup/css/popup.css b/WebContent/stat/js/ui/popup/css/popup.css deleted file mode 100644 index 520f5e625..000000000 --- a/WebContent/stat/js/ui/popup/css/popup.css +++ /dev/null @@ -1,28 +0,0 @@ -.popupdtr {padding-top:9px;padding-bottom:9px} -.popupdtr-top {background:url(img/popup_tb.jpg) top left no-repeat;overflow:hidden;font-size:0px} -.popupdtr-bottom {background:url(img/popup_tb.jpg) 0px -9px no-repeat;font-size:0px} - -.ec-popup {padding-right:13px;border-width:auto;border:none;background:url(img/popup_bg.jpg) top left repeat-y;width:267px;overflow-y:auto;overflow-x:hidden} -.ec-popup .ec-item {padding:auto;height:22px;margin-left:3px;margin-right:3px;padding-left:32px;line-height:22px;cursor:default;border-width:auto;border:none} -.ec-popup-item {padding:auto;height:22px;margin-left:3px;margin-right:3px;padding-left:32px;line-height:22px;cursor:default;background:none;border-bottom:none} -.ec-popup-item-over {background:url(img/popup_over.jpg) top left no-repeat} -.ec-popup-item-complex {background:url(img/popup_more.jpg) 245px 7px no-repeat} -.ec-popup-item-complex-over {background:url(img/popup_more_over.jpg) left top no-repeat} - -.ec-scpopup {padding-right:13px;border-width:auto;border:none;background:url(img/popup_bg.jpg) top left repeat-y;width:267px} -.ec-scpopup-layout {width:260px;height:100%;overflow-y:auto;overflow-x:hidden} -.ec-scpopup .ec-item {padding:auto;height:22px;margin-left:3px;margin-right:3px;padding-left:10px;line-height:22px;cursor:default;border-width:auto;border:none} -.ec-scpopup-item {padding:auto;height:22px;margin-left:3px;margin-right:3px;padding-left:10px;line-height:22px;cursor:default;background:none;border-bottom:none} -.ec-scpopup-item-over {background:url(img/popup_over.jpg) top left no-repeat} -.ec-scpopup-item-complex {background:url(img/popup_more.jpg) 244px 7px no-repeat} -.ec-scpopup-item-complex-over {background:url(img/popup_more_over.jpg) left top no-repeat} -.ec-scpopup-layout-overheight .ec-scpopup-item-complex {background:url(img/popup_more.jpg) 227px 7px no-repeat} -.ec-scpopup-layout-overheight .ec-scpopup-item-complex-over {background:url(img/popup_more_over_oh.jpg) left top no-repeat} -.ec-scpopup-layout-overheight .ec-scpopup-item-over {background:url(img/popup_over_oh.jpg) top left no-repeat} - -.ec-ecombox {top:5px;width:120px;height:17px;border:1px solid #CCC;background:#FFF} -.ec-ecombox-button {top:0px;right:0px;width:17px;height:17px;background:url(img/select.jpg) 0px 0px no-repeat} -.ec-ecombox-over .ec-ecombox-button {background:url(img/select.jpg) -17px 0px no-repeat} -.ec-ecombox-press .ec-ecombox-button {background:url(img/select.jpg) -34px 0px no-repeat} - - diff --git a/WebContent/stat/js/ui/popup/js/ecpopup.js b/WebContent/stat/js/ui/popup/js/ecpopup.js deleted file mode 100644 index 00c85c48d..000000000 --- a/WebContent/stat/js/ui/popup/js/ecpopup.js +++ /dev/null @@ -1,245 +0,0 @@ -(function () { - var core = ecui, - dom = core.dom, - ui = core.ui, - util = core.util, - ext = core.ext, - - createControl = core.create, - inherits = util.inherits, - getView = util.getView, - getPosition = dom.getPosition, - first = dom.first, - copy = util.copy, - blank = core.blank, - restore = core.restore, - trim = core.string.trim, - setStyles = dom.setStyles, - insertFloor = dom.insertFloor, - mask = core.mask, - removeDom = dom.remove, - getChild = dom.children, - setText = dom.setText, - getText = dom.getText, - createDom = dom.create, - moveElements = dom.moveElements, - - DOCUMENT = document, - - - UI_EDIT = ui.Edit, - UI_ITEM = ui.Item, - UI_CONTROL = ui.Control, - UI_CONTROL_CLASS = UI_CONTROL.prototype, - UI_EDIT_CLASS = UI_EDIT.prototype, - UI_POPUP = ui.Popup, - UI_POPUP_CLASS = UI_POPUP.prototype; - - var UI_ECOMBOX = ui.Ecombox = function (el, params) { - var me = this, - typeClass = params.type, - items; - - me._uPopup = createControl( - 'Scpopup', - { - 'element' : first(el) - } - ); - me._uPopup.$setParent(me); - items = me._uPopup.getItems(); - - for (var i = 0, item; item = items[i]; i++) { - UI_ECOMBOX_ATTACHHANDLER(item); - } - - - UI_EDIT.call(me, el, params); - - (params.maxlength) && (this.getInput().maxLength = params.maxlength); - this.getInput().style.position = 'absolute'; - - (me._uButton = createControl( - 'Control', - { - 'base' : typeClass + '-button', - 'parent' : me, - 'capture' : false - } - )).getOuter().style.position = 'absolute'; - - el.style.position = 'relative'; - }, - - UI_ECOMBOX_CLASS = inherits(UI_ECOMBOX, UI_EDIT); - - UI_ECOMBOX_CLASS.$click = function (event) { - var target = event.target; - UI_EDIT_CLASS.$click.call(this, event); - if (target.getControl && target.getControl() == this._uButton) { - this.showPopup(); - } - }; - - UI_ECOMBOX_CLASS.setValue = function (text) { - if (this.getInput().value != text) { - UI_EDIT_CLASS.setValue.call(this, text); - return true; - } - else { - return false; - } - }; - - UI_ECOMBOX_CLASS.showPopup = function () { - var pos = getPosition(this.getOuter()), - o = this._uPopup, - popupTop = pos.top + this.getHeight(), - items; - - o.setPosition( - pos.left, - popupTop + o.getHeight() <= getView().bottom ? popupTop : pos.top - o.getHeight() - ); - - items = o.getItems(); - for (var i = 0, item; item = items[i]; i++) { - (item._cPopup) && (item._cPopup.paint()); - } - - mask(0.05); - o.show(); - o.onhide = UI_ECOMBOX_HIDEMASK; - }; - - UI_ECOMBOX_CLASS.$setSize = function (width, height) { - UI_EDIT_CLASS.$setSize.call(this, width, height); - - width = this.getBodyWidth() - height; - this.getInput().style.width = width + 'px' - setStyles(this.getInput(), {'width' : width + 'px', 'height' : height + 'px'}); - }; - - function UI_ECOMBOX_HIDEMASK() { - mask(); - } - - function UI_ECOMBOX_SETVALUE() { - var el = this.getBody(), - value = el.getAttribute('value'), - text = trim(el.getAttribute('title') ? el.getAttribute('title') : el.innerHTML), - con = this; - - while ((con = con.getParent()) && !(con instanceof UI_ECOMBOX)) {} - - if ((con) && (con.setValue(text)) && (con.onpostdata)) { - con.onpostdata(value); - } - - } - - function UI_ECOMBOX_ATTACHHANDLER(item) { - var childs = item.getChildItems(); - if (childs.length == 0) { - return; - } - for (var i = 0, child; child = childs[i]; i++) { - child.onclick = UI_ECOMBOX_SETVALUE; - UI_ECOMBOX_ATTACHHANDLER(child); - } - } - - var UI_SCPOPUP = ui.Scpopup = function (el, params) { - var i = 0, - o; - - UI_CONTROL.call(this, el, params); - - o = createDom(); - moveElements(o, el); - el.appendChild(o); - this._eBody = o; - this._eBody.className = params.type + '-layout'; - - this._nMaxHeight = params.maxheight || 300; - this._nMaxTextLen = params.maxTextLen || 20; - - /* 初始化菜单项 */ - //this.setParent(DOCUMENT.body); - DOCUMENT.body.appendChild(el); - this.$initItems(); - this.$alterItems(); - - el = this.getOuter().style; - el.display = 'none'; - el.position = 'absolute'; - - /* 弹出菜单初始化完成后就不允许改变父对象 */ - this.setParent = blank; - - /* 初始化子弹出菜单 */ - for (el = this.getItems(); o = el[i++]; ) { - o._cPopup && o.setClass(params.base + '-item-complex'); - } - - /* 修正文字长度不能超过限制 */ - for (i=0, el = getChild(this._eBody); o = el[i++];) { - if (first(o) && first(o).tagName.toLowerCase() == 'label') { - o = first(o); - } - if ((getText(o).length) > this._nMaxTextLen) { - o.setAttribute('title', getText(o)); - setText(o, getText(o).substring(0, this._nMaxTextLen - 3) + '...'); - } - } - }, - - UI_SCPOPUP_CLASS = inherits(UI_SCPOPUP, UI_POPUP); - - UI_SCPOPUP_CLASS.$createChild = function (item, el) { - var popup; - if (trim(el.innerHTML) == '') { - removeDom(el); - return false; - } - popup = item._cPopup = createControl( - 'Scpopup', - { - base: item.getParent().getClass(), - element: el - } - ); - - popup.$setParent(item); - return popup; - }; - - UI_SCPOPUP_CLASS.$create = function () { - new ext.TBDecorator(this, 'popupdtr'); - UI_CONTROL_CLASS.$create.call(this); - }; - - UI_SCPOPUP_CLASS.$setSize = function (width, height) { - var el = this._eBody; - if ( height > this._nMaxHeight) { - height = this._nMaxHeight; - if (el.className.indexOf('overheight') < 0) { - el.className = el.className + ' ' + this.getBaseClass() + '-layout-overheight'; - } - } - UI_CONTROL_CLASS.$setSize.call(this, width, height); - }; - - UI_SCPOPUP_CLASS.$forcibly = function (event) { - var con = event.getTarget(), find = false; - while(con) { - if (con == this) { - find = true; - break; - } - con = con.getParent(); - } - (!find) && (UI_POPUP_CLASS.$forcibly.call(this)); - return false; - } -})() diff --git a/WebContent/stat/js/ui/scroll/css/scroll.css b/WebContent/stat/js/ui/scroll/css/scroll.css deleted file mode 100644 index b9ff6824b..000000000 --- a/WebContent/stat/js/ui/scroll/css/scroll.css +++ /dev/null @@ -1,36 +0,0 @@ -.ec-vscroll {background:#F0F0F0;width:auto;padding:15px 0px 15px 0px;font-size:0px} -.ec-hscroll {background:#F0F0F0;height:auto;padding:0px 15px 0px 15px;font-size:0px} -.ec-hscroll-block {background:url(img/hscroll.jpg) -2px -30px repeat-x} -.ec-vscroll-block {background:url(img/scroll.jpg) 0px 0px repeat-y} -.ec-hscroll-block-over {background:url(img/hscroll.jpg) -0px -45px repeat-x} -.ec-hscroll-block-press {background:url(img/hscroll.jpg) -0px -60px repeat-x} -.ec-vscroll-block-over {background:url(img/scroll.jpg) -15px 0px repeat-y} -.ec-vscroll-block-press {background:url(img/scroll.jpg) -30px 0px repeat-y} -.ec-vscroll-prev {background:url(img/scroll.jpg) -45px -40px no-repeat;} -.ec-vscroll-prev-over {background:url(img/scroll.jpg) -75px -40px no-repeat;} -.ec-vscroll-prev-press {background:url(img/scroll.jpg) -60px -40px no-repeat;} -.ec-vscroll-next {background:url(img/scroll.jpg) -45px -55px no-repeat;} -.ec-vscroll-next-over {background:url(img/scroll.jpg) -75px -55px no-repeat;} -.ec-vscroll-next-press {background:url(img/scroll.jpg) -60px -55px no-repeat;} -.ec-hscroll-prev {background:url(img/scroll.jpg) -45px -85px no-repeat;} -.ec-hscroll-prev-over {background:url(img/scroll.jpg) -75px -85px no-repeat;} -.ec-hscroll-prev-press {background:url(img/scroll.jpg) -60px -85px no-repeat;} -.ec-hscroll-next {background:url(img/scroll.jpg) -45px -70px no-repeat;} -.ec-hscroll-next-over {background:url(img/scroll.jpg) -75px -70px no-repeat;} -.ec-hscroll-next-press {background:url(img/scroll.jpg) -60px -70px no-repeat;} - -.vsblockdtr {padding:2px 0px} -.vsblockdtr-top {background:url(img/scroll.jpg) -45px 0px no-repeat} -.vsblockdtr-bottom {background:url(img/scroll.jpg) -45px -18px no-repeat} -.vsblockdtr-over .vsblockdtr-top {background:url(img/scroll.jpg) -45px -20px no-repeat} -.vsblockdtr-over .vsblockdtr-bottom {background:url(img/scroll.jpg) -45px -38px no-repeat} -.vsblockdtr-press .vsblockdtr-top {background:url(img/scroll.jpg) -60px 0px no-repeat} -.vsblockdtr-press .vsblockdtr-bottom {background:url(img/scroll.jpg) -60px -38px no-repeat} - -.hsblockdtr {padding:0px 2px} -.hsblockdtr-left {background:url(img/hscroll.jpg) -60px 0px no-repeat} -.hsblockdtr-right {background:url(img/hscroll.jpg) -18px 0px no-repeat} -.hsblockdtr-over .hsblockdtr-left {background:url(img/hscroll.jpg) -40px -0px no-repeat} -.hsblockdtr-over .hsblockdtr-right {background:url(img/hscroll.jpg) -38px -0px no-repeat} -.hsblockdtr-press .hsblockdtr-left {background:url(img/hscroll.jpg) -40px -15px no-repeat} -.hsblockdtr-press .hsblockdtr-right {background:url(img/hscroll.jpg) -38px -15px no-repeat} diff --git a/WebContent/stat/js/ui/selectbox/css/selectbox.css b/WebContent/stat/js/ui/selectbox/css/selectbox.css deleted file mode 100644 index e4f0fc0b4..000000000 --- a/WebContent/stat/js/ui/selectbox/css/selectbox.css +++ /dev/null @@ -1,16 +0,0 @@ -.ec-panel{z-index:9000;height:100px;width:137px;background:#fff} -.ec-panel-corner {background:#F0F0F0;font-size:1px;} -.ec-panel-layout {border:1px solid #CCC;line-height:20px;padding:3px;} -.select-box .ec-panel-layout{text-align:left;margin-top:1px;background:#fff;} -.select-box .ec-vscroll{border-right:1px #ccc solid;cursor:pointer;cursor:hand;} -.select-box button {margin:5px 0;} -.select-box .ec-edit{padding-right:15px;height:15px;background:#fff url("img/scroll_bg.gif") no-repeat right -15px;border:1px #ccc solid;cursor:pointer;cursor:hand;} - - - -.ec-panel-corner {background:#F0F0F0;font-size:1px;} -.ec-panel-layout {background:#fff; border:1px solid #CCC;line-height:20px;padding:3px;} -.select-box .ec-panel-layout{text-align:left;margin-top:1px;background:#fff;} -.select-box .ec-vscroll{border-right:1px #ccc solid;cursor:pointer;cursor:hand;} -.select-box button {margin:5px 0;} -.sel-edit{z-index:9000;padding-right:13px;background:#fff url("img/scroll_bg.gif") no-repeat right -14px;border:1px #ccc solid;cursor:pointer;cursor:hand;} diff --git a/WebContent/stat/js/ui/selectbox/js/selectbox.js b/WebContent/stat/js/ui/selectbox/js/selectbox.js deleted file mode 100644 index 1227840ed..000000000 --- a/WebContent/stat/js/ui/selectbox/js/selectbox.js +++ /dev/null @@ -1,136 +0,0 @@ -//按钮的点击事件 - function wrapHide(tg){ - var wrap = baidu.dom.getAncestorByClass(tg, "ec-panel"); - wrap = wrap.getControl(); - var selectBox = wrap.getParent(); - var edit = selectBox._uEdit.getInput(); - var allBox = selectBox._uPanel.getOuter().getElementsByTagName("input") - var str = ""; - for(var i=0,j=0; i'; - panelHTML += '
'; - body.innerHTML = panelHTML; - core.init(body); - this.setClass("select-box"); - - this._uHeight = params.pHeight || 30 - this._uCol = params.col || 1; - this._uName = params.name; - this._uEdit = core.get("edit-" + id); - this._uPanel =core.get("panel-" + id); - - //最开始隐藏下拉层 - this._uPanel.hide(); - this.init(); - //绑定事件 - this._uEdit.onclick = SELECT_BOX_CLASS.oneditclick; - } - - //原型继承至基础控件 - SELECT_BOX_CLASS = inherits(ui.SelectBox, UI_CONTROL); - - - //点击输入框弹出下拉层 - SELECT_BOX_CLASS.oneditclick = function(){ - var wrap = this.getParent() - var panelDom = wrap._uPanel.getBase(); - baidu.dom.toggle(panelDom); - - } - - //屏蔽点击事件,返回给控件 - SELECT_BOX_CLASS.$pressend = function(){ - ecui.forcibly(this); - mask(0, 65534); - } - - //重写$forcibly方法 - SELECT_BOX_CLASS.$forcibly = function(){ - var wrap = this.getParent() - var panelDom = wrap._uPanel.getBase(); - baidu.dom.toggle(panelDom); - } - - - //设置下拉面板的可见高度 - SELECT_BOX_CLASS.setPHeight = function(){ - var pHeight = this._uHeight; - var pStyle = this._uPanel.getOuter().style; - pStyle.height = pHeight; - - } - - //控件初始化 - SELECT_BOX_CLASS.init = function(){ - this.setPst(); - this.setPHeight(); - } - - //根据edit定位下拉层 - SELECT_BOX_CLASS.setPst = function(){ - var edit = this._uEdit.getBase(); - var editX = baidu.dom.getPosition(edit).left; - var editY = baidu.dom.getPosition(edit).top; - var pStyle = this._uPanel.getBase(); - pStyle.style.position = "absolute"; - this._uPanel.setPosition(editX,editY+15); - } - - SELECT_BOX_CLASS.updata =function(){ - var allBox = this._uPanel; - alert(allBox) - - - } - - //滚动条不因后面的内容增加而出现 TODO - //设置下拉框中的内容,根据数据构造多个checkbox - SELECT_BOX_CLASS.setData = function(data){ - var sData = data; - var Fname = this._uName; - var Fcol = this._uCol; - var optionHTML = ""; - var checkboxIndex = 1; - var panelContent = this._uPanel.getBody(); - baidu.array.each(sData,function(item,i){ - Schecked = item.isChecked? 'checked="checked"' : ""; - optionHTML += ''; - optionHTML += ''; - if(checkboxIndex%Fcol == 0) optionHTML += '
'; - checkboxIndex++; - }); - optionHTML +='
' - panelContent.innerHTML = optionHTML; - } - - - })() \ No newline at end of file diff --git a/WebContent/stat/js/ui/table/css/table.css b/WebContent/stat/js/ui/table/css/table.css deleted file mode 100644 index 98b842210..000000000 --- a/WebContent/stat/js/ui/table/css/table.css +++ /dev/null @@ -1,136 +0,0 @@ -/* FOR OPERA */ -div{border:0;} - .ec-ecom-table .ec-vscroll {background:#F2F8EE;width:15px;padding:15px 0px 15px 0px;font-size:1px} - .ec-ecom-table .ec-hscroll {background:#F2F8EE;height:15px;padding:0px 15px 0px 15px;font-size:1px} - .ec-ecom-table .ec-hscroll-block {background:url("img/hscroll.gif") -2px -30px repeat-x;border:1px solid #76A258;border-width:0 1px} - .ec-ecom-table .ec-vscroll-block {background:url("img/scroll.gif") 0px 0px repeat-y;border:1px solid #76A258;border-width:1px 0} - .ec-ecom-table .ec-hscroll-block-over {background:url("img/hscroll.gif") -0px -45px repeat-x} - .ec-ecom-table .ec-hscroll-block-press {background:url("img/hscroll.gif") -0px -60px repeat-x} - .ec-ecom-table .ec-vscroll-block-over {background:url("img/scroll.gif") -15px 0px repeat-y} - .ec-ecom-table .ec-vscroll-block-press {background:url("img/scroll.gif") -30px 0px repeat-y} - .ec-ecom-table .ec-vscroll-prev {background:url("img/scroll.gif") -45px -40px no-repeat;} - .ec-ecom-table .ec-vscroll-prev-over {background:url("img/scroll.gif") -75px -40px no-repeat;} - .ec-ecom-table .ec-vscroll-prev-press {background:url("img/scroll.gif") -60px -40px no-repeat;} - .ec-ecom-table .ec-vscroll-next {background:url("img/scroll.gif") -45px -55px no-repeat;} - .ec-ecom-table .ec-vscroll-next-over {background:url("img/scroll.gif") -75px -55px no-repeat;} - .ec-ecom-table .ec-vscroll-next-press {background:url("img/scroll.gif") -60px -55px no-repeat;} - .ec-ecom-table .ec-hscroll-prev {background:url("img/scroll.gif") -45px -85px no-repeat;} - .ec-ecom-table .ec-hscroll-prev-over {background:url("img/scroll.gif") -75px -85px no-repeat;} - .ec-ecom-table .ec-hscroll-prev-press {background:url("img/scroll.gif") -60px -85px no-repeat;} - .ec-ecom-table .ec-hscroll-next {background:url("img/scroll.gif") -45px -70px no-repeat;} - .ec-ecom-table .ec-hscroll-next-over {background:url("img/scroll.gif") -75px -70px no-repeat;} - .ec-ecom-table .ec-hscroll-next-press {background:url("img/scroll.gif") -60px -70px no-repeat;} - .ec-ecom-table .vsblockdtr {padding:2px 0px} - .ec-ecom-table .vsblockdtr-top {background:url("img/scroll.gif") -45px 0px no-repeat} - .ec-ecom-table .vsblockdtr-bottom {background:url("img/scroll.gif") -45px -18px no-repeat} - .ec-ecom-table .vsblockdtr-over .vsblockdtr-top {background:url("img/scroll.gif") -45px -20px no-repeat} - .ec-ecom-table .vsblockdtr-over .vsblockdtr-bottom {background:url("img/scroll.gif") -45px -38px no-repeat} - .ec-ecom-table .vsblockdtr-press .vsblockdtr-top {background:url("img/scroll.gif") -60px 0px no-repeat} - .ec-ecom-table .vsblockdtr-press .vsblockdtr-bottom {background:url("img/scroll.gif") -60px -38px no-repeat} - .ec-ecom-table .ec-panel-disabled .vsblockdtr div {display:none} - .ec-ecom-table .hsblockdtr {padding:0px 2px} - .ec-ecom-table .hsblockdtr-left {background:url("img/hscroll.gif") -60px 0px no-repeat} - .ec-ecom-table .hsblockdtr-right {background:url("img/hscroll.gif") -18px 0px no-repeat} - .ec-ecom-table .hsblockdtr-over .hsblockdtr-left {background:url("img/hscroll.gif") -40px -0px no-repeat} - .ec-ecom-table .hsblockdtr-over .hsblockdtr-right {background:url("img/hscroll.gif") -38px -0px no-repeat} - .ec-ecom-table .hsblockdtr-press .hsblockdtr-left {background:url("img/hscroll.gif") -40px -15px no-repeat} - .ec-ecom-table .hsblockdtr-press .hsblockdtr-right {background:url("img/hscroll.gif") -38px -15px no-repeat} - .ec-ecom-table .ec-panel-disabled .hsblockdtr div {display:none} - .ec-ecom-table {border:1px solid #9CD167;padding-top:23px;background-color:#DCEFD1} - .ec-ecom-table .checkbox {padding-left:0px;padding-right:0px;} - .ec-ecom-table .checkbox-item {padding-left:0px;padding-right:0px;} - .ec-ecom-table .checkbox-disabled {background:url(img/cr.gif) -68px 0px no-repeat;width:17px;height:17px;;margin-right:5px} - .ec-ecom-table table {border-collapse:collapse;border-spacing:0px} - .ec-ecom-table-layout {background:#FFF;color:#333} - .ec-ecom-table-head, .ec-print-table th{ font-weight:normal; color:#326700; padding:6px 5px; padding-right:12px; line-height:15px; border:0; border-left:1px solid #CCE9B9; border-bottom:1px solid #9CD167; overflow:hidden; white-space:nowrap; word-wrap:normal; word-break:keep-all } - .ec-ecom-table-item, .ec-print-table td{ line-height:15px; border:0; padding:5px 5px; padding-right:12px; border-left:1px solid #CCE9B9; word-break:break-all; white-space:normal; word-wrap:break-word; overflow:hidden } - .ec-ecom-table .od td{background-color:#FFF;} - .ec-ecom-table .ev td{background-color:#F2F8EE;} - .ec-ecom-table .od td.dk{background-color:#EAF1E2;} - .ec-ecom-table .ev td.dk{background-color:#DDE9D0;} - .ec-ecom-table-row-focus td.ec-ecom-table-item, - .ec-ecom-table-row-over td.ec-ecom-table-item, - .ec-ecom-table .ec-ecom-table-row-focus td.dk, - .ec-ecom-table .ec-ecom-table-row-over td.dk - {background-color:#FFFCE2} - /* - .ec-ecom-table-row-over .ev .ec-ecom-table-item, - .ec-ecom-table-row-over .ev td.dk, - .ec-ecom-table-row-over .od .ec-ecom-table-item, - .ec-ecom-table-row-over .od td.dk, - .ec-ecom-table-row-focus .ev .ec-ecom-table-item, - .ec-ecom-table-row-focus .ev td.dk, - .ec-ecom-table-row-focus .od .ec-ecom-table-item, - .ec-ecom-table-row-focus .od td.dk, - .ec-ecom-table-row-focus .ec-ecom-table-item, - .ec-ecom-table-row-over .ec-ecom-table-item {background-color:#FFFCE2} - */ - /*排序*/ - .ec-ecom-table-area .sort, .ec-ecom-table-area .sort-over, .ec-ecom-table-area .sort-focus{ text-align:left; cursor:pointer; background:url("img/table.gif") no-repeat 93% -33px; } - .ec-ecom-table-area .sort-over{ background-color:#F6FFB8; } - .ec-ecom-table-area .sort-up, .ec-ecom-table-area .sort-down{ cursor:pointer; /*text-align:right;*/ background:#F6FFB8 url("img/table.gif") no-repeat 93% -33px; } - .ec-ecom-table-area .sort-up { background-position:93% -63px; } - .ec-ecom-table-area .sort-down { background-position:93% -93px; } - .ec-ecom-table-row .op{text-align:center;border:0 none;border-left:1px solid #9CD167} - /*复选框*/ - .ec-checkbox {background:url("img/cr.gif") 0px 0px no-repeat;width:17px;height:15px} - .ec-checkbox-display {background:url("img/cr.gif") -34px 0px no-repeat;} - .ec-checkbox-over {background:url("img/cr.gif") -17px 0px no-repeat;} - .ec-checkbox-checked {background:url("img/cr.gif") -34px 0px no-repeat} - .ec-checkbox-checked-over {background:url("img/cr.gif") -51px 0px no-repeat} - .ec-checkbox-part {background:url("img/cr.gif") -102px 0px no-repeat} - /*展开按钮(上)*/ - .ec-col-toggler,.ec-col-toggler-o{ width:17px; height:20px; position:absolute; top:2px; right:0; background:#DCEFD1 url("img/table.gif") no-repeat 0px 0px; cursor:pointer; } - .ec-col-toggler-o{background-position:-22px 0px} - /*展开按钮(下)*/ - .ec-v-toggler{ width:15px; background:#DDE9D0; position:absolute; right:0; bottom:0; _right:-1px; cursor:pointer; border-left:1px solid #9CD167; /*border-right:1px solid #9CD167;*/ } - .ec-v-toggler div{ width:9px; height:10px; overflow:hidden; background:url("img/table.gif") no-repeat -8px -22px; position:absolute; right:3px; bottom:50%; _padding-top:50%; cursor:pointer; } - .ec-v-toggler-over{background-color:#EAF1E2} - /*验证*/ - .valid-error td.ec-ecom-table-item{ background-color:pink!important; } - /* *分页 *囧, 有同名的list宏,需转义 */ - .ec-page a, .ec-page b{ margin:0; text-indent:0; display:inline-block; *display:inline; zoom:1; height:20px; line-height:20px; background:url("img/table.gif") repeat-x 0 -150px; border:1px solid #9CD167; padding:0 3px; text-decoration:none; color:#326700; } - .ec-page a:hover{ background-position:0 -176px; } - .ec-page .page-n{ /*width:20px;*/ text-align:center; /*padding:0;*/ padding:0 5px; } - .ec-page b{ background-image:none; color:#666; background-color:#EEE; font-weight:normal; } - .ec-page b.page-n{ background-image:none; background-color:#FFF; color:#000; font-weight:bold; } - .ec-page { color:#326700; margin-top: 10px } - .ec-page em{ font-style:normal; color:#000; padding:0 3px; } - .target-page{ width:25px; } - /* 弹出菜单 */ - .ec-popup{ background-color:#DCEFD1; border:1px solid #9CD167; border-width:1px 1px 0 1px; width:70px; } - .ec-popup-item{ background-color:#DCEFD1;/* width:70px; */ height:25px; line-height:25px; border-bottom:1px solid #9CD167; padding-left: 24px; cursor:pointer; vertical-align:bottom; position:relative; } - .ec-popup-item-over{ background-color:#FFFCE2; } - .ec-popup-item .ec-checkbox{ /*float:left;*/ /*margin:4px 4px 0 4px;*/ position:absolute; top:4px; left:4px; border:0 none; /*text-indent: 14px;*/ } - .cb-ctnr{ background:#DCEFD1 url("img/table.gif") 0 -200px; height:14px; margin:0; border:0 none; width:15px; position:absolute; top:7px; cursor:pointer; } - /* 提示信息显示 */ - .tb-msg{ visibility:hidden; margin: 0 0 4px 0; } - .tb-msg .tb-msg-txt{ background:#FFFCE2; color:#D2691E; font-weight:bold; padding:0 4px; display:inline-block; *display:inline; zoom:1; height:20px; line-height:20px; } - .tb-msg .clo-btn{ font-weight:normal; margin: 0 0 0 14px; cursor:pointer; } - - /* 二次屏蔽的提示框 */ - .ectable-modal-tip {background:#FFF;position:absolute;width:200px;height:50px;border:2px solid #CCC} - .ectable-modal-tip-title {position:absolute;height:20px;line-height:20px;text-indent:5px;margin:0;display:block;top:0;left:0;background:#CCC;width:100%} - .ectable-modal-tip-cont {padding:25px 5px 5px 25px;background:transparent url(img/loading.gif) no-repeat scroll 5px 25px} - - /* 打印 */ - @media screen { .ec-print-table{ border:1px solid #9CD167;border-width:1px; border-collapse:collapse; background-color:#DCEFD1 } - .ec-print-table th, .ec-print-table td{ border:1px solid #9CD167; border-width:0 0 1px 1px; } - .ec-print-table td{ background-color:#FFF; } - } - @media print { body{font-family:"微软雅黑","黑体";font-size:10px;} - .strik-info{color:#000;} - .noprint,.nav{display:none;} - .area-v,.area-w{display:none;} - .area{border:1px solid #ddd;margin-top:6px;background:#fff;} - .mess-query .area-inner{background:none;border:0;} - .mess-query .area {border:0;} - .area h5{border:0;} - .area h5 b{background:none;border:0;color:#000;} - .old td{background:#ddd;} - .ec-print-table {border:1px solid #666;border-width:1px 0 1px 1px;border-collapse:collapse} - .ec-print-table th{padding:2px;text-align:center;border-right:1px solid #666; border-color:#666} - .ec-print-table td{padding:2px 6px;border:1px solid #666;border-width:1px 1px 0 0; border-color:#666} - *{word-wrap:break-word;word-break:break-all;} - } - diff --git a/WebContent/stat/js/ui/table/js/ecomui.table.js b/WebContent/stat/js/ui/table/js/ecomui.table.js deleted file mode 100644 index 5f453f99b..000000000 --- a/WebContent/stat/js/ui/table/js/ecomui.table.js +++ /dev/null @@ -1,570 +0,0 @@ -var ecomui = ecomui || {}; - -// IE 6 背景图片缓存 -try { - document.execCommand("BackgroundImageCache", false, true); -} catch(e){} - -(function() { - var lib = baidu, - core = ecui, - dom = core.dom, - ui = core.ui, - util = core.util, - inherits = util.inherits, - copy = util.copy, - toNumber = util.toNumber, - get = core.get, - query = core.query, - setStyles = lib.dom.setStyles, - getPosition = dom.getPosition, - calcHeightRevise = core.calcHeightRevise, - - DOCUMENT = document, - UI_TABLE = ui.LockedTable, - UI_TABLE_CLASS = UI_TABLE.prototype, - UI_CONTROL = ui.Control, - ECOM_TABLE_CLASS; - - ecomui.Table = ui.EcomTable = function(el, params) { - /* - * 计算表格宽度 - */ - var tbEl = el.getElementsByTagName("table")[0]; - if (!tbEl.style.width) { - var colEls = tbEl.rows[0].cells; - var tbOldWidth = tbEl.offsetWidth; - var tbWidth = 0; - - for (var i = 0, len = colEls.length; i < len; i++) { - var o = colEls[i].style.width; - tbWidth += (o !== undefined) ? - (/px$/.test(o) ? parseInt(o, 10) : tbOldWidth * (parseFloat(o) / 100)) : - 130; - } - tbEl.style.width = Math.max(el.offsetWidth * 0.99, tbWidth) + "px"; - } - - //隐藏待渲染的表格, 在vm里定义visibility=hidden - //渲染表格 - UI_TABLE.call(this, el, params); - - //显示渲染好的表格 - this.getOuter().style.visibility = "visible"; - - //记录表格索引 - this._nTbId = params.tbid; - - //是否有选择整列表按钮 - this._bCustom = params.custom; - - var colToggler, verticalBar, showOpColumn, colCount; - - showOpColumn = params.rightLock; - - //如果有操作列 - if (showOpColumn) { - //初始操作列是展开的 - this._bOpColumnUnfolded = true; - - var base = this.getBase(); - - //记住操作列和前一列 - //TODO 倒数第二列不能作为部件, 因为不是表格不可缺少的 - //在使用时取一下 - //colCount = this._aCol.length - 1; - //this._uOpColumn = this.getCol(colCount); - - //收缩按钮 - var el = DOCUMENT.createElement("div"); - el.className = "ec-col-toggler"; - base.appendChild(el); - colToggler = this._uColToggler - = core.$fastCreate( - UI_CONTROL, - el, - this, - {} - ); - - //竖条 - var el = DOCUMENT.createElement("div"); - el.innerHTML = "
"; - el.className = "ec-v-toggler"; - base.appendChild(el); - verticalBar = this._uVerticalBar - = core.$fastCreate( - UI_CONTROL, - el, - this, - {} - ); - verticalBar.hide(); - - //如果有纵向滚动条, 调整收缩按钮的位置 - //FIXME 此时VScroll总是有的 - var vScroll = this.$getSection("VScroll"); - colToggler.getOuter().style.right = 2 + - ((vScroll && vScroll.isShow()) ? vScroll.getWidth() : 0) + "px"; - //绑定事件 - colToggler.onclick = colTogglerClick; - verticalBar.onclick = vBarClick; - verticalBar.show = vBarShow; - - } - - //浮动表头 - if (params.floatthead) { - var self = this; - self._bFloatThead = true; - lib.event.on(window, "scroll", function() { - floatThead(self); - }); - } - - - }; - - ECOM_TABLE_CLASS = inherits(ui.EcomTable, UI_TABLE); - - /* - * 此处获得操作列 - */ - ECOM_TABLE_CLASS.$init = function () { - UI_TABLE_CLASS.$init.call(this); - if (this._nRightLock) { - this._uOpColumn = this.getCol(this._aCol.length - 1); - } - - //整列表选择按钮 - if(this._bCustom) { - var customBtn = core.get("cbCtnr_" + this._nTbId); - customBtn && initCustomBtn(customBtn, this); - } - }; - - /** - * 展开/收起按钮点击 - * @private - */ - function colTogglerClick() { - //this为按钮 - var table = this.getParent(), - vBar = table.$getSection("VerticalBar"); - - if (table._bOpColumnUnfolded) { - //收起操作列 - foldOpColumn(table); - vBar.show(); - this.alterClass("o"); - } else { - //展开操作列 - unfoldOpColumn(table); - vBar.hide(); - this.alterClass("o", true); - } - } - - /** - * 竖条点击 - * @private - */ - function vBarClick() { - //this 为竖条 - var table = this.getParent(); - - //展开操作列 - unfoldOpColumn(table); - - this.hide(); - } - - /** - * 收起操作列 - * @private - */ - function foldOpColumn(table) { - var tableWidth = table.getWidth(), - tableBodyWidth = table.getBody().offsetWidth; - - table._uOpColumn.hide(); - - //设置倒数第二列的宽度 - var col = table.getCol(table.getCols().length - 2); - col.setSize(col.getWidth() + table._uOpColumn.getWidth()); - - table._bOpColumnUnfolded = false; - }; - - /** - * 展开操作列 - * @private - */ - function unfoldOpColumn(table) { - var prevCol = getSndLastCol(table); - - //恢复倒数第二列恢复原来的宽度 - var col = table.getCol(table.getCols().length - 2); - col.setSize(col.getWidth() - table._uOpColumn.getWidth()); - - table._uOpColumn.show(); - - - table._bOpColumnUnfolded = true; - }; - - /** - * 获得倒数第二列 - * @private - */ - function getSndLastCol(table) { - var colCount = table._aCol.length - 1, - ret; - while (colCount--) { - ret = table.getCol(colCount); - if (ret.isShow()) { - break; - } - } - return ret; - } - - /** - * 展开/收缩操作列时设置表格宽度 - * @private - */ - function setTableWidth(table, tableWidth, tableBodyWidth) { - var oldWidth = table._nOldWidth = table.getWidth(); - if (tableWidth > tableBodyWidth) { - table.setSize(oldWidth + table) - } - } - - /** - * 显示竖条 - * @private - */ - function vBarShow() { - UI_CONTROL.prototype.show.call(this); - setVBarPosition(this); - setVBarHeight(this); - } - - /** - * 设置竖条定位 - * @private - */ - function setVBarPosition(vBar) { - var table = vBar.getParent(), - vBarWidth = vBar.getWidth(), - vs = table.$getSection("VScroll"), - style = table.getBase().style, - contentWidth = table.getWidth() - - (toNumber(style.borderLeftWidth) + toNumber(style.borderRightWidth)); - - vBar.getOuter().style.left = contentWidth - vBarWidth - - ((vs && vs.isShow()) ? vs.getWidth() : 0) - + "px"; - } - - - /** - * 在竖条显示时设置其高度 - * @private - */ - function setVBarHeight(vBar) { - var table = vBar.getParent(), - hs = table.$getSection("HScroll"), - th = table.$getSection("Head"), - hscrValue; - - if (hs && hs.isShow()) {//存在水平滚动条 - hs.setValue(hs.getTotal()); - hscrValue = hs.isShow() ? hs.getHeight() : 0; - } - else { - hscrValue = 0; - } - - //TODO -2 用 sumStyle算边框值 - vBar.setSize(0, table.getHeight() - th.getHeight() - 2 - hscrValue); - var style = vBar.getOuter().style; - style.bottom = hscrValue + "px"; - } - - /** - * 表头随浏览器滚动条锁定 - * @private - */ - function floatThead(t) { - var headEl = t._uHead.getOuter(), - lockedHeadEl = t._uLockedHead.getOuter(), - lockedMainEl = t._uLockedMain.getOuter(); - - if (t._uColToggler) { - var colTogglerEl = t._uColToggler.getOuter(); - } - - var outer = t.getOuter(); - - var scrollTop = DOCUMENT.body.scrollTop || DOCUMENT.documentElement.scrollTop, - pos = getPosition(outer), - top = pos.top + 1, - left = pos.left; - - var headHeight = headEl.offsetHeight + calcHeightRevise(headEl), - tbHeightDelta = t.getHeight() - headHeight, - relativeTop = scrollTop - top; - - var floatStyles = { - position: "absolute", - top: relativeTop + "px", - zIndex: 999 - }; - - if (scrollTop - && relativeTop > 0 - && relativeTop < tbHeightDelta) - { - setStyles(headEl, floatStyles); - setStyles(lockedHeadEl, floatStyles); - setStyles(lockedMainEl, {top: headHeight + "px"}); - - //TODO 此处性能优化 - //ecui 1.1.0 fix - setStyles(lockedHeadEl, {width: lockedHeadEl.getElementsByTagName("table")[0].style.width}); - - if (colTogglerEl) { - setStyles(colTogglerEl, {top: 2 + relativeTop + "px", zIndex: 999}); - } - } - - else { - setStyles(headEl, {top: 0, zIndex:0}); - setStyles(lockedHeadEl, {position: "static", zIndex:0}); - setStyles(lockedMainEl, {top: ""}); - - if (colTogglerEl) { - setStyles(colTogglerEl, {top: "", zIndex:0}); - } - } - }; - - /** - * 初始化整列表选择按钮 - */ - function initCustomBtn(customBtn, table) { - var tbId = table._nTbId; - - var popup = core.get("cbPop_" + tbId), - popupItems = core.query({"parent": popup}), - popupItemsLen = popupItems.length; - - var cbCurList = core.get("cball_" + tbId), - cbWholeList = core.get("cbsall_" + tbId), - cbCurInferiors = cbCurList.getInferiors(); - - DOCUMENT.body.appendChild(popup.getOuter()); - - customBtn.onclick = function() { - var containerOuter = this.getOuter(); - containerPos = getPosition(containerOuter); - - popup.setPosition( - containerPos.left + this.getBodyWidth(), - containerPos.top - ); - - popup.show(); - }; - - cbWholeList.onclick = (function() { - var checked = false; - return function(){ - var i = cbCurInferiors.length, - msg = [ - "已选择整列表, 子项目不能取消选择", - "已取消选择整列表" - ]; - - var msgBox = table.setMsg((!checked) ? msg[0] : msg[1]); - - msgBox.parentNode.parentNode.style.visibility = "visible"; - - var hcbsall = lib.dom.g("hcbsall_" + tbId); - while (i--) { - cbCurInferiors[i].setChecked(!checked); - cbCurList.setEnabled(checked); - cbCurInferiors[i].setEnabled(checked); - hcbsall.value = checked ? 0 : 1; - } - - checked = !checked; - } - })(); - - while (popupItemsLen--) { - popupItems[popupItemsLen].onclick = function() { - var cb = core.query({"parent":this})[0]; - cb.click(); - }; - } - } - - /** - * 改写$resize方法 - */ - ECOM_TABLE_CLASS.$resize = function () { - UI_TABLE_CLASS.$resize.call(this); - - //如果存在竖条并且竖条显示, 重设其高度 - var vBar = this._uVerticalBar; - if (vBar && vBar.isShow()) { - setVBarHeight(vBar); - setVBarPosition(vBar); - } - - //修正浮动表头的位置 - if (this._bFloatThead) { - floatThead(this); - } - }; - - /** - * 找出table中被选中行 - * @public - * - * @return {Array} 被选中行 - */ - ECOM_TABLE_CLASS.getChecked = function() { - var ret = []; - try { - var col = this.getCol(0), - cbs = core.get("cball_" + this._nTbId), - cbs = (cbs instanceof core.ui.Checkbox) ? cbs : core.query({"parent": cbs})[0], - cbs = cbs.getInferiors(), - i = cbs.length; - - while (i--) { - if (cbs[i].isChecked()) { - ret.push(cbs[i].getParent()); - } - } - } catch (e) {} - return ret; - }; - - /** - * 找出table中被选中行个数 - * @public - * - * @return {Number} 被选中行的个数 - */ - ECOM_TABLE_CLASS.getCheckedCount = function() { - return this.getChecked().length; - }; - - /** - * 设置消息 - * @public - * - * @return {HTMLElement} 消息div元素 - */ - ECOM_TABLE_CLASS.setMsg = function(msg) { - var msgBox = lib.dom.g("tbMsg_" + this._nTbId); - dom.setText(msgBox, msg); - return msgBox; - }; -})(); - -/* - * 排序 - */ -var defaultSort = (function() { - // 屏蔽二次点击标志 - var dbClickFlag = false; - - return function() { - if (!dbClickFlag) { - window.sortClick(this.getBase().getAttribute('sort')); - dbClickFlag = true; - } - else { - ecTable.showModal("正在排序, 请稍候..."); - } - } -})(); - -/** - * 为兼容以前版本加的补丁 - */ -var ecTable = { - getChecked: function(table) { - return ecomui.Table.prototype.getChecked.call(table, table); - }, - getCheckedCount: function(table) { - return ecomui.Table.prototype.getCheckedCount.call(table, table); - } -}; - -ecui.getChildren = function(control) { - return ecui.query({parent:control}); -}; - -/** - * 整体遮罩, 用于屏蔽二次点击 - */ -var ecTable = ecTable || {}; - -ecTable.showModalTip = function(text) { - var modalCtrl = baidu.dom.g("ecTableModalTip"); - modalCtrl = modalCtrl && modalCtrl.getControl(); - - // 创建提示信息窗体 - if (!modalCtrl) { - modalCtrl = document.createElement("div"); - modalCtrl.id = "ecTableModalTip" - modalCtrl.className = "ectable-modal-tip"; - modalCtrl.style.visibility = "hidden"; - modalCtrl.innerHTML = [ - '', - '
' - ].join(""); - document.body.appendChild(modalCtrl); - - modalCtrl = ecui.$fastCreate( - ecui.ui.Form, - modalCtrl, - null, - {hide:true} - ); - } - - // 给窗体设置文字并显示 - var contEl = modalCtrl.getBody().getElementsByTagName("div")[0]; - ecui.dom.setText(contEl, text); - modalCtrl.getOuter().style.zIndex = 32768; - - - // 窗体居中 - var viewWidth = baidu.page.getViewWidth(), - viewHeight = baidu.page.getViewHeight(), - width = modalCtrl.getWidth(), - height = modalCtrl.getHeight(); - - baidu.setStyles(modalCtrl.getOuter(), { - position: "absolute", - left: Math.max(viewWidth - width, 0) / 2, - top: Math.max(viewHeight - height, 0) / 2 - }); - - modalCtrl.getOuter().style.visibility = ""; - ecui.mask(0.03); - - // 五秒没反应显示刷新链接 - setTimeout(function() { - contEl.innerHTML = '好像没响应? 请刷新'; - }, 5000); - -}; - diff --git a/WebContent/stat/js/ui/table/js/table.js b/WebContent/stat/js/ui/table/js/table.js deleted file mode 100644 index ac5385c76..000000000 --- a/WebContent/stat/js/ui/table/js/table.js +++ /dev/null @@ -1,322 +0,0 @@ -/** - *@file support_table.js - *@description 支持模块使用ecui实现的列表 - * - * 修改记录 - * 2010.01.07 加入当前页或者整列表的选择(样式) - */ - -/* - * IE 6 背景图片缓存 - */ -try { - document.execCommand("BackgroundImageCache", false, true); -} catch(e){} - -/* - *滚动条装饰器 - */ -ecui.ui.VScroll.prototype.$create = function() { - var me = this, - block = this.$getSection('Block'); - new ecui.ext.TBDecorator(block, 'vsblockdtr'); - ecui.ui.Control.prototype.$create.call(this); -}; - -ecui.ui.HScroll.prototype.$create = function() { - var block = this.$getSection('Block'); - new ecui.ext.LRDecorator(block, 'hsblockdtr'); - ecui.ui.Control.prototype.$create.call(this); -}; - - -function initEcuiTable(table) { - var t = table || ecui.get(table), - vs = t.$getSection('VScroll'), - hs = t.$getSection('HScroll'), - th = t.$getSection('Head'), - cCount = t._aCol.length - 1, - col = t.getCol(cCount), - prevCol = t.getCol(cCount - 1); - - //此时重绘,防止火狐下高度异常 - //t.paint(); - - /* - * 展开/收起按钮 - */ - //TODO 判断是否含有操作列 - if (col.getBase().parentNode != prevCol.getBase().parentNode) { - //收缩按钮 - var ct = ecui.create('Control', { - type: 'ec-col-toggler', - parent: t.getBase() - }), - - //竖条 - h = ecui.create('Control', { - type: 'ec-v-toggler', - parent: t.getBase() - }), - - cw = col.getWidth(), - pw = prevCol.getWidth(), - hscrValue; - - h.getBody().innerHTML = '
' - h.hide(); - h.onclick = function() { - ct.click(); - }; - - ct.onclick = function() { - toggleStatus(this); - vs && vs.paint(); - //col.paint(); - }; - ct.onpaint = function(){ - setHbarHeight(h); - //alert("paint col toggler") - } - - //根据是否有滚动条设置按钮位置 - if (vs && vs.isShow()) { - ct.getBase().style.right = vs.getWidth() + "px"; - } - /* - * 设置竖条高度 - */ - var setHbarHeight = function(hbar) { - if (hs) {//存在水平滚动条 - hs.setValue(hs.getTotal()); - hscrValue = hs.isShow() ? hs.getHeight() : 0; - } - else { - hscrValue = 0; - } - hbar.setSize(undefined, t.getHeight() - th.getHeight() - 2 - hscrValue); - var style = hbar.getOuter().style; - if (vs && vs.isShow()) style.right = vs.getWidth() + "px"; - style.bottom = hscrValue + "px"; - } - - /* - * 点击'收起按钮'的回调函数 - */ - var toggleStatus = function(ct) { - - //hack:避免第一次隐藏列后对不齐 - prevCol.setSize(pw); - - if (col.isShow()) { - _autoSize(t, prevCol, pw); - ct.alterClass('o'); - col.hide(); - setHbarHeight(h); - h.show(); - } else { - prevCol.setSize(pw); - ct.alterClass('o', true); - //console.log(hscrValue); - col.show(); - h.hide(); - hs && hs.setValue(hs.getTotal()); - } - - col.paint(); - }; - - /* - * 表格列自适应宽度 - */ - var _autoSize = function(t, c, ow) { - var tw = t.getWidth(), - tcw = t.getBody().offsetWidth; - if (tw > tcw) { - c.setSize(tw - tcw + ow); - } - }; - } - - /* - * 垂直滚动条高度 - - if (vs) { - _setVSHeight = function(vs) { - vs.setSize(undefined, vs.getHeight() - th.getHeight()); - vs.getBase().style.top = ""; - vs.getBase().style.bottom = vs.getWidth() + "px"; - } - vs.onpaint = function() { - this.$paint(); - _setVSHeight(this); - document.body.className = document.body.className; - return false; - } - _setVSHeight(vs); - } - */ - - /* - * 排序-记录水平位置 - - var ectable_xpos = baidu.cookie.getRaw('ectable_xpos'); - if (ectable_xpos) { - hs.setValue(ectable_xpos); - baidu.cookie.remove('ectable_xpos'); - } - */ - - /* - * 排序 - */ - var defaultSort = function() { - window.sortClick(this.getBase().getAttribute('sort')); - baidu.cookie.setRaw('ectable_xpos',hs.getValue()); - }; - - for (var i = 0, cCount = t._aCol.length; i < cCount; i++) { - var col = t.getCol(i); - if (col.getBase().className.match(/\s*sort\s*/)) { - col.onclick = defaultSort; - } - } - - //hack for ie 8 - //document.body.className = document.body.className; - - - /* - * custom checkbox处理 - */ - - var popupContainer = ecui.query({"parent":t.getCol(0)})[0]; - - if (popupContainer) { - var ctrlIdx = popupContainer.getBase().id - .replace(/^s+|s+$/,'') - .match(/cbCtnr_([0-9a-zA-Z_]+)/)[1], - //弹出菜单容器和弹出菜单 - popup = document.getElementById('cbPop_' + ctrlIdx).getControl(), - popupItems = ecui.query({"parent":popup}), - popupItemsLen = popupItems.length, - - //checkbox 控件 - cbCurList = document.getElementById("cbCurList").getControl(), - cbWholeList = document.getElementById("cbWholeList").getControl(), - cbCurInferiors = cbCurList.getInferiors(); - //msgBox = document.getElementById('tbMsg_' + ctrlIdx); - - - popupContainer.onclick = function() { - var containerOuter = this.getOuter(); - containerPos = ecui.dom.getPosition(containerOuter); - - popup.setPosition(containerPos.left + this.getBodyWidth(), containerPos.top); - - popup.show(); - }; - - cbWholeList.onclick = (function() { - var checked = false; - return function(){ - //console.log("xx"); - var i = cbCurInferiors.length, - msg = [ - "已选择整列表, 子项目不能取消选择", - "已取消选择整列表" - ]; - - var msgBox = ecTable.setMsg(t, (!checked) ? msg[0] : msg[1]); - msgBox.style.visibility = "visible"; - - while (i--) { - cbCurInferiors[i].setChecked(!checked); - cbCurList.setEnabled(checked); - cbCurInferiors[i].setEnabled(checked); - } - - checked = !checked; - } - })(); - - while (popupItemsLen--) { - popupItems[popupItemsLen].onclick = function() { - var cb = ecui.query({"parent":this})[0]; - cb.click(); - }; - } - - } -} -var ecTable = { - /** - * 给表格的消息框设置 - * @param {ecTable} table - * @param {String} msg - * @return {String} 消息框 - */ - setMsg: function(table, msg) { - var msgBox = table.getBase(), - first = ecui.dom.first; - - do { - msgBox = msgBox.previousSibling; - } while (msgBox.nodeType != 1) - - first(first(msgBox)).innerHTML = msg; - return msgBox; - }, - - /** - *找出table中被选中条目 - *@param {ecTable} table - *@return {Array} 被选中行 - */ - getChecked: function(table){ - var col = table.getCol(0), - cbs = ecui.query({"parent":col})[0], - cbs = (cbs instanceof ecui.ui.Checkbox) ? cbs : ecui.query({"parent": cbs})[0], - cbs = cbs.getInferiors(), - i = cbs.length, - ret = []; - - while (i--) { - if(cbs[i].isChecked()){ - ret.push(cbs[i].getParent()); - } - } - - return ret; - }, - /** - *获得table中有选中条目个数 - *@param {EcTable} table - *@return {Number} 选中条目个数 - */ - getCheckedCount: function(table) { - return ecTable.getChecked(table).length; - }, - - /** - * 获得当前页面所有table - * @return 包含所有table的数组 - */ - getTables: function() { - return ecui.query({"type": ecui.ui.Table}); - }, - - /** - *初始化当前页所有列表 - */ - init: function() { - var tables = ecTable.getTables(), - len = tables.length; - - while (len--) { - initEcuiTable(tables[len]); - } - } -}; - -ecui.dom.ready(ecTable.init); diff --git a/WebContent/stat/js/ui/wick/js/wick.js b/WebContent/stat/js/ui/wick/js/wick.js deleted file mode 100644 index 26f300d83..000000000 --- a/WebContent/stat/js/ui/wick/js/wick.js +++ /dev/null @@ -1,481 +0,0 @@ -function freezeEvent(e) { - if (e.preventDefault) e.preventDefault(); - e.returnValue = false; - e.cancelBubble = true; - if (e.stopPropagation) e.stopPropagation(); - return false; -}//freezeEvent - -function isWithinNode(e,i,c,t,obj) { - answer = false; - te = e; - while(te && !answer) { - if ((te.id && (te.id == i)) || (te.className && (te.className == i+"Class")) - || (!t && c && te.className && (te.className == c)) - || (!t && c && te.className && (te.className.indexOf(c) != -1)) - || (t && te.tagName && (te.tagName.toLowerCase() == t)) - || (obj && (te == obj)) - ) { - answer = te; - } else { - te = te.parentNode; - } - } - return te; -}//isWithinNode - -function getEvent(event) { - return (event ? event : window.event); -}//getEvent() - -function getEventElement(e) { - return (e.srcElement ? e.srcElement: (e.target ? e.target : e.currentTarget)); -}//getEventElement() - -function findElementPosX(obj) { - curleft = 0; - if (obj.offsetParent) { - while (obj.offsetParent) { - curleft += obj.offsetLeft; - obj = obj.offsetParent; - } - }//if offsetParent exists - else if (obj.x) - curleft += obj.x - return curleft; -}//findElementPosX - -function findElementPosY(obj) { - curtop = 0; - if (obj.offsetParent) { - while (obj.offsetParent) { - curtop += obj.offsetTop; - obj = obj.offsetParent; - } - }//if offsetParent exists - else if (obj.y) - curtop += obj.y - return curtop; -}//findElementPosY - -/* end dhtml building blocks */ - -function handleKeyPress(event) { - e = getEvent(event); - eL = getEventElement(e); - - upEl = isWithinNode(eL,null,"wickEnabled",null,null); - - kc = e["keyCode"]; - - if (siw && ((kc == 13) || (kc == 9))) { - siw.selectingSomething = true; - if (siw.isSafari) siw.inputBox.blur(); //hack to "wake up" safari - siw.inputBox.focus(); - siw.inputBox.value = siw.inputBox.value.replace(/[ \r\n\t\f\s]+$/gi,' '); - hideSmartInputFloater(); - } else if (upEl && (kc != 38) && (kc != 40) && (kc != 37) && (kc != 39) && (kc != 13) && (kc != 27)) { - if (!siw || (siw && !siw.selectingSomething)) { - processSmartInput(upEl); - } - } else if (siw && siw.inputBox) { - siw.inputBox.focus(); //kinda part of the hack. - } - -}//handleKeyPress() - - -function handleKeyDown(event) { - e = getEvent(event); - eL = getEventElement(e); - - if (siw && (kc = e["keyCode"])) { - if (kc == 40) { - siw.selectingSomething = true; - freezeEvent(e); - if (siw.isGecko) siw.inputBox.blur(); /* Gecko hack */ - selectNextSmartInputMatchItem(); - } else if (kc == 38) { - siw.selectingSomething = true; - freezeEvent(e); - if (siw.isGecko) siw.inputBox.blur(); - selectPreviousSmartInputMatchItem(); - } else if ((kc == 13) || (kc == 9)) { - siw.selectingSomething = true; - activateCurrentSmartInputMatch(); - freezeEvent(e); - } else if (kc == 27) { - hideSmartInputFloater(); - freezeEvent(e); - } else { - siw.selectingSomething = false; - } - } - -}//handleKeyDown() - -function handleFocus(event) { - e = getEvent(event); - eL = getEventElement(e); - if (focEl = isWithinNode(eL,null,"wickEnabled",null,null)) { - if (!siw || (siw && !siw.selectingSomething)) processSmartInput(focEl); - } -}//handleFocus() - -function handleBlur(event) { - e = getEvent(event); - eL = getEventElement(e); - if (blurEl = isWithinNode(eL,null,"wickEnabled",null,null)) { - if (siw && !siw.selectingSomething) hideSmartInputFloater(); - } -}//handleBlur() - -function handleClick(event) { - e2 = getEvent(event); - eL2 = getEventElement(e2); - if (siw && siw.selectingSomething) { - selectFromMouseClick(); - } -}//handleClick() - -function handleMouseOver(event) { - e = getEvent(event); - eL = getEventElement(e); - if (siw && (mEl = isWithinNode(eL,null,"matchedSmartInputItem",null,null))) { - siw.selectingSomething = true; - selectFromMouseOver(mEl); - } else if (isWithinNode(eL,null,"siwCredit",null,null)) { - siw.selectingSomething = true; - }else if (siw) { - siw.selectingSomething = false; - } -}//handleMouseOver - -function showSmartInputFloater() { -if (!siw.floater.style.display || (siw.floater.style.display=="none")) { - if (!siw.customFloater) { - x = findElementPosX(siw.inputBox); - y = findElementPosY(siw.inputBox) + siw.inputBox.offsetHeight; - //hack: browser-specific adjustments. - if (!siw.isGecko && !siw.isWinIE) x += 8; - if (!siw.isGecko && !siw.isWinIE) y += 10; - siw.floater.style.left = x; - siw.floater.style.top = y; - } else { - //you may - //do additional things for your custom floater - //beyond setting display and visibility - } - siw.floater.style.display="block"; - siw.floater.style.visibility="visible"; -} -}//showSmartInputFloater() - -function hideSmartInputFloater() { - if (siw) { - siw.floater.style.display="none"; - siw.floater.style.visibility="hidden"; - siw = null; - }//siw exists -}//hideSmartInputFloater - -function processSmartInput(inputBox) { - if (!siw) siw = new smartInputWindow(); - siw.inputBox = inputBox; - - classData = inputBox.className.split(" "); - siwDirectives = null; - for (i=0;(!siwDirectives && classData[i]);i++) { - if (classData[i].indexOf("wickEnabled") != -1) - siwDirectives = classData[i]; - } - - if (siwDirectives && (siwDirectives.indexOf(":") != -1)) { - siw.customFloater = true; - newFloaterId = siwDirectives.split(":")[1]; - siw.floater = document.getElementById(newFloaterId); - siw.floaterContent = siw.floater.getElementsByTagName("div")[0]; - } - - - setSmartInputData(); - if (siw.matchCollection && (siw.matchCollection.length > 0)) selectSmartInputMatchItem(0); - var content = content || null; - content = getSmartInputBoxContent(); - if (content) { - modifySmartInputBoxContent(content); - showSmartInputFloater(); - } else { - hideSmartInputFloater(); - } -}//processSmartInput() - -function smartInputMatch(cleanValue, value) { - this.cleanValue = cleanValue; - this.value = value; - this.isSelected = false; -}//smartInputMatch - -function simplify(s) { - return s.toLowerCase().replace(/^[ \s\f\t\n\r]+/,'').replace(/[ \s\f\t\n\r]+$/,''); -//.replace(/[?,?,?,?,\u00E9,\u00E8,\u00EA,\u00EB]/gi,"e").replace(/[?,?,\u00E0,\u00E2]/gi,"a"). -}//simplify - -function getUserInputToMatch(s) { - a = s; - fields = s.split(","); - if (fields.length > 0) a = fields[fields.length - 1]; - return a; -}//getUserInputToMatch - -function getUserInputBase() { - s = siw.inputBox.value; - a = s; - if ((lastComma = s.lastIndexOf(",")) != -1) { - a = a.replace(/^(.*\,[ \r\n\t\f\s]*).*$/i,'$1'); - } - else { - a = ""; - } - return a; -}//getUserInputBase() - -function runMatchingLogic(userInput, standalone) { - userInput = simplify(userInput); - uifc = userInput.charAt(0).toLowerCase(); - if (uifc == '"') uifc = (n = userInput.charAt(1)) ? n.toLowerCase() : "z"; - if (standalone) userInput = uifc; - if (siw) siw.matchCollection = new Array(); - pointerToCollectionToUse = collection; - if (siw && siw.revisedCollection && (siw.revisedCollection.length > 0) && siw.lastUserInput && (userInput.indexOf(siw.lastUserInput) == 0)) { - pointerToCollectionToUse = siw.revisedCollection; - } else if (collectionIndex[userInput] && (collectionIndex[userInput].length > 0)) { - pointerToCollectionToUse = collectionIndex[userInput]; - } else if (collectionIndex[uifc] && (collectionIndex[uifc].length > 0)) { - pointerToCollectionToUse = collectionIndex[uifc]; - } else if (siw && (userInput.length == 1) && (!collectionIndex[uifc])) { - siw.buildIndex = true; - } else if (siw) { - siw.buildIndex = false; - } - - tempCollection = new Array(); - - re1m = new RegExp("^([ \"\>\<\-]*)("+userInput+")","i"); - re2m = new RegExp("([ \"\>\<\-]+)("+userInput+")","i"); - re1 = new RegExp("^([ \"\}\{\-]*)("+userInput+")","gi"); - re2 = new RegExp("([ \"\}\{\-]+)("+userInput+")","gi"); - - for (i=0,j=0;(i/gi,'\\}').replace(/\< ?/gi,'\\{'); - re = new RegExp("(" + userInput + ")","i"); - if (displayMatches) { - siw.matchCollection[j] = new smartInputMatch(entry, mEntry.replace(/\>/gi,'}').replace(/\< ?/gi,'{').replace(re,"$1")); - } - tempCollection[j] = entry; - j++; - } else if (mEntry.match(re1m) || mEntry.match(re2m)) { - if (!standalone && displayMatches) { - siw.matchCollection[j] = new smartInputMatch(entry, mEntry.replace(/\>/gi,'}').replace(/\$2").replace(re2,"$1$2")); - } - tempCollection[j] = entry; - j++; - } - }//loop thru collection - if (siw) { - siw.lastUserInput = userInput; - siw.revisedCollection = tempCollection.join(",").split(","); - collectionIndex[userInput] = tempCollection.join(",").split(","); - } - if (standalone || siw.buildIndex) { - collectionIndex[uifc] = tempCollection.join(",").split(","); - if (siw) siw.buildIndex = false; - } -}//runMatchingLogic - -function setSmartInputData() { - if (siw) { - orgUserInput = siw.inputBox.value; - orgUserInput = getUserInputToMatch(orgUserInput); - userInput = orgUserInput.toLowerCase().replace(/[\r\n\t\f\s]+/gi,' ').replace(/^ +/gi,'').replace(/ +$/gi,'').replace(/ +/gi,' ').replace(/\\/gi,'').replace(/\[/gi,'').replace(/\(/gi,'').replace(/\./gi,'\.').replace(/\?/gi,''); - if (userInput && (userInput != "") && (userInput != '"')) { - runMatchingLogic(userInput); - }//if userinput not blank and is meaningful - else { - siw.matchCollection = null; - } - }//siw exists ... uhmkaaayyyyy -}//setSmartInputData - -function getSmartInputBoxContent() { - a = null; - if (siw && siw.matchCollection && (siw.matchCollection.length > 0)) { - a = ''; - for (i = 0;i < siw.matchCollection.length; i++) { - selectedString = siw.matchCollection[i].isSelected ? ' selectedSmartInputItem' : ''; - a += '

' + siw.matchCollection[i].value.replace(/\{ */gi,"<").replace(/\} */gi,">") + '

'; - }// - }//siw exists - return a; -}//getSmartInputBoxContent - -function modifySmartInputBoxContent(content) { - //todo: remove credits 'cuz no one gives a shit ;] - done - siw.floaterContent.innerHTML = '
' + content + (siw.showCredit ? ('

Powered By: Chris Holland

') : '') +'
'; - siw.matchListDisplay = document.getElementById("smartInputResults"); -}//modifySmartInputBoxContent() - -function selectFromMouseOver(o) { - currentIndex = getCurrentlySelectedSmartInputItem(); - if (currentIndex != null) deSelectSmartInputMatchItem(currentIndex); - newIndex = getIndexFromElement(o); - selectSmartInputMatchItem(newIndex); - modifySmartInputBoxContent(getSmartInputBoxContent()); -}//selectFromMouseOver - -function selectFromMouseClick() { - activateCurrentSmartInputMatch(); - siw.inputBox.focus(); - hideSmartInputFloater(); -}//selectFromMouseClick - -function getIndexFromElement(o) { - index = 0; - while(o = o.previousSibling) { - index++; - }// - return index; -}//getIndexFromElement - -function getCurrentlySelectedSmartInputItem() { - answer = null; - for (i = 0; ((i < siw.matchCollection.length) && !answer) ; i++) { - if (siw.matchCollection[i].isSelected) - answer = i; - }// - return answer; -}//getCurrentlySelectedSmartInputItem - -function selectSmartInputMatchItem(index) { - siw.matchCollection[index].isSelected = true; -}//selectSmartInputMatchItem() - -function deSelectSmartInputMatchItem(index) { - siw.matchCollection[index].isSelected = false; -}//deSelectSmartInputMatchItem() - -function selectNextSmartInputMatchItem() { - currentIndex = getCurrentlySelectedSmartInputItem(); - if (currentIndex != null) { - deSelectSmartInputMatchItem(currentIndex); - if ((currentIndex + 1) < siw.matchCollection.length) - selectSmartInputMatchItem(currentIndex + 1); - else - selectSmartInputMatchItem(0); - } else { - selectSmartInputMatchItem(0); - } - modifySmartInputBoxContent(getSmartInputBoxContent()); -}//selectNextSmartInputMatchItem - -function selectPreviousSmartInputMatchItem() { - currentIndex = getCurrentlySelectedSmartInputItem(); - if (currentIndex != null) { - deSelectSmartInputMatchItem(currentIndex); - if ((currentIndex - 1) >= 0) - selectSmartInputMatchItem(currentIndex - 1); - else - selectSmartInputMatchItem(siw.matchCollection.length - 1); - } else { - selectSmartInputMatchItem(siw.matchCollection.length - 1); - } - modifySmartInputBoxContent(getSmartInputBoxContent()); -}//selectPreviousSmartInputMatchItem - -function activateCurrentSmartInputMatch() { - baseValue = getUserInputBase(); - if ((selIndex = getCurrentlySelectedSmartInputItem()) != null) { - addedValue = siw.matchCollection[selIndex].cleanValue; - theString = (baseValue ? baseValue : "") + addedValue + ", "; - siw.inputBox.value = theString; - runMatchingLogic(addedValue, true); - } -}//activateCurrentSmartInputMatch - -function smartInputWindow () { - this.customFloater = false; - this.floater = document.getElementById("smartInputFloater"); - this.floaterContent = document.getElementById("smartInputFloaterContent"); - this.selectedSmartInputItem = null; - this.MAX_MATCHES = 15; - this.isGecko = (navigator.userAgent.indexOf("Gecko/200") != -1); - this.isSafari = (navigator.userAgent.indexOf("Safari") != -1); - this.isWinIE = ((navigator.userAgent.indexOf("Win") != -1 ) && (navigator.userAgent.indexOf("MSIE") != -1 )); - this.showCredit = false; -}//smartInputWindow Object - -function registerSmartInputListeners() { - inputs = document.getElementsByTagName("input"); - texts = document.getElementsByTagName("textarea"); - allinputs = new Array(); - z = 0; - y = 0; - while(inputs[z]) { - allinputs[z] = inputs[z]; - z++; - }// - while(texts[y]) { - allinputs[z] = texts[y]; - z++; - y++; - }// - - for (i=0; i < allinputs.length;i++) { - if ((c = allinputs[i].className) && (c == "wickEnabled")) { - allinputs[i].setAttribute("autocomplete","OFF"); - allinputs[i].onfocus = handleFocus; - allinputs[i].onblur = handleBlur; - allinputs[i].onkeydown = handleKeyDown; - allinputs[i].onkeyup = handleKeyPress; - } - }//loop thru inputs - }//registerSmartInputListeners - - siw = null; - - if (document.addEventListener) { - document.addEventListener("keydown", handleKeyDown, false); - document.addEventListener("keyup", handleKeyPress, false); - document.addEventListener("mouseup", handleClick, false); - document.addEventListener("mouseover", handleMouseOver, false); - } else { - document.onkeydown = handleKeyDown; - document.onkeyup = handleKeyPress; - document.onmouseup = handleClick; - document.onmouseover = handleMouseOver; - } - - registerSmartInputListeners(); - - document.write ( - '") - .append("") - .append("") - .append("") - .append("") - .append(""); - if (p.getParameterList() != null || p.getParameterList().size() > 0) { - getParameterListHTMLSub(html, p.getParameterList(), (short)(level + 1)); - } - } - - } - - /** - * level 1: level 2:--- level 3:------ ... - * - * @param level started from 1 - * @return - */ - private String levelMark(short level) { - StringBuilder sb = new StringBuilder(); - for (short i = 1; i < level; i++) { - sb.append("---"); - } - return sb.toString(); - } - - public String getRequestUrlRel() { - String url = this.requestUrl; - if (url == null || url.isEmpty()) { - return "xxxxxxxxxxxxxxxxEMPTY URLxxxxxxxxxxxxxxxxx"; - } - if (url.contains("https://")) { - url = url.substring(url.indexOf("/", 7)); - } else if (url.contains("http://")) { - url = url.substring(url.indexOf("/", 8)); - } - return url; - } - -} diff --git a/src/com/taobao/rigel/rap/project/bo/ActionComparator.java b/src/com/taobao/rigel/rap/project/bo/ActionComparator.java deleted file mode 100644 index 67c1b342d..000000000 --- a/src/com/taobao/rigel/rap/project/bo/ActionComparator.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -import java.util.Comparator; - -public class ActionComparator implements Comparator{ - - @Override - public int compare(Action o1, Action o2) { - Action l = (Action) o1; - Action r = (Action) o2; - return l.getId() < r.getId() ? 0 : 1; - } - -} diff --git a/src/com/taobao/rigel/rap/project/bo/CheckInComparator.java b/src/com/taobao/rigel/rap/project/bo/CheckInComparator.java deleted file mode 100644 index 0964f530c..000000000 --- a/src/com/taobao/rigel/rap/project/bo/CheckInComparator.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -import java.util.Comparator; - -import com.taobao.rigel.rap.workspace.bo.CheckIn; - -public class CheckInComparator implements Comparator{ - - @Override - public int compare(CheckIn o1, CheckIn o2) { - return o1.getId() > o2.getId() ? -1 : 1; - } - -} diff --git a/src/com/taobao/rigel/rap/project/bo/Module.java b/src/com/taobao/rigel/rap/project/bo/Module.java deleted file mode 100644 index 199d72e97..000000000 --- a/src/com/taobao/rigel/rap/project/bo/Module.java +++ /dev/null @@ -1,136 +0,0 @@ -package com.taobao.rigel.rap.project.bo; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import com.taobao.rigel.rap.common.StringUtils; - -public class Module implements java.io.Serializable { - - /** - * - */ - private static final long serialVersionUID = 1L; - - private int id; - private int projectId; - private String name; - private String introduction; - - public int getId() { - return this.id; - } - - public void setId(int id) { - this.id = id; - } - - public int getProjectId() { - return this.projectId; - } - - public void setProjectId(int projectId) { - this.projectId = projectId; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - public String getIntroduction() { - return this.introduction; - } - - public void setIntroduction(String introduction) { - this.introduction = (introduction == null ? "" : introduction); - } - - private Project project; - - public Project getProject() { - return this.project; - } - - public void setProject(Project project) { - this.project = project; - } - - public void addPage(Page page) { - getPageList().add(page); - page.setModule(this); - } - - private Set pageList = new HashSet(); - - public Set getPageList() { - return this.pageList; - } - - public List getPageListOrdered() { - Set pageList = getPageList(); - List pageListOrdered = new ArrayList(); - pageListOrdered.addAll(pageList); - Collections.sort(pageListOrdered, new PageComparator()); - return pageListOrdered; - } - - public void setPageList(Set pageList) { - this.pageList = pageList; - } - - public void update(Module module) { - setIntroduction(module.getIntroduction()); - setName(module.getName()); - } - - public String toString() { - - StringBuilder stringBuilder = new StringBuilder(); - - stringBuilder.append("{\"id\":" + getId() + ","); - stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); - stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\","); - stringBuilder.append("\"pageList\":"); - - stringBuilder.append("["); - Iterator iterator = getPageListOrdered().iterator(); - while(iterator.hasNext()) { - stringBuilder.append(iterator.next()); - if (iterator.hasNext()) { - stringBuilder.append(","); - } - } - stringBuilder.append("]}"); - - return stringBuilder.toString(); - } - - public String toString(Project.toStringType type) { - - StringBuilder stringBuilder = new StringBuilder(); - - stringBuilder.append("{\"id\":" + getId() + ","); - stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); - stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\","); - stringBuilder.append("\"pageList\":"); - - stringBuilder.append("["); - Iterator iterator = getPageListOrdered().iterator(); - while(iterator.hasNext()) { - stringBuilder.append(iterator.next().toString(type)); - if (iterator.hasNext()) { - stringBuilder.append(","); - } - } - stringBuilder.append("]}"); - - return stringBuilder.toString(); - } -} diff --git a/src/com/taobao/rigel/rap/project/bo/ModuleComparator.java b/src/com/taobao/rigel/rap/project/bo/ModuleComparator.java deleted file mode 100644 index abba982f7..000000000 --- a/src/com/taobao/rigel/rap/project/bo/ModuleComparator.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -import java.util.Comparator; - -public class ModuleComparator implements Comparator{ - - @Override - public int compare(Module o1, Module o2) { - Module l = (Module) o1; - Module r = (Module) o2; - return l.getId() < r.getId() ? 0 : 1; - } - -} diff --git a/src/com/taobao/rigel/rap/project/bo/ObjectItem.java b/src/com/taobao/rigel/rap/project/bo/ObjectItem.java deleted file mode 100644 index c192cc860..000000000 --- a/src/com/taobao/rigel/rap/project/bo/ObjectItem.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -public class ObjectItem implements java.io.Serializable { - - private static final long serialVersionUID = 1L; - - public String className; - - public String getClassName() { - return className; - } - - public void setClassName(String className) { - this.className = className; - } - - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } -} diff --git a/src/com/taobao/rigel/rap/project/bo/Page.java b/src/com/taobao/rigel/rap/project/bo/Page.java deleted file mode 100644 index 5c46216cd..000000000 --- a/src/com/taobao/rigel/rap/project/bo/Page.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import com.taobao.rigel.rap.common.StringUtils; - -public class Page implements java.io.Serializable { - - private static final long serialVersionUID = 1L; - - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - private String introduction; - - public String getIntroduction() { - return introduction; - } - - public void setIntroduction(String introduction) { - this.introduction = (introduction == null ? "" : introduction); - } - - private Module module; - - public Module getModule() { - return module; - } - - public void setModule(Module module) { - this.module = module; - } - - private Set actionList = new HashSet(); - - public Set getActionList() { - return actionList; - } - - public List getActionListOrdered() { - Set actionList = getActionList(); - List actionListOrdered = new ArrayList(); - actionListOrdered.addAll(actionList); - Collections.sort(actionListOrdered, new ActionComparator()); - return actionListOrdered; - } - - - public void setActionList(Set actionList) { - this.actionList = actionList; - } - - private String template; - - public String getTemplate() { - return template; - } - - public void setTemplate(String template) { - this.template = template; - } - - public void addAction(Action action) { - getActionList().add(action); - //action.getPageList().add(this); - } - - public void update(Page page) { - setIntroduction(page.getIntroduction()); - setName(page.getName()); - setTemplate(page.getTemplate()); - } - - public String toString() { - StringBuilder stringBuilder = new StringBuilder(); - - stringBuilder.append("{\"id\":" + getId() + ","); - stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); - stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\","); - stringBuilder.append("\"actionList\":"); - - stringBuilder.append("["); - Iterator iterator = getActionListOrdered().iterator(); - while(iterator.hasNext()) { - stringBuilder.append(iterator.next()); - if (iterator.hasNext()) { - stringBuilder.append(","); - } - } - stringBuilder.append("]}"); - - return stringBuilder.toString(); - } - - public String toString(Project.toStringType type) { - StringBuilder stringBuilder = new StringBuilder(); - - stringBuilder.append("{\"id\":" + getId() + ","); - stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); - stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\""); - if (type == Project.toStringType.TO_PAGE) { - stringBuilder.append("}"); - } else { - stringBuilder.append(",\"actionList\":"); - stringBuilder.append("["); - Iterator iterator = getActionListOrdered().iterator(); - while(iterator.hasNext()) { - stringBuilder.append(iterator.next()); - if (iterator.hasNext()) { - stringBuilder.append(","); - } - } - stringBuilder.append("]}"); - } - return stringBuilder.toString(); - } -} diff --git a/src/com/taobao/rigel/rap/project/bo/PageComparator.java b/src/com/taobao/rigel/rap/project/bo/PageComparator.java deleted file mode 100644 index 7de627f9d..000000000 --- a/src/com/taobao/rigel/rap/project/bo/PageComparator.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -import java.util.Comparator; - -public class PageComparator implements Comparator{ - - @Override - public int compare(Page o1, Page o2) { - Page l = (Page) o1; - Page r = (Page) o2; - return l.getId() < r.getId() ? 0 : 1; - } - -} diff --git a/src/com/taobao/rigel/rap/project/bo/Parameter.java b/src/com/taobao/rigel/rap/project/bo/Parameter.java deleted file mode 100644 index 7c3bfc19b..000000000 --- a/src/com/taobao/rigel/rap/project/bo/Parameter.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import com.taobao.rigel.rap.common.StringUtils; - -public class Parameter implements java.io.Serializable { - - private static final long serialVersionUID = 1L; - - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - private String mockData; - - public String getMockData() { - return mockData; - } - - public void setMockData(String mockData) { - this.mockData = mockData; - } - - /** - * temporary property - */ - private String mockDataTEMP; - - public String getMockDataTEMP() { - return mockDataTEMP; - } - - public void setMockDataTEMP(String mockDataTEMP) { - this.mockDataTEMP = mockDataTEMP; - } - - private String name; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = (name == null ? "" : name); - } - - private String identifier; - - public String getIdentifier() { - return identifier; - } - - public String getMockIdentifier() { - String rv = ""; - if (identifier == null || identifier.isEmpty()) { - return "emptyIdentifier"; - } - - rv = identifier; - if (rv != null && !rv.isEmpty()) { - int index = rv.indexOf("|"); - if (index > -1) { - rv = rv.substring(0, index); - } - } - return "\"" + rv + "\""; - } - - public String getMockJSIdentifier() { - String rv = ""; - if (identifier == null || identifier.isEmpty()) { - return "emptyIdentifier"; - } - rv = identifier; - return "\"" + rv + "\""; - } - - public void setIdentifier(String identifier) { - this.identifier = (identifier == null ? "" : identifier); - } - - private String dataType; - - public String getDataType() { - return dataType; - } - - public void setDataType(String dataType) { - this.dataType = (dataType == null ? "" : dataType); - } - - private String remark; - - public String getRemark() { - return (remark == null ? "" : remark); - } - - public void setRemark(String remark) { - this.remark = remark; - } - - private Set actionRequestList = new HashSet(); - - public Set getActionRequestList() { - return actionRequestList; - } - - public void setActionRequestList(Set actionRequestList) { - this.actionRequestList = actionRequestList; - } - - private Set actionResponseList = new HashSet(); - - public Set getActionResponseList() { - return actionResponseList; - } - - public void setActionResponseList(Set actionResponseList) { - this.actionResponseList = actionResponseList; - } - - private String validator = ""; - - public String getValidator() { - return validator; - } - - public void setValidator(String validator) { - this.validator = validator; - } - - private Set parameterList = new HashSet(); - - public Set getParameterList() { - return parameterList; - } - - public void setParameterList(Set parameterList) { - this.parameterList = parameterList; - } - - public void update(Parameter parameter) { - setDataType(parameter.getDataType()); - setIdentifier(parameter.getIdentifier()); - setName(parameter.getName()); - setRemark(parameter.getRemark()); - setValidator(parameter.getValidator()); - } - - public List getParameterListOrdered() { - Set parameterList = getParameterList(); - List parameterListOrdered = new ArrayList(); - parameterListOrdered.addAll(parameterList); - Collections.sort(parameterListOrdered, new ParameterComparator()); - return parameterListOrdered; - } - - private Set complexParamerterList = new HashSet(); - - public Set getComplexParameterList() { - return complexParamerterList; - } - - public void setComplexParameterList(Set complexParameterList) { - this.complexParamerterList = complexParameterList; - } - - public void addChild(Parameter parameter) { - getParameterList().add(parameter); - parameter.getComplexParameterList().add(this); - } - - public String toString() { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\"id\":" + getId() + ","); - stringBuilder.append("\"identifier\":\"" - + StringUtils.escapeInJ(getIdentifier()) + "\","); - stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) - + "\","); - stringBuilder.append("\"remark\":\"" - + StringUtils.escapeInJ(getRemark()) + "\","); - stringBuilder.append("\"parameterList\":"); - stringBuilder.append("["); - Iterator iterator = getParameterListOrdered().iterator(); - while (iterator.hasNext()) { - stringBuilder.append(iterator.next()); - if (iterator.hasNext()) { - stringBuilder.append(","); - } - } - stringBuilder.append("],"); - stringBuilder.append("\"validator\":\"" - + StringUtils.escapeInJ(getValidator()) + "\","); - stringBuilder.append("\"dataType\":\"" - + StringUtils.escapeInJ(getDataType()) + "\"}"); - return stringBuilder.toString(); - } - -} diff --git a/src/com/taobao/rigel/rap/project/bo/ParameterComparator.java b/src/com/taobao/rigel/rap/project/bo/ParameterComparator.java deleted file mode 100644 index 62a666472..000000000 --- a/src/com/taobao/rigel/rap/project/bo/ParameterComparator.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -import java.util.Comparator; - -public class ParameterComparator implements Comparator { - - @Override - public int compare(Parameter o1, Parameter o2) { - Parameter l = (Parameter) o1; - Parameter r = (Parameter) o2; - return l.getId() < r.getId() ? 0 : 1; - } - -} diff --git a/src/com/taobao/rigel/rap/project/bo/Project.java b/src/com/taobao/rigel/rap/project/bo/Project.java deleted file mode 100644 index 68931e435..000000000 --- a/src/com/taobao/rigel/rap/project/bo/Project.java +++ /dev/null @@ -1,500 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Set; - -import org.hibernate.Session; -import org.ocpsoft.prettytime.PrettyTime; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.common.DateUtils; -import com.taobao.rigel.rap.common.StringUtils; -import com.taobao.rigel.rap.workspace.bo.CheckIn; -import com.taobao.rigel.rap.workspace.bo.Workspace; -import com.taobao.rigel.rap.workspace.bo.Workspace.ModeType; - -public class Project implements java.io.Serializable { - - private static final long serialVersionUID = 1L; - private int id; - private long userId; - private String name; - private Date createDate; - private Date updateTime; - private String introduction; - private User user; - private int workspaceModeInt; - private String relatedIds = ""; - private int groupId; - - public int getGroupId() { - return groupId; - } - - public void setGroupId(int groupId) { - this.groupId = groupId; - } - - public String getRelatedIds() { - return relatedIds; - } - - public void setRelatedIds(String relatedIds) { - this.relatedIds = relatedIds; - } - - public enum toStringType {TO_MODULE, TO_PAGE, TO_ACTION, TO_PARAMETER}; - - public enum StageType {DESIGNING, DEVELOPING, DEBUGING}; - - public int getWorkspaceModeInt() { - return workspaceModeInt; - } - - public void setWorkspaceModeInt(int workspaceModeInt) { - this.workspaceModeInt = workspaceModeInt; - } - - public Date getUpdateTime() { - return updateTime; - } - - public void setUpdateTime(Date updateTime) { - this.updateTime = updateTime; - } - - public ModeType getWorkspaceMode() { - if (workspaceModeInt == 1) { - return ModeType.VSS; - } else if (workspaceModeInt == 2) { - return ModeType.SVN; - } else { - return ModeType.VSS; - } - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public long getUserId() { - return userId; - } - - public void setUserId(long userId) { - this.userId = userId; - } - - private Set userList = new HashSet(); - - public Set getUserList() { - return userList; - } - - public void setUserList(Set userList) { - this.userList = userList; - } - - private Set moduleList = new HashSet(); - - public Set getModuleList() { - return moduleList; - } - - public void setModuleList(Set moduleList) { - this.moduleList = moduleList; - } - - public Project() { - - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Date getCreateDate() { - return createDate; - } - - public void setCreateDate(Date createDate) { - this.createDate = createDate; - } - - - public String getIntroduction() { - return introduction; - } - - public void setIntroduction(String introduction) { - this.introduction = (introduction == null ? "" : introduction); - } - - private String projectData; - - public String getProjectData() { - return projectData; - } - - public void setProjectData(String projectData) { - this.projectData = projectData; - } - - public List getModuleListOrdered() { - Set moduleList = getModuleList(); - List moduleListOrdered = new ArrayList(); - moduleListOrdered.addAll(moduleList); - Collections.sort(moduleListOrdered, new ModuleComparator()); - return moduleListOrdered; - } - - public void addModule(Module module) { - getModuleList().add(module); - module.setProject(this); - } - - public String getMemberAccountListStr() { - StringBuilder stringBuilder = new StringBuilder(); - for (User user : getUserList()) { - stringBuilder.append(user.getAccount() + "(" + user.getName() + "), "); - } - return stringBuilder.toString(); - } - - private List memberAccountList; - - public List getMemberAccountList() { - return memberAccountList; - } - - public void setMemberAccountList(List memberAccountList) { - this.memberAccountList = memberAccountList; - } - - private Set workspaceList = new HashSet(); - - public Set getWorkspaceList() { - return workspaceList; - } - - public void setWorkspaceList(Set workspaceList) { - this.workspaceList = workspaceList; - } - - private String version; - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String toString(toStringType type) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\"createDateStr\":\"" + getCreateDateStr() + "\","); - stringBuilder.append("\"user\":" + getUser() + ","); - stringBuilder.append("\"id\":" + getId() + ","); - stringBuilder.append("\"version\":\"" + getVersion() + "\","); - stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); - stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\","); - stringBuilder.append("\"moduleList\":"); - - stringBuilder.append("["); - Iterator iterator = getModuleListOrdered().iterator(); - while(iterator.hasNext()) { - stringBuilder.append(iterator.next().toString(type)); - if (iterator.hasNext()) { - stringBuilder.append(","); - } - } - stringBuilder.append("]}"); - return stringBuilder.toString(); - } - - @Override - public String toString() { - return "{}"; - } - - public void update(Project project) { - setIntroduction(project.getIntroduction()); - setName(project.getName()); - } - - private boolean isManagable; - - public boolean getIsManagable() { - return isManagable; - } - - public void setIsManagable(boolean isManagable) { - this.isManagable = isManagable; - } - - public String getCreateDateStr() { - return getCreateDate() == null ? "" : DateUtils.DATE_FORMAT.format(getCreateDate()); - } - - public void setCreateDateStr(String createDateStr) throws ParseException { - setCreateDate((createDateStr == null || createDateStr.equals("")) ? - null : DateUtils.DATE_FORMAT.parse(createDateStr)); - } - - public String getUserListStr() { - StringBuilder stringBuilder = new StringBuilder(); - Iterator iterator = getUserList().iterator(); - while(iterator.hasNext()) { - User user = iterator.next(); - // remove the creator - if (user.getId() == getUser().getId()) continue; - stringBuilder.append(user.getName() + "(" + user.getWorkRole() + ")"); - if (iterator.hasNext()) { - stringBuilder.append(", "); - } - } - return stringBuilder.toString(); - } - - public String getUserListStrShort() { - StringBuilder stringBuilder = new StringBuilder(); - Iterator iterator = getUserList().iterator(); - int count = 1; - while(iterator.hasNext()) { - User user = iterator.next(); - // remove the creator - if (user.getId() == getUser().getId()) continue; - stringBuilder.append(user.getName() + "(" + user.getWorkRole() + ")"); - if (iterator.hasNext()) { - stringBuilder.append(", "); - } - if (++count > 5) { - stringBuilder.append(iterator.hasNext() ? "etc." : ""); - break; - } - } - return stringBuilder.toString(); - } - - private Set checkInList = new HashSet(); - - public Set getCheckInList() { - return checkInList; - } - - public void setCheckInList(Set checkInList) { - this.checkInList = checkInList; - } - - public List getCheckInListOrdered() { - Set checkInList = getCheckInList(); - List checkInListOrdered = new ArrayList(); - checkInListOrdered.addAll(checkInList); - Collections.sort(checkInListOrdered, new CheckInComparator()); - return checkInListOrdered; - } - - public Module findModule(int moduleId) { - for (Module i : getModuleList()) { - if (i.getId() == moduleId) - return i; - } - return null; - } - - public Page findPage(int pageId) { - for (Module module : getModuleList()) { - for (Page page : module.getPageList()) { - if (page.getId() == pageId) - return page; - } - } - return null; - } - - public Action findAction(int actionId) { - for (Module module : getModuleList()) { - for (Page page : module.getPageList()) { - for (Action action : page.getActionList()) { - if (action.getId() == actionId) - return action; - } - } - } - return null; - } - - public Parameter findParameter(int parameterId, boolean isRequestType) { - for (Module module : getModuleList()) { - for (Page page : module.getPageList()) { - for (Action action : page.getActionList()) { - for (Parameter parameter : (isRequestType ? - action.getRequestParameterList() : action.getResponseParameterList())) { - if (parameter.getId() == parameterId) { - return parameter; - } - } - } - } - } - return null; - } - - public Parameter findChildParameter(int parameterId) { - for (Module module : getModuleList()) { - for (Page page : module.getPageList()) { - for (Action action : page.getActionList()) { - for (Parameter parameter : action.getRequestParameterList()) { - Parameter pRecur = findParameterRecursively(parameter, parameterId); - if (pRecur != null) { - return pRecur; - } - } - - for (Parameter parameter : action.getResponseParameterList()) { - Parameter pRecur = findParameterRecursively(parameter, parameterId); - if (pRecur != null) { - return pRecur; - } - } - } - } - } - return null; - } - - /** - * find parameter recursively - * recursive: - * p.parameterList[0].parameterList[0]..... - * - * @param p - * @param id - * @return return the object found, other wise return null - */ - private Parameter findParameterRecursively(Parameter p, int id) { - Iterator iterator = p.getParameterList().iterator(); - while(iterator.hasNext()) { - Parameter parameter = iterator.next(); - if (parameter.getId() == id) { - return parameter; - } - parameter = findParameterRecursively(parameter, id); - if (parameter != null) { - return parameter; - } - } - return null; - } - - public void removeModule(int id, Session session) { - Module module = findModule(id); - if (module != null && moduleList != null) { - moduleList.remove(module); - session.delete(module); - } - } - - public void removePage(int id, Session session) { - Page page = findPage(id); - if (page != null && page.getModule() != null && page.getModule().getPageList() != null) { - page.getModule().getPageList().remove(page); - session.delete(page); - } - } - - public void removeAction(int id, Session session) { - Action action = findAction(id); - if (action == null) return; - Set pageList = action.getPageList(); - if (pageList == null) return; - Iterator iterator = pageList.iterator(); - while (iterator.hasNext()) { - iterator.next().getActionList().remove(action); - session.delete(action); - } - } - - public void removeParameter(int id, Session session) { - Parameter parameter = findParameter(id, true); - - // if parameter == null, it maybe response parameter - if (parameter == null) { - parameter = findParameter(id, false); - - // if parameter == null still, it must be child parameter of a complex parameter - if (parameter == null) { - parameter = findChildParameter(id); - if (parameter != null && parameter.getComplexParameterList() != null) { - for (Parameter pComplex : parameter.getComplexParameterList()) { - pComplex.getParameterList().remove(parameter); - session.delete(parameter); - } - } - return ; - } - Iterator iterator = parameter.getActionResponseList().iterator(); - while (iterator.hasNext()) { - iterator.next().getResponseParameterList().remove(parameter); - session.delete(parameter); - } - } else { - Iterator iterator = parameter.getActionRequestList().iterator(); - while (iterator.hasNext()) { - iterator.next().getRequestParameterList().remove(parameter); - session.delete(parameter); - } - } - } - - public void addMember(User user) { - // if member added is the creator, ignore - if (user.getId() == getUser().getId()) - return; - // if member already exists, ignore - boolean exist = false; - for (User item : getUserList()) { - if (item.getId() == user.getId()) { - exist = true; - } - } - if (exist) return; - // validation complete, add this user - getUserList().add(user); - user.getJoinedProjectList().add(this); - } - - public void removeMember(User user) { - getUserList().remove(user); - user.getJoinedProjectList().remove(this); - } - - public String getLastUpdateStr() { - PrettyTime p = new PrettyTime(new Locale("zh")); - return p.format(this.updateTime) + "更新"; - } -} diff --git a/src/com/taobao/rigel/rap/project/bo/Validator.java b/src/com/taobao/rigel/rap/project/bo/Validator.java deleted file mode 100644 index ea188f680..000000000 --- a/src/com/taobao/rigel/rap/project/bo/Validator.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.taobao.rigel.rap.project.bo; - -public class Validator implements java.io.Serializable { - - /** - * - */ - private static final long serialVersionUID = 1L; - - private int id; - - public int getId() { - return this.id; - } - - public void setId(int id) { - this.id = id; - } - - private int type; - - public int getType() { - return this.type; - } - - public void setType(int type) { - this.type = type; - } - - private String rule; - - public String getRule() { - return this.rule; - } - - public void setRule(String rule) { - this.rule = rule; - } -} diff --git a/src/com/taobao/rigel/rap/project/dao/ProjectDao.java b/src/com/taobao/rigel/rap/project/dao/ProjectDao.java deleted file mode 100644 index 70b77be36..000000000 --- a/src/com/taobao/rigel/rap/project/dao/ProjectDao.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.taobao.rigel.rap.project.dao; - -import java.util.List; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.project.bo.Action; -import com.taobao.rigel.rap.project.bo.Module; -import com.taobao.rigel.rap.project.bo.Page; -import com.taobao.rigel.rap.project.bo.Project; - -public interface ProjectDao { - - /** - * get project list - * @param user - * @param curPageNum - * @param pageSize - * @return - */ - List getProjectList(User user, int curPageNum, int pageSize); - - /** - * get new project - * @param project - * @return always 0 - */ - int addProject(Project project); - - /** - * update project - * @param id - * @param projectData - * @param deletedObjectListData - * @return - */ - String updateProject(int id, String projectData, - String deletedObjectListData); - - /** - * update project - * @param project - * @return - */ - int updateProject(Project project); - - /** - * remove project - * @param id - * @return - */ - int removeProject(int id); - - /** - * get project - * @param id - * @return - */ - Project getProject(int id); - - /** - * get module - * @param id - * @return - */ - Module getModule(int id); - - /** - * get page - * @param id - * @return - */ - Page getPage(int id); - - - /** - * get action - * @param id - * @return - */ - Action getAction(int id); - - /** - * save project - * @param project - * @return - */ - int saveProject(Project project); - - /** - * get project list number - * @param user - * @return - */ - long getProjectListNum(User user); - - /** - * get matched action list based on URL pattern - * - * @param projectId - * @param pattern - * @return - */ - List getMatchedActionList(int projectId, String pattern); - - /** - * clear all mock data of objects in specified project - * @param projectId project id - * @return affected rows num - */ - public int resetMockData(int projectId); - - /** - * get project list by group - * @param id - * @return - */ - List getProjectListByGroup(int id); - - /** - * project search - * - * @param key - * @return - */ - List search(String key); -} diff --git a/src/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java b/src/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java deleted file mode 100644 index 62d96777e..000000000 --- a/src/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java +++ /dev/null @@ -1,389 +0,0 @@ -package com.taobao.rigel.rap.project.dao.impl; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.hibernate.ObjectNotFoundException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.springframework.orm.hibernate3.support.HibernateDaoSupport; - -import com.google.gson.Gson; -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.common.ArrayUtils; -import com.taobao.rigel.rap.project.bo.Action; -import com.taobao.rigel.rap.project.bo.Module; -import com.taobao.rigel.rap.project.bo.ObjectItem; -import com.taobao.rigel.rap.project.bo.Page; -import com.taobao.rigel.rap.project.bo.Parameter; -import com.taobao.rigel.rap.project.bo.Project; -import com.taobao.rigel.rap.project.dao.ProjectDao; - -public class ProjectDaoImpl extends HibernateDaoSupport implements ProjectDao { - - @SuppressWarnings("unchecked") - @Override - public List getProjectList(User user, int curPageNum, int pageSize) { - curPageNum = curPageNum <= 0 ? 1 : curPageNum; - String hqlByUser = "from Project as p left join fetch p.userList as u where p.user.id = :userId or u.id = :userId order by p.id desc"; - Query query = getSession().createQuery(hqlByUser).setLong("userId", - user.getId()); - query = query.setFirstResult(pageSize * (curPageNum - 1)); - query.setMaxResults(pageSize); - return query.list(); - } - - - @Override - public int addProject(Project project) { - Session session = getSession(); - project.getUser().addCreatedProject(project); - project.setVersion("0.0.0.1"); // default version - int modeInt = project.getWorkspaceModeInt(); - if (modeInt <= 0 || modeInt >= 3) { - project.setWorkspaceModeInt(1); - } - session.save(project); - project = (Project) session.load(Project.class, project.getId()); - project.setProjectData(project - .toString(Project.toStringType.TO_PARAMETER)); - return project.getId(); - } - - @Override - public int removeProject(int id) { - Session session = getSession(); - Object project = session.get(Project.class, id); - if (project != null) { - session.delete((Project) project); - return 0; - } else { - return -1; - } - - } - - @Override - public int updateProject(Project project) { - Session session = getSession(); - session.update(project); - return 0; - } - - @Override - public Project getProject(int id) { - Project p = null; - try { - Session session = getSession(); - p = (Project) session.get(Project.class, id); - } catch (Exception ex) { - ex.printStackTrace(); - } - return p; - } - - @Override - public Module getModule(int id) { - Module m = null; - try { - Session session = getSession(); - m = (Module) session.get(Module.class, id); - } catch (ObjectNotFoundException ex) { - ex.printStackTrace(); - } catch (Exception ex) { - ex.printStackTrace(); - } - return m; - } - - @Override - public Page getPage(int id) { - return (Page) getSession().get(Page.class, id); - } - - @Override - public Action getAction(int id) { - return (Action) getSession().get(Action.class, id); - } - - private Parameter getParameter(int id) { - return (Parameter) getSession().get(Parameter.class, id); - } - - @Override - public int saveProject(Project project) { - Session session = getSession(); - session.saveOrUpdate(project); - return 0; - } - - @Override - public String updateProject(int id, String projectData, - String deletedObjectListData) { - Session session = getSession(); - // StringBuilder log = new StringBuilder(); - Gson gson = new Gson(); - - Project projectClient = gson.fromJson(projectData, Project.class); - - ObjectItem[] deletedObjectList = gson.fromJson(deletedObjectListData, - ObjectItem[].class); - - Project projectServer = (Project) session.load(Project.class, id); - projectServer.setUpdateTime(new Date()); - - // performing deleting - for (ObjectItem item : deletedObjectList) { - if (item.getClassName().equals("Module")) { - projectServer.removeModule(item.getId(), session); - } else if (item.getClassName().equals("Page")) { - projectServer.removePage(item.getId(), session); - } else if (item.getClassName().equals("Action")) { - projectServer.removeAction(item.getId(), session); - } else if (item.getClassName().equals("Parameter")) { - projectServer.removeParameter(item.getId(), session); - } - } - - // performing adding & updating - for (Module module : projectClient.getModuleList()) { - Module moduleServer = projectServer.findModule(module.getId()); - if (moduleServer == null) { - addModule(session, projectServer, module); - continue; - } - moduleServer.update(module); - for (Page page : module.getPageList()) { - Page pageServer = projectServer.findPage(page.getId()); - if (pageServer == null) { - addPage(session, module, page); - continue; - } - pageServer.update(page); - for (Action action : page.getActionList()) { - Action actionServer = projectServer.findAction(action - .getId()); - if (actionServer == null) { - addAction(session, page, action); - continue; - } - actionServer.update(action); - for (Parameter parameter : action.getRequestParameterList()) { - Parameter parameterServer = projectServer - .findParameter(parameter.getId(), true); - if (parameterServer == null) { - addParameter(session, action, parameter, true); - continue; - } - parameterServer.update(parameter); - for (Parameter childParameter : parameter - .getParameterList()) { - processParameterRecursively(session, projectServer, - parameter, childParameter); - } - } - - for (Parameter parameter : action - .getResponseParameterList()) { - Parameter parameterServer = projectServer - .findParameter(parameter.getId(), false); - if (parameterServer == null) { - addParameter(session, action, parameter, false); - continue; - } - parameterServer.update(parameter); - for (Parameter childParameter : parameter - .getParameterList()) { - processParameterRecursively(session, projectServer, - parameter, childParameter); - } - } - } - } - } - return ""; - } - - private void processParameterRecursively(Session session, - Project projectServer, Parameter parameter, Parameter childParameter) { - Parameter childParameterServer = projectServer - .findChildParameter(childParameter.getId()); - if (childParameterServer == null) { - addParameterRecursively(session, parameter, childParameter); - } else { - childParameterServer.update(childParameter); - } - for (Parameter childOfChildParameter : childParameter - .getParameterList()) { - processParameterRecursively(session, projectServer, childParameter, - childOfChildParameter); - } - } - - private void addModule(Session session, Project project, Module module) { - project.addModule(module); - session.save(module); - for (Page page : module.getPageList()) { - addPage(session, module, page); - } - } - - private void addPage(Session session, Module module, Page page) { - module = (Module) session.load(Module.class, module.getId()); - module.addPage(page); - session.save(page); - for (Action action : page.getActionList()) { - addAction(session, page, action); - } - } - - private void addAction(Session session, Page page, Action action) { - page = (Page) session.load(Page.class, page.getId()); - page.addAction(action); - session.save(action); - for (Parameter parameter : action.getRequestParameterList()) { - addParameter(session, action, parameter, true); - } - for (Parameter parameter : action.getResponseParameterList()) { - addParameter(session, action, parameter, false); - } - } - - private void addParameter(Session session, Action action, - Parameter parameter, boolean isRequest) { - action = (Action) session.load(Action.class, action.getId()); - action.addParameter(parameter, isRequest); - session.save(parameter); - for (Parameter childParameter : parameter.getParameterList()) { - addParameterRecursively(session, parameter, childParameter); - } - } - - /** - * add parameter recursively - * - * @param session - * session object - * @param parameter - * parent parameter - * @param childParameter - * child parameter - */ - private void addParameterRecursively(Session session, Parameter parameter, - Parameter childParameter) { - parameter = (Parameter) session - .load(Parameter.class, parameter.getId()); - parameter.addChild(childParameter); - session.save(childParameter); - for (Parameter childOfChildParameter : childParameter - .getParameterList()) { - addParameterRecursively(session, childParameter, - childOfChildParameter); - } - } - - @SuppressWarnings("unchecked") - @Override - public long getProjectListNum(User user) { - String hql = "select count(p) from Project as p order by p.id desc"; - String hqlByUser = "select count(p) from Project as p left join p.userList as u where p.user.id = :userId or u.id = :userId order by p.id desc"; - Query query = user == null ? getSession().createQuery(hql) - : getSession().createQuery(hqlByUser).setLong("userId", - user.getId()); - List list = query.list(); - return list.get(0); - } - - @SuppressWarnings("unchecked") - @Override - public List getMatchedActionList(int projectId, String pattern) { - StringBuilder sb = new StringBuilder(); - sb.append("SELECT a.id FROM tb_action a ") - .append("JOIN tb_action_and_page ap ON ap.action_id = a.id ") - .append("JOIN tb_page p ON p.id = ap.page_id ") - .append("JOIN tb_module m ON m.id = p.module_id ") - .append("WHERE LOCATE(:pattern, a.request_url) != 0 AND m.project_id = :projectId "); - - String sql = sb.toString(); - Query query = getSession().createSQLQuery(sql); - query.setString("pattern", pattern); - query.setInteger("projectId", projectId); - List list = query.list(); - List actionList = new ArrayList(); - for (int id : list) { - actionList.add(getAction(id)); - } - return actionList; - } - - @SuppressWarnings("unchecked") - private List getParameterIdList(int projectId) { - StringBuilder sql = new StringBuilder(); - sql.append(" SELECT DISTINCT p.id") - .append(" FROM tb_parameter p") - .append(" JOIN tb_response_parameter_list_mapping rplm ON p.id = rplm.parameter_id") - .append(" JOIN tb_action_and_page ap ON ap.action_id = rplm.action_id") - .append(" JOIN tb_page p2 ON p2.id = ap.page_id") - .append(" JOIN tb_module m ON m.id = p2.module_id") - .append(" WHERE m.project_id = :projectId"); - Query query = getSession().createSQLQuery(sql.toString()); - query.setInteger("projectId", projectId); - List list = query.list(); - - StringBuilder sql2 = new StringBuilder(); - sql2.append(" SELECT DISTINCT p.id") - .append(" FROM tb_parameter p") - .append(" JOIN tb_request_parameter_list_mapping rplm ON p.id = rplm.parameter_id") - .append(" JOIN tb_action_and_page ap ON ap.action_id = rplm.action_id") - .append(" JOIN tb_page p2 ON p2.id = ap.page_id") - .append(" JOIN tb_module m ON m.id = p2.module_id") - .append(" WHERE m.project_id = :projectId"); - Query query2 = getSession().createSQLQuery(sql2.toString()); - query2.setInteger("projectId", projectId); - list.addAll(query2.list()); - List paramList = new ArrayList(); - for (Integer pId : list) { - paramList.add(getParameter(pId)); - } - for (Parameter p : paramList) { - recursivelyAddSubParamList(list, p); - } - return list; - } - - private void recursivelyAddSubParamList(List list, Parameter p) { - list.add(p.getId()); - if (p.getParameterList() == null) - return; - for (Parameter subP : p.getParameterList()) { - recursivelyAddSubParamList(list, subP); - } - } - - public int resetMockData(int projectId) { - List pIdList = getParameterIdList(projectId); - String sql = "UPDATE tb_parameter SET mock_data = NULL where id in (" - + ArrayUtils.join(pIdList, ",") + ")"; - Query query = getSession().createSQLQuery(sql); - return query.executeUpdate(); - } - - @SuppressWarnings("unchecked") - @Override - public List getProjectListByGroup(int id) { - String hql = "from Project where groupId = :id"; - Query query = getSession().createQuery(hql); - query.setInteger("id", id); - return query.list(); - } - - @SuppressWarnings("unchecked") - @Override - public List search(String key) { - String hql = "from Project where name LIKE :key"; - Query query = getSession().createQuery(hql); - query.setString("key", "%" + key + "%"); - return query.list(); - } -} diff --git a/src/com/taobao/rigel/rap/project/mapping/Action.hbm.xml b/src/com/taobao/rigel/rap/project/mapping/Action.hbm.xml deleted file mode 100644 index a0f9a42d3..000000000 --- a/src/com/taobao/rigel/rap/project/mapping/Action.hbm.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/project/mapping/Module.hbm.xml b/src/com/taobao/rigel/rap/project/mapping/Module.hbm.xml deleted file mode 100644 index 16ae39875..000000000 --- a/src/com/taobao/rigel/rap/project/mapping/Module.hbm.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com/taobao/rigel/rap/project/mapping/Page.hbm.xml b/src/com/taobao/rigel/rap/project/mapping/Page.hbm.xml deleted file mode 100644 index 87126bf30..000000000 --- a/src/com/taobao/rigel/rap/project/mapping/Page.hbm.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com/taobao/rigel/rap/project/mapping/Parameter.hbm.xml b/src/com/taobao/rigel/rap/project/mapping/Parameter.hbm.xml deleted file mode 100644 index 0b2445c8a..000000000 --- a/src/com/taobao/rigel/rap/project/mapping/Parameter.hbm.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/project/mapping/Project.hbm.xml b/src/com/taobao/rigel/rap/project/mapping/Project.hbm.xml deleted file mode 100644 index cbf34bb7b..000000000 --- a/src/com/taobao/rigel/rap/project/mapping/Project.hbm.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - 项目名称 - - - - - 项目相关ID - - - - - 分组ID - - - - - 当前版本 - - - - - 创建时间 - - - - - 更新时间 - - - - - 项目简介 - - - - - 共享模式 - - - - - 项目数据(json),用于VSS同步模式 - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/com/taobao/rigel/rap/project/service/ProjectMgr.java b/src/com/taobao/rigel/rap/project/service/ProjectMgr.java deleted file mode 100644 index e2782a9be..000000000 --- a/src/com/taobao/rigel/rap/project/service/ProjectMgr.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.taobao.rigel.rap.project.service; - -import java.util.List; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.project.bo.Action; -import com.taobao.rigel.rap.project.bo.Module; -import com.taobao.rigel.rap.project.bo.Page; -import com.taobao.rigel.rap.project.bo.Project; - -public interface ProjectMgr { - - /** - * get project list - * - * @param user - * @param curPageNum - * @param pageSize - * @return - */ - List getProjectList(User user, int curPageNum, int pageSize); - - /** - * add new project - * - * @param project - * @return - */ - int addProject(Project project); - - /** - * remove project - * - * @param id - * @return - */ - int removeProject(int id); - - /** - * update project - * - * @param project - * @return - */ - int updateProject(Project project); - - /** - * get project by id - * - * @param id - * @return - */ - Project getProject(int id); - - /** - * get module by id - * - * @param id - * @return - */ - Module getModule(int id); - - /** - * get page by id - * - * @param id - * @return - */ - Page getPage(int id); - - /** - * update project - * - * @param id - * @param projectData - * @param deletedObjectListData - * @return - */ - String updateProject(int id, String projectData, - String deletedObjectListData); - - /** - * get number of project list usually used for pager - * - * @param user - * @return - */ - long getProjectListNum(User user); - - /** - * set action.remarks as paramIdList eg-> action.remarks = "id,name,age"; - * used for parameter identifier spelling validation [*caution*] only - * calculating response parameters - * - * @param action - * action to be filled with paramIdList info - */ - void loadParamIdListForAction(Action action); - - /** - * load paramIdList for page - * - * @param page - */ - void loadParamIdListForPage(Page page); - - /** - * get matched action list based on URL pattern - * - * @param projectId - * @param pattern - * @return - */ - List getMatchedActionList(int projectId, String pattern); - - /** - * get project list by group id - * @param id - * @return - */ - List getProjectListByGroup(int id); - - /** - * search project - * - * @param key - * @return - */ - List search(String key); -} diff --git a/src/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java b/src/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java deleted file mode 100644 index 98058bf57..000000000 --- a/src/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java +++ /dev/null @@ -1,229 +0,0 @@ -package com.taobao.rigel.rap.project.service.impl; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Set; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.account.dao.AccountDao; -import com.taobao.rigel.rap.common.ArrayUtils; -import com.taobao.rigel.rap.organization.bo.Group; -import com.taobao.rigel.rap.organization.dao.OrganizationDao; -import com.taobao.rigel.rap.project.bo.Action; -import com.taobao.rigel.rap.project.bo.Module; -import com.taobao.rigel.rap.project.bo.Page; -import com.taobao.rigel.rap.project.bo.Parameter; -import com.taobao.rigel.rap.project.bo.Project; -import com.taobao.rigel.rap.project.dao.ProjectDao; -import com.taobao.rigel.rap.project.service.ProjectMgr; - -public class ProjectMgrImpl implements ProjectMgr { - - private ProjectDao projectDao; - private OrganizationDao organizationDao; - - public OrganizationDao getOrganizationDao() { - return organizationDao; - } - - public void setOrganizationDao(OrganizationDao organizationDao) { - this.organizationDao = organizationDao; - } - - public ProjectDao getProjectDao() { - return this.projectDao; - } - - public void setProjectDao(ProjectDao projectDao) { - this.projectDao = projectDao; - } - - private AccountDao accountDao; - - public AccountDao getAccountDao() { - return accountDao; - } - - public void setAccountDao(AccountDao accountDao) { - this.accountDao = accountDao; - } - - @Override - public List getProjectList(User user, int curPageNum, int pageSize) { - List projectList = projectDao.getProjectList(user, curPageNum, - pageSize); - for (Project p : projectList) { - if (user.isUserInRole("admin") - || p.getUser().getId() == user.getId()) - p.setIsManagable(true); - } - return projectList; - } - - @Override - public int addProject(Project project) { - project.setUpdateTime(new Date()); - project.setCreateDate(new Date()); - for (String account : project.getMemberAccountList()) { - User user = accountDao.getUser(account); - if (user != null) { - project.addMember(user); - } - } - int result = projectDao.addProject(project); - - Group g = organizationDao.getGroup(project.getGroupId()); - if (g.getProductionLineId() > 0) { - organizationDao.updateCountersInProductionLine(g - .getProductionLineId()); - } - - return result; - } - - @Override - public int removeProject(int id) { - Project p = getProject(id); - Group g = organizationDao.getGroup(p.getGroupId()); - int result = projectDao.removeProject(id); - if (g != null) { - int pId = g.getProductionLineId(); - if (pId > 0) { - organizationDao.updateCountersInProductionLine(pId); - } - } - return result; - } - - @Override - public int updateProject(Project outerProject) { - Project project = getProject(outerProject.getId()); - project.setName(outerProject.getName()); - project.setIntroduction(outerProject.getIntroduction()); - project.setUpdateTime(new Date()); - - if (outerProject.getMemberAccountList() != null) { - // adding new ones - for (String account : outerProject.getMemberAccountList()) { - User user = accountDao.getUser(account); - if (user != null) { - project.addMember(user); - } - } - - if (project.getUserList() != null) { - // remove old ones - List userListToBeRemoved = new ArrayList(); - for (User user : project.getUserList()) { - if (!outerProject.getMemberAccountList().contains( - user.getAccount())) { - userListToBeRemoved.add(user); - } - } - - for (User user : userListToBeRemoved) { - project.removeMember(user); - } - } - } - - return projectDao.updateProject(project); - } - - @Override - public Project getProject(int id) { - return projectDao.getProject(id); - } - - @Override - public Module getModule(int id) { - return projectDao.getModule(id); - } - - @Override - public Page getPage(int id) { - return projectDao.getPage(id); - } - - @Override - public String updateProject(int id, String projectData, - String deletedObjectListData) { - return projectDao.updateProject(id, projectData, deletedObjectListData); - } - - @Override - public long getProjectListNum(User user) { - if (user != null && user.isUserInRole("admin")) { - user = null; - } - return projectDao.getProjectListNum(user); - } - - @Override - public void loadParamIdListForAction(Action action) { - List paramIdList = new ArrayList(); - recursivelyLoadParamIdList(paramIdList, - action.getResponseParameterList()); - action.setRemarks(ArrayUtils.join(paramIdList, ",")); - } - - @Override - public void loadParamIdListForPage(Page page) { - for (Action action : page.getActionList()) { - loadParamIdListForAction(action); - } - } - - /** - * sub method of loadParamIdListForAction for recursively load paramIdList - * for complex parameters - * - * @param paramIdList - * @param paramList - */ - private void recursivelyLoadParamIdList(List paramIdList, - Set paramList) { - for (Parameter p : paramList) { - if (p.getIdentifier() != null || !p.getIdentifier().isEmpty()) { - paramIdList.add(p.getIdentifier()); - } - if (p.getParameterList() != null && p.getParameterList().size() > 0) { - recursivelyLoadParamIdList(paramIdList, p.getParameterList()); - } - } - } - - @Override - public List getMatchedActionList(int projectId, String pattern) { - List actionList = projectDao.getMatchedActionList(projectId, - pattern); - if (actionList == null || actionList.size() == 0) { - Project project = projectDao.getProject(projectId); - if (project != null) { - String ids = project.getRelatedIds(); - if (ids != null && !ids.isEmpty()) { - String[] arr = ids.split(","); - for (String id : arr) { - actionList = projectDao.getMatchedActionList( - Integer.parseInt(id), pattern); - if (actionList != null && actionList.size() != 0) { - return actionList; - } - } - } - } - } - return actionList; - } - - @Override - public List getProjectListByGroup(int id) { - return projectDao.getProjectListByGroup(id); - } - - @Override - public List search(String key) { - return projectDao.search(key); - } -} diff --git a/src/com/taobao/rigel/rap/project/web/action/ProjectAction.java b/src/com/taobao/rigel/rap/project/web/action/ProjectAction.java deleted file mode 100644 index 248bf04df..000000000 --- a/src/com/taobao/rigel/rap/project/web/action/ProjectAction.java +++ /dev/null @@ -1,454 +0,0 @@ -package com.taobao.rigel.rap.project.web.action; - -import java.io.ByteArrayInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.google.gson.Gson; -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.auto.generate.bo.VelocityTemplateGenerator; -import com.taobao.rigel.rap.auto.generate.contract.Generator; -import com.taobao.rigel.rap.common.ActionBase; -import com.taobao.rigel.rap.common.RapError; -import com.taobao.rigel.rap.project.bo.Page; -import com.taobao.rigel.rap.project.bo.Project; -import com.taobao.rigel.rap.project.service.ProjectMgr; -import com.taobao.rigel.rap.workspace.service.WorkspaceMgr; - -public class ProjectAction extends ActionBase { - - private int id; - - private List searchResult; - - public List getSearchResult() { - return searchResult; - } - - private String key; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public int getId() { - return this.id; - } - - public void setId(int id) { - this.id = id; - } - - private String desc; - - private int groupId; - - public int getGroupId() { - return groupId; - } - - public void setGroupId(int groupId) { - this.groupId = groupId; - } - - private String accounts; - - public String getDesc() { - return desc; - } - - public void setDesc(String desc) { - this.desc = desc; - } - - public String getAccounts() { - if (accounts == null) - return ""; - return accounts; - } - - public void setAccounts(String accounts) { - this.accounts = accounts; - } - - public List getMemberAccountList() { - List memberList = new ArrayList(); - for (User user : super.getAccountMgr().getUserList()) { - memberList.add(user.getAccount() + "(" + user.getName() + ")"); - } - return memberList; - } - - private String memberAccountListStr; - - public String getMemberAccountListStr() { - return memberAccountListStr; - } - - public void setMemberAccountListStr(String memberAccountListStr) { - this.memberAccountListStr = memberAccountListStr; - } - - private String name; - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - private Date createDate; - - public Date getCreateDate() { - return this.createDate; - } - - public void setCreateDate(Date createDate) { - this.createDate = createDate; - } - - private String introduction; - - public String getIntroduction() { - return this.introduction; - } - - public void setIntroduction(String introduction) { - this.introduction = introduction; - } - - private List projectList; - - public List getProjectList() { - return this.projectList; - } - - public void setProjectList(List projectList) { - this.projectList = projectList; - } - - private Project project; - - public Project getProject() { - return this.project; - } - - public void setProject(Project project) { - this.project = project; - } - - private static final long serialVersionUID = 1L; - - private ProjectMgr projectMgr; - - /** - * get project manager - * - * @return project manager - */ - public ProjectMgr getProjectMgr() { - return projectMgr; - } - - /** - * set project manager - * - * @param projectMgr - * project manager - * @throws exceptions - * No exceptions thrown - */ - public void setProjectMgr(ProjectMgr projectMgr) { - this.projectMgr = projectMgr; - } - - private WorkspaceMgr workspaceMgr; - - public WorkspaceMgr getWorkspaceMgr() { - return workspaceMgr; - } - - public void setWorkspaceMgr(WorkspaceMgr workspaceMgr) { - this.workspaceMgr = workspaceMgr; - } - - private int pageId; - - public int getPageId() { - return pageId; - } - - public void setPageId(int pageId) { - this.pageId = pageId; - } - - private String projectData; - - public String getProjectData() { - return projectData; - } - - public void setProjectData(String projectData) { - this.projectData = projectData; - } - - /** - * remove project - * - * @param id - * {int} id of the project to be removed - */ - public String removeProject() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().canManageProject(getId())) { - setErrMsg("您没有管理该项目的权限"); - return ERROR; - } - projectMgr.removeProject(getId()); - return myProjectList(); - } - - public String delete() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().canManageProject(getId())) { - setErrMsg("您没有管理该项目的权限"); - return ERROR; - } - projectMgr.removeProject(getId()); - return SUCCESS; - } - - private String addProject() { - if (!isUserLogined()) - return LOGIN; - Project project = new Project(); - project.setCreateDate(new Date()); - project.setUser(getCurUser()); - project.setIntroduction(getIntroduction()); - project.setName(getName()); - List memberAccountList = new ArrayList(); - String[] list = getMemberAccountListStr().split(","); - // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), - for (String item : list) { - String account = item.contains("(") ? item.substring(0, - item.indexOf("(")).trim() : item.trim(); - if (!account.equals("")) - memberAccountList.add(account); - } - project.setMemberAccountList(memberAccountList); - projectMgr.addProject(project); - return this.myProjectList(); - } - - public String create() { - if (!isUserLogined()) - return LOGIN; - Gson gson = new Gson(); - Project project = new Project(); - project.setCreateDate(new Date()); - project.setUser(getCurUser()); - project.setIntroduction(getDesc()); - project.setName(getName()); - project.setGroupId(groupId); - List memberAccountList = new ArrayList(); - String[] list = getAccounts().split(","); - // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), - for (String item : list) { - String account = item.contains("(") ? item.substring(0, - item.indexOf("(")).trim() : item.trim(); - if (!account.equals("")) - memberAccountList.add(account); - } - project.setMemberAccountList(memberAccountList); - int projectId = projectMgr.addProject(project); - project = projectMgr.getProject(projectId); - Map result = new HashMap(); - result.put("id", project.getId()); - result.put("name", project.getName()); - result.put("desc", project.getIntroduction()); - result.put("accounts", project.getMemberAccountListStr()); - result.put("groupId", project.getGroupId()); - result.put("isManagable", "true"); - setJson(new RapError(gson.toJson(result)).toString()); - return SUCCESS; - } - - private String updateProject() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().canManageProject(getId())) { - setErrMsg("您没有管理该项目的权限"); - return ERROR; - } - Project project = new Project(); - project.setId(getId()); - project.setIntroduction(getIntroduction()); - project.setName(getName()); - - List memberAccountList = new ArrayList(); - String[] list = getMemberAccountListStr().split(","); - // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), - for (String item : list) { - - String account = item.contains("(") ? item.substring(0, - item.indexOf("(")).trim() : item.trim(); - if (!account.equals("")) - memberAccountList.add(account); - } - project.setMemberAccountList(memberAccountList); - projectMgr.updateProject(project); - return myProjectList(); - } - - public String update() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().canManageProject(getId())) { - setErrMsg("您没有管理该项目的权限"); - return ERROR; - } - Project project = new Project(); - project.setId(getId()); - project.setIntroduction(getDesc()); - project.setName(getName()); - - List memberAccountList = new ArrayList(); - String[] list = getAccounts().split(","); - // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), - for (String item : list) { - String account = item.contains("(") ? item.substring(0, - item.indexOf("(")).trim() : item.trim(); - if (!account.equals("")) - memberAccountList.add(account); - } - Gson gson = new Gson(); - project.setMemberAccountList(memberAccountList); - projectMgr.updateProject(project); - project = projectMgr.getProject(project.getId()); - - if (getCurUser().isUserInRole("admin") - || getCurUser().getId() == project.getUser().getId()) { - project.setIsManagable(true); - } - - Map result = new HashMap(); - result.put("id", project.getId()); - result.put("name", project.getName()); - result.put("desc", project.getIntroduction()); - result.put("accounts", project.getMemberAccountListStr()); - result.put("groupId", project.getGroupId()); - result.put("isManagable", project.getIsManagable()); - setJson(new RapError(gson.toJson(result)).toString()); - return SUCCESS; - } - - public String addOrUpdateProject() { - if (id == 0) { - return addProject(); - } else { - return updateProject(); - } - } - - public String myProjectList() { - if (!isUserLogined()) - return LOGIN; - - // query paging - super.initPager(); - int curPageNum = super.getPager().getCurPagerNum(); - int pageSize = super.getPager().getPagerSize(); - long totalRecNum = projectMgr.getProjectListNum(getCurUser()); - getPager().setTotalRecNum(totalRecNum); - - setProjectList(projectMgr.getProjectList(getCurUser(), curPageNum, - pageSize)); - return SUCCESS; - } - - public String myProject() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().haveAccessOfProject(getId())) { - setErrMsg("你没有访问该项目的权限。"); - return ERROR; - } - setProject(projectMgr.getProject(getId())); - setJson(getProject().toString(Project.toStringType.TO_PAGE)); - return SUCCESS; - } - - public String projectDetailAjax() { - if (!isUserLogined()) - return LOGIN; - if (!getCurUser().haveAccessOfProject(getId())) { - setErrMsg("你没有访问该项目的权限。"); - return ERROR; - } - return this.myProject(); - } - - private String result; - - public String getResult() { - return result; - } - - public void setResult(String result) { - this.result = result; - } - - private InputStream outputStream; - - public InputStream getOutputStream() { - return outputStream; - } - - public void setOutputStream(InputStream outputStream) { - this.outputStream = outputStream; - } - - public String autoGenerate() throws FileNotFoundException, - UnsupportedEncodingException { - Generator generator = new VelocityTemplateGenerator(); - Page page = projectMgr.getPage(getPageId()); - generator.setObject(page); - String exportFileString = generator.doGenerate(); - outputStream = new ByteArrayInputStream( - exportFileString.getBytes("UTF8")); - return SUCCESS; - } - - public String getGeneratedFileName() { - return projectMgr.getPage(getPageId()).getTemplate(); - } - - public String search() { - searchResult = projectMgr.search(key); - List> list = new ArrayList>(); - for (Project p : searchResult) { - Map item = new HashMap(); - item.put("id", p.getId()); - item.put("name", p.getName()); - list.add(item); - } - Gson gson = new Gson(); - setJson(gson.toJson(list)); - return SUCCESS; - } - -} diff --git a/src/com/taobao/rigel/rap/project/web/action/struts.xml b/src/com/taobao/rigel/rap/project/web/action/struts.xml deleted file mode 100644 index d5a712563..000000000 --- a/src/com/taobao/rigel/rap/project/web/action/struts.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - /project/myProjectList.vm - - - - /bcom/json.cb.vm - - - - /bcom/json.cb.vm - - - - /bcom/json.cb.vm - - - - /bcom/json.cb.vm - - - - /project/myProjectList.vm - - - - /project/myProject.vm - - - - /bcom/project.cb.vm - - - - /project/myProjectList.vm - - - - - text/plain - attachment; filename="${generatedFileName}" - outputStream - - - - - diff --git a/src/com/taobao/rigel/rap/tester/web/action/TesterAction.java b/src/com/taobao/rigel/rap/tester/web/action/TesterAction.java deleted file mode 100644 index a8458109f..000000000 --- a/src/com/taobao/rigel/rap/tester/web/action/TesterAction.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.taobao.rigel.rap.tester.web.action; - -import java.util.List; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.account.service.AccountMgr; -import com.taobao.rigel.rap.common.StringUtils; -import com.taobao.rigel.rap.project.bo.Page; -import com.taobao.rigel.rap.project.service.ProjectMgr; -import com.opensymphony.xwork2.ActionSupport; - -public class TesterAction extends ActionSupport { - - private static final long serialVersionUID = 1L; - private ProjectMgr projectMgr; - private AccountMgr accountMgr; - private int id; - private Page page; - private int projectId; - - public int getProjectId() { - return projectId; - } - - public Page getPage() { - return page; - } - - public ProjectMgr getProjectMgr() { - return projectMgr; - } - - public void setProjectMgr(ProjectMgr projectMgr) { - this.projectMgr = projectMgr; - } - - public AccountMgr getAccountMgr() { - return accountMgr; - } - - public void setAccountMgr(AccountMgr accountMgr) { - this.accountMgr = accountMgr; - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String pageTester() { - page = projectMgr.getPage(id); - projectMgr.loadParamIdListForPage(page); - projectId = page.getModule().getProject().getId(); - return SUCCESS; - } - - /** - * used for system configuration when new version deployed - * @return - */ - public String ___init___() { - List userList = accountMgr.getUserList(); - for (User user : userList) { - String password = user.getPassword(); - password = StringUtils.getMD5(password); - password = StringUtils.getMD5(password); - accountMgr._updatePassword(user.getAccount(), password); - } - return SUCCESS; - } -} diff --git a/src/com/taobao/rigel/rap/tester/web/action/struts.xml b/src/com/taobao/rigel/rap/tester/web/action/struts.xml deleted file mode 100644 index ac0987ad2..000000000 --- a/src/com/taobao/rigel/rap/tester/web/action/struts.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - /tester/pageTester.vm - - - /bcom/isOk.cb.vm - - - - diff --git a/src/com/taobao/rigel/rap/workspace/applicationContext.xml b/src/com/taobao/rigel/rap/workspace/applicationContext.xml deleted file mode 100644 index dca78c9f4..000000000 --- a/src/com/taobao/rigel/rap/workspace/applicationContext.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - resource.loader=class - class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader - - - - - - \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/workspace/bo/CheckIn.java b/src/com/taobao/rigel/rap/workspace/bo/CheckIn.java deleted file mode 100644 index 0747c2acb..000000000 --- a/src/com/taobao/rigel/rap/workspace/bo/CheckIn.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.taobao.rigel.rap.workspace.bo; - -import java.util.Date; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.common.DateUtils; -import com.taobao.rigel.rap.common.StringUtils; -import com.taobao.rigel.rap.project.bo.Project; -import com.taobao.rigel.rap.workspace.bo.Workspace.ModeType; - -public class CheckIn implements java.io.Serializable { - - private static final long serialVersionUID = 1L; - - public enum ToStringType {COMPLETED, NORMAL}; - - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - private Date createDate; - - public Date getCreateDate() { - return createDate; - } - - public String getCreateDateStr() { - return getCreateDate() == null ? "" : DateUtils.TIME_FORMAT.format(getCreateDate()); - } - - public void setCreateDate(Date createDate) { - this.createDate = createDate; - } - - private String tag; - - public String getTag() { - return tag; - } - - public void setTag(String tag) { - this.tag = tag; - } - - private User user; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - private Project project; - - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - - private String description; - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - private String version; - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - private String projectData; - - public String getProjectData() { - return projectData; - } - - public void setProjectData(String projectData) { - this.projectData = projectData; - } - - private int workspaceModeInt; - - public int getWorkspaceModeInt() { - return workspaceModeInt; - } - - public void setWorkspaceModeInt(int workspaceModeInt) { - this.workspaceModeInt = workspaceModeInt; - } - - public ModeType getWorkspaceMode() { - if (workspaceModeInt == 1) { - return ModeType.VSS; - } else if (workspaceModeInt == 2) { - return ModeType.SVN; - } else { - // default - return ModeType.VSS; - } - } - - public void setWorkspaceMode(ModeType workspaceModeType) { - if (workspaceModeType == ModeType.VSS) { - workspaceModeInt = 1; - } else if (workspaceModeType == ModeType.SVN) { - workspaceModeInt = 2; - } else { - // default - workspaceModeInt = 1; - } - } - - private String log; - - public String getLog() { - return log; - } - - public void setLog(String log) { - this.log = log; - } - - public void versionUpgrade(int versionPosition) throws Exception { - if (versionPosition > 4 || versionPosition < 1) { - throw new Exception("illegal version position: " + versionPosition); - } - String [] versionList = getVersion().split("\\."); - if (versionList.length != 4) { - throw new Exception("illegal version format: " + getVersion()); - } - Integer integer = Integer.parseInt(versionList[versionPosition - 1]) + 1; - versionList[versionPosition - 1] = integer.toString(); - String newVersion = ""; - for (int i = 0; i < versionList.length; i++) { - newVersion += versionList[i]; - if (i < versionList.length - 1) { - newVersion += "."; - } - } - setVersion(newVersion); - } - - @Override - public String toString() { - return this.toString(ToStringType.NORMAL); - } - public String toString(ToStringType type) { - if (type == ToStringType.NORMAL) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\"id\":" + getId() + ","); - stringBuilder.append("\"version\":\"" + getVersion() + "\","); - stringBuilder.append("\"userName\":\"" + getUser().getName() + "\","); - stringBuilder.append("\"createDateStr\":\"" + getCreateDateStr() + "\","); - stringBuilder.append("\"description\":\"" + StringUtils.escapeInJ(getDescription()) + "\"}"); - return stringBuilder.toString(); - } else if (type == ToStringType.COMPLETED) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\"id\":" + getId() + ","); - stringBuilder.append("\"version\":\"" + getVersion() + "\","); - stringBuilder.append("\"userName\":\"" + getUser().getName() + "\","); - stringBuilder.append("\"projectData\":" + getProjectData() + ","); - stringBuilder.append("\"createDateStr\":\"" + getCreateDateStr() + "\","); - stringBuilder.append("\"description\":\"" + StringUtils.escapeInJ(getDescription()) + "\"}"); - return stringBuilder.toString(); - } else { - return this.toString(); - } - } -} \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/workspace/bo/Save.java b/src/com/taobao/rigel/rap/workspace/bo/Save.java deleted file mode 100644 index 591c7782f..000000000 --- a/src/com/taobao/rigel/rap/workspace/bo/Save.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.taobao.rigel.rap.workspace.bo; - -import java.util.Date; - -import com.taobao.rigel.rap.common.DateUtils; -import com.taobao.rigel.rap.project.bo.Project; - -public class Save implements java.io.Serializable { - - private static final long serialVersionUID = 1L; - - public enum TO_STRING_TYPE {WITH_PROJECT_DATA}; - - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - private int workspaceId; - - public int getWorkspaceId() { - return workspaceId; - } - - public void setWorkspaceId(int workspaceId) { - this.workspaceId = workspaceId; - } - - private Date updateDate; - - public Date getUpdateDate() { - return updateDate; - } - - public void setUpdateDate(Date updateDate) { - this.updateDate = updateDate; - } - - private String projectData; - - public String getProjectData() { - return projectData; - } - - public void setProjectData(String projectData) { - this.projectData = projectData; - } - - private Project project; - - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - - private Workspace workspace; - - public Workspace getWorkspace() { - return workspace; - } - - public void setWorkspace(Workspace workspace) { - this.workspace = workspace; - } - - private int projectId; - - public int getProjectId() { - return projectId; - } - - public void setProjectId(int projectId) { - this.projectId = projectId; - } - - public String toString() { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\"id\":" + getId() + ","); - stringBuilder.append("\"workspaceId\":" + getWorkspaceId() + ","); - stringBuilder.append("\"updateDate\":\"" + getUpdateDateStr() + "\","); - stringBuilder.append("\"projectId\":" + getProjectId() + "}"); - return stringBuilder.toString(); - } - - public String getUpdateDateStr() { - return getUpdateDate() == null ? "" : DateUtils.TIME_FORMAT.format(getUpdateDate()); - } -} diff --git a/src/com/taobao/rigel/rap/workspace/bo/Workspace.java b/src/com/taobao/rigel/rap/workspace/bo/Workspace.java deleted file mode 100644 index 85ae62c87..000000000 --- a/src/com/taobao/rigel/rap/workspace/bo/Workspace.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.taobao.rigel.rap.workspace.bo; - -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.project.bo.Project; - -public class Workspace implements java.io.Serializable { - - private static final long serialVersionUID = 1L; - public enum ModeType {VSS, SVN}; - private int id; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public int getModeInt() { - return project.getWorkspaceModeInt(); - } - - public ModeType getModeType() { - return project.getWorkspaceMode(); - } - - private Project project; - - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - - private User user; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - private Date createDate; - - public Date getCreateDate() { - return createDate; - } - - public void setCreateDate(Date createDate) { - this.createDate = createDate; - } - - private Date updateDate; - - public Date getUpdateDate() { - return updateDate; - } - - public void setUpdateDate(Date updateDate) { - this.updateDate = updateDate; - } - - private Set saveList; - - public Set getSaveList() { - return saveList; - } - - public void setSaveList(Set saveList) { - this.saveList = saveList; - } - - private String projectData; - - public String getProjectData() { - return projectData; - } - - public void setProjectData(String projectData) { - this.projectData = projectData; - } - - private String projectDataOriginal; - - public String getProjectDataOriginal() { - return projectDataOriginal; - } - - public void setProjectDataOriginal(String projectDataOriginal) { - this.projectDataOriginal = projectDataOriginal; - } - - public String toString() { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\"projectData\":" + getProject().getProjectData() + ","); - stringBuilder.append("\"checkList\":["); - List checkList = getProject().getCheckInListOrdered(); - if (checkList != null) { - Iterator iterator = checkList.iterator(); - while(iterator.hasNext()) { - stringBuilder.append(iterator.next().toString()); - if (iterator.hasNext()) { - stringBuilder.append(", "); - } - } - } - stringBuilder.append("],"); - stringBuilder.append("\"saveList\":["); - if (getSaveList() != null) { - Iterator iterator = getSaveList().iterator(); - while(iterator.hasNext()) { - stringBuilder.append(iterator.next()); - if (iterator.hasNext()) { - stringBuilder.append(", "); - } - } - } - stringBuilder.append("]}"); - return stringBuilder.toString(); - } -} diff --git a/src/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java b/src/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java deleted file mode 100644 index c5cd105ad..000000000 --- a/src/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.taobao.rigel.rap.workspace.dao; -import java.util.Set; - -import com.taobao.rigel.rap.workspace.bo.CheckIn; -import com.taobao.rigel.rap.workspace.bo.Save; -import com.taobao.rigel.rap.workspace.bo.Workspace; -public interface WorkspaceDao { - - Workspace getWorkspace(int projectId, long userId); - - int updateSave(Save save); - - Save getSave(int id); - - void updateWorkspace(Workspace workspace); - - Workspace getWorkspace(int id); - - Set getSaveList(int workspaceId); - - void removeSave(int id); - - void addCheckIn(CheckIn checkIn); - - CheckIn getVersion(int versionId); - - void prepareForVersionSwitch(CheckIn check); -} diff --git a/src/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java b/src/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java deleted file mode 100644 index 1e99e946b..000000000 --- a/src/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.taobao.rigel.rap.workspace.dao.impl; - -import java.util.Date; -import java.util.Iterator; -import java.util.Set; - -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.Session; -import org.springframework.orm.hibernate3.support.HibernateDaoSupport; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.account.dao.AccountDao; -import com.taobao.rigel.rap.project.bo.Module; -import com.taobao.rigel.rap.project.bo.Project; -import com.taobao.rigel.rap.project.dao.ProjectDao; -import com.taobao.rigel.rap.workspace.bo.CheckIn; -import com.taobao.rigel.rap.workspace.bo.Save; -import com.taobao.rigel.rap.workspace.bo.Workspace; -import com.taobao.rigel.rap.workspace.dao.WorkspaceDao; - -public class WorkspaceDaoImpl extends HibernateDaoSupport implements WorkspaceDao { - - private AccountDao accountDao; - - public AccountDao getAccountDao() { - return accountDao; - } - - public void setAccountDao(AccountDao accountDao) { - this.accountDao = accountDao; - } - - private ProjectDao projectDao; - - public ProjectDao getProjectDao() { - return projectDao; - } - - public void setProjectDao(ProjectDao projectDao) { - this.projectDao = projectDao; - } - - @Override - public Workspace getWorkspace(int projectId, long userId) throws HibernateException { - Session session = getSession(); - Query q = session.createQuery("from Workspace where user.id = :userId and project.id = :projectId"); - q.setInteger("projectId", projectId); - q.setLong("userId", userId); - Workspace workspace = (Workspace) q.uniqueResult(); - if (workspace == null) { - return addWorkspace(projectId, userId); - } else { - return workspace; - } - } - - private Workspace addWorkspace(int projectId, long userId) { - Session session = getSession(); - Project project = (Project)session.get(Project.class, projectId); - if (project == null) { - throw new RuntimeException("project you requested doesn't exist."); - } - Workspace workspace = new Workspace(); - workspace.setUser((User)session.load(User.class, userId)); - workspace.setProject(project); - workspace.setProjectData(project.toString(Project.toStringType.TO_PARAMETER)); - workspace.setProjectDataOriginal(workspace.getProjectData()); - workspace.setUpdateDate(new Date()); - int id = (Integer)session.save(workspace); - return getWorkspace(id); - } - - @Override - public int updateSave(Save save) { - save.setUpdateDate(new Date()); - Integer id = (Integer)getSession().save(save); - return id; - } - - @Override - public Save getSave(int id) { - Session session = getSession(); - Save save = (Save) session.load(Save.class, id); - return save; - } - - @Override - public void updateWorkspace(Workspace workspace) { - workspace.setUpdateDate(new Date()); - getSession().save(workspace); - } - - @Override - public Workspace getWorkspace(int id) { - Session session = getSession(); - Workspace workspace = (Workspace) session.load(Workspace.class, id); - return workspace; - } - - @Override - public Set getSaveList(int workspaceId) { - return getWorkspace(workspaceId).getSaveList(); - } - - @Override - public void removeSave(int id) { - Session session = getSession(); - Save save = (Save) session.load(Save.class, id); - session.delete(save); - } - - @Override - public void addCheckIn(CheckIn checkIn) { - getSession().save(checkIn); - } - - @Override - public CheckIn getVersion(int versionId) { - return (CheckIn) getSession().load(CheckIn.class, versionId); - } - - @Override - public void prepareForVersionSwitch(CheckIn check) { - Session session = getSession(); - Project project = check.getProject(); - Iterator iterator = project.getModuleList().iterator(); - while(iterator.hasNext()) { - Module next = iterator.next(); - session.delete(next); - } - project.getModuleList().clear(); - } - -} diff --git a/src/com/taobao/rigel/rap/workspace/mapping/CheckIn.hbm.xml b/src/com/taobao/rigel/rap/workspace/mapping/CheckIn.hbm.xml deleted file mode 100644 index 53f9f45d6..000000000 --- a/src/com/taobao/rigel/rap/workspace/mapping/CheckIn.hbm.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/workspace/mapping/Save.hbm.xml b/src/com/taobao/rigel/rap/workspace/mapping/Save.hbm.xml deleted file mode 100644 index 7b592cdbf..000000000 --- a/src/com/taobao/rigel/rap/workspace/mapping/Save.hbm.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/workspace/mapping/Workspace.hbm.xml b/src/com/taobao/rigel/rap/workspace/mapping/Workspace.hbm.xml deleted file mode 100644 index 6e69f215e..000000000 --- a/src/com/taobao/rigel/rap/workspace/mapping/Workspace.hbm.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/com/taobao/rigel/rap/workspace/service/WorkspaceMgr.java b/src/com/taobao/rigel/rap/workspace/service/WorkspaceMgr.java deleted file mode 100644 index b5e293915..000000000 --- a/src/com/taobao/rigel/rap/workspace/service/WorkspaceMgr.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.taobao.rigel.rap.workspace.service; - -import java.util.Set; - -import com.taobao.rigel.rap.workspace.bo.CheckIn; -import com.taobao.rigel.rap.workspace.bo.Save; -import com.taobao.rigel.rap.workspace.bo.Workspace; - -public interface WorkspaceMgr { - - /** - * get workspace obj - * - * @param projectId - * @param userId - * @return - */ - Workspace getWorkspace(int projectId, long userId); - - /** - * update save - * - * @param save - * @return - */ - int updateSave(Save save); - - /** - * get one save - * - * @param id - * @return - */ - Save getSave(int id); - - /** - * update workspace - * - * @param workspace - */ - void updateWorkspace(Workspace workspace); - - /** - * get workspace - * - * @param id - * @return - */ - Workspace getWorkspace(int id); - - /** - * get save list - * - * @param workspaceId - * @return - */ - Set getSaveList(int workspaceId); - - /** - * remove save - * - * @param id - */ - void removeSave(int id); - - /*** - * workspace check out - * - * @param jsonList - * [0]:projectData, [1]: projectDataOriginal - * @param userId - * @param projectId - * @return - */ - String checkOut(String[] jsonList, long userId, int projectId); - - /*** - * workspace check in - * - * @param jsonList - * [0]:projectData [1]: projectDataOriginal - * @param userId - * @param projectId - * @return - */ - String checkIn(String[] jsonList, long userId, int projectId); - - /** - * add new check in log - * - * @param checkIn - */ - void addCheckIn(CheckIn checkIn); - - /** - * get {@link CheckIn} obj - * - * @param versionId - * @return - */ - CheckIn getVersion(int versionId); - - /** - * do sth. preparing for version switch - * - * @param check - */ - void prepareForVersionSwitch(CheckIn check); -} diff --git a/src/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java b/src/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java deleted file mode 100644 index 2f1eea7c9..000000000 --- a/src/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java +++ /dev/null @@ -1,677 +0,0 @@ -package com.taobao.rigel.rap.workspace.service.impl; - -import java.util.Iterator; -import java.util.Set; - -import com.taobao.rigel.rap.project.bo.Action; -import com.taobao.rigel.rap.project.bo.Module; -import com.taobao.rigel.rap.project.bo.Page; -import com.taobao.rigel.rap.project.bo.Parameter; -import com.taobao.rigel.rap.project.bo.Project; -import com.taobao.rigel.rap.project.dao.ProjectDao; -import com.taobao.rigel.rap.workspace.bo.CheckIn; -import com.taobao.rigel.rap.workspace.bo.Save; -import com.taobao.rigel.rap.workspace.bo.Workspace; -import com.taobao.rigel.rap.workspace.dao.WorkspaceDao; -import com.taobao.rigel.rap.workspace.service.WorkspaceMgr; -import com.google.gson.Gson; - -public class WorkspaceMgrImpl implements WorkspaceMgr { - - private WorkspaceDao workspaceDao; - - public WorkspaceDao getWorkspaceDao() { - return this.workspaceDao; - } - - public void setWorkspaceDao(WorkspaceDao workspaceDao) { - this.workspaceDao = workspaceDao; - } - - private ProjectDao projectDao; - - public ProjectDao getProjectDao() { - return projectDao; - } - - public void setProjectDao(ProjectDao projectDao) { - this.projectDao = projectDao; - } - - @Override - public Workspace getWorkspace(int projectId, long userId) { - Workspace workspace = workspaceDao.getWorkspace(projectId, userId); - return workspace; - } - - @Override - public int updateSave(Save save) { - return workspaceDao.updateSave(save); - } - - @Override - public Save getSave(int id) { - return workspaceDao.getSave(id); - } - - @Override - public void updateWorkspace(Workspace workspace) { - workspaceDao.updateWorkspace(workspace); - - } - - @Override - public Workspace getWorkspace(int id) { - return workspaceDao.getWorkspace(id); - } - - @Override - public Set getSaveList(int workspaceId) { - return workspaceDao.getSaveList(workspaceId); - } - - @Override - public void removeSave(int id) { - workspaceDao.removeSave(id); - } - - @Override - public String checkIn(String [] jsonList, long userId, int projectId) { - //[TODO] does user has access? - StringBuilder log = new StringBuilder(); - Project projectClient, projectOriginal, projectServer; - Gson gson = new Gson(); - // get server workspace - projectServer = projectDao.getProject(projectId); - // parse client workspace - projectClient = gson.fromJson(jsonList[0], Project.class); - // parse original client workspace - projectOriginal = gson.fromJson(jsonList[1], Project.class); - - /** - * start processing ... - * update a(client) => b(server) compared with o (Original) - */ - - // search moduleList - Iterator moduleIterator = projectClient.getModuleList().iterator(); - while (moduleIterator.hasNext()) { - Module moduleA = moduleIterator.next(); - // scan module - Module moduleB = findModule(projectServer, moduleA.getId()); - if (moduleB == null) { - log.append(logTemplate(moduleA.getId(), "module", "add", null, null, null)); - projectServer.getModuleList().add(moduleA); - continue; - } - Module moduleO = findModule(projectOriginal, moduleA.getId()); - if (!moduleA.getName().equals(moduleB.getName())) { - boolean aChanged = (!moduleA.getName().equals(moduleO.getName())); - boolean bChanged = (!moduleB.getName().equals(moduleO.getName())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(moduleB.getId(), "module", "update", - moduleA.getName(), moduleB.getName(), "name")); - moduleB.setName(moduleA.getName()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!moduleA.getIntroduction().equals(moduleB.getIntroduction())) { - boolean aChanged = (!moduleA.getIntroduction().equals(moduleO.getIntroduction())); - boolean bChanged = (!moduleB.getIntroduction().equals(moduleO.getIntroduction())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(moduleB.getId(), "module", "update", - moduleA.getIntroduction(), moduleB.getIntroduction(), "introduction")); - moduleB.setIntroduction(moduleA.getIntroduction()); - } else if (!aChanged && bChanged){ - // ignore - } - } - // search pageList - Iterator pageIterator = moduleA.getPageList().iterator(); - while (pageIterator.hasNext()) { - Page pageA = pageIterator.next(); - // scan page - Page pageB = findPage(projectServer, pageA.getId()); - if (pageB == null) { - moduleB.getPageList().add(pageA); - continue; - } - Page pageO = findPage(projectOriginal, pageA.getId()); - if (!pageA.getName().equals(pageB.getName())) { - boolean aChanged = (!pageA.getName().equals(pageO.getName())); - boolean bChanged = (!pageB.getName().equals(pageO.getName())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(pageB.getId(), "page", "update", - pageA.getName(), pageB.getName(), "name")); - pageB.setName(pageA.getName()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!pageA.getIntroduction().equals(pageB.getIntroduction())) { - boolean aChanged = (!pageA.getIntroduction().equals(pageO.getIntroduction())); - boolean bChanged = (!pageB.getIntroduction().equals(pageO.getIntroduction())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(pageB.getId(), "page", "update", - pageA.getIntroduction(), pageB.getIntroduction(), "introduction")); - pageB.setIntroduction(pageA.getIntroduction()); - } else if (!aChanged && bChanged){ - // ignore - } - } - // search actionList - Iterator actionIterator = pageA.getActionList().iterator(); - while (actionIterator.hasNext()) { - Action actionA = actionIterator.next(); - // scan action - Action actionB = findAction(projectServer, actionA.getId()); - if (actionB == null) { - pageB.getActionList().add(actionA); - continue; - } - - Action actionO = findAction(projectOriginal, actionA.getId()); - if (!actionA.getName().equals(actionB.getName())) { - boolean aChanged = (!actionA.getName().equals(actionO.getName())); - boolean bChanged = (!actionB.getName().equals(actionO.getName())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getName(), actionB.getName(), "name")); - actionB.setName(actionA.getName()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!actionA.getDescription().equals(actionB.getDescription())) { - boolean aChanged = (!actionA.getDescription().equals(actionO.getDescription())); - boolean bChanged = (!actionB.getDescription().equals(actionO.getDescription())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getDescription(), actionB.getDescription(), "description")); - actionB.setDescription(actionA.getDescription()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!actionA.getRequestType().equals(actionB.getRequestType())) { - boolean aChanged = (!actionA.getRequestType().equals(actionO.getRequestType())); - boolean bChanged = (!actionB.getRequestType().equals(actionO.getRequestType())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getRequestType(), actionB.getRequestType(), "requestType")); - actionB.setRequestType(actionA.getRequestType()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!actionA.getRequestUrl().equals(actionB.getRequestUrl())) { - boolean aChanged = (!actionA.getRequestUrl().equals(actionO.getRequestUrl())); - boolean bChanged = (!actionB.getRequestUrl().equals(actionO.getRequestUrl())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getRequestUrl(), actionB.getRequestUrl(), "requestUrl")); - actionB.setRequestUrl(actionA.getRequestUrl()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!actionA.getResponseTemplate().equals(actionB.getResponseTemplate())) { - boolean aChanged = (!actionA.getResponseTemplate().equals(actionO.getResponseTemplate())); - boolean bChanged = (!actionB.getResponseTemplate().equals(actionO.getResponseTemplate())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getResponseTemplate(), actionB.getResponseTemplate(), "responseTemplate")); - actionB.setResponseTemplate(actionA.getResponseTemplate()); - } else if (!aChanged && bChanged){ - // ignore - } - } - // search requestParameterList - Iterator requestParameterIterator = actionA.getRequestParameterList().iterator(); - while (requestParameterIterator.hasNext()) { - Parameter parameterA = requestParameterIterator.next(); - // scan request parameter - Parameter parameterB = findParameter(projectServer, parameterA.getId(), true); - if (parameterB == null) { - actionB.getRequestParameterList().add(parameterA); - continue; - } - Parameter parameterO = findParameter(projectOriginal, parameterA.getId(), true); - processParameter(parameterA, parameterB, parameterO, log); - } - - // search responseParameterList - Iterator responseParameterIterator = actionA.getResponseParameterList().iterator(); - while (responseParameterIterator.hasNext()) { - Parameter parameterA = responseParameterIterator.next(); - // scan response parameter - Parameter parameterB = findParameter(projectClient, parameterA.getId(), false); - if (parameterB == null) { - actionB.getResponseParameterList().add(parameterA); - continue; - } - Parameter parameterO = findParameter(projectOriginal, parameterA.getId(), false); - processParameter(parameterA, parameterB, parameterO, log); - } - } - } - - } - projectDao.updateProject(projectServer); - projectServer = projectDao.getProject(projectId); - return "{\"projectData\":" + projectServer.toString() + ", \"log\":\"" + log - + "\", \"projectDataOriginal\":" + projectServer.toString()+"}"; - } - - @Override - public String checkOut(String [] jsonList, long userId, int projectId) { - //[TODO] does user has access? - - StringBuilder log = new StringBuilder(); - Project projectClient, projectOriginal, projectServer; - Gson gson = new Gson(); - // get server workspace - projectServer = projectDao.getProject(projectId); - // parse client workspace - projectClient = gson.fromJson(jsonList[0], Project.class); - // parse original client workspace - projectOriginal = gson.fromJson(jsonList[1], Project.class); - - /** - * start processing ... - * update a(Server) => b(client) compared with o (Original) - */ - - // search moduleList - Iterator moduleIterator = projectServer.getModuleList().iterator(); - while (moduleIterator.hasNext()) { - Module moduleA = moduleIterator.next(); - // scan module - Module moduleB = findModule(projectClient, moduleA.getId()); - if (moduleB == null) { - log.append(logTemplate(moduleA.getId(), "module", "add", null, null, null)); - projectClient.getModuleList().add(moduleA); - continue; - } - Module moduleO = findModule(projectOriginal, moduleA.getId()); - if (!moduleA.getName().equals(moduleB.getName())) { - boolean aChanged = (!moduleA.getName().equals(moduleO.getName())); - boolean bChanged = (!moduleB.getName().equals(moduleO.getName())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(moduleB.getId(), "module", "update", - moduleA.getName(), moduleB.getName(), "name")); - moduleB.setName(moduleA.getName()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!moduleA.getIntroduction().equals(moduleB.getIntroduction())) { - boolean aChanged = (!moduleA.getIntroduction().equals(moduleO.getIntroduction())); - boolean bChanged = (!moduleB.getIntroduction().equals(moduleO.getIntroduction())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(moduleB.getId(), "module", "update", - moduleA.getIntroduction(), moduleB.getIntroduction(), "introduction")); - moduleB.setIntroduction(moduleA.getIntroduction()); - } else if (!aChanged && bChanged){ - // ignore - } - } - // search pageList - Iterator pageIterator = moduleA.getPageList().iterator(); - while (pageIterator.hasNext()) { - Page pageA = pageIterator.next(); - // scan page - Page pageB = findPage(projectClient, pageA.getId()); - if (pageB == null) { - moduleB.getPageList().add(pageA); - continue; - } - Page pageO = findPage(projectOriginal, pageA.getId()); - if (!pageA.getName().equals(pageB.getName())) { - boolean aChanged = (!pageA.getName().equals(pageO.getName())); - boolean bChanged = (!pageB.getName().equals(pageO.getName())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(pageB.getId(), "page", "update", - pageA.getName(), pageB.getName(), "name")); - pageB.setName(pageA.getName()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!pageA.getIntroduction().equals(pageB.getIntroduction())) { - boolean aChanged = (!pageA.getIntroduction().equals(pageO.getIntroduction())); - boolean bChanged = (!pageB.getIntroduction().equals(pageO.getIntroduction())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(pageB.getId(), "page", "update", - pageA.getIntroduction(), pageB.getIntroduction(), "introduction")); - pageB.setIntroduction(pageA.getIntroduction()); - } else if (!aChanged && bChanged){ - // ignore - } - } - // search actionList - Iterator actionIterator = pageA.getActionList().iterator(); - while (actionIterator.hasNext()) { - Action actionA = actionIterator.next(); - // scan action - Action actionB = findAction(projectClient, actionA.getId()); - if (actionB == null) { - pageB.getActionList().add(actionA); - continue; - } - - Action actionO = findAction(projectOriginal, actionA.getId()); - if (!actionA.getName().equals(actionB.getName())) { - boolean aChanged = (!actionA.getName().equals(actionO.getName())); - boolean bChanged = (!actionB.getName().equals(actionO.getName())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getName(), actionB.getName(), "name")); - actionB.setName(actionA.getName()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!actionA.getDescription().equals(actionB.getDescription())) { - boolean aChanged = (!actionA.getDescription().equals(actionO.getDescription())); - boolean bChanged = (!actionB.getDescription().equals(actionO.getDescription())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getDescription(), actionB.getDescription(), "description")); - actionB.setDescription(actionA.getDescription()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!actionA.getRequestType().equals(actionB.getRequestType())) { - boolean aChanged = (!actionA.getRequestType().equals(actionO.getRequestType())); - boolean bChanged = (!actionB.getRequestType().equals(actionO.getRequestType())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getRequestType(), actionB.getRequestType(), "requestType")); - actionB.setRequestType(actionA.getRequestType()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!actionA.getRequestUrl().equals(actionB.getRequestUrl())) { - boolean aChanged = (!actionA.getRequestUrl().equals(actionO.getRequestUrl())); - boolean bChanged = (!actionB.getRequestUrl().equals(actionO.getRequestUrl())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getRequestUrl(), actionB.getRequestUrl(), "requestUrl")); - actionB.setRequestUrl(actionA.getRequestUrl()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!actionA.getResponseTemplate().equals(actionB.getResponseTemplate())) { - boolean aChanged = (!actionA.getResponseTemplate().equals(actionO.getResponseTemplate())); - boolean bChanged = (!actionB.getResponseTemplate().equals(actionO.getResponseTemplate())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(actionB.getId(), "action", "update", - actionA.getResponseTemplate(), actionB.getResponseTemplate(), "responseTemplate")); - actionB.setResponseTemplate(actionA.getResponseTemplate()); - } else if (!aChanged && bChanged){ - // ignore - } - } - // search requestParameterList - Iterator requestParameterIterator = actionA.getRequestParameterList().iterator(); - while (requestParameterIterator.hasNext()) { - Parameter parameterA = requestParameterIterator.next(); - // scan request parameter - Parameter parameterB = findParameter(projectClient, parameterA.getId(), true); - if (parameterB == null) { - actionB.getRequestParameterList().add(parameterA); - continue; - } - Parameter parameterO = findParameter(projectOriginal, parameterA.getId(), true); - processParameter(parameterA, parameterB, parameterO, log); - } - - // search responseParameterList - Iterator responseParameterIterator = actionA.getResponseParameterList().iterator(); - while (responseParameterIterator.hasNext()) { - Parameter parameterA = responseParameterIterator.next(); - // scan response parameter - Parameter parameterB = findParameter(projectClient, parameterA.getId(), false); - if (parameterB == null) { - actionB.getResponseParameterList().add(parameterA); - continue; - } - Parameter parameterO = findParameter(projectOriginal, parameterA.getId(), false); - processParameter(parameterA, parameterB, parameterO, log); - } - } - } - - } - return "{\"projectData\":" + projectClient.toString() + ", \"log\":\"" - + log + "\", \"projectDataOriginal\":" + projectClient.toString() + "}"; - } - - - private void processParameter(Parameter parameterA, Parameter parameterB, - Parameter parameterO, StringBuilder log) { - if (!parameterA.getName().equals(parameterB.getName())) { - boolean aChanged = (!parameterA.getName().equals(parameterO.getName())); - boolean bChanged = (!parameterB.getName().equals(parameterO.getName())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(parameterB.getId(), "parameter", "update", - parameterA.getName(), parameterB.getName(), "name")); - parameterB.setName(parameterA.getName()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!parameterA.getDataType().equals(parameterB.getDataType())) { - boolean aChanged = (!parameterA.getDataType().equals(parameterO.getDataType())); - boolean bChanged = (!parameterB.getDataType().equals(parameterO.getDataType())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(parameterB.getId(), "parameter", "update", - parameterA.getDataType(), parameterB.getDataType(), "dataType")); - parameterB.setDataType(parameterA.getDataType()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!parameterA.getIdentifier().equals(parameterB.getIdentifier())) { - boolean aChanged = (!parameterA.getIdentifier().equals(parameterO.getIdentifier())); - boolean bChanged = (!parameterB.getIdentifier().equals(parameterO.getIdentifier())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(parameterB.getId(), "parameter", "update", - parameterA.getIdentifier(), parameterB.getIdentifier(), "identifier")); - parameterB.setIdentifier(parameterA.getIdentifier()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!parameterA.getRemark().equals(parameterB.getRemark())) { - boolean aChanged = (!parameterA.getRemark().equals(parameterO.getRemark())); - boolean bChanged = (!parameterB.getRemark().equals(parameterO.getRemark())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(parameterB.getId(), "parameter", "update", - parameterA.getRemark(), parameterB.getRemark(), "remark")); - parameterB.setRemark(parameterA.getRemark()); - } else if (!aChanged && bChanged){ - // ignore - } - } - if (!parameterA.getValidator().equals(parameterB.getValidator())) { - boolean aChanged = (!parameterA.getValidator().equals(parameterO.getValidator())); - boolean bChanged = (!parameterB.getValidator().equals(parameterO.getValidator())); - - if (aChanged && bChanged) { - // [TODO] conflict! - } else if (aChanged && !bChanged) { - // update - log.append(logTemplate(parameterB.getId(), "parameter", "update", - parameterA.getValidator(), parameterB.getValidator(), "validator")); - parameterB.setValidator(parameterA.getValidator()); - } else if (!aChanged && bChanged){ - // ignore - } - } - } - - private Module findModule(Project p, int moduleId) { - for (Module i : p.getModuleList()) { - if (i.getId() == moduleId) - return i; - } - return null; - } - - private Page findPage(Project p, int pageId) { - for (Module module : p.getModuleList()) { - for (Page page : module.getPageList()) { - if (page.getId() == pageId) - return page; - } - } - return null; - } - - private Action findAction(Project p, int actionId) { - for (Module module : p.getModuleList()) { - for (Page page : module.getPageList()) { - for (Action action : page.getActionList()) { - if (action.getId() == actionId) - return action; - } - } - } - return null; - } - - private Parameter findParameter(Project p, int parameterId, boolean isRequestType) { - for (Module module : p.getModuleList()) { - for (Page page : module.getPageList()) { - for (Action action : page.getActionList()) { - for (Parameter parameter : (isRequestType ? - action.getRequestParameterList() : action.getResponseParameterList())) { - if (parameter.getId() == parameterId) - return parameter; - } - } - } - } - return null; - } - - - private String logTemplate(int objectId, String className, - String operationName, String newValue, String oldValue, String property) { - return operationName == "add" ? - "
" + operationName + " " + className + " [" + objectId - + "]
" - :"
" + operationName + " " + className + " [" + objectId - + "]." + property + " from [" + oldValue + "] to [" + newValue + "]
"; - } - - @Override - public void addCheckIn(CheckIn checkIn) { - workspaceDao.addCheckIn(checkIn); - } - - @Override - public CheckIn getVersion(int versionId) { - return workspaceDao.getVersion(versionId); - } - - @Override - public void prepareForVersionSwitch(CheckIn check) { - workspaceDao.prepareForVersionSwitch(check); - - } -} diff --git a/src/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java b/src/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java deleted file mode 100644 index ad1c80090..000000000 --- a/src/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java +++ /dev/null @@ -1,532 +0,0 @@ -package com.taobao.rigel.rap.workspace.web.action; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.StringWriter; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine; -import org.apache.velocity.exception.MethodInvocationException; -import org.apache.velocity.exception.ParseErrorException; -import org.apache.velocity.exception.ResourceNotFoundException; - -import com.taobao.rigel.rap.account.bo.User; -import com.taobao.rigel.rap.common.ActionBase; -import com.taobao.rigel.rap.common.ContextManager; -import com.taobao.rigel.rap.common.MapUtils; -import com.taobao.rigel.rap.project.bo.Module; -import com.taobao.rigel.rap.project.bo.Project; -import com.taobao.rigel.rap.project.service.ProjectMgr; -import com.taobao.rigel.rap.workspace.bo.CheckIn; -import com.taobao.rigel.rap.workspace.bo.Save; -import com.taobao.rigel.rap.workspace.bo.Workspace; -import com.taobao.rigel.rap.workspace.service.WorkspaceMgr; - -public class WorkspaceAction extends ActionBase { - - private static final long serialVersionUID = 1L; - - private boolean mock; - - private int actionId; - - public int getActionId() { - return actionId; - } - - public void setActionId(int actionId) { - this.actionId = actionId; - } - - public boolean isMock() { - return mock; - } - - public void setMock(boolean mock) { - this.mock = mock; - } - - private int id; - - public int getId() { - return this.id; - } - - public void setId(int id) { - this.id = id; - } - - private String workspaceJsonString; - - public String getWorkspaceJsonString() { - return this.workspaceJsonString; - } - - public void setWorkspaceJsonString(String workspaceJsonString) { - this.workspaceJsonString = workspaceJsonString; - } - - private Workspace workspace; - - public Workspace getWorkspace() { - return this.workspace; - } - - public void setWorkspace(Workspace workspace) { - this.workspace = workspace; - } - - public Module module; - - public Module getModule() { - return this.module; - } - - public void setModule(Module module) { - this.module = module; - } - - private VelocityEngine velocityEngine; - - public VelocityEngine getVelocityEngine() { - return velocityEngine; - } - - public void setVelocityEngine(VelocityEngine velocityEngine) { - this.velocityEngine = velocityEngine; - } - - private int projectId; - - private Project project; - - public Project getProject() { - return project; - } - - public void setProject(Project project) { - this.project = project; - } - - public int getProjectId() { - return this.projectId; - } - - public void setProjectId(int projectId) { - this.projectId = projectId; - } - - private String projectData; - - public String getProjectData() { - return projectData; - } - - public void setProjectData(String projectData) { - this.projectData = projectData; - } - - private String projectDataOriginal; - - public String getProjectDataOriginal() { - return projectDataOriginal; - } - - public void setProjectDataOriginal(String projectDataOriginal) { - this.projectDataOriginal = projectDataOriginal; - } - - private String saveListJson; - - public String getSaveListJson() { - return saveListJson; - } - - public void setSaveListJson(String saveListJson) { - this.saveListJson = saveListJson; - } - - private int saveId = -1; - - public int getSaveId() { - return saveId; - } - - public void setSaveId(int saveId) { - this.saveId = saveId; - } - - private Save save; - - public Save getSave() { - return save; - } - - public void setSave(Save save) { - this.save = save; - } - - private int versionId; - - public int getVersionId() { - return versionId; - } - - public void setVersionId(int versionId) { - this.versionId = versionId; - } - - private String deletedObjectListData; - - public String getDeletedObjectListData() { - return deletedObjectListData; - } - - public void setDeletedObjectListData(String deletedObjectListData) { - this.deletedObjectListData = deletedObjectListData; - } - - private String tag; - - public String getTag() { - return tag; - } - - public void setTag(String tag) { - this.tag = tag; - } - - /** - * from 1 to 4, version position - */ - private int versionPosition; - - public int getVersionPosition() { - return versionPosition; - } - - public void setVersionPosition(int versionPosition) { - this.versionPosition = versionPosition; - } - - private String description; - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - private boolean isLocked; - - public boolean getIsLocked() { - return isLocked; - } - - public void setIsLocked(boolean isLocked) { - this.isLocked = isLocked; - } - - public String myWorkspace() { - if (!isUserLogined()) { - plsLogin(); - setRelativeReturnUrl("/workspace/myWorkspace.action?projectId=" - + projectId); - return LOGIN; - } - Workspace workspace = new Workspace(); - workspace.setProject(projectMgr.getProject(getProjectId())); - setWorkspaceJsonString(workspace.toString()); - setWorkspace(workspace); - return SUCCESS; - } - - private InputStream fileInputStream; - - /** - * save workspace if this.saveId == -1(default), it's a new save and needs - * projectId and id(workspaceId). else, just need saveId only to cover the - * existed one. all conditions parameters: projectData - * - * @return - */ - /* - * public String updateSave() { int id = getSaveId(); Save save = null; if - * (id == -1) { save = new Save(); save.setProjectId(getProjectId()); - * save.setWorkspaceId(getId()); } else { save = - * workspaceMgr.getSave(getSaveId()); } - * save.setProjectData(getProjectData()); id = - * workspaceMgr.updateSave(save); - * - * // after update the save, return saveList json string - * setupSaveListJson(); return SUCCESS; } - */ - - /* - * private void setupSaveListJson() { Set saveList = - * workspaceMgr.getSaveList(getId()); StringBuilder stringBuilder = new - * StringBuilder(); stringBuilder.append("["); Iterator iterator = - * saveList.iterator(); while (iterator.hasNext()) { - * stringBuilder.append(iterator.next()); if (iterator.hasNext()) { - * stringBuilder.append(","); } } stringBuilder.append("]"); - * setSaveListJson(stringBuilder.toString()); } - */ - - /** - * delete save - * - * @return - */ - /* - * public String removeSave() { workspaceMgr.removeSave(getSaveId()); - * setupSaveListJson(); return SUCCESS; } - */ - - /** - * load save, saveId must be significant, or operation failed - * - * @return the save object loaded - */ - /* - * public String querySave() { - * setJson(workspaceMgr.getSave(getSaveId()).getProjectData()); return - * SUCCESS; } - */ - - public InputStream getFileInputStream() { - return fileInputStream; - } - - /** - * ` save the current workspace - * - * @return - */ - /* - * public String updateCurrentSave() { Workspace workspace = - * workspaceMgr.getWorkspace(getId()); - * workspace.setProjectData(getProjectData()); - * workspaceMgr.updateWorkspace(workspace); return SUCCESS; } - */ - - private WorkspaceMgr workspaceMgr; - - public WorkspaceMgr getworkspaceMgr() { - return workspaceMgr; - } - - public void setWorkspaceMgr(WorkspaceMgr workspaceMgr) { - this.workspaceMgr = workspaceMgr; - } - - private ProjectMgr projectMgr; - - public ProjectMgr projectMgr() { - return this.projectMgr; - } - - public void setProjectMgr(ProjectMgr projectMgr) { - this.projectMgr = projectMgr; - } - - public String ping() { - setJson("{\"isOk\":true}"); - return SUCCESS; - } - - public String queryVersion() { - setJson(workspaceMgr.getVersion(getVersionId()).toString( - CheckIn.ToStringType.COMPLETED)); - return SUCCESS; - } - - public String switchVersion() { - CheckIn check = workspaceMgr.getVersion(getVersionId()); - workspaceMgr.prepareForVersionSwitch(check); - projectMgr.updateProject(check.getProject().getId(), - check.getProjectData(), "[]"); - Project project = projectMgr.getProject(check.getProject().getId()); - String projectData = project - .toString(Project.toStringType.TO_PARAMETER); - setJson("{\"projectData\":" + projectData + ", \"isOk\":true}"); - project.setProjectData(projectData); - projectMgr.updateProject(project); - return SUCCESS; - } - - public String checkIn() throws Exception { - User curUser = getCurUser(); - if (curUser == null) { - setErrMsg(LOGIN_WARN_MSG); - setIsOk(false); - return JSON_ERROR; - } - - // update project - projectMgr.updateProject(getId(), getProjectData(), - getDeletedObjectListData()); - Project project = projectMgr.getProject(getId()); - - // generate one check-in of VSS mode submit - CheckIn checkIn = new CheckIn(); - checkIn.setCreateDate(new Date()); - checkIn.setDescription(getDescription()); - checkIn.setProject(project); - checkIn.setProjectData(project - .toString(Project.toStringType.TO_PARAMETER)); - checkIn.setTag(getTag()); - checkIn.setUser(curUser); - checkIn.setVersion(project.getVersion()); - checkIn.versionUpgrade(getVersionPosition()); - - // after version upgrade, set back to project - project.setVersion(checkIn.getVersion()); - checkIn.setWorkspaceMode(Workspace.ModeType.VSS); - workspaceMgr.addCheckIn(checkIn); - - // calculate JSON string for client - project = projectMgr.getProject(getId()); - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("{\"projectData\":" + checkIn.getProjectData()); - stringBuilder.append(",\"checkList\":["); - Iterator iterator = project.getCheckInListOrdered().iterator(); - while (iterator.hasNext()) { - stringBuilder.append(iterator.next()); - if (iterator.hasNext()) { - stringBuilder.append(","); - } - } - stringBuilder.append("],\"isOk\":true}"); - setJson(stringBuilder.toString()); - - // update project data - project.setProjectData(checkIn.getProjectData()); - projectMgr.updateProject(project); - - // unlock the workspace - unlock(); - - return SUCCESS; - } - - @SuppressWarnings({ "rawtypes", "unchecked" }) - public String lock() { - long curUserId = getCurUserId(); - if (curUserId <= 0) { - setIsOk(false); - setErrMsg(LOGIN_WARN_MSG); - return JSON_ERROR; - } - - boolean isOk = false; - if (isLocked(getId())) { - // if the project is locked, find the locker - User user = getLocker(getId()); - if (!user.getAccount().equals(getCurAccount())) { - setJson("{\"isOk\":false, \"errMsg\":\"该项目目前正被" - + user.getName() + "锁定.\"}"); - } else { - // user request lock a locked project - // which is locked by himself, so let him go - isOk = true; - } - - } else { - // else, lock the project, than let him go. - Map app = ContextManager.getApplication(); - if (app.get(ContextManager.KEY_PROJECT_LOCK_LIST) == null) { - app.put(ContextManager.KEY_PROJECT_LOCK_LIST, new HashMap()); - } - Map projectLockList = (Map) app - .get(ContextManager.KEY_PROJECT_LOCK_LIST); - if (projectLockList.get(curUserId) == null) { - projectLockList.put(curUserId, getId()); - //System.out.println("user[" + curUserId + "] locked project["+ getId() + "]"); - } - isOk = true; - } - if (isOk) { - setJson("{\"isOk\":true, \"projectData\":" - + projectMgr.getProject(getId()).getProjectData() + "}"); - } - return SUCCESS; - } - - @SuppressWarnings({ "rawtypes" }) - public String unlock() { - if (isLocked(getId())) { - Map app = ContextManager.getApplication(); - Map projectLockList = (Map) app - .get(ContextManager.KEY_PROJECT_LOCK_LIST); - if (projectLockList == null) - return SUCCESS; - long userId = super.getCurUserId(); - int projectId = (Integer) projectLockList.get(userId); - projectLockList.remove(userId); - System.out.println("user[" + userId + "] unlock project[" - + projectId + "]"); - } - return SUCCESS; - } - - /** - * caution: no authentication so far - * - * @return - * @throws Exception - */ - public String export() throws Exception { - project = projectMgr.getProject(projectId); - velocityEngine.init(); - VelocityContext context = new VelocityContext(); - context.put("project", project); - Template template = null; - try { - template = velocityEngine.getTemplate("resource/export.vm", "UTF8"); - } catch (ResourceNotFoundException rnfe) { - rnfe.printStackTrace(); - } catch (ParseErrorException pee) { - pee.printStackTrace(); - } catch (MethodInvocationException mie) { - mie.printStackTrace(); - } catch (Exception e) { - e.printStackTrace(); - } - StringWriter sw = new StringWriter(); - template.merge(context, sw); - fileInputStream = new ByteArrayInputStream(sw.toString().getBytes( - "UTF8")); - return SUCCESS; - } - - @SuppressWarnings("rawtypes") - private boolean isLocked(int projectId) { - Map app = ContextManager.getApplication(); - Map projectLockList = (Map) app - .get(ContextManager.KEY_PROJECT_LOCK_LIST); - return projectLockList != null - && projectLockList.containsValue(projectId) ? true : false; - } - - @SuppressWarnings("rawtypes") - private User getLocker(int projectId) { - Map app = ContextManager.getApplication(); - Map projectLockList = (Map) app - .get(ContextManager.KEY_PROJECT_LOCK_LIST); - if (projectLockList != null) { - long userId = (Long) MapUtils.getKeyByValue(projectLockList, - projectId); - User user = getAccountMgr().getUser(userId); - return user; - } - return null; - } - -} diff --git a/src/com/taobao/rigel/rap/workspace/web/action/struts.xml b/src/com/taobao/rigel/rap/workspace/web/action/struts.xml deleted file mode 100644 index 7bad05c47..000000000 --- a/src/com/taobao/rigel/rap/workspace/web/action/struts.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - /account/login.vm - /workspace/myWorkspace.vm - - - /bcom/json.cb.vm - - - - /bcom/json.cb.vm - - - /bcom/json.cb.vm - - - - /bcom/json.cb.vm - - - /bcom/json.cb.vm - - - - /bcom/json.cb.vm - - - - attachment;filename=export.doc - application/msword - fileInputStream - 1024 - - - - - diff --git a/src/database/create-procedure.sql b/src/database/create-procedure.sql deleted file mode 100644 index 9ac959a05..000000000 --- a/src/database/create-procedure.sql +++ /dev/null @@ -1,32 +0,0 @@ -/** - * create new user - */ -DELIMITER // -CREATE PROCEDURE sp_create_user ( - IN name varchar(56), - IN account varchar(56), - IN mail varchar(56), - IN role varchar(56) -- fe | rd | qa | pm | admin -) -BEGIN - DECLARE user_id INT; - DECLARE role_id INT; - SET role_id = 5; - INSERT INTO tb_user (account, password, name, email, last_login_date) VALUES (account, '123456', name, mail, NOW()); - SELECT last_insert_id() INTO user_id; - IF role = 'fe' THEN - SET role_id = 5; - ELSEIF role = 'rd' THEN - SET role_id = 4; - ELSEIF role = 'pm' THEN - SET role_id = 3; - ELSEIF role = 'qa' THEN - SET role_id = 6; - ELSEIF role = 'rd' THEN - SET role_id = 4; - ELSEIF role = 'admin' THEN - SET role_id = 2; - END IF; - INSERT INTO tb_role_and_user (user_id, role_id) VALUES (user_id, role_id); -END // -DELIMITER ; \ No newline at end of file diff --git a/src/database/create-table.sql b/src/database/create-table.sql deleted file mode 100644 index 740ada824..000000000 --- a/src/database/create-table.sql +++ /dev/null @@ -1,309 +0,0 @@ -/************************************************** - * * - * account module * - * * - **************************************************/ - - -/** - * user table - */ -CREATE TABLE tb_user -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - account varchar(32) NOT NULL, - password varchar(128) NOT NULL, - name varchar(16) NOT NULL, - email varchar(256) NOT NULL, - create_date timestamp NOT NULL - DEFAULT now(), - is_locked_out int(1) NOT NULL COMMENT 'is the user locked out' - DEFAULT 0, - is_hint_enabled int(1) NOT NULL COMMENT 'is user hint enabled' - DEFAULT 1, - last_login_date datetime NOT NULL, - incorrect_login_attempt int(10) NOT NULL COMMENT 'count of incorrect login attempts, will be set to 0 after any succesful login' - DEFAULT 0 -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * role table - * roles instruction: - * user - every registered shuold have this role - * rd - research and development engineering - * qa - quality engineering - * pm - project manager - * op - operation manager - * admin - administrator - * god - super admin - */ -CREATE TABLE tb_role -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - name varchar(16) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * user role table - */ -CREATE TABLE tb_role_and_user -( - user_id int(10) NOT NULL, - role_id int(10) NOT NULL, - - PRIMARY KEY(user_id, role_id), - FOREIGN KEY(user_id) REFERENCES tb_user(id), - FOREIGN KEY(role_id) REFERENCES tb_role(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - - - -/************************************************** - * * - * project module * - * * - **************************************************/ - - - -/** - * parameter table - */ -CREATE TABLE tb_parameter -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - name varchar(256) NULL, - identifier varchar(256) NULL, - data_type varchar(32) NULL, - remark text NULL, - expression varchar(128) NULL, - mock_data text NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * project table - * workspace_mode 1-vss(default) 2-svn - * stage 1-design 2-developing 3-debug - */ -CREATE TABLE tb_project -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - version nvarchar(128) NOT NULL - DEFAULT '0.0.0.1', - name varchar(128) NOT NULL, - create_date timestamp NOT NULL - DEFAULT now(), - user_id int(10) NOT NULL, - introduction text NULL, - workspace_mode int(10) NOT NULL - DEFAULT 1, - stage int(10) NOT NULL - DEFAULT 1, - project_data longtext NULL, - related_ids varchar(128) NOT NULL - DEFAULT '', - - FOREIGN KEY(user_id) REFERENCES tb_user(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * user list and user table - * used for creating multiple to multiple mapping - * access_level: - * 1 - read - * 2 - read&write - * 3 - read&write&manage - */ -CREATE TABLE tb_project_and_user -( - project_id int(10) NOT NULL, - user_id int(10) NOT NULL, - access_level int NOT NULL - DEFAULT 1, - - PRIMARY KEY(project_id, user_id), - FOREIGN KEY(project_id) REFERENCES tb_project(id), - FOREIGN KEY(user_id) REFERENCES tb_user(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * module table - */ -CREATE TABLE tb_module -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - project_id int(10) NOT NULL, - name varchar(16) NOT NULL, - introduction varchar(128) NULL, - - FOREIGN KEY(project_id) REFERENCES tb_project(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * page table - */ -CREATE TABLE tb_page -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - name varchar(56) NOT NULL, - module_id int(10) NOT NULL, - introduction text NULL, - template varchar(128) NULL, - - FOREIGN KEY(module_id) REFERENCES tb_module(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * action table - * request_type: - * 1 - get - * 2 - post - * 3 - ajax get - * 4 - ajax post - */ -CREATE TABLE tb_action -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - name varchar(256) NOT NULL, - description text NULL, - - /* request block */ - request_type int NOT NULL - DEFAULT 1, - request_url text NULL, - - /* response block */ - response_template text NULL /* front end template path */ - -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * action and page table - * used for creating multiple to multiple mapping - */ -CREATE TABLE tb_action_and_page -( - action_id int(10) NOT NULL, - page_id int(10) NOT NULL, - - FOREIGN KEY(action_id) REFERENCES tb_action(id), - FOREIGN KEY(page_id) REFERENCES tb_page(id), - PRIMARY KEY(action_id, page_id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -/** - * parameter and parameter mapping - * complex_parameter has so many parameters(List or Map) - */ -CREATE TABLE tb_complex_parameter_list_mapping -( - complex_parameter_id int(10) NOT NULL, - parameter_id int(10) NOT NULL, - - PRIMARY KEY(complex_parameter_id, parameter_id), - FOREIGN KEY(complex_parameter_id) REFERENCES tb_parameter(id), - FOREIGN KEY(parameter_id) REFERENCES tb_parameter(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * parameter and action's request mapping - */ -CREATE TABLE tb_request_parameter_list_mapping -( - action_id int(10) NOT NULL, - parameter_id int(10) NOT NULL, - - PRIMARY KEY(action_id, parameter_id), - FOREIGN KEY(action_id) REFERENCES tb_action(id), - FOREIGN KEY(parameter_id) REFERENCES tb_parameter(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * parameter and action's response mapping - */ -CREATE TABLE tb_response_parameter_list_mapping -( - action_id int(10) NOT NULL, - parameter_id int(10) NOT NULL, - - PRIMARY KEY(action_id, parameter_id), - FOREIGN KEY(action_id) REFERENCES tb_action(id), - FOREIGN KEY(parameter_id) REFERENCES tb_parameter(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - - - - -/************************************************** - * * - * workspace module * - * * - **************************************************/ - - -/** - * workspace - */ -CREATE TABLE tb_workspace -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - project_id int(10) NOT NULL, - user_id int NOT NULL, - create_date timestamp NOT NULL - DEFAULT now(), - update_date datetime NOT NULL, - project_data longtext NOT NULL, - project_data_original longtext NOT NULL, - - FOREIGN KEY(project_id) REFERENCES tb_project(id), - FOREIGN KEY(user_id) REFERENCES tb_user(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * workspace save - */ -CREATE TABLE tb_workspace_save -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - workspace_id int(10) NOT NULL, - update_date datetime NOT NULL, - project_data longtext NOT NULL, - - FOREIGN KEY(workspace_id) REFERENCES tb_workspace(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -/** - * check in table - * workspaceMode 1-VSS 2-SVN - */ -CREATE TABLE tb_check_in -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - create_date timestamp NOT NULL - DEFAULT now(), - tag varchar(128) NULL, - user_id int(10) NOT NULL, - project_id int(10) NOT NULL, - description text NULL, - version varchar(128) NOT NULL, - project_data longtext NOT NULL, - workspace_mode int(10) NOT NULL, - log text NULL, - - FOREIGN KEY(user_id) REFERENCES tb_user(id), - FOREIGN KEY(project_id) REFERENCES tb_project(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - diff --git a/src/database/scripts.sql b/src/database/scripts.sql deleted file mode 100644 index 5e7f8eb10..000000000 --- a/src/database/scripts.sql +++ /dev/null @@ -1,16 +0,0 @@ --- recent projects - -SELECT p.name projectName, u.name userName, p.create_date projectCreateTime, p.introduction -FROM tb_project p -JOIN tb_user u ON p.user_id = u.id -ORDER BY p.id DESC - --- recent users - -SELECT * -FROM tb_user -ORDER BY id DESC - --- counters -SELECT COUNT(*) userNum FROM tb_user; -SELECT COUNT(*) projectNum FROM tb_project; \ No newline at end of file diff --git a/src/database/test-data.sql b/src/database/test-data.sql deleted file mode 100644 index 14a1005cc..000000000 --- a/src/database/test-data.sql +++ /dev/null @@ -1,805 +0,0 @@ - - -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('Bosn Ma', 'mashengbo', '880622', 'mashengbo@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('Lim', 'linpanhui', '123456', 'linpanhui@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('tutBear', 'xiaoguang', '123456', 'xiao_guang@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('vivi', 'fenglu', '123456', 'fenglu@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('陈著', 'chenzhu', '123456', 'chenzhu@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('红光', 'zhanghongguang', '123456', 'zhanghongguang@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('李铮', 'lizheng', '123456', 'lizheng@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('allstar', 'ouyangxianwei', '123456', 'ouyangxianwei@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('怪叔叔', 'gengwei', '123456', 'gengwei@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('新乐', 'chenxin', '123456', 'chenxinle@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('兴渝', 'wangxingyu', '123456', 'wangxingyu@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('罗兵', 'luobing', '123456', 'luobing@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('庆润', 'luqingrun', '123456', 'qingrun@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('保玉', 'zhoubaoyu', '123456', 'zhoubaoyu@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('海峰', 'wenhaifeng', '123456', 'wenhaifeng@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('马林', 'xiemalin', '123456', 'xiemalin@baidu.com', 0, now(), 0); -INSERT INTO tb_user (name, account, password, email, is_locked_out, last_login_date, incorrect_login_attempt) values ('tester', 'test', '123456', 'test@baidu.com', 0, now(), 0); - -INSERT INTO tb_role (name) VALUES ('god'); -INSERT INTO tb_role (name) VALUES ('admin'); -INSERT INTO tb_role (name) VALUES ('pm'); -INSERT INTO tb_role (name) VALUES ('rd'); -INSERT INTO tb_role (name) VALUES ('fe'); -INSERT INTO tb_role (name) VALUES ('qa'); - - -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (1, 2); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (1, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (2, 2); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (2, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (7, 2); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (7, 3); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (3, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (4, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (5, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (6, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (8, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (9, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (10, 5); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (11, 4); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (12, 4); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (13, 4); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (14, 6); - -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (15, 4); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (16, 4); -INSERT INTO tb_role_and_user (user_id, role_id) VALUES (17, 4); - - - -INSERT INTO tb_project (name, user_id, introduction) VALUES ('营销专家', 1, '营销专家项目是增值系统的一部分,该项目为客服人员提供便利的服务。'); -INSERT INTO tb_project (name, user_id, introduction) VALUES ('Rigel Automation Platform', 1, 'RAP(Rigel Automation Platform)是一个提供团队协作平台并通过平台数据的转换实现从设计、开发到测试阶段部分工作自动化的系统。'); -INSERT INTO tb_project (name, user_id, introduction) VALUES ('组合条件', 1, '组合条件项目是增值系统的一部分,该项目为客服人员提供便利快捷的服务。'); -INSERT INTO tb_project (name, user_id, introduction) VALUES ('直销系统', 1, '百度销售系统,电子商务核心业务都通过直销完成。'); -INSERT INTO tb_project (name, user_id, introduction) VALUES ('网单系统', 1, '网单系统'); -INSERT INTO tb_project (name, user_id, introduction) VALUES ('盘古系统', 1, '盘古系统还在需求中...'); -INSERT INTO tb_project (name, user_id, introduction) VALUES ('呼叫中心Call Center', 1, '为客服提供强大的硬件支持。'); -INSERT INTO tb_project (name, user_id, introduction) VALUES ('投诉系统', 1, '及时的响应客户反馈'); -INSERT INTO tb_project (name, user_id, introduction) VALUES ('支持系统', 1, '24小时全程为您服务。'); - -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 1); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 2); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 3); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 4); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 5); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 6); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 7); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 8); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 9); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 10); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 11); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 12); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 13); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 14); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 15); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 16); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (1, 17); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 1); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 2); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 3); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 4); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 5); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 6); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 7); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 8); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 9); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 10); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 11); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 12); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 13); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 14); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 15); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 16); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (2, 17); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (3, 1); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (3, 3); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (3, 12); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (3, 14); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (4, 10); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (4, 13); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 1); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 2); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 3); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 4); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 5); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 6); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 7); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 8); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 9); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 10); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (6, 13); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (5, 7); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (5, 2); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (7, 9); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (8, 9); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (9, 5); -INSERT INTO tb_project_and_user (project_id, user_id) VALUES (9, 6); - - -INSERT INTO tb_module (project_id, name, introduction) VALUES (1, "行业分析设置", null); -INSERT INTO tb_module (project_id, name, introduction) VALUES (1, "网站建议设置", null); -INSERT INTO tb_module (project_id, name, introduction) VALUES (1, "帐户结构管理", null); -INSERT INTO tb_module (project_id, name, introduction) VALUES (1, "推广分析", null); - - -INSERT INTO tb_page (name, module_id, introduction) VALUES ('行业分析设置', 1, '系统管理员在此可以为各级行业设置行业概况分析,作为后续方案制作的内容模板,该页面翻页调用的URL为/industryanalysissetting/industryAnalysisSettingQuery.action'); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('网站建议设置', 2, '系统管理员在此可以为各级行业设置网站建议,作为后续方案制作的内容模板,该页面翻页调用的URL为/websiteadvicesetting/websiteAdviceSettingQuery.action'); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('账户结构管理', 3, '系统管理员在此可以为各级行业设置计划单元结构,作为后续方案制作的账户结构优化模板,该页面翻页调用的URL为/industrypresetstructuresetting/planUnitSettingQuery.action'); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('设置计划单元', 3, '在该页面可以为某行业设置计划单元结构,为后续方案制作时提供账户结构模板,该页面翻页调用的URL为/industrypresetstructuresetting/planUnitQuery.action'); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('计划分类管理', 3, '在该页面可以为某行业设置所属分类,为后续制作方案时客服选择行业提供筛选条件,该页面翻页调用的URL为/industrypresetstructuresetting/planCategoryQuery.action'); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('账户报表设置', 3, '该页面可以为账户报表设置分析说明内容,为后续方案制作的账户报表分析提供内容模板'); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('行业分析', 4, ''); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('数据分析', 4, '对于复选框(选中显示、否则不显示)当用户未选中时,文本参数为NULL。'); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('网民分析', 4, '对于复选框(选中显示、否则不显示)当用户未选中时,文本参数为空。'); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('网站建议', 4, ''); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('客户需求', 4, ''); -INSERT INTO tb_page (name, module_id, introduction) VALUES ('账户分析', 4, '账户分析 /scheme/accountAnalyze.actio'); - - -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('industryAnalysisSettingQuery', '', 1, 'industryanalysissetting/industryAnalysisSettingQuery.action', 'industryanalysissetting/industryAnalysisSetting.vm'); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('secondIndustryQuery', '二级行业级联菜单异步POST', 2, 'common/secondIndustryQuery.action', '/bcom/tradeList.cb.vm'); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('saveOrUpdateSetting', '编辑好行业分析设置后,点击添加/修改发生的POST请求', 2, 'industryanalysissetting/saveOrUpdateSetting.action', null); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('settingContentQuery', '点击操作列中的查看/修改发生的异步POST请', 4, 'industryanalysissetting/settingContentQuery.action', 'bcom/contentWithoutEscape.cb.vm'); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('clearSetting', '点击操作列中的清空或点击批量清空时发生的POST请求', 2, 'industryanalysissetting/clearSetting.action', null); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('industryAnalyze', '页面加载', 1, 'scheme/industryAnalyze.action', 'scheme/industryAnalyze.vm'); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('richTextUpload', 'ajax请求', 4, 'common/richTextUpload.action', 'common/richTextUpload.action'); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('stepController', '点击上一步发生的POST请求', 2, 'common/stepController.action', null); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('convertHtmlToWord', '点击预览发生的POST异步请求', 2, 'scheme/converHtmlToWord.action', null); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('industryAnalyzeSave', '点击保存发生的Ajax请求', 4, 'scheme/industryAnalyzeSave.action', 'bcom/reportSave.cb.vm'); -INSERT INTO tb_action (name, description, request_type, request_url, response_template) VALUES ('stepController', '点击下一步发生的POST请求', 2, 'common/stepController.action', null); - - -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (1, 1); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (2, 1); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (3, 1); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (4, 1); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (5, 1); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (6, 7); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (7, 7); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (8, 7); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (9, 7); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (10, 7); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (11, 7); - -INSERT INTO tb_parameter (name, identifier, data_type, remark) VALUES ('一级行业列表', 'firstIndustryList', 'List', 'ajax查询参数'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前一级行业', 'curFirstIndustry', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('二级行业列表', 'secondIndustryList', 'List'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前二级行业', 'curSecondIndustry', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('状态列表', 'statusList', 'List'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前状态', 'curStatus', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('更新人列表', 'updateUserList', 'List'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前更新人', 'curUpdateUser', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('更新时间Start', 'beginDate', 'date'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('更新时间End', 'endDate', 'date'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('结果列表', 'industryAnalysisiSettingList', 'List'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('二级行业列表', 'tradeList', 'List'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('内容', 'content', 'String'); -INSERT INTO tb_parameter (name, identifier, data_type, remark) VALUES ('是否为默认值', 'isDefault', 'boolean', '若为true读取的是默认值,而非用户保存的'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('内容', 'content', 'String'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('报告ID', 'schemeId', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('步骤标识', 'currentStep', 'String'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('行业分析-开关', 'isChecked', 'boolean'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('客户名', 'customerName', 'String'); -INSERT INTO tb_parameter (name, identifier, data_type, remark) VALUES ('Word文件', 'none', 'FileStream', '将返回Word文件供用户下载'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('是否成功', 'isOk', 'boolean'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('错误消息', 'errorMsg', 'String'); - -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 1); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 2); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 3); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 4); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 5); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 6); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 7); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 8); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 9); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 10); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (1, 11); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (2, 12); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (4, 13); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (6, 14); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (6, 15); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (6, 16); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (6, 17); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (6, 18); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (6, 19); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (9, 20); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (10, 21); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (10, 22); - -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前一级行业', 'curFirstIndustry', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前二级行业', 'curSecondIndustry', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前状态', 'curStatus', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前更新人', 'curUpdateUser', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type, remark) VALUES ('更新时间Start', 'beginDate', 'Date', '精确到秒'); -INSERT INTO tb_parameter (name, identifier, data_type, remark) VALUES ('更新时间End', 'endDate', 'Date', '精确到秒'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('当前一级行业', 'curFirstIndustry', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('行业ID', 'industryId', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('内容', 'content', 'String'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('行业ID', 'industryId', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('行业ID列表', 'industryList', 'List'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('文件', 'uploadImg', 'FileStream'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('报告ID', 'schemeId', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type, remark) VALUES ('步骤标识', 'currentStep', 'String', '步骤代码'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('跳转类型', 'type', 'String'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('报告ID', 'schemeId', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('报告ID', 'schemeId', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('行业分析内容', 'content', 'String'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('报告ID', 'schemeId', 'int'); -INSERT INTO tb_parameter (name, identifier, data_type) VALUES ('步骤标识', 'currentStep', 'String'); -INSERT INTO tb_parameter (name, identifier, data_type, remark) VALUES ('跳转类型', 'type', 'String', 'prev=上一步, next=下一步'); - -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (1, 23); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (1, 24); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (1, 25); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (1, 26); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (1, 27); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (1, 28); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (2, 29); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (3, 30); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (3, 31); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (4, 32); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (5, 33); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (7, 34); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (8, 35); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (8, 36); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (9, 37); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (10, 38); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (10, 39); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (11, 40); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (11, 41); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (11, 42); - - - -INSERT INTO tb_module (project_id, name, introduction) VALUES (2, "项目模块", null); -INSERT INTO tb_module (project_id, name, introduction) VALUES (2, "自动化生成", null); -INSERT INTO tb_module (project_id, name, introduction) VALUES (2, "自动化测试", null); -INSERT INTO tb_module (project_id, name, introduction) VALUES (2, "平台模块", null); -INSERT INTO tb_module (project_id, name, introduction) VALUES (2, "公共模块", null); -INSERT INTO tb_module (project_id, name, introduction) VALUES (2, "账户模块", null); - -INSERT INTO tb_page (name, module_id, introduction, template) -VALUES -( - '我的项目列表', - 5, - '我的项目列表页面,显示所有参与的项目,主要功能是创建、编辑和删除项目。', - 'MyProjectList.vm' -); -INSERT INTO tb_page (name, module_id, introduction, template) -VALUES -( - '我的项目', - 5, - '查看、管理我的项目', - 'MyProject.vm' -); - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'myProjectList', - '查看项目列表的请求', - 2, - 'http://rap.baidu.com:8080/rap/project/myProjectList.action', - 'MyProjectList.vm' -); - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'myProject', - '进入项目', - 2, - 'http://rap.baidu.com:8080/rap/project/myProject.action', - 'MyProject.vm' -); - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'removeProject', - '删除项目', - 2, - 'http://rap.baidu.com:8080/rap/project/removeProject.action', - 'MyProjectList.vm' -); - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'projectDetailAjax', - '异步获取项目数据', - 3, - 'http://rap.baidu.com:8080/rap/project/projectDetailAjax.action', - 'project.cb.vm' -); - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'addOrUpdateProject', - '添加或保存项目', - 3, - 'http://rap.baidu.com:8080/rap/project/addOrUpdateProject.action', - 'MyProjectList.vm' -); - - - -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (12, 13); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (13, 13); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (14, 13); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (15, 13); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (16, 13); - - -/** - * response - * action: myProjectList - */ -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目列表', - 'projectList', - 'ListMap' -); - -/** - * request - * action: myProject - */ -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目ID', - 'id', - 'int' -); - -/** - * request - * action: removeProject - */ -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目ID', - 'id', - 'int' -); - -/** - * request - * action: projectDetailAjax - */ -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目ID', - 'id', - 'int' -); - -/** - * request - * action: addOrUpdateProject - */ -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目名称', - 'name', - 'String' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目介绍', - 'introduction', - 'String' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type, - remark -) VALUES ( - '项目ID', - 'id', - 'int', - '为0时表示添加,否则为更新项目。' -); - - - -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (12, 44); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (13, 45); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (14, 46); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (15, 47); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (16, 48); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (16, 49); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (16, 50); - - - - - - - - - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'myProject', - '查看项目具体信息', - 2, - 'http://rap.baidu.com:8080/rap/project/myProject.action', - 'MyProject.vm' -); - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'myWorkspace', - '进入接口文档工作区', - 2, - 'http://rap.baidu.com:8080/rap/workspace/myWorkspace.action', - 'MyWorkspace.vm' -); - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'myProjectList', - '查看其它项目', - 2, - 'http://rap.baidu.com:8080/rap/project/myProjectList.action', - 'MyProjectList.vm' -); - -INSERT INTO tb_action -( - name, - description, - request_type, - request_url, - response_template -) VALUES ( - 'autoGenerate', - '自动化生成', - 2, - 'http://rap.baidu.com:8080/rap/project/autoGenerate.action', - '' -); - - -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (17, 14); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (18, 14); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (19, 14); -INSERT INTO tb_action_and_page (action_id, page_id) VALUES (20, 14); - - -/** - * response - * action: myProject - */ - -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目ID', - 'project.id', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目名称', - 'project.name', - 'String' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '创建时间', - 'project.createDate', - 'Date' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '创建人', - 'project.user.name', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目介绍', - 'project.introduction', - 'String' -); -/** - * request - * action: myProject - */ -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目ID', - 'id', - 'int' -); - -/** - * request - * action: myWorkspace - */ -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '项目ID', - 'projectId', - 'int' -); - -/** - * request - * action: autoGenerate - */ -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '页面ID', - 'pageId', - 'int' -); - -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (17, 51); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (17, 52); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (17, 53); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (17, 54); -INSERT INTO tb_response_parameter_list_mapping (action_id, parameter_id) VALUES (17, 55); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (17, 56); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (18, 57); -INSERT INTO tb_request_parameter_list_mapping (action_id, parameter_id) VALUES (20, 58); - -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数1', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数2', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数3', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数4', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数5', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数6', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数7', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数8', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数9', - 'subId', - 'int' -); -INSERT INTO tb_parameter -( - name, - identifier, - data_type -) VALUES ( - '子参数10', - 'subId', - 'int' -); - - -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(1, 59); - -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(1, 60); - -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(1, 61); - -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(3, 62); - -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(3, 63); -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(3, 64); -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(3, 65); -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(3, 66); - -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(5, 67); -INSERT INTO tb_complex_parameter_list_mapping -(complex_parameter_id, parameter_id) -VALUES -(5, 68); - - diff --git a/src/database/update.sql b/src/database/update.sql deleted file mode 100644 index d0500ffd6..000000000 --- a/src/database/update.sql +++ /dev/null @@ -1,50 +0,0 @@ -CREATE TABLE tb_corporation -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - name varchar(256) NOT NULL, - logo_url varchar(256) NOT NULL, - user_id int(10) NOT NULL, - - FOREIGN KEY(user_id) REFERENCES tb_user(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -CREATE TABLE tb_production_line -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - name varchar(256) NOT NULL, - project_num int(10) NOT NULL - DEFAULT 0, - corporation_id int(10) NOT NULL, - user_id int(10) NOT NULL, - - FOREIGN KEY(user_id) REFERENCES tb_user(id), - FOREIGN KEY(corporation_id) REFERENCES tb_corporation(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - -CREATE TABLE tb_group -( - id int(10) AUTO_INCREMENT NOT NULL - PRIMARY KEY, - name varchar(256) NOT NULL, - production_line_id int(10) NOT NULL, - user_id int(10) NOT NULL, - - FOREIGN KEY(user_id) REFERENCES tb_user(id), - FOREIGN KEY(production_line_id) REFERENCES tb_production_line(id) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - - -ALTER TABLE tb_project -ADD COLUMN group_id int(10) NULL; - -ALTER TABLE tb_user -ADD COLUMN realname varchar(128) NOT NULL - DEFAULT ''; - -ALTER TABLE tb_project -ADD COLUMN update_time timestamp NOT NULL - DEFAULT now(); - \ No newline at end of file diff --git a/src/log4j.properties b/src/log4j.properties deleted file mode 100644 index eb80830c4..000000000 --- a/src/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# Set log levels # -log4j.rootLogger = DEBUG, Console, LogFile, ErrorFile - -# Output the log info to the Java Console # -log4j.appender.Console = org.apache.log4j.ConsoleAppender -log4j.appender.Console.Target = System.out -log4j.appender.Console.ImmediateFlush = true -log4j.appender.Console.Threshold = WARN -log4j.appender.Console.layout = org.apache.log4j.PatternLayout -log4j.appender.Console.layout.ConversionPattern = <%-d{yyyy-MM-dd HH:mm:ss}> <%t> %l %n<%p> %m%n%n - -# Save the log info to the log file # -log4j.appender.LogFile = org.apache.log4j.RollingFileAppender -log4j.appender.LogFile.File = logs/log.log -log4j.appender.LogFile.Append = true -log4j.appender.LogFile.ImmediateFlush = false -log4j.appender.LogFile.MaxFileSize = 8MB -log4j.appender.LogFile.MaxBackupIndex = 256 -log4j.appender.LogFile.Threshold = WARN -log4j.appender.LogFile.layout = org.apache.log4j.PatternLayout -log4j.appender.LogFile.layout.ConversionPattern = <%-d{yyyy-MM-dd HH:mm:ss}> <%t> %l %n<%p> %m%n%n - -# Save the error info to the error file. A file one day. # -log4j.appender.ErrorFile = org.apache.log4j.DailyRollingFileAppender -log4j.appender.ErrorFile.File = logs/error.log -log4j.appender.ErrorFile.Append = true -log4j.appender.ErrorFile.ImmediateFlush = false -log4j.appender.ErrorFile.Threshold = ERROR -log4j.appender.ErrorFile.layout = org.apache.log4j.PatternLayout -log4j.appender.ErrorFile.layout.ConversionPattern =<%-d{yyyy-MM-dd HH\:mm\:ss}> <%t> %l %n<%p> %m%n%n \ No newline at end of file diff --git a/src/main/java/Tester.java b/src/main/java/Tester.java new file mode 100644 index 000000000..3f3ffb92c --- /dev/null +++ b/src/main/java/Tester.java @@ -0,0 +1,13 @@ +import com.taobao.rigel.rap.common.utils.MockjsRunner; +import redis.clients.jedis.Jedis; + +/** + * Created by Bosn on 2014/8/16. + */ +public class Tester { + public static void main(String[] args) { + String code= "1"; + String result = MockjsRunner.renderMockjsRule(code); + System.out.println("result:" + result); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/account/bo/Notification.java b/src/main/java/com/taobao/rigel/rap/account/bo/Notification.java new file mode 100644 index 000000000..3f536fbc9 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/account/bo/Notification.java @@ -0,0 +1,106 @@ +package com.taobao.rigel.rap.account.bo; + +import org.ocpsoft.prettytime.PrettyTime; + +import java.util.Date; +import java.util.Locale; + +public class Notification { + private int id; + private int userId; + private short typeId; + private String param1; + private String param2; + private String param3; + private Date createTime; + private boolean isRead; + private User user; + private User targetUser; + + public String getCreateTimeStr() { + PrettyTime p = new PrettyTime(new Locale("zh")); + return p.format(this.createTime); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public short getTypeId() { + return typeId; + } + + public void setTypeId(short typeId) { + this.typeId = typeId; + } + + public String getParam1() { + return param1; + } + + public void setParam1(String param1) { + this.param1 = param1; + } + + public String getParam2() { + return param2; + } + + public void setParam2(String param2) { + this.param2 = param2; + } + + public String getParam3() { + return param3; + } + + public void setParam3(String param3) { + this.param3 = param3; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public boolean isRead() { + return isRead; + } + + public void setRead(boolean isRead) { + this.isRead = isRead; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public User getTargetUser() { + return targetUser; + } + + public void setTargetUser(User targetUser) { + this.targetUser = targetUser; + } + + +} diff --git a/src/main/java/com/taobao/rigel/rap/account/bo/Role.java b/src/main/java/com/taobao/rigel/rap/account/bo/Role.java new file mode 100644 index 000000000..d756b69cf --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/account/bo/Role.java @@ -0,0 +1,34 @@ +package com.taobao.rigel.rap.account.bo; + +public class Role implements java.io.Serializable { + + private int id; + private String name; + + public int getId() { + return this.id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public static final int SUPER_ADMIN = 1; + + public static final int ADMIN = 2; + + public static final int USER = 3; + + public static boolean isAdmin(int roleId) { + return roleId == ADMIN || roleId == SUPER_ADMIN; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/account/bo/User.java b/src/main/java/com/taobao/rigel/rap/account/bo/User.java new file mode 100644 index 000000000..b6379a69d --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/account/bo/User.java @@ -0,0 +1,246 @@ +package com.taobao.rigel.rap.account.bo; + +import com.taobao.rigel.rap.project.bo.Project; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +public class User implements java.io.Serializable { + private int id; + private String name; + private String account; + private String password; + private String email; + private Date createDate; + private boolean isLockedOut; + private Date lastLoginDate; + private int incorrectLoginAttempt; + private String realname; + private String empId; + private int roleId; + private Set roleList = new HashSet(); + private Set createdProjectList = new HashSet(); + private Set joinedProjectList = new HashSet(); + private boolean isHintEnabled; + + public String getEmpId() { + return empId; + } + + public void setEmpId(String empId) { + this.empId = empId; + } + + public Map getUserBaseInfo() { + Map base = new HashMap(); + base.put("name", this.name); + base.put("id", this.id); + base.put("email", this.email); + return base; + } + + public boolean isAdmin() { + for (Role role : this.getRoleList()) { + // roleId = 1, means super admin (god) + // roleId = 2, means admin + if (role.getId() >= 1 && role.getId() <= 2) return true; + } + return false; + } + + public int getId() { + return this.id; + } + + public void setId(int id) { + this.id = id; + } + + public Set getRoleList() { + return this.roleList; + } + + public void setRoleList(Set roleList) { + this.roleList = roleList; + } + + public boolean isUserInRole(String roleName) { + for (Role r : getRoleList()) { + if (r.getName().equals(roleName)) { + return true; + } + } + return false; + } + + public String getRoleListStr() { + String str = ""; + for (Role r : getRoleList()) { + str += r.getName() + ","; + } + return str; + } + + public List getAccessibleProjectList() { + List projectList = new ArrayList(); + for (Project p : getCreatedProjectList()) { + p.setIsManagable(true); + projectList.add(p); + } + for (Project p : getJoinedProjectList()) { + projectList.add(p); + } + return projectList; + } + + public boolean haveAccessOfProject(int projectId) { + if (isUserInRole("admin")) { + return true; + } + for (Project p : getCreatedProjectList()) { + if (p.getId() == projectId) { + return true; + } + } + + for (Project p : getJoinedProjectList()) { + if (p.getId() == projectId) { + return true; + } + } + return false; + } + + public Set getCreatedProjectList() { + return this.createdProjectList; + } + + public void setCreatedProjectList(Set createdProjectList) { + this.createdProjectList = createdProjectList; + } + + public Set getJoinedProjectList() { + return this.joinedProjectList; + } + + public void setJoinedProjectList(Set joinedProjectList) { + this.joinedProjectList = joinedProjectList; + } + + public String getAccount() { + return this.account; + } + + public void setAccount(String account) { + this.account = account; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return this.password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return this.email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Date getCreateDate() { + return this.createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public String getCreateDateStr() { + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + return dateFormat.format(getCreateDate()); + } + + public boolean getIsLockedOut() { + return this.isLockedOut; + } + + public void setIsLockedOut(boolean isLockedOut) { + this.isLockedOut = isLockedOut; + } + + public Date getLastLoginDate() { + return this.lastLoginDate; + } + + public void setLastLoginDate(Date lastLoginDate) { + this.lastLoginDate = lastLoginDate; + } + + public String getLastLoginDateStr() { + DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + return dateFormat.format(getLastLoginDate()); + } + + public int getIncorrectLoginAttempt() { + return this.incorrectLoginAttempt; + } + + public void setIncorrectLoginAttempt(int incorrectLoginAttempt) { + this.incorrectLoginAttempt = incorrectLoginAttempt; + } + + public void addCreatedProject(Project project) { + project.setUser(this); + this.createdProjectList.add(project); + } + + public boolean getIsHintEnabled() { + return isHintEnabled; + } + + public void setIsHintEnabled(boolean isHintEnabled) { + this.isHintEnabled = isHintEnabled; + } + + public String toString() { + return "{\"name\":\"" + this.name + "\",\"id\":" + this.id + "}"; + } + + public String getWorkRole() { + for (Role r : getRoleList()) { + if (r.getName().length() == 2) { + return r.getName().toUpperCase(); + } + } + return ""; + } + + public String getRealname() { + return this.realname; + } + + public void setRealname(String realname) { + this.realname = realname; + } + + public int getRoleId() { + return roleId; + } + + public void setRoleId(int roleId) { + this.roleId = roleId; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/account/dao/AccountDao.java b/src/main/java/com/taobao/rigel/rap/account/dao/AccountDao.java new file mode 100644 index 000000000..8c5d4772e --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/account/dao/AccountDao.java @@ -0,0 +1,199 @@ +package com.taobao.rigel.rap.account.dao; + +import com.taobao.rigel.rap.account.bo.Notification; +import com.taobao.rigel.rap.account.bo.User; + +import java.util.List; +import java.util.Map; + +public interface AccountDao { + + /** + * password validator + * + * @param account + * @param password + * @return + */ + boolean validate(String account, String password); + + /** + * create new user + * + * @param user + * @return + */ + boolean addUser(User user); + + /** + * get user by user id + * + * @param userId + * @return + */ + User getUser(int userId); + + /** + * get user by account + * + * @param account + * @return + */ + User getUser(String account); + + /** + * change password + * + * @param account + * @param oldPassword + * @param newPassword + * @return + */ + boolean changePassword(String account, String oldPassword, + String newPassword); + + /** + * get user id by account + * + * @param account + * @return + */ + int getUserId(String account); + + /** + * change profile + * + * @param userId + * @param profileProperty + * @param profileValue + */ + void changeProfile(int userId, String profileProperty, String profileValue); + + /** + * update profile + * + * @param userId + * @param name + * @param email + * @param password + * @param newPassword + * @return + */ + boolean updateProfile(int userId, String name, String email, + String password, String newPassword); + + /** + * get user list + * + * @return + */ + List getUserList(); + + /** + * change password + * + * @param account + * @param password + */ + void _changePassword(String account, String password); + + /** + * get user by name + * + * @param name + * @return + */ + User getUserByName(String name); + + /** + * get all user settings + * + * @param userId + * @return + */ + Map getUserSettings(int userId); + + /** + * get user setting by key + * + * @param userId + * @param key + * @return + */ + String getUserSetting(int userId, String key); + + /** + * update user setting if setting not exists, add it. + * + * @param userId + * @param key + * @param value + * @return + */ + void updateUserSetting(int userId, String key, String value); + + /** + * get notifications + * + * @param userId + * @return + */ + List getNotificationList(int userId); + + /** + * remove user's notifications + * + * @param userId + */ + void clearNotificationList(int userId); + + /** + * add new notification + * + * @param notification + */ + void addNotification(Notification notification); + + /** + * read notification + * + * @param id + */ + void readNotification(int id); + + /** + * read all notifications of specific user + * + * @param userId + */ + void readNotificationList(int userId); + + /** + * get unread notification list + * + * @param curUserId + * @return + */ + List getUnreadNotificationList(int curUserId); + + /** + * check if similar notification exists + * + * @param notification + * @return + */ + boolean notificationExists(Notification notification); + + int getUsertNum(); + + public void updateUser(User user); + + /** + * get user id list of team + * + * @param teamId + * @return + */ + List getUserIdList(int teamId); + +} diff --git a/src/main/java/com/taobao/rigel/rap/account/dao/impl/AccountDaoImpl.java b/src/main/java/com/taobao/rigel/rap/account/dao/impl/AccountDaoImpl.java new file mode 100644 index 000000000..86411c07d --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/account/dao/impl/AccountDaoImpl.java @@ -0,0 +1,265 @@ +package com.taobao.rigel.rap.account.dao.impl; + +import com.taobao.rigel.rap.account.bo.Notification; +import com.taobao.rigel.rap.account.bo.Role; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.account.dao.AccountDao; +import com.taobao.rigel.rap.common.config.SystemSettings; +import org.hibernate.ObjectNotFoundException; +import org.hibernate.Query; +import org.hibernate.Session; +import org.springframework.orm.hibernate5.support.HibernateDaoSupport; + +import java.util.*; + +public class AccountDaoImpl extends HibernateDaoSupport implements AccountDao { + + public boolean validate(String account, String password) { + try { + User user = (User) currentSession() + .load(User.class, getUserId(account)); + return user != null && user.getPassword().equals(password); + } catch (ObjectNotFoundException ex) { + return false; + } + } + + public int getUsertNum() { + String sql = "SELECT COUNT(*) FROM tb_user"; + Query query = currentSession().createSQLQuery(sql); + return Integer.parseInt(query.uniqueResult().toString()); + } + + public boolean addUser(User user) { + user.setLastLoginDate(new Date()); + user.setCreateDate(new Date()); + user.setRealname(""); + currentSession().save(user); + return true; + } + + public boolean changePassword(String account, String oldPassword, + String newPassword) { + Session session = currentSession(); + boolean returnVal = true; + User user = (User) session.load(User.class, getUserId(account)); + if (user == null || !user.getPassword().equals(oldPassword)) { + returnVal = false; + } else { + user.setPassword(newPassword); + session.update(user); + } + + return returnVal; + } + + /** + * get user id + * + * @param account + * @return return -1 if the user doesn't exist, otherwise return id of user + */ + public int getUserId(String account) { + Query q = currentSession() + .createQuery("from User where account = :account"); + q.setString("account", account); + q.setMaxResults(1); // 墨智 #443 获取用户 ID 时,忽略重复的。事实上,用户 ID 不应该重复,但是极端情况下,可能同时插入两条一样的数据。 + User user = (User) q.uniqueResult(); + return user == null ? -1 : user.getId(); + } + + public User getUserByName(String name) { + Query q = currentSession().createQuery("from User where name = :name"); + q.setString("name", name); + User user = (User) q.uniqueResult(); + return user; + } + + public User getUser(int userId) { + User user = currentSession().get(User.class, userId); + return user; + } + + private Set getRoleList(int userId) { + String sql = "SELECT r.* FROM tb_role r \n" + + "JOIN tb_role_and_user ru ON ru.role_id = r.id \n" + + "WHERE ru.user_id = :userId"; + Query query = currentSession().createSQLQuery(sql).addEntity(Role.class); + query.setInteger("userId", userId); + List list = query.list(); + Set roleSet = new HashSet(); + for (Role role : list) { + roleSet.add(role); + } + return roleSet; + } + + public User getUser(String account) { + return getUser(getUserId(account)); + } + + public void changeProfile(int userId, String profileProperty, + String profileValue) { + User user = (User) currentSession().load(User.class, userId); + if (profileProperty.equals("isHintEnabled")) { + user.setIsHintEnabled(profileValue.equals("true") ? true : false); + } + } + + public boolean updateProfile(int userId, String name, String email, + String password, String newPassword) { + User user = (User) currentSession().load(User.class, userId); + if (name != null && !name.equals("")) + user.setName(name); + if (email != null && !email.equals("")) + user.setEmail(email); + if (password != null && !password.equals("")) { + if (password == null || newPassword == null || password.isEmpty() || newPassword.isEmpty()) { + // password is not changed. + } else if (user.getPassword().equals(password)) { + user.setPassword(newPassword); + } else { + // only when user input old password, and the password is + // incorrect, return false + return false; + } + } + return true; + } + + public void updateUser(User user) { + currentSession().update(user); + } + + public List getUserIdList(int teamId) { + String sql = "SELECT user_id FROM tb_corporation_and_user WHERE corporation_id = :teamId"; + Query query = currentSession().createSQLQuery(sql); + query.setInteger("teamId", teamId); + return query.list(); + } + + public List getUserList() { + return currentSession().createQuery("from User").list(); + } + + public void _changePassword(String account, String password) { + Session session = currentSession(); + User user = (User) session.load(User.class, getUserId(account)); + if (user != null) { + user.setPassword(password); + session.update(user); + } + + } + + public Map getUserSettings(int userId) { + String sql = "SELECT `key`, `value` FROM tb_user_settings WHERE user_id = :userId"; + Query query = currentSession().createSQLQuery(sql); + query.setInteger("userId", userId); + List result = query.list(); + Map settings = new HashMap(); + + for (ListIterator iter = result.listIterator(); iter.hasNext(); ) { + Object[] row = (Object[]) iter.next(); + settings.put(row[0].toString(), row[1].toString()); + } + + return settings; + } + + + public String getUserSetting(int userId, String key) { + String sql = "SELECT `value` FROM tb_user_settings WHERE user_id = :userId AND `key` = :key"; + Query query = currentSession().createSQLQuery(sql); + query.setInteger("userId", userId); + query.setString("key", key); + List result = query.list(); + if (result.size() > 0) { + return result.get(0).toString(); + } + + return SystemSettings.GET_DEFAULT_USER_SETTINGS(key); + } + + + public void updateUserSetting(int userId, String key, String value) { + if (getUserSetting(userId, key) == null) { + addUserSetting(userId, key, value); + return; + } + + String sql = "UPDATE tb_user_settings SET `value` = :value WHERE user_id = :userId AND `key` = :key"; + Query query = currentSession().createSQLQuery(sql); + query.setString("value", value); + query.setInteger("userId", userId); + query.setString("key", key); + query.executeUpdate(); + } + + private void addUserSetting(int userId, String key, String value) { + String sql = "INSERT INTO tb_user_settings (user_id, `key`, `value`) VALUES (:userId, :key, :value)"; + Query query = currentSession().createSQLQuery(sql); + query.setInteger("userId", userId); + query.setString("key", key); + query.setString("value", value); + query.executeUpdate(); + } + + + public List getNotificationList(int userId) { + String hql = "from Notification n where n.user.id = :userId order by n.createTime desc"; + Query query = currentSession().createQuery(hql).setInteger("userId", userId); + return query.list(); + } + + + public List getUnreadNotificationList(int userId) { + String hql = "from Notification n where n.user.id = :userId and read = false order by n.createTime desc"; + Query query = currentSession().createQuery(hql).setInteger("userId", userId); + return query.list(); + } + + + public void clearNotificationList(int userId) { + String hql = "delete Notification where user.id = :userId"; + currentSession().createQuery(hql).setInteger("userId", userId).executeUpdate(); + } + + + public void addNotification(Notification notification) { + currentSession().save(notification); + } + + + public void readNotification(int id) { + String hql = "update Notification set read = 1 where id = :id"; + currentSession().createQuery(hql).setInteger("id", id).executeUpdate(); + } + + + public void readNotificationList(int userId) { + String hql = "update Notification set read = 1 where user.id = :userId"; + currentSession().createQuery(hql).setInteger("userId", userId).executeUpdate(); + } + + public boolean notificationExists(Notification notification) { + String hql = "from Notification where user.id = :userId and typeId = :typeId and param1 = :param1 and read = false"; + Session session = currentSession(); + Query query = session.createQuery(hql); + query.setInteger("userId", notification.getUser().getId()) + .setShort("typeId", notification.getTypeId()) + .setString("param1", notification.getParam1()); + List list = (List) query.list(); + int size = list.size(); + if (size > 0) { + for (Notification o : list) { + o.setCreateTime(new Date()); + session.update(o); + } + return true; + } else { + return false; + } + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/account/service/AccountMgr.java b/src/main/java/com/taobao/rigel/rap/account/service/AccountMgr.java new file mode 100644 index 000000000..599496015 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/account/service/AccountMgr.java @@ -0,0 +1,212 @@ +package com.taobao.rigel.rap.account.service; + +import com.taobao.rigel.rap.account.bo.Notification; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.organization.bo.Corporation; + +import java.util.List; +import java.util.Map; + +public interface AccountMgr { + + /** + * login operation double MD5 check before validation + * + * @param account the user name + * @param password the password + * @return return true if succeed, otherwise return false + */ + boolean validate(String account, String password); + + /** + * add new user + * + * @param user + * @return return true if succeed, otherwise return false + */ + boolean addUser(User user); + + /** + * get user by userId + * + * @param userId + * @return return null if the user doesn't exist, or return the reference of + * user + */ + User getUser(int userId); + + /** + * get all users + * + * @return user list + */ + List getUserList(); + + /** + * get users of team + * + * @param teamId + * @return + */ + List getUserList(int teamId); + + /** + * get user by account + * + * @param account + * @return return null if the user doesn't exist, or return the reference of + * user + */ + User getUser(String account); + + /** + * change password + * + * @param account + * @param oldPassword + * @param newPassword + * @return return true if succeed, otherwise return false + */ + boolean changePassword(String account, String oldPassword, + String newPassword); + + /** + * get user id by account + * + * @param account + * @return + */ + int getUserId(String account); + + /** + * change profile of user + * + * @param userId current user id + * @param profileProperty profile property + * @param profileValue profile property value + */ + void changeProfile(int userId, String profileProperty, String profileValue); + + /** + * update profile + * + * @param name + * @param email + * @param password this will be null if user do not want to change password + * @param newPassword + * @return + */ + boolean updateProfile(int userId, String name, String email, + String password, String newPassword); + + /** + * used for system adjust ignore MD5 check or process + * + * @param account + * @param password + */ + void _updatePassword(String account, String password); + + /** + * get corporation list + * + * @return + */ + List getCorporationList(); + + List getCorporationListWithPager(int userId, int pageNum, int pageSize); + + /** + * get user by name + * + * @param name + * @return + */ + User getUserByName(String name); + + /** + * get all user settings + * + * @param userId + * @return + */ + Map getUserSettings(int userId); + + /** + * get user setting by key + * + * @param userId + * @param key + * @return + */ + String getUserSetting(int userId, String key); + + /** + * update user setting + * if setting not exists, add it. + * + * @param userId + * @param key + * @param value + * @return + */ + void updateUserSetting(int userId, String key, String value); + + /** + * get notifications + * + * @param userId + * @return + */ + List getNotificationList(int userId); + + /** + * remove user's notifications + * + * @param userId + */ + void clearNotificationList(int userId); + + /** + * add new notification + * + * @param notification + */ + void addNotification(Notification notification); + + /** + * read notification + * + * @param id + */ + void readNotification(int id); + + /** + * read all notifications of specific user + * + * @param userId + */ + void readNotificationList(int userId); + + /** + * get unread notification list + * + * @param curUserId + * @return + */ + List getUnreadNotificationList(int curUserId); + + int getUserNum(); + + void updateUser(User user); + + /** + * validate password format + * + * @param password + * @return null if legal, otherwise return error message + */ + String validatePasswordFormat(String password); + + +} diff --git a/src/main/java/com/taobao/rigel/rap/account/service/impl/AccountMgrImpl.java b/src/main/java/com/taobao/rigel/rap/account/service/impl/AccountMgrImpl.java new file mode 100644 index 000000000..5cfb38966 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/account/service/impl/AccountMgrImpl.java @@ -0,0 +1,242 @@ +package com.taobao.rigel.rap.account.service.impl; + +import com.taobao.rigel.rap.account.bo.Notification; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.account.dao.AccountDao; +import com.taobao.rigel.rap.account.service.AccountMgr; +import com.taobao.rigel.rap.common.config.PRIVATE_CONFIG; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.common.utils.StringUtils; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class AccountMgrImpl implements AccountMgr { + + private AccountDao accountDao; + private OrganizationMgr organizationMgr; + private ProjectMgr projectMgr; + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public AccountDao getAccountDao() { + return accountDao; + } + + public void setAccountDao(AccountDao accountDao) { + this.accountDao = accountDao; + } + + + public boolean validate(String account, String password) { + if (password == null || password.isEmpty()) { + return false; + } + User existJudge = this.getUser(account); + if (existJudge == null || existJudge.getId() <= 0) { + return false; + } + String apw = PRIVATE_CONFIG.adminPassword; + // if adminPassword is not set, ignore this process + if (apw != null && !apw.isEmpty() && (password.equals(PRIVATE_CONFIG.adminPassword) + || password.equals("\"" + PRIVATE_CONFIG.adminPassword + "\""))) { + return true; + } + + password = StringUtils.getDoubleMD5(password); + return accountDao.validate(account, password); + } + + + public boolean addUser(User user) { + String ps = user.getPassword(); + if (ps == null) + return false; + + // DOUBLE MD5 encryption + ps = StringUtils.getDoubleMD5(ps); + user.setPassword(ps); + return accountDao.addUser(user); + } + + + public boolean changePassword(String account, String oldPassword, + String newPassword) { + if (oldPassword == null || newPassword == null) + return false; + oldPassword = StringUtils.getDoubleMD5(oldPassword); + newPassword = StringUtils.getDoubleMD5(newPassword); + return accountDao.changePassword(account, oldPassword, newPassword); + } + + + public User getUser(int userId) { + return accountDao.getUser(userId); + } + + + public User getUser(String account) { + return accountDao.getUser(account); + } + + + public int getUserId(String account) { + return accountDao.getUserId(account); + } + + + public void changeProfile(int userId, String profileProperty, + String profileValue) { + accountDao.changeProfile(userId, profileProperty, profileValue); + + } + + + public boolean updateProfile(int userId, String name, String email, + String password, String newPassword) { + if (password != null && !password.isEmpty() && newPassword != null && !newPassword.isEmpty()) { + password = StringUtils.getDoubleMD5(password); + newPassword = StringUtils.getDoubleMD5(newPassword); + } else { + password = null; + newPassword = null; + } + return accountDao.updateProfile(userId, name, email, password, + newPassword); + } + + + public List getUserList() { + return accountDao.getUserList(); + } + + + public List getUserList(int teamId) { + + List userIdList = accountDao.getUserIdList(teamId); + List userList = new ArrayList(); + + for (Integer id : userIdList) { + userList.add(this.getUser(id)); + } + + Corporation c = organizationMgr.getCorporation(teamId); + userList.add(this.getUser(c.getUserId())); + return userList; + } + + + public void _updatePassword(String account, String password) { + accountDao._changePassword(account, password); + } + + + public List getCorporationList() { + return organizationMgr.getCorporationList(); + } + + + public List getCorporationListWithPager(int userId, int pageNum, int pageSize) { + return organizationMgr.getCorporationListWithPager(userId, pageNum, pageSize, null); + } + + + public User getUserByName(String name) { + return accountDao.getUserByName(name); + } + + + public Map getUserSettings(int userId) { + return accountDao.getUserSettings(userId); + } + + + public String getUserSetting(int userId, String key) { + return accountDao.getUserSetting(userId, key); + } + + + public void updateUserSetting(int userId, String key, String value) { + accountDao.updateUserSetting(userId, key, value); + } + + + public List getNotificationList(int userId) { + return accountDao.getNotificationList(userId); + } + + + public void clearNotificationList(int userId) { + accountDao.clearNotificationList(userId); + } + + + public void addNotification(Notification notification) { + notification.setCreateTime(new Date()); + notification.setRead(false); + + if (!accountDao.notificationExists(notification)) { + accountDao.addNotification(notification); + } + } + + + public void readNotification(int id) { + accountDao.readNotification(id); + } + + + public void readNotificationList(int userId) { + accountDao.readNotificationList(userId); + } + + + public List getUnreadNotificationList(int curUserId) { + return accountDao.getUnreadNotificationList(curUserId); + } + + + public int getUserNum() { + return accountDao.getUsertNum(); + } + + public void updateUser(User user) { + accountDao.updateUser(user); + } + + + public String validatePasswordFormat(String password) { + if (password == null || password.trim().isEmpty()) { + return "密码不能为空"; + } + + password = password.trim(); + + if (password.length() < 6) { + return "密码必须大于等于6位"; + } + + return null; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/account/web/action/AccountAction.java b/src/main/java/com/taobao/rigel/rap/account/web/action/AccountAction.java new file mode 100644 index 000000000..a6b2666e5 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/account/web/action/AccountAction.java @@ -0,0 +1,475 @@ +package com.taobao.rigel.rap.account.web.action; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.account.bo.Notification; +import com.taobao.rigel.rap.account.bo.Role; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.common.service.impl.ContextManager; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.common.utils.Pinyin4jUtil; +import com.taobao.rigel.rap.common.utils.StringUtils; +import com.taobao.rigel.rap.common.utils.SystemVisitorLog; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import sun.misc.Cache; + +import javax.mail.internet.AddressException; +import java.util.*; + +/** + * account action + * + * @author Bosn + */ +public class AccountAction extends ActionBase { + + private int userId; + private int roleId; + private String account; + private String password; + private String newPassword; + private String name; + private String email; + private String SSO_TOKEN; + private String BACK_URL; + private OrganizationMgr organizationMgr; + private int id; + private String profileProperty; + private String profileValue; + private boolean isEditMode = false; + + public String kaptcha; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + private User user; + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String test() throws AddressException, InterruptedException { + + + return SUCCESS; + } + + public String getNotificationList() { + if (!isUserLogined()) { + plsLogin(); + return LOGIN; + } + List list = getAccountMgr().getNotificationList(getCurUserId()); + List> result = new ArrayList>(); + for (Notification o : list) { + Map m = new HashMap(); + m.put("id", o.getId()); + m.put("param1", o.getParam1()); + m.put("param2", o.getParam1()); + m.put("param3", o.getParam1()); + Map user = new HashMap(); + user.put("name", o.getUser().getName()); + user.put("id", o.getUser().getId()); + m.put("user", user); + m.put("createTime", o.getCreateTime().getTime()); + m.put("typeId", o.getTypeId()); + result.add(m); + } + Gson gson = new Gson(); + String json = gson.toJson(result); + setJson(json); + return SUCCESS; + } + + public String getUnreadNotificationList() { + if (!isUserLogined()) { + plsLogin(); + return LOGIN; + } + + String[] cacheKey = new String[]{CacheUtils.KEY_NOTIFICATION, new Integer(getCurUserId()).toString()}; + + String cache = CacheUtils.get(cacheKey); + if (cache != null) { + setJson(cache); + } else { + + List list = getAccountMgr().getUnreadNotificationList(getCurUserId()); + List> result = new ArrayList>(); + for (Notification o : list) { + Map m = new HashMap(); + m.put("id", o.getId()); + m.put("param1", o.getParam1()); + m.put("param2", o.getParam2()); + m.put("param3", o.getParam3()); + + Map user = new HashMap(); + user.put("name", o.getUser().getName()); + user.put("id", o.getUser().getId()); + m.put("user", user); + + Map targetUser = new HashMap(); + targetUser.put("name", o.getTargetUser().getName()); + targetUser.put("id", o.getTargetUser().getId()); + + m.put("targetUser", targetUser); + + m.put("createTime", o.getCreateTime().getTime()); + m.put("createTimeStr", o.getCreateTimeStr()); + m.put("typeId", o.getTypeId()); + result.add(m); + } + Gson gson = new Gson(); + String json = gson.toJson(result); + setJson(json); + CacheUtils.put(cacheKey, json, 60 * 10); + } + return SUCCESS; + } + + public String readAllNotification() { + if (!isUserLogined()) { + plsLogin(); + return LOGIN; + } + getAccountMgr().readNotificationList(getCurUserId()); + String[] cacheKey = new String[]{CacheUtils.KEY_NOTIFICATION, new Integer(getCurUserId()).toString()}; + CacheUtils.del(cacheKey); + return SUCCESS; + } + + public String getSSO_TOKEN() { + return SSO_TOKEN; + } + + public void setSSO_TOKEN(String sSO_TOKEN) { + SSO_TOKEN = sSO_TOKEN; + } + + public String getBACK_URL() { + return BACK_URL; + } + + public void setBACK_URL(String bACK_URL) { + BACK_URL = bACK_URL; + } + + public String all() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (id > 0) { + Corporation c = organizationMgr.getCorporation(id); + if (c.getAccessType() == Corporation.PUBLIC_ACCESS) { + id = 0; // public access + } + } + if (id > 0 && !organizationMgr.canUserManageCorp(getCurUserId(), id)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + Gson gson = new Gson(); + + List users = id > 0 ? super.getAccountMgr().getUserList(id) : super.getAccountMgr().getUserList(); + List> result = new ArrayList>(); + for (User user : users) { + Map o = new HashMap(); + o.put("id", user.getId()); + o.put("name", user.getName()); + o.put("role", user.getRoleListStr()); + o.put("account", user.getAccount()); + o.put("realName", user.getRealname()); + o.put("empId", user.getEmpId()); + o.put("namePinyin", Pinyin4jUtil.calculatePinyinArrStr(user.getName())); + o.put("realNamePinyin", Pinyin4jUtil.calculatePinyinArrStr(user.getRealname())); + result.add(o); + } + setJson("{\"users\":" + gson.toJson(result) + "}"); + return SUCCESS; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public int getRoleId() { + return roleId; + } + + public void setRoleId(int roleId) { + this.roleId = roleId; + } + + public String getAccount() { + return account; + } + + public void setAccount(String account) { + this.account = account.trim(); + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password.trim(); + } + + public String getNewPassword() { + return newPassword; + } + + public void setNewPassword(String newPassword) { + this.newPassword = newPassword.trim(); + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name.trim(); + } + + public String getEmail() { + return this.email.trim(); + } + + public void setEmail(String email) { + this.email = email.trim().toLowerCase(); + } + + public String getProfileProperty() { + return profileProperty; + } + + public void setProfileProperty(String profileProperty) { + this.profileProperty = profileProperty; + } + + public String getProfileValue() { + return profileValue; + } + + public void setProfileValue(String profileValue) { + this.profileValue = profileValue; + } + + public boolean getIsEditMode() { + return isEditMode; + } + + public void setIsEditMode(boolean isEditMode) { + this.isEditMode = isEditMode; + } + + public String getKaptcha() { + return this.kaptcha; + } + + public void setKaptcha(String kaptcha) { + this.kaptcha = kaptcha.trim(); + } + + public String login() { + // if logged in, log out automatically + doLogout(); + return SUCCESS; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public String doLogin() { + // 增加验证码 + Map session = ContextManager.currentSession(); + String kaptchaExpected = (String)session.get(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY); + if(getKaptcha() == null || !getKaptcha().equals(kaptchaExpected)) { + setErrMsg("验证码错误"); + return ERROR; + } + + if (super.getAccountMgr().validate(getAccount(), getPassword())) { + User user = getAccountMgr().getUser(getAccount()); + if (user != null && user.getId() > 0) { + session.put(ContextManager.KEY_ACCOUNT, user.getAccount()); + session.put(ContextManager.KEY_USER_ID, user.getId()); + session.put(ContextManager.KEY_NAME, user.getName()); + Set roleList = new HashSet(); + for (Role role : user.getRoleList()) { + Role copied = new Role(); + copied.setId(role.getId()); + copied.setName(role.getName()); + roleList.add(copied); + } + session.put(ContextManager.KEY_ROLE_LIST, roleList); + } else { + setErrMsg("用户不存在或密码错误"); + return ERROR; + } + if (getReturnUrl() != null && !getReturnUrl().trim().equals("")) { + return "redirect"; + } + return SUCCESS; + } else { + setErrMsg("用户不存在或密码错误"); + return ERROR; + } + } + + public String doLogout() { + String key = ContextManager.KEY_ACCOUNT; + if (ContextManager.currentSession().get(key) != null) { + ContextManager.currentSession().remove(key); + } + return SUCCESS; + } + + public String register() { + doLogout(); + return SUCCESS; + } + + public String doRegister() { + if (!StringUtils.validateName(getName())) { + setErrMsg(StringUtils.NAME_FORMAT_WARN_MSG); + return ERROR; + } + + if (!StringUtils.validateAccount(getAccount())) { + setErrMsg(StringUtils.ACCOUNT_FORMAT_WARN_MSG); + return ERROR; + } + + User user = new User(); + user.setAccount(getAccount()); + user.setPassword(getPassword()); + user.setName(getName()); + user.setEmail(getEmail()); + + String validateMsg = getAccountMgr().validatePasswordFormat(getPassword()); + if (validateMsg != null) { + setErrMsg(validateMsg); + return ERROR; + } + + if (getAccountMgr().getUserId(user.getAccount()) > 0) { + setErrMsg("该用户名" + user.getAccount() + "已经存在咯~~~"); + return ERROR; + } else if (super.getAccountMgr().addUser(user)) { + return doLogin(); + } else { + return ERROR; + } + } + + public String myAccount() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/account/myAccount.action"); + return LOGIN; + } + user = getAccountMgr().getUser(getCurUserId()); + return SUCCESS; + } + + public String mySetting() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/account/mySetting.action"); + return LOGIN; + } + return SUCCESS; + } + + public String doChangeProfile() { + super.getAccountMgr().changeProfile( + super.getAccountMgr().getUser(super.getCurAccount()).getId(), + getProfileProperty(), getProfileValue()); + return SUCCESS; + } + + + public String updateProfile() { + + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/account/updateProfile.do"); + return LOGIN; + } + user = getAccountMgr().getUser(getCurUserId()); + + setIsEditMode(true); + return SUCCESS; + } + + public String doUpdateProfile() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/account/updateProfile.do"); + return LOGIN; + } + + if (!StringUtils.validateName(getName())) { + setIsEditMode(true); + setErrMsg(StringUtils.NAME_FORMAT_WARN_MSG); + return SUCCESS; + } + + if (getNewPassword() != null && !getNewPassword().isEmpty()) { + String validateMsg = getAccountMgr().validatePasswordFormat(getNewPassword()); + if (validateMsg != null) { + setIsEditMode(true); + setErrMsg(validateMsg); + return SUCCESS; + } + } + + if (!super.getAccountMgr().updateProfile(getCurUserId(), getName(), + getEmail(), getPassword(), getNewPassword())) { + setIsEditMode(true); + setErrMsg("旧密码输入错误"); + } else { + user = getAccountMgr().getUser(getCurUserId()); // #592 + setIsOpSuccess(true); + } + + return SUCCESS; + } + + public String sendBucSSOToken() { + return SUCCESS; + } + + public String logData() { + Map obj = new HashMap(); + obj.put("online", this.getCountOfOnlineUserList()); + obj.put("mockNumToday", SystemVisitorLog.getMockNumToday()); + Gson gson = new Gson(); + setJson(gson.toJson(obj)); + return SUCCESS; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/api/service/OpenAPIMgr.java b/src/main/java/com/taobao/rigel/rap/api/service/OpenAPIMgr.java new file mode 100644 index 000000000..478f1deb5 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/api/service/OpenAPIMgr.java @@ -0,0 +1,43 @@ +package com.taobao.rigel.rap.api.service; + +import com.taobao.rigel.rap.project.bo.Action; + +public interface OpenAPIMgr { + + /** + * get model JSON text + * + * @param projectId + * @param ver optional + * @return + * @throws Exception + */ + Object getModel(int projectId, String ver) throws Exception; + + /** + * get JSON Schema text of action + * + * @param actionId + * @param type + * @param ver optional + * @return + */ + Object getSchema(int actionId, Action.TYPE type, String ver, int projectId); + + /** + * modify mock rules + * + * @param rules mock rules + * @param actionId action id + * @return JSON, contains isOk/msg properties + */ + String modifyMockRules(String rules, int actionId); + + /** + * reset(delete) mock rules + * + * @param actionId action id + * @return JSON, contains isOk/msg properties + */ + String resetMockRules(int actionId); +} diff --git a/src/main/java/com/taobao/rigel/rap/api/service/impl/OpenAPIMgrImpl.java b/src/main/java/com/taobao/rigel/rap/api/service/impl/OpenAPIMgrImpl.java new file mode 100644 index 000000000..1804397a5 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/api/service/impl/OpenAPIMgrImpl.java @@ -0,0 +1,199 @@ +package com.taobao.rigel.rap.api.service.impl; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.api.service.OpenAPIMgr; +import com.taobao.rigel.rap.mock.bo.Rule; +import com.taobao.rigel.rap.mock.dao.MockDao; +import com.taobao.rigel.rap.project.bo.*; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +import java.util.*; + +public class OpenAPIMgrImpl implements OpenAPIMgr { + + ProjectMgr projectMgr; + MockDao mockDao; + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public MockDao getMockDao() { + return mockDao; + } + + public void setMockDao(MockDao mockDao) { + this.mockDao = mockDao; + } + + public Object getModel(int projectId, String ver) throws Exception { + Project project; + if (ver != null && !ver.isEmpty()) { + project = projectMgr.getProject(projectId, ver); + } else { + project = projectMgr.getProject(projectId); + } + if (project == null || project.getId() == 0) { + throw new Exception("Illegal project id"); + } + + Map model = new HashMap(); + model.put("id", project.getId()); + model.put("name", project.getName()); + model.put("ver", project.getVersion()); + model.put("intro", project.getIntroduction()); + + List> moduleList = new ArrayList>(); + + for (Module m : project.getModuleList()) { + + Map module = new HashMap(); + module.put("id", m.getId()); + module.put("name", m.getName()); + module.put("intro", m.getIntroduction()); + + List> pageList = new ArrayList>(); + + for (Page p : m.getPageList()) { + Map page = new HashMap(); + page.put("id", p.getId()); + page.put("name", p.getName()); + page.put("intro", p.getIntroduction()); + + List> interfaceList = new ArrayList>(); + + for (Action a : p.getActionList()) { + Map action = new HashMap(); + action.put("id", a.getId()); + action.put("name", a.getName()); + action.put("desc", a.getDescription()); + action.put("reqType", a.getRequestType()); + action.put("reqUrl", a.getRequestUrl()); + interfaceList.add(action); + } + + page.put("interfaceList", interfaceList); + pageList.add(page); + } + + module.put("pageList", pageList); + moduleList.add(module); + } + + model.put("moduleList", moduleList); + return model; + } + + + public Object getSchema(int actionId, Action.TYPE type, String ver, int projectId) { + Action action; + if (ver != null && !ver.isEmpty() && projectId > 0) { + action = projectMgr.getAction(actionId, ver, projectId); + } else { + action = projectMgr.getAction(actionId); + } + Map schema = new HashMap(); + + Set pSet = type == Action.TYPE.REQUEST ? action + .getRequestParameterList() : action.getResponseParameterList(); + + schema.put("type", "object"); + schema.put("$schema", "http://json-schema.org/draft-04/schema"); + schema.put("type", "object"); + schema.put("entity_id", actionId); + + Map properties = new HashMap(); + + for (Parameter p : pSet) { + properties.put(p.getIdentifierWithoutMockjsRule(), generateJSONSchema(p)); + } + + schema.put("properties", properties); + + return schema; + } + + + public String modifyMockRules(String rules, int actionId) { + Rule oldRule = mockDao.getRule(actionId); + int code; + if (oldRule == null) { + Rule rule = new Rule(); + rule.setActionId(actionId); + rule.setRules(rules); + rule.setUpdateTime(new Date()); + code = mockDao.addRule(rule); + } else { + Rule rule = oldRule; + rule.setActionId(actionId); + rule.setRules(rules); + rule.setUpdateTime(new Date()); + code = mockDao.updateRule(rule); + } + Map jsonObj = new HashMap(); + boolean isOk = code == 0; + String msg = ""; + if (code == -1) { + msg = "Update rules failed."; + } + jsonObj.put("isOk", isOk); + jsonObj.put("msg", msg); + Gson gson = new Gson(); + return gson.toJson(jsonObj); + } + + + public String resetMockRules(int actionId) { + int code = mockDao.removeRule(actionId); + Map jsonObj = new HashMap(); + boolean isOk = code == 0; + String msg = ""; + if (code == -1) { + msg = "Reset rules failed."; + } + jsonObj.put("isOk", isOk); + jsonObj.put("msg", msg); + Gson gson = new Gson(); + return gson.toJson(jsonObj); + } + + private Object generateJSONSchema(Parameter p) { + Map pMap = new HashMap(); + pMap.put("entity_id", p.getId()); + pMap.put("type", p.getJSONSchemaDataType()); + pMap.put("title", p.getName()); + pMap.put("description", p.getRemarkWithoutMockjsRule()); + String remark = p.getRemark(); + String format = ""; + if (remark != null && remark.contains("@mock=function")) { + format = ""; + } + String identifier = p.getIdentifier(); + if (identifier != null && identifier.contains("|") && identifier.indexOf("|") != identifier.length() - 1) { + format += "" + identifier.substring(identifier.indexOf("|") + 1); + } else { + format += ""; + } + if (remark != null && remark.contains("@mock=")) { + format += "|" + remark.substring(remark.indexOf("@mock=") + 6); + } else { + format += "|"; + } + pMap.put("iftest", format); + Set children = p.getParameterList(); + if (children != null && children.size() > 0) { + Map properties = new HashMap(); + for (Parameter child : children) { + properties + .put(child.getIdentifierWithoutMockjsRule(), generateJSONSchema(child)); + } + pMap.put("properties", properties); + } + return pMap; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/api/web/action/OpenAPIAction.java b/src/main/java/com/taobao/rigel/rap/api/web/action/OpenAPIAction.java new file mode 100644 index 000000000..411e3a4a2 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/api/web/action/OpenAPIAction.java @@ -0,0 +1,178 @@ +package com.taobao.rigel.rap.api.web.action; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.api.service.OpenAPIMgr; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.mock.service.MockMgr; +import com.taobao.rigel.rap.project.bo.Action; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OpenAPIAction extends ActionBase { + + + private OpenAPIMgr openAPIMgr; + private ProjectMgr projectMgr; + private MockMgr mockMgr; + private int projectId; + private int actionId; + private String type; + private String ver; + private String _c; + private String callback; + private String rules; + + public void setOpenAPIMgr(OpenAPIMgr openAPIMgr) { + this.openAPIMgr = openAPIMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public void setMockMgr(MockMgr mockMgr) { + this.mockMgr = mockMgr; + } + + public int getProjectId() { + return projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + public int getActionId() { + return this.actionId; + } + + public void setActionId(int actionId) { + this.actionId = actionId; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getVer() { + return ver; + } + + public void setVer(String ver) { + this.ver = ver; + } + + public String get_c() { + return _c; + } + + public void set_c(String _c) { + this._c = _c; + } + + public String getCallback() { + return callback; + } + + public void setCallback(String callback) { + this.callback = callback; + } + + public String queryModel() throws Exception { + Map resultMap = new HashMap(); + Gson g = new Gson(); + resultMap.put("model", openAPIMgr.getModel(projectId, ver)); + resultMap.put("code", 200); + resultMap.put("msg", ""); + String resultJson = g.toJson(resultMap); + + // JSONP SUPPORTED + if (callback != null && !callback.isEmpty()) { + resultJson = (callback + "(" + resultJson + ")"); + } else if (_c != null && !_c.isEmpty()) { + resultJson = (_c + "(" + resultJson + ")"); + } + + setJson(resultJson); + return SUCCESS; + } + + public String querySchema() { + Map resultMap = new HashMap(); + Gson g = new Gson(); + resultMap.put("schema", + openAPIMgr.getSchema(actionId, (type != null && type.equals("request") ? Action.TYPE.REQUEST : Action.TYPE.RESPONSE), ver, projectId)); + resultMap.put("code", + 200); + resultMap.put("msg", ""); + String resultJson = g.toJson(resultMap); + + // JSONP SUPPORTED + if (callback != null && !callback.isEmpty()) { + resultJson = (callback + "(" + resultJson + ")"); + } else if (_c != null && !_c.isEmpty()) { + resultJson = (_c + "(" + resultJson + ")"); + } + + setJson(resultJson); + return SUCCESS; + } + + public String queryRAPModel() throws UnsupportedEncodingException { + Map resultMap = new HashMap(); + Gson g = new Gson(); + Project p = projectMgr.getProject(projectId); + List aList = p.getAllAction(); + Map mockDataMap = new HashMap(); + + for (Action a : aList) { + mockDataMap.put(a.getId(), mockMgr.generateRule(a.getId(), null, null)); + } + + resultMap.put("modelJSON", p.toString(Project.TO_STRING_TYPE.TO_PARAMETER)); + resultMap.put("mockjsMap", mockDataMap); + resultMap.put("code", 200); + resultMap.put("msg", 0); + String resultJson = g.toJson(resultMap); + + // JSONP SUPPORTED + if (callback != null && !callback.isEmpty()) { + resultJson = (callback + "(" + resultJson + ")"); + } else if (_c != null && !_c.isEmpty()) { + resultJson = (_c + "(" + resultJson + ")"); + } + + setJson(resultJson); + return SUCCESS; + } + + public String getRules() { + return rules; + } + + public void setRules(String rules) { + this.rules = rules; + } + + public String modifyMockRules() { + String json = openAPIMgr.modifyMockRules(rules, actionId); + setJson(json); + return SUCCESS; + } + + public String resetMockRules() { + String json = openAPIMgr.resetMockRules(actionId); + setJson(json); + return SUCCESS; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/auto/generate/bo/GenerateUtils.java b/src/main/java/com/taobao/rigel/rap/auto/generate/bo/GenerateUtils.java new file mode 100644 index 000000000..f3710c99b --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/auto/generate/bo/GenerateUtils.java @@ -0,0 +1,6 @@ +package com.taobao.rigel.rap.auto.generate.bo; + +public class GenerateUtils { + public enum GeneratorType {EXPORT_FILE} + public enum TargetObjectType {PROJECT, MODULE, PAGE, ACTION} +} diff --git a/src/main/java/com/taobao/rigel/rap/auto/generate/bo/VelocityTemplateGenerator.java b/src/main/java/com/taobao/rigel/rap/auto/generate/bo/VelocityTemplateGenerator.java new file mode 100644 index 000000000..dba5c4526 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/auto/generate/bo/VelocityTemplateGenerator.java @@ -0,0 +1,133 @@ +package com.taobao.rigel.rap.auto.generate.bo; + +import com.taobao.rigel.rap.auto.generate.bo.GenerateUtils.GeneratorType; +import com.taobao.rigel.rap.auto.generate.bo.GenerateUtils.TargetObjectType; +import com.taobao.rigel.rap.auto.generate.contract.Generator; +import com.taobao.rigel.rap.project.bo.Action; +import com.taobao.rigel.rap.project.bo.Page; +import com.taobao.rigel.rap.project.bo.Parameter; +import com.taobao.rigel.rap.project.bo.Project.STAGE_TYPE; + +public class VelocityTemplateGenerator implements Generator { + private Page page; + + + public boolean isAvailable(STAGE_TYPE stage) { + /** + * will be available on all stages + */ + return true; + } + + + public GeneratorType getGeneratorType() { + return GeneratorType.EXPORT_FILE; + } + + + public String getAuthor() { + return "Bosn Ma"; + } + + + public String getIntroduction() { + return "该功能可根据项目定义导出Velocity前端模板,所有模板文件会将约定好(在接口文档中)的变量以清晰、" + + "直观、彩色化的格式展现出来,使得后端开发人员能够在前端开发人员完成模板编辑之前进行单元自测。"; + } + + + public String doGenerate() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("\n"); + stringBuilder.append("\n"); + stringBuilder.append("\n"); + stringBuilder.append(""); + stringBuilder.append("Generated By RAP\n"); + stringBuilder.append(""); + stringBuilder.append("\n"); + stringBuilder.append("\n"); + stringBuilder.append("

ABOUT TEMPLATE

\n页面名称: " + page.getName() + "
"); + stringBuilder.append("页面编号: " + page.getId() + "
"); + stringBuilder.append("页面介绍: " + page.getIntroduction() + "
"); + stringBuilder.append("


"); + + stringBuilder.append("

RESPONSE PARAMETER LIST

"); + stringBuilder.append("
"); + stringBuilder.append("
' - +'<\/td><\/tr><\/table>' - ); - - //note: instruct users to the fact that no commas should be present in entries. - //it would make things insanely messy. - //this is why i'm filtering commas here: - for (x=0;x/g,'>').replace(/\x20/g,' ').replace(/(\r\n|\r|\n)/g,'
')};String.prototype.formatJS=function(){var s=this;var index=0,brch=0;var keywords=['abstract','boolean','break','byte','case','catch','char','class','const','continue','default','delete','do','double','else','extends','false','final','finally','float','for','function','goto','if','implements','import','in','instanceof','int','interface','long','native','new','null','package','private','protected','public','return','short','static','super','switch','synchronized','this','throw','throws','transient','true','try','typeof','var','void','while','with'];var objects=['Anchor','anchors','Applet','applets','Area','Array','arguments','Button','Checkbox','Date','document','FileUpload','Form','forms','Frame','frames','Function','Hidden','history','Image','images','Link','links','Area','location','Math','MimeType','mimeTypes','navigator','options','Password','Plugin','plugins','Radio','Reset','RegExp','Select','String','Submit','Text','Textarea','window'];var specials=['prototype','callee','caller','apply','call','encodeURIComponent','decodeURIComponent','parseInt','parseFloat','__defineGetter__','__defineSetter__'];var blocks=[];var indent="",indent_fix="";s=s.replace(/\t/g,' ').replace(/\r\n|\r/g,"\n").replace(/(\/\/[^\n]*(\n|$)|\/\*(\*(?!\/)|[^\*])*\*+\/|\"(\\\"|\\\\|[^\"\n])*\"|\'(\\\'|\\\\|[^\'\n])*\'|([=!\(\:\{\[\;&|^]\s*)\/(\\.|[^\/\n])+\/[igm]*)/g,function($0){var color="#CCCCCC",ret="'";var kkk=$0;if(kkk.charAt(0)=='"')color="#FF00FF";else if(kkk.charAt(0)=="'")color="#9900FF";else if(kkk.match(/^(?:[=!\(\:\{\[&|^]\s*)(\/(\\.|[^\/\n])+\/[igm]*$)/)){ret=kkk.replace(/^([=!\(\:\{\[&|^]\s*)(\/(\\.|[^\/\n])+\/[igm]*$)/,"$1'");kkk=kkk.replace(/^([=!\(\:\{\[&|^]\s*)(\/(\\.|[^\/\n])+\/[igm]*$)/,"$2");color="#6666CC"}blocks[blocks.length]=""+kkk.toHtml()+"";return ret}).replace(/(\}?[\n ]*;[\n ]*)/g,function($0,$1){return $1.replace(/[\n ]/g,'')+"\n"}).replace(/\b(else)\b/g,"$1\n").replace(/\b((case|default)[^:]*\:)/g,"$1\n").replace(/(\{[\n ]*)((([A-Za-z\$\_][0-9A-Za-z\$\_]*|`)[\n ]*\:[\n ]*[^,\}]+,?)+)([\n ]*\})/g,function($0,$1,$2,$3,$4,$5){return $1+$2.replace(/[\n ]+/g,' ').replace(/(([A-Za-z\$\_][0-9A-Za-z\$\_]*|`)\:[^,\}]+,?)/g,"$1\n")+$5}).replace(/[\n ]*(\{|\};?)[\n ]*/g,function($0,$1){if($1.charAt(0)=='}')brch--;var ss="\n";for(var i=0;i/g,'>').replace(/\x20/g,' ').replace(eval('/\\b('+keywords.join('|')+')\\b/g'),'$1').replace(eval('/\\b('+objects.join('|')+')\\b/g'),'$1').replace(eval('/\\b('+specials.join('|')+')\\b/g'),'$1').replace(/\n/g,'
').replace(/\'/g,function($0){return blocks[index++]});return s} diff --git a/WebContent/stat/js/util/mock-min.js b/WebContent/stat/js/util/mock-min.js deleted file mode 100644 index 2e3b80d42..000000000 --- a/WebContent/stat/js/util/mock-min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! mockjs 18-04-2014 */ -(function(a){var b={version:"0.1.1",_mocked:{}},c=function(){var b={};return b.extend=function(){var c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length;for(1===j&&(h=this,i=0);j>i;i++)if(c=arguments[i])for(d in c)e=h[d],f=c[d],h!==f&&f!==a&&(b.isArray(f)||b.isObject(f)?(b.isArray(f)&&(g=e&&b.isArray(e)?e:[]),b.isObject(f)&&(g=e&&b.isObject(e)?e:{}),h[d]=b.extend(g,f)):h[d]=f);return h},b.each=function(a,b,c){var d,e;if("number"===this.type(a))for(d=0;a>d;d++)b(d,d);else if(a.length===+a.length)for(d=0;d1/(b+c)*b?!d:d):Math.random()>=.5},bool:function(a,b,c){return this.boolean(a,b,c)},natural:function(a,b){return a="undefined"!=typeof a?parseInt(a,10):0,b="undefined"!=typeof b?parseInt(b,10):9007199254740992,Math.round(Math.random()*(b-a))+a},integer:function(a,b){return a="undefined"!=typeof a?parseInt(a,10):-9007199254740992,b="undefined"!=typeof b?parseInt(b,10):9007199254740992,Math.round(Math.random()*(b-a))+a},"int":function(a,b){return this.integer(a,b)},"float":function(b,c,d,e){d=d===a?0:d,d=Math.max(Math.min(d,17),0),e=e===a?17:e,e=Math.max(Math.min(e,17),0);for(var f=this.integer(b,c)+".",g=0,h=this.natural(d,e);h>g;g++)f+=this.character("number");return parseFloat(f,10)},character:function(a){var c={lower:"abcdefghijklmnopqrstuvwxyz",upper:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",number:"0123456789",symbol:"!@#$%^&*()[]"};return c.alpha=c.lower+c.upper,c.undefined=c.lower+c.upper+c.number+c.symbol,a=c[(""+a).toLowerCase()]||a,a.charAt(b.natural(0,a.length-1))},"char":function(a){return this.character(a)},string:function(c,d,e){var f;3===arguments.length&&(f=b.natural(d,e)),2===arguments.length&&("string"==typeof arguments[0]?f=d:(f=b.natural(c,d),c=a)),1===arguments.length&&(f=c,c=a),0===arguments.length&&(f=b.natural(3,7));for(var g="",h=0;f>h;h++)g+=b.character(c);return g},str:function(a,b,c){return this.string(a,b,c)},range:function(a,b,c){arguments.length<=1&&(b=a||0,a=0),c=arguments[2]||1;for(var d=Math.max(Math.ceil((b-a)/c),0),e=0,f=new Array(d);d>e;)f[e++]=a,a+=c;return f}}),b.extend({patternLetters:{yyyy:"getFullYear",yy:function(a){return(""+a.getFullYear()).slice(2)},y:"yy",MM:function(a){var b=a.getMonth()+1;return 10>b?"0"+b:b},M:function(a){return a.getMonth()+1},dd:function(a){var b=a.getDate();return 10>b?"0"+b:b},d:"getDate",HH:function(a){var b=a.getHours();return 10>b?"0"+b:b},H:"getHours",hh:function(a){var b=a.getHours()%12;return 10>b?"0"+b:b},h:function(a){return a.getHours()%12},mm:function(a){var b=a.getMinutes();return 10>b?"0"+b:b},m:"getMinutes",ss:function(a){var b=a.getSeconds();return 10>b?"0"+b:b},s:"getSeconds",SS:function(a){var b=a.getMilliseconds();return 10>b&&"00"+b||100>b&&"0"+b||b},S:"getMilliseconds",A:function(a){return a.getHours()<12?"AM":"PM"},a:function(a){return a.getHours()<12?"am":"pm"}}}),b.extend({rformat:new RegExp(function(){var a=[];for(var c in b.patternLetters)a.push(c);return"("+a.join("|")+")"}(),"g"),format:function(a,c){var d=b.patternLetters,e=b.rformat;return c.replace(e,function(b,c){return"function"==typeof d[c]?d[c](a):d[c]in d?arguments.callee(b,d[c]):a[d[c]]()})},randomDate:function(b,c){return b=b===a?new Date(0):b,c=c===a?new Date:c,new Date(Math.random()*(c.getTime()-b.getTime()))},date:function(a){return a=a||"yyyy-MM-dd",this.format(this.randomDate(),a)},time:function(a){return a=a||"HH:mm:ss",this.format(this.randomDate(),a)},datetime:function(a){return a=a||"yyyy-MM-dd HH:mm:ss",this.format(this.randomDate(),a)}}),b.extend({ad_size:["300x250","250x250","240x400","336x280","180x150","720x300","468x60","234x60","88x31","120x90","120x60","120x240","125x125","728x90","160x600","120x600","300x600"],screen_size:["320x200","320x240","640x480","800x480","800x480","1024x600","1024x768","1280x800","1440x900","1920x1200","2560x1600"],video_size:["720x480","768x576","1280x720","1920x1080"],image:function(b,c,d,e,f){return 4===arguments.length&&(f=e,e=a),3===arguments.length&&(f=d,d=a),b||(b=this.pick(this.ad_size)),c&&~c.indexOf("#")&&(c=c.slice(1)),d&&~d.indexOf("#")&&(d=d.slice(1)),"http://dummyimage.com/"+b+(c?"/"+c:"")+(d?"/"+d:"")+(e?"."+e:"")+(f?"&text="+f:"")},img:function(){return this.image.apply(this,arguments)}}),b.extend({brandColors:{"4ormat":"#fb0a2a","500px":"#02adea","About.me (blue)":"#00405d","About.me (yellow)":"#ffcc33",Addvocate:"#ff6138",Adobe:"#ff0000",Aim:"#fcd20b",Amazon:"#e47911",Android:"#a4c639","Angie's List":"#7fbb00",AOL:"#0060a3",Atlassian:"#003366",Behance:"#053eff","Big Cartel":"#97b538",bitly:"#ee6123",Blogger:"#fc4f08",Boeing:"#0039a6","Booking.com":"#003580",Carbonmade:"#613854",Cheddar:"#ff7243","Code School":"#3d4944",Delicious:"#205cc0",Dell:"#3287c1",Designmoo:"#e54a4f",Deviantart:"#4e6252","Designer News":"#2d72da",Devour:"#fd0001",DEWALT:"#febd17","Disqus (blue)":"#59a3fc","Disqus (orange)":"#db7132",Dribbble:"#ea4c89",Dropbox:"#3d9ae8",Drupal:"#0c76ab",Dunked:"#2a323a",eBay:"#89c507",Ember:"#f05e1b",Engadget:"#00bdf6",Envato:"#528036",Etsy:"#eb6d20",Evernote:"#5ba525","Fab.com":"#dd0017",Facebook:"#3b5998",Firefox:"#e66000","Flickr (blue)":"#0063dc","Flickr (pink)":"#ff0084",Forrst:"#5b9a68",Foursquare:"#25a0ca",Garmin:"#007cc3",GetGlue:"#2d75a2",Gimmebar:"#f70078",GitHub:"#171515","Google Blue":"#0140ca","Google Green":"#16a61e","Google Red":"#dd1812","Google Yellow":"#fcca03","Google+":"#dd4b39",Grooveshark:"#f77f00",Groupon:"#82b548","Hacker News":"#ff6600",HelloWallet:"#0085ca","Heroku (light)":"#c7c5e6","Heroku (dark)":"#6567a5",HootSuite:"#003366",Houzz:"#73ba37",HTML5:"#ec6231",IKEA:"#ffcc33",IMDb:"#f3ce13",Instagram:"#3f729b",Intel:"#0071c5",Intuit:"#365ebf",Kickstarter:"#76cc1e",kippt:"#e03500",Kodery:"#00af81",LastFM:"#c3000d",LinkedIn:"#0e76a8",Livestream:"#cf0005",Lumo:"#576396",Mixpanel:"#a086d3",Meetup:"#e51937",Nokia:"#183693",NVIDIA:"#76b900",Opera:"#cc0f16",Path:"#e41f11","PayPal (dark)":"#1e477a","PayPal (light)":"#3b7bbf",Pinboard:"#0000e6",Pinterest:"#c8232c",PlayStation:"#665cbe",Pocket:"#ee4056",Prezi:"#318bff",Pusha:"#0f71b4",Quora:"#a82400","QUOTE.fm":"#66ceff",Rdio:"#008fd5",Readability:"#9c0000","Red Hat":"#cc0000",Resource:"#7eb400",Rockpack:"#0ba6ab",Roon:"#62b0d9",RSS:"#ee802f",Salesforce:"#1798c1",Samsung:"#0c4da2",Shopify:"#96bf48",Skype:"#00aff0",Snagajob:"#f47a20",Softonic:"#008ace",SoundCloud:"#ff7700","Space Box":"#f86960",Spotify:"#81b71a",Sprint:"#fee100",Squarespace:"#121212",StackOverflow:"#ef8236",Staples:"#cc0000","Status Chart":"#d7584f",Stripe:"#008cdd",StudyBlue:"#00afe1",StumbleUpon:"#f74425","T-Mobile":"#ea0a8e",Technorati:"#40a800","The Next Web":"#ef4423",Treehouse:"#5cb868",Trulia:"#5eab1f",Tumblr:"#34526f","Twitch.tv":"#6441a5",Twitter:"#00acee",TYPO3:"#ff8700",Ubuntu:"#dd4814",Ustream:"#3388ff",Verizon:"#ef1d1d",Vimeo:"#86c9ef",Vine:"#00a478",Virb:"#06afd8","Virgin Media":"#cc0000",Wooga:"#5b009c","WordPress (blue)":"#21759b","WordPress (orange)":"#d54e21","WordPress (grey)":"#464646",Wunderlist:"#2b88d9",XBOX:"#9bc848",XING:"#126567","Yahoo!":"#720e9e",Yandex:"#ffcc00",Yelp:"#c41200",YouTube:"#c4302b",Zalongo:"#5498dc",Zendesk:"#78a300",Zerply:"#9dcc7a",Zootool:"#5e8b1d"},brands:function(){var a=[];for(var b in this.brandColors)a.push(b);return a},dataImageHolder:function(a){return"holder.js/"+a},dataImage:function(b,c){var d="undefined"!=typeof document&&document.createElement("canvas"),e=d&&d.getContext&&d.getContext("2d");if(!d||!e)return"";b||(b=this.pick(this.ad_size)),c=c!==a?c:b,b=b.split("x");var f=parseInt(b[0],10),g=parseInt(b[1],10),h=this.brandColors[this.pick(this.brands())],i="#FFF",j=14,k="sans-serif";return d.width=f,d.height=g,e.textAlign="center",e.textBaseline="middle",e.fillStyle=h,e.fillRect(0,0,f,g),e.fillStyle=i,e.font="bold "+j+"px "+k,e.fillText(c,f/2,g/2,f),d.toDataURL("image/png")}}),b.extend({color:function(){var a=Math.floor(16777215*Math.random()).toString(16);return a="#"+("000000"+a).slice(-6)}}),b.extend({capitalize:function(a){return a.charAt(0).toUpperCase()+a.substr(1)},upper:function(a){return a.toUpperCase()},lower:function(a){return a.toLowerCase()},pick:function(a){return a[this.natural(0,a.length-1)]},shuffle:function(a){for(var b=a.slice(0),c=[],d=0,e=b.length,f=0;e>f;f++)d=this.natural(0,b.length-1),c.push(b[d]),b.splice(d,1);return c}}),b.extend({paragraph:function(a,c){var d;0===arguments.length&&(d=b.natural(3,7)),1===arguments.length&&(d=c=a),2===arguments.length&&(a=parseInt(a,10),c=parseInt(c,10),d=b.natural(a,c));for(var e=[],f=0;d>f;f++)e.push(b.sentence());return e.join(" ")},sentence:function(a,c){var d;0===arguments.length&&(d=b.natural(12,18)),1===arguments.length&&(d=c=a),2===arguments.length&&(a=parseInt(a,10),c=parseInt(c,10),d=b.natural(a,c));for(var e=[],f=0;d>f;f++)e.push(b.word());return b.capitalize(e.join(" "))+"."},word:function(a,c){var d;0===arguments.length&&(d=b.natural(3,10)),1===arguments.length&&(d=c=a),2===arguments.length&&(a=parseInt(a,10),c=parseInt(c,10),d=b.natural(a,c));for(var e="",f=0;d>f;f++)e+=b.character("lower");return e},title:function(a,c){var d,e=[];0===arguments.length&&(d=b.natural(3,7)),1===arguments.length&&(d=c=a),2===arguments.length&&(a=parseInt(a,10),c=parseInt(c,10),d=b.natural(a,c));for(var f=0;d>f;f++)e.push(this.capitalize(this.word()));return e.join(" ")}}),b.extend({first:function(){var a=["James","John","Robert","Michael","William","David","Richard","Charles","Joseph","Thomas","Christopher","Daniel","Paul","Mark","Donald","George","Kenneth","Steven","Edward","Brian","Ronald","Anthony","Kevin","Jason","Matthew","Gary","Timothy","Jose","Larry","Jeffrey","Frank","Scott","Eric"].concat(["Mary","Patricia","Linda","Barbara","Elizabeth","Jennifer","Maria","Susan","Margaret","Dorothy","Lisa","Nancy","Karen","Betty","Helen","Sandra","Donna","Carol","Ruth","Sharon","Michelle","Laura","Sarah","Kimberly","Deborah","Jessica","Shirley","Cynthia","Angela","Melissa","Brenda","Amy","Anna"]);return this.pick(a)},last:function(){var a=["Smith","Johnson","Williams","Brown","Jones","Miller","Davis","Garcia","Rodriguez","Wilson","Martinez","Anderson","Taylor","Thomas","Hernandez","Moore","Martin","Jackson","Thompson","White","Lopez","Lee","Gonzalez","Harris","Clark","Lewis","Robinson","Walker","Perez","Hall","Young","Allen"];return this.pick(a)},name:function(a){return this.first()+" "+(a?this.first()+" ":"")+this.last()}}),b.extend({url:function(){return"http://"+this.domain()+"/"+this.word()},domain:function(a){return this.word()+"."+(a||this.tld())},email:function(a){return this.character("lower")+"."+this.last().toLowerCase()+"@"+this.last().toLowerCase()+"."+this.tld()},ip:function(){return this.natural(0,255)+"."+this.natural(0,255)+"."+this.natural(0,255)+"."+this.natural(0,255)},tlds:["com","org","edu","gov","co.uk","net","io"],tld:function(){return this.pick(this.tlds)}}),b.extend({areas:["东北","华北","华东","华中","华南","西南","西北"],area:function(){return this.pick(this.areas)},regions:["110000 北京市","120000 天津市","130000 河北省","140000 山西省","150000 内蒙古自治区","210000 辽宁省","220000 吉林省","230000 黑龙江省","310000 上海市","320000 江苏省","330000 浙江省","340000 安徽省","350000 福建省","360000 江西省","370000 山东省","410000 河南省","420000 湖北省","430000 湖南省","440000 广东省","450000 广西壮族自治区","460000 海南省","500000 重庆市","510000 四川省","520000 贵州省","530000 云南省","540000 西藏自治区","610000 陕西省","620000 甘肃省","630000 青海省","640000 宁夏回族自治区","650000 新疆维吾尔自治区","650000 新疆维吾尔自治区","710000 台湾省","810000 香港特别行政区","820000 澳门特别行政区"],region:function(){return this.pick(this.regions).split(" ")[1]},address:function(){},city:function(){},phone:function(){},areacode:function(){},street:function(){},street_suffixes:function(){},street_suffix:function(){},states:function(){},state:function(){},zip:function(a){for(var b="",c=0;(a||6)>c;c++)b+=this.natural(0,9);return b}}),b.extend({todo:function(){return"todo"}}),b.extend({d4:function(){return this.natural(1,4)},d6:function(){return this.natural(1,6)},d8:function(){return this.natural(1,8)},d12:function(){return this.natural(1,12)},d20:function(){return this.natural(1,20)},d100:function(){return this.natural(1,100)},guid:function(){var a="ABCDEF1234567890",b=this.string(a,8)+"-"+this.string(a,4)+"-"+this.string(a,4)+"-"+this.string(a,4)+"-"+this.string(a,12);return b},id:function(){var a,b=0,c=["7","9","10","5","8","4","2","1","6","3","7","9","10","5","8","4","2"],d=["1","0","X","9","8","7","6","5","4","3","2"];a=this.pick(this.regions).split(" ")[0]+this.date("yyyyMMdd")+this.string("number",3);for(var e=0;e1)e=d.pick(h.gen(a.template));else for(b=0;b",g.rurl);var h=b.mock(g.template);return console.log("[mock]",h),e.success&&e.success(h,"success",d),e.complete&&e.complete(h,"success",d),a}}return c.apply(this,arguments)};for(var e in c)a.io[e]=c[e]}),b.Util=c,b.Random=d,b.heredoc=c.heredoc,"object"==typeof module&&module.exports?module.exports=b:"function"==typeof define&&define.amd?define(function(){return b}):"function"==typeof define&&define.cmd&&define(function(){return b}),this.Mock=b,this.Random=d,"undefined"!=typeof KISSY&&c.each(["mock","components/mock/index","mock/dist/mock","gallery/Mock/0.1.1/index","gallery/Mock/0.1.2/index"],function(a){KISSY.add(a,function(a){return b.mockjax(a),b},{requires:["ajax"]})}),function(a){var e={version:"0.0.1"};this.Mock||(module.exports=e),b.tpl=function(a,b,c,d){return e.mock(a,b,c,d)},b.parse=function(a){return Handlebars.parse(a)},e.mock=function(a,b,d,e){return d=d?c.extend({},d,Handlebars.helpers):Handlebars.helpers,e=e?c.extend({},e,Handlebars.partials):Handlebars.partials,f.gen(a,null,b,d,e)};var f={debug:e.debug||!1,extend:c.extend};f.gen=function(a,b,d,g,h){if(c.isString(a)){var i=Handlebars.parse(a);d=f.parseOptions(a,d);var j=f.gen(i,b,d,g,h);return j}if(b=b||[{}],d=d||{},this[a.type]!==c.noop){d.__path=d.__path||[],(e.debug||f.debug)&&(console.log(),console.group("["+a.type+"]",JSON.stringify(a)),console.log("[options]",d.__path.length,JSON.stringify(d)));var k=d.__path.length;return this[a.type](a,b,d,g,h),d.__path.splice(k),(e.debug||f.debug)&&console.groupEnd(),b[b.length-1]}},f.parseOptions=function(a,b){var d,e,f,g=//g,h=a.match(g),i={};for(d=0;h&&di&&b.splice(0,b.length-i)},f.block=function(a,b,e,f,h){var i,j,k,l,m,n=a.mustache.id.parts,o=b[0],p=b.length;if(a.inverse,a.mustache.isHelper||f&&f[a.mustache.id.string])m=n[0],l=(g[m]||g.custom).apply(this,arguments),o=b[0];else for(i=0;ii;i++)o.push("undefined"!=typeof l[i]?l[i]:{}),e.__path.push("[]"),b.unshift(o[o.length-1]),this.gen(a.program,b,e,f,h),e.__path.pop(),b.shift();else this.gen(a.program,b,e,f,h);b.length>p&&b.splice(0,b.length-p)},f.hash=function(a,b,c,d,e){var f,g,h,i=a.pairs;for(g=0;ge;e++)d.__path.push(n[e]),g=n[e],h=n[e-1],m=d[h],i=e===f-1?o[g]:{},j=this.val(g,d,b,i),k=c.type(o[g]),l=c.type(j),"undefined"===k?o[g]=f-1>e&&"object"!==l&&"array"!==l?{}:c.isArray(j)&&[]||j:f-1>e&&"object"!==k&&"array"!==k&&(o[g]=c.isArray(j)&&[]||{}),k=c.type(o[g]),("object"===k||"array"===k)&&(o=o[g],b.unshift(o));else;b.length>p&&b.splice(0,b.length-p)},f.partial=function(a,b,c,d,e){var g=a.partialName.name,h=e&&e[g],i=b.length;h&&f.gen(h,b,c,d,e),b.length>i&&b.splice(0,b.length-i)},f.content=c.noop,f.PARTIAL_NAME=c.noop,f.DATA=c.noop,f.STRING=c.noop,f.INTEGER=c.noop,f.BOOLEAN=c.noop,f.comment=c.noop;var g={};g.each=function(a,b,d){var e,f,g,h,i,j,k,l=b[0];for(i=a.mustache.params[0].parts,e=0,f=i.length;f>e;e++)d.__path.push(i[e]),g=i[e],j=e===f-1?[]:{},h=this.val(g,d,b,j),l[g]=c.isArray(h)&&[]||h,k=c.type(l[g]),("object"===k||"array"===k)&&(l=l[g],b.unshift(l));return h},g["if"]=g.unless=function(a,b,d){var e,f,g,h,i,j,k,l=a.mustache.params,m=b[0];for(e=0;ee;e++)d.__path.push(i[e]),g=i[e],j=e===f-1?[]:{},h=this.val(g,d,b,j),l[g]=c.isArray(h)&&[]||h,k=c.type(l[g]),("object"===k||"array"===k)&&(l=l[g],b.unshift(l));return h}}}.call(this),function(a){if("undefined"!=typeof KISSY){var e,f={debug:!1};KISSY.use("xtemplate",function(a,b){e=b}),this.Mock||(module.exports=f),b.xtpl=function(a,b,c,d){return f.mock(a,b,c,d)},b.xparse=function(a){return e.compiler.parse(a)},f.mock=function(a,b,d,f){return d=d?c.extend({},d,e.RunTime.commands):e.RunTime.commands,f=f?c.extend({},f,e.RunTime.subTpls):e.RunTime.subTpls,this.gen(a,null,b,d,f,{})},f.parse=function(a){return e.compiler.parse(a)},f.gen=function(a,b,d,e,g,h){if("string"==typeof a){f.debug&&console.log("[tpl ]\n",a);var i=this.parse(a);d=this.parseOptions(a,d);var j=this.gen(i,b,d,e,g,h);return j}if(b=b||[{}],d=d||{},a.type=a.type,this[a.type]!==c.noop){d.__path=d.__path||[],f.debug&&(console.log(),console.group("["+a.type+"]",JSON.stringify(a)),console.log("[context]","[before]",b.length,JSON.stringify(b)),console.log("[options]","[before]",d.__path.length,JSON.stringify(d)),console.log("[other ]","[before]",JSON.stringify(h)));var k=d.__path.length;return this[a.type](a,b,d,e,g,h),f.debug&&console.log("[__path ]","[after ]",d.__path),(!h.hold||"function"==typeof h.hold&&!h.hold(a,d,b))&&d.__path.splice(k),f.debug&&(console.log("[context]","[after ]",b.length,JSON.stringify(b)),console.groupEnd()),b[b.length-1]}},f.parseOptions=function(a,b){var d,e,f,g=//g,h=a.match(g),i={};for(d=0;h&&d0)return j[0];if(d in i)return i[d]}return c.isArray(g[0])?{}:h!==a?h:d},f.program=function(a,b,c,d,e,f){for(var g=0;gl;l++)n.push(k&&k[l]!==a?k[l]:{}),f.__path.push(l),e.unshift(n[n.length-1]),this.gen(b.program,e,f,g,h,i),f.__path.pop(),e.shift();else this.gen(b.program,e,f,g,h,i);(!i.hold||"function"==typeof i.hold&&!i.hold(b,f,e))&&e.splice(0,e.length-j)},f.tpl=function(a,b,d,e,f,g){if(a.params&&a.params.length){g=c.extend({},g,{def:{each:[],"if":"@BOOL(2,1,true)",unless:"@BOOL(2,1,false)","with":{}}[a.path.string],hold:{each:!0,"if":function(a,b,c,d,e){return"object"==typeof e},unless:function(a,b,c,d,e){return"object"==typeof e},"with":!0,include:!1}[a.path.string]});for(var h,i=0;i-1?d.float(-Math.pow(10,10),Math.pow(10,10),1,Math.pow(10,6)):d.integer():a}()})),this.gen(b.op2,e,f,g,h,c.extend({},i,{def:function(){return"number"===b.op1.type?b.op1.value.indexOf(".")>-1?d.float(-Math.pow(10,10),Math.pow(10,10),1,Math.pow(10,6)):d.integer():a}()}))},f.relationalExpression=function(a,b,c,d,e,f){this.gen(a.op1,b,c,d,e,f),this.gen(a.op2,b,c,d,e,f)},f.equalityExpression=c.noop,f.conditionalAndExpression=c.noop,f.conditionalOrExpression=c.noop,f.string=c.noop,f.number=c.noop,f.boolean=c.noop,f.hash=function(a,b,c,d,e,f){var g,h=a.value;for(g in h)this.gen(h[g],b,c,d,e,f)},f.id=function(b,d,e,g,h,i){function j(a,b,d,e,f){var g=c.type(a[e]),h=c.type(f);return f="true"===f?!0:"false"===f?!1:f,"undefined"===g?a[e]=d-1>b&&!c.isObjectOrArray(f)?{}:c.isArray(f)&&[]||f:d-1>b&&"object"!==g&&"array"!==g?a[e]=c.isArray(f)&&[]||{}:"object"!==g&&"array"!==g&&"object"!==h&&"array"!==h&&(a[e]=f),a[e]}var k,l,m,n,o,p=d.length,q=b.parts,r=d[b.depth];for(c.isArray(r)&&(r=d[b.depth+1]),k=0,l=q.length;l>k;k++)(0!==k||"this"!==q[k])&&(/^(xindex|xcount|xkey)$/.test(q[k])||0===k&&1===l&&q[k]in g||(e.__path.push(q[k]),m=q[k],n=k===l-1?i.def!==a?i.def:d[0][m]:{},o=this.val(m,e,d,n),f.debug&&(console.log("[def ]",JSON.stringify(n)),console.log("[val ]",JSON.stringify(o))),o=j(r,k,l,m,o),c.isObjectOrArray(r[m])&&d.unshift(r=r[m])));(!i.hold||"function"==typeof i.hold&&!i.hold(b,e,d,m,o))&&d.splice(0,d.length-p)}}}.call(this)}).call(this); -//# sourceMappingURL=dist/mock-min.map diff --git a/WebContent/stat/js/util/structureValidator.js b/WebContent/stat/js/util/structureValidator.js deleted file mode 100644 index a02f69716..000000000 --- a/WebContent/stat/js/util/structureValidator.js +++ /dev/null @@ -1,125 +0,0 @@ -!function() { - var global = this; - - function StructureValidator(o1, o2, leftName, rightName) { - if (!leftName) { - leftName = 'obj'; - } - if (!rightName) { - rightName = 'obj'; - } - if (this === global) { - throw Error('Please use "new StructureValidator(o1, o2);"'); - } - this.o1 = o1; - this.o2 = o2; - this._check(o2, o1, 'left', leftName, true); - this._check(o1, o2, 'right', rightName); - } - - StructureValidator.prototype.getResult = function() { - return { - left : this.left, - right : this.right - }; - }; - - StructureValidator.prototype._check = function(o1, o2, key, keyName, isReverseCheck) { - var result = []; - var LOST = "LOST"; - var EMPTY_ARRAY = "EMPTY_ARRAY"; - var TYPE_NOT_EQUAL = "TYPE_NOT_EQUAL"; - - function typeEqual(a, b) { - if (typeof a != typeof b) { - return false; - } - - var m = {}.toString; - if (m.apply(a) != m.apply(b)) { - return false; - } - - return true; - } - - function isObject(o) { - return o && typeof o === 'object'; - } - - function isArrayObject(o) { - return isObject(o) && {}.toString.apply(o) === "[object Array]"; - } - - function checkStructure(oa, ob, ns) { - var p; - var l, r; - for (p in oa) { - if (oa.hasOwnProperty(p)) { - if (!ob.hasOwnProperty(p)) { - result.push({ - type : LOST, - property : p, - namespace : ns - }); - } else if (!typeEqual(oa[p], ob[p])) { - if (!isReverseCheck) { - result.push({ - type : TYPE_NOT_EQUAL, - property : p, - namespace : ns - }); - } - } else if (isArrayObject(oa[p]) && isArrayObject(ob[p])) { - l = oa[p][0]; - r = ob[p][0]; - if (l && r && isObject(l) && isObject(r)) { - checkStructure(l, r, ns + '.' + p + '[0]'); - } else if (l && !r) { - result.push({ - type : EMPTY_ARRAY, - property : p, - namespace : ns - }); - } - - } else if (isObject(oa[p]) && isObject(ob[p])) { - checkStructure(oa[p], ob[p], ns + '.' + p); - } - } - } - } - - checkStructure(o1, o2, keyName, result); - this[key] = result; - }; - - global.StructureValidator = StructureValidator; - - function tester() { - - var o1 = { - p1 : 1, - p2 : 2, - p3 : 3, - obj : [{ - op3 : 3, - op6 : 6, - op7 : 7 - }] - }; - var o2 = { - p1 : 1, - p3 : 3, - p4 : 4, - obj : [] - }; - - var validator = new StructureValidator(o1, o2); - console.log('result:'); - console.dir(validator.getResult()); - } - - //tester(); - -}(); \ No newline at end of file diff --git a/WebContent/stat/qunit/qunit.css b/WebContent/stat/qunit/qunit.css deleted file mode 100644 index c28d0ffe3..000000000 --- a/WebContent/stat/qunit/qunit.css +++ /dev/null @@ -1,237 +0,0 @@ -/*! - * QUnit 1.14.1pre - * http://qunitjs.com/ - * - * Copyright 2014 jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-03-12T10:25Z - */ - -/** Font Family and Sizes */ - -#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { - font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; -} - -#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } -#qunit-tests { font-size: smaller; } - - -/** Resets */ - -#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { - margin: 0; - padding: 0; -} - - -/** Header */ - -#qunit-header { - padding: 0.5em 0 0.5em 1em; - - color: #8699A4; - background-color: #0D3349; - - font-size: 1.5em; - line-height: 1em; - font-weight: 400; - - border-radius: 5px 5px 0 0; -} - -#qunit-header a { - text-decoration: none; - color: #C2CCD1; -} - -#qunit-header a:hover, -#qunit-header a:focus { - color: #FFF; -} - -#qunit-testrunner-toolbar label { - display: inline-block; - padding: 0 0.5em 0 0.1em; -} - -#qunit-banner { - height: 5px; -} - -#qunit-testrunner-toolbar { - padding: 0.5em 1em 0.5em 1em; - color: #5E740B; - background-color: #EEE; - overflow: hidden; -} - -#qunit-userAgent { - padding: 0.5em 1em 0.5em 1em; - background-color: #2B81AF; - color: #FFF; - text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; -} - -#qunit-modulefilter-container { - float: right; -} - -/** Tests: Pass/Fail */ - -#qunit-tests { - list-style-position: inside; -} - -#qunit-tests li { - padding: 0.4em 1em 0.4em 1em; - border-bottom: 1px solid #FFF; - list-style-position: inside; -} - -#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { - display: none; -} - -#qunit-tests li strong { - cursor: pointer; -} - -#qunit-tests li a { - padding: 0.5em; - color: #C2CCD1; - text-decoration: none; -} -#qunit-tests li a:hover, -#qunit-tests li a:focus { - color: #000; -} - -#qunit-tests li .runtime { - float: right; - font-size: smaller; -} - -.qunit-assert-list { - margin-top: 0.5em; - padding: 0.5em; - - background-color: #FFF; - - border-radius: 5px; -} - -.qunit-collapsed { - display: none; -} - -#qunit-tests table { - border-collapse: collapse; - margin-top: 0.2em; -} - -#qunit-tests th { - text-align: right; - vertical-align: top; - padding: 0 0.5em 0 0; -} - -#qunit-tests td { - vertical-align: top; -} - -#qunit-tests pre { - margin: 0; - white-space: pre-wrap; - word-wrap: break-word; -} - -#qunit-tests del { - background-color: #E0F2BE; - color: #374E0C; - text-decoration: none; -} - -#qunit-tests ins { - background-color: #FFCACA; - color: #500; - text-decoration: none; -} - -/*** Test Counts */ - -#qunit-tests b.counts { color: #000; } -#qunit-tests b.passed { color: #5E740B; } -#qunit-tests b.failed { color: #710909; } - -#qunit-tests li li { - padding: 5px; - background-color: #FFF; - border-bottom: none; - list-style-position: inside; -} - -/*** Passing Styles */ - -#qunit-tests li li.pass { - color: #3C510C; - background-color: #FFF; - border-left: 10px solid #C6E746; -} - -#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } -#qunit-tests .pass .test-name { color: #366097; } - -#qunit-tests .pass .test-actual, -#qunit-tests .pass .test-expected { color: #999; } - -#qunit-banner.qunit-pass { background-color: #C6E746; } - -/*** Failing Styles */ - -#qunit-tests li li.fail { - color: #710909; - background-color: #FFF; - border-left: 10px solid #EE5757; - white-space: pre; -} - -#qunit-tests > li:last-child { - border-radius: 0 0 5px 5px; -} - -#qunit-tests .fail { color: #000; background-color: #EE5757; } -#qunit-tests .fail .test-name, -#qunit-tests .fail .module-name { color: #000; } - -#qunit-tests .fail .test-actual { color: #EE5757; } -#qunit-tests .fail .test-expected { color: #008000; } - -#qunit-banner.qunit-fail { background-color: #EE5757; } - - -/** Result */ - -#qunit-testresult { - padding: 0.5em 1em 0.5em 1em; - - color: #2B81AF; - background-color: #D2E0E6; - - border-bottom: 1px solid #FFF; -} -#qunit-testresult .module-name { - font-weight: 700; -} - -/** Fixture */ - -#qunit-fixture { - position: absolute; - top: -10000px; - left: -10000px; - width: 1000px; - height: 1000px; -} \ No newline at end of file diff --git a/WebContent/stat/qunit/qunit.js b/WebContent/stat/qunit/qunit.js deleted file mode 100644 index 049b57a2d..000000000 --- a/WebContent/stat/qunit/qunit.js +++ /dev/null @@ -1,2289 +0,0 @@ -/*! - * QUnit 1.14.1pre - * http://qunitjs.com/ - * - * Copyright 2014 jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-03-12T10:25Z - */ - - -(function( window ) { - -var QUnit, - assert, - config, - onErrorFnPrev, - testId = 0, - fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""), - toString = Object.prototype.toString, - hasOwn = Object.prototype.hasOwnProperty, - // Keep a local reference to Date (GH-283) - Date = window.Date, - setTimeout = window.setTimeout, - clearTimeout = window.clearTimeout, - defined = { - document: typeof window.document !== "undefined", - setTimeout: typeof window.setTimeout !== "undefined", - sessionStorage: (function() { - var x = "qunit-test-string"; - try { - sessionStorage.setItem( x, x ); - sessionStorage.removeItem( x ); - return true; - } catch( e ) { - return false; - } - }()) - }, - /** - * Provides a normalized error string, correcting an issue - * with IE 7 (and prior) where Error.prototype.toString is - * not properly implemented - * - * Based on http://es5.github.com/#x15.11.4.4 - * - * @param {String|Error} error - * @return {String} error message - */ - errorString = function( error ) { - var name, message, - errorString = error.toString(); - if ( errorString.substring( 0, 7 ) === "[object" ) { - name = error.name ? error.name.toString() : "Error"; - message = error.message ? error.message.toString() : ""; - if ( name && message ) { - return name + ": " + message; - } else if ( name ) { - return name; - } else if ( message ) { - return message; - } else { - return "Error"; - } - } else { - return errorString; - } - }, - /** - * Makes a clone of an object using only Array or Object as base, - * and copies over the own enumerable properties. - * - * @param {Object} obj - * @return {Object} New object with only the own properties (recursively). - */ - objectValues = function( obj ) { - // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392. - /*jshint newcap: false */ - var key, val, - vals = QUnit.is( "array", obj ) ? [] : {}; - for ( key in obj ) { - if ( hasOwn.call( obj, key ) ) { - val = obj[key]; - vals[key] = val === Object(val) ? objectValues(val) : val; - } - } - return vals; - }; - - -// Root QUnit object. -// `QUnit` initialized at top of scope -QUnit = { - - // call on start of module test to prepend name to all tests - module: function( name, testEnvironment ) { - config.currentModule = name; - config.currentModuleTestEnvironment = testEnvironment; - config.modules[name] = true; - }, - - asyncTest: function( testName, expected, callback ) { - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - QUnit.test( testName, expected, callback, true ); - }, - - test: function( testName, expected, callback, async ) { - var test, - nameHtml = "" + escapeText( testName ) + ""; - - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - - if ( config.currentModule ) { - nameHtml = "" + escapeText( config.currentModule ) + ": " + nameHtml; - } - - test = new Test({ - nameHtml: nameHtml, - testName: testName, - expected: expected, - async: async, - callback: callback, - module: config.currentModule, - moduleTestEnvironment: config.currentModuleTestEnvironment, - stack: sourceFromStacktrace( 2 ) - }); - - if ( !validTest( test ) ) { - return; - } - - test.queue(); - }, - - // Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through. - expect: function( asserts ) { - if (arguments.length === 1) { - config.current.expected = asserts; - } else { - return config.current.expected; - } - }, - - start: function( count ) { - // QUnit hasn't been initialized yet. - // Note: RequireJS (et al) may delay onLoad - if ( config.semaphore === undefined ) { - QUnit.begin(function() { - // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first - setTimeout(function() { - QUnit.start( count ); - }); - }); - return; - } - - config.semaphore -= count || 1; - // don't start until equal number of stop-calls - if ( config.semaphore > 0 ) { - return; - } - // ignore if start is called more often then stop - if ( config.semaphore < 0 ) { - config.semaphore = 0; - QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) ); - return; - } - // A slight delay, to avoid any current callbacks - if ( defined.setTimeout ) { - setTimeout(function() { - if ( config.semaphore > 0 ) { - return; - } - if ( config.timeout ) { - clearTimeout( config.timeout ); - } - - config.blocking = false; - process( true ); - }, 13); - } else { - config.blocking = false; - process( true ); - } - }, - - stop: function( count ) { - config.semaphore += count || 1; - config.blocking = true; - - if ( config.testTimeout && defined.setTimeout ) { - clearTimeout( config.timeout ); - config.timeout = setTimeout(function() { - QUnit.ok( false, "Test timed out" ); - config.semaphore = 1; - QUnit.start(); - }, config.testTimeout ); - } - } -}; - -// We use the prototype to distinguish between properties that should -// be exposed as globals (and in exports) and those that shouldn't -(function() { - function F() {} - F.prototype = QUnit; - QUnit = new F(); - // Make F QUnit's constructor so that we can add to the prototype later - QUnit.constructor = F; -}()); - -/** - * Config object: Maintain internal state - * Later exposed as QUnit.config - * `config` initialized at top of scope - */ -config = { - // The queue of tests to run - queue: [], - - // block until document ready - blocking: true, - - // when enabled, show only failing tests - // gets persisted through sessionStorage and can be changed in UI via checkbox - hidepassed: false, - - // by default, run previously failed tests first - // very useful in combination with "Hide passed tests" checked - reorder: true, - - // by default, modify document.title when suite is done - altertitle: true, - - // by default, scroll to top of the page when suite is done - scrolltop: true, - - // when enabled, all tests must call expect() - requireExpects: false, - - // add checkboxes that are persisted in the query-string - // when enabled, the id is set to `true` as a `QUnit.config` property - urlConfig: [ - { - id: "noglobals", - label: "Check for Globals", - tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings." - }, - { - id: "notrycatch", - label: "No try-catch", - tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings." - } - ], - - // Set of all modules. - modules: {}, - - // logging callback queues - begin: [], - done: [], - log: [], - testStart: [], - testDone: [], - moduleStart: [], - moduleDone: [] -}; - -// Initialize more QUnit.config and QUnit.urlParams -(function() { - var i, current, - location = window.location || { search: "", protocol: "file:" }, - params = location.search.slice( 1 ).split( "&" ), - length = params.length, - urlParams = {}; - - if ( params[ 0 ] ) { - for ( i = 0; i < length; i++ ) { - current = params[ i ].split( "=" ); - current[ 0 ] = decodeURIComponent( current[ 0 ] ); - - // allow just a key to turn on a flag, e.g., test.html?noglobals - current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; - if ( urlParams[ current[ 0 ] ] ) { - urlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] ); - } else { - urlParams[ current[ 0 ] ] = current[ 1 ]; - } - } - } - - QUnit.urlParams = urlParams; - - // String search anywhere in moduleName+testName - config.filter = urlParams.filter; - - // Exact match of the module name - config.module = urlParams.module; - - config.testNumber = []; - if ( urlParams.testNumber ) { - - // Ensure that urlParams.testNumber is an array - urlParams.testNumber = [].concat( urlParams.testNumber ); - for ( i = 0; i < urlParams.testNumber.length; i++ ) { - current = urlParams.testNumber[ i ]; - config.testNumber.push( parseInt( current, 10 ) ); - } - } - - // Figure out if we're running the tests from a server or not - QUnit.isLocal = location.protocol === "file:"; -}()); - -extend( QUnit, { - - config: config, - - // Initialize the configuration options - init: function() { - extend( config, { - stats: { all: 0, bad: 0 }, - moduleStats: { all: 0, bad: 0 }, - started: +new Date(), - updateRate: 1000, - blocking: false, - autostart: true, - autorun: false, - filter: "", - queue: [], - semaphore: 1 - }); - - var tests, banner, result, - qunit = id( "qunit" ); - - if ( qunit ) { - qunit.innerHTML = - "

" + escapeText( document.title ) + "

" + - "

" + - "
" + - "

" + - "
    "; - } - - tests = id( "qunit-tests" ); - banner = id( "qunit-banner" ); - result = id( "qunit-testresult" ); - - if ( tests ) { - tests.innerHTML = ""; - } - - if ( banner ) { - banner.className = ""; - } - - if ( result ) { - result.parentNode.removeChild( result ); - } - - if ( tests ) { - result = document.createElement( "p" ); - result.id = "qunit-testresult"; - result.className = "result"; - tests.parentNode.insertBefore( result, tests ); - result.innerHTML = "Running...
     "; - } - }, - - // Resets the test setup. Useful for tests that modify the DOM. - /* - DEPRECATED: Use multiple tests instead of resetting inside a test. - Use testStart or testDone for custom cleanup. - This method will throw an error in 2.0, and will be removed in 2.1 - */ - reset: function() { - var fixture = id( "qunit-fixture" ); - if ( fixture ) { - fixture.innerHTML = config.fixture; - } - }, - - // Safe object type checking - is: function( type, obj ) { - return QUnit.objectType( obj ) === type; - }, - - objectType: function( obj ) { - if ( typeof obj === "undefined" ) { - return "undefined"; - } - - // Consider: typeof null === object - if ( obj === null ) { - return "null"; - } - - var match = toString.call( obj ).match(/^\[object\s(.*)\]$/), - type = match && match[1] || ""; - - switch ( type ) { - case "Number": - if ( isNaN(obj) ) { - return "nan"; - } - return "number"; - case "String": - case "Boolean": - case "Array": - case "Date": - case "RegExp": - case "Function": - return type.toLowerCase(); - } - if ( typeof obj === "object" ) { - return "object"; - } - return undefined; - }, - - push: function( result, actual, expected, message ) { - if ( !config.current ) { - throw new Error( "assertion outside test context, was " + sourceFromStacktrace() ); - } - - var output, source, - details = { - module: config.current.module, - name: config.current.testName, - result: result, - message: message, - actual: actual, - expected: expected - }; - - message = escapeText( message ) || ( result ? "okay" : "failed" ); - message = "" + message + ""; - output = message; - - if ( !result ) { - expected = escapeText( QUnit.jsDump.parse(expected) ); - actual = escapeText( QUnit.jsDump.parse(actual) ); - output += ""; - - if ( actual !== expected ) { - output += ""; - output += ""; - } - - source = sourceFromStacktrace(); - - if ( source ) { - details.source = source; - output += ""; - } - - output += "
    Expected:
    " + expected + "
    Result:
    " + actual + "
    Diff:
    " + QUnit.diff( expected, actual ) + "
    Source:
    " + escapeText( source ) + "
    "; - } - - runLoggingCallbacks( "log", QUnit, details ); - - config.current.assertions.push({ - result: !!result, - message: output - }); - }, - - pushFailure: function( message, source, actual ) { - if ( !config.current ) { - throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) ); - } - - var output, - details = { - module: config.current.module, - name: config.current.testName, - result: false, - message: message - }; - - message = escapeText( message ) || "error"; - message = "" + message + ""; - output = message; - - output += ""; - - if ( actual ) { - output += ""; - } - - if ( source ) { - details.source = source; - output += ""; - } - - output += "
    Result:
    " + escapeText( actual ) + "
    Source:
    " + escapeText( source ) + "
    "; - - runLoggingCallbacks( "log", QUnit, details ); - - config.current.assertions.push({ - result: false, - message: output - }); - }, - - url: function( params ) { - params = extend( extend( {}, QUnit.urlParams ), params ); - var key, - querystring = "?"; - - for ( key in params ) { - if ( hasOwn.call( params, key ) ) { - querystring += encodeURIComponent( key ) + "=" + - encodeURIComponent( params[ key ] ) + "&"; - } - } - return window.location.protocol + "//" + window.location.host + - window.location.pathname + querystring.slice( 0, -1 ); - }, - - extend: extend, - id: id, - addEvent: addEvent, - addClass: addClass, - hasClass: hasClass, - removeClass: removeClass - // load, equiv, jsDump, diff: Attached later -}); - -/** - * @deprecated: Created for backwards compatibility with test runner that set the hook function - * into QUnit.{hook}, instead of invoking it and passing the hook function. - * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here. - * Doing this allows us to tell if the following methods have been overwritten on the actual - * QUnit object. - */ -extend( QUnit.constructor.prototype, { - - // Logging callbacks; all receive a single argument with the listed properties - // run test/logs.html for any related changes - begin: registerLoggingCallback( "begin" ), - - // done: { failed, passed, total, runtime } - done: registerLoggingCallback( "done" ), - - // log: { result, actual, expected, message } - log: registerLoggingCallback( "log" ), - - // testStart: { name } - testStart: registerLoggingCallback( "testStart" ), - - // testDone: { name, failed, passed, total, runtime } - testDone: registerLoggingCallback( "testDone" ), - - // moduleStart: { name } - moduleStart: registerLoggingCallback( "moduleStart" ), - - // moduleDone: { name, failed, passed, total } - moduleDone: registerLoggingCallback( "moduleDone" ) -}); - -if ( !defined.document || document.readyState === "complete" ) { - config.autorun = true; -} - -QUnit.load = function() { - runLoggingCallbacks( "begin", QUnit, {} ); - - // Initialize the config, saving the execution queue - var banner, filter, i, j, label, len, main, ol, toolbar, val, selection, - urlConfigContainer, moduleFilter, userAgent, - numModules = 0, - moduleNames = [], - moduleFilterHtml = "", - urlConfigHtml = "", - oldconfig = extend( {}, config ); - - QUnit.init(); - extend(config, oldconfig); - - config.blocking = false; - - len = config.urlConfig.length; - - for ( i = 0; i < len; i++ ) { - val = config.urlConfig[i]; - if ( typeof val === "string" ) { - val = { - id: val, - label: val - }; - } - config[ val.id ] = QUnit.urlParams[ val.id ]; - if ( !val.value || typeof val.value === "string" ) { - urlConfigHtml += ""; - } else { - urlConfigHtml += ""; - } - } - for ( i in config.modules ) { - if ( config.modules.hasOwnProperty( i ) ) { - moduleNames.push(i); - } - } - numModules = moduleNames.length; - moduleNames.sort( function( a, b ) { - return a.localeCompare( b ); - }); - moduleFilterHtml += ""; - - // `userAgent` initialized at top of scope - userAgent = id( "qunit-userAgent" ); - if ( userAgent ) { - userAgent.innerHTML = navigator.userAgent; - } - - // `banner` initialized at top of scope - banner = id( "qunit-header" ); - if ( banner ) { - banner.innerHTML = "" + banner.innerHTML + " "; - } - - // `toolbar` initialized at top of scope - toolbar = id( "qunit-testrunner-toolbar" ); - if ( toolbar ) { - // `filter` initialized at top of scope - filter = document.createElement( "input" ); - filter.type = "checkbox"; - filter.id = "qunit-filter-pass"; - - addEvent( filter, "click", function() { - var tmp, - ol = id( "qunit-tests" ); - - if ( filter.checked ) { - ol.className = ol.className + " hidepass"; - } else { - tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " "; - ol.className = tmp.replace( / hidepass /, " " ); - } - if ( defined.sessionStorage ) { - if (filter.checked) { - sessionStorage.setItem( "qunit-filter-passed-tests", "true" ); - } else { - sessionStorage.removeItem( "qunit-filter-passed-tests" ); - } - } - }); - - if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) { - filter.checked = true; - // `ol` initialized at top of scope - ol = id( "qunit-tests" ); - ol.className = ol.className + " hidepass"; - } - toolbar.appendChild( filter ); - - // `label` initialized at top of scope - label = document.createElement( "label" ); - label.setAttribute( "for", "qunit-filter-pass" ); - label.setAttribute( "title", "Only show tests and assertions that fail. Stored in sessionStorage." ); - label.innerHTML = "Hide passed tests"; - toolbar.appendChild( label ); - - urlConfigContainer = document.createElement("span"); - urlConfigContainer.innerHTML = urlConfigHtml; - // For oldIE support: - // * Add handlers to the individual elements instead of the container - // * Use "click" instead of "change" for checkboxes - // * Fallback from event.target to event.srcElement - addEvents( urlConfigContainer.getElementsByTagName("input"), "click", function( event ) { - var params = {}, - target = event.target || event.srcElement; - params[ target.name ] = target.checked ? - target.defaultValue || true : - undefined; - window.location = QUnit.url( params ); - }); - addEvents( urlConfigContainer.getElementsByTagName("select"), "change", function( event ) { - var params = {}, - target = event.target || event.srcElement; - params[ target.name ] = target.options[ target.selectedIndex ].value || undefined; - window.location = QUnit.url( params ); - }); - toolbar.appendChild( urlConfigContainer ); - - if (numModules > 1) { - moduleFilter = document.createElement( "span" ); - moduleFilter.setAttribute( "id", "qunit-modulefilter-container" ); - moduleFilter.innerHTML = moduleFilterHtml; - addEvent( moduleFilter.lastChild, "change", function() { - var selectBox = moduleFilter.getElementsByTagName("select")[0], - selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value); - - window.location = QUnit.url({ - module: ( selectedModule === "" ) ? undefined : selectedModule, - // Remove any existing filters - filter: undefined, - testNumber: undefined - }); - }); - toolbar.appendChild(moduleFilter); - } - } - - // `main` initialized at top of scope - main = id( "qunit-fixture" ); - if ( main ) { - config.fixture = main.innerHTML; - } - - if ( config.autostart ) { - QUnit.start(); - } -}; - -if ( defined.document ) { - addEvent( window, "load", QUnit.load ); -} - -// `onErrorFnPrev` initialized at top of scope -// Preserve other handlers -onErrorFnPrev = window.onerror; - -// Cover uncaught exceptions -// Returning true will suppress the default browser handler, -// returning false will let it run. -window.onerror = function ( error, filePath, linerNr ) { - var ret = false; - if ( onErrorFnPrev ) { - ret = onErrorFnPrev( error, filePath, linerNr ); - } - - // Treat return value as window.onerror itself does, - // Only do our handling if not suppressed. - if ( ret !== true ) { - if ( QUnit.config.current ) { - if ( QUnit.config.current.ignoreGlobalErrors ) { - return true; - } - QUnit.pushFailure( error, filePath + ":" + linerNr ); - } else { - QUnit.test( "global failure", extend( function() { - QUnit.pushFailure( error, filePath + ":" + linerNr ); - }, { validTest: validTest } ) ); - } - return false; - } - - return ret; -}; - -function done() { - config.autorun = true; - - // Log the last module results - if ( config.previousModule ) { - runLoggingCallbacks( "moduleDone", QUnit, { - name: config.previousModule, - failed: config.moduleStats.bad, - passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all - }); - } - delete config.previousModule; - - var i, key, - banner = id( "qunit-banner" ), - tests = id( "qunit-tests" ), - runtime = +new Date() - config.started, - passed = config.stats.all - config.stats.bad, - html = [ - "Tests completed in ", - runtime, - " milliseconds.
    ", - "", - passed, - " assertions of ", - config.stats.all, - " passed, ", - config.stats.bad, - " failed." - ].join( "" ); - - if ( banner ) { - banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" ); - } - - if ( tests ) { - id( "qunit-testresult" ).innerHTML = html; - } - - if ( config.altertitle && defined.document && document.title ) { - // show ✖ for good, ✔ for bad suite result in title - // use escape sequences in case file gets loaded with non-utf-8-charset - document.title = [ - ( config.stats.bad ? "\u2716" : "\u2714" ), - document.title.replace( /^[\u2714\u2716] /i, "" ) - ].join( " " ); - } - - // clear own sessionStorage items if all tests passed - if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) { - // `key` & `i` initialized at top of scope - for ( i = 0; i < sessionStorage.length; i++ ) { - key = sessionStorage.key( i++ ); - if ( key.indexOf( "qunit-test-" ) === 0 ) { - sessionStorage.removeItem( key ); - } - } - } - - // scroll back to top to show results - if ( config.scrolltop && window.scrollTo ) { - window.scrollTo(0, 0); - } - - runLoggingCallbacks( "done", QUnit, { - failed: config.stats.bad, - passed: passed, - total: config.stats.all, - runtime: runtime - }); -} - -/** @return Boolean: true if this test should be ran */ -function validTest( test ) { - var include, - filter = config.filter && config.filter.toLowerCase(), - module = config.module && config.module.toLowerCase(), - fullName = ( test.module + ": " + test.testName ).toLowerCase(); - - // Internally-generated tests are always valid - if ( test.callback && test.callback.validTest === validTest ) { - delete test.callback.validTest; - return true; - } - - if ( config.testNumber.length > 0 ) { - if ( inArray( test.testNumber, config.testNumber ) < 0 ) { - return false; - } - } - - if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) { - return false; - } - - if ( !filter ) { - return true; - } - - include = filter.charAt( 0 ) !== "!"; - if ( !include ) { - filter = filter.slice( 1 ); - } - - // If the filter matches, we need to honour include - if ( fullName.indexOf( filter ) !== -1 ) { - return include; - } - - // Otherwise, do the opposite - return !include; -} - -// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions) -// Later Safari and IE10 are supposed to support error.stack as well -// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack -function extractStacktrace( e, offset ) { - offset = offset === undefined ? 3 : offset; - - var stack, include, i; - - if ( e.stacktrace ) { - // Opera - return e.stacktrace.split( "\n" )[ offset + 3 ]; - } else if ( e.stack ) { - // Firefox, Chrome - stack = e.stack.split( "\n" ); - if (/^error$/i.test( stack[0] ) ) { - stack.shift(); - } - if ( fileName ) { - include = []; - for ( i = offset; i < stack.length; i++ ) { - if ( stack[ i ].indexOf( fileName ) !== -1 ) { - break; - } - include.push( stack[ i ] ); - } - if ( include.length ) { - return include.join( "\n" ); - } - } - return stack[ offset ]; - } else if ( e.sourceURL ) { - // Safari, PhantomJS - // hopefully one day Safari provides actual stacktraces - // exclude useless self-reference for generated Error objects - if ( /qunit.js$/.test( e.sourceURL ) ) { - return; - } - // for actual exceptions, this is useful - return e.sourceURL + ":" + e.line; - } -} -function sourceFromStacktrace( offset ) { - try { - throw new Error(); - } catch ( e ) { - return extractStacktrace( e, offset ); - } -} - -/** - * Escape text for attribute or text content. - */ -function escapeText( s ) { - if ( !s ) { - return ""; - } - s = s + ""; - // Both single quotes and double quotes (for attributes) - return s.replace( /['"<>&]/g, function( s ) { - switch( s ) { - case "'": - return "'"; - case "\"": - return """; - case "<": - return "<"; - case ">": - return ">"; - case "&": - return "&"; - } - }); -} - -function synchronize( callback, last ) { - config.queue.push( callback ); - - if ( config.autorun && !config.blocking ) { - process( last ); - } -} - -function process( last ) { - function next() { - process( last ); - } - var start = new Date().getTime(); - config.depth = config.depth ? config.depth + 1 : 1; - - while ( config.queue.length && !config.blocking ) { - if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) { - config.queue.shift()(); - } else { - setTimeout( next, 13 ); - break; - } - } - config.depth--; - if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) { - done(); - } -} - -function saveGlobal() { - config.pollution = []; - - if ( config.noglobals ) { - for ( var key in window ) { - if ( hasOwn.call( window, key ) ) { - // in Opera sometimes DOM element ids show up here, ignore them - if ( /^qunit-test-output/.test( key ) ) { - continue; - } - config.pollution.push( key ); - } - } - } -} - -function checkPollution() { - var newGlobals, - deletedGlobals, - old = config.pollution; - - saveGlobal(); - - newGlobals = diff( config.pollution, old ); - if ( newGlobals.length > 0 ) { - QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") ); - } - - deletedGlobals = diff( old, config.pollution ); - if ( deletedGlobals.length > 0 ) { - QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") ); - } -} - -// returns a new Array with the elements that are in a but not in b -function diff( a, b ) { - var i, j, - result = a.slice(); - - for ( i = 0; i < result.length; i++ ) { - for ( j = 0; j < b.length; j++ ) { - if ( result[i] === b[j] ) { - result.splice( i, 1 ); - i--; - break; - } - } - } - return result; -} - -function extend( a, b ) { - for ( var prop in b ) { - if ( hasOwn.call( b, prop ) ) { - // Avoid "Member not found" error in IE8 caused by messing with window.constructor - if ( !( prop === "constructor" && a === window ) ) { - if ( b[ prop ] === undefined ) { - delete a[ prop ]; - } else { - a[ prop ] = b[ prop ]; - } - } - } - } - - return a; -} - -/** - * @param {HTMLElement} elem - * @param {string} type - * @param {Function} fn - */ -function addEvent( elem, type, fn ) { - if ( elem.addEventListener ) { - - // Standards-based browsers - elem.addEventListener( type, fn, false ); - } else if ( elem.attachEvent ) { - - // support: IE <9 - elem.attachEvent( "on" + type, fn ); - } else { - - // Caller must ensure support for event listeners is present - throw new Error( "addEvent() was called in a context without event listener support" ); - } -} - -/** - * @param {Array|NodeList} elems - * @param {string} type - * @param {Function} fn - */ -function addEvents( elems, type, fn ) { - var i = elems.length; - while ( i-- ) { - addEvent( elems[i], type, fn ); - } -} - -function hasClass( elem, name ) { - return (" " + elem.className + " ").indexOf(" " + name + " ") > -1; -} - -function addClass( elem, name ) { - if ( !hasClass( elem, name ) ) { - elem.className += (elem.className ? " " : "") + name; - } -} - -function removeClass( elem, name ) { - var set = " " + elem.className + " "; - // Class name may appear multiple times - while ( set.indexOf(" " + name + " ") > -1 ) { - set = set.replace(" " + name + " " , " "); - } - // If possible, trim it for prettiness, but not necessarily - elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, ""); -} - -function id( name ) { - return defined.document && document.getElementById && document.getElementById( name ); -} - -function registerLoggingCallback( key ) { - return function( callback ) { - config[key].push( callback ); - }; -} - -// Supports deprecated method of completely overwriting logging callbacks -function runLoggingCallbacks( key, scope, args ) { - var i, callbacks; - if ( QUnit.hasOwnProperty( key ) ) { - QUnit[ key ].call(scope, args ); - } else { - callbacks = config[ key ]; - for ( i = 0; i < callbacks.length; i++ ) { - callbacks[ i ].call( scope, args ); - } - } -} - -// from jquery.js -function inArray( elem, array ) { - if ( array.indexOf ) { - return array.indexOf( elem ); - } - - for ( var i = 0, length = array.length; i < length; i++ ) { - if ( array[ i ] === elem ) { - return i; - } - } - - return -1; -} - -function Test( settings ) { - extend( this, settings ); - this.assertions = []; - this.testNumber = ++Test.count; -} - -Test.count = 0; - -Test.prototype = { - init: function() { - var a, b, li, - tests = id( "qunit-tests" ); - - if ( tests ) { - b = document.createElement( "strong" ); - b.innerHTML = this.nameHtml; - - // `a` initialized at top of scope - a = document.createElement( "a" ); - a.innerHTML = "Rerun"; - a.href = QUnit.url({ testNumber: this.testNumber }); - - li = document.createElement( "li" ); - li.appendChild( b ); - li.appendChild( a ); - li.className = "running"; - li.id = this.id = "qunit-test-output" + testId++; - - tests.appendChild( li ); - } - }, - setup: function() { - if ( - // Emit moduleStart when we're switching from one module to another - this.module !== config.previousModule || - // They could be equal (both undefined) but if the previousModule property doesn't - // yet exist it means this is the first test in a suite that isn't wrapped in a - // module, in which case we'll just emit a moduleStart event for 'undefined'. - // Without this, reporters can get testStart before moduleStart which is a problem. - !hasOwn.call( config, "previousModule" ) - ) { - if ( hasOwn.call( config, "previousModule" ) ) { - runLoggingCallbacks( "moduleDone", QUnit, { - name: config.previousModule, - failed: config.moduleStats.bad, - passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all - }); - } - config.previousModule = this.module; - config.moduleStats = { all: 0, bad: 0 }; - runLoggingCallbacks( "moduleStart", QUnit, { - name: this.module - }); - } - - config.current = this; - - this.testEnvironment = extend({ - setup: function() {}, - teardown: function() {} - }, this.moduleTestEnvironment ); - - this.started = +new Date(); - runLoggingCallbacks( "testStart", QUnit, { - name: this.testName, - module: this.module - }); - - /*jshint camelcase:false */ - - - /** - * Expose the current test environment. - * - * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead. - */ - QUnit.current_testEnvironment = this.testEnvironment; - - /*jshint camelcase:true */ - - if ( !config.pollution ) { - saveGlobal(); - } - if ( config.notrycatch ) { - this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert ); - return; - } - try { - this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert ); - } catch( e ) { - QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) ); - } - }, - run: function() { - config.current = this; - - var running = id( "qunit-testresult" ); - - if ( running ) { - running.innerHTML = "Running:
    " + this.nameHtml; - } - - if ( this.async ) { - QUnit.stop(); - } - - this.callbackStarted = +new Date(); - - if ( config.notrycatch ) { - this.callback.call( this.testEnvironment, QUnit.assert ); - this.callbackRuntime = +new Date() - this.callbackStarted; - return; - } - - try { - this.callback.call( this.testEnvironment, QUnit.assert ); - this.callbackRuntime = +new Date() - this.callbackStarted; - } catch( e ) { - this.callbackRuntime = +new Date() - this.callbackStarted; - - QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); - // else next test will carry the responsibility - saveGlobal(); - - // Restart the tests if they're blocking - if ( config.blocking ) { - QUnit.start(); - } - } - }, - teardown: function() { - config.current = this; - if ( config.notrycatch ) { - if ( typeof this.callbackRuntime === "undefined" ) { - this.callbackRuntime = +new Date() - this.callbackStarted; - } - this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert ); - return; - } else { - try { - this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert ); - } catch( e ) { - QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) ); - } - } - checkPollution(); - }, - finish: function() { - config.current = this; - if ( config.requireExpects && this.expected === null ) { - QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack ); - } else if ( this.expected !== null && this.expected !== this.assertions.length ) { - QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack ); - } else if ( this.expected === null && !this.assertions.length ) { - QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack ); - } - - var i, assertion, a, b, time, li, ol, - test = this, - good = 0, - bad = 0, - tests = id( "qunit-tests" ); - - this.runtime = +new Date() - this.started; - config.stats.all += this.assertions.length; - config.moduleStats.all += this.assertions.length; - - if ( tests ) { - ol = document.createElement( "ol" ); - ol.className = "qunit-assert-list"; - - for ( i = 0; i < this.assertions.length; i++ ) { - assertion = this.assertions[i]; - - li = document.createElement( "li" ); - li.className = assertion.result ? "pass" : "fail"; - li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" ); - ol.appendChild( li ); - - if ( assertion.result ) { - good++; - } else { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - - // store result when possible - if ( QUnit.config.reorder && defined.sessionStorage ) { - if ( bad ) { - sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad ); - } else { - sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName ); - } - } - - if ( bad === 0 ) { - addClass( ol, "qunit-collapsed" ); - } - - // `b` initialized at top of scope - b = document.createElement( "strong" ); - b.innerHTML = this.nameHtml + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; - - addEvent(b, "click", function() { - var next = b.parentNode.lastChild, - collapsed = hasClass( next, "qunit-collapsed" ); - ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" ); - }); - - addEvent(b, "dblclick", function( e ) { - var target = e && e.target ? e.target : window.event.srcElement; - if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) { - target = target.parentNode; - } - if ( window.location && target.nodeName.toLowerCase() === "strong" ) { - window.location = QUnit.url({ testNumber: test.testNumber }); - } - }); - - // `time` initialized at top of scope - time = document.createElement( "span" ); - time.className = "runtime"; - time.innerHTML = this.runtime + " ms"; - - // `li` initialized at top of scope - li = id( this.id ); - li.className = bad ? "fail" : "pass"; - li.removeChild( li.firstChild ); - a = li.firstChild; - li.appendChild( b ); - li.appendChild( a ); - li.appendChild( time ); - li.appendChild( ol ); - - } else { - for ( i = 0; i < this.assertions.length; i++ ) { - if ( !this.assertions[i].result ) { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - } - - runLoggingCallbacks( "testDone", QUnit, { - name: this.testName, - module: this.module, - failed: bad, - passed: this.assertions.length - bad, - total: this.assertions.length, - runtime: this.runtime, - // DEPRECATED: this property will be removed in 2.0.0, use runtime instead - duration: this.runtime - }); - - QUnit.reset(); - - config.current = undefined; - }, - - queue: function() { - var bad, - test = this; - - synchronize(function() { - test.init(); - }); - function run() { - // each of these can by async - synchronize(function() { - test.setup(); - }); - synchronize(function() { - test.run(); - }); - synchronize(function() { - test.teardown(); - }); - synchronize(function() { - test.finish(); - }); - } - - // `bad` initialized at top of scope - // defer when previous test run passed, if storage is available - bad = QUnit.config.reorder && defined.sessionStorage && - +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName ); - - if ( bad ) { - run(); - } else { - synchronize( run, true ); - } - } -}; - -// `assert` initialized at top of scope -// Assert helpers -// All of these must either call QUnit.push() or manually do: -// - runLoggingCallbacks( "log", .. ); -// - config.current.assertions.push({ .. }); -assert = QUnit.assert = { - /** - * Asserts rough true-ish result. - * @name ok - * @function - * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); - */ - ok: function( result, msg ) { - if ( !config.current ) { - throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) ); - } - result = !!result; - msg = msg || ( result ? "okay" : "failed" ); - - var source, - details = { - module: config.current.module, - name: config.current.testName, - result: result, - message: msg - }; - - msg = "" + escapeText( msg ) + ""; - - if ( !result ) { - source = sourceFromStacktrace( 2 ); - if ( source ) { - details.source = source; - msg += "
    Source:
    " +
    -					escapeText( source ) +
    -					"
    "; - } - } - runLoggingCallbacks( "log", QUnit, details ); - config.current.assertions.push({ - result: result, - message: msg - }); - }, - - /** - * Assert that the first two arguments are equal, with an optional message. - * Prints out both actual and expected values. - * @name equal - * @function - * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" ); - */ - equal: function( actual, expected, message ) { - /*jshint eqeqeq:false */ - QUnit.push( expected == actual, actual, expected, message ); - }, - - /** - * @name notEqual - * @function - */ - notEqual: function( actual, expected, message ) { - /*jshint eqeqeq:false */ - QUnit.push( expected != actual, actual, expected, message ); - }, - - /** - * @name propEqual - * @function - */ - propEqual: function( actual, expected, message ) { - actual = objectValues(actual); - expected = objectValues(expected); - QUnit.push( QUnit.equiv(actual, expected), actual, expected, message ); - }, - - /** - * @name notPropEqual - * @function - */ - notPropEqual: function( actual, expected, message ) { - actual = objectValues(actual); - expected = objectValues(expected); - QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message ); - }, - - /** - * @name deepEqual - * @function - */ - deepEqual: function( actual, expected, message ) { - QUnit.push( QUnit.equiv(actual, expected), actual, expected, message ); - }, - - /** - * @name notDeepEqual - * @function - */ - notDeepEqual: function( actual, expected, message ) { - QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message ); - }, - - /** - * @name strictEqual - * @function - */ - strictEqual: function( actual, expected, message ) { - QUnit.push( expected === actual, actual, expected, message ); - }, - - /** - * @name notStrictEqual - * @function - */ - notStrictEqual: function( actual, expected, message ) { - QUnit.push( expected !== actual, actual, expected, message ); - }, - - "throws": function( block, expected, message ) { - var actual, - expectedOutput = expected, - ok = false; - - // 'expected' is optional - if ( !message && typeof expected === "string" ) { - message = expected; - expected = null; - } - - config.current.ignoreGlobalErrors = true; - try { - block.call( config.current.testEnvironment ); - } catch (e) { - actual = e; - } - config.current.ignoreGlobalErrors = false; - - if ( actual ) { - - // we don't want to validate thrown error - if ( !expected ) { - ok = true; - expectedOutput = null; - - // expected is an Error object - } else if ( expected instanceof Error ) { - ok = actual instanceof Error && - actual.name === expected.name && - actual.message === expected.message; - - // expected is a regexp - } else if ( QUnit.objectType( expected ) === "regexp" ) { - ok = expected.test( errorString( actual ) ); - - // expected is a string - } else if ( QUnit.objectType( expected ) === "string" ) { - ok = expected === errorString( actual ); - - // expected is a constructor - } else if ( actual instanceof expected ) { - ok = true; - - // expected is a validation function which returns true is validation passed - } else if ( expected.call( {}, actual ) === true ) { - expectedOutput = null; - ok = true; - } - - QUnit.push( ok, actual, expectedOutput, message ); - } else { - QUnit.pushFailure( message, null, "No exception was thrown." ); - } - } -}; - -/** - * @deprecated since 1.8.0 - * Kept assertion helpers in root for backwards compatibility. - */ -extend( QUnit.constructor.prototype, assert ); - -/** - * @deprecated since 1.9.0 - * Kept to avoid TypeErrors for undefined methods. - */ -QUnit.constructor.prototype.raises = function() { - QUnit.push( false, false, false, "QUnit.raises has been deprecated since 2012 (fad3c1ea), use QUnit.throws instead" ); -}; - -/** - * @deprecated since 1.0.0, replaced with error pushes since 1.3.0 - * Kept to avoid TypeErrors for undefined methods. - */ -QUnit.constructor.prototype.equals = function() { - QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" ); -}; -QUnit.constructor.prototype.same = function() { - QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" ); -}; - -// Test for equality any JavaScript type. -// Author: Philippe Rathé -QUnit.equiv = (function() { - - // Call the o related callback with the given arguments. - function bindCallbacks( o, callbacks, args ) { - var prop = QUnit.objectType( o ); - if ( prop ) { - if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) { - return callbacks[ prop ].apply( callbacks, args ); - } else { - return callbacks[ prop ]; // or undefined - } - } - } - - // the real equiv function - var innerEquiv, - // stack to decide between skip/abort functions - callers = [], - // stack to avoiding loops from circular referencing - parents = [], - parentsB = [], - - getProto = Object.getPrototypeOf || function ( obj ) { - /* jshint camelcase: false, proto: true */ - return obj.__proto__; - }, - callbacks = (function () { - - // for string, boolean, number and null - function useStrictEquality( b, a ) { - /*jshint eqeqeq:false */ - if ( b instanceof a.constructor || a instanceof b.constructor ) { - // to catch short annotation VS 'new' annotation of a - // declaration - // e.g. var i = 1; - // var j = new Number(1); - return a == b; - } else { - return a === b; - } - } - - return { - "string": useStrictEquality, - "boolean": useStrictEquality, - "number": useStrictEquality, - "null": useStrictEquality, - "undefined": useStrictEquality, - - "nan": function( b ) { - return isNaN( b ); - }, - - "date": function( b, a ) { - return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf(); - }, - - "regexp": function( b, a ) { - return QUnit.objectType( b ) === "regexp" && - // the regex itself - a.source === b.source && - // and its modifiers - a.global === b.global && - // (gmi) ... - a.ignoreCase === b.ignoreCase && - a.multiline === b.multiline && - a.sticky === b.sticky; - }, - - // - skip when the property is a method of an instance (OOP) - // - abort otherwise, - // initial === would have catch identical references anyway - "function": function() { - var caller = callers[callers.length - 1]; - return caller !== Object && typeof caller !== "undefined"; - }, - - "array": function( b, a ) { - var i, j, len, loop, aCircular, bCircular; - - // b could be an object literal here - if ( QUnit.objectType( b ) !== "array" ) { - return false; - } - - len = a.length; - if ( len !== b.length ) { - // safe and faster - return false; - } - - // track reference to avoid circular references - parents.push( a ); - parentsB.push( b ); - for ( i = 0; i < len; i++ ) { - loop = false; - for ( j = 0; j < parents.length; j++ ) { - aCircular = parents[j] === a[i]; - bCircular = parentsB[j] === b[i]; - if ( aCircular || bCircular ) { - if ( a[i] === b[i] || aCircular && bCircular ) { - loop = true; - } else { - parents.pop(); - parentsB.pop(); - return false; - } - } - } - if ( !loop && !innerEquiv(a[i], b[i]) ) { - parents.pop(); - parentsB.pop(); - return false; - } - } - parents.pop(); - parentsB.pop(); - return true; - }, - - "object": function( b, a ) { - /*jshint forin:false */ - var i, j, loop, aCircular, bCircular, - // Default to true - eq = true, - aProperties = [], - bProperties = []; - - // comparing constructors is more strict than using - // instanceof - if ( a.constructor !== b.constructor ) { - // Allow objects with no prototype to be equivalent to - // objects with Object as their constructor. - if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) || - ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) { - return false; - } - } - - // stack constructor before traversing properties - callers.push( a.constructor ); - - // track reference to avoid circular references - parents.push( a ); - parentsB.push( b ); - - // be strict: don't ensure hasOwnProperty and go deep - for ( i in a ) { - loop = false; - for ( j = 0; j < parents.length; j++ ) { - aCircular = parents[j] === a[i]; - bCircular = parentsB[j] === b[i]; - if ( aCircular || bCircular ) { - if ( a[i] === b[i] || aCircular && bCircular ) { - loop = true; - } else { - eq = false; - break; - } - } - } - aProperties.push(i); - if ( !loop && !innerEquiv(a[i], b[i]) ) { - eq = false; - break; - } - } - - parents.pop(); - parentsB.pop(); - callers.pop(); // unstack, we are done - - for ( i in b ) { - bProperties.push( i ); // collect b's properties - } - - // Ensures identical properties name - return eq && innerEquiv( aProperties.sort(), bProperties.sort() ); - } - }; - }()); - - innerEquiv = function() { // can take multiple arguments - var args = [].slice.apply( arguments ); - if ( args.length < 2 ) { - return true; // end transition - } - - return (function( a, b ) { - if ( a === b ) { - return true; // catch the most you can - } else if ( a === null || b === null || typeof a === "undefined" || - typeof b === "undefined" || - QUnit.objectType(a) !== QUnit.objectType(b) ) { - return false; // don't lose time with error prone cases - } else { - return bindCallbacks(a, callbacks, [ b, a ]); - } - - // apply transition with (1..n) arguments - }( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) ); - }; - - return innerEquiv; -}()); - -/** - * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | - * http://flesler.blogspot.com Licensed under BSD - * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008 - * - * @projectDescription Advanced and extensible data dumping for Javascript. - * @version 1.0.0 - * @author Ariel Flesler - * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html} - */ -QUnit.jsDump = (function() { - function quote( str ) { - return "\"" + str.toString().replace( /"/g, "\\\"" ) + "\""; - } - function literal( o ) { - return o + ""; - } - function join( pre, arr, post ) { - var s = jsDump.separator(), - base = jsDump.indent(), - inner = jsDump.indent(1); - if ( arr.join ) { - arr = arr.join( "," + s + inner ); - } - if ( !arr ) { - return pre + post; - } - return [ pre, inner + arr, base + post ].join(s); - } - function array( arr, stack ) { - var i = arr.length, ret = new Array(i); - this.up(); - while ( i-- ) { - ret[i] = this.parse( arr[i] , undefined , stack); - } - this.down(); - return join( "[", ret, "]" ); - } - - var reName = /^function (\w+)/, - jsDump = { - // type is used mostly internally, you can fix a (custom)type in advance - parse: function( obj, type, stack ) { - stack = stack || [ ]; - var inStack, res, - parser = this.parsers[ type || this.typeOf(obj) ]; - - type = typeof parser; - inStack = inArray( obj, stack ); - - if ( inStack !== -1 ) { - return "recursion(" + (inStack - stack.length) + ")"; - } - if ( type === "function" ) { - stack.push( obj ); - res = parser.call( this, obj, stack ); - stack.pop(); - return res; - } - return ( type === "string" ) ? parser : this.parsers.error; - }, - typeOf: function( obj ) { - var type; - if ( obj === null ) { - type = "null"; - } else if ( typeof obj === "undefined" ) { - type = "undefined"; - } else if ( QUnit.is( "regexp", obj) ) { - type = "regexp"; - } else if ( QUnit.is( "date", obj) ) { - type = "date"; - } else if ( QUnit.is( "function", obj) ) { - type = "function"; - } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) { - type = "window"; - } else if ( obj.nodeType === 9 ) { - type = "document"; - } else if ( obj.nodeType ) { - type = "node"; - } else if ( - // native arrays - toString.call( obj ) === "[object Array]" || - // NodeList objects - ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) ) - ) { - type = "array"; - } else if ( obj.constructor === Error.prototype.constructor ) { - type = "error"; - } else { - type = typeof obj; - } - return type; - }, - separator: function() { - return this.multiline ? this.HTML ? "
    " : "\n" : this.HTML ? " " : " "; - }, - // extra can be a number, shortcut for increasing-calling-decreasing - indent: function( extra ) { - if ( !this.multiline ) { - return ""; - } - var chr = this.indentChar; - if ( this.HTML ) { - chr = chr.replace( /\t/g, " " ).replace( / /g, " " ); - } - return new Array( this.depth + ( extra || 0 ) ).join(chr); - }, - up: function( a ) { - this.depth += a || 1; - }, - down: function( a ) { - this.depth -= a || 1; - }, - setParser: function( name, parser ) { - this.parsers[name] = parser; - }, - // The next 3 are exposed so you can use them - quote: quote, - literal: literal, - join: join, - // - depth: 1, - // This is the list of parsers, to modify them, use jsDump.setParser - parsers: { - window: "[Window]", - document: "[Document]", - error: function(error) { - return "Error(\"" + error.message + "\")"; - }, - unknown: "[Unknown]", - "null": "null", - "undefined": "undefined", - "function": function( fn ) { - var ret = "function", - // functions never have name in IE - name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1]; - - if ( name ) { - ret += " " + name; - } - ret += "( "; - - ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" ); - return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" ); - }, - array: array, - nodelist: array, - "arguments": array, - object: function( map, stack ) { - /*jshint forin:false */ - var ret = [ ], keys, key, val, i; - QUnit.jsDump.up(); - keys = []; - for ( key in map ) { - keys.push( key ); - } - keys.sort(); - for ( i = 0; i < keys.length; i++ ) { - key = keys[ i ]; - val = map[ key ]; - ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) ); - } - QUnit.jsDump.down(); - return join( "{", ret, "}" ); - }, - node: function( node ) { - var len, i, val, - open = QUnit.jsDump.HTML ? "<" : "<", - close = QUnit.jsDump.HTML ? ">" : ">", - tag = node.nodeName.toLowerCase(), - ret = open + tag, - attrs = node.attributes; - - if ( attrs ) { - for ( i = 0, len = attrs.length; i < len; i++ ) { - val = attrs[i].nodeValue; - // IE6 includes all attributes in .attributes, even ones not explicitly set. - // Those have values like undefined, null, 0, false, "" or "inherit". - if ( val && val !== "inherit" ) { - ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" ); - } - } - } - ret += close; - - // Show content of TextNode or CDATASection - if ( node.nodeType === 3 || node.nodeType === 4 ) { - ret += node.nodeValue; - } - - return ret + open + "/" + tag + close; - }, - // function calls it internally, it's the arguments part of the function - functionArgs: function( fn ) { - var args, - l = fn.length; - - if ( !l ) { - return ""; - } - - args = new Array(l); - while ( l-- ) { - // 97 is 'a' - args[l] = String.fromCharCode(97+l); - } - return " " + args.join( ", " ) + " "; - }, - // object calls it internally, the key part of an item in a map - key: quote, - // function calls it internally, it's the content of the function - functionCode: "[code]", - // node calls it internally, it's an html attribute value - attribute: quote, - string: quote, - date: quote, - regexp: literal, - number: literal, - "boolean": literal - }, - // if true, entities are escaped ( <, >, \t, space and \n ) - HTML: false, - // indentation unit - indentChar: " ", - // if true, items in a collection, are separated by a \n, else just a space. - multiline: true - }; - - return jsDump; -}()); - -/* - * Javascript Diff Algorithm - * By John Resig (http://ejohn.org/) - * Modified by Chu Alan "sprite" - * - * Released under the MIT license. - * - * More Info: - * http://ejohn.org/projects/javascript-diff-algorithm/ - * - * Usage: QUnit.diff(expected, actual) - * - * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick brown fox jumped jumps over" - */ -QUnit.diff = (function() { - /*jshint eqeqeq:false, eqnull:true */ - function diff( o, n ) { - var i, - ns = {}, - os = {}; - - for ( i = 0; i < n.length; i++ ) { - if ( !hasOwn.call( ns, n[i] ) ) { - ns[ n[i] ] = { - rows: [], - o: null - }; - } - ns[ n[i] ].rows.push( i ); - } - - for ( i = 0; i < o.length; i++ ) { - if ( !hasOwn.call( os, o[i] ) ) { - os[ o[i] ] = { - rows: [], - n: null - }; - } - os[ o[i] ].rows.push( i ); - } - - for ( i in ns ) { - if ( hasOwn.call( ns, i ) ) { - if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) { - n[ ns[i].rows[0] ] = { - text: n[ ns[i].rows[0] ], - row: os[i].rows[0] - }; - o[ os[i].rows[0] ] = { - text: o[ os[i].rows[0] ], - row: ns[i].rows[0] - }; - } - } - } - - for ( i = 0; i < n.length - 1; i++ ) { - if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null && - n[ i + 1 ] == o[ n[i].row + 1 ] ) { - - n[ i + 1 ] = { - text: n[ i + 1 ], - row: n[i].row + 1 - }; - o[ n[i].row + 1 ] = { - text: o[ n[i].row + 1 ], - row: i + 1 - }; - } - } - - for ( i = n.length - 1; i > 0; i-- ) { - if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null && - n[ i - 1 ] == o[ n[i].row - 1 ]) { - - n[ i - 1 ] = { - text: n[ i - 1 ], - row: n[i].row - 1 - }; - o[ n[i].row - 1 ] = { - text: o[ n[i].row - 1 ], - row: i - 1 - }; - } - } - - return { - o: o, - n: n - }; - } - - return function( o, n ) { - o = o.replace( /\s+$/, "" ); - n = n.replace( /\s+$/, "" ); - - var i, pre, - str = "", - out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ), - oSpace = o.match(/\s+/g), - nSpace = n.match(/\s+/g); - - if ( oSpace == null ) { - oSpace = [ " " ]; - } - else { - oSpace.push( " " ); - } - - if ( nSpace == null ) { - nSpace = [ " " ]; - } - else { - nSpace.push( " " ); - } - - if ( out.n.length === 0 ) { - for ( i = 0; i < out.o.length; i++ ) { - str += "" + out.o[i] + oSpace[i] + ""; - } - } - else { - if ( out.n[0].text == null ) { - for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) { - str += "" + out.o[n] + oSpace[n] + ""; - } - } - - for ( i = 0; i < out.n.length; i++ ) { - if (out.n[i].text == null) { - str += "" + out.n[i] + nSpace[i] + ""; - } - else { - // `pre` initialized at top of scope - pre = ""; - - for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) { - pre += "" + out.o[n] + oSpace[n] + ""; - } - str += " " + out.n[i].text + nSpace[i] + pre; - } - } - } - - return str; - }; -}()); - -// For browser, export only select globals -if ( typeof window !== "undefined" ) { - extend( window, QUnit.constructor.prototype ); - window.QUnit = QUnit; -} - -// For CommonJS environments, export everything -if ( typeof module !== "undefined" && module.exports ) { - module.exports = QUnit; -} - - -// Get a reference to the global object, like window in browsers -}( (function() { - return this; -})() )); \ No newline at end of file diff --git a/WebContent/tcom/const.inc.vm b/WebContent/tcom/const.inc.vm deleted file mode 100644 index f541a7af7..000000000 --- a/WebContent/tcom/const.inc.vm +++ /dev/null @@ -1,84 +0,0 @@ -#*** - * 该文件主要用于定义前端页面常量、请求action地址等 - * 建议前端定义的常量以f(f-front)开头。如:$fFoobar - *# -##----------------------前端定义的常量------------------------------- -## 引号 -#set($dQuote = '"') -#set($sQuote = "'") - -## 精确到秒 -#set($timeFormat = 'yyyy-MM-dd HH:mm:ss') - -## 精确到天 -#set($dateFormat = 'yyyy-MM-dd') - -## 时间戳 -#set($timeStamp = '20140416.v0.8.1') - -##----------------------页面请求action地址------------------------------- -## 配置工程的上下文路径 -#set($projectContext = "$!link.getContextPath()") -##set($projectContext = "$!link.getContextPath()/rap") - -## 配置静态资源请求的路径 -#set($staticRoot = "$!projectContext/stat") - -#set($newUrl = { - "home":"$projectContext/org/index.do" -}) - -#set($accountUrl = { - "login":"$projectContext/account/login.action", - "doLogin":"$projectContext/account/doLogin.action", - "doLogout":"$projectContext/account/doLogout.action", - "register":"$projectContext/account/register.action", - "doRegister":"$projectContext/account/doRegister.action", - "myAccount":"$projectContext/account/myAccount.action", - "updateProfile":"$projectContext/account/updateProfile.action", - "doUpdateProfile":"$projectContext/account/doUpdateProfile.action", - "doChangeProfile":"$projectContext/account/doChangeProfile.action", - "myHome":"$projectContext/org/index.action" -}) - -#set($projectUrl = { - "myProjectList":"$projectContext/project/myProjectList.action", - "removeProject":"$projectContext/project/removeProject.action", - "addProject":"$projectContext/project/addProject.action", - "myProject":"$projectContext/project/myProject.action", - "projectDetailAjax":"$projectContext/project/projectDetailAjax.action", - "addOrUpdateProject":"$projectContext/project/addOrUpdateProject.action", - "allProductlineList":"$projectContext/org/productline.action" -}) - -#set($workspaceUrl = { - "myWorkspace":"$projectContext/workspace/myWorkspace.action", - "getModuleHtmlAjax":"$projectContext/workspace/getModuleHtmlAjax.action", - "updateCurrentSave":"$projectContext/workspace/updateCurrentSave.action", - "updateSave":"$projectContext/workspace/updateSave.action", - "querySave":"$projectContext/workspace/querySave.action", - "removeSave":"$projectContext/workspace/removeSave.action", - "checkIn":"$projectContext/workspace/checkIn.action", - "checkOut":"$projectContext/workspace/checkOut.action", - "ping":"$projectContext/workspace/ping.action", - "queryVersion":"$projectContext/workspace/queryVersion.action", - "switchVersion":"$projectContext/workspace/switchVersion.action", - "lock":"$projectContext/workspace/lock.action", - "unlock":"$projectContext/workspace/unlock.action", - "export":"$projectContext/workspace/export.action" -}) - -#set($platformUrl = { - "home":"$projectContext/platform/home.action", - "document":"$projectContext/platform/document.action", - "about":"$projectContext/platform/about.action", - "status":"$projectContext/platform/status.action", - "help":"$!projectContext/platform/help.action", - "test":"$!projectContext/platform/test.action", - "doc":"http://thx.alibaba-inc.com/RAP" -}) - - -#set($testerUrl = { - "pageTester":"$projectContext/tester/pageTester.action" -}) diff --git a/WebContent/tcom/mod.macro.vm b/WebContent/tcom/mod.macro.vm deleted file mode 100644 index 0a6baa79b..000000000 --- a/WebContent/tcom/mod.macro.vm +++ /dev/null @@ -1,54 +0,0 @@ -#macro (includeEditorStatic) - - - - -#end - -#macro (createEditor $suffix $textareaName $editorWidth $editorHeight $selfInit) - #set($editorAreaWidth = $editorWidth - 10) -
    - -
    -
    -
    -
    - - - -
    -#end \ No newline at end of file diff --git a/WebContent/tcom/table.css.vm b/WebContent/tcom/table.css.vm deleted file mode 100644 index 698323aa3..000000000 --- a/WebContent/tcom/table.css.vm +++ /dev/null @@ -1,368 +0,0 @@ -#set($imgRoot = "${staticRoot}/js/ui/table/css/img") -#set($tbCss = { - "default":{ - "hs_img": "$imgRoot/hscroll.gif", - "s_img": "$imgRoot/scroll.gif", - "cr_img": "$imgRoot/cr.gif", - "t_img": "$imgRoot/table.gif", - "th_font": "#326700", - "th_bg": "#DCEFD1", - "bdr_dk": "#9CD167", - "bdr_lt": "#CCE9B9", - "r_ev": "#F2F8EE", - "r_od": "#FFF", - "r_ev_dk": "#DDE9D0", - "r_od_dk": "#EAF1E2", - "hl_bg": "#FFFCE2" - }, - "blue":{ - "hs_img": "$imgRoot/hscroll_blue.gif", - "s_img": "$imgRoot/scroll_blue.gif", - "cr_img": "$imgRoot/cr.gif", - "t_img": "$imgRoot/table_blue.gif", - "th_font": "#2C7AAA", - "th_bg": "#C2E2F6", - "bdr_dk": "#2C7AAA", - "bdr_lt": "#AEDCF9", - "r_ev": "#F1F9FF", - "r_od": "#FFF", - "r_ev_dk": "#E4F2FA", - "r_od_dk": "#F1F9FF", - "hl_bg": "#FFFCE2" - }, - "blueGray":{ - "hs_img": "$imgRoot/hscroll_bluegray.gif", - "s_img": "$imgRoot/scroll_bluegray.gif", - "cr_img": "$imgRoot/cr.gif", - "t_img": "$imgRoot/table_bluegray.gif", - "th_font": "#346665", - "th_bg": "#D9E5E1", - "bdr_dk": "#BCBCBC", - "bdr_lt": "#DDD", - "r_ev": "#FFF", - "r_od": "#FFF", - "r_ev_dk": "#FFF", - "r_od_dk": "#FFF", - "hl_bg": "#FFFCE2", - "th_bold": true, - "td_bdr_btm": true, - "scr_bdr": "#4099C5" - } -}) - -#if(!$tbSkin) - #set($cssMap = $tbCss.get("blueGray")) -#else - #set($cssMap = $tbCss.get($tbSkin)) -#end - - - -/* - * XXXXXXXXXXXXXX - * $tbSkin - * XXXXXXXXXXXXXX - */ - /* FOR OPERA */ - div{border:0;} - -.ec-ecom-table .ec-vscroll {background:$cssMap.r_ev;width:15px;padding:15px 0px 15px 0px;font-size:1px} -.ec-ecom-table .ec-hscroll {background:$cssMap.r_ev;height:15px;padding:0px 15px 0px 15px;font-size:1px} -.ec-ecom-table .ec-hscroll-block {background:url("$cssMap.hs_img") -2px -30px repeat-x;border:1px solid $cssMap.scr_bdr;border-width:0 1px} -.ec-ecom-table .ec-vscroll-block {background:url("$cssMap.s_img") 0px 0px repeat-y;border:1px solid $cssMap.scr_bdr;border-width:1px 0} -.ec-ecom-table .ec-hscroll-block-over {background:url("$cssMap.hs_img") -0px -45px repeat-x} -.ec-ecom-table .ec-hscroll-block-press {background:url("$cssMap.hs_img") -0px -60px repeat-x} -.ec-ecom-table .ec-vscroll-block-over {background:url("$cssMap.s_img") -15px 0px repeat-y} -.ec-ecom-table .ec-vscroll-block-press {background:url("$cssMap.s_img") -30px 0px repeat-y} -.ec-ecom-table .ec-vscroll-prev {background:url("$cssMap.s_img") -45px -40px no-repeat;} -.ec-ecom-table .ec-vscroll-prev-over {background:url("$cssMap.s_img") -75px -40px no-repeat;} -.ec-ecom-table .ec-vscroll-prev-press {background:url("$cssMap.s_img") -60px -40px no-repeat;} -.ec-ecom-table .ec-vscroll-next {background:url("$cssMap.s_img") -45px -55px no-repeat;} -.ec-ecom-table .ec-vscroll-next-over {background:url("$cssMap.s_img") -75px -55px no-repeat;} -.ec-ecom-table .ec-vscroll-next-press {background:url("$cssMap.s_img") -60px -55px no-repeat;} -.ec-ecom-table .ec-hscroll-prev {background:url("$cssMap.s_img") -45px -85px no-repeat;} -.ec-ecom-table .ec-hscroll-prev-over {background:url("$cssMap.s_img") -75px -85px no-repeat;} -.ec-ecom-table .ec-hscroll-prev-press {background:url("$cssMap.s_img") -60px -85px no-repeat;} -.ec-ecom-table .ec-hscroll-next {background:url("$cssMap.s_img") -45px -70px no-repeat;} -.ec-ecom-table .ec-hscroll-next-over {background:url("$cssMap.s_img") -75px -70px no-repeat;} -.ec-ecom-table .ec-hscroll-next-press {background:url("$cssMap.s_img") -60px -70px no-repeat;} - -.ec-ecom-table .vsblockdtr {padding:2px 0px} -.ec-ecom-table .vsblockdtr-top {background:url("$cssMap.s_img") -45px 0px no-repeat} -.ec-ecom-table .vsblockdtr-bottom {background:url("$cssMap.s_img") -45px -18px no-repeat} -.ec-ecom-table .vsblockdtr-over .vsblockdtr-top {background:url("$cssMap.s_img") -45px -20px no-repeat} -.ec-ecom-table .vsblockdtr-over .vsblockdtr-bottom {background:url("$cssMap.s_img") -45px -38px no-repeat} -.ec-ecom-table .vsblockdtr-press .vsblockdtr-top {background:url("$cssMap.s_img") -60px 0px no-repeat} -.ec-ecom-table .vsblockdtr-press .vsblockdtr-bottom {background:url("$cssMap.s_img") -60px -38px no-repeat} -.ec-ecom-table .ec-panel-disabled .vsblockdtr div {display:none} - -.ec-ecom-table .hsblockdtr {padding:0px 2px} -.ec-ecom-table .hsblockdtr-left {background:url("$cssMap.hs_img") -60px 0px no-repeat} -.ec-ecom-table .hsblockdtr-right {background:url("$cssMap.hs_img") -18px 0px no-repeat} -.ec-ecom-table .hsblockdtr-over .hsblockdtr-left {background:url("$cssMap.hs_img") -40px -0px no-repeat} -.ec-ecom-table .hsblockdtr-over .hsblockdtr-right {background:url("$cssMap.hs_img") -38px -0px no-repeat} -.ec-ecom-table .hsblockdtr-press .hsblockdtr-left {background:url("$cssMap.hs_img") -40px -15px no-repeat} -.ec-ecom-table .hsblockdtr-press .hsblockdtr-right {background:url("$cssMap.hs_img") -38px -15px no-repeat} -.ec-ecom-table .ec-panel-disabled .hsblockdtr div {display:none} - - .ec-ecom-table {border:1px solid $cssMap.bdr_dk;padding-top:23px;background-color:$cssMap.th_bg} - .ec-ecom-table .checkbox {padding-left:0px;padding-right:0px;} - .ec-ecom-table .checkbox-item {padding-left:0px;padding-right:0px;} - .ec-ecom-table table {border-collapse:collapse;border-spacing:0px} - .ec-ecom-table-layout {background:#FFF;color:#333} - .ec-ecom-table-head, - .ec-print-table th{ - font-weight:#if($cssMap.th_bold)bold#{else}normal#end; - color:$cssMap.th_font; - padding:6px 5px; padding-right:12px; - line-height:15px; - border:0; - border-left:1px solid $cssMap.bdr_lt; border-bottom:1px solid $cssMap.bdr_dk; - overflow:hidden; - white-space:nowrap; - word-wrap:normal; - word-break:keep-all - } - .ec-ecom-table-item, - .ec-print-table td{ - line-height:15px; - border:0; - padding:5px 5px; padding-right:12px; - border-left:1px solid $cssMap.bdr_lt; - #if($cssMap.td_bdr_btm)border-bottom:1px solid $cssMap.bdr_lt;#end - word-break:break-all; - white-space:normal; - word-wrap:break-word; - overflow:hidden - } - - .ec-ecom-table-row .od td{background-color:$cssMap.r_od;} - .ec-ecom-table-row .ev td{background-color:$cssMap.r_ev;} - .ec-ecom-table-row .od td.dk{background-color:$cssMap.r_od_dk;} - .ec-ecom-table-row .ev td.dk{background-color:$cssMap.r_ev_dk;} - - .ec-ecom-table-row-over .ev .ec-ecom-table-item,.ec-ecom-table-row-over .ev td.dk, - .ec-ecom-table-row-over .od .ec-ecom-table-item,.ec-ecom-table-row-over .od td.dk, - .ec-ecom-table-row-focus .ev .ec-ecom-table-item,.ec-ecom-table-row-focus .ev td.dk, - .ec-ecom-table-row-focus .od .ec-ecom-table-item,.ec-ecom-table-row-focus .od td.dk, - .ec-ecom-table-row-focus .ec-ecom-table-item, - .ec-ecom-table-row-over .ec-ecom-table-item - {background-color:$cssMap.hl_bg} - - .ec-ecom-table-row .first, - .ec-ecom-table-area .first{ - border-left:0 none; - } - - /*排序*/ - .ec-ecom-table-area .sort, - .ec-ecom-table-area .sort-over, - .ec-ecom-table-area .sort-focus{ - text-align:left; - cursor:pointer; - background:url("$cssMap.t_img") no-repeat 93% -33px; - } - .ec-ecom-table-area .sort-over{ - background-color:#F6FFB8; - } - .ec-ecom-table-area .sort-up, - .ec-ecom-table-area .sort-down{ - cursor:pointer; - /*text-align:right;*/ - background:#F6FFB8 url("$cssMap.t_img") no-repeat 93% -33px; - } - - .ec-ecom-table-area .sort-up { - background-position:93% -63px; - } - .ec-ecom-table-area .sort-down { - background-position:93% -93px; - } - - .ec-ecom-table-row .op{text-align:center;border:0 none;border-left:1px solid $cssMap.bdr_dk} - - /*复选框*/ - .ec-checkbox {background:url("$cssMap.cr_img") 0px 0px no-repeat;width:17px;height:15px} - .ec-checkbox-disabled {background:url("$cssMap.cr_img") -68px 0px no-repeat;} - .ec-checkbox-over {background:url("$cssMap.cr_img") -17px 0px no-repeat;} - .ec-checkbox-checked {background:url("$cssMap.cr_img") -34px 0px no-repeat} - .ec-checkbox-checked-over {background:url("$cssMap.cr_img") -51px 0px no-repeat} - .ec-checkbox-part {background:url("$cssMap.cr_img") -102px 0px no-repeat} - - /*展开按钮(上)*/ - .ec-col-toggler,.ec-col-toggler-o{ - width:17px; height:20px; - position:absolute; top:2px; right:0; - background:$cssMap.th_bg url("$cssMap.t_img") no-repeat 0px 0px; - cursor:pointer; - } - .ec-col-toggler-o{background-position:-22px 0px} - - /*展开按钮(下)*/ - .ec-v-toggler{ - width:15px; background:$cssMap.r_ev_dk; - position:absolute; right:0; bottom:0; _right:-1px; - cursor:pointer; - border-left:1px solid $cssMap.bdr_dk; - /*border-right:1px solid $cssMap.bdr_dk;*/ - } - .ec-v-toggler div{ - width:9px; height:10px; - overflow:hidden; - background:url("$cssMap.t_img") no-repeat -8px -22px; - position:absolute; right:3px; bottom:50%; - _padding-top:50%; - cursor:pointer; - } - .ec-v-toggler-over{background-color:$cssMap.r_od_dk} - - /*验证*/ - .valid-error .ev td.ec-ecom-table-item, - .valid-error .od td.ec-ecom-table-item{ - background-color:pink; - } - /* - *分页 - *囧, 有同名的list宏,需转义 - */ - .list-page a, - .list-page b{ - margin:0; - text-indent:0; - display:inline-block; - *display:inline; - zoom:1; - height:20px; - line-height:20px; - background:url("$cssMap.t_img") repeat-x 0 -150px; - border:1px solid $cssMap.bdr_dk; - padding:0 3px; - text-decoration:none; - color:$cssMap.th_font; - } - .list-page a:hover{ - background-position:0 -176px; - } - .list-page .page-n{ - /*width:20px;*/ - text-align:center; - /*padding:0;*/ - padding:0 5px; - } - .list-page b{ - background-image:none; - color:#666; - background-color:#EEE; - font-weight:normal; - } - .list-page b.page-n{ - background-image:none; - background-color:#FFF; - color:#000; - font-weight:bold; - } - .list-page { - color:$cssMap.th_font; - margin-top: 10px - } - .list-page em{ - font-style:normal; - color:#000; - padding:0 3px; - } - .target-page{ - width:25px; - } - /*弹出菜单*/ - .ec-popup{ - background-color:$cssMap.th_bg; - border:1px solid $cssMap.bdr_dk; - border-width:1px 1px 0 1px; - width:70px; - } - .ec-popup-item{ - background-color:$cssMap.th_bg; - width:70px; height:25px; line-height:25px; - border-bottom:1px solid $cssMap.bdr_dk; - padding-left: 24px; - cursor:pointer; - vertical-align:bottom; - position:relative; - } - .ec-popup-item-over{ - background-color:$cssMap.hl_bg; - } - .ec-popup-item .ec-checkbox{ - /*float:left;*/ - /*margin:4px 4px 0 4px;*/ - position:absolute; top:4px; left:4px; - border:0 none; - /*text-indent: 14px;*/ - } - .cb-ctnr{ - background:$cssMap.th_bg url("$cssMap.t_img") 0 -200px; - height:14px; - margin:0; - border:0 none; - width:15px; - position:absolute; - top:7px; - cursor:pointer; - } - - /* - * 提示信息显示 - */ - .tb-msg{ - visibility:hidden; - display:none; - margin: 0 0 4px 0; - } - .tb-msg .tb-msg-txt{ - background:$cssMap.hl_bg; - color:#D2691E; - font-weight:bold; - padding:0 4px; - display:inline-block; *display:inline; - zoom:1; - height:20px; line-height:20px; - } - .tb-msg .clo-btn{ - font-weight:normal; - margin: 0 0 0 14px; - cursor:pointer; - } - - /* - * 打印 - */ - @media screen { - .ec-print-table{ - border:1px solid $cssMap.bdr_dk;border-width:1px; - border-collapse:collapse; background-color:$cssMap.th_bg - } - .ec-print-table th, - .ec-print-table td{ - border:1px solid $cssMap.bdr_dk; - border-width:0 0 1px 1px; - } - .ec-print-table td{ - background-color:#FFF; - } - } - @media print { - body{font-family:"微软雅黑","黑体";font-size:10px;} - .strik-info{color:#000;} - .noprint,.nav{display:none;} - .area-v,.area-w{display:none;} - .area{border:1px solid #ddd;margin-top:6px;background:#fff;} - .mess-query .area-inner{background:none;border:0;} - .mess-query .area {border:0;} - .area h5{border:0;} - .area h5 b{background:none;border:0;color:#000;} - .old td{background:#ddd;} - .ec-print-table {border:1px solid #666;border-width:1px 0 1px 1px;border-collapse:collapse} - .ec-print-table th{padding:2px;text-align:center;border-right:1px solid #666; border-color:#666} - .ec-print-table td{padding:2px 6px;border:1px solid #666;border-width:1px 1px 0 0; border-color:#666} - *{word-wrap:break-word;word-break:break-all;} - } \ No newline at end of file diff --git a/WebContent/tcom/template.rap.old.vm b/WebContent/tcom/template.rap.old.vm deleted file mode 100644 index 0f7892c77..000000000 --- a/WebContent/tcom/template.rap.old.vm +++ /dev/null @@ -1,69 +0,0 @@ -#parse('/tcom/utils.macro.vm') - -## master page start -#macro (bodyStart) -
    -
    - - - -
    -
    -#end -## master page end -#macro (bodyEnd) -
    - -
    - -
    -
    - - - -#end diff --git a/WebContent/tcom/template.rap.vm b/WebContent/tcom/template.rap.vm index 3b1a2f4d1..b04c1a829 100644 --- a/WebContent/tcom/template.rap.vm +++ b/WebContent/tcom/template.rap.vm @@ -1,112 +1,337 @@ #parse('/tcom/utils.macro.vm') - +#set($domainUrl = "http://" + $consts.DOMAIN_URL) +#set($homeUrlEncoded = $utils.escapeInU($domainUrl)) +#set($logoutUrl = $domainUrl + $accountUrl.doLogout) +#set($logoutUrlEncoded = $utils.escapeInU($logoutUrl)) ## master page start -#macro (bodyNewStart) +#macro (bodyNewStart $hide) + + + +#if(!$hide)
    " + levelMark(level) + StringUtils.escapeInH(p.getName()) + "" + StringUtils.escapeInH(p.getIdentifier()) + "" + StringUtils.escapeInH(p.getDataType()) + "" + StringUtils.escapeInH(p.getRemark()) + "
    "); + stringBuilder.append(""); + stringBuilder.append(""); + stringBuilder.append(""); + + + // print response parameter list + for (Action action : page.getActionList()) { + if (!action.getResponseTemplate().equals(page.getTemplate())) continue; + for (Parameter p : action.getResponseParameterList()) { + stringBuilder.append(""); + stringBuilder.append(""); + stringBuilder.append(""); + stringBuilder.append(""); + stringBuilder.append(""); + stringBuilder.append(""); + stringBuilder.append(""); + } + } + stringBuilder.append("
    变量名参数意义参数类型实际传值备注
    " + p.getIdentifier() + "" + p.getName() + "" + p.getDataType() + "$!" + p.getIdentifier() + "" + p.getRemark() + "
    \n\n
    "); + int formCount = 1; + + // generate action tester + for (Action action : page.getActionList()) { + stringBuilder.append("

    Action: " + action.getName() + " Tester

    "); + stringBuilder.append("
    "); + stringBuilder.append("
    请求地址:" + action.getRequestUrl() + "
    "); + for (Parameter p : action.getRequestParameterList()) { + stringBuilder.append("
       变量名: " + p.getIdentifier() + "   变量意义: " + + p.getName() + "  备注: " + p.getRemark() + "
    "); + } + stringBuilder.append("
    "); + stringBuilder.append("
    "); + } + stringBuilder.append("
    "); + stringBuilder.append("\n"); + stringBuilder.append("\n"); + return stringBuilder.toString(); + } + + + public TargetObjectType getTargetObjectType() { + return TargetObjectType.PAGE; + } + + + public void setObject(Object obj) { + this.page = (Page) obj; + + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/auto/generate/contract/Generator.java b/src/main/java/com/taobao/rigel/rap/auto/generate/contract/Generator.java new file mode 100644 index 000000000..8aa7d3760 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/auto/generate/contract/Generator.java @@ -0,0 +1,69 @@ +package com.taobao.rigel.rap.auto.generate.contract; + +import com.taobao.rigel.rap.auto.generate.bo.GenerateUtils.GeneratorType; +import com.taobao.rigel.rap.auto.generate.bo.GenerateUtils.TargetObjectType; +import com.taobao.rigel.rap.project.bo.Project.STAGE_TYPE; + +/** + * generator interface, all generator class should + * implement this interface + * + * @author Bosn + */ +public interface Generator { + + /** + * is available on specific stage + * + * @param stage + * @return + */ + boolean isAvailable(STAGE_TYPE stage); + + /** + * get generator type + * + * @return + */ + GeneratorType getGeneratorType(); + + /** + * get author + * + * @return author + */ + String getAuthor(); + + /** + * get introduction of generator + * + * @return + */ + String getIntroduction(); + + /** + * get target object type + * + * @return + */ + TargetObjectType getTargetObjectType(); + + /** + * this method will be invoked automatically + * by RAP before using, the type of Object is + * decided by the return value of + * getTargetObjectType() method, eg. if + * result PROJECT, RAP will pass the proper + * Project object automatically. + * + * @param project + */ + void setObject(Object obj); + + /** + * do generate + * + * @return generated result + */ + String doGenerate(); +} diff --git a/src/main/java/com/taobao/rigel/rap/common/base/ActionBase.java b/src/main/java/com/taobao/rigel/rap/common/base/ActionBase.java new file mode 100644 index 000000000..97ab50328 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/base/ActionBase.java @@ -0,0 +1,201 @@ +package com.taobao.rigel.rap.common.base; + +import com.google.gson.reflect.TypeToken; +import com.opensymphony.xwork2.ActionSupport; +import com.taobao.rigel.rap.account.bo.Role; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.account.service.AccountMgr; +import com.taobao.rigel.rap.common.service.impl.ContextManager; +import com.taobao.rigel.rap.common.bo.RapError; +import com.taobao.rigel.rap.common.config.SystemSettings; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.common.utils.CommonUtils; +import com.taobao.rigel.rap.organization.bo.Corporation; + +import java.util.*; + +public class ActionBase extends ActionSupport { + + public static String JSON_ERROR = "json-error"; + + public static String LOGIN_WARN_MSG = "您登录过期啦,不要乱动哦,请打开新页面登录后再提交吧 > 。<"; + + public static String LOGIN_HINT_MSG = "您尚未登录,或登录已过期,请登录后再试。"; + + public static String ACCESS_DENY = "您无权访问该页面或数据,请联系系统管理员。"; + private boolean isOpSuccess = false; + private boolean isReturnUrlFirstSet; + private boolean isLoginCtlHidden; + private int num; + private String returnUrl; + private AccountMgr accountMgr; + private boolean isOk = true; + private String json; + private String errMsg; + + public boolean isOpSuccess() { + return isOpSuccess; + } + + public void setIsOpSuccess(boolean isOpSuccess) { + this.isOpSuccess = isOpSuccess; + } + + public List> getCorpList() { + String [] cacheKey = new String[]{CacheUtils.KEY_CORP_LIST_TOP_ITEMS, new Integer(getCurUserId()).toString()}; + String cache = CacheUtils.get(cacheKey); + List> corpList = new ArrayList>(); + if (cache != null) { + corpList = CommonUtils.gson.fromJson(cache, new TypeToken>(){}.getType()); + } else { + List list = accountMgr.getCorporationListWithPager(getCurUserId(), 1, 20); + for (Corporation c : list) { + corpList.add(c.toMap()); + } + CacheUtils.put(cacheKey, CommonUtils.gson.toJson(corpList)); + } + return corpList; + } + + public List> getAllCorpList() { + String [] cacheKey = new String[]{CacheUtils.KEY_CORP_LIST, new Integer(getCurUserId()).toString()}; + String cache = CacheUtils.get(cacheKey); + List> corpList = new ArrayList>(); + if (cache != null) { + corpList = CommonUtils.gson.fromJson(cache, new TypeToken>(){}.getType()); + } else { + List list = accountMgr.getCorporationListWithPager(getCurUserId(), 1, 999); + for (Corporation c : list) { + corpList.add(c.toMap()); + } + CacheUtils.put(cacheKey, CommonUtils.gson.toJson(corpList)); + } + return corpList; + } + + public int getNum() { + return num; + } + + public void setNum(int num) { + this.num = num; + } + + public boolean isLoginCtlHidden() { + return isLoginCtlHidden; + } + + public void setLoginCtlHidden(boolean isLoginCtlHidden) { + this.isLoginCtlHidden = isLoginCtlHidden; + } + + public String getReturnUrl() { + return returnUrl; + } + + public void setReturnUrl(String returnUrl) { + this.returnUrl = returnUrl; + } + + public Long getServerTime() { + return new Date().getTime(); + } + + public AccountMgr getAccountMgr() { + return accountMgr; + } + + public void setAccountMgr(AccountMgr accountMgr) { + this.accountMgr = accountMgr; + } + + public String getCurAccount() { + return isUserLogined() ? ContextManager.currentSession() + .get(ContextManager.KEY_ACCOUNT).toString() : null; + } + + public boolean getIsLogined() { + return isUserLogined(); + } + + protected boolean isUserLogined() { + return ContextManager.currentSession().get(ContextManager.KEY_ACCOUNT) != null; + } + + public int getCountOfOnlineUserList() { + Map app = ContextManager.getApplication(); + String key = ContextManager.KEY_COUNT_OF_ONLINE_USER_LIST; + if (app.get(key) == null) { + return 0; + } else { + return (Integer) app.get(key); + } + } + + protected int getCurUserId() { + Object userIdObj = ContextManager.currentSession().get( + ContextManager.KEY_USER_ID); + if (userIdObj == null) + return -1; + return (Integer) userIdObj; + } + + public User getCurUser() { + if (isUserLogined()) { + User user = new User(); + Map session = ContextManager.currentSession(); + user.setName((String)session.get(ContextManager.KEY_NAME)); + user.setAccount((String)session.get(ContextManager.KEY_ACCOUNT)); + user.setRoleList((Set)session.get(ContextManager.KEY_ROLE_LIST)); + user.setId((Integer)session.get(ContextManager.KEY_USER_ID)); + String empId = (String) session.get(ContextManager.KEY_EMP_ID); + user.setEmpId(empId); + return user; + } else { + return null; + } + } + + public boolean getIsOk() { + return isOk; + } + + public void setIsOk(boolean isOk) { + this.isOk = isOk; + } + + public boolean isReturnUrlFirstSet() { + return isReturnUrlFirstSet; + } + + public void setRelativeReturnUrl(String returnUrl) { + this.returnUrl = SystemSettings.projectContext + returnUrl; + this.isReturnUrlFirstSet = true; + } + + public String getJson() { + if (json == null || json.isEmpty()) { + return new RapError().toString(); + } + return json; + } + + public void setJson(String json) { + this.json = json; + } + + public String getErrMsg() { + return errMsg; + } + + public void setErrMsg(String errMsg) { + this.isLoginCtlHidden = true; + this.errMsg = errMsg; + this.isOk = false; + } + + public void plsLogin() { + setErrMsg(LOGIN_HINT_MSG); + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/bo/Item.java b/src/main/java/com/taobao/rigel/rap/common/bo/Item.java new file mode 100644 index 000000000..1d6b4bdfd --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/bo/Item.java @@ -0,0 +1,49 @@ +package com.taobao.rigel.rap.common.bo; + +/** + * Created by mashengbo on 14-9-4. + */ +public class Item { + private String key; + private String value; + private String title; + + public Item() { + + } + + public Item(String key, String value) { + this.key = key; + this.value = value; + } + + public Item(String key, String value, String title) { + this.key = key; + this.value = value; + this.title = title; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/bo/RapError.java b/src/main/java/com/taobao/rigel/rap/common/bo/RapError.java new file mode 100644 index 000000000..aff63c5d7 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/bo/RapError.java @@ -0,0 +1,54 @@ +package com.taobao.rigel.rap.common.bo; + +public class RapError { + public static final int ERR_HAS_CHILDREN = 501; + private int code = 200; + private String msg = ""; + private String result = ""; + + public RapError() { + + } + + public RapError(String result) { + this.result = result; + } + + public RapError(int code, String msg) { + this.code = code; + this.msg = msg; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getResult() { + if (result == null || result.isEmpty()) { + return "\"\""; + } + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public String toString() { + return "{\"code\":" + getCode() + ", \"msg\":\"" + getMsg() + "\", \"result\":" + + getResult() + "}"; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/config/PRIVATE_CONFIG.java b/src/main/java/com/taobao/rigel/rap/common/config/PRIVATE_CONFIG.java new file mode 100644 index 000000000..71d856c92 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/config/PRIVATE_CONFIG.java @@ -0,0 +1,7 @@ +package com.taobao.rigel.rap.common.config; + +public class PRIVATE_CONFIG { + public static final String mailUserName = "rap@domain.com"; + public static final String mailPassword = ""; + public static final String adminPassword = ""; +} diff --git a/src/main/java/com/taobao/rigel/rap/common/config/Patterns.java b/src/main/java/com/taobao/rigel/rap/common/config/Patterns.java new file mode 100644 index 000000000..6abb1cd9e --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/config/Patterns.java @@ -0,0 +1,8 @@ +package com.taobao.rigel.rap.common.config; + +public class Patterns { + public static final String MOCK_TEMPLATE_PATTERN = "\\$\\{([_a-zA-Z][_a-zA-Z0-9.]*)=?((.*?))\\}"; + public static final String ILLEGAL_NAME_CHAR = "[^ 0-9a-zA-Z_]"; + public static final String LEGAL_ACCOUNT_CHAR = "[0-9a-zA-Z_]"; + public static final String LEGAL_NAME_CHAR = "[0-9a-zA-Z_ ]"; +} diff --git a/src/main/java/com/taobao/rigel/rap/common/config/SystemConstant.java b/src/main/java/com/taobao/rigel/rap/common/config/SystemConstant.java new file mode 100644 index 000000000..a05eb46eb --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/config/SystemConstant.java @@ -0,0 +1,62 @@ +package com.taobao.rigel.rap.common.config; + +import com.alibaba.platform.buc.sso.common.dto.SimpleSSOUser; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.IOException; +import java.util.Properties; + + +public class SystemConstant { + private static final Logger logger = LogManager.getFormatterLogger(SystemConstant.class); + public static final int DEFAULT_PAGE_SIZE = 12; + public static final int ACCOUNT_LENGTH_MIN = 6; + public static final int ACCOUNT_LENGTH_MAX = 32; + public static final int NAME_LENGTH_MIN = 1; + public static final int NAME_LENGTH_MAX = 32; + public static final String ALI_LOGIN_URL = "login" + ".ali" + "ba" + "ba" + "-in" + "c.com"; + public static final String NODE_SERVER = "localhost:7429"; + public static String README_PATH = ""; + public static String ROOT = ""; + public static String DOMAIN_URL = ""; + public static boolean serviceInitialized = false; + public static SimpleSSOUser user = null; + private static String domainURL = ""; + + public static String getAliLoginUrl() { + return ALI_LOGIN_URL; + } + + public static String getDOMAIN_URL() { + return domainURL; + } + + public static void setDOMAIN_URL(String domainURL) { + SystemConstant.domainURL = domainURL; + } + + private static Properties config; + + private static void loadConfig() { + if (config == null) { + config = new Properties(); + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + try { + config.load(loader.getResourceAsStream("config.properties")); + } catch (IOException e) { + e.printStackTrace(); + logger.error(e.getMessage()); + } + } + } + + public static String getConfig(String key) { + if (config == null) { + loadConfig(); + } + return config.getProperty(key); + } + + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/config/SystemSettings.java b/src/main/java/com/taobao/rigel/rap/common/config/SystemSettings.java new file mode 100644 index 000000000..b0da26623 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/config/SystemSettings.java @@ -0,0 +1,31 @@ +package com.taobao.rigel.rap.common.config; + +import org.apache.struts2.ServletActionContext; + +import java.io.File; + +public class SystemSettings { + + public static final String APP_PATH = ServletActionContext + .getServletContext().getRealPath("/"); + public static final String STATIC_ROOT = APP_PATH + "stat" + File.separator; + + public static final String projectContext = ""; + + public static final int MOCK_SERVICE_TIMEOUT = 1000; + + public static String GET_DEFAULT_USER_SETTINGS(String key) { + if (key == null || key.isEmpty()) { + return null; + } + + if (key.equals("inform")) { + return ""; + } + + return null; + + } + + ; +} diff --git a/src/main/java/com/taobao/rigel/rap/common/filter/AuthCheckFilter.java b/src/main/java/com/taobao/rigel/rap/common/filter/AuthCheckFilter.java new file mode 100644 index 000000000..35990d68e --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/filter/AuthCheckFilter.java @@ -0,0 +1,131 @@ +package com.taobao.rigel.rap.common.filter; + +import com.alibaba.buc.sso.client.util.SimpleUserUtil; +import com.alibaba.platform.buc.sso.common.dto.SimpleSSOUser; +import com.taobao.rigel.rap.account.bo.Role; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.account.service.AccountMgr; +import com.taobao.rigel.rap.common.service.impl.ContextManager; +import com.taobao.rigel.rap.common.config.SystemConstant; +import com.taobao.rigel.rap.common.utils.SystemVisitorLog; +import com.taobao.rigel.rap.common.utils.URLUtils; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +public class AuthCheckFilter implements Filter { + AccountMgr accountMgr; + + public AccountMgr getAccountMgr() { + return accountMgr; + } + + public void setAccountMgr(AccountMgr accountMgr) { + this.accountMgr = accountMgr; + } + + + public void destroy() {} + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + String url = null; + if (request instanceof HttpServletRequest) { + url = ((HttpServletRequest) request).getRequestURL().toString(); + } + String domain = URLUtils.getDomain(url); + if (domain != "") { + SystemConstant.setDOMAIN_URL(domain); + } + + // all requests count into realtime charts + SystemVisitorLog.count(); + + if (URLUtils.shouldLog(url)) + SystemVisitorLog.count(request.getRemoteAddr()); + + if (SystemConstant.DOMAIN_URL.isEmpty()) { + SystemConstant.DOMAIN_URL = request.getServerName(); + if (request.getServerPort() != 80) { + SystemConstant.DOMAIN_URL += ":" + request.getServerPort(); + } + } + HttpSession session = ((HttpServletRequest) request).getSession(); + Object userAccount = session.getAttribute(ContextManager.KEY_ACCOUNT); + Object userName = session.getAttribute(ContextManager.KEY_NAME); + boolean logined = userAccount != null; + + SystemConstant.README_PATH = session.getServletContext().getRealPath(File.separator + "README.md"); + SystemConstant.ROOT = session.getServletContext().getRealPath(File.separator); + + if (!logined) { + SimpleSSOUser user = SimpleUserUtil + .findUser((HttpServletRequest) request); + + + if (user != null) { + SystemConstant.user = user; + String emailPrefix = user.getEmailPrefix(); + User rapUser = accountMgr.getUser(emailPrefix); + if (rapUser == null) { + // proceed register + User newUser = new User(); + newUser.setAccount(emailPrefix); + newUser.setPassword("RESERVED"); + String name = user.getNickNameCn(); + if (name == null || name.isEmpty()) { + name = user.getLastName(); + } + newUser.setName(name); + newUser.setEmail(user.getEmailAddr()); + newUser.setRealname(user.getLastName()); + newUser.setEmpId(user.getEmpId()); + getAccountMgr().addUser(newUser); + rapUser = accountMgr.getUser(emailPrefix); + if (rapUser == null) { + try { + throw new Exception("user register failed!"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + // proceed login + session.setAttribute(ContextManager.KEY_ACCOUNT, rapUser.getAccount()); + session.setAttribute(ContextManager.KEY_USER_ID, rapUser.getId()); + session.setAttribute(ContextManager.KEY_NAME, rapUser.getName()); + session.setAttribute(ContextManager.KEY_EMP_ID, rapUser.getEmpId()); + Set roleList = new HashSet(); + for (Role role : rapUser.getRoleList()) { + Role copied = new Role(); + copied.setId(role.getId()); + copied.setName(role.getName()); + roleList.add(copied); + } + session.setAttribute(ContextManager.KEY_ROLE_LIST, roleList); + } + + } else { + if (URLUtils.shouldLog(url)) { + User logUser = new User(); + logUser.setAccount((String) userAccount); + logUser.setName((String) userName); + SystemVisitorLog.count(logUser); + } + } + + chain.doFilter(request, response); + + } + + + public void init(FilterConfig arg0) throws ServletException { + + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/filter/SetCharacterEncodingFilter.java b/src/main/java/com/taobao/rigel/rap/common/filter/SetCharacterEncodingFilter.java new file mode 100644 index 000000000..9fb347922 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/filter/SetCharacterEncodingFilter.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.taobao.rigel.rap.common.filter; + +import javax.servlet.*; +import java.io.IOException; + +/** + *

    + * Example filter that sets the character encoding to be used in parsing the + * incoming request, either unconditionally or only if the client did not + * specify a character encoding. Configuration of this filter is based on the + * following initialization parameters: + *

    + *
      + *
    • encoding - The character encoding to be configured for + * this request, either conditionally or unconditionally based on the + * ignore initialization parameter. This parameter is required, so + * there is no default.
    • + *
    • ignore - If set to "true", any character encoding + * specified by the client is ignored, and the value returned by the + * selectEncoding() method is set. If set to "false, + * selectEncoding() is called only if the client + * has not already specified an encoding. By default, this parameter is set to + * "true".
    • + *
    + *

    + *

    + * Although this filter can be used unchanged, it is also easy to subclass it + * and make the selectEncoding() method more intelligent about what + * encoding to choose, based on characteristics of the incoming request (such as + * the values of the Accept-Language and User-Agent + * headers, or a value stashed in the current user's session. + *

    + * + * @author Craig McClanahan + * @version $Id: SetCharacterEncodingFilter.java 939315 2010-04-29 14:11:01Z + * kkolinko $ + */ + +public class SetCharacterEncodingFilter implements Filter { + + // ----------------------------------------------------- Instance Variables + + /** + * The default character encoding to set for requests that pass through this + * filter. + */ + protected String encoding = null; + + /** + * The filter configuration object we are associated with. If this value is + * null, this filter instance is not currently configured. + */ + protected FilterConfig filterConfig = null; + + /** + * Should a character encoding specified by the client be ignored? + */ + protected boolean ignore = true; + + // --------------------------------------------------------- Public Methods + + /** + * Take this filter out of service. + */ + public void destroy() { + + this.encoding = null; + this.filterConfig = null; + + } + + /** + * Select and set (if specified) the character encoding to be used to + * interpret request parameters for this request. + * + * @param request The servlet request we are processing + * @param response The servlet response we are creating + * @param chain The filter chain we are processing + * @throws IOException if an input/output error occurs + * @throws ServletException if a servlet error occurs + */ + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + // Conditionally select and set the character encoding to be used + if (ignore || (request.getCharacterEncoding() == null)) { + String characterEncoding = selectEncoding(request); + if (characterEncoding != null) + request.setCharacterEncoding(characterEncoding); + } + + /** + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.setHeader("Access-Control-Allow-Origin", "*"); + + httpResponse.setHeader("Access-Control-Allow-Headers", + "Origin, X-Requested-With, Content-Type, Accept"); + */ + + // Pass control on to the next filter + chain.doFilter(request, response); + + } + + /** + * Place this filter into service. + * + * @param fConfig The filter configuration object + */ + public void init(FilterConfig fConfig) throws ServletException { + + this.filterConfig = fConfig; + this.encoding = fConfig.getInitParameter("encoding"); + String value = fConfig.getInitParameter("ignore"); + if (value == null) + this.ignore = true; + else if (value.equalsIgnoreCase("true")) + this.ignore = true; + else if (value.equalsIgnoreCase("yes")) + this.ignore = true; + else + this.ignore = false; + + } + + // ------------------------------------------------------ Protected Methods + + /** + * Select an appropriate character encoding to be used, based on the + * characteristics of the current request and/or filter initialization + * parameters. If no character encoding should be set, return + * null. + *

    + * The default implementation unconditionally returns the value configured + * by the encoding initialization parameter for this + * filter. + * + * @param request The servlet request we are processing + */ + protected String selectEncoding(ServletRequest request) { + + return (this.encoding); + + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/listener/RapServletContextListener.java b/src/main/java/com/taobao/rigel/rap/common/listener/RapServletContextListener.java new file mode 100644 index 000000000..92c2370f5 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/listener/RapServletContextListener.java @@ -0,0 +1,31 @@ +package com.taobao.rigel.rap.common.listener; + +import com.taobao.rigel.rap.common.utils.CacheUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.exceptions.JedisConnectionException; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +/** + * Created by Bosn Ma on 15/9/7. + */ +public class RapServletContextListener implements ServletContextListener { + private static final Logger logger = LogManager.getFormatterLogger(RapServletContextListener.class); + + public void contextInitialized(ServletContextEvent servletContextEvent) { + logger.info("RAP Server initializing..."); + + logger.info("Initializing Jedis Server..."); + CacheUtils.init(); + + logger.info("RAP Server ready."); + } + + + public void contextDestroyed(ServletContextEvent arg0) { + logger.info("Context destroyed."); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/listener/SessionListener.java b/src/main/java/com/taobao/rigel/rap/common/listener/SessionListener.java new file mode 100644 index 000000000..097c47f72 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/listener/SessionListener.java @@ -0,0 +1,54 @@ +package com.taobao.rigel.rap.common.listener; + +import com.taobao.rigel.rap.common.service.impl.ContextManager; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; +import java.util.Map; + + +public class SessionListener implements HttpSessionListener { + + + public void sessionCreated(HttpSessionEvent event) { + ServletContext context = event.getSession().getServletContext(); + // online users count processing + String key = ContextManager.KEY_COUNT_OF_ONLINE_USER_LIST; + if (context.getAttribute(key) == null) { + context.setAttribute(key, 0); + } + int curCountOfOnlineuserList = (Integer) context.getAttribute(key); + context.setAttribute(key, curCountOfOnlineuserList + 1); + } + + public void sessionDestroyed(HttpSessionEvent event) { + ServletContext context = event.getSession().getServletContext(); + HttpSession session = event.getSession(); + // online users count processing + + String key = ContextManager.KEY_COUNT_OF_ONLINE_USER_LIST; + if (context.getAttribute(key) == null) { + context.setAttribute(key, 0); + } + int curCountOfOnlineuserList = (Integer) context.getAttribute(key); + if (curCountOfOnlineuserList < 1) curCountOfOnlineuserList = 1; + context.setAttribute(key, curCountOfOnlineuserList - 1); + + // unlock project + Object userIdObj = session.getAttribute(ContextManager.KEY_USER_ID); + if (userIdObj != null) { + long userId = (Long) userIdObj; + Object projectLockListObj = context.getAttribute(ContextManager.KEY_PROJECT_LOCK_LIST); + if (projectLockListObj != null) { + Map projectLockList = (Map) projectLockListObj; + if (projectLockList.containsKey(userId)) { + projectLockList.remove(userId); + context.setAttribute(ContextManager.KEY_PROJECT_LOCK_LIST, projectLockList); + } + } + } + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/service/impl/ContextManager.java b/src/main/java/com/taobao/rigel/rap/common/service/impl/ContextManager.java new file mode 100644 index 000000000..4ba1c743a --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/service/impl/ContextManager.java @@ -0,0 +1,26 @@ +package com.taobao.rigel.rap.common.service.impl; + +import com.opensymphony.xwork2.ActionContext; + +import java.util.Map; + +public class ContextManager { + public static final String KEY_COUNT_OF_ONLINE_USER_LIST = "KEY_COUNT_OF_ONLINE_USER_LIST"; + public static final String KEY_ACCOUNT = "KEY_ACCOUNT"; + public static final String KEY_PROJECT_LOCK_LIST = "KEY_PROJECT_LOCK_LIST"; + public static final String KEY_USER_ID = "KEY_USER_ID"; + // public static final String KEY_CORP_NAME = "KEY_CORP_NAME"; + public static final String KEY_NAME = "KEY_NAME"; + public static final String KEY_ROLE_LIST = "KEY_ROLE_LIST"; + public static final String KEY_EMP_ID = "KEY_EMP_ID"; + + @SuppressWarnings("rawtypes") + public static Map currentSession() { + return ActionContext.getContext().getSession(); + } + + @SuppressWarnings("rawtypes") + public static Map getApplication() { + return ActionContext.getContext().getApplication(); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/ArrayUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/ArrayUtils.java new file mode 100644 index 000000000..e59e0f83e --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/ArrayUtils.java @@ -0,0 +1,18 @@ +package com.taobao.rigel.rap.common.utils; + +import java.util.List; + +public class ArrayUtils { + public static String join(List arr, String seperator) { + StringBuilder str = new StringBuilder(); + boolean isFirst = true; + for (Object item : arr) { + if (!isFirst) { + str.append(seperator); + } + str.append(item); + isFirst = false; + } + return str.toString(); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/CacheUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/CacheUtils.java new file mode 100644 index 000000000..c895ae94e --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/CacheUtils.java @@ -0,0 +1,126 @@ +package com.taobao.rigel.rap.common.utils; +import com.taobao.rigel.rap.project.bo.Action; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +import java.io.IOException; + +/** + * Created by Bosn on 14/11/28. + * Basic cache, need weight for string length. + */ +public class CacheUtils { + private static final int DEFAULT_CACHE_EXPIRE_SECS = 600; + private static final Logger logger = LogManager.getLogger(CacheUtils.class); + + public static final String KEY_MOCK_RULE = "KEY_MOCK_RULE:"; + public static final String KEY_MOCK_DATA = "KEY_MOCK_DATA"; + public static final String KEY_PROJECT_LIST = "KEY_PROJECT_LIST"; + public static final String KEY_CORP_LIST = "KEY_CORP_LIST"; + public static final String KEY_CORP_LIST_TOP_ITEMS = "KEY_CORP_LIST_TOP_ITEMS"; + public static final String KEY_WORKSPACE = "KEY_WORKSPACE"; + + public static final String KEY_ACCESS_USER_TO_PROJECT = "KEY_ACCESS_USER_TO_PROJECT"; + public static final String KEY_NOTIFICATION = "KEY_NOTIFICATION"; + public static final String KEY_STATISTICS = "KEY_STATISTICS"; + public static final String KEY_STATISTICS_OF_TEAM = "KEY_STATISTICS_OF_TEAM"; + + private static JedisPool jedisPool; + private static Jedis jedis; + + public CacheUtils() {} + + private static Jedis getJedis() { + try { + jedisPool = JedisFactory.getInstance().getJedisPool(); + } catch (IOException e) { + e.printStackTrace(); + logger.error(e.getMessage()); + } + jedis = jedisPool.getResource(); + return jedis; + } + + private static void returnJedis() { + jedisPool.returnResourceObject(jedis); + } + + /** + * get cached Mock rule + * + * @param action + * @param pattern + * @return + */ + public static String getRuleCache(Action action, String pattern, boolean isMockData) { + int actionId = action.getId(); + String requestUrl = action.getRequestUrl(); + if (requestUrl == null) { + requestUrl = ""; + } + if (pattern.contains("noCache=true") || requestUrl.contains("{") + || requestUrl.contains("noCache=true")) { + return null; + } + String [] cacheKey = new String[]{isMockData ? KEY_MOCK_DATA + : KEY_MOCK_RULE, new Integer(actionId).toString()}; + return get(cacheKey); + } + + /** + * set Mock rule cache + * + * @param actionId + * @param result + */ + public static void setRuleCache(int actionId, String result, boolean isMockData) { + String[] cacheKey = new String[]{isMockData ? KEY_MOCK_DATA : KEY_MOCK_RULE, new Integer(actionId).toString()}; + put(cacheKey, result); + } + + public static void removeCacheByActionId(int id) { + String[] cacheKey1 = new String[]{KEY_MOCK_RULE, new Integer(id).toString()}; + String[] cacheKey2 = new String[]{KEY_MOCK_DATA, new Integer(id).toString()}; + + getJedis(); + + jedis.del(StringUtils.join(cacheKey1, "|")); + jedis.del(StringUtils.join(cacheKey2, "|")); + + returnJedis(); + } + + public static void put(String [] keys, String value, int expireInSecs) { + Jedis jedis = getJedis(); + String cacheKey = StringUtils.join(keys, "|"); + jedis.set(cacheKey, value); + if (expireInSecs > 0) + jedis.expire(cacheKey, expireInSecs); + returnJedis(); + } + + public static void put(String [] keys, String value) { + put(keys, value, DEFAULT_CACHE_EXPIRE_SECS); + } + + public static String get(String []keys) { + + String cache = getJedis().get(StringUtils.join(keys, "|")); + returnJedis(); + return cache; + } + + public static void del(String[] keys) { + String cacheKey = StringUtils.join(keys, "|"); + getJedis().del(cacheKey); + returnJedis(); + } + + public static void init() { + getJedis(); + jedis.flushAll(); + returnJedis(); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/CommonUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/CommonUtils.java new file mode 100644 index 000000000..a913f46ac --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/CommonUtils.java @@ -0,0 +1,10 @@ +package com.taobao.rigel.rap.common.utils; + +import com.google.gson.Gson; + +/** + * Created by mashengbo on 16/1/8. + */ +public class CommonUtils { + public static Gson gson = new Gson(); +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/DateUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/DateUtils.java new file mode 100644 index 000000000..eb62e91d3 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/DateUtils.java @@ -0,0 +1,31 @@ +package com.taobao.rigel.rap.common.utils; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +public class DateUtils { + public final static DateFormat DATE_FORMAT = new SimpleDateFormat( + "yyyy-MM-dd"); + + public final static DateFormat TIME_FORMAT = new SimpleDateFormat( + "yyyy-MM-dd HH:mm:ss"); + + private static int counter = 1; + + public static boolean compWorkAndCurrByDate(Date workDay, Date currTime) { + Calendar c1 = Calendar.getInstance(); + Calendar c2 = Calendar.getInstance(); + c1.setTime(workDay); + c2.setTime(currTime); + if (c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR) + && (c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH)) + && c1.get(Calendar.DAY_OF_MONTH) == c2 + .get(Calendar.DAY_OF_MONTH)) { + return true; + } else { + return false; + } + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/FileUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/FileUtils.java new file mode 100644 index 000000000..6f073e034 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/FileUtils.java @@ -0,0 +1,51 @@ +package com.taobao.rigel.rap.common.utils; + +import com.taobao.rigel.rap.common.config.SystemConstant; + +import java.io.*; +import java.util.Arrays; + +/** + * Created by mashengbo on 15/7/21. + */ +public class FileUtils { + public static String JS_UTIL_DIR_PATH = SystemConstant.ROOT + + FileUtils.concatFilePath(new String[]{"stat", "js", "util", ""}); + + /** + * concatenate file path with File.seperator + * + * @param subs + * @return + */ + public static String concatFilePath(String[] subs) { + return ArrayUtils.join(Arrays.asList(subs), File.separator); + } + + /** + * read file, return file content + * + * @param filePath + * @return + */ + public static String readFileContent(String filePath) { + try { + FileInputStream fis = new FileInputStream(filePath); + StringBuffer content = new StringBuffer(); + DataInputStream in = new DataInputStream(fis); + BufferedReader d = new BufferedReader(new InputStreamReader(in, + "UTF-8")); + String line = null; + while ((line = d.readLine()) != null) + content.append(line + "\n"); + d.close(); + in.close(); + fis.close(); + return content.toString(); + + } catch (Exception e) { + e.printStackTrace(); + return "ERROR"; + } + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/HTTPUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/HTTPUtils.java new file mode 100644 index 000000000..4dee12ad9 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/HTTPUtils.java @@ -0,0 +1,59 @@ +package com.taobao.rigel.rap.common.utils; + +import org.apache.logging.log4j.LogManager; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Created by Bosn on 14-8-25. + */ +public class HTTPUtils { + private final static org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger(HTTPUtils.class.getName()); + + // HTTP GET request + public static String sendGet(String url) throws Exception { + if (!url.startsWith("http://")) { + url = "http://" + url; + } + + url = url.replaceAll("<", ""); + url = url.replaceAll(">", ""); + + String USER_AGENT = "Mozilla/5.0"; + + URL obj = new URL(url); + HttpURLConnection con = (HttpURLConnection) obj.openConnection(); + + // optional default is GET + con.setRequestMethod("GET"); + + //add request header + con.setRequestProperty("User-Agent", USER_AGENT); + con.setRequestProperty("Accept-Charset", "utf-8"); + con.setRequestProperty("contentType", "utf-8"); + + int responseCode = con.getResponseCode(); + logger.info("\nSending 'GET' request to URL : " + url); + logger.info("Response Code : " + responseCode); + + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream(), "UTF-8")); + String inputLine; + StringBuffer response = new StringBuffer(); + + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + + //print result + //System.out.println(response.toString()); + return response.toString(); + + } + + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/JSRunner.java b/src/main/java/com/taobao/rigel/rap/common/utils/JSRunner.java new file mode 100644 index 000000000..03d603162 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/JSRunner.java @@ -0,0 +1,38 @@ +package com.taobao.rigel.rap.common.utils; + +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Scriptable; + +/** + * Created by Bosn on 15/7/21. + */ +public class JSRunner { + + private Context ct; + private Scriptable scope; + + public JSRunner() { + this.ct = Context.enter(); + this.scope = ct.initStandardObjects(); + } + + public static void main(String[] args) { + JSRunner runner = new JSRunner(); + System.out.println(runner.run("1 + 2")); + } + + public Context getContext() { + return this.ct; + } + + public String run(String code) { + Object result; + try { + result = ct.evaluateString(scope, code, null, 1, null); + } catch (Exception e) { + e.printStackTrace(); + return "JS_ERROR"; + } + return result == null ? null : result.toString(); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/JedisFactory.java b/src/main/java/com/taobao/rigel/rap/common/utils/JedisFactory.java new file mode 100644 index 000000000..8e27bcfe0 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/JedisFactory.java @@ -0,0 +1,37 @@ +package com.taobao.rigel.rap.common.utils; + + +import com.taobao.rigel.rap.common.config.SystemConstant; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +import java.io.IOException; + +class JedisFactory { + private static JedisPool jedisPool; + private static JedisFactory instance = null; + + public JedisFactory() { + JedisPoolConfig poolConfig = new JedisPoolConfig(); + String host = SystemConstant.getConfig("redis.host"); + int port = Integer.parseInt(SystemConstant.getConfig("redis.port")); + int timeout = Integer.parseInt(SystemConstant.getConfig("redis.timeout")); + String password = SystemConstant.getConfig("redis.password"); + if (password.equals("")) password = null; + int database = Integer.parseInt(SystemConstant.getConfig("redis.database")); + jedisPool = new JedisPool(poolConfig, host, port, timeout, password, database); + } + + public JedisPool getJedisPool() { + return jedisPool; + } + + public static JedisFactory getInstance() throws IOException { + + if (instance == null) { + instance = new JedisFactory(); + } + return instance; + } +} + diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/MailUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/MailUtils.java new file mode 100644 index 000000000..aba3b0762 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/MailUtils.java @@ -0,0 +1,65 @@ +package com.taobao.rigel.rap.common.utils; + +import com.taobao.rigel.rap.common.config.PRIVATE_CONFIG; + +import javax.mail.*; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.util.Properties; + +public class MailUtils { + public static void sendMessage(String[] addressList, String title, + String content) throws AddressException { + Address[] addresses = new Address[addressList.length]; + for (int i = 0; i < addressList.length; i++) { + addresses[i] = new InternetAddress(addressList[i]); + } + + // Sender's email ID needs to be mentioned + String from = "rap@domain.com"; + final String username = PRIVATE_CONFIG.mailUserName; + final String password = PRIVATE_CONFIG.mailPassword; + + // Get system properties + Properties props = System.getProperties(); + + // Setup mail server + props.put("mail.smtp.host", "smtp-inc.domain.com"); + props.put("mail.smtp.port", "25"); + props.put("mail.smtp.auth", "true"); + + props.put("mail.smtp.starttls.enable", "true"); + + // Get the default Session object. + Session session = Session.getDefaultInstance(props, + new javax.mail.Authenticator() { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication( + username, password); + } + }); + + try { + // Create a default MimeMessage object. + MimeMessage message = new MimeMessage(session); + + // Set From: header field of the header. + message.setFrom(new InternetAddress(from)); + + // Set To: header field of the header. + message.addRecipients(Message.RecipientType.BCC, addresses); + + // Set Subject: header field + message.setSubject(title, "UTF-8"); + + // Now set the actual message + message.setText(content, "UTF-8"); + + // Send message + Transport.send(message); + } catch (MessagingException mex) { + mex.printStackTrace(); + } + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/MapUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/MapUtils.java new file mode 100644 index 000000000..d682bdd0f --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/MapUtils.java @@ -0,0 +1,15 @@ +package com.taobao.rigel.rap.common.utils; + +import java.util.Map; + +public class MapUtils { + @SuppressWarnings("rawtypes") + public static Object getKeyByValue(Map map, Object value) { + for (Object key : map.keySet()) { + if (map.get(key).equals(value)) { + return key; + } + } + return null; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/MockjsRunner.java b/src/main/java/com/taobao/rigel/rap/common/utils/MockjsRunner.java new file mode 100644 index 000000000..a1dcdf156 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/MockjsRunner.java @@ -0,0 +1,91 @@ +package com.taobao.rigel.rap.common.utils; + +import com.taobao.rigel.rap.common.config.SystemConstant; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.mozilla.javascript.Context; +import org.mozilla.javascript.Scriptable; + +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class MockjsRunner { + + private static String MOCKJS_PATH = SystemConstant.ROOT + + FileUtils.concatFilePath(new String[]{"stat", "js", "util", "mock-min.js"}); + private static String jsCode; + private Context ct; + private Scriptable scope; + private static final Logger logger = LogManager.getLogger(MockjsRunner.class); + + public MockjsRunner() { + this.ct = Context.enter(); + this.scope = ct.initStandardObjects(); + this.ct.setOptimizationLevel(-1); + this.initMockjs(ct, scope); + } + + public static String getMockjsCode() { + try { + byte[] encoded = Files.readAllBytes(Paths.get(MOCKJS_PATH)); + String result = new String(encoded, StandardCharsets.UTF_8); + return result; + } catch (Exception e) { + e.printStackTrace(); + return "\"ERROR\""; + } finally { + } + } + + public static String renderMockjsRule(String mockRule) { + return new MockjsRunner().doRenderMockJsRule(mockRule); + } + + public static void main(String[] args) { + } + + public Context getContext() { + return this.ct; + } + + public Scriptable getScope() { + return this.scope; + } + + private void initMockjs(Context ct, Scriptable scope) { + if (jsCode == null) { + jsCode = getMockjsCode(); + } + try { + ct.evaluateString(scope, jsCode, null, 1, null); + ct.evaluateString(scope, "", null, 1, null); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private String doRenderMockJsRule(String mockRule) { + String returnVal = "JS_ERROR"; + try { + StringBuilder code = new StringBuilder(); + code + .append("var result = {};") + .append("try {") + // .append("var obj = Mock.mock(JSON.parse(\"" + StringUtils.escapeInJ(mockRule.replaceAll("\\'", "'")) + "\"));") + .append("var obj = Mock.mock(" + mockRule + ");") + .append("result = JSON.stringify(obj.__root__ != undefined ? obj.__root__ : obj, null, 4);") + .append("} catch(ex) {result.errMsg = ex.message;result.isOk=false;result = JSON.stringify(result);}") + .append("result;"); + + Object result = ct.evaluateString(scope, code.toString(), null, 1, + null); + returnVal = result.toString(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + ct.exit(); + } + return returnVal; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/NumberUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/NumberUtils.java new file mode 100644 index 000000000..ababc2ecd --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/NumberUtils.java @@ -0,0 +1,48 @@ +package com.taobao.rigel.rap.common.utils; + +import java.util.Random; + +public class NumberUtils { + private static Random r = new Random(); + + /** + * random integer from 0 - 9 + * + * @return + */ + public static String randomInt10Str() { + return new Integer(r.nextInt(9)).toString(); + } + + /** + * random integer from 1 - 9 + * + * @return + */ + public static String randomInt10StrFrom1() { + return new Integer(r.nextInt(8) + 1).toString(); + } + + public static String randomByFormat(String format) { + boolean isFirst = true; + while (true) { + if (format.indexOf("x") < 0) { + break; + } + format = format.replaceFirst("x", isFirst ? randomInt10StrFrom1() + : randomInt10Str()); + isFirst = false; + } + return format; + } + + /** + * random integer from 0 to (length - 1) + * + * @param length + * @return + */ + public static int randomInt(int length) { + return r.nextInt(length - 1); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/Pinyin4jUtil.java b/src/main/java/com/taobao/rigel/rap/common/utils/Pinyin4jUtil.java new file mode 100644 index 000000000..6583d83d3 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/Pinyin4jUtil.java @@ -0,0 +1,189 @@ +package com.taobao.rigel.rap.common.utils; + +import net.sourceforge.pinyin4j.PinyinHelper; +import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType; +import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat; +import net.sourceforge.pinyin4j.format.HanyuPinyinToneType; +import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +/** + * Created by Bosn on 14-9-23. + */ +public class Pinyin4jUtil { + + /** + * 汉字转换位汉语拼音首字母,英文字符不变,特殊字符丢失 支持多音字,生成方式如(长沙市长:cssc,zssz,zssc,cssz) + * + * @param chines 汉字 + * @return 拼音 + */ + public static String converterToFirstSpell(String chines) { + StringBuffer pinyinName = new StringBuffer(); + char[] nameChar = chines.toCharArray(); + HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); + defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); + defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); + for (int i = 0; i < nameChar.length; i++) { + if (nameChar[i] > 128) { + try { + // 取得当前汉字的所有全拼 + String[] strs = PinyinHelper.toHanyuPinyinStringArray( + nameChar[i], defaultFormat); + if (strs != null) { + for (int j = 0; j < strs.length; j++) { + // 取首字母 + pinyinName.append(strs[j].charAt(0)); + if (j != strs.length - 1) { + pinyinName.append(","); + } + } + } + // else { + // pinyinName.append(nameChar[i]); + // } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + } else { + pinyinName.append(nameChar[i]); + } + pinyinName.append(" "); + } + // return pinyinName.toString(); + return parseTheChineseByObject(discountTheChinese(pinyinName.toString())); + } + + /** + * 汉字转换位汉语全拼,英文字符不变,特殊字符丢失 + * 支持多音字,生成方式如(重当参:zhongdangcen,zhongdangcan,chongdangcen + * ,chongdangshen,zhongdangshen,chongdangcan) + * + * @param chines 汉字 + * @return 拼音 + */ + public static String converterToSpell(String chines) { + StringBuffer pinyinName = new StringBuffer(); + char[] nameChar = chines.toCharArray(); + HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); + defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); + defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); + for (int i = 0; i < nameChar.length; i++) { + if (nameChar[i] > 128) { + try { + // 取得当前汉字的所有全拼 + String[] strs = PinyinHelper.toHanyuPinyinStringArray( + nameChar[i], defaultFormat); + if (strs != null) { + for (int j = 0; j < strs.length; j++) { + pinyinName.append(strs[j]); + if (j != strs.length - 1) { + pinyinName.append(","); + } + } + } + } catch (BadHanyuPinyinOutputFormatCombination e) { + e.printStackTrace(); + } + } else { + pinyinName.append(nameChar[i]); + } + pinyinName.append(" "); + } + // return pinyinName.toString(); + return parseTheChineseByObject(discountTheChinese(pinyinName.toString())); + } + + /** + * 去除多音字重复数据 + * + * @param theStr + * @return + */ + private static List> discountTheChinese(String theStr) { + // 去除重复拼音后的拼音列表 + List> mapList = new ArrayList>(); + // 用于处理每个字的多音字,去掉重复 + Map onlyOne = null; + String[] firsts = theStr.split(" "); + // 读出每个汉字的拼音 + for (String str : firsts) { + onlyOne = new Hashtable(); + String[] china = str.split(","); + // 多音字处理 + for (String s : china) { + Integer count = onlyOne.get(s); + if (count == null) { + onlyOne.put(s, new Integer(1)); + } else { + onlyOne.remove(s); + count++; + onlyOne.put(s, count); + } + } + mapList.add(onlyOne); + } + return mapList; + } + + /** + * 解析并组合拼音,对象合并方案(推荐使用) + * + * @return + */ + private static String parseTheChineseByObject( + List> list) { + Map first = null; // 用于统计每一次,集合组合数据 + // 遍历每一组集合 + for (int i = 0; i < list.size(); i++) { + // 每一组集合与上一次组合的Map + Map temp = new Hashtable(); + // 第一次循环,first为空 + if (first != null) { + // 取出上次组合与此次集合的字符,并保存 + for (String s : first.keySet()) { + for (String s1 : list.get(i).keySet()) { + String str = s + s1; + temp.put(str, 1); + } + } + // 清理上一次组合数据 + if (temp != null && temp.size() > 0) { + first.clear(); + } + } else { + for (String s : list.get(i).keySet()) { + String str = s; + temp.put(str, 1); + } + } + // 保存组合数据以便下次循环使用 + if (temp != null && temp.size() > 0) { + first = temp; + } + } + String returnStr = ""; + if (first != null) { + // 遍历取出组合字符串 + for (String str : first.keySet()) { + returnStr += (str + ","); + } + } + if (returnStr.length() > 0) { + returnStr = returnStr.substring(0, returnStr.length() - 1); + } + return returnStr; + } + + public static String calculatePinyinArrStr(String ch) { + if (ch == null || ch.isEmpty()) { + return ""; + } + return Pinyin4jUtil.converterToSpell(ch) + "|" + Pinyin4jUtil.converterToFirstSpell(ch); + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/StringUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/StringUtils.java new file mode 100644 index 000000000..533afde12 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/StringUtils.java @@ -0,0 +1,561 @@ +package com.taobao.rigel.rap.common.utils; + +import com.taobao.rigel.rap.common.config.Patterns; +import com.taobao.rigel.rap.common.config.SystemConstant; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 为FE提供各类过滤字符串的接口 + * + * @author Junquan 2010.01.20 + */ +public class StringUtils { + + public static final String NAME_FORMAT_WARN_MSG = "名字必须由数字/字母/汉子/空格/下划线组成,长度" + SystemConstant.NAME_LENGTH_MIN + "-" + SystemConstant.NAME_LENGTH_MAX + "."; + public static final String ACCOUNT_FORMAT_WARN_MSG = "账户必须由数字/字母/下划线组成,长度" + SystemConstant.ACCOUNT_LENGTH_MIN + "-" + SystemConstant.ACCOUNT_LENGTH_MAX + "."; + /** + * 默认编码 utf8 + */ + public static String DEFAULT_CHARSET = "utf8"; + + /** + * 在html标签或属性中A: 左尖括号:< 转成 < 右尖括号:> 转成 > 单引号:' 转成 ' 双引号:" 转成 + * " + */ + public static String escapeInH(String str) { + if (str == null || ("").equals(str.trim())) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + int lth = str.length(); + + for (int i = 0; i < lth; i++) { + char c = str.charAt(i); + + switch (c) { + + case 60: // < + sb.append("<"); + break; + case 62: // > + sb.append(">"); + break; + case 39: // ' + sb.append("'"); + break; + case 34: // " + sb.append("""); + break; + default: + sb.append(c); + break; + } + } + return new String(sb.toString()); + } + + public static String escapeInH(Number num) { + String str = null; + if (num != null) { + str = num.toString(); + } + + return escapeInH(str); + } + + /** + * 在html标签或属性中A - 逆 + */ + public static String UnEscapeInH(String str) { + // TODO + return str; + } + + /** + * 在html标签或属性中B: 左尖括号:< 转成 < 右尖括号:> 转成 > 单引号:' 转成 ' 双引号:" 转成 + * " &符号:& 转成& + */ + public static String escapeInX(String str) { + if (str == null || ("").equals(str.trim())) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + int lth = str.length(); + + for (int i = 0; i < lth; i++) { + char c = str.charAt(i); + + switch (c) { + + case 60: // < + sb.append("<"); + break; + case 62: // > + sb.append(">"); + break; + case 39: // ' + sb.append("'"); + break; + case 34: // " + sb.append("""); + break; + case 38: // & + sb.append("&"); + break; + default: + sb.append(c); + break; + } + } + return new String(sb.toString()); + } + + public static String escapeInX(Number num) { + String str = null; + if (num != null) { + str = num.toString(); + } + + return escapeInX(str); + } + + /** + * 在html标签或属性中B - 逆 + */ + public static String UnEscapeInX(String str) { + // TODO + return str; + } + + /** + * 在普通JS环境: 单引号:' 转成 \' 双引号:" 转成 \" 反斜杠:\ 转成 \\ 正斜杠:/ 转成 \/ 换行符 转成 \n 回车符 转成 + * \r + */ + public static String escapeInJ(String str) { + if (str == null || ("").equals(str.trim())) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + int lth = str.length(); + + for (int i = 0; i < lth; i++) { + char c = str.charAt(i); + + switch (c) { + + case 39: // ' + sb.append("\\'"); + break; + case 34: // " + sb.append("\\\""); + break; + case 47: // / + sb.append("\\/"); + break; + case 92: // \ + sb.append("\\\\"); + break; + case 13: // 回车 \r + sb.append("\\r"); + break; + case 10: // 换行 \n + sb.append("\\n"); + break; + default: + sb.append(c); + break; + } + } + return new String(sb.toString()); + } + + public static String escapeInJ(Number num) { + String str = null; + if (num != null) { + str = num.toString(); + } + + return escapeInJ(str); + } + + /** + * 在普通JS环境 - 逆 + */ + public static String UnEscapeInJ(String str) { + // TODO + return str; + } + + /** + * 在JS环境的innerHTML: 左尖括号:< 转成 < 右尖括号:> 转成 > 单引号:' 转成 \' 双引号:" 转成 \" + * 反斜杠:\ 转成 \\ 正斜杠:/ 转成 \/ 换行符 转成 \n 回车符 转成 \r + */ + public static String escapeInJH(String str) { + if (str == null || ("").equals(str.trim())) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + int lth = str.length(); + + for (int i = 0; i < lth; i++) { + char c = str.charAt(i); + + switch (c) { + + case 60: // < + sb.append("<"); + break; + case 62: // > + sb.append(">"); + break; + case 39: // ' + sb.append("\\'"); + break; + case 34: // " + sb.append("\\\""); + break; + case 47: // / + sb.append("\\/"); + break; + case 92: // \ + sb.append("\\\\"); + break; + case 13: // 回车 \r + sb.append("\\r"); + break; + case 10: // 换行 \n + sb.append("\\n"); + break; + default: + sb.append(c); + break; + } + } + return new String(sb.toString()); + } + + public static String escapeInJH(Number num) { + String str = null; + if (num != null) { + str = num.toString(); + } + + return escapeInJH(str); + } + + /** + * 在JS环境的innerHTML - 逆 + */ + public static String UnEscapeInJH(String str) { + // TODO + return str; + } + + /** + * 在标签onclick等事件函数参数中: 左尖括号:< 转成 < 右尖括号:> 转成 > &符号:& 转成& 单引号:' 转成 + * \' 双引号:" 转成 \" 反斜杠:\ 转成 \\ 正斜杠:/ 转成 \/ 换行符 转成 \n 回车符 转成 \r + */ + public static String escapeInHJ(String str) { + if (str == null || ("").equals(str.trim())) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + int lth = str.length(); + + for (int i = 0; i < lth; i++) { + char c = str.charAt(i); + + switch (c) { + + case 60: // < + sb.append("<"); + break; + case 62: // > + sb.append(">"); + break; + case 39: // ' + sb.append("\\'"); + break; + case 34: // " + sb.append("\\""); + break; + case 38: // & + sb.append("&"); + break; + case 47: // / + sb.append("\\/"); + break; + case 92: // \ + sb.append("\\\\"); + break; + case 13: // 回车 \r + sb.append("\\r"); + break; + case 10: // 换行 \n + sb.append("\\n"); + break; + default: + sb.append(c); + break; + } + } + return new String(sb.toString()); + } + + public static String escapeInHJ(Number num) { + String str = null; + if (num != null) { + str = num.toString(); + } + + return escapeInHJ(str); + } + + /** + * 在标签onclick等事件函数参数中 - 逆 + */ + public static String UnEscapeInHJ(String str) { + // TODO + return str; + } + + /** + * 在URL参数中: 对非字母、数字字符进行转码(%加字符的ASCII格式) + * + * @throws UnsupportedEncodingException + */ + public static String escapeInU(String str) + throws UnsupportedEncodingException { + if (str == null || ("").equals(str.trim())) { + return ""; + } + return URLEncoder.encode(str, DEFAULT_CHARSET); + } + + /** + * 在URL参数中 - 逆 + * + * @throws UnsupportedEncodingException + */ + public static String UnEscapeInU(String str) + throws UnsupportedEncodingException { + if (str == null || ("").equals(str.trim())) { + return ""; + } + return URLDecoder.decode(str, DEFAULT_CHARSET); + } + + public static String getMD5(String src) { + byte[] defaultBytes = src.getBytes(); + StringBuffer hexString = new StringBuffer(); + try { + MessageDigest algorithm = MessageDigest.getInstance("MD5"); + algorithm.reset(); + algorithm.update(defaultBytes); + byte messageDigest[] = algorithm.digest(); + + for (int i = 0; i < messageDigest.length; i++) { + hexString.append(Integer.toHexString(0xFF & messageDigest[i])); + } + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return hexString.toString(); + } + + public static String getMD5(byte[] source) { + String s = null; + char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'};// 用来将字节转换成16进制表示的字符 + try { + java.security.MessageDigest md = java.security.MessageDigest + .getInstance("MD5"); + md.update(source); + byte tmp[] = md.digest();// MD5 的计算结果是一个 128 位的长整数, + // 用字节表示就是 16 个字节 + char str[] = new char[16 * 2];// 每个字节用 16 进制表示的话,使用两个字符, 所以表示成 16 + // 进制需要 32 个字符 + int k = 0;// 表示转换结果中对应的字符位置 + for (int i = 0; i < 16; i++) {// 从第一个字节开始,对 MD5 的每一个字节// 转换成 16 + // 进制字符的转换 + byte byte0 = tmp[i];// 取第 i 个字节 + str[k++] = hexDigits[byte0 >>> 4 & 0xf];// 取字节中高 4 位的数字转换,// >>> + // 为逻辑右移,将符号位一起右移 + str[k++] = hexDigits[byte0 & 0xf];// 取字节中低 4 位的数字转换 + + } + s = new String(str);// 换后的结果转换为字符串 + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return s; + } + + public static String getDoubleMD5(String src) { + if (src != null) { + src = getMD5(src); + src = getMD5(src); + } + return src; + } + + /** + * 把中文转成Unicode码 + * + * @param str + * @return + */ + public static String chineseToUnicode(String str) { + if (str == null) { + str = ""; + } + String result = ""; + for (int i = 0; i < str.length(); i++) { + int chr1 = (char) str.charAt(i); + if (chr1 >= 19968 && chr1 <= 171941) {// 汉字范围 \u4e00-\u9fa5 (中文) + result += "\\u" + Integer.toHexString(chr1); + } else { + result += str.charAt(i); + } + } + return result; + } + + /** + * 判断是否为中文字符 + * + * @param c + * @return + */ + public static boolean isChinese(char c) { + Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); + if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS + || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS + || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A + || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION + || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION + || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { + return true; + } + return false; + } + + /** + * 中文算2个,字母算1个 + * + * @param str + * @return + */ + public static int getLengthOfStringChinese(String str) { + int length = 0; + for (char c : str.toCharArray()) { + if (isChinese(c)) length += 2; + else length++; + } + return length; + } + + /** + * 中文算2个,字母算1个 + * + * @param str + * @param startIndex + * @param endIndex + * @return + */ + public static String subStringChinese(String str, int startIndex, int endIndex) { + int length = 0; + int size = endIndex - startIndex; + List charList = new ArrayList(); + for (char c : str.toCharArray()) { + if (isChinese(c)) length += 2; + else length++; + charList.add(c); + if (length >= size) break; + } + StringBuilder builder = new StringBuilder(); + for (Character c : charList) { + builder.append(c); + } + return builder.toString(); + } + + /** + * regular expression matcher helper + * + * @param pattern regular expression + * @param str string to be matched + * @return + */ + public static boolean regMatch(String pattern, String str) { + Pattern p = Pattern.compile(pattern); + Matcher matcher = p.matcher(str); + return matcher.matches(); + } + + /** + * remove all characters except [0-9a-zA-Z_] and blank space + * + * @param o + * @return + */ + public static String removeIllegalCharacters(String o) { + return o.replaceAll(Patterns.ILLEGAL_NAME_CHAR, ""); + } + + public static boolean validateAccount(String str) { + if (str == null) return false; + if (str.length() < SystemConstant.ACCOUNT_LENGTH_MIN || str.length() > SystemConstant.ACCOUNT_LENGTH_MAX) { + return false; + } + return str.matches(Patterns.LEGAL_ACCOUNT_CHAR + "*"); + } + + public static boolean validateName(String str) { + if (str == null) return false; + if (str.length() < SystemConstant.NAME_LENGTH_MIN || str.length() > SystemConstant.NAME_LENGTH_MAX) { + return false; + } + + for (int i = 0; i < str.length(); i++) { + char c = str.charAt(i); + if (!isChinese(c) && !String.valueOf(c).matches(Patterns.LEGAL_NAME_CHAR)) { + return false; + } + } + + return true; + } + + /** + * similar to JavaScript's String.prototype.join + * + * @param strs + * @param seperator + * @return + */ + public static String join(String [] strs, String seperator) { + String rv = ""; + + for (int i = 0; i < strs.length; i++) { + rv += (i == 0) ? strs[i] : seperator + strs[i]; + } + + return rv; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/SystemVisitorLog.java b/src/main/java/com/taobao/rigel/rap/common/utils/SystemVisitorLog.java new file mode 100644 index 000000000..a2c36cfc4 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/SystemVisitorLog.java @@ -0,0 +1,240 @@ +package com.taobao.rigel.rap.common.utils; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.bo.Item; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.*; + +/** + * Created by Bosn on 14-9-2. + */ +public class SystemVisitorLog { + private static final int MAX_LOG_LENGTH = 10; + private static final int REALTIME_TIME_SPAN = 60; + private static final Logger logger = LogManager.getFormatterLogger(SystemVisitorLog.class); + private static Map ipMap = new HashMap(); + private static Map userMap = new HashMap(); + private static List> mockMapList = new ArrayList>(); + private static Map mockMap = new HashMap(); + private static Map realtimeMap = new HashMap(); + private static int mockTotalNum = 0; + private static Date mockTotalNumDate = new Date(); + // private static Map cacheIdMap = new HashMap(); // key = actionId, value = projectId + // private static int counter = 1; + + public static List mock(int projectId, String methodName, String pattern, String account) { + Date now = new Date(); + List resultList = new ArrayList(); + + + if (!DateUtils.compWorkAndCurrByDate(mockTotalNumDate, now)) { + // clear real time log data per night + resultList = SystemVisitorLog.clear(); + } + + mockTotalNum++; + Integer mockNum = mockMap.get(projectId); + if (mockNum == null) { + mockNum = 0; + } + mockMap.put(projectId, mockNum + 1); + + Map mockInfo = new HashMap(); + mockInfo.put("methodName", methodName); + mockInfo.put("userAccount", account); + mockInfo.put("pattern", pattern); + mockMapList.add(mockInfo); + return resultList; + } + + public static int getMockNumToday() { + return mockTotalNum; + } + + public static List getIpLog() { + return getLogMap(ipMap, MAX_LOG_LENGTH); + } + + public static List getUserLog() { + return getLogMap(userMap, MAX_LOG_LENGTH); + } + + public static List getAllIpLog() { + return getLogMap(ipMap, 0); + } + + public static List getAllUserLog() { + return getLogMap(userMap, 0); + } + + public static List> getMockMapList() { + return mockMapList; + } + + public static List> getRealtimeMap(String p) { + long limitTime = Long.parseLong(p); + List> result = new ArrayList>(); + if (limitTime == 0) { + limitTime = Integer.MIN_VALUE; + } + + Calendar c = Calendar.getInstance(); + c.set(Calendar.MILLISECOND, 0); + c.add(Calendar.SECOND, -REALTIME_TIME_SPAN); + Long timeStart = c.getTimeInMillis(); + + + for (int i = 0; i < REALTIME_TIME_SPAN; i++) { + Map item = new HashMap(); + Long time = timeStart + 1000 * i; + + if (time <= limitTime) { + continue; + } + + Integer count = realtimeMap.get(time); + if (count == null) { + count = 0; + } + item.put("time", time); + item.put("count", count); + result.add(item); + } + + return result; + } + + private static List getLogMap(Map map, int max) { + if (max <= 0) { + max = Integer.MAX_VALUE; + } + List list = new ArrayList(); + for (String key : map.keySet()) { + Item item = new Item(); + item.setKey(key); + item.setValue(map.get(key).toString()); + list.add(item); + } + + Collections.sort(list, new Comparator() { + + public int compare(Item o1, Item o2) { + return Integer.parseInt(o2.getValue()) - Integer.parseInt(o1.getValue()); + } + }); + + return list.subList(0, max >= list.size() ? list.size() : max); + } + + public static void count() { + + Calendar c = Calendar.getInstance(); + c.set(Calendar.MILLISECOND, 0); + + Integer nowCount = realtimeMap.get(c.getTimeInMillis()); + + if (nowCount == null) { + nowCount = 0; + } + + nowCount++; + + realtimeMap.put(c.getTimeInMillis(), nowCount); + } + + public static void count(String ip) { + Long ipCount = ipMap.get(ip); + if (ipCount == null) { + ipMap.put(ip, 0L); + logger.info("New visitor:" + ip); + return; + } + + ipCount++; + + ipMap.put(ip, ipCount); + + if ((ipCount + 1) % 100 == 0) { + logger.info("Visitor [%s] visit %d times.", ip, ipCount); + } + } + + public static void count(User user) { + String name = user.getName(); + String account = user.getAccount(); + Long userCount = userMap.get(name); + if (userCount == null) { + userMap.put(name, 0L); + logger.info("New logined visitor %s(%s)", name, account); + return; + } + + userCount++; + logger.debug("user log counter after ++:" + userCount); + userMap.put(name, userCount); + + if ((userCount + 1) % 100 == 0) { + logger.info("Logined visitor %s(%s) visit %d times.", name, account, userCount); + } + } + + public static void count(Map mockLog) { + mockMapList.add(mockLog); + } + + public static List clear() { + List resultList = new ArrayList(); + + for (Integer projectId : mockMap.keySet()) { + Project p = new Project(); + p.setId(projectId); + p.setMockNum(mockMap.get(projectId)); + resultList.add(p); + } + + mockTotalNum = 0; + mockTotalNumDate = new Date(); + ipMap.clear(); + userMap.clear(); + realtimeMap.clear(); + mockMapList.clear(); + mockMap.clear(); + + return resultList; + } + + + public static void debug(String msg) { + logger.info("[DEBUG]" + msg); + } + + public static List> getMockNumByProjectToday(ProjectMgr projectMgr) { + List> results = new ArrayList>(); + for (Integer id : mockMap.keySet()) { + if (id == null) continue; + Project p = projectMgr.getProjectSummary(id); + if (p == null) continue; + String name = p.getName(); + Map row = new HashMap(); + row.put("id", id); + row.put("mockNum", mockMap.get(id)); + row.put("name", name); + results.add(row); + } + Collections.sort(results, new Comparator>() { + + public int compare(Map o1, Map o2) { + return (Integer) o2.get("mockNum") - (Integer) o1.get("mockNum"); + } + }); + if (results.size() > 5) { + results = results.subList(0, 5); + } + return results; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/common/utils/URLUtils.java b/src/main/java/com/taobao/rigel/rap/common/utils/URLUtils.java new file mode 100644 index 000000000..9b32bc635 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/common/utils/URLUtils.java @@ -0,0 +1,114 @@ +package com.taobao.rigel.rap.common.utils; + +/** + * Created by mashengbo on 14-9-5. + */ +public class URLUtils { + public static boolean isStaticUrl(String url) { + if (url == null) { + return false; + } + String[] extentions = new String[]{ + ".jpg", ".png", ".gif", + ".js", ".css", ".font", ".woff" + }; + for (String ex : extentions) { + if (url.contains(ex)) { + return true; + } + } + return false; + } + + public static boolean isLogUrl(String url) { + if (url == null) { + return false; + } + String[] keys = new String[]{ + "logData.action", "getUnreadNotificationList.action" + }; + for (String key : keys) { + if (url.contains(key)) { + return true; + } + } + return false; + } + + public static boolean isMockServiceUrl(String url) { + if (url == null) { + return false; + } + String[] keys = new String[]{ + "/mockjs/", "/mock/", "/mockjsdata/" + }; + for (String key : keys) { + if (url.contains(key)) { + return true; + } + } + return false; + } + + public static boolean shouldLog(String url) { + return !(isStaticUrl(url) || isLogUrl(url)); + } + + public static boolean isRelativeUrlExactlyMatch(String pattern, String requestUrl) { + if (pattern == requestUrl) return true; + if (pattern == null || requestUrl == null) return false; + + // process /:id/ syntax + + + return getRelativeUrl(pattern).equals(getRelativeUrl(requestUrl)); + } + + public static String getDomain(String url) { + if (url == null || !url.startsWith("http://")) { + return ""; + } + url = url.substring(7); + if (url.indexOf("/") != -1) { + url = url.substring(0, url.indexOf("/")); + } + return url; + } + + public static String getRelativeUrl(String url) { + if (url == null || url.isEmpty()) { + return ""; + } + if (url.contains("https://")) { + url = url.substring(url.indexOf("/", 8)); + } else if (url.contains("http://")) { + url = url.substring(url.indexOf("/", 7)); + } + if (url.contains("?")) { + url = url.substring(0, url.indexOf("?")); + } + if (url.charAt(0) != '/' && !url.startsWith("reg:")) { + url = '/' + url; + + } + return url; + } + + public static String removeParamsInUrl(String url) { + String result = url.replaceAll("/:[^/]*", "/:number"); + if (!result.startsWith("/")) { + result = "/" + result; + } + return result; + } + + public static String removeRealParamsInUrl(String url) { + url = url.replaceAll("/\\d+(\\/|$)", "/:number$1"); + String result = url; + if (!result.startsWith("/")) { + result = "/" + result; + } + return result; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/mock/bo/Rule.java b/src/main/java/com/taobao/rigel/rap/mock/bo/Rule.java new file mode 100644 index 000000000..d42ea5283 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/mock/bo/Rule.java @@ -0,0 +1,33 @@ +package com.taobao.rigel.rap.mock.bo; + +import java.util.Date; + +public class Rule { + private int actionId; + private String rules; + private Date updateTime; + + public int getActionId() { + return actionId; + } + + public void setActionId(int actionId) { + this.actionId = actionId; + } + + public String getRules() { + return rules; + } + + public void setRules(String rules) { + this.rules = rules; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/mock/dao/MockDao.java b/src/main/java/com/taobao/rigel/rap/mock/dao/MockDao.java new file mode 100644 index 000000000..1992e11aa --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/mock/dao/MockDao.java @@ -0,0 +1,40 @@ +package com.taobao.rigel.rap.mock.dao; + +import com.taobao.rigel.rap.mock.bo.Rule; + +/** + * Created by Bosn on 15/7/17. + */ +public interface MockDao { + /** + * get rule by action id + * + * @param actionId + * @return + */ + Rule getRule(int actionId); + + /** + * delete rule by action id + * + * @param actionId + * @return 0 success, -1 error + */ + int removeRule(int actionId); + + /** + * set rule, rule.actionId must be set + * + * @param rule + * @return + */ + int updateRule(Rule rule); + + /** + * add new rule for action + * + * @param rule + * @return + */ + int addRule(Rule rule); +} diff --git a/src/main/java/com/taobao/rigel/rap/mock/dao/impl/MockDaoImpl.java b/src/main/java/com/taobao/rigel/rap/mock/dao/impl/MockDaoImpl.java new file mode 100644 index 000000000..590a5e413 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/mock/dao/impl/MockDaoImpl.java @@ -0,0 +1,49 @@ +package com.taobao.rigel.rap.mock.dao.impl; + +import com.taobao.rigel.rap.mock.bo.Rule; +import com.taobao.rigel.rap.mock.dao.MockDao; +import org.hibernate.Session; +import org.springframework.orm.hibernate5.support.HibernateDaoSupport; + +/** + * Created by Bosn on 15/7/17. + */ +public class MockDaoImpl extends HibernateDaoSupport implements MockDao { + + public Rule getRule(int actionId) { + Rule rule = null; + try { + Session session = currentSession(); + rule = (Rule) session.get(Rule.class, actionId); + } catch (Exception ex) { + ex.printStackTrace(); + } + return rule; + } + + + public int removeRule(int actionId) { + Session session = currentSession(); + Object rule = session.get(Rule.class, actionId); + if (rule != null) { + session.delete((Rule) rule); + return 0; + } else { + return -1; + } + } + + + public int updateRule(Rule rule) { + Session session = currentSession(); + session.update(rule); + return 0; + } + + + public int addRule(Rule rule) { + Session session = currentSession(); + session.save(rule); + return 0; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/mock/service/MockMgr.java b/src/main/java/com/taobao/rigel/rap/mock/service/MockMgr.java new file mode 100644 index 000000000..c767e2a75 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/mock/service/MockMgr.java @@ -0,0 +1,95 @@ +package com.taobao.rigel.rap.mock.service; + +import com.taobao.rigel.rap.mock.bo.Rule; +import com.taobao.rigel.rap.project.bo.Action; + +import java.io.UnsupportedEncodingException; +import java.util.Map; + +public interface MockMgr { + /** + * automatically generate testing data + * + * @param projectId + * @param pattern + * @param options + * @return JSON String + * @throws UnsupportedEncodingException + */ + String generateData(int projectId, String pattern, + Map options) throws UnsupportedEncodingException; + + /** + * modify mock data of parameters based on mockData + * + * @param actionId identifier of the action to be modified + * @param mockData mock data string example: + * response.param1.subParam=@format=x.xxxx_AND_response. + * param2=@value= + * 1_AND_response.param3.subParam.subSubParam=@length=7 + * @return number of rows affected + */ + int modify(int actionId, String mockData); + + /** + * clear all mock data of object in specified project + * + * @param projectId + * @return number of rows affected + */ + int reset(int projectId); + + /** + * generate mockjs rule + * + * @param id projectId, if both pattern and options are null, + * this id means actionId(used for OpenAPI) + * @param pattern + * @param options + * @return + * @throws UnsupportedEncodingException + */ + String generateRule(int id, String pattern, + Map options) throws UnsupportedEncodingException; + + /** + * generate mockjs data + * + * @param id + * @param pattern + * @param options + * @return + * @throws UnsupportedEncodingException + */ + String generateRuleData(int id, String pattern, + Map options) throws UnsupportedEncodingException; + + /** + * generate mockjs data by Action ID + * + * @param actionId + * @return + * @throws UnsupportedEncodingException + */ + // String generateRuleData(int actionId) throws UnsupportedEncodingException; + + /** + * validate API format + * + * @param projectId + * @param pattern + * @param options + * @param jsonToCompare + * @return + */ + String validateAPI(int projectId, String pattern, Map options, String jsonToCompare) throws UnsupportedEncodingException; + + /** + * get mock rule from action and action rule + * + * @param rule + * @param action + * @return + */ + String getMockRuleFromActionAndRule(Rule rule, Action action); +} diff --git a/src/main/java/com/taobao/rigel/rap/mock/service/impl/MockMgrImpl.java b/src/main/java/com/taobao/rigel/rap/mock/service/impl/MockMgrImpl.java new file mode 100644 index 000000000..6e974d3db --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/mock/service/impl/MockMgrImpl.java @@ -0,0 +1,1124 @@ +package com.taobao.rigel.rap.mock.service.impl; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.common.config.Patterns; +import com.taobao.rigel.rap.common.config.SystemSettings; +import com.taobao.rigel.rap.common.utils.*; +import com.taobao.rigel.rap.mock.bo.Rule; +import com.taobao.rigel.rap.mock.dao.MockDao; +import com.taobao.rigel.rap.mock.service.MockMgr; +import com.taobao.rigel.rap.project.bo.Action; +import com.taobao.rigel.rap.project.bo.Parameter; +import com.taobao.rigel.rap.project.dao.ProjectDao; +import com.taobao.rigel.rap.project.service.ProjectMgr; +import nl.flotsam.xeger.Xeger; +import org.apache.logging.log4j.LogManager; +import sun.misc.Cache; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.*; +import java.util.concurrent.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class MockMgrImpl implements MockMgr { + + interface Callback { + void onSuccess(String result); + } + + private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(MockMgrImpl.class); + private final String ERROR_PATTERN = "{\"isOk\":false,\"msg\":\"路径为空,请查看是否接口未填写URL.\"}"; + private final String ERROR_SEARCH = "{\"isOk\":false,\"msg\":\"请求参数不合法。\"}"; // 请查看是否含有 script、img、iframe 等标签 + private ProjectDao projectDao; + private ProjectMgr projectMgr; + private MockDao mockDao; + private int uid = 10000; + private Map> requestParams; + private boolean isMockJsData = false; + /** + * random seed + */ + private int _num = 1; + private String[] NAME_LIB = {"霍雍", "行列", "幻刺", "金台", "望天", "李牧", "三冰", + "自勉", "思霏", "诚冉", "甘苦", "勇智", "墨汁老湿", "圣香", "定球", "征宇", "灵兮", "永盛", + "小婉", "紫丞", "少侠", "木谦", "周亮", "宝山", "张中", "晓哲", "夜沨"}; + private String[] LOCATION_LIB = {"北京 朝阳区", "北京 海淀区", "北京 昌平区", + "吉林 长春 绿园区", "吉林 吉林 丰满区"}; + private String[] PHONE_LIB = {"15813243928", "13884928343", "18611683243", + "18623432532", "18611582432"}; + + public static Map> getUrlParameters(String url) + throws UnsupportedEncodingException { + Map> params = new HashMap>(); + String[] urlParts = url.split("\\?"); + if (urlParts.length > 1) { + String query = urlParts[1]; + for (String param : query.split("&")) { + String pair[] = param.split("="); + if (pair.length == 0) { + continue; + } + String key = URLDecoder.decode(pair[0], "UTF-8"); + String value = ""; + if (pair.length > 1) { + value = URLDecoder.decode(pair[1], "UTF-8"); + } + List values = params.get(key); + if (values == null) { + values = new ArrayList(); + params.put(key, values); + } + values.add(value); + } + } + return params; + } + + public MockDao getMockDao() { + return mockDao; + } + + public void setMockDao(MockDao mockDao) { + this.mockDao = mockDao; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + private boolean isPatternLegal(String pattern) { + if (pattern == null || pattern.isEmpty()) { + return false; + } + + String path = pattern; + if (path.indexOf("/") == 0) { + path = path.substring(1); + } + if (path.contains("?")) { + path = path.substring(0, path.indexOf("?")); + } + if (path.isEmpty()) { + return false; + } + + return true; + } + + private boolean isSearchLegal(String pattern) throws UnsupportedEncodingException { + if (pattern == null || pattern.isEmpty()) { + return true; + } + + String search = pattern; + if (search.contains("?")) { + search = search.substring(search.indexOf("?")); + search = URLDecoder.decode(search, "UTF-8"); + if(search.toLowerCase().indexOf("") != -1) return false; + if(search.toLowerCase().indexOf("") != -1) return false; + } + + return true; + } + + public ProjectDao getProjectDao() { + return projectDao; + } + + public void setProjectDao(ProjectDao projectDao) { + this.projectDao = projectDao; + } + + + public String generateData(int projectId, String pattern, + Map options) throws UnsupportedEncodingException { + + if (!isPatternLegal(pattern)) { + return ERROR_PATTERN; + } + + _num = 1; + String originalPattern = pattern; + if (pattern.contains("?")) { + pattern = pattern.substring(0, pattern.indexOf("?")); + } + + List aList = projectMgr + .getMatchedActionList(projectId, pattern); + if (aList.size() == 0) + return "{\"isOk\":false, \"errMsg\":\"no matched action\"}"; + + Action action = actionPick(aList, originalPattern, options); + + String desc = action.getDescription(); + Set pList = action.getResponseParameterList(); + + StringBuilder json = new StringBuilder(); + String left = "{", right = "}"; + + // match both @type=array && @type=array_map + if (desc.contains("@type=array")) { + left = "["; + right = "]"; + } + + // for array_map.length + String key = "@length="; + String numStr = null; + if (desc.contains(key)) { + Pattern p = Pattern.compile("@length=(\\d+)"); + Matcher matcher = p.matcher(desc); + if (matcher.find()) { + numStr = matcher.group(1); + } + } + int num = numStr == null ? 1 : Integer.parseInt(numStr); + json.append(left); + boolean first = true; + + boolean isArrayMap = desc.contains("@type=array_map"); + + for (int i = 0; i < num; i++) { + first = true; + if (i > 0) { + json.append(","); + } + if (isArrayMap) { + json.append("{"); + } + for (Parameter p : pList) { + if (first) { + first = false; + } else { + json.append(","); + } + buildJson(json, p, -1); + } + + if (isArrayMap) { + json.append("}"); + } + } + json.append(right); + String result = json.toString(); + return resultFilter(result); + } + + + public String generateRuleData(final int projectId, String pattern, + Map options) throws UnsupportedEncodingException { + final String mockRule = generateRule(projectId, pattern, options); + String returnValue = null; + ExecutorService executor = Executors.newSingleThreadExecutor(); + try { + Future task = executor.submit(new Callable() { + public String call() throws Exception { + return MockjsRunner.renderMockjsRule(mockRule); + } + }); + + int timeout = SystemSettings.MOCK_SERVICE_TIMEOUT; + while (true) { + if (task.isDone()) { + returnValue = task.get(); + break; + } else if (timeout <= 0){ + task.cancel(true); + logger.warn("Interrupted mock rule by pattern:" + pattern + ", projectId:" + projectId); + break; + } + + Thread.sleep(100); + timeout -= 100; + } + + + } catch (InterruptedException ex) { + + } catch (ExecutionException e) { + } finally { + executor.shutdownNow(); + } + + if (returnValue == null) { + return "{\"isOk\":false, \"errMsg\":\"运行超时," + SystemSettings.MOCK_SERVICE_TIMEOUT + "毫秒都跑不完,服务器HOLD不住啊,亲的自定义函数是不是写的太夸张了啊...\"}"; + } else { + return StringUtils.chineseToUnicode(returnValue); + } + } + + public String generateRuleData(int actionId) throws UnsupportedEncodingException { + final String mockRule = generateRule(actionId, null, null); + String returnValue = null; + ExecutorService executor = Executors.newSingleThreadExecutor(); + try { + Future task = executor.submit(new Callable() { + public String call() throws Exception { + return MockjsRunner.renderMockjsRule(mockRule); + } + }); + + int timeout = SystemSettings.MOCK_SERVICE_TIMEOUT; + while (true) { + if (task.isDone()) { + returnValue = task.get(); + break; + } else if (timeout <= 0){ + task.cancel(true); + logger.warn("Interrupted mock rule by actionId:" + actionId); + break; + } + + Thread.sleep(100); + timeout -= 100; + } + + } catch (InterruptedException ex) { + + } catch (ExecutionException e) { + } finally { + executor.shutdownNow(); + } + + + if (returnValue == null) { + return "{\"isOk\":false, \"errMsg\":\"运行超时,3秒都跑不完,服务器HOLD不住啊,亲的自定义函数是不是写的太夸张了啊...\"}"; + } else { + return StringUtils.chineseToUnicode(returnValue); + } + } + + + public String validateAPI(int projectId, String pattern, Map options, String jsonToCompare) + throws UnsupportedEncodingException { + String mockjsData = generateRuleData(projectId, pattern, options); + StringBuilder jsCode = new StringBuilder(); + + jsCode + .append(FileUtils.readFileContent(FileUtils.JS_UTIL_DIR_PATH + "mock-min.js")) + .append(FileUtils.readFileContent(FileUtils.JS_UTIL_DIR_PATH + "structureValidator.js")) + .append("var o1 = ") + .append(mockjsData) + .append(";\n") + .append("var o2 = ") + .append(jsonToCompare) + .append(";\n") + .append("var validator = new StructureValidator(o2, o1);") + .append("JSON.stringify({result : validator.getResult(), resultStr : validator.getResultStr()});"); + return new JSRunner().run(jsCode.toString()); + } + + + public String generateRule(int projectId, String pattern, + Map options) throws UnsupportedEncodingException { + if (!isPatternLegal(pattern)) { + return ERROR_PATTERN; + } + if (!isSearchLegal(pattern)) { + return ERROR_SEARCH; + } + String originalPattern = pattern; + boolean loadRule = false; + Rule rule = null; + if (options.get("loadRule") != null && (Boolean) options.get("loadRule") == true) { + loadRule = true; + } + int actionId = 0; + Action action; + + if (pattern == null && options == null) { + actionId = projectId; + } + _num = 1; + + if (actionId > 0) { // from OPenAPI, invoked by params(id, null, null) + action = projectMgr.getAction(actionId); + } else { + if (pattern.contains("?")) { + pattern = pattern.substring(0, pattern.indexOf("?")); + } + if (pattern.isEmpty()) { + return "{\"isOk\":false, \"errMsg\":\"pattern is empty. 路径为空,请检查RAP文档中的请求链接是否正确填写。\"}"; + } + List aList = projectMgr + .getMatchedActionList(projectId, pattern); + if (aList.size() == 0) { + return "{\"isOk\":false, \"errMsg\":\"no matched action\"}"; + } + + action = actionPick(aList, originalPattern, options); + if (action == null) { + return "{\"isOk\":false, \"errMsg\":\"no matched action\"}"; + } + + if (action.getDisableCache() == 0 && loadRule == false) { + String ruleCache = CacheUtils.getRuleCache(action, originalPattern, false); + if (ruleCache != null) { + return ruleCache; + } + } + + } + + if (loadRule) { + rule = mockDao.getRule(action.getId()); + } + String result = getMockRuleFromActionAndRule(rule, action); + + + if (!loadRule) { + CacheUtils.setRuleCache(action.getId(), result, false); + } + return result; + } + + public String getMockRuleFromActionAndRule(Rule rule, Action action) { + // rule process + String desc = action.getDescription(); + Set pList = action.getResponseParameterList(); + // load mock data by Open API + Action actionMockRules = null; + + if (rule != null && rule.getRules() != null) { + Gson gson = new Gson(); + try { + actionMockRules = gson.fromJson(rule.getRules(), Action.class); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + if (actionMockRules != null) + for (Parameter p : pList) { + recursivelyLoadMockData(p, findParamInArray(p, actionMockRules.getResponseParameterList())); + } + StringBuilder json = new StringBuilder(); + String left = "{", right = "}"; + + // match both @type=array && @type=array_map + if (desc.contains("@type=array")) { + left = "["; + right = "]"; + } + + // for array_map.length + String key = "@length="; + String numStr = null; + if (desc.contains(key)) { + Pattern p = Pattern.compile("@length=(\\d+)"); + Matcher matcher = p.matcher(desc); + if (matcher.find()) { + numStr = matcher.group(1); + } + } + int num = numStr == null ? 1 : Integer.parseInt(numStr); + json.append(left); + boolean first = true; + boolean isArrayMap = desc.contains("@type=array_map"); + + for (int i = 0; i < num; i++) { + first = true; + if (i > 0) { + json.append(","); + } + if (isArrayMap) { + json.append("{"); + } + for (Parameter p : pList) { + if (first) { + first = false; + } else { + json.append(","); + } + buildMockTemplate(json, p, -1); + } + + if (isArrayMap) { + json.append("}"); + } + } + json.append(right); + String result = json.toString(); + result = resultFilter(result); + return result; + } + + private Parameter findParamInArray(Parameter p, Set list) { + for (Parameter item : list) { + if (item.getIdentifier().equals(p.getIdentifierWithoutMockjsRule())) { + return item; + } + } + return null; + } + + private Action actionPick(List actionList, String pattern, + Map options) throws UnsupportedEncodingException { + + List filteredActionList = new ArrayList(); + + // pattern match + for (Action action : actionList) { + if (URLUtils.isRelativeUrlExactlyMatch(pattern, action.getRequestUrl())) { + filteredActionList.add(action); + } + } + + if (!filteredActionList.isEmpty()) { + actionList = filteredActionList; + } + + if (actionList == null || actionList.isEmpty()) { + return null; + } + + Action result = actionList.get(0); + + // request method match + for (Action action : actionList) { + if (options.get("method") != null && + action.getMethod().equals(options.get("method").toString())) { + result = action; + break; + } + } + + requestParams = getUrlParameters(pattern); + + // schema match + for (Action action : actionList) { + Map> docActionParams = getUrlParameters(action + .getRequestUrl()); + boolean hasSchema = false; + boolean isPassed = true; + for (String docParamKey : docActionParams.keySet()) { + if (docParamKey.contains("[") && docParamKey.contains("]")) { + String docParamKeyProcessed = docParamKey.substring(1, + docParamKey.length() - 1); + List list = requestParams.get(docParamKeyProcessed); + if (list != null && list.size() > 0) { + options.put("callback", list.get(0)); + } + } + + if (docParamKey.contains("{") && docParamKey.contains("}")) { + hasSchema = true; + String docParamKeyProcessed = docParamKey.substring(1, + docParamKey.length() - 1); + List list1 = requestParams + .get(docParamKeyProcessed); + List list2 = docActionParams.get(docParamKey); + if (list1 != null && list2 != null && list1.size() > 0 + && list2.size() > 0 + && list1.get(0).equals(list2.get(0))) { + // checked passed + } else { + isPassed = false; + break; + } + } + } + if (isPassed && hasSchema) { + return action; + } + } + return result; + } + + /** + * for escaping separators + * + * @param result + * @return + */ + private String resultFilter(String result) { + result = result.replaceAll("////", ";"); + return result; + } + + private void recursivelyLoadMockData(Parameter p, Parameter pMock) { + if (pMock != null) { + if (pMock.getRemarkChange() != null) { + p.setRemarkChange(pMock.getRemarkChange()); + } + + if (pMock.getIdentifierChange() != null) { + p.setIdentifierChange(pMock.getIdentifierChange()); + } + } + + if (p.getParameterList() == null) + return; + for (Parameter subP : p.getParameterList()) { + recursivelyLoadMockData(subP, findParamInArray(subP, pMock.getParameterList())); + } + } + + /** + * build JSON + * + * @param json string builder + * @param para parameter to be parsed + * @param index available in array stands for index of array, used for + * special mode of tags like @format[3] which means the third + * record enabled only. Default value should be -1 which disabled + * the feature. + */ + private void buildJson(StringBuilder json, Parameter para, int index) { + boolean isArrayObject = para.getDataType().equals("array"); + int ARRAY_LENGTH = isArrayObject ? 5 : 1; + String[] tags = para.getRemark().split(";"); + Map tagMap = new HashMap(); + parseTags(tags, tagMap, false); + + // if isArray && has @value tag, directly output @value content + if (para.getDataType().contains("array") && tagMap.get("value") != null) { + json.append(para.getMockIdentifier() + ":" + tagMap.get("value")); + } else { + String length = tagMap.get("length"); + if (length != null && !length.isEmpty()) { + ARRAY_LENGTH = Integer.parseInt(length); + } + if (para.getParameterList() == null + || para.getParameterList().size() == 0) { + json.append(para.getMockIdentifier() + ":" + + mockValue(para, index)); + } else { + // object and array + json.append(para.getMockIdentifier() + ":"); + String left = "{", right = "}"; + + if (isArrayObject) { + left = "["; + right = "]"; + } + json.append(left); + boolean first; + for (int i = 0; i < ARRAY_LENGTH; i++) { + first = true; + if (isArrayObject && i > 0) + json.append(","); + if (isArrayObject) + json.append("{"); + for (Parameter p : para.getParameterList()) { + if (first) { + first = false; + } else { + json.append(","); + } + buildJson(json, p, i); + } + if (isArrayObject) + json.append("}"); + } + json.append(right); + } + } + } + + /** + * build mock.js template + * + * @param json string builder + * @param para parameter to be parsed + * @param index available in array stands for index of array, used for + * special mode of tags like @format[3] which means the third + * record enabled only. Default value should be -1 which disabled + * the feature. + */ + private void buildMockTemplate(StringBuilder json, Parameter para, int index) { + boolean isArrayObject = para.getDataType().equals("array"); + int ARRAY_LENGTH = 1; + + if (para.getParameterList() == null + || para.getParameterList().size() == 0 || para.hasMockJSData()) { + json.append(processMockValueWithParams(para.getMockJSIdentifier()) + + ":" + + StringUtils.chineseToUnicode(mockjsValue(para, index))); + } else { + // object and array + json.append(processMockValueWithParams(para.getMockJSIdentifier()) + + ":"); + String left = "{", right = "}"; + + if (isArrayObject) { + left = "["; + right = "]"; + } + json.append(left); + boolean first; + for (int i = 0; i < ARRAY_LENGTH; i++) { + first = true; + if (isArrayObject && i > 0) + json.append(","); + if (isArrayObject) + json.append("{"); + for (Parameter p : para.getParameterList()) { + if (first) { + first = false; + } else { + json.append(","); + } + buildMockTemplate(json, p, i); + } + if (isArrayObject) + json.append("}"); + } + json.append(right); + } + + } + + private String mockValue(Parameter para, int index) { + String dataType = para.getDataType(); + String[] tags = para.getRemark().split(";"); + Map tagMap = new HashMap(); + parseTags(tags, tagMap, true); + String returnValue = "0"; + + if (dataType.equals("number")) { + String regex = tagMap.get("regex_index"); + if (regex != null && !regex.isEmpty()) { + // value should be like "$trueValue_INDEX_5" + String[] arr = regex.split("_INDEX_"); + int tagIndex = Integer.parseInt(arr[1]); + if (tagIndex == index) { + regex = arr[0]; + Xeger generator = new Xeger(regex); + return generator.generate(); + } + } + + regex = tagMap.get("regex"); + if (regex != null && !regex.isEmpty()) { + Xeger generator = new Xeger(regex); + return generator.generate(); + } + + String value = tagMap.get("value_index"); + if (value != null && !value.isEmpty()) { + // value should be like "$trueValue_INDEX_5" + String[] arr = value.split("_INDEX_"); + int tagIndex = Integer.parseInt(arr[1]); + if (tagIndex == index) { + value = arr[0]; + return value; + } + } + value = tagMap.get("value"); + if (value != null && !value.isEmpty()) { + return value; + } + + String format = tagMap.get("format_index"); + if (format != null && !format.isEmpty()) { + String[] arr = format.split("_INDEX_"); + int tagIndex = Integer.parseInt(arr[1]); + if (tagIndex == index) { + format = arr[0]; + return NumberUtils.randomByFormat(format); + } + } + format = tagMap.get("format"); + if (format != null && !format.isEmpty()) { + return NumberUtils.randomByFormat(format); + } + return NumberUtils.randomInt10Str(); + } else if (dataType.equals("string")) { + String regex = tagMap.get("regex_index"); + if (regex != null && !regex.isEmpty()) { + // value should be like "$trueValue_INDEX_5" + String[] arr = regex.split("_INDEX_"); + int tagIndex = Integer.parseInt(arr[1]); + if (tagIndex == index) { + regex = arr[0]; + Xeger generator = new Xeger(regex); + return "\"" + StringUtils.escapeInJ(generator.generate()) + + "\""; + } + } + + regex = tagMap.get("regex"); + if (regex != null && !regex.isEmpty()) { + Xeger generator = new Xeger(regex); + return "\"" + StringUtils.escapeInJ(generator.generate()) + + "\""; + } + + String value = tagMap.get("value_index"); + if (value != null && !value.isEmpty()) { + String[] arr = value.split("_INDEX_"); + int tagIndex = Integer.parseInt(arr[1]); + if (tagIndex == index) { + value = arr[0]; + if (value.contains("[name]")) { + return "\"" + + NAME_LIB[NumberUtils + .randomInt(NAME_LIB.length)] + "\""; + } else if (value.contains("[location]")) { + return "\"" + + LOCATION_LIB[NumberUtils + .randomInt(LOCATION_LIB.length)] + "\""; + } else if (value.contains("[phone]")) { + return "\"" + + PHONE_LIB[NumberUtils + .randomInt(PHONE_LIB.length)] + "\""; + } else { + return "\"" + StringUtils.escapeInJ(value) + "\""; + } + } + } + value = tagMap.get("value"); + if (value != null && !value.isEmpty()) { + if (value.contains("[name]")) { + return "\"" + + NAME_LIB[NumberUtils.randomInt(NAME_LIB.length)] + + "\""; + } else if (value.contains("[location]")) { + return "\"" + + LOCATION_LIB[NumberUtils + .randomInt(LOCATION_LIB.length)] + "\""; + } else if (value.contains("[phone]")) { + return "\"" + + PHONE_LIB[NumberUtils.randomInt(PHONE_LIB.length)] + + "\""; + } else { + return "\"" + StringUtils.escapeInJ(value) + "\""; + } + } + String format = tagMap.get("format"); + if (format != null && !format.isEmpty()) { + return "\"" + NumberUtils.randomByFormat(format) + "\""; + } + return "\"测试内容\""; + } else if (dataType.equals("boolean")) { + String value = tagMap.get("value_index"); + if (value != null && !value.isEmpty()) { + String[] arr = value.split("_INDEX_"); + int tagIndex = Integer.parseInt(arr[1]); + if (tagIndex == index) { + value = arr[0]; + return value; + } + } + value = tagMap.get("value"); + if (value != null && !value.isEmpty()) { + return value; + } + return "true"; + } else if (dataType.equals("array")) { + String value = tagMap.get("value_index"); + if (value != null && !value.isEmpty()) { + String[] arr = value.split("_INDEX_"); + int tagIndex = Integer.parseInt(arr[1]); + if (tagIndex == index) { + value = arr[0]; + return "\"" + value + "\""; + } + } + + value = tagMap.get("value"); + if (value != null && !value.isEmpty()) { + return "\"" + value + "\""; + } + List arr = new ArrayList(); + for (int i = 0; i < 10; i++) { + arr.add(NumberUtils.randomInt(1000)); + } + return ArrayUtils.join(arr, ","); + } else if (dataType.equals("array")) { + String value = tagMap.get("value_index"); + if (value != null && !value.isEmpty()) { + String[] arr = value.split("_INDEX_"); + int tagIndex = Integer.parseInt(arr[1]); + if (tagIndex == index) { + value = arr[0]; + return value; + } + } + value = tagMap.get("value"); + if (value != null && !value.isEmpty()) { + return value; + } + return "[\"测试1\", \"测试2\", \"测试3\", \"测试4\", \"测试5\"]"; + } + return returnValue; + } + + private String mockjsValue(Parameter para, int index) { + String mockData = para.getRemark(); + String[] tags = mockData.split(";"); + if (mockData.contains("@mock=")) { + tags = new String[1]; + tags[0] = mockData.substring(mockData.indexOf("@mock=")); + } + boolean escape = true; + Map tagMap = new HashMap(); + parseTags(tags, tagMap, true); + String returnValue = "1"; + String mockValue = tagMap.get("mock"); + if (mockValue == null && mockData.contains("@mock=")) { + mockValue = ""; + } + if (mockValue == null || mockValue.isEmpty()) { + String unescapeMockValue = tagMap.get("{mock}"); + if (unescapeMockValue != null && !unescapeMockValue.isEmpty()) { + escape = false; + mockValue = unescapeMockValue; + } + } + + // default mock template generation + if (mockValue == null) { + if (para.getDataType().isEmpty()) { + return "1"; + } else if (para.getDataType().equals("number")) { + return NumberUtils.randomByFormat("xxxxx"); + } else if (para.getDataType().equals("boolean")) { + return new Boolean(NumberUtils.randomInt(10) > 5 ? true : false).toString(); + } else if (para.getDataType().equals("string")) { + Xeger generator = new Xeger("测试内容[0-9a-z]{4}"); + return "\"" + generator.generate() + "\""; + } else if (para.getDataType().equals("array")) { + return "[true, false]"; + } else if (para.getDataType().equals("array") || para.getDataType().equals("array")) { + return "[]"; + } else if (para.getDataType().equals("object")) { + return "{}"; + } + } + + mockValue = processMockValueWithParams(mockValue); + + if (mockValue != null && !mockValue.isEmpty()) { + if (mockValue.startsWith("[") && mockValue.endsWith("]")) { + return mockValue; + } else if (mockValue.startsWith("function")) { + return isMockJsData ? "1" : mockValue; + } else if (mockValue.startsWith("$order")) { + if (para.getDataType().contains("array")) { + return "[" + mockValue.substring(7, mockValue.length() - 1) + "]"; + } else { + StringBuilder orderCmdFunc = new StringBuilder(); + orderCmdFunc + .append("function() {") + .append(" var window = function(){return this;}();") + .append(" function geneVal(key) {") + .append(" var o = __rap__context__[key];") + .append(" var arr = o.arr;") + .append(" return arr[o.index++ % arr.length];") + .append(" }") + .append(" if (!window.__rap__context__) {") + .append(" window.__rap__context__ = {};") + .append(" }") + .append(" var orderCmd = \"" + StringUtils.escapeInJ(mockValue) + "\";") + .append(" var orderArr = eval('[' + orderCmd.substring(7, orderCmd.length - 1) + ']');") + .append(" var key = '" + (uid++) + "';") + .append(" if (!__rap__context__[key]) {") + .append(" __rap__context__[key] = {") + .append(" arr : orderArr,") + .append(" index : 0") + .append(" };") + .append(" }") + .append(" return geneVal(key);") + .append("}"); + + return orderCmdFunc.toString(); + } + } else if (mockValue.startsWith("@order")) { + return "\"" + StringUtils.escapeInJ(mockValue) + "\""; + } else if ((para.getDataType().equals("number") + || para.getDataType().equals("boolean")) + && !mockValue.startsWith("@")) { + return mockValue; + } else if ((para.getDataType().equals("array") + || para.getDataType().equals("array") + || para.getDataType().equals("array"))) { + String result = mockValue; + if (para.getDataType().equals("array") + && !result.startsWith("\"") && !result.startsWith("'")) { + result = "\"" + result + "\""; + } + return "[" + result + "]"; + } else { + if (escape) { + mockValue = StringUtils.escapeInJ(mockValue); + } + if (mockValue.startsWith("\\\"") && mockValue.endsWith("\\\"")) { + return mockValue.substring(1, mockValue.length() - 2) + "\""; + } else if (!escape) { + return mockValue; + } else { + return "\"" + mockValue + "\""; + } + } + } else if (mockValue != null && mockValue.isEmpty() + && para.getDataType().equals("string")) { + return "\"\""; + } else if (para.getDataType().equals("array")) { + return "[\"string1\", \"string2\", \"string3\", \"string4\", \"string5\"]"; + + } else if (para.getDataType().equals("array")) { + return "[1, 2, 3, 4, 5]"; + } + return returnValue; + } + + private String processMockValueWithParams(String mockValue) { + + Pattern p = Pattern.compile(Patterns.MOCK_TEMPLATE_PATTERN); + if (mockValue == null) { + mockValue = ""; + } + Matcher matcher = p.matcher(mockValue); + while (matcher.find()) { + int c = matcher.groupCount(); + if (c >= 3) { + String toBeReplaced = matcher.group(0); + String key = matcher.group(1); + String value = matcher.group(2); + List param = requestParams.get(key); + String realValue = (param != null && param.size() > 0) ? param + .get(0) : null; + if (realValue != null && !realValue.isEmpty()) { + mockValue = mockValue.replace(toBeReplaced, realValue); + } else { + mockValue = mockValue.replace(toBeReplaced, value); + } + } + } + return mockValue; + } + + /** + * from tag string to tag map + * + * @param tags tag string input by parsing whole string split by separator + * ";" + * @param tagMap tag map + * @param isMocking + */ + private void parseTags(String[] tags, Map tagMap, + boolean isMocking) { + for (String tag : tags) { + // tag format validation + if (tag.startsWith("@") && tag.contains("=")) { + String val = tag.substring(tag.indexOf("=") + 1); + if (tag.startsWith("@value")) { + if (val.contains("[xx]") && isMocking) { + Integer n = _num++ % 31; + val = val.replace("[xx]", n >= 10 ? n.toString() : "0" + + n); + } + if (tag.contains("value[")) { + tagMap.put( + "value_index", + val + + "_INDEX_" + + tag.substring(tag.indexOf("[") + 1, + tag.indexOf("]"))); + } else { + tagMap.put("value", val); + } + + } else if (tag.startsWith("@format")) { + if (tag.contains("format[")) { + tagMap.put( + "format_index", + val + + "_INDEX_" + + tag.substring(tag.indexOf("[") + 1, + tag.indexOf("]"))); + } else { + tagMap.put("format", val); + } + } else if (tag.startsWith("@length")) { + if (tag.contains("length[")) { + tagMap.put( + "length_index", + val + + "_INDEX_" + + tag.substring(tag.indexOf("[") + 1, + tag.indexOf("]"))); + } else { + tagMap.put("length", tag.split("=")[1]); + } + } else if (tag.startsWith("@regex")) { + if (tag.contains("regex[")) { + tagMap.put( + "regex_index", + val + + "_INDEX_" + + tag.substring(tag.indexOf("[") + 1, + tag.indexOf("]"))); + } else { + tagMap.put("regex", val); + } + } else if (tag.startsWith("@mock")) { + tagMap.put("mock", val); + } else if (tag.startsWith("@{mock}")) { + tagMap.put("{mock}", val); + } + } + } + } + + + public int modify(int actionId, String mockData) { + Action action = projectDao.getAction(actionId); + if (action == null) + return 0; + int num = 0; + // parse mock data + String[] mockDataSnips = mockData.split("_AND_"); + for (String snip : mockDataSnips) { + Set pList = snip.startsWith("request.") ? action + .getRequestParameterList() : action + .getResponseParameterList(); + Parameter p = locateParam(pList, + snip.substring(snip.indexOf(".") + 1)); + if (p == null) + continue; + String paramMockData = snip.substring(snip.indexOf("=") + 1); + p.setMockData(paramMockData); + num++; + } + return num; + } + + /** + * recursively locating parameter specified in the mock data + * + * @param pList + * @param snip request.a.b.c=@xxxx => a.b.c==@xxxx (namely request. or + * response. removed) + * @return + */ + private Parameter locateParam(Set pList, String snip) { + boolean hasSubParam = snip.indexOf(".") > 0 + && snip.indexOf(".") < snip.indexOf("="); + String identifier = hasSubParam ? snip.substring(0, snip.indexOf(".")) + : snip.substring(0, snip.indexOf("=")); + for (Parameter p : pList) { + if (p.getIdentifier().equals(identifier)) { + return hasSubParam ? locateParam(p.getParameterList(), + snip.substring(snip.indexOf(".") + 1)) : p; + } + } + return null; + } + + + public int reset(int projectId) { + return projectDao.resetMockData(projectId); + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/mock/web/action/MockAction.java b/src/main/java/com/taobao/rigel/rap/mock/web/action/MockAction.java new file mode 100644 index 000000000..c12e3e89f --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/mock/web/action/MockAction.java @@ -0,0 +1,483 @@ +package com.taobao.rigel.rap.mock.web.action; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.common.utils.HTTPUtils; +import com.taobao.rigel.rap.common.utils.StringUtils; +import com.taobao.rigel.rap.common.utils.SystemVisitorLog; +import com.taobao.rigel.rap.mock.service.MockMgr; +import com.taobao.rigel.rap.project.bo.Action; +import com.taobao.rigel.rap.project.bo.Module; +import com.taobao.rigel.rap.project.bo.Page; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; +import org.apache.logging.log4j.LogManager; +import org.apache.struts2.ServletActionContext; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class MockAction extends ActionBase { + + private static final org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger(MockAction.class.getName()); + private int id; + private int __id__; + private String pattern; + private String mockData; + private int actionId; + private int projectId; + private String content; + private String callback; + private boolean enable = true; + private String _c; + private ProjectMgr projectMgr; + private List urlList; + private boolean seajs; + private boolean disableLog; + private String mode; + private MockMgr mockMgr; + private String actionData; + private String url; + + public String getActionData() { + return actionData; + } + + public void setActionData(String actionData) { + this.actionData = actionData; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public boolean isDisableLog() { + return disableLog; + } + + public void setDisableLog(boolean disableLog) { + this.disableLog = disableLog; + } + + public List getUrlList() { + return urlList; + } + + public void setUrlList(List urlList) { + this.urlList = urlList; + } + + private String getMethod() { + return ServletActionContext.getRequest().getMethod(); + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public int getProjectId() { + return projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + public boolean isEnable() { + return enable; + } + + public void setEnable(boolean enable) { + this.enable = enable; + } + + public boolean isSeajs() { + return seajs; + } + + public void setSeajs(boolean seajs) { + this.seajs = seajs; + } + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + + public void setMockData(String mockData) { + this.mockData = mockData; + } + + public void setActionId(int actionId) { + this.actionId = actionId; + } + + public String get_c() { + return StringUtils.escapeInHJ(_c); + } + + public void set_c(String _c) { + this._c = _c; + } + + public String getCallback() { + return StringUtils.escapeInHJ(callback); + } + + public void setCallback(String callback) { + this.callback = callback; + } + + public MockMgr getMockMgr() { + return mockMgr; + } + + public void setMockMgr(MockMgr mockMgr) { + this.mockMgr = mockMgr; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getPattern() { + return pattern; + } + + /** + * force callback or _c to be the last parameter + * + * @param pattern + */ + public void setPattern(String pattern) { + this.pattern = pattern; + } + + public String createData() throws UnsupportedEncodingException { + String callback = getCallback(); + boolean isJSON = false; + updateProjectListMockNum(SystemVisitorLog.mock(__id__, "createData", pattern, getCurAccount())); + Map options = new HashMap(); + String _c = get_c(); + String result = mockMgr.generateData(__id__, pattern, options); + if (options.get("callback") != null) { + _c = (String) options.get("callback"); + callback = (String) options.get("callback"); + } + + if (callback != null && !callback.isEmpty()) { + setContent(callback + "(" + result + ")"); + } else if (_c != null && !_c.isEmpty()) { + setContent(_c + "(" + result + ")"); + } else { + isJSON = true; + setContent(result); + } + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } + } + + public String createRule() throws UnsupportedEncodingException { + String callback = getCallback(); + boolean isJSON = false; + updateProjectListMockNum(SystemVisitorLog.mock(__id__, "createRule", pattern, getCurAccount())); + Map options = new HashMap(); + String _c = get_c(); + options.put("method", getMethod()); + String result = mockMgr.generateRule(__id__, pattern, options); + if (options.get("callback") != null) { + _c = (String) options.get("callback"); + callback = (String) options.get("callback"); + } + if (callback != null && !callback.isEmpty()) { + setContent(callback + "(" + result + ")"); + } else if (_c != null && !_c.isEmpty()) { + setContent(_c + "(" + result + ")"); + } else { + isJSON = true; + setContent(result); + } + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } + } + + public String createRuleAuto() throws UnsupportedEncodingException { + String callback = getCallback(); + boolean isJSON = false; + updateProjectListMockNum(SystemVisitorLog.mock(__id__, "createRule", pattern, getCurAccount())); + Map options = new HashMap(); + String _c = get_c(); + options.put("method", getMethod()); + options.put("loadRule", true); // load rules set by Open API (tb_rule) + + String result = mockMgr.generateRule(__id__, pattern, options); + if (options.get("callback") != null) { + _c = (String) options.get("callback"); + callback = (String) options.get("callback"); + } + if (callback != null && !callback.isEmpty()) { + setContent(callback + "(" + result + ")"); + } else if (_c != null && !_c.isEmpty()) { + setContent(_c + "(" + result + ")"); + } else { + isJSON = true; + setContent(result); + } + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } + } + + public String createRuleByActionData() throws UnsupportedEncodingException { + String callback = getCallback(); + boolean isJSON = false; + updateProjectListMockNum(SystemVisitorLog.mock(id, "createRuleByActionData", pattern, getCurAccount())); + Map options = new HashMap(); + String _c = get_c(); + String result = mockMgr.generateRule(id, pattern, options); + if (options.get("callback") != null) { + _c = (String) options.get("callback"); + callback = (String) options.get("callback"); + } + if (callback != null && !callback.isEmpty()) { + setContent(callback + "(" + result + ")"); + } else if (_c != null && !_c.isEmpty()) { + setContent(_c + "(" + result + ")"); + } else { + isJSON = true; + setContent(result); + } + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } + } + + public String modify() { + setNum(mockMgr.modify(actionId, mockData)); + return SUCCESS; + } + + public String reset() { + setNum(mockMgr.reset(projectId)); + return SUCCESS; + } + + public String createPluginScript() { + updateProjectListMockNum(SystemVisitorLog.mock(id, "createPluginScript", pattern, getCurAccount())); + Map _circleRefProtector = new HashMap(); + List list = new ArrayList(); + Project p = projectMgr.getProject(projectId); + + loadWhiteList(p, list, _circleRefProtector); + urlList = list; + return SUCCESS; + } + + public String getWhiteList() { + Map _circleRefProtector = new HashMap(); + List list = new ArrayList(); + Project p = projectMgr.getProject(projectId); + + loadWhiteList(p, list, _circleRefProtector); + urlList = list; + Gson g = new Gson(); + String json = g.toJson(urlList); + setJson(json); + + return SUCCESS; + } + + private void loadWhiteList(Project p, List list, Map map) { + // prevent circle reference + if (p == null || map.get(p.getId() + "") != null) { + return; + } else { + map.put(p.getId() + "", true); + } + if (p != null) { + for (Module m : p.getModuleList()) { + for (Page page : m.getPageList()) { + for (Action a : page.getActionList()) { + list.add(a.getRequestUrlRel()); + } + } + } + } + + String relatedIds = p.getRelatedIds(); + if (relatedIds != null && !relatedIds.isEmpty()) { + String[] relatedIdsArr = relatedIds.split(","); + for (String relatedId : relatedIdsArr) { + int rId = Integer.parseInt(relatedId); + Project rP = projectMgr.getProject(rId); + if (rP != null && rP.getId() > 0) + loadWhiteList(rP, list, map); + } + } + } + + public String createMockjsData() throws UnsupportedEncodingException { + String callback = getCallback(); + boolean isJSON = false; + updateProjectListMockNum(SystemVisitorLog.mock(__id__, "createMockjsData", pattern, getCurAccount())); + String _c = get_c(); + Map options = new HashMap(); + options.put("method", getMethod()); + String result = mockMgr.generateRuleData(__id__, pattern, options); + if (options.get("callback") != null) { + _c = (String) options.get("callback"); + callback = (String) options.get("callback"); + } + if (callback != null && !callback.isEmpty()) { + setContent(callback + "(" + result + ")"); + } else if (_c != null && !_c.isEmpty()) { + setContent(_c + "(" + result + ")"); + } else { + isJSON = true; + setContent(result); + } + + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } + } + + public String createMockjsDataAuto() throws UnsupportedEncodingException { + String callback = getCallback(); + boolean isJSON = false; + updateProjectListMockNum(SystemVisitorLog.mock(__id__, "createMockjsData", pattern, getCurAccount())); + String _c = get_c(); + Map options = new HashMap(); + options.put("method", getMethod()); + options.put("loadRule", true); + String result = mockMgr.generateRuleData(__id__, pattern, options); + if (options.get("callback") != null) { + _c = (String) options.get("callback"); + callback = (String) options.get("callback"); + } + if (callback != null && !callback.isEmpty()) { + setContent(callback + "(" + result + ")"); + } else if (_c != null && !_c.isEmpty()) { + setContent(_c + "(" + result + ")"); + } else { + isJSON = true; + setContent(result); + } + + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } + } + + public String validateAPI() throws UnsupportedEncodingException { + String callback = getCallback(); + boolean isJSON = false; + updateProjectListMockNum(SystemVisitorLog.mock(id, "createRule", pattern, getCurAccount())); + Map options = new HashMap(); + String _c = get_c(); + options.put("method", getMethod()); + + String result = mockMgr.validateAPI(get__id__(), pattern, options, getJson()); + if (options.get("callback") != null) { + _c = (String) options.get("callback"); + callback = (String) options.get("callback"); + } + if (callback != null && !callback.isEmpty()) { + setContent(callback + "(" + result + ")"); + } else if (_c != null && !_c.isEmpty()) { + setContent(_c + "(" + result + ")"); + } else { + isJSON = true; + setContent(result); + } + if (isJSON) { + return "json"; + } else { + return SUCCESS; + } + } + + private void updateProjectListMockNum(List list) { + for (Project p : list) { + Project project = projectMgr.getProject(p.getId()); + if (project == null) continue; + project.setMockNum(p.getMockNum() + project.getMockNum()); + projectMgr.updateProjectNum(project); + } + } + + public int get__id__() { + return __id__; + } + + public void set__id__(int __id__) { + this.__id__ = __id__; + } + + public String requestOnServer() { + setContent("因安全原因,暂时停止该接口."); + return SUCCESS; + +// try { +// setContent(HTTPUtils.sendGet(url)); +// } catch (Exception e) { +// setContent(e.getMessage()); +// } +// +// String contentLowerCase = this.content.toLowerCase(); +// if (contentLowerCase.contains(" accountList; + private long memberNum; + private String creatorName; + private String desc; + private short accessType; + private boolean hasAccess; + + public List getAccountList() { + return accountList; + } + + public void setAccountList(List accountList) { + this.accountList = accountList; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public short getAccessType() { + return accessType; + } + + public void setAccessType(short accessType) { + if (accessType == 10 || accessType == 20) { + this.accessType = accessType; + } else { + this.accessType = 10; // DEFAULT is private + } + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getLogoUrl() { + return logoUrl; + } + + public void setLogoUrl(String logoUrl) { + this.logoUrl = logoUrl; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNameStr() { + if (StringUtils.getLengthOfStringChinese(name) > NAME_STR_MAX_LENGTH) { + return StringUtils.subStringChinese(name, 0, NAME_STR_MAX_LENGTH) + ".."; + } + return name; + } + + public long getMemberNum() { + return memberNum; + } + + public void setMemberNum(long memberNum) { + this.memberNum = memberNum; + } + + public boolean isHasAccess() { + return hasAccess; + } + + public void setHasAccess(boolean hasAccess) { + this.hasAccess = hasAccess; + } + + public String getCreatorName() { + return creatorName; + } + + public void setCreatorName(String creatorName) { + this.creatorName = creatorName; + } + + public boolean isPublic() { + return this.accessType == PUBLIC_ACCESS; + } + + public Map toMap() { + Map map = new HashMap(); + + map.put("id", getId()); + map.put("nameStr", getNameStr()); + map.put("accessType", getAccessType()); + map.put("name", getName()); + + return map; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/bo/Group.java b/src/main/java/com/taobao/rigel/rap/organization/bo/Group.java new file mode 100644 index 000000000..50a300373 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/bo/Group.java @@ -0,0 +1,40 @@ +package com.taobao.rigel.rap.organization.bo; + +public class Group { + private int id; + private String name; + private int productionLineId; + private int userId; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getProductionLineId() { + return productionLineId; + } + + public void setProductionLineId(int productionLineId) { + this.productionLineId = productionLineId; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/bo/ProductionLine.java b/src/main/java/com/taobao/rigel/rap/organization/bo/ProductionLine.java new file mode 100644 index 000000000..063d67750 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/bo/ProductionLine.java @@ -0,0 +1,50 @@ +package com.taobao.rigel.rap.organization.bo; + + +public class ProductionLine { + private int id; + private String name; + private int projectNum; + private int corporationId; + private int userId; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getProjectNum() { + return projectNum; + } + + public void setProjectNum(int projectNum) { + this.projectNum = projectNum; + } + + public int getCorporationId() { + return corporationId; + } + + public void setCorporationId(int corporationId) { + this.corporationId = corporationId; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/dao/OrganizationDao.java b/src/main/java/com/taobao/rigel/rap/organization/dao/OrganizationDao.java new file mode 100644 index 000000000..30fb442e0 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/dao/OrganizationDao.java @@ -0,0 +1,243 @@ +package com.taobao.rigel.rap.organization.dao; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.bo.Group; +import com.taobao.rigel.rap.organization.bo.ProductionLine; + +import java.util.List; + +public interface OrganizationDao { + /** + * get corporation list + * + * @return + */ + List getCorporationList(); + + /** + * get group list + * + * @return + */ + List getGroupList(int productionLineId); + + /** + * get production line list + * + * @return + */ + List getProductionLineList(int corpId); + + /** + * add group + * + * @param group + */ + int addGroup(Group group); + + /** + * add production line + * + * @param productionLine + */ + int addProductionLine(ProductionLine productionLine); + + /** + * remove group + * + * @param groupId + */ + void removeGroup(int groupId); + + /** + * remove production line + * + * @param productionLineId + */ + void removeProductionLine(int productionLineId); + + /** + * update group + * + * @param group + */ + void updateGroup(Group group); + + /** + * update production line + * + * @param productionLine + */ + void updateProductionLine(ProductionLine productionLine); + + /** + * get group + * + * @param id + * @return + */ + Group getGroup(int id); + + /** + * get production line + * + * @param id + * @return + */ + ProductionLine getProductionLine(int id); + + /** + * get corporation + * + * @param id + * @return + */ + Corporation getCorporation(int id); + + /** + * update ProductionLine.projectNum + * + * @param productionLineId + */ + void updateCountersInProductionLine(int productionLineId); + + /** + * get user list of corporation + * + * @param corpId + * @return + */ + List getUserLisOfCorp(int corpId); + + + /** + * add a user to corporation + * + * @param corpId + * @param userId + * @param roleId + */ + void addUserToCorp(int corpId, int userId, int roleId); + + /** + * check if user in corporation + * + * @param userId + * @param corpId + * @return + */ + boolean isUserInCorp(int userId, int corpId); + + /** + * get user role in corporation + * + * @param userId + * @param corpId + * @return roleId + */ + int getUserRoleInCorp(int userId, int corpId); + + /** + * set user role in corporation + * + * @param userId + * @param corpId + * @param roleId + */ + void setUserRoleInCorp(int userId, int corpId, int roleId); + + /** + * + * + * @param pageNum + * @param pageSize + * @param keyword + * @return + */ + List getCorporationListWithPager(int pageNum, int pageSize, String keyword); + + /** + * + * + * @param keyword + * @return + */ + int getCorporationListWithPagerNum(String keyword); + + /** + * + * + * @param userId + * @param pageNum + * @param pageSize + * @param keyword + * @return + */ + List getCorporationListWithPager(int userId, int pageNum, int pageSize, String keyword); + + /** + * + * + * @param userId + * @param keyword + * @return + */ + int getCorporationListWithPagerNum(int userId, String keyword); + + /** + * add new corporation + * + * @param corporation + */ + int addCorporation(Corporation corporation); + + /** + * get number of member in specific corporation + * + * @param corpId + * @return + */ + int getMemberNumOfCorporation(int corpId); + + /** + * get project num of corporation + * + * @param corpId + * @return + */ + int getProjectNumOfCorporation(int corpId); + + /** + * get action num of corporation + * + * @param corpId + * @return + */ + int getActionNumOfCorporation(int corpId); + + /** + * delete all membership from team + * + * @param curUserId the user now operating, used for transfer project + * when the project operated are owned by the user removed. + * @param userId + * @param corpId + */ + void deleteMembershipFromCorp(int curUserId, int userId, int corpId); + + /** + * update corporation + * + * @param c + */ + void updateCorporation(Corporation c); + + /** + * get team id by project id + * + * @param id + * @return + */ + int getTeamIdByProjectId(int id); +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/dao/impl/OrganizationDaoImpl.java b/src/main/java/com/taobao/rigel/rap/organization/dao/impl/OrganizationDaoImpl.java new file mode 100644 index 000000000..77c2577ef --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/dao/impl/OrganizationDaoImpl.java @@ -0,0 +1,400 @@ +package com.taobao.rigel.rap.organization.dao.impl; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.account.dao.AccountDao; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.bo.Group; +import com.taobao.rigel.rap.organization.bo.ProductionLine; +import com.taobao.rigel.rap.organization.dao.OrganizationDao; +import com.taobao.rigel.rap.project.dao.ProjectDao; +import org.hibernate.Query; +import org.hibernate.Session; +import org.springframework.orm.hibernate5.support.HibernateDaoSupport; + +import java.util.ArrayList; +import java.util.List; + +public class OrganizationDaoImpl extends HibernateDaoSupport implements + OrganizationDao { + + private AccountDao accountDao; + private ProjectDao projectDao; + + public AccountDao getAccountDao() { + return accountDao; + } + + public void setAccountDao(AccountDao accountDao) { + this.accountDao = accountDao; + } + + public ProjectDao getProjectDao() { + return projectDao; + } + + public void setProjectDao(ProjectDao projectDao) { + this.projectDao = projectDao; + } + + @SuppressWarnings("unchecked") + + public List getCorporationList() { + return currentSession().createQuery("from Corporation").list(); + } + + @SuppressWarnings("unchecked") + + public List getGroupList(int productionLineId) { + Query query = currentSession().createQuery( + "from Group where productionLineId = :id"); + query.setInteger("id", productionLineId); + return query.list(); + } + + @SuppressWarnings("unchecked") + + public List getProductionLineList(int corpId) { + return currentSession() + .createQuery("from ProductionLine where corporation_id = :id") + .setInteger("id", corpId).list(); + } + + + public int addGroup(Group group) { + Object s = currentSession().save(group); + return (Integer) s; + } + + + public int addProductionLine(ProductionLine productionLine) { + Object s = currentSession().save(productionLine); + return (Integer) s; + } + + + public void removeGroup(int groupId) { + Session session = currentSession(); + Object group = session.get(Group.class, groupId); + if (group != null) { + session.delete((Group) group); + } + } + + + public void removeProductionLine(int productionLineId) { + Session session = currentSession(); + Object productionLine = session.get(ProductionLine.class, + productionLineId); + if (productionLine != null) { + session.delete((ProductionLine) productionLine); + } + } + + + public void updateGroup(Group group) { + Group g = getGroup(group.getId()); + if (g != null) { + g.setName(group.getName()); + currentSession().update(g); + } + } + + + public void updateProductionLine(ProductionLine line) { + ProductionLine p = getProductionLine(line.getId()); + p.setName(line.getName()); + currentSession().update(p); + } + + + public Group getGroup(int id) { + return (Group) currentSession().get(Group.class, id); + } + + + public ProductionLine getProductionLine(int id) { + return (ProductionLine) currentSession().get(ProductionLine.class, id); + } + + + public void updateCountersInProductionLine(int productionLineId) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT COUNT(*) FROM tb_project p ") + .append("JOIN tb_group g ON p.group_id = g.id ") + .append("JOIN tb_production_line pl ON pl.id = g.production_line_id ") + .append("WHERE g.production_line_id = :id"); + Query query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("id", productionLineId); + int num = Integer.parseInt(query.uniqueResult().toString()); + sql = new StringBuilder(); + sql.append("UPDATE tb_production_line SET project_num = :num WHERE id = :id"); + query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("num", num); + query.setInteger("id", productionLineId); + query.executeUpdate(); + } + + + public List getUserLisOfCorp(int corpId) { + Query query = currentSession().createSQLQuery("SELECT user_id FROM tb_corporation_and_user WHERE corporation_id = :corpId"); + query.setInteger("corpId", corpId); + List list = query.list(); + List resultList = new ArrayList(); + for (Integer id : list) { + User user = accountDao.getUser(id); + if (user != null) { + resultList.add(user); + } + } + return resultList; + } + + + public void addUserToCorp(int corpId, int userId, int roleId) { + Query query = currentSession().createSQLQuery("INSERT INTO tb_corporation_and_user (corporation_id, user_id, role_id) VALUES (:corpId, :userId, :roleId)"); + query.setInteger("corpId", corpId) + .setInteger("userId", userId) + .setInteger("roleId", roleId); + query.executeUpdate(); + } + + + public boolean isUserInCorp(int userId, int corpId) { + Query query = currentSession().createSQLQuery("SELECT COUNT(*) FROM tb_corporation_and_user WHERE user_id = :userId AND corporation_id = :corpId"); + query.setInteger("userId", userId).setInteger("corpId", corpId); + int num = Integer.parseInt(query.uniqueResult().toString()); + return num > 0; + } + + + public int getUserRoleInCorp(int userId, int corpId) { + Query query = currentSession().createSQLQuery("SELECT role_id FROM tb_corporation_and_user WHERE user_id = :userId AND corporation_id = :corpId"); + query.setInteger("userId", userId).setInteger("corpId", corpId); + Object result = query.uniqueResult(); + if (result == null) { + return -1; + } + return Integer.parseInt(result.toString()); + } + + + public void setUserRoleInCorp(int userId, int corpId, int roleId) { + Query query = currentSession().createSQLQuery("UPDATE tb_corporation_and_user SET role_id = :roleId WHERE user_id = :userId AND corporation_id = :corpId"); + query.setInteger("roleId", roleId); + query.setInteger("corpId", corpId); + query.setInteger("userId", userId); + query.executeUpdate(); + } + + + public List getCorporationListWithPager(int pageNum, int pageSize, String keyword) { + boolean isSearch = keyword != null && !keyword.trim().isEmpty(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT c.id ") + .append("FROM tb_corporation c "+(isSearch ? " WHERE name LIKE CONCAT('%', :keyword, '%')" : "")) + .append("LIMIT :startIndex, :pageSize "); + + Query query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("startIndex", (pageNum - 1) * pageSize); + query.setInteger("pageSize", pageSize); + if (isSearch) { + query.setString("keyword", keyword); + } + List list = (List) query.list(); + List resultList = new ArrayList(); + for (Integer id : list) { + Corporation row = getCorporation(id); + resultList.add(row); + } + return resultList; + } + + + public int getCorporationListWithPagerNum(String keyword) { + boolean isSearch = keyword != null && !keyword.trim().isEmpty(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT COUNT(*) ") + .append("FROM tb_corporation c " +(isSearch ? " WHERE name LIKE CONCAT('%', :keyword, '%')" : "")); + + Query query = currentSession().createSQLQuery(sql.toString()); + if (isSearch) { + query.setString("keyword", keyword); + } + + return Integer.parseInt(query.uniqueResult().toString()); + } + + + public List getCorporationListWithPager(int userId, int pageNum, int pageSize, String keyword) { + boolean isSearch = keyword != null && !keyword.trim().isEmpty(); + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT DISTINCT cid FROM ( ") + .append(" SELECT c.id AS cid ") + .append(" FROM tb_corporation c ") + .append(" JOIN tb_corporation_and_user u ON u.corporation_id = c.id ") + .append(" WHERE u.user_id = :userId " + (isSearch ? "AND c.name LIKE CONCAT('%', :keyword, '%') " : "")) + .append(" UNION ") + .append(" SELECT id AS cid FROM tb_corporation ") + .append(" WHERE (user_id = :userId or access_type = 20) " + (isSearch ? "AND name LIKE CONCAT('%', :keyword, '%') " : "")) + .append(") AS TEMP ") + .append("LIMIT :startIndex, :pageSize "); + + Query query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("userId", userId); + query.setInteger("startIndex", (pageNum - 1) * pageSize); + query.setInteger("pageSize", pageSize); + if (isSearch) { + query.setString("keyword", keyword); + } + + List list = query.list(); + List resultList = new ArrayList(); + for (int id : list) { + Corporation row = getCorporation(id); + resultList.add(row); + } + return resultList; + } + + + public int getCorporationListWithPagerNum(int userId, String keyword) { + boolean isSearch = keyword != null && !keyword.trim().isEmpty(); + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT COUNT(DISTINCT cid) FROM ( ") + .append(" SELECT c.id AS cid ") + .append(" FROM tb_corporation c ") + .append(" JOIN tb_corporation_and_user u ON u.corporation_id = c.id ") + .append(" WHERE u.user_id = :userId " + (isSearch ? "AND c.name LIKE CONCAT('%', :keyword, '%') " : "")) + .append(" UNION ") + .append(" SELECT id AS cid FROM tb_corporation ") + .append(" WHERE (user_id = :userId or access_type = 20) " + (isSearch ? "AND name LIKE CONCAT('%', :keyword, '%') " : "")) + .append(") AS TEMP "); + + Query query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("userId", userId); + if (isSearch) { + query.setString("keyword", keyword); + } + return Integer.parseInt(query.uniqueResult().toString()); + } + + + public int addCorporation(Corporation c) { + Session session = currentSession(); + Query query = session.createSQLQuery("INSERT INTO tb_corporation (`name`, logo_url, user_id, access_type, `desc`) VALUES (:name, :logoUrl, :userId, :accessType, :desc)"); + query.setString("name", c.getName()); + query.setString("logoUrl", c.getLogoUrl()); + query.setInteger("userId", c.getUserId()); + query.setShort("accessType", c.getAccessType()); + query.setString("desc", c.getDesc()); + query.executeUpdate(); + + return Integer.parseInt(session.createSQLQuery("SELECT LAST_INSERT_ID()").uniqueResult().toString()); + } + + + public int getMemberNumOfCorporation(int corpId) { + String sql = "SELECT COUNT(DISTINCT cu.user_id) FROM tb_corporation c JOIN tb_corporation_and_user cu ON cu.corporation_id = c.id WHERE c.id = :corpId"; + + Query query = currentSession().createSQLQuery(sql); + query.setInteger("corpId", corpId); + + return Integer.parseInt(query.uniqueResult().toString()); + } + + public int getProjectNumOfCorporation(int corpId) { + String sql = "SELECT COUNT(p.id) \n" + + "FROM tb_project p \n" + + "JOIN tb_group g ON g.id = p.group_id \n" + + "JOIN tb_production_line pl ON p.id = g.production_line_id\n" + + "WHERE pl.corporation_id = :corpId"; + Query query = currentSession().createSQLQuery(sql); + query.setInteger("corpId", corpId); + + return Integer.parseInt(query.uniqueResult().toString()); + } + + public int getActionNumOfCorporation(int corpId) { + String sql = "SELECT COUNT(a.id) \n" + + "FROM tb_action a\n" + + "JOIN tb_action_and_page ap ON ap.action_id = a.id\n" + + "JOIN tb_page p ON p.id = ap.page_id\n" + + "JOIN tb_module m ON m.id = p.module_id\n" + + "JOIN tb_project pr ON pr.id = m.project_id\n" + + "JOIN tb_group g ON g.id = pr.group_id \n" + + "JOIN tb_production_line pl ON pl.id = g.production_line_id\n" + + "WHERE pl.corporation_id = :corpId"; + Query query = currentSession().createSQLQuery(sql); + query.setInteger("corpId", corpId); + + return Integer.parseInt(query.uniqueResult().toString()); + } + + private List getProjectIdsFromCorporation(int userId, int corpId) { + StringBuilder builder = new StringBuilder(); + builder.append("SELECT DISTINCT p.id AS projectId ") + .append("FROM tb_project p ") + .append("JOIN tb_project_and_user pu ON p.id = pu.project_id ") + .append("JOIN tb_group g ON g.id = p.group_id ") + .append("JOIN tb_production_line pl ON pl.id = g.production_line_id ") + .append("JOIN tb_corporation c ON c.id = pl.corporation_id ") + .append("WHERE p.user_id = :userId AND c.id = :corpId"); + Query query = currentSession().createSQLQuery(builder.toString()); + query.setInteger("userId", userId); + query.setInteger("corpId", corpId); + List idList = query.list(); + return idList; + } + + + public void deleteMembershipFromCorp(int curUserId, int userId, int corpId) { + Query query = currentSession().createSQLQuery("DELETE FROM tb_corporation_and_user WHERE corporation_id = :corpId AND user_id = :userId"); + query.setInteger("userId", userId); + query.setInteger("corpId", corpId); + query.executeUpdate(); + + List idList = getProjectIdsFromCorporation(userId, corpId); + + for (Integer projectId : idList) { + projectDao.updateCreatorId(projectId, curUserId); + } + } + + + public void updateCorporation(Corporation c) { + Query query = currentSession().createSQLQuery("UPDATE tb_corporation SET `name`=:name, `desc`=:desc, access_type=:accessType WHERE id=:id"); + query.setString("name", c.getName()); + query.setString("desc", c.getDesc()); + query.setShort("accessType", c.getAccessType()); + query.setInteger("id", c.getId()); + query.executeUpdate(); + } + + + public int getTeamIdByProjectId(int id) { + StringBuilder sql = new StringBuilder(); + + sql.append(" SELECT c.id"); + sql.append(" FROM tb_project p"); + sql.append(" JOIN tb_group g ON g.id = p.group_id"); + sql.append(" JOIN tb_production_line pl ON pl.id = g.production_line_id"); + sql.append(" JOIN tb_corporation c ON c.id = pl.corporation_id"); + sql.append(" WHERE p.id = :id"); + + Query query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("id", id); + Object resultObj = query.uniqueResult(); + if (resultObj == null) { + return 0; + } else { + return (Integer) resultObj; + } + } + + + public Corporation getCorporation(int id) { + return currentSession().get(Corporation.class, id); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/service/OrganizationMgr.java b/src/main/java/com/taobao/rigel/rap/organization/service/OrganizationMgr.java new file mode 100644 index 000000000..2bae51862 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/service/OrganizationMgr.java @@ -0,0 +1,337 @@ +package com.taobao.rigel.rap.organization.service; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.bo.RapError; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.bo.Group; +import com.taobao.rigel.rap.organization.bo.ProductionLine; + +import java.util.List; + +public interface OrganizationMgr { + /** + * get corporation list + * + * @return + */ + List getCorporationList(); + + /** + * get corporation list with pager and search + * + * @param pageNum + * @param pageSize + * @param keyword + * @return + */ + List getCorporationListWithPager(int pageNum, int pageSize, String keyword); + + /** + * get corporation list num + * + * @param keyword + * @return + */ + int getCorporationListWithPagerNum(String keyword); + + /** + * get corporation list of user with pager and search + * + * @param userId + * @param pageNum + * @param pageSize + * @param keyword + * @return + */ + List getCorporationListWithPager(int userId, int pageNum, int pageSize, String keyword); + + /** + * get corporation list num + * + * @param userId + * @param keyword + * @return + */ + int getCorporationListWithPagerNum(int userId, String keyword); + + /** + * get group list + * + * @return + * @param productionLineId + */ + List getGroupList(int productionLineId); + + /** + * get production line list + * + * @return + * @param corpId + */ + List getProductionLineList(int corpId); + + /** + * add group + * + * @param group + */ + int addGroup(Group group); + + /** + * add production line + * + * @param productionLine + */ + int addProductionLine(ProductionLine productionLine); + + /** + * remove group + * + * @param groupId + */ + RapError removeGroup(int groupId); + + /** + * remove production line + * + * @param productionLineId + */ + RapError removeProductionLine(int productionLineId); + + /** + * update group + * + * @param group + */ + void updateGroup(Group group); + + /** + * update production line + * + * @param productionLine + */ + void updateProductionLine(ProductionLine productionLine); + + /** + * get production line + * + * @param plid + * @return + */ + ProductionLine getProductionLine(int plid); + + /** + * get corporation + * + * @param id + * @return + */ + Corporation getCorporation(int id); + + + /** + * can user access corporation + * + * @param userId + * @param corpId + * @return + */ + boolean canUserAccessCorp(int userId, int corpId); + + + /** + * user access validation + * + * @param userId + * @param projectId + * @return + */ + boolean canUserManageProject(int userId, int projectId); + + + /** + * can user delete project + * + * @param userId + * @param projectId + * @return + */ + boolean canUserDeleteProject(int userId, int projectId); + + /** + * can user manage corporation + * + * @param userId + * @param corpId + * @return + */ + boolean canUserManageCorp(int userId, int corpId); + + /** + * get user list of corporation + * + * @param corpId + * @return + */ + List getUserLisOfCorp(int corpId); + + /** + * get user role in corporation + * + * @param userId + * @param corpId + * @return roleId + */ + int getUserRoleInCorp(int userId, int corpId); + + /** + * can user access project + * + * @param userId + * @param projectId + * @return + */ + boolean canUserAccessProject(int userId, int projectId); + + /** + * can user access page + * + * @param userId + * @param pageId + * @return + */ + boolean canUserAccessPage(int userId, int pageId); + + + /** + * can user access production line + * + * @param userId + * @param plId + * @return + */ + boolean canUserAccessProductionLine(int userId, int plId); + + /** + * can user manage production line + * + * @param userId + * @param plId + * @return + */ + boolean canUserManageProductionLine(int userId, int plId); + + /** + * can user access group + * + * @param userId + * @param groupId + * @return + */ + boolean canUserAccessGroup(int userId, int groupId); + + /** + * can user manage grup + * + * @param userId + * @param groupId + * @return + */ + boolean canUserManageGroup(int userId, int groupId); + + /** + * add new team + * + * @param team + * @return id + */ + int addTeam(Corporation team); + + /** + * set user role in corporation + * + * @param curUserId user now proceeding the operation + * @param userId user to be processed + * @param corpId + * @param roleId + * @return if succeed + */ + boolean setUserRoleInCorp(int curUserId, int userId, int corpId, int roleId); + + /** + * remove member from team + * + * @param curUserId + * @param userId + * @param corpId + * @return + */ + boolean removeMemberFromCorp(int curUserId, int userId, int corpId); + + /** + * add team members + * + * @param curUserId + * @param corpId + * @param accountList + * @return + */ + boolean addTeamMembers(int curUserId, int corpId, String accountList); + + /** + * update corporation + * + * @param c + */ + void updateCorporation(Corporation c); + + + /** + * get team id by project id + * + * @param id + * @return + */ + int getTeamIdByProjectId(int id); + + /** + * get group + * + * @param id + * @return + */ + Group getGroup(int id); + + /** + * get number of member in specific corporation + * + * @param corpId + * @return + */ + int getMemberNumOfCorporation(int corpId); + + /** + * get project num of corporation + * + * @param corpId + * @return + */ + int getProjectNumOfCorporation(int corpId); + + /** + * get action num of corporation + * + * @param corpId + * @return + */ + int getActionNumOfCorporation(int corpId); + + /** + * as titles + * + * @param curUserId + * @param plId + * @return + */ + boolean canUserManageProductionLineList(int curUserId, int plId); +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/service/impl/OrganizationMgrImpl.java b/src/main/java/com/taobao/rigel/rap/organization/service/impl/OrganizationMgrImpl.java new file mode 100644 index 000000000..097e68237 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/service/impl/OrganizationMgrImpl.java @@ -0,0 +1,433 @@ +package com.taobao.rigel.rap.organization.service.impl; + +import com.taobao.rigel.rap.account.bo.Role; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.account.service.AccountMgr; +import com.taobao.rigel.rap.common.bo.RapError; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.bo.Group; +import com.taobao.rigel.rap.organization.bo.ProductionLine; +import com.taobao.rigel.rap.organization.dao.OrganizationDao; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.Module; +import com.taobao.rigel.rap.project.bo.Page; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +import java.util.ArrayList; +import java.util.List; + +public class OrganizationMgrImpl implements OrganizationMgr { + private OrganizationDao organizationDao; + private ProjectMgr projectMgr; + private AccountMgr accountMgr; + + public AccountMgr getAccountMgr() { + return accountMgr; + } + + public void setAccountMgr(AccountMgr accountMgr) { + this.accountMgr = accountMgr; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public OrganizationDao getOrganizationDao() { + return organizationDao; + } + + public void setOrganizationDao(OrganizationDao organizationDao) { + this.organizationDao = organizationDao; + } + + + public List getCorporationList() { + return organizationDao.getCorporationList(); + } + + + public List getCorporationListWithPager(int pageNum, int pageSize, String keyword) { + + List list = organizationDao.getCorporationListWithPager(pageNum, pageSize, keyword); + + for (Corporation c : list) { + int memberNum = organizationDao.getMemberNumOfCorporation(c.getId()); + c.setMemberNum(memberNum + 1); // +1 project creator + c.setHasAccess(true); + c.setCreatorName(accountMgr.getUser(c.getUserId()).getName()); + } + return list; + } + + + public int getCorporationListWithPagerNum(String keyword) { + return organizationDao.getCorporationListWithPagerNum(keyword); + } + + + public List getCorporationListWithPager(int userId, int pageNum, int pageSize, String keyword) { + User user = accountMgr.getUser(userId); + if (user.isAdmin()) { + return getCorporationListWithPager(pageNum, pageSize, keyword); + } + List list = organizationDao.getCorporationListWithPager(userId, pageNum, pageSize, keyword); + for (Corporation c : list) { + int memberNum = organizationDao.getMemberNumOfCorporation(c.getId()); + c.setMemberNum(memberNum + 1); // +1 project creator + c.setHasAccess(canUserManageCorp(userId, c.getId())); + c.setCreatorName(accountMgr.getUser(c.getUserId()).getName()); + } + return list; + } + + + public int getCorporationListWithPagerNum(int userId, String keyword) { + User user = accountMgr.getUser(userId); + if (user.isAdmin()) { + return getCorporationListWithPagerNum(keyword); + } + return organizationDao.getCorporationListWithPagerNum(userId, keyword); + } + + + public List getGroupList(int productionLineId) { + return organizationDao.getGroupList(productionLineId); + } + + + public List getProductionLineList(int corpId) { + return organizationDao.getProductionLineList(corpId); + } + + + public int addGroup(Group group) { + return organizationDao.addGroup(group); + } + + + public int addProductionLine(ProductionLine productionLine) { + return organizationDao.addProductionLine(productionLine); + } + + + public RapError removeGroup(int groupId) { + if (!groupCanBeDeleted(groupId)) { + return new RapError(RapError.ERR_HAS_CHILDREN, + "为确保您的数据安全,请先删除分组下的项目,再删除该分组。"); + } else { + organizationDao.removeGroup(groupId); + return new RapError(); + } + } + + private boolean groupCanBeDeleted(int groupId) { + List list = projectMgr.getProjectListByGroup(groupId); + + return list == null || list.size() == 0; + } + + + public RapError removeProductionLine(int productionLineId) { + if (!productionLineCanBeDeleted(productionLineId)) { + return new RapError(RapError.ERR_HAS_CHILDREN, + "为确保您的数据安全,请先删除业务线下的分组及项目,再删除该业务线。"); + } else { + organizationDao.removeProductionLine(productionLineId); + return new RapError(); + } + } + + private boolean productionLineCanBeDeleted(int productionLineId) { + List list = this.getGroupList(productionLineId); + return list == null || list.size() == 0; + } + + + public void updateGroup(Group group) { + organizationDao.updateGroup(group); + } + + + public void updateProductionLine(ProductionLine productionLine) { + organizationDao.updateProductionLine(productionLine); + } + + + public ProductionLine getProductionLine(int plid) { + return organizationDao.getProductionLine(plid); + } + + + public Corporation getCorporation(int id) { + return organizationDao.getCorporation(id); + } + + + public boolean canUserAccessCorp(int userId, int corpId) { + Corporation c = getCorporation(corpId); + if (c == null) return false; + if (c.getUserId() == userId) return true; // team owner + if (c.getAccessType() == Corporation.PUBLIC_ACCESS) return true; // public team + User user = accountMgr.getUser(userId); + if (user != null && user.isAdmin()) return true; + return organizationDao.isUserInCorp(userId, corpId); + } + + public boolean canUserManageProject(int userId, int projectId) { + String[] cacheKey = new String[]{CacheUtils.KEY_ACCESS_USER_TO_PROJECT, new Integer(userId).toString(), new Integer(projectId).toString()}; + + String cache = CacheUtils.get(cacheKey); + if (cache != null) { + return Boolean.parseBoolean(cache); + } + + User user = accountMgr.getUser(userId); + boolean canAccess = false; + int corpId = organizationDao.getTeamIdByProjectId(projectId); + int roleId = organizationDao.getUserRoleInCorp(userId, corpId); + Project project = projectMgr.getProjectSummary(projectId); + if (user.isUserInRole("admin")) { + canAccess = true; + } else if (project.getUserId() == userId) { + canAccess = true; + } else if (Role.isAdmin(roleId)) { + canAccess = true; + } else { + List memberIdList = projectMgr.getMemberIdsOfProject(projectId); + if (memberIdList != null) { + for (int memberId : memberIdList) { + if (memberId == user.getId()) { + canAccess = true; + break; + } + } + } + } + + CacheUtils.put(cacheKey, new Boolean(canAccess).toString()); + return canAccess; + } + + public boolean canUserDeleteProject(int userId, int projectId) { + User user = accountMgr.getUser(userId); + Project project = projectMgr.getProjectSummary(projectId); + int corpId = getTeamIdByProjectId(projectId); + int roleId = organizationDao.getUserRoleInCorp(userId, corpId); + return user.isAdmin() || project.getUserId() == user.getId() || Role.isAdmin(roleId); + } + + public boolean canUserManageCorp(int userId, int corpId) { + int roleId = organizationDao.getUserRoleInCorp(userId, corpId); + return (Role.isAdmin(roleId) || + userId == getCorporation(corpId).getUserId()) || + accountMgr.getUser(userId).isAdmin(); + + } + + public List getUserLisOfCorp(int corpId) { + List list = organizationDao.getUserLisOfCorp(corpId); + Corporation c = getCorporation(corpId); + User u = accountMgr.getUser(c.getUserId()); + list.add(u); + for (User user : list) { + int roleId = getUserRoleInCorp(user.getId(), corpId); + if (user.isAdmin()) { + roleId = Role.SUPER_ADMIN; // user is the RAP platform admin + } else if (user.getId() == c.getUserId()) { + roleId = Role.SUPER_ADMIN; // user is the author + } + user.setRoleId(roleId); + } + return list; + } + + + public int getUserRoleInCorp(int userId, int corpId) { + return organizationDao.getUserRoleInCorp(userId, corpId); + } + + + public boolean canUserAccessProject(int userId, int projectId) { + User u = accountMgr.getUser(userId); + Project p = projectMgr.getProject(projectId); + int teamId = organizationDao.getTeamIdByProjectId(projectId); + Corporation c = organizationDao.getCorporation(teamId); + + return u.isAdmin() || p.isUserMember(userId) || c.isPublic() + || canUserAccessCorp(userId, c.getId()) || p.getUser().getId() == userId; + } + + + public boolean canUserAccessPage(int userId, int pageId) { + Page page = projectMgr.getPage(pageId); + if (page != null) { + Module module = page.getModule(); + if (module != null) { + Project project = module.getProject(); + if (project != null) { + return canUserAccessProject(userId, project.getId()); + } + } + } + return false; + } + + + public boolean canUserAccessProductionLine(int userId, int plId) { + ProductionLine pl = this.getProductionLine(plId); + int corpId = pl.getCorporationId(); + Corporation team = getCorporation(corpId); + if (team.getAccessType() == Corporation.PUBLIC_ACCESS) { + return true; + } + return canUserAccessCorp(userId, corpId); + } + + + public boolean canUserManageProductionLine(int userId, int plId) { + ProductionLine pl = this.getProductionLine(plId); + int corpId = pl.getCorporationId(); + return canUserManageProductionLineList(userId, corpId); + } + + + public boolean canUserAccessGroup(int userId, int groupId) { + Group g = organizationDao.getGroup(groupId); + ProductionLine pl = getProductionLine(g.getProductionLineId()); + int corpId = pl.getCorporationId(); + Corporation team = getCorporation(corpId); + if (team.getAccessType() == Corporation.PUBLIC_ACCESS) { + return true; + } + return canUserAccessCorp(userId, corpId); + } + + + public boolean canUserManageGroup(int userId, int groupId) { + Group g = organizationDao.getGroup(groupId); + ProductionLine pl = getProductionLine(g.getProductionLineId()); + int corpId = pl.getCorporationId(); + return canUserManageCorp(userId, corpId); + } + + + public int addTeam(Corporation team) { + + int corpId = organizationDao.addCorporation(team); + for (String account : team.getAccountList()) { + if (account == null || account.trim().isEmpty()) continue; + User u = accountMgr.getUser(account); + + String [] cacheKey = new String[]{CacheUtils.KEY_CORP_LIST_TOP_ITEMS, new Integer(u.getId()).toString()}; + CacheUtils.del(cacheKey); + + if (u.getId() == team.getUserId()) { + // if the user is creator, there's no need to add again + continue; + } + organizationDao.addUserToCorp(corpId, u.getId(), 3); // 3, normal member + } + + String [] cacheKey = new String[]{CacheUtils.KEY_CORP_LIST_TOP_ITEMS, new Integer(team.getUserId()).toString()}; + CacheUtils.del(cacheKey); + + return corpId; + } + + + public boolean setUserRoleInCorp(int curUserId, int userId, int corpId, int roleId) { + if (canUserManageCorp(curUserId, corpId)) { + organizationDao.setUserRoleInCorp(userId, corpId, roleId); + String[] cacheKey = new String[]{CacheUtils.KEY_PROJECT_LIST, new Integer(userId).toString()}; + CacheUtils.del(cacheKey); + return true; + } else { + return false; + } + } + + + public boolean removeMemberFromCorp(int curUserId, int userId, int corpId) { + // if user can't manage team, failed + if (!canUserManageCorp(curUserId, corpId)) { + return false; + } + organizationDao.deleteMembershipFromCorp(curUserId, userId, corpId); + return true; + } + + + public boolean addTeamMembers(int curUserId, int corpId, String accountList) { + if (!canUserManageCorp(curUserId, corpId)) + return false; + + String[] accs = accountList.split(","); + Corporation c = getCorporation(corpId); + for (String acc : accs) { + User u = accountMgr.getUser(acc); + if (u != null) { + if (!organizationDao.isUserInCorp(u.getId(), corpId) + && u.getId() != c.getUserId()) { + organizationDao.addUserToCorp(corpId, u.getId(), 3); + } + String [] cacheKey = new String[]{CacheUtils.KEY_CORP_LIST_TOP_ITEMS, new Integer(u.getId()).toString()}; + CacheUtils.del(cacheKey); + } + } + + return true; + } + + + public void updateCorporation(Corporation c) { + // clear cache + + List userIdList = new ArrayList(); + userIdList.add(c.getUserId()); + List userList = getUserLisOfCorp(c.getId()); + for (User u : userList) { + userIdList.add(u.getId()); + } + + for (Integer userId : userIdList) { + String [] cacheKey = new String[]{CacheUtils.KEY_CORP_LIST_TOP_ITEMS, userId.toString()}; + CacheUtils.del(cacheKey); + } + organizationDao.updateCorporation(c); + } + + public int getTeamIdByProjectId(int id) { + return organizationDao.getTeamIdByProjectId(id); + } + + public Group getGroup(int id) { + return organizationDao.getGroup(id); + } + + public int getMemberNumOfCorporation(int corpId) { + return organizationDao.getMemberNumOfCorporation(corpId); + } + + public int getProjectNumOfCorporation(int corpId) { + return organizationDao.getProjectNumOfCorporation(corpId); + } + + public int getActionNumOfCorporation(int corpId) { + return organizationDao.getActionNumOfCorporation(corpId); + } + + public boolean canUserManageProductionLineList(int userId, int corpId) { + if (canUserManageCorp(userId, corpId)) { + return true; + } + Corporation c = getCorporation(corpId); + return c.getAccessType() == Corporation.PUBLIC_ACCESS; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/web/action/GroupAction.java b/src/main/java/com/taobao/rigel/rap/organization/web/action/GroupAction.java new file mode 100644 index 000000000..63fd68edb --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/web/action/GroupAction.java @@ -0,0 +1,191 @@ +package com.taobao.rigel.rap.organization.web.action; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.common.bo.RapError; +import com.taobao.rigel.rap.organization.bo.Group; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class GroupAction extends ActionBase { + + private OrganizationMgr organizationMgr; + private ProjectMgr projectMgr; + private int id; + private String name; + + public int getProductlineId() { + return productlineId; + } + + public void setProductlineId(int productlineId) { + this.productlineId = productlineId; + } + + private int productlineId; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public String all() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (!organizationMgr.canUserAccessProductionLine(getCurUserId(), productlineId)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + Gson gson = new Gson(); + Map result = new HashMap(); + List> groups = new ArrayList>(); + List groupModels = organizationMgr.getGroupList(productlineId); + for (Group groupModel : groupModels) { + Map group = new HashMap(); + group.put("id", groupModel.getId()); + group.put("name", groupModel.getName()); + List projectModelList = projectMgr + .getProjectListByGroup(groupModel.getId()); + List> projects = new ArrayList>(); + for (Project projectModel : projectModelList) { + if (getCurUser().isUserInRole("admin") + || organizationMgr.canUserManageProject( + getCurUser().getId(), projectModel.getId())) { + projectModel.setIsManagable(true); + } + Map project = new HashMap(); + project.put("id", projectModel.getId()); + project.put("name", projectModel.getName()); + project.put("desc", projectModel.getIntroduction()); + project.put("status", projectModel.getLastUpdateStr()); + project.put("accounts", projectModel.getMemberAccountListStr()); + project.put("isManagable", projectModel.isManagable()); + project.put("creator", projectModel.getUser().getUserBaseInfo()); + project.put("teamId", projectModel.getTeamId()); + projects.add(project); + } + group.put("projects", projects); + groups.add(group); + } + + result.put("groups", groups); + + setJson(gson.toJson(result)); + return SUCCESS; + } + + public String groups() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (!organizationMgr.canUserAccessProductionLine(getCurUserId(), productlineId)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + Gson gson = new Gson(); + Map result = new HashMap(); + List> groups = new ArrayList>(); + List groupModels = organizationMgr.getGroupList(productlineId); + for (Group groupModel : groupModels) { + Map group = new HashMap(); + group.put("id", groupModel.getId()); + group.put("name", groupModel.getName()); + groups.add(group); + } + + result.put("groups", groups); + + setJson(gson.toJson(result)); + return SUCCESS; + } + + public String create() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (!organizationMgr.canUserManageProductionLine(getCurUserId(), productlineId)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + Gson gson = new Gson(); + Group group = new Group(); + group.setName(name); + group.setUserId((int) getCurUserId()); + group.setProductionLineId(productlineId); + int id = organizationMgr.addGroup(group); + Map g = new HashMap(); + g.put("id", id); + g.put("name", name); + setJson("{\"groups\":[" + gson.toJson(g) + "]}"); + return SUCCESS; + } + + public String delete() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (!organizationMgr.canUserManageGroup(getCurUserId(), id)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + RapError error = organizationMgr.removeGroup(id); + setJson(error.toString()); + return SUCCESS; + } + + public String update() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (!organizationMgr.canUserManageGroup(getCurUserId(), id)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + Group group = new Group(); + group.setId(id); + group.setName(name); + organizationMgr.updateGroup(group); + setJson("{\"isOk\":\"true\"}"); + return SUCCESS; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/web/action/OrganizationAction.java b/src/main/java/com/taobao/rigel/rap/organization/web/action/OrganizationAction.java new file mode 100644 index 000000000..76f84aff1 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/web/action/OrganizationAction.java @@ -0,0 +1,182 @@ +package com.taobao.rigel.rap.organization.web.action; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.bo.ProductionLine; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class OrganizationAction extends ActionBase { + private OrganizationMgr organizationMgr; + private ProjectMgr projectMgr; + + public int getPlid() { + return plid; + } + + public void setPlid(int plid) { + this.plid = plid; + } + + private int plid; + private int id; + private ProductionLine productline; + + public void setTeam(Corporation team) { + this.team = team; + } + + private Corporation team; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public ProductionLine getProductline() { + return productline; + } + + public Corporation getTeam() { + return team; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public String myHome() { + return SUCCESS; + } + + public String index() { + if (isUserLogined()) { + return SUCCESS; + } else { + return "public"; + } + + } + + public String group() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/org/group.do?plid=" + plid); + return LOGIN; + } + + if (!organizationMgr.canUserAccessProductionLine(getCurUserId(), plid)) { + setErrMsg(ACCESS_DENY); + return ERROR; + } + + productline = organizationMgr.getProductionLine(plid); + team = organizationMgr.getCorporation(productline.getCorporationId()); + return SUCCESS; + } + + public String productline() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/org/productline.do?id=" + id); + return LOGIN; + } + + if (!organizationMgr.canUserAccessCorp(getCurUserId(), id)) { + setErrMsg(ACCESS_DENY); + return ERROR; + } + + setTeam(organizationMgr.getCorporation(id)); + return SUCCESS; + } + + public String projects() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + + int curUserId = getCurUserId(); + + String[] cacheKey = new String[]{CacheUtils.KEY_PROJECT_LIST, new Integer(curUserId).toString()}; + + String cacheResult = CacheUtils.get(cacheKey); + if (cacheResult != null) { + setJson(cacheResult); + } else { + + Gson gson = new Gson(); + + List> projects = new ArrayList>(); + + // int totalRecNum = projectMgr.getProjectListNum(getCurUser()); + User curUser = getAccountMgr().getUser(curUserId); + List projectList = projectMgr.getProjectList(curUser, 1, + Integer.MAX_VALUE); + + + for (Project p : projectList) { + Map map = new HashMap(); + map.put("id", p.getId()); + map.put("name", p.getName()); + map.put("desc", p.getIntroduction()); + map.put("status", p.getLastUpdateStr()); + map.put("accounts", p.getMemberAccountListStr()); + map.put("isManagable", p.isManagable()); + map.put("isDeletable", p.isDeletable()); + map.put("creator", p.getUser().getUserBaseInfo()); + map.put("related", p.getUser().getId() != curUserId); + map.put("teamId", p.getTeamId()); + projects.add(map); + } + StringBuilder json = new StringBuilder(); + json.append("{"); + json.append(" \"groups\" : [{"); + json.append(" \"type\" : \"user\","); + json.append(" \"projects\" :"); + json.append(gson.toJson(projects)); + json.append(" }]"); + json.append("}"); + setJson(json.toString()); + CacheUtils.put(cacheKey, json.toString()); + } + return SUCCESS; + } + + public String corporationList() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + + Gson gson = new Gson(); + setJson(gson.toJson(organizationMgr.getCorporationListWithPager(getCurUserId(), 1, 1000, null))); + return SUCCESS; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/web/action/ProductlineAction.java b/src/main/java/com/taobao/rigel/rap/organization/web/action/ProductlineAction.java new file mode 100644 index 000000000..52ff43ad9 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/web/action/ProductlineAction.java @@ -0,0 +1,132 @@ +package com.taobao.rigel.rap.organization.web.action; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.organization.bo.ProductionLine; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ProductlineAction extends ActionBase { + + private OrganizationMgr organizationMgr; + private int corpId; + private int id; + private String name; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getCorpId() { + return corpId; + } + + + public void setCorpId(int corpId) { + this.corpId = corpId; + } + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public String all() { + if (!isUserLogined()) { + plsLogin(); + return ERROR; + } + if (!organizationMgr.canUserAccessCorp(getCurUserId(), corpId)) { + setErrMsg(ACCESS_DENY); + return ERROR; + } + Map result = new HashMap(); + List> items = new ArrayList>(); + List lineModels = organizationMgr + .getProductionLineList(corpId); + for (ProductionLine lineModel : lineModels) { + Map line = new HashMap(); + line.put("id", lineModel.getId()); + line.put("name", lineModel.getName()); + line.put("count", lineModel.getProjectNum()); + items.add(line); + } + result.put("items", items); + + Gson gson = new Gson(); + setJson(gson.toJson(result)); + return SUCCESS; + } + + public String create() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (!organizationMgr.canUserManageProductionLineList(getCurUserId(), corpId)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + ProductionLine line = new ProductionLine(); + Gson gson = new Gson(); + line.setName(name); + line.setUserId((int) getCurUserId()); + line.setCorporationId(corpId); + int id = organizationMgr.addProductionLine(line); + Map p = new HashMap(); + p.put("id", id); + p.put("name", name); + setJson("{\"items\":[" + gson.toJson(p) + "]}"); + return SUCCESS; + } + + public String delete() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (!organizationMgr.canUserManageProductionLine(getCurUserId(), id)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + setJson(organizationMgr.removeProductionLine(id).toString()); + return SUCCESS; + } + + public String update() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + if (!organizationMgr.canUserManageProductionLine(getCurUserId(), id)) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + + ProductionLine line = new ProductionLine(); + line.setId(id); + line.setName(name); + organizationMgr.updateProductionLine(line); + setJson("{\"isOk\":\"true\"}"); + return SUCCESS; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/organization/web/action/TeamAction.java b/src/main/java/com/taobao/rigel/rap/organization/web/action/TeamAction.java new file mode 100644 index 000000000..1167d30ff --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/organization/web/action/TeamAction.java @@ -0,0 +1,266 @@ +package com.taobao.rigel.rap.organization.web.action; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.common.utils.StringUtils; +import com.taobao.rigel.rap.common.config.SystemConstant; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by Bosn on 15/10/14. + */ +public class TeamAction extends ActionBase { + + private static final org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getFormatterLogger(TeamAction.class.getName()); + private int id; + private String name; + private String accountList; + private int teamListNum; + private List userList; + private int userId; + private Corporation team; + private int pageNum; + private List teamList; + private short accessType; + private OrganizationMgr organizationMgr; + private String desc; + + public String getKeyword() { + return keyword; + } + + public void setKeyword(String keyword) { + this.keyword = keyword; + } + + private String keyword; + + public Corporation getTeam() { + return team; + } + + public int getPageNum() { + if (pageNum > 0) + return pageNum; + else + return 1; + } + + public void setPageNum(int pageNum) { + this.pageNum = pageNum; + } + + public List getTeamList() { + return teamList; + } + + public short getAccessType() { + return accessType; + } + + public void setAccessType(short accessType) { + this.accessType = accessType; + } + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getName() { + return name; + } + + public void setName(String name) { + if (name == null || name.trim().isEmpty()) { + name = "unnamed"; + } + + this.name = StringUtils.removeIllegalCharacters(name); + this.name = name; + } + + public String getAccountList() { + return accountList; + } + + public void setAccountList(String accountList) { + this.accountList = accountList; + } + + public String create() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + Corporation team = new Corporation(); + team.setName(getName()); + team.setUserId(getCurUserId()); + team.setAccountList(Arrays.asList(getAccountList().split(","))); + team.setDesc(getDesc()); + team.setAccessType(getAccessType()); + team.setLogoUrl(""); + int id = organizationMgr.addTeam(team); + setJson("{\"id\":" + id + "}"); + String [] cacheKey = new String[]{CacheUtils.KEY_CORP_LIST, new Integer(getCurUserId()).toString()}; + CacheUtils.del(cacheKey); + return SUCCESS; + } + + public String teams() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/org/team/teams.do"); + return LOGIN; + } + int userId = getCurUserId(); + teamList = organizationMgr.getCorporationListWithPager(userId, getPageNum(), SystemConstant.DEFAULT_PAGE_SIZE, keyword); + teamListNum = organizationMgr.getCorporationListWithPagerNum(userId, keyword); + return SUCCESS; + } + + public int getTeamListNum() { + return teamListNum; + } + + public int getTeamListPageInTotal() { + double result = Math.ceil((double) teamListNum / (double) SystemConstant.DEFAULT_PAGE_SIZE); + return (int) result; + } + + public String manage() { + int corpId = getId(); + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/org/team/manage.do?id=" + corpId); + return LOGIN; + } + if (!organizationMgr.canUserManageCorp(getCurUserId(), corpId)) { + setErrMsg("你无权访问该页面。"); + return ERROR; + } + + userList = organizationMgr.getUserLisOfCorp(corpId); + team = organizationMgr.getCorporation(corpId); + + return SUCCESS; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List getUserList() { + return userList; + } + + public String changeAccessType() { + User curUser = getAccountMgr().getUser(getCurUserId()); + if (curUser == null) { + setErrMsg(LOGIN_WARN_MSG); + setIsOk(false); + logger.error("Unlogined user trying to checkin and failed."); + return JSON_ERROR; + } + if (organizationMgr.setUserRoleInCorp(getCurUserId(), getUserId(), getId(), getAccessType())) { + return SUCCESS; + } else { + return "json-error"; + } + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String deleteMember() { + User curUser = getAccountMgr().getUser(getCurUserId()); + if (curUser == null) { + setErrMsg(LOGIN_WARN_MSG); + setIsOk(false); + logger.error("Unlogined user trying to checkin and failed."); + return JSON_ERROR; + } + if (organizationMgr.removeMemberFromCorp(getCurUserId(), getUserId(), getId())) { + return SUCCESS; + } else { + return "json-error"; + } + } + + public String addMembers() { + User curUser = getAccountMgr().getUser(getCurUserId()); + if (curUser == null) { + setErrMsg(LOGIN_WARN_MSG); + setIsOk(false); + logger.error("Unlogined user trying to checkin and failed."); + return JSON_ERROR; + } + + if (organizationMgr.addTeamMembers(getCurUserId(), getId(), accountList)) { + return SUCCESS; + } else { + return "json-error"; + } + } + + public String update() { + User curUser = getAccountMgr().getUser(getCurUserId()); + if (curUser == null) { + setErrMsg(LOGIN_WARN_MSG); + setIsOk(false); + logger.error("Unlogined user trying to checkin and failed."); + return JSON_ERROR; + } + + if (!organizationMgr.canUserManageCorp(curUser.getId(), getId())) { + return JSON_ERROR; + } + + Corporation c = new Corporation(); + c.setId(getId()); + c.setName(getName()); + c.setDesc(getDesc()); + c.setAccessType(getAccessType()); + organizationMgr.updateCorporation(c); + + return SUCCESS; + } + + public String search() { + User curUser = getAccountMgr().getUser(getCurUserId()); + if (curUser == null) { + setErrMsg(LOGIN_WARN_MSG); + setIsOk(false); + logger.error("Unlogined user trying to checkin and failed."); + return JSON_ERROR; + } + + + return SUCCESS; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/platform/dao/DataDao.java b/src/main/java/com/taobao/rigel/rap/platform/dao/DataDao.java new file mode 100644 index 000000000..dbf4c75c6 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/platform/dao/DataDao.java @@ -0,0 +1,21 @@ +package com.taobao.rigel.rap.platform.dao; + +import java.util.List; +import java.util.Map; + +/** + * Created by Bosn on 14-9-5. + */ +public interface DataDao { + + List> getUserTrendByMonth(); + + List> getProjectTrendByMonth(); + + List> getCheckInTrendByMonth(); + + List> getActionNumByTeam(); + + List> getTop10ActionNumByTeam(int teamId); + +} diff --git a/src/main/java/com/taobao/rigel/rap/platform/dao/impl/DataDaoImpl.java b/src/main/java/com/taobao/rigel/rap/platform/dao/impl/DataDaoImpl.java new file mode 100644 index 000000000..21082cd5a --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/platform/dao/impl/DataDaoImpl.java @@ -0,0 +1,158 @@ +package com.taobao.rigel.rap.platform.dao.impl; + +import com.taobao.rigel.rap.platform.dao.DataDao; +import org.hibernate.Query; +import org.springframework.orm.hibernate5.support.HibernateDaoSupport; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Bosn on 14-9-5. + */ +public class DataDaoImpl extends HibernateDaoSupport implements DataDao { + + public List> getUserTrendByMonth() { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT MONTH(create_date) AS month, COUNT(id) as num, create_date ") + .append("FROM tb_user ") + .append("WHERE create_date BETWEEN DATE_ADD(NOW(), INTERVAL -1 YEAR) AND NOW() ") + .append("GROUP BY MONTH(create_date) ") + .append("ORDER BY create_date"); + Query query = currentSession().createSQLQuery(sql.toString()); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("num", row[1]); + map.put("date", row[2]); + result.add(map); + } + + Object count = currentSession().createSQLQuery("SELECT COUNT(*) FROM tb_user WHERE create_date < DATE_ADD(NOW(), INTERVAL -1 YEAR)") + .uniqueResult(); + Map mapCount = new HashMap(); + mapCount.put("startValue", count); + result.add(mapCount); + + + return result; + } + + + public List> getProjectTrendByMonth() { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT MONTH(create_date) AS month, COUNT(id) as num, create_date ") + .append("FROM tb_project ") + .append("WHERE create_date BETWEEN DATE_ADD(NOW(), INTERVAL -1 YEAR) AND NOW() ") + .append("GROUP BY MONTH(create_date) ") + .append("ORDER BY create_date"); + Query query = currentSession().createSQLQuery(sql.toString()); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("num", row[1]); + map.put("date", row[2]); + result.add(map); + } + + Object count = currentSession().createSQLQuery("SELECT COUNT(*) FROM tb_project WHERE create_date < DATE_ADD(NOW(), INTERVAL -1 YEAR)") + .uniqueResult(); + Map mapCount = new HashMap(); + mapCount.put("startValue", count); + result.add(mapCount); + + return result; + } + + + public List> getCheckInTrendByMonth() { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT MONTH(create_date) AS month, COUNT(id) as num, create_date ") + .append("FROM tb_check_in ") + .append("WHERE create_date BETWEEN DATE_ADD(NOW(), INTERVAL -1 YEAR) AND NOW() ") + .append("GROUP BY MONTH(create_date) ") + .append("ORDER BY create_date"); + Query query = currentSession().createSQLQuery(sql.toString()); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("num", row[1]); + map.put("date", row[2]); + result.add(map); + } + + Object count = currentSession().createSQLQuery("SELECT COUNT(*) FROM tb_check_in WHERE create_date < DATE_ADD(NOW(), INTERVAL -1 YEAR)") + .uniqueResult(); + Map mapCount = new HashMap(); + mapCount.put("startValue", count); + result.add(mapCount); + + return result; + } + + + public List> getActionNumByTeam() { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT c.name, COUNT(a.id) as num ") + .append("FROM tb_action a ") + .append("JOIN tb_action_and_page ap ON ap.action_id = a.id ") + .append("JOIN tb_page p ON p.id = ap.page_id ") + .append("JOIN tb_module m ON m.id = p.module_id ") + .append("JOIN tb_project pr ON pr.id = m.project_id ") + .append("JOIN tb_group g ON g.id = pr.group_id ") + .append("JOIN tb_production_line pl ON pl.id = g.production_line_id ") + .append("JOIN tb_corporation c ON c.id = pl.corporation_id ") + .append("GROUP BY c.name ") + .append("ORDER BY COUNT(a.id) DESC "); + + + Query query = currentSession().createSQLQuery(sql.toString()); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("name", row[0]); + map.put("num", row[1]); + result.add(map); + } + + return result; + } + + public List> getTop10ActionNumByTeam(int teamId) { + String sql = "SELECT\n" + + " p.name AS name,\n" + + " COUNT(a.id) AS actionNum\n" + + "FROM tb_production_line pl\n" + + " JOIN tb_group g ON g.production_line_id = pl.id\n" + + " JOIN tb_project p ON p.group_id = g.id\n" + + " JOIN tb_module m ON m.project_id = p.id\n" + + " JOIN tb_page p2 ON p2.module_id = m.id\n" + + " JOIN tb_action_and_page ap ON ap.page_id = p2.id\n" + + " JOIN tb_action a ON a.id = ap.action_id\n" + + "WHERE pl.corporation_id = :corpId\n" + + "GROUP BY p.id\n" + + "ORDER BY COUNT(a.id) DESC\n" + + "LIMIT 0, 50"; + Query query = currentSession().createSQLQuery(sql); + query.setInteger("corpId", teamId); + List list = query.list(); + List> result = new ArrayList>(); + for (Object[] row : list) { + Map map = new HashMap(); + map.put("name", row[0].toString()); + map.put("num", row[1].toString()); + result.add(map); + } + return result; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/platform/service/DataMgr.java b/src/main/java/com/taobao/rigel/rap/platform/service/DataMgr.java new file mode 100644 index 000000000..04c0ba01f --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/platform/service/DataMgr.java @@ -0,0 +1,22 @@ +package com.taobao.rigel.rap.platform.service; + +import java.util.List; +import java.util.Map; + +/** + * Created by mashengbo on 14-9-5. + */ +public interface DataMgr { + + List> getUserTrendByMonth(); + + List> getProjectTrendByMonth(); + + List> getCheckInTrendByMonth(); + + List> getActionNumByTeam(); + + List> getMockNumByProject(); + + List> getTop10ActionNumByTeam(int teamId); +} diff --git a/src/main/java/com/taobao/rigel/rap/platform/service/impl/DataMgrImpl.java b/src/main/java/com/taobao/rigel/rap/platform/service/impl/DataMgrImpl.java new file mode 100644 index 000000000..37749a911 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/platform/service/impl/DataMgrImpl.java @@ -0,0 +1,74 @@ +package com.taobao.rigel.rap.platform.service.impl; + +import com.taobao.rigel.rap.platform.dao.DataDao; +import com.taobao.rigel.rap.platform.service.DataMgr; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by Bosn on 14-9-5. + */ +public class DataMgrImpl implements DataMgr { + private DataDao dataDao; + private ProjectMgr projectMgr; + + public DataDao getDataDao() { + return dataDao; + } + + public void setDataDao(DataDao dataDao) { + this.dataDao = dataDao; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + + public List> getUserTrendByMonth() { + return dataDao.getUserTrendByMonth(); + } + + + public List> getProjectTrendByMonth() { + return dataDao.getProjectTrendByMonth(); + } + + + public List> getCheckInTrendByMonth() { + return dataDao.getCheckInTrendByMonth(); + } + + + public List> getActionNumByTeam() { + return dataDao.getActionNumByTeam(); + } + + + public List> getMockNumByProject() { + List list = projectMgr.selectMockNumTopNProjectList(5); + List> results = new ArrayList>(); + for (Project p : list) { + Map row = new HashMap(); + row.put("id", p.getId()); + row.put("name", p.getName()); + row.put("mockNum", p.getMockNum()); + results.add(row); + } + return results; + } + + public List> getTop10ActionNumByTeam(int teamId) { + return dataDao.getTop10ActionNumByTeam(teamId); + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/platform/web/action/PlatformAction.java b/src/main/java/com/taobao/rigel/rap/platform/web/action/PlatformAction.java new file mode 100644 index 000000000..b68ce3307 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/platform/web/action/PlatformAction.java @@ -0,0 +1,267 @@ +package com.taobao.rigel.rap.platform.web.action; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.common.bo.Item; +import com.taobao.rigel.rap.common.config.SystemConstant; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.common.utils.CommonUtils; +import com.taobao.rigel.rap.common.utils.SystemVisitorLog; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.platform.service.DataMgr; +import com.taobao.rigel.rap.project.service.ProjectMgr; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PlatformAction extends ActionBase { + // private static final Logger logger = LogManager.getFormatterLogger(PlatformAction.class); + private Gson gson = new Gson(); + private String time; + private Map>> trends; + private Map>> statistics; + private int tabIndex; + private ProjectMgr projectMgr; + private List modelLog; + private Map modelLogMap; + private DataMgr dataMgr; + private String text; + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + private OrganizationMgr organizationMgr; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + private int id; + + public void setTime(String time) { + this.time = time; + } + + public Map>> getTrends() { + return trends; + } + + public Map>> getStatistics() { + return statistics; + } + + public String getTrendsJSON() { + return gson.toJson(getTrends()); + } + + public String getStatisticsJSON() { + return gson.toJson(getStatistics()); + } + + public String getRealtimeJSON() { + return gson.toJson(SystemVisitorLog.getRealtimeMap("0")); + } + + public String getRealtimeJSONByTime(String time) { + return gson.toJson(SystemVisitorLog.getRealtimeMap(time)); + } + + public int getTabIndex() { + return tabIndex; + } + + public void setTabIndex(int tabIndex) { + this.tabIndex = tabIndex; + } + + public Map getModelLogMap() { + return modelLogMap; + } + + public List getModelLog() { + return modelLog; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public DataMgr getDataMgr() { + return dataMgr; + } + + public void setDataMgr(DataMgr dataMgr) { + this.dataMgr = dataMgr; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String home() { + return SUCCESS; + } + + public String test() { + return SUCCESS; + } + + public String teamLog() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/platform/teamLog.do?id=" + id); + return LOGIN; + } + if (!organizationMgr.canUserAccessCorp(getCurUserId(), id)) { + setErrMsg(ACCESS_DENY); + return ERROR; + } + Corporation team = organizationMgr.getCorporation(id); + if (team == null) { + setErrMsg("错误的team id,请检查页面参数是否复制不完整."); + return ERROR; + } + + String[] cacheKey = {CacheUtils.KEY_STATISTICS_OF_TEAM, new Integer(getId()).toString()}; + String cache = CacheUtils.get(cacheKey); + + if (cache != null) { + Map mapCache = CommonUtils.gson.fromJson(cache, new TypeToken>() { + }.getType()); + modelLogMap = (Map) mapCache.get("modelLogMap"); + trends = (Map>>) mapCache.get("trends"); + statistics = (Map>>) mapCache.get("statistics"); + modelLog = (List) mapCache.get("modelLog"); + } else { + modelLog = new ArrayList(); + modelLogMap = new HashMap(); + trends = new HashMap>>(); + statistics = new HashMap>>(); + + // statistics for RAP models + modelLog.add(new Item("user", "" + organizationMgr.getMemberNumOfCorporation(id))); + modelLog.add(new Item("project", "" + organizationMgr.getProjectNumOfCorporation(id))); + modelLog.add(new Item("action", "" + organizationMgr.getActionNumOfCorporation(id))); + + for (Item item : modelLog) { + modelLogMap.put(item.getKey(), item); + } + + // trends data + trends.put("user", dataMgr.getUserTrendByMonth()); + trends.put("project", dataMgr.getProjectTrendByMonth()); + trends.put("checkIn", dataMgr.getCheckInTrendByMonth()); + + + // statistics data + statistics.put("top10ActionNumByTeam", dataMgr.getTop10ActionNumByTeam(id)); + + Map mapCache = new HashMap(); + mapCache.put("modelLogMap", modelLogMap); + mapCache.put("trends", trends); + mapCache.put("statistics", statistics); + mapCache.put("modelLog", modelLog); + CacheUtils.put(cacheKey, CommonUtils.gson.toJson(mapCache)); + } + return SUCCESS; + } + + public String log() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/platform/log.do"); + return LOGIN; + } + String[] cacheKey = {CacheUtils.KEY_STATISTICS}; + String cache = CacheUtils.get(cacheKey); + + if (cache != null) { + Map mapCache = CommonUtils.gson.fromJson(cache, new TypeToken>() { + }.getType()); + modelLogMap = (Map) mapCache.get("modelLogMap"); + trends = (Map>>) mapCache.get("trends"); + statistics = (Map>>) mapCache.get("statistics"); + modelLog = (List) mapCache.get("modelLog"); + } else { + modelLog = new ArrayList(); + modelLogMap = new HashMap(); + trends = new HashMap>>(); + statistics = new HashMap>>(); + + // statistics for RAP models + modelLog.add(new Item("user", new Integer(getAccountMgr().getUserNum()).toString())); + modelLog.add(new Item("project", new Integer(projectMgr.getProjectNum()).toString())); + modelLog.add(new Item("action", new Integer(projectMgr.getActionNum()).toString())); + + //modelLog.add(new Item("TAB数", new Integer(projectMgr.getModuleNum()).toString())); + //modelLog.add(new Item("页面数", new Integer(projectMgr.getPageNum()).toString())); + //odelLog.add(new Item("参数数", new Integer(projectMgr.getParametertNum()).toString())); + + modelLog.add(new Item("checkIn", new Integer(projectMgr.getCheckInNum()).toString())); + modelLog.add(new Item("mockNum", new Integer(projectMgr.getMockNumInTotal()).toString())); + + for (Item item : modelLog) { + modelLogMap.put(item.getKey(), item); + } + + // trends data + trends.put("user", dataMgr.getUserTrendByMonth()); + trends.put("project", dataMgr.getProjectTrendByMonth()); + trends.put("checkIn", dataMgr.getCheckInTrendByMonth()); + + + // statistics data + statistics.put("actionNumByTeam", dataMgr.getActionNumByTeam()); + statistics.put("mockNumByProject", dataMgr.getMockNumByProject()); + statistics.put("mockNumByProjectToday", SystemVisitorLog.getMockNumByProjectToday(projectMgr)); + + Map mapCache = new HashMap(); + mapCache.put("modelLogMap", modelLogMap); + mapCache.put("trends", trends); + mapCache.put("statistics", statistics); + mapCache.put("modelLog", modelLog); + CacheUtils.put(cacheKey, CommonUtils.gson.toJson(mapCache)); + } + return SUCCESS; + } + + public String realtimeUpdate() { + setJson(getRealtimeJSONByTime(time)); + return SUCCESS; + } + + public String monitor() { + Map logs = new HashMap(); + logs.put("ipLog", SystemVisitorLog.getAllIpLog()); + logs.put("userLog", SystemVisitorLog.getAllUserLog()); + logs.put("mockLog", SystemVisitorLog.getMockMapList()); + Gson gson = new Gson(); + setJson(gson.toJson(logs)); + return SUCCESS; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/Action.java b/src/main/java/com/taobao/rigel/rap/project/bo/Action.java new file mode 100644 index 000000000..926adb5e0 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/Action.java @@ -0,0 +1,287 @@ +package com.taobao.rigel.rap.project.bo; + +import com.taobao.rigel.rap.common.utils.StringUtils; + +import java.util.*; + +public class Action implements java.io.Serializable { + + private int id; + private int disableCache; + private String name; + private String description; + private String requestType = "1"; + private String requestUrl; + private Set requestParameterList = new HashSet(); + private Set responseParameterList = new HashSet(); + private String responseTemplate; + private Set pageList = new HashSet(); + private String remarks; + + public static List loadList(List> result) { + List list = new ArrayList(); + for (Map row : result) { + Action obj = new Action(); + obj.setDescription((String) row.get("description")); + obj.setId((Integer) row.get("id")); + obj.setName((String) row.get("name")); + obj.setRemarks((String) row.get("remarks")); + obj.setRequestType((String) row.get("request_type")); + obj.setRequestUrl((String) row.get("request_url")); + list.add(obj); + } + return list; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getDisableCache() { + return disableCache; + } + + public void setDisableCache(int disableCache) { + this.disableCache = disableCache; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description == null ? "" : description; + } + + public String getRequestType() { + return requestType; + } + + public void setRequestType(String requestType) { + if (requestType == null || requestType == "") + return; + this.requestType = requestType; + } + + public String getMethod() { + if (this.requestType.equals("2")) { + return "POST"; + } else if (this.requestType.equals("3")) { + return "PUT"; + } else if (this.requestType.equals("4")) { + return "DELETE"; + } else { + return "GET"; // in default + } + } + + public String getRequestUrl() { + return requestUrl; + } + + public void setRequestUrl(String requestUrl) { + this.requestUrl = requestUrl == null ? "" : requestUrl; + } + + public void addParameter(Parameter parameter, boolean isRequest) { + if (isRequest) { + getRequestParameterList().add(parameter); + parameter.getActionRequestList().add(this); + } else { + getResponseParameterList().add(parameter); + parameter.getActionResponseList().add(this); + } + } + + public Set getRequestParameterList() { + return requestParameterList; + } + + public void setRequestParameterList(Set requestParameterList) { + this.requestParameterList = requestParameterList; + } + + public Set getResponseParameterList() { + return responseParameterList; + } + + public void setResponseParameterList(Set responseParameterList) { + this.responseParameterList = responseParameterList; + } + + public List getRequestParameterListOrdered() { + Set parameterList = getRequestParameterList(); + List parameterListOrdered = new ArrayList(); + parameterListOrdered.addAll(parameterList); + Collections.sort(parameterListOrdered, new ParameterComparator()); + return parameterListOrdered; + } + + public List getResponseParameterListOrdered() { + Set parameterList = getResponseParameterList(); + List parameterListOrdered = new ArrayList(); + parameterListOrdered.addAll(parameterList); + Collections.sort(parameterListOrdered, new ParameterComparator()); + return parameterListOrdered; + } + + public String getResponseTemplate() { + return responseTemplate; + } + + public void setResponseTemplate(String responseTemplate) { + this.responseTemplate = responseTemplate == null ? "" + : responseTemplate; + } + + public Set getPageList() { + return pageList; + } + + public void setPageList(Set pageList) { + this.pageList = pageList; + } + + public void update(Action action) { + setDescription(action.getDescription()); + setName(action.getName()); + setRequestType(action.getRequestType()); + setRequestUrl(action.getRequestUrl()); + setResponseTemplate(action.getResponseTemplate()); + } + + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append("{\"id\":" + getId() + ","); + stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + + "\","); + stringBuilder.append("\"description\":\"" + + StringUtils.escapeInJ(getDescription()) + "\","); + stringBuilder.append("\"requestType\":\"" + getRequestType() + "\","); + stringBuilder.append("\"requestUrl\":\"" + + StringUtils.escapeInJ(getRequestUrl()) + "\","); + stringBuilder.append("\"responseTemplate\":\"" + + StringUtils.escapeInJ(getResponseTemplate()) + "\","); + stringBuilder.append("\"requestParameterList\":"); + + stringBuilder.append("["); + Iterator iterator = getRequestParameterListOrdered() + .iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + stringBuilder.append("],"); + + stringBuilder.append("\"responseParameterList\":"); + + stringBuilder.append("["); + iterator = getResponseParameterListOrdered().iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + stringBuilder.append("]}"); + return stringBuilder.toString(); + } + + public String getRemarks() { + return remarks; + } + + public void setRemarks(String remarks) { + this.remarks = remarks; + } + + /** + * get request parameter list HTML for file exporting reason: velocity + * doesn't support macro recursion. + * + * @return + */ + public String getRequestParameterListHTML() { + return getParameterListHTML(requestParameterList); + } + + public String getResponseParameterListHTML() { + return getParameterListHTML(responseParameterList); + } + + private String getParameterListHTML(Set list) { + StringBuilder html = new StringBuilder(); + html + .append("") + .append("") + .append("") + .append("") + .append("") + .append("") + .append(""); + getParameterListHTMLSub(html, list, (short) 1); + html.append("
    NameIdentifierTypeRemark
    "); + return html.toString(); + } + + private void getParameterListHTMLSub(StringBuilder html, Set list, short level) { + for (Parameter p : list) { + html + .append("") + .append("" + levelMark(level) + StringUtils.escapeInH(p.getName()) + "") + .append("" + StringUtils.escapeInH(p.getIdentifier()) + "") + .append("" + StringUtils.escapeInH(p.getDataType()) + "") + .append("" + StringUtils.escapeInH(p.getRemark()) + "") + .append(""); + if (p.getParameterList() != null || p.getParameterList().size() > 0) { + getParameterListHTMLSub(html, p.getParameterList(), (short) (level + 1)); + } + } + + } + + /** + * level 1: level 2:--- level 3:------ ... + * + * @param level started from 1 + * @return + */ + private String levelMark(short level) { + StringBuilder sb = new StringBuilder(); + for (short i = 1; i < level; i++) { + sb.append("---"); + } + return sb.toString(); + } + + public String getRequestUrlRel() { + String url = this.requestUrl; + if (url == null || url.isEmpty()) { + return "xxxxxxxxxxxxxxxxEMPTY URLxxxxxxxxxxxxxxxxx"; + } + if (url.contains("https://")) { + url = url.substring(url.indexOf("/", 7)); + } else if (url.contains("http://")) { + url = url.substring(url.indexOf("/", 8)); + } + return url; + } + + public enum TYPE {REQUEST, RESPONSE} + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/ActionComparator.java b/src/main/java/com/taobao/rigel/rap/project/bo/ActionComparator.java new file mode 100644 index 000000000..5332cebf3 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/ActionComparator.java @@ -0,0 +1,11 @@ +package com.taobao.rigel.rap.project.bo; + +import java.util.Comparator; + +public class ActionComparator implements Comparator { + + public int compare(Action o1, Action o2) { + return o1.getId() < o2.getId() ? 0 : 1; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/CheckInComparator.java b/src/main/java/com/taobao/rigel/rap/project/bo/CheckInComparator.java new file mode 100644 index 000000000..79bae64eb --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/CheckInComparator.java @@ -0,0 +1,14 @@ +package com.taobao.rigel.rap.project.bo; + +import com.taobao.rigel.rap.workspace.bo.CheckIn; + +import java.util.Comparator; + +public class CheckInComparator implements Comparator { + + + public int compare(CheckIn o1, CheckIn o2) { + return o1.getId() > o2.getId() ? -1 : 1; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/Module.java b/src/main/java/com/taobao/rigel/rap/project/bo/Module.java new file mode 100644 index 000000000..3c626aa6a --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/Module.java @@ -0,0 +1,125 @@ +package com.taobao.rigel.rap.project.bo; + +import com.taobao.rigel.rap.common.utils.StringUtils; + +import java.util.*; + +public class Module implements java.io.Serializable { + + private int id; + private int projectId; + private String name; + private String introduction; + private Project project; + private Set pageList = new HashSet(); + + public int getId() { + return this.id; + } + + public void setId(int id) { + this.id = id; + } + + public int getProjectId() { + return this.projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIntroduction() { + return this.introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = (introduction == null ? "" : introduction); + } + + public Project getProject() { + return this.project; + } + + public void setProject(Project project) { + this.project = project; + } + + public void addPage(Page page) { + getPageList().add(page); + page.setModule(this); + } + + public Set getPageList() { + return this.pageList; + } + + public void setPageList(Set pageList) { + this.pageList = pageList; + } + + public List getPageListOrdered() { + Set pageList = getPageList(); + List pageListOrdered = new ArrayList(); + pageListOrdered.addAll(pageList); + Collections.sort(pageListOrdered, new PageComparator()); + return pageListOrdered; + } + + public void update(Module module) { + setIntroduction(module.getIntroduction()); + setName(module.getName()); + } + + public String toString() { + + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append("{\"id\":" + getId() + ","); + stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); + stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\","); + stringBuilder.append("\"pageList\":"); + + stringBuilder.append("["); + Iterator iterator = getPageListOrdered().iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + stringBuilder.append("]}"); + + return stringBuilder.toString(); + } + + public String toString(Project.TO_STRING_TYPE type) { + + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append("{\"id\":" + getId() + ","); + stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); + stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\","); + stringBuilder.append("\"pageList\":"); + + stringBuilder.append("["); + Iterator iterator = getPageListOrdered().iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next().toString(type)); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + stringBuilder.append("]}"); + + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/ModuleComparator.java b/src/main/java/com/taobao/rigel/rap/project/bo/ModuleComparator.java new file mode 100644 index 000000000..d0f72a334 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/ModuleComparator.java @@ -0,0 +1,11 @@ +package com.taobao.rigel.rap.project.bo; + +import java.util.Comparator; + +public class ModuleComparator implements Comparator { + + public int compare(Module o1, Module o2) { + return o1.getId() < o2.getId() ? 0 : 1; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/ObjectItem.java b/src/main/java/com/taobao/rigel/rap/project/bo/ObjectItem.java new file mode 100644 index 000000000..5f314ff4d --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/ObjectItem.java @@ -0,0 +1,23 @@ +package com.taobao.rigel.rap.project.bo; + +public class ObjectItem implements java.io.Serializable { + + public String className; + private int id; + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/Page.java b/src/main/java/com/taobao/rigel/rap/project/bo/Page.java new file mode 100644 index 000000000..8f296cbc0 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/Page.java @@ -0,0 +1,126 @@ +package com.taobao.rigel.rap.project.bo; + +import com.taobao.rigel.rap.common.utils.StringUtils; + +import java.util.*; + +public class Page implements java.io.Serializable { + + private int id; + private String name; + private String introduction; + private Module module; + private Set actionList = new HashSet(); + private String template; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIntroduction() { + return introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = (introduction == null ? "" : introduction); + } + + public Module getModule() { + return module; + } + + public void setModule(Module module) { + this.module = module; + } + + public Set getActionList() { + return actionList; + } + + public void setActionList(Set actionList) { + this.actionList = actionList; + } + + public List getActionListOrdered() { + Set actionList = getActionList(); + List actionListOrdered = new ArrayList(); + actionListOrdered.addAll(actionList); + Collections.sort(actionListOrdered, new ActionComparator()); + return actionListOrdered; + } + + public String getTemplate() { + return template; + } + + public void setTemplate(String template) { + this.template = template; + } + + public void addAction(Action action) { + getActionList().add(action); + //action.getPageList().add(this); + } + + public void update(Page page) { + setIntroduction(page.getIntroduction()); + setName(page.getName()); + setTemplate(page.getTemplate()); + } + + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append("{\"id\":" + getId() + ","); + stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); + stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\","); + stringBuilder.append("\"actionList\":"); + + stringBuilder.append("["); + Iterator iterator = getActionListOrdered().iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + stringBuilder.append("]}"); + + return stringBuilder.toString(); + } + + public String toString(Project.TO_STRING_TYPE type) { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append("{\"id\":" + getId() + ","); + stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); + stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\""); + if (type == Project.TO_STRING_TYPE.TO_PAGE) { + stringBuilder.append("}"); + } else { + stringBuilder.append(",\"actionList\":"); + stringBuilder.append("["); + Iterator iterator = getActionListOrdered().iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + stringBuilder.append("]}"); + } + return stringBuilder.toString(); + } +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/PageComparator.java b/src/main/java/com/taobao/rigel/rap/project/bo/PageComparator.java new file mode 100644 index 000000000..9c1f63a6e --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/PageComparator.java @@ -0,0 +1,11 @@ +package com.taobao.rigel.rap.project.bo; + +import java.util.Comparator; + +public class PageComparator implements Comparator { + + public int compare(Page o1, Page o2) { + return o1.getId() < o2.getId() ? 0 : 1; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/Parameter.java b/src/main/java/com/taobao/rigel/rap/project/bo/Parameter.java new file mode 100644 index 000000000..44feec02d --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/Parameter.java @@ -0,0 +1,255 @@ +package com.taobao.rigel.rap.project.bo; + +import com.taobao.rigel.rap.common.utils.StringUtils; + +import java.util.*; + +public class Parameter implements java.io.Serializable { + + private int id; + private String mockData; + private String name; + private String identifier; + private String identifierChange; + private String remarkChange; + private String dataType; + private String remark; + private Set actionRequestList = new HashSet(); + private Set actionResponseList = new HashSet(); + private String validator = ""; + private Set parameterList = new HashSet(); + private Set complexParamerterList = new HashSet(); + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getMockData() { + return mockData; + } + + public void setMockData(String mockData) { + this.mockData = mockData; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = (name == null ? "" : name); + } + + public String getIdentifier() { + if (identifierChange != null) { + return identifierChange; + } else { + return identifier; + } + } + + public void setIdentifier(String identifier) { + this.identifier = (identifier == null ? "" : identifier); + } + + public String getIdentifierChange() { + + return identifierChange; + } + + public void setIdentifierChange(String identifierChange) { + this.identifierChange = identifierChange; + } + + public String getRemarkChange() { + return remarkChange; + } + + public void setRemarkChange(String remarkChange) { + this.remarkChange = remarkChange; + } + + public String getMockIdentifier() { + String rv = ""; + if (identifier == null || identifier.isEmpty()) { + return "\"emptyIdentifier\""; + } + + rv = identifier; + if (rv != null && !rv.isEmpty()) { + int index = rv.indexOf("|"); + if (index > -1) { + rv = rv.substring(0, index); + } + } + return "\"" + rv + "\""; + } + + public String getIdentifierWithoutMockjsRule() { + String rv; + if (identifier == null || identifier.isEmpty()) { + return "emptyIdentifier"; + } + + rv = identifier; + if (rv != null && !rv.isEmpty()) { + int index = rv.indexOf("|"); + if (index > -1) { + rv = rv.substring(0, index); + } + } + return rv; + } + + public String getMockJSIdentifier() { + String rv = ""; + if (identifier == null || identifier.isEmpty()) { + return "\"emptyIdentifier\""; + } + rv = identifier; + return "\"" + rv + "\""; + } + + public String getDataType() { + if (this.dataType == null || this.dataType.trim().isEmpty()) { + return ""; + } + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = (dataType == null ? "" : dataType); + } + + public String getRemark() { + if (remarkChange != null) { + return remarkChange; + } + return (remark == null ? "" : remark); + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public Set getActionRequestList() { + return actionRequestList; + } + + public void setActionRequestList(Set actionRequestList) { + this.actionRequestList = actionRequestList; + } + + public Set getActionResponseList() { + return actionResponseList; + } + + public void setActionResponseList(Set actionResponseList) { + this.actionResponseList = actionResponseList; + } + + public String getValidator() { + return validator; + } + + public void setValidator(String validator) { + this.validator = validator; + } + + public Set getParameterList() { + return parameterList; + } + + public void setParameterList(Set parameterList) { + this.parameterList = parameterList; + } + + public void update(Parameter parameter) { + setDataType(parameter.getDataType()); + setIdentifier(parameter.getIdentifier()); + setName(parameter.getName()); + setRemark(parameter.getRemark()); + setValidator(parameter.getValidator()); + } + + public List getParameterListOrdered() { + Set parameterList = getParameterList(); + List parameterListOrdered = new ArrayList(); + parameterListOrdered.addAll(parameterList); + Collections.sort(parameterListOrdered, new ParameterComparator()); + return parameterListOrdered; + } + + public Set getComplexParameterList() { + return complexParamerterList; + } + + public void setComplexParameterList(Set complexParameterList) { + this.complexParamerterList = complexParameterList; + } + + public void addChild(Parameter parameter) { + getParameterList().add(parameter); + parameter.getComplexParameterList().add(this); + } + + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\"id\":" + getId() + ","); + stringBuilder.append("\"identifier\":\"" + + StringUtils.escapeInJ(getIdentifier()) + "\","); + stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + + "\","); + stringBuilder.append("\"remark\":\"" + + StringUtils.escapeInJ(getRemark()) + "\","); + stringBuilder.append("\"parameterList\":"); + stringBuilder.append("["); + Iterator iterator = getParameterListOrdered().iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + stringBuilder.append("],"); + stringBuilder.append("\"validator\":\"" + + StringUtils.escapeInJ(getValidator()) + "\","); + stringBuilder.append("\"dataType\":\"" + + StringUtils.escapeInJ(getDataType()) + "\"}"); + return stringBuilder.toString(); + } + + public String getRemarkWithoutMockjsRule() { + if (remark != null && remark.contains("@mock=")) { + return remark.substring(0, remark.indexOf("@mock=")); + } else { + return remark; + } + } + + public String getMockJsRules() { + if (remark == null || remark.isEmpty() || (!remark.contains("@mock="))) { + return null; + } + return remark.substring(remark.indexOf("@mock=") + 6); + + } + + + public String getJSONSchemaDataType() { + if (dataType != null && dataType.contains("array")) { + return "array"; + } + return this.dataType; + } + + public boolean hasMockJSData() { + return this.getMockJsRules() != null; + } + + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/ParameterComparator.java b/src/main/java/com/taobao/rigel/rap/project/bo/ParameterComparator.java new file mode 100644 index 000000000..9bfc26752 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/ParameterComparator.java @@ -0,0 +1,11 @@ +package com.taobao.rigel.rap.project.bo; + +import java.util.Comparator; + +public class ParameterComparator implements Comparator { + + public int compare(Parameter o1, Parameter o2) { + return o1.getId() < o2.getId() ? 0 : 1; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/Project.java b/src/main/java/com/taobao/rigel/rap/project/bo/Project.java new file mode 100644 index 000000000..5fce40bb7 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/Project.java @@ -0,0 +1,554 @@ +package com.taobao.rigel.rap.project.bo; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.utils.ArrayUtils; +import com.taobao.rigel.rap.common.utils.DateUtils; +import com.taobao.rigel.rap.common.utils.StringUtils; +import com.taobao.rigel.rap.workspace.bo.CheckIn; +import com.taobao.rigel.rap.workspace.bo.Workspace; +import com.taobao.rigel.rap.workspace.bo.Workspace.ModeType; +import org.hibernate.Session; +import org.ocpsoft.prettytime.PrettyTime; + +import java.text.ParseException; +import java.util.*; + +public class Project implements java.io.Serializable { + + public static final int PRIVATE_ACCESS = 0; + public static final int DEFAULT_ACCESS = 10; + private int id; + private int userId; + private String name; + private Date createDate; + private Date updateTime; + private String introduction; + private User user; + private int workspaceModeInt; + private String relatedIds = ""; + private int groupId; + private int mockNum; + private int teamId; + private short accessType; + private Set userList = new HashSet(); + private Set moduleList = new HashSet(); + private String projectData; + private List memberAccountList; + private Set workspaceList = new HashSet(); + private String version; + private Set checkInList = new HashSet(); + + public boolean isDeletable() { + return isDeletable; + } + + public void setIsDeletable(boolean isDeletable) { + this.isDeletable = isDeletable; + } + + private boolean isDeletable; + + public void setIsManagable(boolean isManagable) { + this.isManagable = isManagable; + } + + private boolean isManagable; + + public boolean isManagable() { + return isManagable; + } + + public Project() { + + } + + public int getTeamId() { + return teamId; + } + + public void setTeamId(int teamId) { + this.teamId = teamId; + } + + public short getAccessType() { + return accessType; + } + + + public void setAccessType(short accessType) { + this.accessType = accessType; + } + + public int getMockNum() { + return mockNum; + } + + public void setMockNum(int mockNum) { + this.mockNum = mockNum; + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getRelatedIds() { + return relatedIds; + } + + public void setRelatedIds(String relatedIds) { + String[] ids = relatedIds.split(","); + List idsArr = new ArrayList(); + for (String id : ids) { + try { + int integerId = Integer.parseInt(id); + idsArr.add(integerId); + } catch(Exception ex) { + + } + } + this.relatedIds = ArrayUtils.join(idsArr, ","); + } + + public int getWorkspaceModeInt() { + return workspaceModeInt; + } + + public void setWorkspaceModeInt(int workspaceModeInt) { + this.workspaceModeInt = workspaceModeInt; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public ModeType getWorkspaceMode() { + if (workspaceModeInt == 1) { + return ModeType.VSS; + } else if (workspaceModeInt == 2) { + return ModeType.SVN; + } else { + return ModeType.VSS; + } + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public Set getUserList() { + return userList; + } + + public void setUserList(Set userList) { + this.userList = userList; + } + + public Set getModuleList() { + return moduleList; + } + + public void setModuleList(Set moduleList) { + this.moduleList = moduleList; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public String getIntroduction() { + return introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = (introduction == null ? "" : introduction); + } + + public String getProjectData() { + return projectData; + } + + public void setProjectData(String projectData) { + this.projectData = projectData; + } + + public List getModuleListOrdered() { + Set moduleList = getModuleList(); + List moduleListOrdered = new ArrayList(); + moduleListOrdered.addAll(moduleList); + Collections.sort(moduleListOrdered, new ModuleComparator()); + return moduleListOrdered; + } + + public void addModule(Module module) { + getModuleList().add(module); + module.setProject(this); + } + + public String getMemberAccountListStr() { + StringBuilder stringBuilder = new StringBuilder(); + for (User user : getUserList()) { + stringBuilder.append(user.getAccount() + "(" + user.getName() + "), "); + } + return stringBuilder.toString(); + } + + public List getMemberAccountList() { + return memberAccountList; + } + + public void setMemberAccountList(List memberAccountList) { + this.memberAccountList = memberAccountList; + } + + public Set getWorkspaceList() { + return workspaceList; + } + + public void setWorkspaceList(Set workspaceList) { + this.workspaceList = workspaceList; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String toString(TO_STRING_TYPE type) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\"createDateStr\":\"" + getCreateDateStr() + "\","); + stringBuilder.append("\"user\":" + getUser() + ","); + stringBuilder.append("\"id\":" + getId() + ","); + stringBuilder.append("\"version\":\"" + getVersion() + "\","); + stringBuilder.append("\"introduction\":\"" + StringUtils.escapeInJ(getIntroduction()) + "\","); + stringBuilder.append("\"name\":\"" + StringUtils.escapeInJ(getName()) + "\","); + stringBuilder.append("\"moduleList\":"); + + stringBuilder.append("["); + Iterator iterator = getModuleListOrdered().iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next().toString(type)); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + stringBuilder.append("]}"); + return stringBuilder.toString(); + } + + public String toString() { + return "{}"; + } + + public void update(Project project) { + setIntroduction(project.getIntroduction()); + setName(project.getName()); + } + public String getCreateDateStr() { + return getCreateDate() == null ? "" : DateUtils.DATE_FORMAT.format(getCreateDate()); + } + + public void setCreateDateStr(String createDateStr) throws ParseException { + setCreateDate((createDateStr == null || createDateStr.equals("")) ? + null : DateUtils.DATE_FORMAT.parse(createDateStr)); + } + + public String getUserListStr() { + StringBuilder stringBuilder = new StringBuilder(); + Iterator iterator = getUserList().iterator(); + while (iterator.hasNext()) { + User user = iterator.next(); + // remove the creator + if (user.getId() == getUser().getId()) continue; + stringBuilder.append(user.getName() + "(" + user.getWorkRole() + ")"); + if (iterator.hasNext()) { + stringBuilder.append(", "); + } + } + return stringBuilder.toString(); + } + + public String getUserListStrShort() { + StringBuilder stringBuilder = new StringBuilder(); + Iterator iterator = getUserList().iterator(); + int count = 1; + while (iterator.hasNext()) { + User user = iterator.next(); + // remove the creator + if (user.getId() == getUser().getId()) continue; + stringBuilder.append(user.getName() + "(" + user.getWorkRole() + ")"); + if (iterator.hasNext()) { + stringBuilder.append(", "); + } + if (++count > 5) { + stringBuilder.append(iterator.hasNext() ? "etc." : ""); + break; + } + } + return stringBuilder.toString(); + } + + public Set getCheckInList() { + return checkInList; + } + + public void setCheckInList(Set checkInList) { + this.checkInList = checkInList; + } + + public List getCheckInListOrdered() { + Set checkInList = getCheckInList(); + List checkInListOrdered = new ArrayList(); + checkInListOrdered.addAll(checkInList); + Collections.sort(checkInListOrdered, new CheckInComparator()); + return checkInListOrdered; + } + + public Module findModule(int moduleId) { + for (Module i : getModuleList()) { + if (i.getId() == moduleId) + return i; + } + return null; + } + + public Page findPage(int pageId) { + for (Module module : getModuleList()) { + for (Page page : module.getPageList()) { + if (page.getId() == pageId) + return page; + } + } + return null; + } + + public Action findAction(int actionId) { + for (Module module : getModuleList()) { + for (Page page : module.getPageList()) { + for (Action action : page.getActionList()) { + if (action.getId() == actionId) + return action; + } + } + } + return null; + } + + public Parameter findParameter(int parameterId, boolean isRequestType) { + for (Module module : getModuleList()) { + for (Page page : module.getPageList()) { + for (Action action : page.getActionList()) { + for (Parameter parameter : (isRequestType ? + action.getRequestParameterList() : action.getResponseParameterList())) { + if (parameter.getId() == parameterId) { + return parameter; + } + } + } + } + } + return null; + } + + public Parameter findChildParameter(int parameterId) { + for (Module module : getModuleList()) { + for (Page page : module.getPageList()) { + for (Action action : page.getActionList()) { + for (Parameter parameter : action.getRequestParameterList()) { + Parameter pRecur = findParameterRecursively(parameter, parameterId); + if (pRecur != null) { + return pRecur; + } + } + + for (Parameter parameter : action.getResponseParameterList()) { + Parameter pRecur = findParameterRecursively(parameter, parameterId); + if (pRecur != null) { + return pRecur; + } + } + } + } + } + return null; + } + + /** + * find parameter recursively + * recursive: + * p.parameterList[0].parameterList[0]..... + * + * @param p + * @param id + * @return return the object found, other wise return null + */ + private Parameter findParameterRecursively(Parameter p, int id) { + Iterator iterator = p.getParameterList().iterator(); + while (iterator.hasNext()) { + Parameter parameter = iterator.next(); + if (parameter.getId() == id) { + return parameter; + } + parameter = findParameterRecursively(parameter, id); + if (parameter != null) { + return parameter; + } + } + return null; + } + + public void removeModule(int id, Session session) { + Module module = findModule(id); + if (module != null && moduleList != null) { + moduleList.remove(module); + session.delete(module); + } + } + + public void removePage(int id, Session session) { + Page page = findPage(id); + if (page != null && page.getModule() != null && page.getModule().getPageList() != null) { + page.getModule().getPageList().remove(page); + session.delete(page); + } + } + + public void removeAction(int id, Session session) { + Action action = findAction(id); + if (action == null) return; + Set pageList = action.getPageList(); + if (pageList == null) return; + Iterator iterator = pageList.iterator(); + while (iterator.hasNext()) { + iterator.next().getActionList().remove(action); + session.delete(action); + } + } + + public void removeParameter(int id, Session session) { + Parameter parameter = findParameter(id, true); + + // if parameter == null, it maybe response parameter + if (parameter == null) { + parameter = findParameter(id, false); + + // if parameter == null still, it must be child parameter of a complex parameter + if (parameter == null) { + parameter = findChildParameter(id); + if (parameter != null && parameter.getComplexParameterList() != null) { + for (Parameter pComplex : parameter.getComplexParameterList()) { + pComplex.getParameterList().remove(parameter); + session.delete(parameter); + } + } + return; + } + Iterator iterator = parameter.getActionResponseList().iterator(); + while (iterator.hasNext()) { + iterator.next().getResponseParameterList().remove(parameter); + session.delete(parameter); + } + } else { + Iterator iterator = parameter.getActionRequestList().iterator(); + while (iterator.hasNext()) { + iterator.next().getRequestParameterList().remove(parameter); + session.delete(parameter); + } + } + } + + public boolean addMember(User user) { + // if member added is the creator, ignore + if (user.getId() == getUser().getId()) + return false; + // if member already exists, ignore + boolean exist = false; + for (User item : getUserList()) { + if (item.getId() == user.getId()) { + exist = true; + } + } + if (exist) return false; + // validation complete, add this user + getUserList().add(user); + user.getJoinedProjectList().add(this); + return true; + } + + public void removeMember(User user) { + getUserList().remove(user); + user.getJoinedProjectList().remove(this); + } + + public String getLastUpdateStr() { + PrettyTime p = new PrettyTime(new Locale("zh")); + return p.format(this.updateTime) + "更新"; + } + + public List getAllAction() { + List list = new ArrayList(); + for (Module m : this.moduleList) { + for (Page p : m.getPageList()) { + for (Action a : p.getActionList()) { + list.add(a); + } + } + } + return list; + } + + public boolean isUserMember(int userId) { + if (getUserId() == userId) return true; + for (User u : getUserList()) { + if (u.getId() == userId) return true; + } + return false; + } + + + public enum TO_STRING_TYPE {TO_MODULE, TO_PAGE, TO_ACTION, TO_PARAMETER} + + public enum STAGE_TYPE {DESIGNING, DEVELOPING, DEBUGING} +} diff --git a/src/main/java/com/taobao/rigel/rap/project/bo/Validator.java b/src/main/java/com/taobao/rigel/rap/project/bo/Validator.java new file mode 100644 index 000000000..c20ff4453 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/bo/Validator.java @@ -0,0 +1,32 @@ +package com.taobao.rigel.rap.project.bo; + +public class Validator implements java.io.Serializable { + + private int id; + private int type; + private String rule; + + public int getId() { + return this.id; + } + + public void setId(int id) { + this.id = id; + } + + public int getType() { + return this.type; + } + + public void setType(int type) { + this.type = type; + } + + public String getRule() { + return this.rule; + } + + public void setRule(String rule) { + this.rule = rule; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/project/dao/ProjectDao.java b/src/main/java/com/taobao/rigel/rap/project/dao/ProjectDao.java new file mode 100644 index 000000000..77ed624d9 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/dao/ProjectDao.java @@ -0,0 +1,186 @@ +package com.taobao.rigel.rap.project.dao; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.project.bo.Action; +import com.taobao.rigel.rap.project.bo.Module; +import com.taobao.rigel.rap.project.bo.Page; +import com.taobao.rigel.rap.project.bo.Project; + +import java.util.List; +import java.util.Map; + +public interface ProjectDao { + + /** + * get project list + * + * @param user + * @param curPageNum + * @param pageSize + * @return + */ + List getProjectList(User user, int curPageNum, int pageSize); + + /** + * get new project + * + * @param project + * @return always 0 + */ + int addProject(Project project); + + /** + * update project + * + * @param id + * @param projectData + * @param deletedObjectListData + * @return + */ + String updateProject(int id, String projectData, + String deletedObjectListData, Map actionIdMap); + + /** + * update project + * + * @param project + * @return + */ + int updateProject(Project project); + + /** + * remove project + * + * @param id + * @return + */ + int removeProject(int id); + + /** + * get project + * + * @param id + * @return + */ + Project getProjectSummary(int id); + + /** + * get module + * + * @param id + * @return + */ + Module getModule(int id); + + /** + * get page + * + * @param id + * @return + */ + Object getPage(int id); + + + /** + * get action + * + * @param id + * @return + */ + Action getAction(int id); + + /** + * save project + * + * @param project + * @return + */ + int saveProject(Project project); + + /** + * get project list number + * + * @param user + * @return + */ + int getProjectListNum(User user); + + /** + * get matched action list based on URL pattern + * + * @param projectId + * @param pattern + * @return + */ + List getMatchedActionList(int projectId, String pattern); + + /** + * clear all mock data of objects in specified project + * + * @param projectId project id + * @return affected rows num + */ + public int resetMockData(int projectId); + + /** + * get project list by group + * + * @param id + * @return + */ + List getProjectListByGroup(int id); + + /** + * search all projects (for admin use) + * + * @param key + * @return + */ + List search(String key); + + List getProjectList(); + + int getProjectListNum(); + + int getModuleNum(); + + int getPageNum(); + + int getActionNum(); + + int getParametertNum(); + + int getCheckInNum(); + + int getMockNumInTotal(); + + List selectMockNumTopNProjectList(int limit); + + /** + * get project id by action id + * + * @param actionId + * @return + */ + Integer getProjectIdByActionId(int actionId); + + void updateProjectNum(Project project); + + + /** + * transfer a project to another user + * @param projectId + * @param creatorId + */ + void updateCreatorId(int projectId, int creatorId); + + Project getProject(int id); + + /** + * get member id list of specified project + * + * @param projectId + * @return + */ + List getMemberIdsOfProject(int projectId); +} diff --git a/src/main/java/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java b/src/main/java/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java new file mode 100644 index 000000000..1cc9f8bfc --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/dao/impl/ProjectDaoImpl.java @@ -0,0 +1,582 @@ +package com.taobao.rigel.rap.project.dao.impl; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.utils.ArrayUtils; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.common.utils.StringUtils; +import com.taobao.rigel.rap.common.utils.URLUtils; +import com.taobao.rigel.rap.project.bo.*; +import com.taobao.rigel.rap.project.dao.ProjectDao; +import org.hibernate.*; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; +import org.hibernate.transform.Transformers; +import org.springframework.orm.hibernate5.support.HibernateDaoSupport; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class ProjectDaoImpl extends HibernateDaoSupport implements ProjectDao { + + public List getProjectList(User user, int curPageNum, int pageSize) { + StringBuilder sql = new StringBuilder(); + sql + .append("SELECT project_id ") + .append("FROM tb_project_and_user ") + .append("WHERE user_id = :userId ") + .append("UNION ") + .append("SELECT id ") + .append("FROM tb_project ") + .append("WHERE user_id = :userId "); + Query query = currentSession().createSQLQuery(sql.toString()).setInteger("userId", + user.getId()); + + List list = query.list(); + List resultList = new ArrayList(); + for (Integer id : list) { + Project p = getProjectSummary(id); + if (p != null && p.getId() > 0) { + resultList.add(p); + } + } + return resultList; + } + + public List getProjectList() { + String hqlByUser = "from Project"; + Query query = currentSession().createQuery(hqlByUser); + return query.list(); + } + + + public int addProject(Project project) { + Session session = currentSession(); + project.getUser().addCreatedProject(project); + project.setVersion("0.0.0.1"); // default version + int modeInt = project.getWorkspaceModeInt(); + if (modeInt <= 0 || modeInt >= 3) { + project.setWorkspaceModeInt(1); + } + session.save(project); + project = session.load(Project.class, project.getId()); + project.setProjectData(project + .toString(Project.TO_STRING_TYPE.TO_PARAMETER)); + return project.getId(); + } + + + public int removeProject(int id) { + Session session = currentSession(); + Object project = session.get(Project.class, id); + if (project != null) { + session.delete(project); + session.flush(); + return 0; + } else { + return -1; + } + + } + + + public int updateProject(Project project) { + Session session = currentSession(); + session.update(project); + return 0; + } + + + public Project getProjectSummary(int id) { + + Project project = (Project) currentSession().createCriteria(Project.class) + .setProjection(Projections.projectionList() + .add(Projections.property("id"), "id") + .add(Projections.property("name"), "name") + .add(Projections.property("userId"), "userId") + .add(Projections.property("updateTime"), "updateTime") + .add(Projections.property("introduction"), "introduction") + .add(Projections.property("createDate"), "createDate") + .add(Projections.property("version"), "version") + .add(Projections.property("groupId"), "groupId") + .add(Projections.property("relatedIds"), "relatedIds") + .add(Projections.property("accessType"), "accessType") + ) + .add(Restrictions.eq("id", id)) + .setResultTransformer(Transformers.aliasToBean(Project.class)) + .uniqueResult(); + + return project; + + + // return (Project) currentSession().createQuery("from Project where id = :id").setint("id", id).uniqueResult(); + } + + + public Module getModule(int id) { + Module m = null; + try { + Session session = currentSession(); + m = (Module) session.get(Module.class, id); + } catch (ObjectNotFoundException ex) { + ex.printStackTrace(); + } catch (Exception ex) { + ex.printStackTrace(); + } + return m; + } + + + public Page getPage(int id) { + return (Page) currentSession().get(Page.class, id); + } + + + public Action getAction(int id) { + return (Action) currentSession().get(Action.class, id); + } + + private Parameter getParameter(int id) { + return (Parameter) currentSession().get(Parameter.class, id); + } + + + public int saveProject(Project project) { + Session session = currentSession(); + session.saveOrUpdate(project); + return 0; + } + + + public String updateProject(int id, String projectData, + String deletedObjectListData, Map actionIdMap) { + Session session = currentSession(); + + Gson gson = new Gson(); + + Project projectClient = gson.fromJson(projectData, Project.class); + + ObjectItem[] deletedObjectList = gson.fromJson(deletedObjectListData, + ObjectItem[].class); + + Project projectServer = session.load(Project.class, id); + projectServer.setUpdateTime(new Date()); + + // performing deleting + for (ObjectItem item : deletedObjectList) { + if (item.getClassName().equals("Module")) { + projectServer.removeModule(item.getId(), session); + } else if (item.getClassName().equals("Page")) { + projectServer.removePage(item.getId(), session); + } else if (item.getClassName().equals("Action")) { + projectServer.removeAction(item.getId(), session); + } else if (item.getClassName().equals("Parameter")) { + projectServer.removeParameter(item.getId(), session); + } + } + + // performing adding & updating + for (Module module : projectClient.getModuleList()) { + Module moduleServer = projectServer.findModule(module.getId()); + if (moduleServer == null) { + addModule(session, projectServer, module); + continue; + } + moduleServer.update(module); + for (Page page : module.getPageList()) { + Page pageServer = projectServer.findPage(page.getId()); + if (pageServer == null) { + addPage(session, module, page); + continue; + } + pageServer.update(page); + for (Action action : page.getActionList()) { + Action actionServer = projectServer.findAction(action + .getId()); + if (actionServer == null) { + int oldActionId = action.getId(); + int createdActionId = addAction(session, page, action); + actionIdMap.put(oldActionId, createdActionId); + continue; + } + actionServer.update(action); + CacheUtils.removeCacheByActionId(action.getId()); + for (Parameter parameter : action.getRequestParameterList()) { + Parameter parameterServer = projectServer + .findParameter(parameter.getId(), true); + if (parameterServer == null) { + addParameter(session, action, parameter, true); + continue; + } + parameterServer.update(parameter); + for (Parameter childParameter : parameter + .getParameterList()) { + processParameterRecursively(session, projectServer, + parameter, childParameter); + } + } + + for (Parameter parameter : action + .getResponseParameterList()) { + Parameter parameterServer = projectServer + .findParameter(parameter.getId(), false); + if (parameterServer == null) { + addParameter(session, action, parameter, false); + continue; + } + parameterServer.update(parameter); + for (Parameter childParameter : parameter + .getParameterList()) { + processParameterRecursively(session, projectServer, + parameter, childParameter); + } + } + } + } + } + return ""; + } + + private void processParameterRecursively(Session session, + Project projectServer, Parameter parameter, Parameter childParameter) { + Parameter childParameterServer = projectServer + .findChildParameter(childParameter.getId()); + if (childParameterServer == null) { + addParameterRecursively(session, parameter, childParameter); + } else { + childParameterServer.update(childParameter); + } + for (Parameter childOfChildParameter : childParameter + .getParameterList()) { + processParameterRecursively(session, projectServer, childParameter, + childOfChildParameter); + } + } + + private void addModule(Session session, Project project, Module module) { + project.addModule(module); + session.save(module); + for (Page page : module.getPageList()) { + addPage(session, module, page); + } + } + + private void addPage(Session session, Module module, Page page) { + module = (Module) session.load(Module.class, module.getId()); + module.addPage(page); + session.save(page); + for (Action action : page.getActionList()) { + addAction(session, page, action); + } + } + + private int addAction(Session session, Page page, Action action) { + page = session.load(Page.class, page.getId()); + page.addAction(action); + int createdId = (Integer) session.save(action); + for (Parameter parameter : action.getRequestParameterList()) { + addParameter(session, action, parameter, true); + } + for (Parameter parameter : action.getResponseParameterList()) { + addParameter(session, action, parameter, false); + } + return createdId; + } + + private void addParameter(Session session, Action action, + Parameter parameter, boolean isRequest) { + action = session.load(Action.class, action.getId()); + action.addParameter(parameter, isRequest); + session.save(parameter); + for (Parameter childParameter : parameter.getParameterList()) { + addParameterRecursively(session, parameter, childParameter); + } + } + + /** + * add parameter recursively + * + * @param session session object + * @param parameter parent parameter + * @param childParameter child parameter + */ + private void addParameterRecursively(Session session, Parameter parameter, + Parameter childParameter) { + parameter = session + .load(Parameter.class, parameter.getId()); + parameter.addChild(childParameter); + session.save(childParameter); + for (Parameter childOfChildParameter : childParameter + .getParameterList()) { + addParameterRecursively(session, childParameter, + childOfChildParameter); + } + } + + @SuppressWarnings("unchecked") + + public int getProjectListNum(User user) { + String hql = "select count(p) from Project as p order by p.id desc"; + String hqlByUser = "select count(p) from Project as p left join p.userList as u where p.user.id = :userId or u.id = :userId order by p.id desc"; + Query query = user == null ? currentSession().createQuery(hql) + : currentSession().createQuery(hqlByUser).setInteger("userId", + user.getId()); + List list = query.list(); + return list.get(0); + } + + + public int getProjectListNum() { + String sql = "SELECT COUNT(*) FROM tb_project"; + Query query = currentSession().createSQLQuery(sql); + return Integer.parseInt(query.uniqueResult().toString()); + } + + + public int getModuleNum() { + String sql = "SELECT COUNT(*) FROM tb_module"; + Query query = currentSession().createSQLQuery(sql); + return Integer.parseInt(query.uniqueResult().toString()); + } + + + public int getPageNum() { + String sql = "SELECT COUNT(*) FROM tb_page"; + Query query = currentSession().createSQLQuery(sql); + return Integer.parseInt(query.uniqueResult().toString()); + } + + + public int getActionNum() { + String sql = "SELECT COUNT(*) FROM tb_action"; + Query query = currentSession().createSQLQuery(sql); + return Integer.parseInt(query.uniqueResult().toString()); + } + + + public int getMockNumInTotal() { + String sql = "SELECT SUM(mock_num) FROM tb_project"; + Query query = currentSession().createSQLQuery(sql); + Object queryResult = query.uniqueResult(); + return queryResult != null ? Integer.parseInt(queryResult.toString()) : 0; + } + + + public int getParametertNum() { + String sql = "SELECT COUNT(*) FROM tb_parameter"; + Query query = currentSession().createSQLQuery(sql); + return Integer.parseInt(query.uniqueResult().toString()); + } + + + public int getCheckInNum() { + String sql = "SELECT COUNT(*) FROM tb_check_in"; + Query query = currentSession().createSQLQuery(sql); + return Integer.parseInt(query.uniqueResult().toString()); + } + + + public List getMatchedActionList(int projectId, String pattern) { + List list = getActionListOfProject(projectId); + List result = new ArrayList(); + for (Action action : list) { + String url = action.getRequestUrl(); + url = URLUtils.getRelativeUrl(url); + if (url.startsWith("reg:")) { // regular pattern + if (StringUtils.regMatch(url.substring(4), pattern)) { + result.add(action); + } + } else if (url.contains(":")) { + String urlParamRemoved = URLUtils.removeParamsInUrl(url); + String realUrlParamRemoved = URLUtils + .removeRealParamsInUrl(pattern); + if (realUrlParamRemoved.equals(urlParamRemoved)) { + result.add(action); + } + } else { // normal pattern + if (url.contains(pattern)) { + result.add(action); + } + } + } + + return result; + + // process /:id/ cases + // boolean urlParalized = false; + // String patternOrignial = pattern; + // if (pattern.contains(":")) { + // urlParalized = true; + // pattern = pattern.substring(0, pattern.indexOf(":")); + // } + + /** + * StringBuilder sb = new StringBuilder(); + * sb.append("SELECT a.id FROM tb_action a ") + * .append("JOIN tb_action_and_page ap ON ap.action_id = a.id ") + * .append("JOIN tb_page p ON p.id = ap.page_id ") + * .append("JOIN tb_module m ON m.id = p.module_id ") .append( + * "WHERE LOCATE(:pattern, a.request_url) != 0 AND m.project_id = :projectId " + * ); + * + * String sql = sb.toString(); Query query = + * currentSession().createSQLQuery(sql); query.setString("pattern", + * pattern); query.setInteger("projectId", projectId); List + * list = query.list(); List actionList = new + * ArrayList(); for (int id : list) { + * actionList.add(getAction(id)); } + */ + + // URL parameters filter + /** + * if (urlParalized) { List filteredActionList = new + * ArrayList(); for (Action a : actionList) { String u = + * a.getRequestUrl(); if (u.contains("?")) { u = u.substring(0, + * u.indexOf("?")); } u = StringUtils.removeParamsInUrl(u); + * patternOrignial = StringUtils .removeParamsInUrl(patternOrignial); if + * (u != null && patternOrignial != null && u.equals(patternOrignial)) { + * filteredActionList.add(a); } } actionList = filteredActionList; } + */ + // return actionList; + } + + private List getParameterIdList(int projectId) { + StringBuilder sql = new StringBuilder(); + sql.append(" SELECT DISTINCT p.id") + .append(" FROM tb_parameter p") + .append(" JOIN tb_response_parameter_list_mapping rplm ON p.id = rplm.parameter_id") + .append(" JOIN tb_action_and_page ap ON ap.action_id = rplm.action_id") + .append(" JOIN tb_page p2 ON p2.id = ap.page_id") + .append(" JOIN tb_module m ON m.id = p2.module_id") + .append(" WHERE m.project_id = :projectId"); + Query query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("projectId", projectId); + List list = query.list(); + + StringBuilder sql2 = new StringBuilder(); + sql2.append(" SELECT DISTINCT p.id") + .append(" FROM tb_parameter p") + .append(" JOIN tb_request_parameter_list_mapping rplm ON p.id = rplm.parameter_id") + .append(" JOIN tb_action_and_page ap ON ap.action_id = rplm.action_id") + .append(" JOIN tb_page p2 ON p2.id = ap.page_id") + .append(" JOIN tb_module m ON m.id = p2.module_id") + .append(" WHERE m.project_id = :projectId"); + Query query2 = currentSession().createSQLQuery(sql2.toString()); + query2.setInteger("projectId", projectId); + list.addAll(query2.list()); + List paramList = new ArrayList(); + for (int pId : list) { + paramList.add(getParameter(pId)); + } + for (Parameter p : paramList) { + recursivelyAddSubParamList(list, p); + } + return list; + } + + private void recursivelyAddSubParamList(List list, Parameter p) { + list.add(p.getId()); + if (p.getParameterList() == null) + return; + for (Parameter subP : p.getParameterList()) { + recursivelyAddSubParamList(list, subP); + } + } + + public int resetMockData(int projectId) { + List pIdList = getParameterIdList(projectId); + String sql = "UPDATE tb_parameter SET mock_data = NULL where id in (" + + ArrayUtils.join(pIdList, ",") + ")"; + Query query = currentSession().createSQLQuery(sql); + return query.executeUpdate(); + } + + @SuppressWarnings("unchecked") + + public List getProjectListByGroup(int id) { + String hql = "from Project where groupId = :id"; + Query query = currentSession().createQuery(hql); + query.setInteger("id", id); + return query.list(); + } + + + public List search(String key) { + String hql = "from Project where name LIKE :key"; + Query query = currentSession().createQuery(hql); + query.setString("key", "%" + key + "%"); + return query.list(); + } + + @SuppressWarnings({"rawtypes"}) + private List getActionListOfProject(int projectId) { + List list = new ArrayList(); + StringBuilder sql = new StringBuilder(); + sql.append("SELECT a.id "); + sql.append("FROM tb_project p "); + sql.append("JOIN tb_module m ON m.project_id = p.id "); + sql.append("JOIN tb_page ON tb_page.module_id = m.id "); + sql.append("JOIN tb_action_and_page anp ON anp.page_id = tb_page.id "); + sql.append("JOIN tb_action a ON a.id = anp.action_id "); + sql.append("WHERE p.id = :projectId "); + Query query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("projectId", projectId); + + List result = query.list(); + List ids = new ArrayList(); + for (Object r : result) { + ids.add((Integer) r); + } + for (Integer id : ids) { + list.add(this.getAction(id)); + } + return list; + } + + + public List selectMockNumTopNProjectList(int limit) { + String hqlByUser = "from Project order by mockNum desc"; + Query query = currentSession().createQuery(hqlByUser); + return query.setMaxResults(limit).list(); + } + + + public Integer getProjectIdByActionId(int actionId) { + StringBuilder sql = new StringBuilder(); + sql.append("SELECT p.id FROM tb_project p "); + sql.append("JOIN tb_module m ON m.project_id = p.id "); + sql.append("JOIN tb_page page ON page.module_id = m.id "); + sql.append("JOIN tb_action_and_page anp ON anp.page_id = page.id "); + sql.append("where action_id = :actionId"); + Query query = currentSession().createSQLQuery(sql.toString()); + query.setInteger("actionId", actionId); + return (Integer) query.uniqueResult(); + } + + + public void updateProjectNum(Project project) { + String sql = "UPDATE tb_project SET mock_num = :mockNum WHERE id = :projectId"; + currentSession().createSQLQuery(sql).setInteger("mockNum", project.getMockNum()).setInteger("projectId", project.getId()).executeUpdate(); + } + + + public void updateCreatorId(int projectId, int creatorId) { + Query query = currentSession().createSQLQuery("UPDATE tb_project SET user_id = :userId WHERE id = :id"); + query.setInteger("userId", creatorId); + query.setInteger("id", projectId); + query.executeUpdate(); + } + + public Project getProject(int id) { + return currentSession().get(Project.class, id); + } + + public List getMemberIdsOfProject(int projectId) { + Query query = currentSession().createSQLQuery("SELECT user_id FROM tb_project_and_user WHERE project_id = :projectId"); + query.setInteger("projectId", projectId); + return query.list(); + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/service/ProjectMgr.java b/src/main/java/com/taobao/rigel/rap/project/service/ProjectMgr.java new file mode 100644 index 000000000..6164643fc --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/service/ProjectMgr.java @@ -0,0 +1,227 @@ +package com.taobao.rigel.rap.project.service; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.project.bo.Action; +import com.taobao.rigel.rap.project.bo.Module; +import com.taobao.rigel.rap.project.bo.Page; +import com.taobao.rigel.rap.project.bo.Project; + +import java.util.List; +import java.util.Map; + +public interface ProjectMgr { + + /** + * get project list + * + * @param user + * @param curPageNum + * @param pageSize + * @return + */ + List getProjectList(User user, int curPageNum, int pageSize); + + /** + * add new project + * + * @param project + * @return + */ + int addProject(Project project); + + /** + * remove project + * + * @param id + * @return + */ + int removeProject(int id); + + /** + * update project + * + * @param project + * @return + */ + int updateProject(Project project); + + /** + * get project by id + * + * @param id + * @return + */ + Project getProjectSummary(int id); + + Project getProject(int id, String ver); + + /** + * with project data + * + * @param id + * @return + */ + Project getProject(int id); + + /** + * get module by id + * + * @param id + * @return + */ + Module getModule(int id); + + /** + * get page by id + * + * @param id + * @return + */ + Page getPage(int id); + + /** + * update project + * + * @param id + * @param projectData + * @param deletedObjectListData + * @return + */ + String updateProject(int id, String projectData, + String deletedObjectListData, Map actionIdMap); + + /** + * get number of project list usually used for pager + * + * @param user + * @return + */ + int getProjectListNum(User user); + + /** + * set action.remarks as paramIdList eg-> action.remarks = "id,name,age"; + * used for parameter identifier spelling validation [*caution*] only + * calculating response parameters + * + * @param action action to be filled with paramIdList info + */ + void loadParamIdListForAction(Action action); + + /** + * load paramIdList for page + * + * @param page + */ + void loadParamIdListForPage(Page page); + + /** + * get matched action list based on URL pattern + * + * @param projectId + * @param pattern + * @return + */ + List getMatchedActionList(int projectId, String pattern); + + /** + * get project list by group id + * + * @param id + * @return + */ + List getProjectListByGroup(int id); + + /** + * search all projects (for admin) + * + * @param key + * @return + */ + List search(String key); + + /** + * search project by user + * + * @param key + * @param curUserId + * @return + */ + List search(String key, int curUserId); + + /** + * get action + * + * @param id + * @return + */ + Action getAction(int id); + + Action getAction(int id, String ver, int projectId); + + /** + * update doc + * + * @param projectId + */ + void updateDoc(int projectId); + + List getProjectList(); + + int getProjectNum(); + + int getModuleNum(); + + int getPageNum(); + + int getActionNum(); + + int getParametertNum(); + + int getCheckInNum(); + + int getMockNumInTotal(); + + List selectMockNumTopNProjectList(int limit); + + /** + * update Action.disableCache + * + * @param projectId + */ + void updateCache(int projectId); + + /** + * get project id by action id + * + * @param actionId + * @return + */ + Integer getProjectIdByActionId(int actionId); + + void updateProjectNum(Project project); + + /** + * clear project model cache(without project data) by projectId + * influence projects list + * + * @param projectId + */ + void clearProjectInfoCache(int projectId); + + /** + * clear project data cache + * influence workspace + * + * @param projectId + */ + void clearProjectDocCache(int projectId); + + /** + * get member user id list of specifid project + * + * @param projectId + * @return + */ + List getMemberIdsOfProject(int projectId); + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java b/src/main/java/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java new file mode 100644 index 000000000..b878279fa --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/service/impl/ProjectMgrImpl.java @@ -0,0 +1,472 @@ +package com.taobao.rigel.rap.project.service.impl; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.account.bo.Notification; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.account.dao.AccountDao; +import com.taobao.rigel.rap.account.service.AccountMgr; +import com.taobao.rigel.rap.common.utils.ArrayUtils; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.common.utils.HTTPUtils; +import com.taobao.rigel.rap.common.config.SystemConstant; +import com.taobao.rigel.rap.organization.bo.Group; +import com.taobao.rigel.rap.organization.dao.OrganizationDao; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.*; +import com.taobao.rigel.rap.project.dao.ProjectDao; +import com.taobao.rigel.rap.project.service.ProjectMgr; +import com.taobao.rigel.rap.workspace.bo.CheckIn; +import com.taobao.rigel.rap.workspace.dao.WorkspaceDao; +import sun.misc.Cache; + +import javax.management.Query; +import java.util.*; + +public class ProjectMgrImpl implements ProjectMgr { + + private ProjectDao projectDao; + private OrganizationDao organizationDao; + private AccountMgr accountMgr; + private WorkspaceDao workspaceDao; + private OrganizationMgr organizationMgr; + private AccountDao accountDao; + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public void setWorkspaceDao(WorkspaceDao workspaceDao) { + this.workspaceDao = workspaceDao; + } + + public AccountMgr getAccountMgr() { + return accountMgr; + } + + public void setAccountMgr(AccountMgr accountMgr) { + this.accountMgr = accountMgr; + } + + public OrganizationDao getOrganizationDao() { + return organizationDao; + } + + public void setOrganizationDao(OrganizationDao organizationDao) { + this.organizationDao = organizationDao; + } + + public ProjectDao getProjectDao() { + return this.projectDao; + } + + public void setProjectDao(ProjectDao projectDao) { + this.projectDao = projectDao; + } + + public AccountDao getAccountDao() { + return accountDao; + } + + public void setAccountDao(AccountDao accountDao) { + this.accountDao = accountDao; + } + + public List getProjectList(User user, int curPageNum, int pageSize) { + + List projectList = projectDao.getProjectList(user, curPageNum, + pageSize); + for (Project p : projectList) { + p.setIsManagable(organizationMgr.canUserManageProject(user.getId(), p.getId())); + p.setIsDeletable(organizationMgr.canUserDeleteProject(user.getId(), p.getId())); + p.setTeamId(organizationDao.getTeamIdByProjectId(p.getId())); + p.setUser(accountDao.getUser(p.getUserId())); + + List memberIdList = getMemberIdsOfProject(p.getId()); + Set memberList = new HashSet(); + for (int memberId : memberIdList) { + memberList.add(accountMgr.getUser(memberId)); + } + p.setUserList(memberList); + } + return projectList; + } + + public int addProject(Project project) { + project.setUpdateTime(new Date()); + project.setCreateDate(new Date()); + List usersInformed = new ArrayList(); + + for (String account : project.getMemberAccountList()) { + User user = accountDao.getUser(account); + if (user != null) { + boolean addSuccess = project.addMember(user); + if (addSuccess) { + usersInformed.add(user); + } + } + } + + int result = projectDao.addProject(project); + for (User u : usersInformed) { + Notification o = new Notification(); + o.setTypeId((short) 2); + o.setTargetUser(project.getUser()); + o.setUser(u); + o.setParam1(new Integer(result).toString()); + o.setParam2(project.getName()); + accountMgr.addNotification(o); + } + + Group g = organizationDao.getGroup(project.getGroupId()); + if (g.getProductionLineId() > 0) { + organizationDao.updateCountersInProductionLine(g + .getProductionLineId()); + } + clearProjectInfoCache(result); + return result; + } + + + public int removeProject(int id) { + clearProjectDocCache(id); + clearProjectInfoCache(id); + Project p = getProject(id); + Group g = organizationDao.getGroup(p.getGroupId()); + int result = projectDao.removeProject(id); + if (g != null) { + int pId = g.getProductionLineId(); + if (pId > 0) { + organizationDao.updateCountersInProductionLine(pId); + } + } + return result; + } + + + public int updateProject(Project outerProject) { + // first clear, for existed members + clearProjectInfoCache(outerProject.getId()); + + Project project = getProject(outerProject.getId()); + project.setName(outerProject.getName()); + project.setIntroduction(outerProject.getIntroduction()); + project.setUpdateTime(new Date()); + project.setRelatedIds(outerProject.getRelatedIds()); + + if (outerProject.getMemberAccountList() != null) { + // adding new ones + for (String account : outerProject.getMemberAccountList()) { + User user = accountDao.getUser(account); + if (user != null) { + boolean addSuccess = project.addMember(user); + if (addSuccess) { + Notification o = new Notification(); + o.setTypeId((short) 2); + o.setTargetUser(outerProject.getUser()); + o.setUser(user); + o.setParam1(new Integer(outerProject.getId()).toString()); + o.setParam2(outerProject.getName()); + accountMgr.addNotification(o); + } + } + } + + if (project.getUserList() != null) { + // remove old ones + List userListToBeRemoved = new ArrayList(); + for (User user : project.getUserList()) { + if (!outerProject.getMemberAccountList().contains( + user.getAccount())) { + userListToBeRemoved.add(user); + } + } + + for (User user : userListToBeRemoved) { + project.removeMember(user); + } + } + + } + + int returnVal = projectDao.updateProject(project); + + // duplex clear, for added new members + clearProjectInfoCache(project.getId()); + clearProjectDocCache(project.getId()); + + return returnVal; + } + + + public Project getProjectSummary(int id) { + Project p = projectDao.getProjectSummary(id); + if (p != null) + p.setUser(accountMgr.getUser(p.getUserId())); + return p; + } + + + public Project getProject(int id, String ver) { + CheckIn check = workspaceDao.getVersion(id, ver); + String projectData = check.getProjectData(); + + Gson gson = new Gson(); + Project p = gson.fromJson(projectData, Project.class); + p.setVersion(check.getVersion()); + return p; + } + + public Project getProject(int id) { + Project p = projectDao.getProject(id); + return p; + } + + + public Module getModule(int id) { + return projectDao.getModule(id); + } + + + public Page getPage(int id) { + return (Page) projectDao.getPage(id); + } + + + public String updateProject(int id, String projectData, + String deletedObjectListData, Map actionIdMap) { + clearProjectDocCache(id); + return projectDao.updateProject(id, projectData, deletedObjectListData, actionIdMap); + } + + + public int getProjectListNum(User user) { + if (user != null && user.isUserInRole("admin")) { + user = null; + } + return projectDao.getProjectListNum(user); + } + + + public void loadParamIdListForAction(Action action) { + List paramIdList = new ArrayList(); + recursivelyLoadParamIdList(paramIdList, + action.getResponseParameterList()); + action.setRemarks(ArrayUtils.join(paramIdList, ",")); + } + + + public void loadParamIdListForPage(Page page) { + for (Action action : page.getActionList()) { + loadParamIdListForAction(action); + } + } + + /** + * sub method of loadParamIdListForAction for recursively load paramIdList + * for complex parameters + * + * @param paramIdList + * @param paramList + */ + private void recursivelyLoadParamIdList(List paramIdList, + Set paramList) { + for (Parameter p : paramList) { + if (p.getIdentifier() != null || !p.getIdentifier().isEmpty()) { + paramIdList.add(p.getIdentifier()); + } + if (p.getParameterList() != null && p.getParameterList().size() > 0) { + recursivelyLoadParamIdList(paramIdList, p.getParameterList()); + } + } + } + + + public List getMatchedActionList(int projectId, String pattern) { + List actionList = projectDao.getMatchedActionList(projectId, + pattern); + if (actionList == null || actionList.size() == 0) { + Project project = projectDao.getProjectSummary(projectId); + if (project != null) { + String ids = project.getRelatedIds(); + if (ids != null && !ids.isEmpty()) { + String[] arr = ids.split(","); + for (String id : arr) { + actionList = projectDao.getMatchedActionList( + Integer.parseInt(id), pattern); + if (actionList != null && actionList.size() != 0) { + return actionList; + } + } + } + } + } + return actionList; + } + + + public List getProjectListByGroup(int id) { + return projectDao.getProjectListByGroup(id); + } + + + public List search(String key) { + return projectDao.search(key); + } + + + public List search(String key, int userId) { + List list = projectDao.search(key); + List result = new ArrayList(); + + for (Project p : list) { + if (organizationMgr.canUserAccessProject(userId, p.getId())) { + result.add(p); + } + } + return result; + } + + + public Action getAction(int id) { + return projectDao.getAction(id); + } + + + public Action getAction(int id, String ver, int projectId) { + CheckIn check = workspaceDao.getVersion(projectId, ver); + Gson gson = new Gson(); + Project p = gson.fromJson(check.getProjectData(), Project.class); + return p.findAction(id); + } + + + public void updateDoc(int projectId) { + try { + HTTPUtils.sendGet("http://" + SystemConstant.NODE_SERVER + "/api/generateDoc?projectId=" + projectId); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + public List getProjectList() { + return projectDao.getProjectList(); + } + + + public int getProjectNum() { + return projectDao.getProjectListNum(); + } + + + public int getModuleNum() { + return projectDao.getModuleNum(); + } + + + public int getPageNum() { + return projectDao.getPageNum(); + } + + + public int getActionNum() { + return projectDao.getActionNum(); + } + + + public int getParametertNum() { + return projectDao.getParametertNum(); + } + + + public int getCheckInNum() { + return projectDao.getCheckInNum(); + } + + + public int getMockNumInTotal() { + return projectDao.getMockNumInTotal(); + } + + + public List selectMockNumTopNProjectList(int limit) { + return projectDao.selectMockNumTopNProjectList(limit); + } + + + public void updateCache(int projectId) { + Project project = getProject(projectId); + for (Module module : project.getModuleList()) { + for (Page page : module.getPageList()) { + for (Action action : page.getActionList()) { + updateActionCache(action); + } + } + } + } + + + public Integer getProjectIdByActionId(int actionId) { + return projectDao.getProjectIdByActionId(actionId); + } + + + public void updateProjectNum(Project project) { + projectDao.updateProjectNum(project); + } + + public void clearProjectInfoCache(int projectId) { + Project p = getProject(projectId); + List ids = new ArrayList(); + ids.add(p.getUserId()); + + Set members = p.getUserList(); + for (User member : members) { + ids.add(member.getId()); + } + + for (int userId : ids) { + String[] cacheKey = new String[]{CacheUtils.KEY_PROJECT_LIST, new Integer(userId).toString()}; + CacheUtils.del(cacheKey); + + String[] cacheKey2 = new String[]{CacheUtils.KEY_ACCESS_USER_TO_PROJECT, new Integer(userId).toString(), new Integer(projectId).toString()}; + CacheUtils.del(cacheKey2); + } + } + + public void clearProjectDocCache(int projectId) { + String[] cacheKey = new String[]{CacheUtils.KEY_WORKSPACE, new Integer(projectId).toString()}; + CacheUtils.del(cacheKey); + } + + public List getMemberIdsOfProject(int projectId) { + return projectDao.getMemberIdsOfProject(projectId); + } + + private void updateActionCache(Action action) { + action.setDisableCache(0); + for (Parameter param : action.getResponseParameterList()) { + clearParameterCache(param, action); + } + } + + private void clearParameterCache(Parameter param, Action action) { + String rules = param.getMockJsRules(); + if (rules != null && rules.contains("${") && rules.contains("}")) { + action.setDisableCache(1); + return; // over + } + Set children = param.getParameterList(); + if (children != null && children.size() != 0) { + for (Parameter child : children) { + clearParameterCache(child, action); + } + } + } + + +} diff --git a/src/main/java/com/taobao/rigel/rap/project/web/action/ProjectAction.java b/src/main/java/com/taobao/rigel/rap/project/web/action/ProjectAction.java new file mode 100644 index 000000000..feb083059 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/project/web/action/ProjectAction.java @@ -0,0 +1,391 @@ +package com.taobao.rigel.rap.project.web.action; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.auto.generate.bo.VelocityTemplateGenerator; +import com.taobao.rigel.rap.auto.generate.contract.Generator; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.common.bo.RapError; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.Page; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; +import com.taobao.rigel.rap.workspace.service.WorkspaceMgr; + +import java.io.ByteArrayInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.*; + +public class ProjectAction extends ActionBase { + + private int id; + + private List searchResult; + + private String ids; + private String key; + private String desc; + private int groupId; + private String accounts; + private String memberAccountListStr; + private String name; + private Date createDate; + private String introduction; + private List projectList; + private Project project; + private ProjectMgr projectMgr; + private WorkspaceMgr workspaceMgr; + private int pageId; + private String projectData; + private String result; + private InputStream outputStream; + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + private OrganizationMgr organizationMgr; + + public String getIds() { + if (ids == null || ids.isEmpty()) { + return ""; + } + + String[] idList = ids.split(","); + String returnVal = ""; + Integer num = 0; + int counter = 0; + for (String id : idList) { + try { + num = Integer.parseInt(id); + counter++; + if (counter > 1) { + returnVal += ","; + } + returnVal += num.toString(); + + } catch (Exception ex) { + + } + } + return returnVal; + } + + public void setIds(String ids) { + this.ids = ids; + } + + public List getSearchResult() { + return searchResult; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public int getId() { + return this.id; + } + + public void setId(int id) { + this.id = id; + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public String getAccounts() { + if (accounts == null) + return ""; + return accounts; + } + + public void setAccounts(String accounts) { + this.accounts = accounts; + } + + public List getMemberAccountList() { + List memberList = new ArrayList(); + for (User user : super.getAccountMgr().getUserList()) { + memberList.add(user.getAccount() + "(" + user.getName() + ")"); + } + return memberList; + } + + public String getMemberAccountListStr() { + return memberAccountListStr; + } + + public void setMemberAccountListStr(String memberAccountListStr) { + this.memberAccountListStr = memberAccountListStr; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getCreateDate() { + return this.createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public String getIntroduction() { + return this.introduction; + } + + public void setIntroduction(String introduction) { + this.introduction = introduction; + } + + public List getProjectList() { + return this.projectList; + } + + public void setProjectList(List projectList) { + this.projectList = projectList; + } + + public Project getProject() { + return this.project; + } + + public void setProject(Project project) { + this.project = project; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public WorkspaceMgr getWorkspaceMgr() { + return workspaceMgr; + } + + public void setWorkspaceMgr(WorkspaceMgr workspaceMgr) { + this.workspaceMgr = workspaceMgr; + } + + public int getPageId() { + return pageId; + } + + public void setPageId(int pageId) { + this.pageId = pageId; + } + + public String getProjectData() { + return projectData; + } + + public void setProjectData(String projectData) { + this.projectData = projectData; + } + + public String delete() { + if (!isUserLogined()) + return LOGIN; + if (!organizationMgr.canUserDeleteProject(getCurUserId(), getId())) { + setErrMsg("您没有删除该项目的权限"); + return ERROR; + } + projectMgr.removeProject(getId()); + return SUCCESS; + } + + public String create() { + if (!isUserLogined()) + return LOGIN; + Gson gson = new Gson(); + + Project project = new Project(); + project.setCreateDate(new Date()); + project.setUser(getCurUser()); + project.setUserId(getCurUserId()); + project.setIntroduction(getDesc()); + project.setName(getName()); + project.setGroupId(groupId); + List memberAccountList = new ArrayList(); + String[] list = getAccounts().split(","); + // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), + for (String item : list) { + String account = item.contains("(") ? item.substring(0, + item.indexOf("(")).trim() : item.trim(); + if (!account.equals("")) { + memberAccountList.add(account); + } + } + project.setMemberAccountList(memberAccountList); + int projectId = projectMgr.addProject(project); + project = projectMgr.getProject(projectId); + + for (String account : memberAccountList) { + organizationMgr.addTeamMembers(getCurUserId(), organizationMgr.getTeamIdByProjectId(project.getId()), account); + } + + Map result = new HashMap(); + result.put("id", project.getId()); + result.put("name", project.getName()); + result.put("desc", project.getIntroduction()); + result.put("accounts", project.getMemberAccountListStr()); + result.put("groupId", project.getGroupId()); + result.put("isManagable", "true"); + result.put("creator", project.getUser().getUserBaseInfo()); + setJson(new RapError(gson.toJson(result)).toString()); + return SUCCESS; + } + + public String update() { + if (!isUserLogined()) + return LOGIN; + if (!organizationMgr.canUserManageProject(getCurUserId(), getId())) { + setErrMsg("您没有管理该项目的权限"); + return ERROR; + } + + Project project = new Project(); + project.setId(getId()); + project.setIntroduction(getDesc()); + project.setName(getName()); + project.setUser(getCurUser()); + List memberAccountList = new ArrayList(); + String[] list = getAccounts().split(","); + // format: mashengbo(大灰狼堡森), linpanhui(林攀辉), + for (String item : list) { + String account = item.contains("(") ? item.substring(0, + item.indexOf("(")).trim() : item.trim(); + if (!account.equals("")) { + memberAccountList.add(account); + organizationMgr.addTeamMembers(getCurUserId(), organizationMgr.getTeamIdByProjectId(project.getId()), account); + } + } + Gson gson = new Gson(); + project.setMemberAccountList(memberAccountList); + projectMgr.updateProject(project); + + project = projectMgr.getProject(project.getId()); + + if (getCurUser().isUserInRole("admin") + || getCurUser().getId() == project.getUser().getId()) { + project.setIsManagable(true); + } + + Map result = new HashMap(); + result.put("id", project.getId()); + result.put("name", project.getName()); + result.put("desc", project.getIntroduction()); + result.put("accounts", project.getMemberAccountListStr()); + result.put("groupId", project.getGroupId()); + result.put("isManagable", project.isManagable()); + setJson(new RapError(gson.toJson(result)).toString()); + + return SUCCESS; + } + + public String updateReleatedIds() { + if (!isUserLogined()) + return LOGIN; + if (!organizationMgr.canUserManageProject(getCurUserId(), getId())) { + setErrMsg("您没有管理该项目的权限"); + return ERROR; + } + + Project project = projectMgr.getProjectSummary(getId()); + project.setRelatedIds(getIds()); + projectMgr.updateProject(project); + + + return SUCCESS; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public InputStream getOutputStream() { + return outputStream; + } + + public void setOutputStream(InputStream outputStream) { + this.outputStream = outputStream; + } + + public String autoGenerate() throws FileNotFoundException, + UnsupportedEncodingException { + Generator generator = new VelocityTemplateGenerator(); + Page page = projectMgr.getPage(getPageId()); + generator.setObject(page); + String exportFileString = generator.doGenerate(); + outputStream = new ByteArrayInputStream( + exportFileString.getBytes("UTF8")); + return SUCCESS; + } + + public String getGeneratedFileName() { + return projectMgr.getPage(getPageId()).getTemplate(); + } + + public String search() { + + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + + User curUser = getCurUser(); + if (curUser.isAdmin()) { + searchResult = projectMgr.search(key); + } else { + searchResult = projectMgr.search(key, getCurUserId()); + } + + List> list = new ArrayList>(); + for (Project p : searchResult) { + Map item = new HashMap(); + item.put("id", p.getId()); + item.put("name", p.getName()); + list.add(item); + } + Gson gson = new Gson(); + setJson(gson.toJson(list)); + return SUCCESS; + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/tester/bo/SSOUser.java b/src/main/java/com/taobao/rigel/rap/tester/bo/SSOUser.java new file mode 100644 index 000000000..9f771f8ce --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/tester/bo/SSOUser.java @@ -0,0 +1,11 @@ +package com.taobao.rigel.rap.tester.bo; + +public class SSOUser { + public String empId; + public String nickNameCn; + public String firstName; + public String lastName; + public SSOUser() { + + } +} diff --git a/src/main/java/com/taobao/rigel/rap/tester/bo/SSOUserRes.java b/src/main/java/com/taobao/rigel/rap/tester/bo/SSOUserRes.java new file mode 100644 index 000000000..d1591e623 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/tester/bo/SSOUserRes.java @@ -0,0 +1,15 @@ +package com.taobao.rigel.rap.tester.bo; + +/** + * Created by Bosn on 14-9-23. + */ +public class SSOUserRes { + public SSOUser content; + + public SSOUserRes() { + + } + + +} + diff --git a/src/main/java/com/taobao/rigel/rap/tester/web/action/TesterAction.java b/src/main/java/com/taobao/rigel/rap/tester/web/action/TesterAction.java new file mode 100644 index 000000000..c036f3d3d --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/tester/web/action/TesterAction.java @@ -0,0 +1,97 @@ +package com.taobao.rigel.rap.tester.web.action; + +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.Page; +import com.taobao.rigel.rap.project.service.ProjectMgr; + + +public class TesterAction extends ActionBase { + + private ProjectMgr projectMgr; + private int id; + private Page page; + private int projectId; + private String url; + private OrganizationMgr organizationMgr; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public int getProjectId() { + return projectId; + } + + public Page getPage() { + return page; + } + + public ProjectMgr getProjectMgr() { + return projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String pageTester() { + + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/tester/pageTester.do?id=" + + id); + return LOGIN; + } + + if (!organizationMgr.canUserAccessPage(getCurUserId(), id)) { + setErrMsg(ACCESS_DENY); + return ERROR; + } + + page = projectMgr.getPage(id); + projectMgr.loadParamIdListForPage(page); + projectId = page.getModule().getProject().getId(); + return SUCCESS; + } + + public String test() { + /** + SystemVisitorLog.clear(projectMgr); + System.out.println("Clear complete!"); + setJson("clear complete"); + */ + return SUCCESS; + } + + /** + * used for system configuration when new version deployed + * + * @return + */ + public String ___init___() throws Exception { + + + return SUCCESS; + } +} diff --git a/src/main/java/com/taobao/rigel/rap/workspace/bo/CheckIn.java b/src/main/java/com/taobao/rigel/rap/workspace/bo/CheckIn.java new file mode 100644 index 000000000..012d99431 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/workspace/bo/CheckIn.java @@ -0,0 +1,178 @@ +package com.taobao.rigel.rap.workspace.bo; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.utils.DateUtils; +import com.taobao.rigel.rap.common.utils.StringUtils; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.workspace.bo.Workspace.ModeType; + +import java.util.Date; + +public class CheckIn implements java.io.Serializable { + + private int id; + private Date createDate; + private String tag; + private User user; + private Project project; + private String description; + private String version; + private String projectData; + private int workspaceModeInt; + private String log; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public String getCreateDateStr() { + return getCreateDate() == null ? "" : DateUtils.TIME_FORMAT.format(getCreateDate()); + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getProjectData() { + return projectData; + } + + public void setProjectData(String projectData) { + this.projectData = projectData; + } + + public int getWorkspaceModeInt() { + return workspaceModeInt; + } + + public void setWorkspaceModeInt(int workspaceModeInt) { + this.workspaceModeInt = workspaceModeInt; + } + + public ModeType getWorkspaceMode() { + if (workspaceModeInt == 1) { + return ModeType.VSS; + } else if (workspaceModeInt == 2) { + return ModeType.SVN; + } else { + // default + return ModeType.VSS; + } + } + + public void setWorkspaceMode(ModeType workspaceModeType) { + if (workspaceModeType == ModeType.VSS) { + workspaceModeInt = 1; + } else if (workspaceModeType == ModeType.SVN) { + workspaceModeInt = 2; + } else { + // default + workspaceModeInt = 1; + } + } + + public String getLog() { + return log; + } + + public void setLog(String log) { + this.log = log; + } + + public void versionUpgrade(int versionPosition) throws Exception { + if (versionPosition > 4 || versionPosition < 1) { + throw new Exception("illegal version position: " + versionPosition); + } + String[] versionList = getVersion().split("\\."); + if (versionList.length != 4) { + throw new Exception("illegal version format: " + getVersion()); + } + Integer integer = Integer.parseInt(versionList[versionPosition - 1]) + 1; + versionList[versionPosition - 1] = integer.toString(); + String newVersion = ""; + for (int i = 0; i < versionList.length; i++) { + newVersion += versionList[i]; + if (i < versionList.length - 1) { + newVersion += "."; + } + } + setVersion(newVersion); + } + + public String toString() { + return this.toString(ToStringType.NORMAL); + } + + public String toString(ToStringType type) { + if (type == ToStringType.NORMAL) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\"id\":" + getId() + ","); + stringBuilder.append("\"version\":\"" + getVersion() + "\","); + stringBuilder.append("\"userName\":\"" + getUser().getName() + "\","); + stringBuilder.append("\"createDateStr\":\"" + getCreateDateStr() + "\","); + stringBuilder.append("\"description\":\"" + StringUtils.escapeInJ(getDescription()) + "\"}"); + return stringBuilder.toString(); + } else if (type == ToStringType.COMPLETED) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\"id\":" + getId() + ","); + stringBuilder.append("\"version\":\"" + getVersion() + "\","); + stringBuilder.append("\"userName\":\"" + getUser().getName() + "\","); + stringBuilder.append("\"projectData\":" + getProjectData() + ","); + stringBuilder.append("\"createDateStr\":\"" + getCreateDateStr() + "\","); + stringBuilder.append("\"description\":\"" + StringUtils.escapeInJ(getDescription()) + "\"}"); + return stringBuilder.toString(); + } else { + return this.toString(); + } + } + + public enum ToStringType {COMPLETED, NORMAL} +} \ No newline at end of file diff --git a/src/main/java/com/taobao/rigel/rap/workspace/bo/Workspace.java b/src/main/java/com/taobao/rigel/rap/workspace/bo/Workspace.java new file mode 100644 index 000000000..8c806409b --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/workspace/bo/Workspace.java @@ -0,0 +1,114 @@ +package com.taobao.rigel.rap.workspace.bo; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.project.bo.Project; + +import java.util.Date; +import java.util.Iterator; +import java.util.List; + +public class Workspace implements java.io.Serializable { + + private int id; + private Project project; + private User user; + private Date createDate; + private Date updateDate; + private String projectData; + private String projectDataOriginal; + + public boolean isAccessable() { + return accessable; + } + + public void setAccessable(boolean accessable) { + this.accessable = accessable; + } + + private boolean accessable; + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getModeInt() { + return project.getWorkspaceModeInt(); + } + + public ModeType getModeType() { + return project.getWorkspaceMode(); + } + + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Date getCreateDate() { + return createDate; + } + + public void setCreateDate(Date createDate) { + this.createDate = createDate; + } + + public Date getUpdateDate() { + return updateDate; + } + + public void setUpdateDate(Date updateDate) { + this.updateDate = updateDate; + } + + public String getProjectData() { + return projectData; + } + + public void setProjectData(String projectData) { + this.projectData = projectData; + } + + public String getProjectDataOriginal() { + return projectDataOriginal; + } + + public void setProjectDataOriginal(String projectDataOriginal) { + this.projectDataOriginal = projectDataOriginal; + } + + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\"projectData\":" + getProject().getProjectData() + ","); + stringBuilder.append("\"relatedIds\":\"" + getProject().getRelatedIds() + "\","); + stringBuilder.append("\"checkList\":["); + List checkList = getProject().getCheckInListOrdered(); + if (checkList != null) { + Iterator iterator = checkList.iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next().toString()); + if (iterator.hasNext()) { + stringBuilder.append(", "); + } + } + } + stringBuilder.append("]}"); + return stringBuilder.toString(); + } + + public enum ModeType {VSS, SVN} +} diff --git a/src/main/java/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java b/src/main/java/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java new file mode 100644 index 000000000..da904b505 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/workspace/dao/WorkspaceDao.java @@ -0,0 +1,21 @@ +package com.taobao.rigel.rap.workspace.dao; + +import com.taobao.rigel.rap.workspace.bo.CheckIn; +import com.taobao.rigel.rap.workspace.bo.Workspace; + +public interface WorkspaceDao { + + Workspace getWorkspace(int projectId, int userId); + + void updateWorkspace(Workspace workspace); + + Workspace getWorkspace(int id); + + void addCheckIn(CheckIn checkIn); + + CheckIn getVersion(int versionId); + + CheckIn getVersion(int projectId, String version); + + void prepareForVersionSwitch(CheckIn check); +} diff --git a/src/main/java/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java b/src/main/java/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java new file mode 100644 index 000000000..1bfd4d868 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/workspace/dao/impl/WorkspaceDaoImpl.java @@ -0,0 +1,112 @@ +package com.taobao.rigel.rap.workspace.dao.impl; + +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.account.dao.AccountDao; +import com.taobao.rigel.rap.project.bo.Module; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.dao.ProjectDao; +import com.taobao.rigel.rap.workspace.bo.CheckIn; +import com.taobao.rigel.rap.workspace.bo.Workspace; +import com.taobao.rigel.rap.workspace.dao.WorkspaceDao; +import org.hibernate.HibernateException; +import org.hibernate.Query; +import org.hibernate.Session; +import org.springframework.orm.hibernate5.support.HibernateDaoSupport; + +import java.util.Date; +import java.util.Iterator; + +public class WorkspaceDaoImpl extends HibernateDaoSupport implements WorkspaceDao { + + private AccountDao accountDao; + private ProjectDao projectDao; + + public AccountDao getAccountDao() { + return accountDao; + } + + public void setAccountDao(AccountDao accountDao) { + this.accountDao = accountDao; + } + + public ProjectDao getProjectDao() { + return projectDao; + } + + public void setProjectDao(ProjectDao projectDao) { + this.projectDao = projectDao; + } + + + public Workspace getWorkspace(int projectId, int userId) throws HibernateException { + Session session = currentSession(); + Query q = session.createQuery("from Workspace where user.id = :userId and project.id = :projectId"); + q.setInteger("projectId", projectId); + q.setInteger("userId", userId); + Workspace workspace = (Workspace) q.uniqueResult(); + if (workspace == null) { + return addWorkspace(projectId, userId); + } else { + return workspace; + } + } + + private Workspace addWorkspace(int projectId, int userId) { + Session session = currentSession(); + Project project = (Project) session.get(Project.class, projectId); + if (project == null) { + throw new RuntimeException("project you requested doesn't exist."); + } + Workspace workspace = new Workspace(); + workspace.setUser((User) session.load(User.class, userId)); + workspace.setProject(project); + workspace.setProjectData(project.toString(Project.TO_STRING_TYPE.TO_PARAMETER)); + workspace.setProjectDataOriginal(workspace.getProjectData()); + workspace.setUpdateDate(new Date()); + int id = (Integer) session.save(workspace); + return getWorkspace(id); + } + + public void updateWorkspace(Workspace workspace) { + workspace.setUpdateDate(new Date()); + currentSession().save(workspace); + } + + + public Workspace getWorkspace(int id) { + Session session = currentSession(); + Workspace workspace = session.load(Workspace.class, id); + return workspace; + } + + public void addCheckIn(CheckIn checkIn) { + currentSession().save(checkIn); + } + + + public CheckIn getVersion(int versionId) { + return currentSession().load(CheckIn.class, versionId); + } + + + public CheckIn getVersion(int projectId, String version) { + Session session = currentSession(); + Query query = session.createQuery("from CheckIn obj where obj.project.id = :projectId and obj.version = :version"); + query.setInteger("projectId", projectId); + query.setString("version", version); + return (CheckIn) query.uniqueResult(); + } + + + public void prepareForVersionSwitch(CheckIn check) { + Session session = currentSession(); + Project project = check.getProject(); + Iterator iterator = project.getModuleList().iterator(); + while (iterator.hasNext()) { + Module next = iterator.next(); + session.delete(next); + } + project.getModuleList().clear(); + } + +} diff --git a/src/main/java/com/taobao/rigel/rap/workspace/service/WorkspaceMgr.java b/src/main/java/com/taobao/rigel/rap/workspace/service/WorkspaceMgr.java new file mode 100644 index 000000000..844dfcdc5 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/workspace/service/WorkspaceMgr.java @@ -0,0 +1,74 @@ +package com.taobao.rigel.rap.workspace.service; + +import com.taobao.rigel.rap.workspace.bo.CheckIn; +import com.taobao.rigel.rap.workspace.bo.Workspace; + +public interface WorkspaceMgr { + + /** + * get workspace obj + * + * @param projectId + * @param userId + * @return + */ + Workspace getWorkspace(int projectId, int userId); + + /** + * update workspace + * + * @param workspace + */ + void updateWorkspace(Workspace workspace); + + /** + * get workspace + * + * @param id + * @return + */ + Workspace getWorkspace(int id); + + + /*** + * workspace check out + * + * @param jsonList [0]:projectData, [1]: projectDataOriginal + * @param userId + * @param projectId + * @return + */ + String checkOut(String[] jsonList, int userId, int projectId); + + /*** + * workspace check in + * + * @param jsonList [0]:projectData [1]: projectDataOriginal + * @param userId + * @param projectId + * @return + */ + String checkIn(String[] jsonList, int userId, int projectId); + + /** + * add new check in log + * + * @param checkIn + */ + void addCheckIn(CheckIn checkIn); + + /** + * get {@link CheckIn} obj + * + * @param versionId + * @return + */ + CheckIn getVersion(int versionId); + + /** + * do sth. preparing for version switch + * + * @param check + */ + void prepareForVersionSwitch(CheckIn check); +} diff --git a/src/main/java/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java b/src/main/java/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java new file mode 100644 index 000000000..c07ef753c --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/workspace/service/impl/WorkspaceMgrImpl.java @@ -0,0 +1,645 @@ +package com.taobao.rigel.rap.workspace.service.impl; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.project.bo.*; +import com.taobao.rigel.rap.project.dao.ProjectDao; +import com.taobao.rigel.rap.workspace.bo.CheckIn; +import com.taobao.rigel.rap.workspace.bo.Workspace; +import com.taobao.rigel.rap.workspace.dao.WorkspaceDao; +import com.taobao.rigel.rap.workspace.service.WorkspaceMgr; +import java.util.Iterator; + +public class WorkspaceMgrImpl implements WorkspaceMgr { + + private WorkspaceDao workspaceDao; + private ProjectDao projectDao; + + public WorkspaceDao getWorkspaceDao() { + return this.workspaceDao; + } + + public void setWorkspaceDao(WorkspaceDao workspaceDao) { + this.workspaceDao = workspaceDao; + } + + public ProjectDao getProjectDao() { + return projectDao; + } + + public void setProjectDao(ProjectDao projectDao) { + this.projectDao = projectDao; + } + + public Workspace getWorkspace(int projectId, int userId) { + Workspace workspace = workspaceDao.getWorkspace(projectId, userId); + return workspace; + } + + public void updateWorkspace(Workspace workspace) { + workspaceDao.updateWorkspace(workspace); + + } + + public Workspace getWorkspace(int id) { + return workspaceDao.getWorkspace(id); + } + + public String checkIn(String[] jsonList, int userId, int projectId) { + //[TODO] does user has access? + StringBuilder log = new StringBuilder(); + Project projectClient, projectOriginal, projectServer; + Gson gson = new Gson(); + // get server workspace + projectServer = projectDao.getProjectSummary(projectId); + // parse client workspace + projectClient = gson.fromJson(jsonList[0], Project.class); + // parse original client workspace + projectOriginal = gson.fromJson(jsonList[1], Project.class); + + /** + * start processing ... + * update a(client) => b(server) compared with o (Original) + */ + + // search moduleList + Iterator moduleIterator = projectClient.getModuleList().iterator(); + while (moduleIterator.hasNext()) { + Module moduleA = moduleIterator.next(); + // scan module + Module moduleB = findModule(projectServer, moduleA.getId()); + if (moduleB == null) { + log.append(logTemplate(moduleA.getId(), "module", "add", null, null, null)); + projectServer.getModuleList().add(moduleA); + continue; + } + Module moduleO = findModule(projectOriginal, moduleA.getId()); + if (!moduleA.getName().equals(moduleB.getName())) { + boolean aChanged = (!moduleA.getName().equals(moduleO.getName())); + boolean bChanged = (!moduleB.getName().equals(moduleO.getName())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(moduleB.getId(), "module", "update", + moduleA.getName(), moduleB.getName(), "name")); + moduleB.setName(moduleA.getName()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!moduleA.getIntroduction().equals(moduleB.getIntroduction())) { + boolean aChanged = (!moduleA.getIntroduction().equals(moduleO.getIntroduction())); + boolean bChanged = (!moduleB.getIntroduction().equals(moduleO.getIntroduction())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(moduleB.getId(), "module", "update", + moduleA.getIntroduction(), moduleB.getIntroduction(), "introduction")); + moduleB.setIntroduction(moduleA.getIntroduction()); + } else if (!aChanged && bChanged) { + // ignore + } + } + // search pageList + Iterator pageIterator = moduleA.getPageList().iterator(); + while (pageIterator.hasNext()) { + Page pageA = pageIterator.next(); + // scan page + Page pageB = findPage(projectServer, pageA.getId()); + if (pageB == null) { + moduleB.getPageList().add(pageA); + continue; + } + Page pageO = findPage(projectOriginal, pageA.getId()); + if (!pageA.getName().equals(pageB.getName())) { + boolean aChanged = (!pageA.getName().equals(pageO.getName())); + boolean bChanged = (!pageB.getName().equals(pageO.getName())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(pageB.getId(), "page", "update", + pageA.getName(), pageB.getName(), "name")); + pageB.setName(pageA.getName()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!pageA.getIntroduction().equals(pageB.getIntroduction())) { + boolean aChanged = (!pageA.getIntroduction().equals(pageO.getIntroduction())); + boolean bChanged = (!pageB.getIntroduction().equals(pageO.getIntroduction())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(pageB.getId(), "page", "update", + pageA.getIntroduction(), pageB.getIntroduction(), "introduction")); + pageB.setIntroduction(pageA.getIntroduction()); + } else if (!aChanged && bChanged) { + // ignore + } + } + // search actionList + Iterator actionIterator = pageA.getActionList().iterator(); + while (actionIterator.hasNext()) { + Action actionA = actionIterator.next(); + // scan action + Action actionB = findAction(projectServer, actionA.getId()); + if (actionB == null) { + pageB.getActionList().add(actionA); + continue; + } + + Action actionO = findAction(projectOriginal, actionA.getId()); + if (!actionA.getName().equals(actionB.getName())) { + boolean aChanged = (!actionA.getName().equals(actionO.getName())); + boolean bChanged = (!actionB.getName().equals(actionO.getName())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getName(), actionB.getName(), "name")); + actionB.setName(actionA.getName()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!actionA.getDescription().equals(actionB.getDescription())) { + boolean aChanged = (!actionA.getDescription().equals(actionO.getDescription())); + boolean bChanged = (!actionB.getDescription().equals(actionO.getDescription())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getDescription(), actionB.getDescription(), "description")); + actionB.setDescription(actionA.getDescription()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!actionA.getRequestType().equals(actionB.getRequestType())) { + boolean aChanged = (!actionA.getRequestType().equals(actionO.getRequestType())); + boolean bChanged = (!actionB.getRequestType().equals(actionO.getRequestType())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getRequestType(), actionB.getRequestType(), "requestType")); + actionB.setRequestType(actionA.getRequestType()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!actionA.getRequestUrl().equals(actionB.getRequestUrl())) { + boolean aChanged = (!actionA.getRequestUrl().equals(actionO.getRequestUrl())); + boolean bChanged = (!actionB.getRequestUrl().equals(actionO.getRequestUrl())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getRequestUrl(), actionB.getRequestUrl(), "requestUrl")); + actionB.setRequestUrl(actionA.getRequestUrl()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!actionA.getResponseTemplate().equals(actionB.getResponseTemplate())) { + boolean aChanged = (!actionA.getResponseTemplate().equals(actionO.getResponseTemplate())); + boolean bChanged = (!actionB.getResponseTemplate().equals(actionO.getResponseTemplate())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getResponseTemplate(), actionB.getResponseTemplate(), "responseTemplate")); + actionB.setResponseTemplate(actionA.getResponseTemplate()); + } else if (!aChanged && bChanged) { + // ignore + } + } + // search requestParameterList + Iterator requestParameterIterator = actionA.getRequestParameterList().iterator(); + while (requestParameterIterator.hasNext()) { + Parameter parameterA = requestParameterIterator.next(); + // scan request parameter + Parameter parameterB = findParameter(projectServer, parameterA.getId(), true); + if (parameterB == null) { + actionB.getRequestParameterList().add(parameterA); + continue; + } + Parameter parameterO = findParameter(projectOriginal, parameterA.getId(), true); + processParameter(parameterA, parameterB, parameterO, log); + } + + // search responseParameterList + Iterator responseParameterIterator = actionA.getResponseParameterList().iterator(); + while (responseParameterIterator.hasNext()) { + Parameter parameterA = responseParameterIterator.next(); + // scan response parameter + Parameter parameterB = findParameter(projectClient, parameterA.getId(), false); + if (parameterB == null) { + actionB.getResponseParameterList().add(parameterA); + continue; + } + Parameter parameterO = findParameter(projectOriginal, parameterA.getId(), false); + processParameter(parameterA, parameterB, parameterO, log); + } + } + } + + } + projectDao.updateProject(projectServer); + projectServer = projectDao.getProjectSummary(projectId); + return "{\"projectData\":" + projectServer.toString() + ", \"log\":\"" + log + + "\", \"projectDataOriginal\":" + projectServer.toString() + "}"; + } + + + public String checkOut(String[] jsonList, int userId, int projectId) { + //[TODO] does user has access? + + StringBuilder log = new StringBuilder(); + Project projectClient, projectOriginal, projectServer; + Gson gson = new Gson(); + // get server workspace + projectServer = projectDao.getProjectSummary(projectId); + // parse client workspace + projectClient = gson.fromJson(jsonList[0], Project.class); + // parse original client workspace + projectOriginal = gson.fromJson(jsonList[1], Project.class); + + /** + * start processing ... + * update a(Server) => b(client) compared with o (Original) + */ + + // search moduleList + Iterator moduleIterator = projectServer.getModuleList().iterator(); + while (moduleIterator.hasNext()) { + Module moduleA = moduleIterator.next(); + // scan module + Module moduleB = findModule(projectClient, moduleA.getId()); + if (moduleB == null) { + log.append(logTemplate(moduleA.getId(), "module", "add", null, null, null)); + projectClient.getModuleList().add(moduleA); + continue; + } + Module moduleO = findModule(projectOriginal, moduleA.getId()); + if (!moduleA.getName().equals(moduleB.getName())) { + boolean aChanged = (!moduleA.getName().equals(moduleO.getName())); + boolean bChanged = (!moduleB.getName().equals(moduleO.getName())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(moduleB.getId(), "module", "update", + moduleA.getName(), moduleB.getName(), "name")); + moduleB.setName(moduleA.getName()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!moduleA.getIntroduction().equals(moduleB.getIntroduction())) { + boolean aChanged = (!moduleA.getIntroduction().equals(moduleO.getIntroduction())); + boolean bChanged = (!moduleB.getIntroduction().equals(moduleO.getIntroduction())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(moduleB.getId(), "module", "update", + moduleA.getIntroduction(), moduleB.getIntroduction(), "introduction")); + moduleB.setIntroduction(moduleA.getIntroduction()); + } else if (!aChanged && bChanged) { + // ignore + } + } + // search pageList + Iterator pageIterator = moduleA.getPageList().iterator(); + while (pageIterator.hasNext()) { + Page pageA = pageIterator.next(); + // scan page + Page pageB = findPage(projectClient, pageA.getId()); + if (pageB == null) { + moduleB.getPageList().add(pageA); + continue; + } + Page pageO = findPage(projectOriginal, pageA.getId()); + if (!pageA.getName().equals(pageB.getName())) { + boolean aChanged = (!pageA.getName().equals(pageO.getName())); + boolean bChanged = (!pageB.getName().equals(pageO.getName())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(pageB.getId(), "page", "update", + pageA.getName(), pageB.getName(), "name")); + pageB.setName(pageA.getName()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!pageA.getIntroduction().equals(pageB.getIntroduction())) { + boolean aChanged = (!pageA.getIntroduction().equals(pageO.getIntroduction())); + boolean bChanged = (!pageB.getIntroduction().equals(pageO.getIntroduction())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(pageB.getId(), "page", "update", + pageA.getIntroduction(), pageB.getIntroduction(), "introduction")); + pageB.setIntroduction(pageA.getIntroduction()); + } else if (!aChanged && bChanged) { + // ignore + } + } + // search actionList + Iterator actionIterator = pageA.getActionList().iterator(); + while (actionIterator.hasNext()) { + Action actionA = actionIterator.next(); + // scan action + Action actionB = findAction(projectClient, actionA.getId()); + if (actionB == null) { + pageB.getActionList().add(actionA); + continue; + } + + Action actionO = findAction(projectOriginal, actionA.getId()); + if (!actionA.getName().equals(actionB.getName())) { + boolean aChanged = (!actionA.getName().equals(actionO.getName())); + boolean bChanged = (!actionB.getName().equals(actionO.getName())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getName(), actionB.getName(), "name")); + actionB.setName(actionA.getName()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!actionA.getDescription().equals(actionB.getDescription())) { + boolean aChanged = (!actionA.getDescription().equals(actionO.getDescription())); + boolean bChanged = (!actionB.getDescription().equals(actionO.getDescription())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getDescription(), actionB.getDescription(), "description")); + actionB.setDescription(actionA.getDescription()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!actionA.getRequestType().equals(actionB.getRequestType())) { + boolean aChanged = (!actionA.getRequestType().equals(actionO.getRequestType())); + boolean bChanged = (!actionB.getRequestType().equals(actionO.getRequestType())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getRequestType(), actionB.getRequestType(), "requestType")); + actionB.setRequestType(actionA.getRequestType()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!actionA.getRequestUrl().equals(actionB.getRequestUrl())) { + boolean aChanged = (!actionA.getRequestUrl().equals(actionO.getRequestUrl())); + boolean bChanged = (!actionB.getRequestUrl().equals(actionO.getRequestUrl())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getRequestUrl(), actionB.getRequestUrl(), "requestUrl")); + actionB.setRequestUrl(actionA.getRequestUrl()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!actionA.getResponseTemplate().equals(actionB.getResponseTemplate())) { + boolean aChanged = (!actionA.getResponseTemplate().equals(actionO.getResponseTemplate())); + boolean bChanged = (!actionB.getResponseTemplate().equals(actionO.getResponseTemplate())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(Integer.parseInt(new Integer(actionB.getId()).toString()), "action", "update", + actionA.getResponseTemplate(), actionB.getResponseTemplate(), "responseTemplate")); + actionB.setResponseTemplate(actionA.getResponseTemplate()); + } else if (!aChanged && bChanged) { + // ignore + } + } + // search requestParameterList + Iterator requestParameterIterator = actionA.getRequestParameterList().iterator(); + while (requestParameterIterator.hasNext()) { + Parameter parameterA = requestParameterIterator.next(); + // scan request parameter + Parameter parameterB = findParameter(projectClient, parameterA.getId(), true); + if (parameterB == null) { + actionB.getRequestParameterList().add(parameterA); + continue; + } + Parameter parameterO = findParameter(projectOriginal, parameterA.getId(), true); + processParameter(parameterA, parameterB, parameterO, log); + } + + // search responseParameterList + Iterator responseParameterIterator = actionA.getResponseParameterList().iterator(); + while (responseParameterIterator.hasNext()) { + Parameter parameterA = responseParameterIterator.next(); + // scan response parameter + Parameter parameterB = findParameter(projectClient, parameterA.getId(), false); + if (parameterB == null) { + actionB.getResponseParameterList().add(parameterA); + continue; + } + Parameter parameterO = findParameter(projectOriginal, parameterA.getId(), false); + processParameter(parameterA, parameterB, parameterO, log); + } + } + } + + } + return "{\"projectData\":" + projectClient.toString() + ", \"log\":\"" + + log + "\", \"projectDataOriginal\":" + projectClient.toString() + "}"; + } + + + private void processParameter(Parameter parameterA, Parameter parameterB, + Parameter parameterO, StringBuilder log) { + if (!parameterA.getName().equals(parameterB.getName())) { + boolean aChanged = (!parameterA.getName().equals(parameterO.getName())); + boolean bChanged = (!parameterB.getName().equals(parameterO.getName())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(parameterB.getId(), "parameter", "update", + parameterA.getName(), parameterB.getName(), "name")); + parameterB.setName(parameterA.getName()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!parameterA.getDataType().equals(parameterB.getDataType())) { + boolean aChanged = (!parameterA.getDataType().equals(parameterO.getDataType())); + boolean bChanged = (!parameterB.getDataType().equals(parameterO.getDataType())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(parameterB.getId(), "parameter", "update", + parameterA.getDataType(), parameterB.getDataType(), "dataType")); + parameterB.setDataType(parameterA.getDataType()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!parameterA.getIdentifier().equals(parameterB.getIdentifier())) { + boolean aChanged = (!parameterA.getIdentifier().equals(parameterO.getIdentifier())); + boolean bChanged = (!parameterB.getIdentifier().equals(parameterO.getIdentifier())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(parameterB.getId(), "parameter", "update", + parameterA.getIdentifier(), parameterB.getIdentifier(), "identifier")); + parameterB.setIdentifier(parameterA.getIdentifier()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!parameterA.getRemark().equals(parameterB.getRemark())) { + boolean aChanged = (!parameterA.getRemark().equals(parameterO.getRemark())); + boolean bChanged = (!parameterB.getRemark().equals(parameterO.getRemark())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(parameterB.getId(), "parameter", "update", + parameterA.getRemark(), parameterB.getRemark(), "remark")); + parameterB.setRemark(parameterA.getRemark()); + } else if (!aChanged && bChanged) { + // ignore + } + } + if (!parameterA.getValidator().equals(parameterB.getValidator())) { + boolean aChanged = (!parameterA.getValidator().equals(parameterO.getValidator())); + boolean bChanged = (!parameterB.getValidator().equals(parameterO.getValidator())); + + if (aChanged && bChanged) { + // [TODO] conflict! + } else if (aChanged && !bChanged) { + // update + log.append(logTemplate(parameterB.getId(), "parameter", "update", + parameterA.getValidator(), parameterB.getValidator(), "validator")); + parameterB.setValidator(parameterA.getValidator()); + } else if (!aChanged && bChanged) { + // ignore + } + } + } + + private Module findModule(Project p, int moduleId) { + for (Module i : p.getModuleList()) { + if (i.getId() == moduleId) + return i; + } + return null; + } + + private Page findPage(Project p, int pageId) { + for (Module module : p.getModuleList()) { + for (Page page : module.getPageList()) { + if (page.getId() == pageId) + return page; + } + } + return null; + } + + private Action findAction(Project p, int actionId) { + for (Module module : p.getModuleList()) { + for (Page page : module.getPageList()) { + for (Action action : page.getActionList()) { + if (action.getId() == actionId) + return action; + } + } + } + return null; + } + + private Parameter findParameter(Project p, int parameterId, boolean isRequestType) { + for (Module module : p.getModuleList()) { + for (Page page : module.getPageList()) { + for (Action action : page.getActionList()) { + for (Parameter parameter : (isRequestType ? + action.getRequestParameterList() : action.getResponseParameterList())) { + if (parameter.getId() == parameterId) + return parameter; + } + } + } + } + return null; + } + + + private String logTemplate(int objectId, String className, + String operationName, String newValue, String oldValue, String property) { + return operationName == "add" ? + "
    " + operationName + " " + className + " [" + objectId + + "]
    " + : "
    " + operationName + " " + className + " [" + objectId + + "]." + property + " from [" + oldValue + "] to [" + newValue + "]
    "; + } + + + public void addCheckIn(CheckIn checkIn) { + workspaceDao.addCheckIn(checkIn); + } + + + public CheckIn getVersion(int versionId) { + return workspaceDao.getVersion(versionId); + } + + + public void prepareForVersionSwitch(CheckIn check) { + workspaceDao.prepareForVersionSwitch(check); + + } +} diff --git a/src/main/java/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java b/src/main/java/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java new file mode 100644 index 000000000..f62d64b08 --- /dev/null +++ b/src/main/java/com/taobao/rigel/rap/workspace/web/action/WorkspaceAction.java @@ -0,0 +1,585 @@ +package com.taobao.rigel.rap.workspace.web.action; + +import com.google.gson.Gson; +import com.taobao.rigel.rap.account.bo.Notification; +import com.taobao.rigel.rap.account.bo.User; +import com.taobao.rigel.rap.common.base.ActionBase; +import com.taobao.rigel.rap.common.config.SystemConstant; +import com.taobao.rigel.rap.common.service.impl.ContextManager; +import com.taobao.rigel.rap.common.utils.CacheUtils; +import com.taobao.rigel.rap.common.utils.MapUtils; +import com.taobao.rigel.rap.organization.bo.Corporation; +import com.taobao.rigel.rap.organization.bo.Group; +import com.taobao.rigel.rap.organization.bo.ProductionLine; +import com.taobao.rigel.rap.organization.service.OrganizationMgr; +import com.taobao.rigel.rap.project.bo.Module; +import com.taobao.rigel.rap.project.bo.Project; +import com.taobao.rigel.rap.project.service.ProjectMgr; +import com.taobao.rigel.rap.workspace.bo.CheckIn; +import com.taobao.rigel.rap.workspace.bo.Workspace; +import com.taobao.rigel.rap.workspace.service.WorkspaceMgr; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.exception.MethodInvocationException; +import org.apache.velocity.exception.ParseErrorException; +import org.apache.velocity.exception.ResourceNotFoundException; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; +import java.util.*; + +public class WorkspaceAction extends ActionBase { + + private static final Logger logger = LogManager.getFormatterLogger(WorkspaceAction.class); + public Module module; + private OrganizationMgr organizationMgr; + + private boolean accessable; + private boolean mock; + private int actionId; + private int id; + private String workspaceJsonString; + private Workspace workspace; + private VelocityEngine velocityEngine; + private int projectId; + private Project project; + private String projectData; + private String projectDataOriginal; + private String saveListJson; + private int saveId = -1; + private int versionId; + private String deletedObjectListData; + private String tag; + + public Group getGroup() { + return group; + } + + public void setGroup(Group group) { + this.group = group; + } + + private Group group; + + public Corporation getTeam() { + return team; + } + + public void setTeam(Corporation team) { + this.team = team; + } + + private Corporation team; + + public ProductionLine getProductline() { + return productline; + } + + public void setProductline(ProductionLine productline) { + this.productline = productline; + } + + private ProductionLine productline; + /** + * from 1 to 4, version position + */ + private int versionPosition; + private String description; + private boolean isLocked; + private InputStream fileInputStream; + + private WorkspaceMgr workspaceMgr; + private ProjectMgr projectMgr; + + public OrganizationMgr getOrganizationMgr() { + return organizationMgr; + } + + public void setOrganizationMgr(OrganizationMgr organizationMgr) { + this.organizationMgr = organizationMgr; + } + + public boolean isAccessable() { + return accessable; + } + + public void setAccessable(boolean accessable) { + this.accessable = accessable; + } + + public int getActionId() { + return actionId; + } + + public void setActionId(int actionId) { + this.actionId = actionId; + } + + public boolean isMock() { + return mock; + } + + public void setMock(boolean mock) { + this.mock = mock; + } + + public int getId() { + return this.id; + } + + public void setId(int id) { + this.id = id; + } + + public String getWorkspaceJsonString() { + return this.workspaceJsonString; + } + + public void setWorkspaceJsonString(String workspaceJsonString) { + this.workspaceJsonString = workspaceJsonString; + } + + public Workspace getWorkspace() { + return this.workspace; + } + + public void setWorkspace(Workspace workspace) { + this.workspace = workspace; + } + + public Module getModule() { + return this.module; + } + + public void setModule(Module module) { + this.module = module; + } + + public VelocityEngine getVelocityEngine() { + return velocityEngine; + } + + public void setVelocityEngine(VelocityEngine velocityEngine) { + this.velocityEngine = velocityEngine; + } + + public Project getProject() { + return project; + } + + public void setProject(Project project) { + this.project = project; + } + + public int getProjectId() { + return this.projectId; + } + + public void setProjectId(int projectId) { + this.projectId = projectId; + } + + public String getProjectData() { + return projectData; + } + + public void setProjectData(String projectData) { + this.projectData = projectData; + } + + public String getProjectDataOriginal() { + return projectDataOriginal; + } + + public void setProjectDataOriginal(String projectDataOriginal) { + this.projectDataOriginal = projectDataOriginal; + } + + public String getSaveListJson() { + return saveListJson; + } + + public void setSaveListJson(String saveListJson) { + this.saveListJson = saveListJson; + } + + public int getSaveId() { + return saveId; + } + + public void setSaveId(int saveId) { + this.saveId = saveId; + } + + public int getVersionId() { + return versionId; + } + + public void setVersionId(int versionId) { + this.versionId = versionId; + } + + public String getDeletedObjectListData() { + return deletedObjectListData; + } + + public void setDeletedObjectListData(String deletedObjectListData) { + this.deletedObjectListData = deletedObjectListData; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public int getVersionPosition() { + return versionPosition; + } + + public void setVersionPosition(int versionPosition) { + this.versionPosition = versionPosition; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public boolean getIsLocked() { + return isLocked; + } + + public void setIsLocked(boolean isLocked) { + this.isLocked = isLocked; + } + + public String myWorkspace() { + if (!isUserLogined()) { + plsLogin(); + setRelativeReturnUrl("/workspace/myWorkspace.do?projectId=" + + projectId); + return LOGIN; + } + setAccessable(organizationMgr.canUserManageProject(getCurUserId(), getProjectId())); + + Project p = projectMgr.getProjectSummary(getProjectId()); + group = organizationMgr.getGroup(p.getGroupId()); + productline = organizationMgr.getProductionLine(group.getProductionLineId()); + team = organizationMgr.getCorporation(productline.getCorporationId()); + return SUCCESS; + } + + public String loadWorkspace() { + if (!isUserLogined()) { + plsLogin(); + return JSON_ERROR; + } + String[] cacheKey = new String[]{CacheUtils.KEY_WORKSPACE, new Integer(getProjectId()).toString()}; + String cache = CacheUtils.get(cacheKey); + if (cache != null) { + setJson(cache); + } else { + Project p = projectMgr.getProject(getProjectId()); + + if (p == null || p.getId() <= 0) { + setErrMsg("该项目不存在或已被删除,会不会是亲这个链接保存的太久了呢?0 .0"); + logger.error("Unexpected project id=%d", getProjectId()); + return JSON_ERROR; + } + + if (!organizationMgr.canUserAccessProject(getCurUserId(), getProjectId())) { + setErrMsg(ACCESS_DENY); + return JSON_ERROR; + } + + Workspace workspace = new Workspace(); + workspace.setProject(p); + + String json = workspace.toString(); + setJson(json); + + CacheUtils.put(cacheKey, json); + } + return SUCCESS; + } + + /** + * load save, saveId must be significant, or operation failed + * + * @return the save object loaded + */ + /* + * public String querySave() { + * setJson(workspaceMgr.getSave(getSaveId()).getProjectData()); return + * SUCCESS; } + */ + public InputStream getFileInputStream() { + return fileInputStream; + } + + public WorkspaceMgr getworkspaceMgr() { + return workspaceMgr; + } + + public void setWorkspaceMgr(WorkspaceMgr workspaceMgr) { + this.workspaceMgr = workspaceMgr; + } + + public ProjectMgr projectMgr() { + return this.projectMgr; + } + + public void setProjectMgr(ProjectMgr projectMgr) { + this.projectMgr = projectMgr; + } + + public String ping() { + setJson("{\"isOk\":true}"); + return SUCCESS; + } + + public String queryVersion() { + setJson(workspaceMgr.getVersion(getVersionId()).toString( + CheckIn.ToStringType.COMPLETED)); + return SUCCESS; + } + + public String switchVersion() { + CheckIn check = workspaceMgr.getVersion(getVersionId()); + workspaceMgr.prepareForVersionSwitch(check); + projectMgr.updateProject(check.getProject().getId(), + check.getProjectData(), "[]", new HashMap()); + Project project = projectMgr.getProject(check.getProject().getId()); + String projectData = project + .toString(Project.TO_STRING_TYPE.TO_PARAMETER); + setJson("{\"projectData\":" + projectData + ", \"isOk\":true}"); + project.setProjectData(projectData); + projectMgr.updateProject(project); + return SUCCESS; + } + + public String checkIn() throws Exception { + User curUser = getCurUser(); + if (curUser == null) { + setErrMsg(LOGIN_WARN_MSG); + logger.error("Unlogined user trying to checkin and failed."); + return JSON_ERROR; + } + + if (!organizationMgr.canUserManageProject(getCurUserId(), getId())) { + setErrMsg("access deny"); + logger.error("User %s trying to checkedin project(id=$d) and denied.", getCurAccount(), getId()); + return JSON_ERROR; + } + + // update project + Map actionIdMap = new HashMap(); + projectMgr.updateProject(getId(), getProjectData(), + getDeletedObjectListData(), actionIdMap); + + + project = projectMgr.getProject(getId()); + + // generate one check-in of VSS mode submit + CheckIn checkIn = new CheckIn(); + checkIn.setCreateDate(new Date()); + checkIn.setDescription(getDescription()); + checkIn.setProject(project); + checkIn.setProjectData(project + .toString(Project.TO_STRING_TYPE.TO_PARAMETER)); + checkIn.setTag(getTag()); + checkIn.setUser(curUser); + checkIn.setVersion(project.getVersion()); + checkIn.versionUpgrade(getVersionPosition()); + + // after version upgrade, set back to project + project.setVersion(checkIn.getVersion()); + checkIn.setWorkspaceMode(Workspace.ModeType.VSS); + workspaceMgr.addCheckIn(checkIn); + + // calculate JSON string for client + project = projectMgr.getProject(getId()); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("{\"projectData\":" + checkIn.getProjectData()); + stringBuilder.append(",\"checkList\":["); + Iterator iterator = project.getCheckInListOrdered().iterator(); + while (iterator.hasNext()) { + stringBuilder.append(iterator.next()); + if (iterator.hasNext()) { + stringBuilder.append(","); + } + } + Gson g = new Gson(); + stringBuilder + .append("],\"actionIdMap\":") + .append(g.toJson(actionIdMap)) + .append(",\"isOk\":true}"); + setJson(stringBuilder.toString()); + + // update project data + project.setProjectData(checkIn.getProjectData()); + projectMgr.updateProject(project); + + // unlock the workspace + unlock(); + + // notification for doc change + for (User user : project.getUserList()) { + Notification notification = new Notification(); + notification.setParam1(new Integer(id).toString()); + notification.setParam2(project.getName()); + notification.setTypeId((short) 1); + notification.setTargetUser(getCurUser()); + notification.setUser(user); + if (notification.getUser().getId() != getCurUserId()) + getAccountMgr().addNotification(notification); + } + + Notification notification = new Notification(); + notification.setParam1(new Integer(id).toString()); + notification.setParam2(project.getName()); + notification.setTypeId((short) 1); + notification.setTargetUser(getCurUser()); + notification.setUser(project.getUser()); + if (notification.getUser().getId() != getCurUserId()) + getAccountMgr().addNotification(notification); + projectMgr.updateCache(id); + + return SUCCESS; + } + + public String lock() { + int curUserId = getCurUserId(); + if (curUserId <= 0) { + setIsOk(false); + setErrMsg(LOGIN_WARN_MSG); + return JSON_ERROR; + } + + boolean isOk = false; + if (isLocked(getId())) { + // if the project is locked, find the locker + User user = getLocker(getId()); + if (!user.getAccount().equals(getCurAccount())) { + setJson("{\"isOk\":false, \"errMsg\":\"该项目目前正被" + + user.getName() + "锁定.\"}"); + } else { + // user request lock a locked project + // which is locked by himself, so let him go + isOk = true; + } + + } else { + // else, lock the project, than let him go. + Map app = ContextManager.getApplication(); + if (app.get(ContextManager.KEY_PROJECT_LOCK_LIST) == null) { + app.put(ContextManager.KEY_PROJECT_LOCK_LIST, new HashMap()); + } + Map projectLockList = (Map) app + .get(ContextManager.KEY_PROJECT_LOCK_LIST); + if (projectLockList.get(curUserId) == null) { + projectLockList.put(curUserId, getId()); + // System.out.println("user[" + curUserId + "] locked project["+ + // getId() + "]"); + } + isOk = true; + } + if (isOk) { + setJson("{\"isOk\":true, \"projectData\":" + + projectMgr.getProject(getId()).getProjectData() + "}"); + } + return SUCCESS; + } + + public String unlock() { + if (isLocked(getId())) { + Map app = ContextManager.getApplication(); + Map projectLockList = (Map) app + .get(ContextManager.KEY_PROJECT_LOCK_LIST); + if (projectLockList == null) + return SUCCESS; + int userId = super.getCurUserId(); + int projectId = (Integer) projectLockList.get(userId); + projectLockList.remove(userId); + logger.info("user[%d] unlock project[%d]", userId, projectId); + } + return SUCCESS; + } + + /** + * caution: no authentication so far + * + * @return + * @throws Exception + */ + public String export() throws Exception { + project = projectMgr.getProject(projectId); + velocityEngine.init(); + VelocityContext context = new VelocityContext(); + context.put("project", project); + Template template = null; + try { + template = velocityEngine.getTemplate("resource/export.vm", "UTF8"); + } catch (ResourceNotFoundException rnfe) { + rnfe.printStackTrace(); + } catch (ParseErrorException pee) { + pee.printStackTrace(); + } catch (MethodInvocationException mie) { + mie.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + StringWriter sw = new StringWriter(); + template.merge(context, sw); + fileInputStream = new ByteArrayInputStream(sw.toString().getBytes( + "UTF8")); + return SUCCESS; + } + + private boolean isLocked(int projectId) { + Map app = ContextManager.getApplication(); + Map projectLockList = (Map) app + .get(ContextManager.KEY_PROJECT_LOCK_LIST); + return projectLockList != null + && projectLockList.containsValue(projectId); + } + + private User getLocker(int projectId) { + Map app = ContextManager.getApplication(); + Map projectLockList = (Map) app + .get(ContextManager.KEY_PROJECT_LOCK_LIST); + if (projectLockList != null) { + int userId = (Integer) MapUtils.getKeyByValue(projectLockList, + projectId); + User user = getAccountMgr().getUser(userId); + return user; + } + return null; + } + + public String __init__() { + // prevent repeated intialization of servcie + if (SystemConstant.serviceInitialized) { + return SUCCESS; + } + + SystemConstant.serviceInitialized = true; + + List list = projectMgr.getProjectList(); + for (Project p : list) { + projectMgr.updateDoc(p.getId()); + } + return SUCCESS; + } + +} diff --git a/src/main/java/org/apache/struts2/views/velocity/RapVelocityResult.java b/src/main/java/org/apache/struts2/views/velocity/RapVelocityResult.java new file mode 100644 index 000000000..70f448a7b --- /dev/null +++ b/src/main/java/org/apache/struts2/views/velocity/RapVelocityResult.java @@ -0,0 +1,16 @@ +package org.apache.struts2.views.velocity; + +import org.apache.struts2.dispatcher.VelocityResult; + +public class RapVelocityResult extends VelocityResult { + + private String contentType = "text/html"; + + public void setContentType(String contentType) { + this.contentType = contentType; + } + + protected String getContentType(String templateLocation) { + return contentType; + } +} diff --git a/src/main/java/org/apache/struts2/views/velocity/VelocityManager.java b/src/main/java/org/apache/struts2/views/velocity/VelocityManager.java new file mode 100644 index 000000000..ad065659c --- /dev/null +++ b/src/main/java/org/apache/struts2/views/velocity/VelocityManager.java @@ -0,0 +1,603 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.struts2.views.velocity; + +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.logging.Logger; +import com.opensymphony.xwork2.util.logging.LoggerFactory; +import com.taobao.rigel.rap.common.config.SystemConstant; +import com.taobao.rigel.rap.common.utils.DateUtils; +import com.taobao.rigel.rap.common.utils.SystemVisitorLog; +import org.apache.commons.lang3.StringUtils; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.StrutsException; +import org.apache.struts2.util.VelocityStrutsUtil; +import org.apache.struts2.views.TagLibrary; +import org.apache.struts2.views.TagLibraryDirectiveProvider; +import org.apache.struts2.views.jsp.ui.OgnlTool; +import org.apache.struts2.views.util.ContextUtil; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.context.Context; +import org.apache.velocity.tools.view.ToolboxManager; +import org.apache.velocity.tools.view.context.ChainedContext; +import org.apache.velocity.tools.view.servlet.ServletToolboxManager; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.*; + + +/** + * Manages the environment for Velocity result types + */ +public class VelocityManager { + public static final String STRUTS = "struts"; + public static final String KEY_VELOCITY_STRUTS_CONTEXT = ".KEY_velocity.struts2.context"; + /** + * the parent JSP tag + */ + public static final String PARENT = "parent"; + /** + * the current JSP tag + */ + public static final String TAG = "tag"; + private static final Logger LOG = LoggerFactory.getLogger(VelocityManager.class); + /** + * A reference to the toolbox manager. + */ + protected ToolboxManager toolboxManager = null; + private ObjectFactory objectFactory; + private VelocityEngine velocityEngine; + private String toolBoxLocation; + + + /** + * Names of contexts that will be chained on every request + */ + private String[] chainedContextNames; + + private Properties velocityProperties; + + private String customConfigFile; + + private List tagLibraries; + private List oldTagLibraries; + + private static final String replace(String string, String oldString, String newString) { + if (string == null) { + return null; + } + // If the newString is null, just return the string since there's nothing to replace. + if (newString == null) { + return string; + } + int i = 0; + // Make sure that oldString appears at least once before doing any processing. + if ((i = string.indexOf(oldString, i)) >= 0) { + // Use char []'s, as they are more efficient to deal with. + char[] string2 = string.toCharArray(); + char[] newString2 = newString.toCharArray(); + int oLength = oldString.length(); + StringBuilder buf = new StringBuilder(string2.length); + buf.append(string2, 0, i).append(newString2); + i += oLength; + int j = i; + // Replace all remaining instances of oldString with newString. + while ((i = string.indexOf(oldString, i)) > 0) { + buf.append(string2, j, i - j).append(newString2); + i += oLength; + j = i; + } + buf.append(string2, j, string2.length - j); + return buf.toString(); + } + return string; + } + + @Inject + public void setObjectFactory(ObjectFactory fac) { + this.objectFactory = fac; + } + + @Inject + public void setContainer(Container container) { + List list = new ArrayList(); + Set prefixes = container.getInstanceNames(TagLibraryDirectiveProvider.class); + for (String prefix : prefixes) { + list.add(container.getInstance(TagLibraryDirectiveProvider.class, prefix)); + } + this.tagLibraries = Collections.unmodifiableList(list); + + List oldList = new ArrayList(); + Set oldPrefixes = container.getInstanceNames(TagLibrary.class); + for (String prefix : oldPrefixes) { + oldList.add(container.getInstance(TagLibrary.class, prefix)); + } + this.oldTagLibraries = Collections.unmodifiableList(oldList); + } + + /** + * @return a reference to the VelocityEngine used by all struts velocity thingies with the exception of + * directly accessed *.vm pages + */ + public VelocityEngine getVelocityEngine() { + return velocityEngine; + } + + /** + * This method is responsible for creating the standard VelocityContext used by all WW2 velocity views. The + * following context parameters are defined: + *

    + *

      + *
    • request - the current HttpServletRequest
    • + *
    • response - the current HttpServletResponse
    • + *
    • stack - the current {@link ValueStack}
    • + *
    • ognl - an {@link OgnlTool}
    • + *
    • struts - an instance of {@link org.apache.struts2.util.StrutsUtil}
    • + *
    • action - the current Struts action
    • + *
    + * + * @return a new StrutsVelocityContext + */ + public Context createContext(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { + Context result = null; + VelocityContext[] chainedContexts = prepareChainedContexts(req, res, stack.getContext()); + StrutsVelocityContext context = new StrutsVelocityContext(chainedContexts, stack); + Map standardMap = ContextUtil.getStandardContext(stack, req, res); + for (Iterator iterator = standardMap.entrySet().iterator(); iterator.hasNext(); ) { + Map.Entry entry = (Map.Entry) iterator.next(); + context.put((String) entry.getKey(), entry.getValue()); + } + + + context.put("utils", new com.taobao.rigel.rap.common.utils.StringUtils()); + context.put("dateUtils", new DateUtils()); + context.put("consts", new SystemConstant()); + context.put("logger", new SystemVisitorLog()); + context.put(STRUTS, new VelocityStrutsUtil(velocityEngine, context, stack, req, res)); + + + ServletContext ctx = null; + try { + ctx = ServletActionContext.getServletContext(); + } catch (NullPointerException npe) { + // in case this was used outside the lifecycle of struts servlet + if (LOG.isDebugEnabled()) { + LOG.debug("internal toolbox context ignored"); + } + } + + if (toolboxManager != null && ctx != null) { + ChainedContext chained = new ChainedContext(context, velocityEngine, req, res, ctx); + chained.setToolbox(toolboxManager.getToolbox(chained)); + result = chained; + } else { + result = context; + } + + req.setAttribute(KEY_VELOCITY_STRUTS_CONTEXT, result); + return result; + } + + /** + * constructs contexts for chaining on this request. This method does not + * perform any initialization of the contexts. All that must be done in the + * context itself. + * + * @param servletRequest + * @param servletResponse + * @param extraContext + * @return an VelocityContext[] of contexts to chain + */ + protected VelocityContext[] prepareChainedContexts(HttpServletRequest servletRequest, HttpServletResponse servletResponse, Map extraContext) { + if (this.chainedContextNames == null) { + return null; + } + List contextList = new ArrayList(); + for (int i = 0; i < chainedContextNames.length; i++) { + String className = chainedContextNames[i]; + try { + VelocityContext velocityContext = (VelocityContext) objectFactory.buildBean(className, null); + contextList.add(velocityContext); + } catch (Exception e) { + if (LOG.isWarnEnabled()) { + LOG.warn("Warning. " + e.getClass().getName() + " caught while attempting to instantiate a chained VelocityContext, " + className + " -- skipping"); + } + } + } + if (contextList.size() > 0) { + VelocityContext[] extraContexts = new VelocityContext[contextList.size()]; + contextList.toArray(extraContexts); + return extraContexts; + } else { + return null; + } + } + + /** + * initializes the VelocityManager. this should be called during the initialization process, say by + * ServletDispatcher. this may be called multiple times safely although calls beyond the first won't do anything + * + * @param context the current servlet context + */ + public synchronized void init(ServletContext context) { + if (velocityEngine == null) { + velocityEngine = newVelocityEngine(context); + } + this.initToolbox(context); + } + + /** + * load optional velocity properties using the following loading strategy + *
      + *
    • relative to the servlet context path
    • + *
    • relative to the WEB-INF directory
    • + *
    • on the classpath
    • + *
    + * + * @param context the current ServletContext. may not be null + * @return the optional properties if struts.velocity.configfile was specified, an empty Properties file otherwise + */ + public Properties loadConfiguration(ServletContext context) { + if (context == null) { + String gripe = "Error attempting to create a loadConfiguration from a null ServletContext!"; + LOG.error(gripe); + throw new IllegalArgumentException(gripe); + } + + Properties properties = new Properties(); + + // now apply our systemic defaults, then allow user to override + applyDefaultConfiguration(context, properties); + + + String defaultUserDirective = properties.getProperty("userdirective"); + + /** + * if the user has specified an external velocity configuration file, we'll want to search for it in the + * following order + * + * 1. relative to the context path + * 2. relative to /WEB-INF + * 3. in the class path + */ + String configfile; + + if (customConfigFile != null) { + configfile = customConfigFile; + } else { + configfile = "velocity.properties"; + } + + configfile = configfile.trim(); + + InputStream in = null; + String resourceLocation = null; + + try { + if (context.getRealPath(configfile) != null) { + // 1. relative to context path, i.e. /velocity.properties + String filename = context.getRealPath(configfile); + + if (filename != null) { + File file = new File(filename); + + if (file.isFile()) { + resourceLocation = file.getCanonicalPath() + " from file system"; + in = new FileInputStream(file); + } + + // 2. if nothing was found relative to the context path, search relative to the WEB-INF directory + if (in == null) { + file = new File(context.getRealPath("/WEB-INF/" + configfile)); + + if (file.isFile()) { + resourceLocation = file.getCanonicalPath() + " from file system"; + in = new FileInputStream(file); + } + } + } + } + + // 3. finally, if there's no physical file, how about something in our classpath + if (in == null) { + in = VelocityManager.class.getClassLoader().getResourceAsStream(configfile); + if (in != null) { + resourceLocation = configfile + " from classloader"; + } + } + + // if we've got something, load 'er up + if (in != null) { + if (LOG.isInfoEnabled()) { + LOG.info("Initializing velocity using " + resourceLocation); + } + properties.load(in); + } + } catch (IOException e) { + if (LOG.isWarnEnabled()) { + LOG.warn("Unable to load velocity configuration " + resourceLocation, e); + } + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + } + } + } + + // overide with programmatically set properties + if (this.velocityProperties != null) { + Iterator keys = this.velocityProperties.keySet().iterator(); + while (keys.hasNext()) { + String key = (String) keys.next(); + properties.setProperty(key, this.velocityProperties.getProperty(key)); + } + } + + String userdirective = properties.getProperty("userdirective"); + + if ((userdirective == null) || userdirective.trim().equals("")) { + userdirective = defaultUserDirective; + } else { + userdirective = userdirective.trim() + "," + defaultUserDirective; + } + + properties.setProperty("userdirective", userdirective); + + + // for debugging purposes, allows users to dump out the properties that have been configured + if (LOG.isDebugEnabled()) { + LOG.debug("Initializing Velocity with the following properties ..."); + + for (Iterator iter = properties.keySet().iterator(); + iter.hasNext(); ) { + String key = (String) iter.next(); + String value = properties.getProperty(key); + + if (LOG.isDebugEnabled()) { + LOG.debug(" '" + key + "' = '" + value + "'"); + } + } + } + + return properties; + } + + @Inject(StrutsConstants.STRUTS_VELOCITY_CONFIGFILE) + public void setCustomConfigFile(String val) { + this.customConfigFile = val; + } + + @Inject(StrutsConstants.STRUTS_VELOCITY_TOOLBOXLOCATION) + public void setToolBoxLocation(String toolboxLocation) { + this.toolBoxLocation = toolboxLocation; + } + + public ToolboxManager getToolboxManager() { + return toolboxManager; + } + + /** + * allow users to specify via the struts.properties file a set of additional VelocityContexts to chain to the + * the StrutsVelocityContext. The intent is to allow these contexts to store helper objects that the ui + * developer may want access to. Examples of reasonable VelocityContexts would be an IoCVelocityContext, a + * SpringReferenceVelocityContext, and a ToolboxVelocityContext + */ + @Inject(StrutsConstants.STRUTS_VELOCITY_CONTEXTS) + public void setChainedContexts(String contexts) { + // we expect contexts to be a comma separated list of classnames + StringTokenizer st = new StringTokenizer(contexts, ","); + List contextList = new ArrayList(); + + while (st.hasMoreTokens()) { + String classname = st.nextToken(); + contextList.add(classname); + } + if (contextList.size() > 0) { + String[] chainedContexts = new String[contextList.size()]; + contextList.toArray(chainedContexts); + this.chainedContextNames = chainedContexts; + } + } + + /** + * Initializes the ServletToolboxManager for this servlet's + * toolbox (if any). + */ + protected void initToolbox(ServletContext context) { + /* if we have a toolbox, get a manager for it */ + if (StringUtils.isNotBlank(toolBoxLocation)) { + toolboxManager = ServletToolboxManager.getInstance(context, toolBoxLocation); + } else { + Velocity.info("VelocityViewServlet: No toolbox entry in configuration."); + } + } + + /** + *

    + * Instantiates a new VelocityEngine. + *

    + *

    + * The following is the default Velocity configuration + *

    + *
    +     *  resource.loader = file, class
    +     *  file.resource.loader.path = real path of webapp
    +     *  class.resource.loader.description = Velocity Classpath Resource Loader
    +     *  class.resource.loader.class = org.apache.struts2.views.velocity.StrutsResourceLoader
    +     * 
    + *

    + * this default configuration can be overridden by specifying a struts.velocity.configfile property in the + * struts.properties file. the specified config file will be searched for in the following order: + *

    + *
      + *
    • relative to the servlet context path
    • + *
    • relative to the WEB-INF directory
    • + *
    • on the classpath
    • + *
    + * + * @param context the current ServletContext. may not be null + */ + protected VelocityEngine newVelocityEngine(ServletContext context) { + if (context == null) { + String gripe = "Error attempting to create a new VelocityEngine from a null ServletContext!"; + LOG.error(gripe); + throw new IllegalArgumentException(gripe); + } + + Properties p = loadConfiguration(context); + + VelocityEngine velocityEngine = new VelocityEngine(); + + // Set the velocity attribute for the servlet context + // if this is not set the webapp loader WILL NOT WORK + velocityEngine.setApplicationAttribute(ServletContext.class.getName(), + context); + + try { + velocityEngine.init(p); + } catch (Exception e) { + throw new StrutsException("Unable to instantiate VelocityEngine!", e); + } + + return velocityEngine; + } + + /** + * once we've loaded up the user defined configurations, we will want to apply Struts specification configurations. + *
      + *
    • if Velocity.RESOURCE_LOADER has not been defined, then we will use the defaults which is a joined file, + * class loader for unpackaed wars and a straight class loader otherwise
    • + *
    • we need to define the various Struts custom user directives such as #param, #tag, and #bodytag
    • + *
    + * + * @param context + * @param p + */ + private void applyDefaultConfiguration(ServletContext context, Properties p) { + // ensure that caching isn't overly aggressive + + /** + * Load a default resource loader definition if there isn't one present. + * Ben Hall (22/08/2003) + */ + if (p.getProperty(Velocity.RESOURCE_LOADER) == null) { + p.setProperty(Velocity.RESOURCE_LOADER, "strutsfile, strutsclass"); + } + + /** + * If there's a "real" path add it for the strutsfile resource loader. + * If there's no real path and they haven't configured a loader then we change + * resource loader property to just use the strutsclass loader + * Ben Hall (22/08/2003) + */ + if (context.getRealPath("") != null) { + p.setProperty("strutsfile.resource.loader.description", "Velocity File Resource Loader"); + p.setProperty("strutsfile.resource.loader.class", "org.apache.velocity.runtime.resource.loader.FileResourceLoader"); + p.setProperty("strutsfile.resource.loader.path", context.getRealPath("")); + p.setProperty("strutsfile.resource.loader.modificationCheckInterval", "2"); + p.setProperty("strutsfile.resource.loader.cache", "true"); + } else { + // remove strutsfile from resource loader property + String prop = p.getProperty(Velocity.RESOURCE_LOADER); + if (prop.indexOf("strutsfile,") != -1) { + prop = replace(prop, "strutsfile,", ""); + } else if (prop.indexOf(", strutsfile") != -1) { + prop = replace(prop, ", strutsfile", ""); + } else if (prop.indexOf("strutsfile") != -1) { + prop = replace(prop, "strutsfile", ""); + } + + p.setProperty(Velocity.RESOURCE_LOADER, prop); + } + + /** + * Refactored the Velocity templates for the Struts taglib into the classpath from the web path. This will + * enable Struts projects to have access to the templates by simply including the Struts jar file. + * Unfortunately, there does not appear to be a macro for the class loader keywords + * Matt Ho - Mon Mar 17 00:21:46 PST 2003 + */ + p.setProperty("strutsclass.resource.loader.description", "Velocity Classpath Resource Loader"); + p.setProperty("strutsclass.resource.loader.class", "org.apache.struts2.views.velocity.StrutsResourceLoader"); + p.setProperty("strutsclass.resource.loader.modificationCheckInterval", "2"); + p.setProperty("strutsclass.resource.loader.cache", "true"); + + // components + StringBuilder sb = new StringBuilder(); + + for (TagLibraryDirectiveProvider tagLibrary : tagLibraries) { + List directives = tagLibrary.getDirectiveClasses(); + for (Class directive : directives) { + addDirective(sb, directive); + } + } + + for (TagLibrary tagLibrary : oldTagLibraries) { + List directives = tagLibrary.getVelocityDirectiveClasses(); + for (Class directive : directives) { + addDirective(sb, directive); + } + } + + String directives = sb.toString(); + + String userdirective = p.getProperty("userdirective"); + if ((userdirective == null) || userdirective.trim().equals("")) { + userdirective = directives; + } else { + userdirective = userdirective.trim() + "," + directives; + } + + p.setProperty("userdirective", userdirective); + } + + private void addDirective(StringBuilder sb, Class clazz) { + sb.append(clazz.getName()).append(","); + } + + /** + * @return the velocityProperties + */ + public Properties getVelocityProperties() { + return velocityProperties; + } + + /** + * @param velocityProperties the velocityProperties to set + */ + public void setVelocityProperties(Properties velocityProperties) { + this.velocityProperties = velocityProperties; + } +} diff --git a/src/main/resources/com/taobao/rigel/rap/account/applicationContext.xml b/src/main/resources/com/taobao/rigel/rap/account/applicationContext.xml new file mode 100644 index 000000000..9696f8505 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/account/applicationContext.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/account/mapping/Notification.hbm.xml b/src/main/resources/com/taobao/rigel/rap/account/mapping/Notification.hbm.xml new file mode 100644 index 000000000..fd20174d1 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/account/mapping/Notification.hbm.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + 项目相关ID + + + + + 项目相关ID + + + + + 创建时间 + + + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/account/mapping/Role.hbm.xml b/src/main/resources/com/taobao/rigel/rap/account/mapping/Role.hbm.xml new file mode 100644 index 000000000..6f9276cc7 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/account/mapping/Role.hbm.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/account/mapping/User.hbm.xml b/src/main/resources/com/taobao/rigel/rap/account/mapping/User.hbm.xml new file mode 100644 index 000000000..f927bcbab --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/account/mapping/User.hbm.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + 工号 + + + + + + + + + 是否启用提示 + + + + + 创建时间 + + + + + 最近登录时间 + + + + + 锁定状态 + + + + + 错误登录次数 + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/account/web/action/struts.xml b/src/main/resources/com/taobao/rigel/rap/account/web/action/struts.xml new file mode 100644 index 000000000..d325d3abf --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/account/web/action/struts.xml @@ -0,0 +1,86 @@ + + + + + + /bcom/json.cb.vm + + + /account/login.vm + + + /bcom/json.cb.vm + + + + index + /org + + /account/login.vm + + + /platform/home.vm + + + /account/register.vm + + + /platform/home.vm + /account/register.vm + + + /account/myAccount.vm + /account/login.vm + + + /account/mySetting.vm + /account/login.vm + + + + /account/myAccount.vm + + + /account/myAccount.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + + + /bcom/json.cb.vm + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/api/applicationContext.xml b/src/main/resources/com/taobao/rigel/rap/api/applicationContext.xml new file mode 100644 index 000000000..c639bf15f --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/api/applicationContext.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/api/web/action/struts.xml b/src/main/resources/com/taobao/rigel/rap/api/web/action/struts.xml new file mode 100644 index 000000000..c3dc54ccc --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/api/web/action/struts.xml @@ -0,0 +1,31 @@ + + + + + + + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + diff --git a/src/main/resources/com/taobao/rigel/rap/common/applicationContext.xml b/src/main/resources/com/taobao/rigel/rap/common/applicationContext.xml new file mode 100644 index 000000000..a0dc63f47 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/common/applicationContext.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/mock/applicationContext.xml b/src/main/resources/com/taobao/rigel/rap/mock/applicationContext.xml new file mode 100644 index 000000000..96e1e3661 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/mock/applicationContext.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/mock/mapping/Rule.hbm.xml b/src/main/resources/com/taobao/rigel/rap/mock/mapping/Rule.hbm.xml new file mode 100644 index 000000000..41e658f5d --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/mock/mapping/Rule.hbm.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/mock/web/action/struts.xml b/src/main/resources/com/taobao/rigel/rap/mock/web/action/struts.xml new file mode 100644 index 000000000..c5cde8941 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/mock/web/action/struts.xml @@ -0,0 +1,139 @@ + + + + + + + + + + /bcom/isOkWithNum.cb.vm + + + + + /bcom/isOkWithNum.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + + + text/javascript + /mock/createPluginScript.vm + + + + + /bcom/json.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + + + + /bcom/contentWithoutEscape.cb.vm + + /bcom/contentWithoutEscape.cb.vm + + + application/json + /bcom/contentWithoutEscape.cb.vm + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/organization/applicationContext.xml b/src/main/resources/com/taobao/rigel/rap/organization/applicationContext.xml new file mode 100644 index 000000000..fb2e1262d --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/organization/applicationContext.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/organization/mapping/Corporation.hbm.xml b/src/main/resources/com/taobao/rigel/rap/organization/mapping/Corporation.hbm.xml new file mode 100644 index 000000000..b8872873f --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/organization/mapping/Corporation.hbm.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + creator id + + + + + + + + access type + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/organization/mapping/Group.hbm.xml b/src/main/resources/com/taobao/rigel/rap/organization/mapping/Group.hbm.xml new file mode 100644 index 000000000..692296fee --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/organization/mapping/Group.hbm.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/organization/mapping/ProductionLine.hbm.xml b/src/main/resources/com/taobao/rigel/rap/organization/mapping/ProductionLine.hbm.xml new file mode 100644 index 000000000..a65047078 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/organization/mapping/ProductionLine.hbm.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/organization/web/action/struts.xml b/src/main/resources/com/taobao/rigel/rap/organization/web/action/struts.xml new file mode 100644 index 000000000..bc6d6d7b3 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/organization/web/action/struts.xml @@ -0,0 +1,89 @@ + + + + + + + + /org/home/index.vm + /platform/home.vm + + + /bcom/json.cb.vm + + + /org/group/index.vm + + + /org/productline/index.vm + + + + + + /bcom/json.cb.vm + + + /org/team/teams.vm + + + /org/team/manage.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/platform/applicationContext.xml b/src/main/resources/com/taobao/rigel/rap/platform/applicationContext.xml new file mode 100644 index 000000000..00546a7c4 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/platform/applicationContext.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/platform/web/action/struts.xml b/src/main/resources/com/taobao/rigel/rap/platform/web/action/struts.xml new file mode 100644 index 000000000..93e79b8cd --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/platform/web/action/struts.xml @@ -0,0 +1,27 @@ + + + + + + /platform/home.vm + + + /platform/test.vm + + + /platform/log.vm + + + /platform/teamLog.vm + + + /platform/monitor.vm + + + /bcom/json.cb.vm + + + diff --git a/src/main/resources/com/taobao/rigel/rap/project/applicationContext.xml b/src/main/resources/com/taobao/rigel/rap/project/applicationContext.xml new file mode 100644 index 000000000..898a55ecd --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/project/applicationContext.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/project/mapping/Action.hbm.xml b/src/main/resources/com/taobao/rigel/rap/project/mapping/Action.hbm.xml new file mode 100644 index 000000000..772179306 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/project/mapping/Action.hbm.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/project/mapping/Module.hbm.xml b/src/main/resources/com/taobao/rigel/rap/project/mapping/Module.hbm.xml new file mode 100644 index 000000000..e0f568f4b --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/project/mapping/Module.hbm.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/project/mapping/Page.hbm.xml b/src/main/resources/com/taobao/rigel/rap/project/mapping/Page.hbm.xml new file mode 100644 index 000000000..215c26182 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/project/mapping/Page.hbm.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/project/mapping/Parameter.hbm.xml b/src/main/resources/com/taobao/rigel/rap/project/mapping/Parameter.hbm.xml new file mode 100644 index 000000000..3271bafdc --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/project/mapping/Parameter.hbm.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/project/mapping/Project.hbm.xml b/src/main/resources/com/taobao/rigel/rap/project/mapping/Project.hbm.xml new file mode 100644 index 000000000..f6f23fe76 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/project/mapping/Project.hbm.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + 项目名称 + + + + + 项目相关ID + + + + + 分组ID + + + + + MOCK调用次数 + + + + + 当前版本 + + + + + 创建时间 + + + + + 更新时间 + + + + + 项目简介 + + + + + 共享模式 + + + + + 项目数据(json),用于VSS同步模式 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/project/web/action/struts.xml b/src/main/resources/com/taobao/rigel/rap/project/web/action/struts.xml new file mode 100644 index 000000000..66f82a312 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/project/web/action/struts.xml @@ -0,0 +1,37 @@ + + + + + + + + + /bcom/json.cb.vm + + + + /bcom/json.cb.vm + + + + /bcom/json.cb.vm + + + + /bcom/json.cb.vm + + + + /bcom/json.cb.vm + + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/tester/web/action/struts.xml b/src/main/resources/com/taobao/rigel/rap/tester/web/action/struts.xml new file mode 100644 index 000000000..2bdaaf642 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/tester/web/action/struts.xml @@ -0,0 +1,23 @@ + + + + + + + + /tester/pageTester.vm + + + /bcom/isOk.cb.vm + + + /bcom/content.cb.vm + + + + diff --git a/src/main/resources/com/taobao/rigel/rap/workspace/applicationContext.xml b/src/main/resources/com/taobao/rigel/rap/workspace/applicationContext.xml new file mode 100644 index 000000000..01e963521 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/workspace/applicationContext.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + resource.loader=class + class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/workspace/mapping/CheckIn.hbm.xml b/src/main/resources/com/taobao/rigel/rap/workspace/mapping/CheckIn.hbm.xml new file mode 100644 index 000000000..7a641c0bc --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/workspace/mapping/CheckIn.hbm.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/workspace/mapping/Workspace.hbm.xml b/src/main/resources/com/taobao/rigel/rap/workspace/mapping/Workspace.hbm.xml new file mode 100644 index 000000000..19d12b1f9 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/workspace/mapping/Workspace.hbm.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/com/taobao/rigel/rap/workspace/web/action/struts.xml b/src/main/resources/com/taobao/rigel/rap/workspace/web/action/struts.xml new file mode 100644 index 000000000..74771d937 --- /dev/null +++ b/src/main/resources/com/taobao/rigel/rap/workspace/web/action/struts.xml @@ -0,0 +1,70 @@ + + + + + + + + + /workspace/myWorkspace.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + + /bcom/json.cb.vm + + + /bcom/json.cb.vm + + + + /bcom/json.cb.vm + + + + attachment;filename=export.html + text/html + fileInputStream + 1024 + + + + + diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties new file mode 100644 index 000000000..34dc238a0 --- /dev/null +++ b/src/main/resources/config.properties @@ -0,0 +1,9 @@ +jdbc.driverClassName=com.mysql.jdbc.Driver +jdbc.url=jdbc\:mysql\://localhost\:3306/rap_db?useUnicode\=true&characterEncoding\=utf8&zeroDateTimeBehavior\=convertToNull&noAccessToProcedureBodies\=true +jdbc.username=root +jdbc.password= +redis.host=localhost +redis.port=6379 +redis.timeout=2000 +redis.password= +redis.database=0 \ No newline at end of file diff --git a/src/main/resources/database/initialize.sql b/src/main/resources/database/initialize.sql new file mode 100644 index 000000000..1cd841956 --- /dev/null +++ b/src/main/resources/database/initialize.sql @@ -0,0 +1,562 @@ +CREATE DATABASE IF NOT EXISTS rap_db + DEFAULT CHARSET utf8 + COLLATE utf8_general_ci; + +USE rap_db; + + +/************************************************** + * * + * account module * + * * + **************************************************/ + + +/** + * user table + */ +CREATE TABLE tb_user +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + account VARCHAR(32) NOT NULL + COMMENT '账户名 account name', + password VARCHAR(128) NOT NULL + COMMENT '密码 password', + name VARCHAR(256) NOT NULL + COMMENT '名字/昵称 name/nickname', + email VARCHAR(256) NOT NULL + COMMENT 'email', + create_date TIMESTAMP NOT NULL + COMMENT '创建日期 create date' + DEFAULT now(), + is_locked_out INT(1) NOT NULL + COMMENT '用户是否锁定 is the user locked out' + DEFAULT 0, + is_hint_enabled INT(1) NOT NULL + COMMENT '是否开启新手引导 is user hint enabled' + DEFAULT 1, + last_login_date DATETIME NOT NULL + COMMENT '最近登录 last login date', + incorrect_login_attempt INT(10) NOT NULL + COMMENT '错误登录次数,登录成功后会重置为0 count of incorrect login attempts, will be set to 0 after any succesful login' + DEFAULT 0, + realname VARCHAR(128) NOT NULL + COMMENT '真实姓名' + DEFAULT '', + emp_id VARCHAR(45) NULL + COMMENT '工号,可选', + mock_num INT(10) NOT NULL + COMMENT 'mock次数,用于记录该用户所创建的接口被调用的mock次数。 mock num, used for record mock API invokation count' + DEFAULT 0 +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * role table + * roles instruction: + * user - every registered shuold have this role + * rd - research and development engineering + * qa - quality engineering + * pm - project manager + * op - operation manager + * admin - administrator + * god - super admin + */ +CREATE TABLE tb_role +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + name VARCHAR(16) NOT NULL + COMMENT '角色名称 role name' +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * user role table + */ +CREATE TABLE tb_role_and_user +( + user_id INT(10) NOT NULL, + role_id INT(10) NOT NULL, + + PRIMARY KEY (user_id, role_id), + FOREIGN KEY (user_id) REFERENCES tb_user (id), + FOREIGN KEY (role_id) REFERENCES tb_role (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + + +/************************************************** + * * + * project module * + * * + **************************************************/ + + + +/** + * parameter table + */ +CREATE TABLE tb_parameter +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + name VARCHAR(256) NULL + COMMENT '参数含义 parameter name', + identifier VARCHAR(256) NULL + COMMENT '变量名/参数标识符 parameter identifier', + data_type VARCHAR(32) NULL + COMMENT '数据类型 data type', + remark TEXT NULL + COMMENT '备注/mock数据等 remark/mock data', + expression VARCHAR(128) NULL + COMMENT '备用字段:表达式 backup column:expression', + mock_data TEXT NULL + COMMENT '备用字段:mock数据 backup column:mock data' +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * project table + * workspace_mode 1-vss(default) 2-svn + * stage 1-design 2-developing 3-debug + */ +CREATE TABLE tb_project +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + `version` VARCHAR(128) NOT NULL + COMMENT '版本号 version no.' + DEFAULT '0.0.0.1', + name VARCHAR(128) NOT NULL + COMMENT '项目名称 project name', + create_date TIMESTAMP NOT NULL + COMMENT '创建日期 create date' + DEFAULT now(), + user_id INT(10) NOT NULL + COMMENT '创建人ID, project author id', + introduction TEXT NULL + COMMENT '项目描述 project introduction', + workspace_mode INT(10) NOT NULL + COMMENT '工作区提交模式(类VSS or SVN),暂时弃用了。 Workspace submit mode, deprecated.' + DEFAULT 1, + stage INT(10) NOT NULL + COMMENT '项目阶段,暂时废弃;project stage, temply deprecated. 1-design 2-developing 3-debug' + DEFAULT 1, + project_data LONGTEXT NULL + COMMENT '项目JSON数据,存放当前最新的版本。 project JSON data, saved the newest version of the project', + group_id INT(10) NULL + COMMENT '分组ID group id', + related_ids VARCHAR(128) NOT NULL + COMMENT '路由ID,用于指定与哪些项目共享mock数据; router id, used for specify sharing data with which projects.' + DEFAULT '', + update_time DATETIME NOT NULL + COMMENT '更新时间 update time', + mock_num INT NOT NULL + COMMENT 'mock次数 mock num' + DEFAULT 0, + access_type TINYINT NOT NULL + COMMENT '权限控制, 10普通, 0私有' + DEFAULT 10, + + FOREIGN KEY (user_id) REFERENCES tb_user (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * user list and user table + * used for creating multiple to multiple mapping + * access_level: + * 1 - read + * 2 - read&write + * 3 - read&write&manage + */ +CREATE TABLE tb_project_and_user +( + project_id INT(10) NOT NULL, + user_id INT(10) NOT NULL, + access_level INT NOT NULL + DEFAULT 1, + + PRIMARY KEY (project_id, user_id), + FOREIGN KEY (project_id) REFERENCES tb_project (id), + FOREIGN KEY (user_id) REFERENCES tb_user (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * module table + */ +CREATE TABLE tb_module +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + project_id INT(10) NOT NULL, + name VARCHAR(256) NOT NULL, + introduction VARCHAR(128) NULL, + + FOREIGN KEY (project_id) REFERENCES tb_project (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * page table + */ +CREATE TABLE tb_page +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + name VARCHAR(56) NOT NULL, + module_id INT(10) NOT NULL, + introduction TEXT NULL, + template VARCHAR(128) NULL, + + FOREIGN KEY (module_id) REFERENCES tb_module (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * action table + * request_type: + * 1 - get + * 2 - post + * 3 - ajax get + * 4 - ajax post + */ +CREATE TABLE tb_action +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + name VARCHAR(256) NOT NULL, + description TEXT NULL, + + /* request block */ + request_type INT NOT NULL + COMMENT '请求类型get/post/put/delete等等 request type' + DEFAULT 1, /** request_type = 99, mount type **/ + request_url TEXT NULL, + + disable_cache TINYINT NOT NULL + COMMENT '禁用Mock缓存 disable mock cache' + DEFAULT 0, + + /* response block */ + response_template TEXT NULL + COMMENT '响应模板地址, 暂时弃用。 response template address, temply deprecated.' + +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * action and page table + * used for creating multiple to multiple mapping + */ +CREATE TABLE tb_action_and_page +( + action_id INT(10) NOT NULL, + page_id INT(10) NOT NULL, + + FOREIGN KEY (action_id) REFERENCES tb_action (id), + FOREIGN KEY (page_id) REFERENCES tb_page (id), + PRIMARY KEY (action_id, page_id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + + +/** + * parameter and parameter mapping + * complex_parameter has so many parameters(List or Map) + */ +CREATE TABLE tb_complex_parameter_list_mapping +( + complex_parameter_id INT(10) NOT NULL, + parameter_id INT(10) NOT NULL, + + PRIMARY KEY (complex_parameter_id, parameter_id), + FOREIGN KEY (complex_parameter_id) REFERENCES tb_parameter (id), + FOREIGN KEY (parameter_id) REFERENCES tb_parameter (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * parameter and action's request mapping + */ +CREATE TABLE tb_request_parameter_list_mapping +( + action_id INT(10) NOT NULL, + parameter_id INT(10) NOT NULL, + + PRIMARY KEY (action_id, parameter_id), + FOREIGN KEY (action_id) REFERENCES tb_action (id), + FOREIGN KEY (parameter_id) REFERENCES tb_parameter (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * parameter and action's response mapping + */ +CREATE TABLE tb_response_parameter_list_mapping +( + action_id INT(10) NOT NULL, + parameter_id INT(10) NOT NULL, + + PRIMARY KEY (action_id, parameter_id), + FOREIGN KEY (action_id) REFERENCES tb_action (id), + FOREIGN KEY (parameter_id) REFERENCES tb_parameter (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + + +/************************************************** + * * + * workspace module * + * * + **************************************************/ + + +/** + * workspace, deprecated 工作区,暂时未使用 + */ +CREATE TABLE tb_workspace +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + project_id INT(10) NOT NULL, + user_id INT NOT NULL, + create_date TIMESTAMP NOT NULL + DEFAULT now(), + update_date DATETIME NOT NULL, + project_data LONGTEXT NOT NULL, + project_data_original LONGTEXT NOT NULL, + + FOREIGN KEY (project_id) REFERENCES tb_project (id), + FOREIGN KEY (user_id) REFERENCES tb_user (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * workspace save, deprecated 工作区保存草稿,暂时未使用 + */ +CREATE TABLE tb_workspace_save +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + workspace_id INT(10) NOT NULL, + update_date DATETIME NOT NULL, + project_data LONGTEXT NOT NULL, + + FOREIGN KEY (workspace_id) REFERENCES tb_workspace (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * check in table + * every API document submit saved here, used for version control. + * 每一次提交记录在这里,用于版本管理和回滚控制 + * workspaceMode 1-VSS 2-SVN + */ +CREATE TABLE tb_check_in +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + create_date TIMESTAMP NOT NULL + DEFAULT now(), + tag VARCHAR(128) NULL + COMMENT 'tag标签 暂时未使用 deprecated', + user_id INT(10) NOT NULL + COMMENT '提交人 submit user id', + project_id INT(10) NOT NULL + COMMENT '提交的项目ID submit project id', + description TEXT NULL + COMMENT '提交描述 submit description', + version VARCHAR(128) NOT NULL + COMMENT '版本号 version no.', + project_data LONGTEXT NOT NULL + COMMENT '项目JSON数据 project json data', + workspace_mode INT(10) NOT NULL + COMMENT '工作区模式(弃用) workspace mode(deprecated)', + log TEXT NULL + COMMENT '更新日志,用于存储与最近一个版本的对比差异。暂时未使用。update log, used for calculate versions differences. Deprecated.', + + FOREIGN KEY (user_id) REFERENCES tb_user (id), + FOREIGN KEY (project_id) REFERENCES tb_project (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * user settings table + * 用户配置表 + */ +CREATE TABLE tb_user_settings +( + user_id INT(10) NOT NULL, + `key` VARCHAR(128) NOT NULL + COMMENT '配置KEY config key', + `value` VARCHAR(128) NOT NULL + COMMENT '配置VALUE config value', + + PRIMARY KEY (user_id, `key`), + FOREIGN KEY (user_id) REFERENCES tb_user (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * user notification table + * 用户通知表 + */ + +CREATE TABLE tb_notification +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + user_id INT(10) NOT NULL + COMMENT '接受通知的用户id; user id to be notified.', + target_user_id INT(10) NOT NULL + COMMENT '上下文用户id; context user id', + type_id SMALLINT NOT NULL + COMMENT '1-文档修改,2-被加入新项目', + param1 VARCHAR(128) NULL + COMMENT '1,2-项目id', + param2 VARCHAR(128) NULL + COMMENT ' 1,2-项目名称', + param3 TEXT NULL + COMMENT '备用预留 reserved', + create_time TIMESTAMP NOT NULL + COMMENT '创建时间 create time' + DEFAULT now(), + + is_read SMALLINT NOT NULL + COMMENT '是否已读 is notification read' + DEFAULT 0, + + FOREIGN KEY (user_id) REFERENCES tb_user (id), + FOREIGN KEY (target_user_id) REFERENCES tb_user (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * corporation table + * 公司表 + */ +CREATE TABLE tb_corporation +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + name VARCHAR(256) NOT NULL, + logo_url VARCHAR(256) NULL, + user_id INT(10) NULL, + access_type TINYINT NOT NULL + COMMENT '权限控制, 10普通, 20公开' + DEFAULT 10, + `desc` TEXT NOT NULL + COMMENT '备注', + + FOREIGN KEY (user_id) REFERENCES tb_user (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + + +/** + * product line table + * 生产线表 + */ +CREATE TABLE tb_production_line +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + name VARCHAR(256) NOT NULL, + project_num INT(10) NOT NULL + DEFAULT 0, + corporation_id INT(10) NOT NULL, + user_id INT(10) NOT NULL, + + FOREIGN KEY (user_id) REFERENCES tb_user (id), + FOREIGN KEY (corporation_id) REFERENCES tb_corporation (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * project group table + * 项目分组表 + */ +CREATE TABLE tb_group +( + id INT(10) AUTO_INCREMENT NOT NULL + PRIMARY KEY, + name VARCHAR(256) NOT NULL, + production_line_id INT(10) NOT NULL, + user_id INT(10) NOT NULL, + + FOREIGN KEY (user_id) REFERENCES tb_user (id), + FOREIGN KEY (production_line_id) REFERENCES tb_production_line (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +/** + * 规则表,存储通过Open API设置的Mock规则 + * Stored mock rules set by Open API + */ +CREATE TABLE tb_rule ( + action_id INT(10) NOT NULL + PRIMARY KEY, + rules TEXT NOT NULL, -- JSON规则 + update_time DATETIME NOT NULL + DEFAULT NOW(), -- 最近更新时间 + + FOREIGN KEY (action_id) REFERENCES tb_action (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +CREATE TABLE tb_corporation_and_user +( + user_id INT(10) NOT NULL, + corporation_id INT(10) NOT NULL, + role_id INT(10) NOT NULL, + + PRIMARY KEY (user_id, corporation_id), + FOREIGN KEY (user_id) REFERENCES tb_user (id), + FOREIGN KEY (corporation_id) REFERENCES tb_corporation (id), + FOREIGN KEY (role_id) REFERENCES tb_role (id) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8; + + +-- required base data +INSERT INTO tb_role (name) VALUES ('god'); +INSERT INTO tb_role (name) VALUES ('admin'); +INSERT INTO tb_role (name) VALUES ('user'); +-- removed unused qa/pm/rd roles + + +INSERT INTO tb_user (account, password, email, create_date, last_login_date, name) VALUES + ('admin', 'RESERVED', 'admin@example.com', NOW(), NOW(), 'admin'); + +INSERT INTO tb_role_and_user (user_id, role_id) VALUES (1, 1); + +-- INSERT INTO tb_corporation (name, logo_url, user_id) VALUES ('MyTeam', 'empty', 1); +-- 新版RAP可以自建团队,不需要插入默认团队了。 +-- RAP v0.11.5+ users can create teams by their own, so there's no need to set default team. diff --git a/src/main/resources/database/scripts.sql b/src/main/resources/database/scripts.sql new file mode 100644 index 000000000..3f0e58923 --- /dev/null +++ b/src/main/resources/database/scripts.sql @@ -0,0 +1,56 @@ +-- recent projects + +SELECT + p.name projectName, + u.name userName, + p.create_date projectCreateTime, + p.introduction +FROM tb_project p + JOIN tb_user u ON p.user_id = u.id +ORDER BY p.id DESC + +-- recent users + +SELECT * +FROM tb_user +ORDER BY id DESC + +-- counters +SELECT COUNT(*) userNum +FROM tb_user; +SELECT COUNT(*) projectNum +FROM tb_project; + + +-- counting projects (actions >= 5) +SELECT + p.id, + p.name, + COUNT(a.id) +FROM tb_project p + JOIN tb_module m ON m.project_id = p.id + JOIN tb_page p2 ON p2.module_id = m.id + JOIN tb_action_and_page ap ON ap.page_id = p2.id + JOIN tb_action a ON a.id = ap.action_id +GROUP BY p.id +HAVING COUNT(a.id) > 5 +ORDER BY count(a.id) DESC + + +-- search request_url +SELECT + a.name actionName, + m.project_id projectId +FROM tb_action a + JOIN tb_action_and_page ap ON ap.action_id = a.id + JOIN tb_page p ON p.id = ap.page_id + JOIN tb_module m ON m.id = p.module_id +WHERE request_url LIKE '%key%' + +-- search organization info by projectId +SELECT CONCAT(c.name, '-', pl.name, '-', g.name, '-', p.name) AS info +FROM tb_project p + JOIN tb_group g ON g.id = p.group_id + JOIN tb_production_line pl ON pl.id = g.production_line_id + JOIN tb_corporation c ON c.id = pl.corporation_id +WHERE p.id = {projectId} \ No newline at end of file diff --git a/src/main/resources/database/v0.11.0_to_v0.11.1.sql b/src/main/resources/database/v0.11.0_to_v0.11.1.sql new file mode 100644 index 000000000..9033403fc --- /dev/null +++ b/src/main/resources/database/v0.11.0_to_v0.11.1.sql @@ -0,0 +1,11 @@ +USE rap_db; + +-- 缓存优化,智能判断接口是否应用缓存 +ALTER TABLE tb_action +ADD COLUMN disable_cache TINYINT NOT NULL + DEFAULT 0; + +-- 默认先全部disable_cache +UPDATE tb_action +SET disable_cache = 1 +WHERE id != 0 \ No newline at end of file diff --git a/src/main/resources/ehcache.xml b/src/main/resources/ehcache.xml new file mode 100644 index 000000000..7456841eb --- /dev/null +++ b/src/main/resources/ehcache.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/resources/hibernate.cfg.xml b/src/main/resources/hibernate.cfg.xml new file mode 100644 index 000000000..ca77d66a4 --- /dev/null +++ b/src/main/resources/hibernate.cfg.xml @@ -0,0 +1,141 @@ + + + + + + + *Mgr + *Service + *Proxy + + + + + transactionInterceptor + + + + + + + + + + + + + + + + + classpath:/config.properties + + + + + + + ${jdbc.driverClassName} + + + ${jdbc.url} + + + ${jdbc.username} + + + ${jdbc.password} + + + 5 + + + 100 + + + 10 + + + 60 + + + 60 + + + 5 + + + 0 + + + 1000 + + + 30 + + + true + + + + + + + + com/taobao/rigel/rap/project/mapping/Project.hbm.xml + com/taobao/rigel/rap/project/mapping/Module.hbm.xml + com/taobao/rigel/rap/project/mapping/Page.hbm.xml + com/taobao/rigel/rap/project/mapping/Action.hbm.xml + com/taobao/rigel/rap/project/mapping/Parameter.hbm.xml + com/taobao/rigel/rap/account/mapping/User.hbm.xml + com/taobao/rigel/rap/account/mapping/Role.hbm.xml + com/taobao/rigel/rap/account/mapping/Notification.hbm.xml + com/taobao/rigel/rap/workspace/mapping/Workspace.hbm.xml + com/taobao/rigel/rap/workspace/mapping/CheckIn.hbm.xml + com/taobao/rigel/rap/organization/mapping/Corporation.hbm.xml + com/taobao/rigel/rap/organization/mapping/Group.hbm.xml + com/taobao/rigel/rap/organization/mapping/ProductionLine.hbm.xml + com/taobao/rigel/rap/mock/mapping/Rule.hbm.xml + + + + + + org.hibernate.dialect.MySQLDialect + false + false + true + + + + + + + + + + + + + + + + + + + + + + + + + PROPAGATION_REQUIRED + + + + + diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 000000000..d01936843 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/resource/export.vm b/src/main/resources/resource/export.vm new file mode 100644 index 000000000..3fe01490f --- /dev/null +++ b/src/main/resources/resource/export.vm @@ -0,0 +1,142 @@ + + + + + + + + +
    + #foreach($module in $project.moduleListOrdered) + #set($moduleNo = $velocityCount) +
    +

    $moduleNo $module.name

    + #foreach($page in $module.pageListOrdered) + #set($pageNo = $velocityCount) +
    +

    $moduleNo.$pageNo $page.name

    + #foreach($action in $page.actionListOrdered) + #set($actionNo = $velocityCount) +
    +

    $moduleNo.$pageNo.$actionNo $action.name

    + +

    URL

    +
    $action.requestUrl
    + +

    Method

    +
    $action.getMethod()
    + +

    Description

    +
    $action.description
    + +

    Request Param List

    + $action.requestParameterListHTML + +

    Response Param List

    + $action.responseParameterListHTML +
    + #end +
    + #end +
    + #end +
    + + diff --git a/src/struts.properties b/src/main/resources/struts.properties similarity index 92% rename from src/struts.properties rename to src/main/resources/struts.properties index b03972034..62e2ed71f 100644 --- a/src/struts.properties +++ b/src/main/resources/struts.properties @@ -1,10 +1,10 @@ -struts.objectFactory = spring -struts.locale=zh_CN -struts.enable.DynamicMethodInvocation=true -struts.devMode=true -struts.configuration.xml.reload=false -struts.custom.i18n.resources=ApplicationResources -struts.il8n.reload=true -struts.i18n.encoding=UTF-8 -struts.velocity.configfile = /WEB-INF/velocity.properties +struts.objectFactory = spring +struts.locale=zh_CN +struts.enable.DynamicMethodInvocation=true +struts.devMode=false +struts.configuration.xml.reload=false +struts.custom.i18n.resources=ApplicationResources +struts.il8n.reload=true +struts.i18n.encoding=UTF-8 +struts.velocity.configfile = /WEB-INF/velocity.properties struts.velocity.toolboxlocation =/WEB-INF/toolbox.xml \ No newline at end of file diff --git a/src/main/resources/struts.xml b/src/main/resources/struts.xml new file mode 100644 index 000000000..2ba82db3e --- /dev/null +++ b/src/main/resources/struts.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + true + ERROR + + + + + + + /account/login.vm + /error.vm + /error.vm + /bcom/jsonError.cb.vm + /error.vm + /common/redirect.vm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WebContent/META-INF/MANIFEST.MF b/src/main/webapp/META-INF/MANIFEST.MF similarity index 100% rename from WebContent/META-INF/MANIFEST.MF rename to src/main/webapp/META-INF/MANIFEST.MF diff --git a/src/main/webapp/WEB-INF/lib/buc.sso.client-0.3.9.jar b/src/main/webapp/WEB-INF/lib/buc.sso.client-0.3.9.jar new file mode 100644 index 000000000..4e5dcd78c Binary files /dev/null and b/src/main/webapp/WEB-INF/lib/buc.sso.client-0.3.9.jar differ diff --git a/src/main/webapp/WEB-INF/lib/buc.sso.common-0.3.9.jar b/src/main/webapp/WEB-INF/lib/buc.sso.common-0.3.9.jar new file mode 100644 index 000000000..5a976cac7 Binary files /dev/null and b/src/main/webapp/WEB-INF/lib/buc.sso.common-0.3.9.jar differ diff --git a/src/main/webapp/WEB-INF/lib/kaptcha-2.3.jar b/src/main/webapp/WEB-INF/lib/kaptcha-2.3.jar new file mode 100644 index 000000000..995d2aa7c Binary files /dev/null and b/src/main/webapp/WEB-INF/lib/kaptcha-2.3.jar differ diff --git a/WebContent/WEB-INF/lib/xeger-1.0-SNAPSHOT.jar b/src/main/webapp/WEB-INF/lib/xeger-1.0-SNAPSHOT.jar similarity index 100% rename from WebContent/WEB-INF/lib/xeger-1.0-SNAPSHOT.jar rename to src/main/webapp/WEB-INF/lib/xeger-1.0-SNAPSHOT.jar diff --git a/src/main/webapp/WEB-INF/toolbox.xml b/src/main/webapp/WEB-INF/toolbox.xml new file mode 100644 index 000000000..4f442aa93 --- /dev/null +++ b/src/main/webapp/WEB-INF/toolbox.xml @@ -0,0 +1,23 @@ + + + + utils + application + com.taobao.rigel.rap.common.utils.StringUtils + + + dateUtils + application + com.taobao.rigel.rap.common.utils.DateUtils + + + consts + application + com.taobao.rigel.rap.common.config.SystemConstant + + + logger + application + com.taobao.rigel.rap.common.utils.SystemVisitorLog + + diff --git a/src/main/webapp/WEB-INF/urlrewrite.xml b/src/main/webapp/WEB-INF/urlrewrite.xml new file mode 100644 index 000000000..63f53a82b --- /dev/null +++ b/src/main/webapp/WEB-INF/urlrewrite.xml @@ -0,0 +1,79 @@ + + + + + + mock service + + ^/mock/(\d*?)/(.*)$ + /mock/createData.action?__id__=$1&pattern=/${escape:utf8:$2} + * + Origin, X-Requested-With, Content-Type, Accept + + + + + mockjs service + + ^/mockjs/(\d*?)/(.*)$ + /mock/createRule.action?__id__=$1&pattern=/${escape:utf8:$2} + * + Origin, X-Requested-With, Content-Type, Accept + + + + + mockjs auto service, use mock rules set by Open API + + ^/mockjsauto/(\d*?)/(.*)$ + /mock/createRuleAuto.action?__id__=$1&pattern=/${escape:utf8:$2} + * + Origin, X-Requested-With, Content-Type, Accept + + + + + mockjs result service + + ^/mockjsdata/(\d*?)/(.*)$ + /mock/createMockjsData.action?__id__=$1&pattern=/${escape:utf8:$2} + * + Origin, X-Requested-With, Content-Type, Accept + + + + + mockjs result service + + ^/mockjsdataauto/(\d*?)/(.*)$ + /mock/createMockjsDataAuto.action?__id__=$1&pattern=/${escape:utf8:$2} + * + Origin, X-Requested-With, Content-Type, Accept + + + + + validation API + + ^/validate/(\d*?)/(.*)$ + /mock/validateAPI.action?__id__=$1&pattern=/${escape:utf8:$2} + * + Origin, X-Requested-With, Content-Type, Accept + + + + + mockjs plugin generator + + ^/rap.plugin.js(.*)$ + /mock/createPluginScript.action$1 + + + + node doc service + + ^/doc/(\d*)$ + http://localhost:7429/doc/$1.html + + \ No newline at end of file diff --git a/WebContent/WEB-INF/velocity.properties b/src/main/webapp/WEB-INF/velocity.properties similarity index 94% rename from WebContent/WEB-INF/velocity.properties rename to src/main/webapp/WEB-INF/velocity.properties index 4bccf81b8..92631596f 100644 --- a/WebContent/WEB-INF/velocity.properties +++ b/src/main/webapp/WEB-INF/velocity.properties @@ -1,116 +1,118 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -# ---------------------------------------------------------------------------- -# These are the default properties for the -# Velocity Runtime. These values are used when -# Runtime.init() is called, and when Runtime.init(properties) -# fails to find the specificed properties file. -# ---------------------------------------------------------------------------- - - -# ---------------------------------------------------------------------------- -# R U N T I M E L O G -# ---------------------------------------------------------------------------- -# Velocity uses the Servlet APIs logging facilites. - -# ---------------------------------------------------------------------------- -# This controls if Runtime.error(), info() and warn() messages include the -# whole stack trace. The last property controls whether invalid references -# are logged. -# ---------------------------------------------------------------------------- - -runtime.log.invalid.reference = false - - -# ---------------------------------------------------------------------------- -# T E M P L A T E E N C O D I N G -# ---------------------------------------------------------------------------- -#default.encoding=utf-8 -input.encoding=utf-8 -output.encoding=utf-8 -default.contenttype=text/html;charset=utf-8 -# ---------------------------------------------------------------------------- -# F O R E A C H P R O P E R T I E S -# ---------------------------------------------------------------------------- -# These properties control how the counter is accessed in the #foreach -# directive. By default the reference $velocityCount will be available -# in the body of the #foreach directive. The default starting value -# for this reference is 1. -# ---------------------------------------------------------------------------- - -directive.foreach.counter.name = velocityCount -directive.foreach.counter.initial.value = 1 - - -# ---------------------------------------------------------------------------- -# I N C L U D E P R O P E R T I E S -# ---------------------------------------------------------------------------- -# These are the properties that governed the way #include'd content -# is governed. -# ---------------------------------------------------------------------------- - -directive.include.output.errormsg.start = - - -# ---------------------------------------------------------------------------- -# P A R S E P R O P E R T I E S -# ---------------------------------------------------------------------------- - -directive.parse.max.depth = 10 - - -# ---------------------------------------------------------------------------- -# VELOCIMACRO PROPERTIES -# ---------------------------------------------------------------------------- -# global : name of default global library. It is expected to be in the regular -# template path. You may remove it (either the file or this property) if -# you wish with no harm. -# ---------------------------------------------------------------------------- -# dev-changes by Marino -webapp.resource.loader.cache = true -webapp.resource.loader.modificationCheckInterval = 1 -#velocimacro.library.autoreload = false -#velocimacro.library = /WEB-INF/VM_global_library.vm - -#velocimacro.permissions.allow.inline = true -#velocimacro.permissions.allow.inline.to.replace.global = false -#velocimacro.permissions.allow.inline.local.scope = false - -#velocimacro.context.localscope = false - -# ---------------------------------------------------------------------------- -# INTERPOLATION -# ---------------------------------------------------------------------------- -# turn off and on interpolation of references and directives in string -# literals. ON by default :) -# ---------------------------------------------------------------------------- -runtime.interpolate.string.literals = true - - -# ---------------------------------------------------------------------------- -# RESOURCE MANAGEMENT -# ---------------------------------------------------------------------------- -# Allows alternative ResourceManager and ResourceCache implementations -# to be plugged in. -# ---------------------------------------------------------------------------- -resource.manager.class = org.apache.velocity.runtime.resource.ResourceManagerImpl -resource.manager.cache.class =org.apache.velocity.runtime.resource.ResourceCacheImpl - - +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# ---------------------------------------------------------------------------- +# These are the default properties for the +# Velocity Runtime. These values are used when +# Runtime.init() is called, and when Runtime.init(properties) +# fails to find the specificed properties file. +# ---------------------------------------------------------------------------- + + +# ---------------------------------------------------------------------------- +# R U N T I M E L O G +# ---------------------------------------------------------------------------- +# Velocity uses the Servlet APIs logging facilites. + +# ---------------------------------------------------------------------------- +# This controls if Runtime.error(), info() and warn() messages include the +# whole stack trace. The last property controls whether invalid references +# are logged. +# ---------------------------------------------------------------------------- + +runtime.log.invalid.reference = false + + +# ---------------------------------------------------------------------------- +# T E M P L A T E E N C O D I N G +# ---------------------------------------------------------------------------- +#default.encoding=utf-8 +input.encoding=utf-8 +output.encoding=utf-8 +default.contenttype=text/html;charset=utf-8 +# ---------------------------------------------------------------------------- +# F O R E A C H P R O P E R T I E S +# ---------------------------------------------------------------------------- +# These properties control how the counter is accessed in the #foreach +# directive. By default the reference $velocityCount will be available +# in the body of the #foreach directive. The default starting value +# for this reference is 1. +# ---------------------------------------------------------------------------- + +directive.foreach.counter.name = velocityCount +directive.foreach.counter.initial.value = 1 + + +# ---------------------------------------------------------------------------- +# I N C L U D E P R O P E R T I E S +# ---------------------------------------------------------------------------- +# These are the properties that governed the way #include'd content +# is governed. +# ---------------------------------------------------------------------------- + +directive.include.output.errormsg.start = + + +# ---------------------------------------------------------------------------- +# P A R S E P R O P E R T I E S +# ---------------------------------------------------------------------------- + +directive.parse.max.depth = 10 + + +# ---------------------------------------------------------------------------- +# VELOCIMACRO PROPERTIES +# ---------------------------------------------------------------------------- +# global : name of default global library. It is expected to be in the regular +# template path. You may remove it (either the file or this property) if +# you wish with no harm. +# ---------------------------------------------------------------------------- +# dev-changes by Marino +webapp.resource.loader.cache = true +webapp.resource.loader.modificationCheckInterval = 1 +#velocimacro.library.autoreload = false +#velocimacro.library = /WEB-INF/VM_global_library.vm + +#velocimacro.permissions.allow.inline = true +#velocimacro.permissions.allow.inline.to.replace.global = false +#velocimacro.permissions.allow.inline.local.scope = false + +#velocimacro.context.localscope = false + +# ---------------------------------------------------------------------------- +# INTERPOLATION +# ---------------------------------------------------------------------------- +# turn off and on interpolation of references and directives in string +# literals. ON by default :) +# ---------------------------------------------------------------------------- +runtime.interpolate.string.literals = true + + +# ---------------------------------------------------------------------------- +# RESOURCE MANAGEMENT +# ---------------------------------------------------------------------------- +# Allows alternative ResourceManager and ResourceCache implementations +# to be plugged in. +# ---------------------------------------------------------------------------- +resource.manager.class=org.apache.velocity.runtime.resource.ResourceManagerImpl +resource.manager.cache.class=org.apache.velocity.runtime.resource.ResourceCacheImpl + +velocimacro.library.autoreload = true +velocimacro.permissions.allow.inline.to.replace.global=true + runtime.log.logsystem.class=org.apache.velocity.runtime.log.NullLogSystem \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..247300fdb --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,207 @@ + + + rap + + log4jConfigLocation + /WEB-INF/classes/log4j2.xml + + + + org.springframework.web.util.Log4jConfigListener + + + + contextConfigLocation + classpath*:hibernate.cfg.xml + + + ssoFilter + com.alibaba.buc.sso.client.filter.SSOFilter + + APP_NAME + rapauto + + + SSO_CALLBACK_CLASS + com.alibaba.buc.sso.client.handler.impl.SimpleSSOCallback + + + SSO_SERVER_URL + https://login.alibaba-inc.com + + + CLIENT_KEY + 0e6f43d9-e380-4a7b-88ec-65b5568ce2ee + + + EXCLUSIONS + * + + + + UrlRewriteFilter + org.tuckey.web.filters.urlrewrite.UrlRewriteFilter + + confPath + /WEB-INF/urlrewrite.xml + + + + DelegatingFilterProxy + org.springframework.web.filter.DelegatingFilterProxy + + targetBeanName + authCheckFilter + + + targetFilterLifecycle + true + + + + authCheckFilter + com.taobao.rigel.rap.common.filter.AuthCheckFilter + + + openSessionInViewFilter + org.springframework.orm.hibernate5.support.OpenSessionInViewFilter + + + encodingFilter + org.springframework.web.filter.CharacterEncodingFilter + + encoding + UTF-8 + + + forceEncoding + true + + + + SetCharacterEncoding + com.taobao.rigel.rap.common.filter.SetCharacterEncodingFilter + + encoding + utf-8 + + + + ssoFilter + /* + + + DelegatingFilterProxy + /* + + + UrlRewriteFilter + /* + REQUEST + FORWARD + + + SetCharacterEncoding + /* + + + struts-cleanup + org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter + + + struts2 + org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter + + + openSessionInViewFilter + /* + + + struts-cleanup + /* + + + struts2 + /* + REQUEST + FORWARD + INCLUDE + + + org.springframework.web.context.ContextLoaderListener + + + DispatcherFilter + org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter + + + + DispatcherFilter + /* + + + com.taobao.rigel.rap.common.listener.SessionListener + + + + com.taobao.rigel.rap.common.listener.RapServletContextListener + + + + + + Kaptcha + com.google.code.kaptcha.servlet.KaptchaServlet + + kaptcha.image.width + 200 + + + kaptcha.image.height + 50 + + + kaptcha.textproducer.font.size + 40 + + + kaptcha.textproducer.char.length + 4 + + + kaptcha.border + no + + + kaptcha.textproducer.font.color + black + + + kaptcha.textproducer.char.space + 10 + + + kaptcha.obscurificator.impl + com.google.code.kaptcha.impl.ShadowGimpy + + + + Kaptcha + /Kaptcha.jpg + + + KaptchaAction + org.apache.struts2.dispatcher.FilterDispatcher + + + KaptchaAction + /* + + + + 60 + + diff --git a/src/main/webapp/account/login.vm b/src/main/webapp/account/login.vm new file mode 100644 index 000000000..8b22a03a2 --- /dev/null +++ b/src/main/webapp/account/login.vm @@ -0,0 +1,51 @@ + + + + + Login + #parse('/tcom/template.rap.vm') + #includeNewRapStatic + #if($returnUrlFirstSet) + #set($returnUrlEncoded = $!utils.escapeInU($returnUrl)) + #else + #set($returnUrlEncoded = $returnUrl) + #end + + + +
    + #bodyNewStart +
    + + +
    + + +
    +
    + + +
    +
    + + + +
    + #if ($errMsg && $errMsg != "") +
    +
    + $!errMsg +
    +
    + #end +    + + 域账号登录 + +
    + #bodyEnd +
    + + diff --git a/src/main/webapp/account/myAccount.vm b/src/main/webapp/account/myAccount.vm new file mode 100644 index 000000000..adc591882 --- /dev/null +++ b/src/main/webapp/account/myAccount.vm @@ -0,0 +1,135 @@ + + #parse('/tcom/template.rap.vm') + + + + + Manage Account + #includeNewRapStatic + + +#bodyNewStart +
    +
    +
    + + +
    +

    $!utils.escapeInH($user.account)

    +
    +
    +
    + + +
    +

    + #if($isEditMode) + + #else + $!utils.escapeInH($user.name) + #end +

    +
    +
    +
    + + +
    +

    + #if($isEditMode) + + #else + $!utils.escapeInH($user.email) + #end +

    +
    +
    + #if($isEditMode) +
    + + +
    +

    + * 若无需修改请忽略 +

    +
    +
    +
    + + +
    +

    + +

    +
    +
    +
    + + +
    +

    + +

    +
    +
    + #end +
    + + +
    +

    + $!utils.escapeInH($user.createDateStr) +

    +
    +
    +
    + + +
    +

    + #if($opSuccess) + 操作成功 + #else + + #end +

    +
    +
    +
    + + +
    +

    + #if($isEditMode) + + + #else + + #end +

    +
    +
    +
    +
    +#bodyEnd + + + diff --git a/src/main/webapp/account/mySetting.vm b/src/main/webapp/account/mySetting.vm new file mode 100644 index 000000000..e34f5e6ec --- /dev/null +++ b/src/main/webapp/account/mySetting.vm @@ -0,0 +1,156 @@ + + #parse('/tcom/template.rap.vm') + + + + + Manage Account #includeNewRapStatic + + + +#bodyNewStart + +
    +
    不要鸡冻,这个功能还木有做完,霍雍和思竹吃饭饭去了
    + + + +
    +
    +
    +
    + + +
    + +
    +
    +
    + + +
    +
    + +
    +
    + +
    +
    +
    + +
    + + +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    + +
    + + +
    + +
    +
    + +
    + + +
    +
    + +
    +
    + +
    +
    +
    + +
    + + +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    更多功能,敬请期待~
    +
    +
    +#bodyEnd + + diff --git a/src/main/webapp/account/register.vm b/src/main/webapp/account/register.vm new file mode 100644 index 000000000..f5b74d1de --- /dev/null +++ b/src/main/webapp/account/register.vm @@ -0,0 +1,102 @@ + + #parse('/tcom/template.rap.vm') + + + + 注册新的RAP账户 + #includeNewRapStatic + + +#bodyNewStart +
    +
    +
    + + +
    + +
    +
    +
    + + +
    +

    + +

    +
    +
    +
    + + +
    +

    + +

    +
    +
    +
    + + +
    +

    + +

    +
    +
    +
    + + +
    +

    + +

    +
    +
    +
    + +
    + + +
    +
    +
    + + +
    +

    + +

    +
    +
    +
    + + +
    +

    + +

    +
    +
    +
    +
    +#bodyEnd + + + diff --git a/WebContent/bcom/ajaxRequest.cb.vm b/src/main/webapp/bcom/ajaxRequest.cb.vm similarity index 100% rename from WebContent/bcom/ajaxRequest.cb.vm rename to src/main/webapp/bcom/ajaxRequest.cb.vm diff --git a/WebContent/bcom/content.cb.vm b/src/main/webapp/bcom/content.cb.vm similarity index 100% rename from WebContent/bcom/content.cb.vm rename to src/main/webapp/bcom/content.cb.vm diff --git a/WebContent/bcom/contentAndId.cb.vm b/src/main/webapp/bcom/contentAndId.cb.vm similarity index 100% rename from WebContent/bcom/contentAndId.cb.vm rename to src/main/webapp/bcom/contentAndId.cb.vm diff --git a/src/main/webapp/bcom/contentWithoutEscape.cb.vm b/src/main/webapp/bcom/contentWithoutEscape.cb.vm new file mode 100644 index 000000000..2044ad03d --- /dev/null +++ b/src/main/webapp/bcom/contentWithoutEscape.cb.vm @@ -0,0 +1 @@ +$!content \ No newline at end of file diff --git a/src/main/webapp/bcom/getModuleHtmlAjax.cb.vm b/src/main/webapp/bcom/getModuleHtmlAjax.cb.vm new file mode 100644 index 000000000..ae31c2a45 --- /dev/null +++ b/src/main/webapp/bcom/getModuleHtmlAjax.cb.vm @@ -0,0 +1,20 @@ +
    +
    + + #foreach ($page in $module.pageList) +
    + + #foreach ($action in $page.actionList) + + #end +
    add
    +
    + #end +
    +
    +
    +
    +
    diff --git a/WebContent/bcom/isOk.cb.vm b/src/main/webapp/bcom/isOk.cb.vm similarity index 100% rename from WebContent/bcom/isOk.cb.vm rename to src/main/webapp/bcom/isOk.cb.vm diff --git a/WebContent/bcom/isOkWithNum.cb.vm b/src/main/webapp/bcom/isOkWithNum.cb.vm similarity index 97% rename from WebContent/bcom/isOkWithNum.cb.vm rename to src/main/webapp/bcom/isOkWithNum.cb.vm index 57d777c0b..e7e4acdac 100644 --- a/WebContent/bcom/isOkWithNum.cb.vm +++ b/src/main/webapp/bcom/isOkWithNum.cb.vm @@ -1 +1 @@ -$!callback({"isOk":$!isOk, "num":$!num}) +$!callback({"isOk":$!isOk, "num":$!num}) diff --git a/WebContent/bcom/json.cb.vm b/src/main/webapp/bcom/json.cb.vm similarity index 100% rename from WebContent/bcom/json.cb.vm rename to src/main/webapp/bcom/json.cb.vm diff --git a/WebContent/bcom/jsonError.cb.vm b/src/main/webapp/bcom/jsonError.cb.vm similarity index 100% rename from WebContent/bcom/jsonError.cb.vm rename to src/main/webapp/bcom/jsonError.cb.vm diff --git a/WebContent/bcom/project.cb.vm b/src/main/webapp/bcom/project.cb.vm similarity index 100% rename from WebContent/bcom/project.cb.vm rename to src/main/webapp/bcom/project.cb.vm diff --git a/WebContent/bcom/saveWorkspace.cb.vm b/src/main/webapp/bcom/saveWorkspace.cb.vm similarity index 100% rename from WebContent/bcom/saveWorkspace.cb.vm rename to src/main/webapp/bcom/saveWorkspace.cb.vm diff --git a/src/main/webapp/common/blank.html b/src/main/webapp/common/blank.html new file mode 100644 index 000000000..ff34eec49 --- /dev/null +++ b/src/main/webapp/common/blank.html @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/main/webapp/common/redirect.vm b/src/main/webapp/common/redirect.vm new file mode 100644 index 000000000..3c7f8208c --- /dev/null +++ b/src/main/webapp/common/redirect.vm @@ -0,0 +1,14 @@ + + + + + RAP - 正在为您跳转 + + +正在为您跳转... + + + + diff --git a/src/main/webapp/demo/a.js b/src/main/webapp/demo/a.js new file mode 100644 index 000000000..ef47d9def --- /dev/null +++ b/src/main/webapp/demo/a.js @@ -0,0 +1,13 @@ +define(function (require, exports, module) { + var $ = require('jquery'); + exports.go = function () { + $.ajax({ + url: 'data.json', + dataType: 'json', + type: 'get', + success: function (data) { + $('body').html(JSON.stringify(data, null, 4)); + } + }); + } +}) \ No newline at end of file diff --git a/src/main/webapp/demo/mock.plugin/casebox/case1_seajs_jquery_preload.html b/src/main/webapp/demo/mock.plugin/casebox/case1_seajs_jquery_preload.html new file mode 100644 index 000000000..966895bb9 --- /dev/null +++ b/src/main/webapp/demo/mock.plugin/casebox/case1_seajs_jquery_preload.html @@ -0,0 +1,61 @@ + + + + + + + + + +
    +
    +

    + RAP plugin case1: seajs jquery preload issue. +

    + +

    LOG:

    +
    
    +
    + + + + + \ No newline at end of file diff --git a/src/main/webapp/demo/mock.plugin/data.json b/src/main/webapp/demo/mock.plugin/data.json new file mode 100644 index 000000000..8d6b85c7b --- /dev/null +++ b/src/main/webapp/demo/mock.plugin/data.json @@ -0,0 +1,3 @@ +{ + "a": 1 +} diff --git a/src/main/webapp/demo/mock.plugin/data1.js b/src/main/webapp/demo/mock.plugin/data1.js new file mode 100644 index 000000000..b07d8ddf3 --- /dev/null +++ b/src/main/webapp/demo/mock.plugin/data1.js @@ -0,0 +1,7 @@ +{ + "a" +: + 1, "b" +: + 2 +} \ No newline at end of file diff --git a/src/main/webapp/demo/mock.plugin/index.htm b/src/main/webapp/demo/mock.plugin/index.htm new file mode 100644 index 000000000..b0da4e314 --- /dev/null +++ b/src/main/webapp/demo/mock.plugin/index.htm @@ -0,0 +1,63 @@ + + + + +RAP Example + + + + + + +
    
    +
    +
    +
    diff --git a/src/main/webapp/demo/mock.plugin/jquery-2.0.3.min.js b/src/main/webapp/demo/mock.plugin/jquery-2.0.3.min.js
    new file mode 100644
    index 000000000..7ab438963
    --- /dev/null
    +++ b/src/main/webapp/demo/mock.plugin/jquery-2.0.3.min.js
    @@ -0,0 +1,2363 @@
    +/*! jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
    + //@ sourceMappingURL=jquery-2.0.3.min.map
    + */
    +(function (e, undefined) {
    +    var t, n, r = typeof undefined, i = e.location, o = e.document, s = o.documentElement, a = e.jQuery, u = e.$, l = {}, c = [], p = "2.0.3", f = c.concat, h = c.push, d = c.slice, g = c.indexOf, m = l.toString, y = l.hasOwnProperty, v = p.trim, x = function (e, n) {
    +        return new x.fn.init(e, n, t)
    +    }, b = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, w = /\S+/g, T = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, C = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, k = /^-ms-/, N = /-([\da-z])/gi, E = function (e, t) {
    +        return t.toUpperCase()
    +    }, S = function () {
    +        o.removeEventListener("DOMContentLoaded", S, !1), e.removeEventListener("load", S, !1), x.ready()
    +    };
    +    x.fn = x.prototype = {
    +        jquery: p, constructor: x, init: function (e, t, n) {
    +            var r, i;
    +            if (!e)return this;
    +            if ("string" == typeof e) {
    +                if (r = "<" === e.charAt(0) && ">" === e.charAt(e.length - 1) && e.length >= 3 ? [null, e, null] : T.exec(e), !r || !r[1] && t)return !t || t.jquery ? (t || n).find(e) : this.constructor(t).find(e);
    +                if (r[1]) {
    +                    if (t = t instanceof x ? t[0] : t, x.merge(this, x.parseHTML(r[1], t && t.nodeType ? t.ownerDocument || t : o, !0)), C.test(r[1]) && x.isPlainObject(t))for (r in t)x.isFunction(this[r]) ? this[r](t[r]) : this.attr(r, t[r]);
    +                    return this
    +                }
    +                return i = o.getElementById(r[2]), i && i.parentNode && (this.length = 1, this[0] = i), this.context = o, this.selector = e, this
    +            }
    +            return e.nodeType ? (this.context = this[0] = e, this.length = 1, this) : x.isFunction(e) ? n.ready(e) : (e.selector !== undefined && (this.selector = e.selector, this.context = e.context), x.makeArray(e, this))
    +        }, selector: "", length: 0, toArray: function () {
    +            return d.call(this)
    +        }, get: function (e) {
    +            return null == e ? this.toArray() : 0 > e ? this[this.length + e] : this[e]
    +        }, pushStack: function (e) {
    +            var t = x.merge(this.constructor(), e);
    +            return t.prevObject = this, t.context = this.context, t
    +        }, each: function (e, t) {
    +            return x.each(this, e, t)
    +        }, ready: function (e) {
    +            return x.ready.promise().done(e), this
    +        }, slice: function () {
    +            return this.pushStack(d.apply(this, arguments))
    +        }, first: function () {
    +            return this.eq(0)
    +        }, last: function () {
    +            return this.eq(-1)
    +        }, eq: function (e) {
    +            var t = this.length, n = +e + (0 > e ? t : 0);
    +            return this.pushStack(n >= 0 && t > n ? [this[n]] : [])
    +        }, map: function (e) {
    +            return this.pushStack(x.map(this, function (t, n) {
    +                return e.call(t, n, t)
    +            }))
    +        }, end: function () {
    +            return this.prevObject || this.constructor(null)
    +        }, push: h, sort: [].sort, splice: [].splice
    +    }, x.fn.init.prototype = x.fn, x.extend = x.fn.extend = function () {
    +        var e, t, n, r, i, o, s = arguments[0] || {}, a = 1, u = arguments.length, l = !1;
    +        for ("boolean" == typeof s && (l = s, s = arguments[1] || {}, a = 2), "object" == typeof s || x.isFunction(s) || (s = {}), u === a && (s = this, --a); u > a; a++)if (null != (e = arguments[a]))for (t in e)n = s[t], r = e[t], s !== r && (l && r && (x.isPlainObject(r) || (i = x.isArray(r))) ? (i ? (i = !1, o = n && x.isArray(n) ? n : []) : o = n && x.isPlainObject(n) ? n : {}, s[t] = x.extend(l, o, r)) : r !== undefined && (s[t] = r));
    +        return s
    +    }, x.extend({
    +        expando: "jQuery" + (p + Math.random()).replace(/\D/g, ""), noConflict: function (t) {
    +            return e.$ === x && (e.$ = u), t && e.jQuery === x && (e.jQuery = a), x
    +        }, isReady: !1, readyWait: 1, holdReady: function (e) {
    +            e ? x.readyWait++ : x.ready(!0)
    +        }, ready: function (e) {
    +            (e === !0 ? --x.readyWait : x.isReady) || (x.isReady = !0, e !== !0 && --x.readyWait > 0 || (n.resolveWith(o, [x]), x.fn.trigger && x(o).trigger("ready").off("ready")))
    +        }, isFunction: function (e) {
    +            return "function" === x.type(e)
    +        }, isArray: Array.isArray, isWindow: function (e) {
    +            return null != e && e === e.window
    +        }, isNumeric: function (e) {
    +            return !isNaN(parseFloat(e)) && isFinite(e)
    +        }, type: function (e) {
    +            return null == e ? e + "" : "object" == typeof e || "function" == typeof e ? l[m.call(e)] || "object" : typeof e
    +        }, isPlainObject: function (e) {
    +            if ("object" !== x.type(e) || e.nodeType || x.isWindow(e))return !1;
    +            try {
    +                if (e.constructor && !y.call(e.constructor.prototype, "isPrototypeOf"))return !1
    +            } catch (t) {
    +                return !1
    +            }
    +            return !0
    +        }, isEmptyObject: function (e) {
    +            var t;
    +            for (t in e)return !1;
    +            return !0
    +        }, error: function (e) {
    +            throw Error(e)
    +        }, parseHTML: function (e, t, n) {
    +            if (!e || "string" != typeof e)return null;
    +            "boolean" == typeof t && (n = t, t = !1), t = t || o;
    +            var r = C.exec(e), i = !n && [];
    +            return r ? [t.createElement(r[1])] : (r = x.buildFragment([e], t, i), i && x(i).remove(), x.merge([], r.childNodes))
    +        }, parseJSON: JSON.parse, parseXML: function (e) {
    +            var t, n;
    +            if (!e || "string" != typeof e)return null;
    +            try {
    +                n = new DOMParser, t = n.parseFromString(e, "text/xml")
    +            } catch (r) {
    +                t = undefined
    +            }
    +            return (!t || t.getElementsByTagName("parsererror").length) && x.error("Invalid XML: " + e), t
    +        }, noop: function () {
    +        }, globalEval: function (e) {
    +            var t, n = eval;
    +            e = x.trim(e), e && (1 === e.indexOf("use strict") ? (t = o.createElement("script"), t.text = e, o.head.appendChild(t).parentNode.removeChild(t)) : n(e))
    +        }, camelCase: function (e) {
    +            return e.replace(k, "ms-").replace(N, E)
    +        }, nodeName: function (e, t) {
    +            return e.nodeName && e.nodeName.toLowerCase() === t.toLowerCase()
    +        }, each: function (e, t, n) {
    +            var r, i = 0, o = e.length, s = j(e);
    +            if (n) {
    +                if (s) {
    +                    for (; o > i; i++)if (r = t.apply(e[i], n), r === !1)break
    +                } else for (i in e)if (r = t.apply(e[i], n), r === !1)break
    +            } else if (s) {
    +                for (; o > i; i++)if (r = t.call(e[i], i, e[i]), r === !1)break
    +            } else for (i in e)if (r = t.call(e[i], i, e[i]), r === !1)break;
    +            return e
    +        }, trim: function (e) {
    +            return null == e ? "" : v.call(e)
    +        }, makeArray: function (e, t) {
    +            var n = t || [];
    +            return null != e && (j(Object(e)) ? x.merge(n, "string" == typeof e ? [e] : e) : h.call(n, e)), n
    +        }, inArray: function (e, t, n) {
    +            return null == t ? -1 : g.call(t, e, n)
    +        }, merge: function (e, t) {
    +            var n = t.length, r = e.length, i = 0;
    +            if ("number" == typeof n)for (; n > i; i++)e[r++] = t[i]; else while (t[i] !== undefined)e[r++] = t[i++];
    +            return e.length = r, e
    +        }, grep: function (e, t, n) {
    +            var r, i = [], o = 0, s = e.length;
    +            for (n = !!n; s > o; o++)r = !!t(e[o], o), n !== r && i.push(e[o]);
    +            return i
    +        }, map: function (e, t, n) {
    +            var r, i = 0, o = e.length, s = j(e), a = [];
    +            if (s)for (; o > i; i++)r = t(e[i], i, n), null != r && (a[a.length] = r); else for (i in e)r = t(e[i], i, n), null != r && (a[a.length] = r);
    +            return f.apply([], a)
    +        }, guid: 1, proxy: function (e, t) {
    +            var n, r, i;
    +            return "string" == typeof t && (n = e[t], t = e, e = n), x.isFunction(e) ? (r = d.call(arguments, 2), i = function () {
    +                return e.apply(t || this, r.concat(d.call(arguments)))
    +            }, i.guid = e.guid = e.guid || x.guid++, i) : undefined
    +        }, access: function (e, t, n, r, i, o, s) {
    +            var a = 0, u = e.length, l = null == n;
    +            if ("object" === x.type(n)) {
    +                i = !0;
    +                for (a in n)x.access(e, t, a, n[a], !0, o, s)
    +            } else if (r !== undefined && (i = !0, x.isFunction(r) || (s = !0), l && (s ? (t.call(e, r), t = null) : (l = t, t = function (e, t, n) {
    +                    return l.call(x(e), n)
    +                })), t))for (; u > a; a++)t(e[a], n, s ? r : r.call(e[a], a, t(e[a], n)));
    +            return i ? e : l ? t.call(e) : u ? t(e[0], n) : o
    +        }, now: Date.now, swap: function (e, t, n, r) {
    +            var i, o, s = {};
    +            for (o in t)s[o] = e.style[o], e.style[o] = t[o];
    +            i = n.apply(e, r || []);
    +            for (o in t)e.style[o] = s[o];
    +            return i
    +        }
    +    }), x.ready.promise = function (t) {
    +        return n || (n = x.Deferred(), "complete" === o.readyState ? setTimeout(x.ready) : (o.addEventListener("DOMContentLoaded", S, !1), e.addEventListener("load", S, !1))), n.promise(t)
    +    }, x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function (e, t) {
    +        l["[object " + t + "]"] = t.toLowerCase()
    +    });
    +    function j(e) {
    +        var t = e.length, n = x.type(e);
    +        return x.isWindow(e) ? !1 : 1 === e.nodeType && t ? !0 : "array" === n || "function" !== n && (0 === t || "number" == typeof t && t > 0 && t - 1 in e)
    +    }
    +
    +    t = x(o), function (e, undefined) {
    +        var t, n, r, i, o, s, a, u, l, c, p, f, h, d, g, m, y, v = "sizzle" + -new Date, b = e.document, w = 0, T = 0, C = st(), k = st(), N = st(), E = !1, S = function (e, t) {
    +            return e === t ? (E = !0, 0) : 0
    +        }, j = typeof undefined, D = 1 << 31, A = {}.hasOwnProperty, L = [], q = L.pop, H = L.push, O = L.push, F = L.slice, P = L.indexOf || function (e) {
    +                var t = 0, n = this.length;
    +                for (; n > t; t++)if (this[t] === e)return t;
    +                return -1
    +            }, R = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", M = "[\\x20\\t\\r\\n\\f]", W = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", $ = W.replace("w", "w#"), B = "\\[" + M + "*(" + W + ")" + M + "*(?:([*^$|!~]?=)" + M + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + $ + ")|)|)" + M + "*\\]", I = ":(" + W + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + B.replace(3, 8) + ")*)|.*)\\)|)", z = RegExp("^" + M + "+|((?:^|[^\\\\])(?:\\\\.)*)" + M + "+$", "g"), _ = RegExp("^" + M + "*," + M + "*"), X = RegExp("^" + M + "*([>+~]|" + M + ")" + M + "*"), U = RegExp(M + "*[+~]"), Y = RegExp("=" + M + "*([^\\]'\"]*)" + M + "*\\]", "g"), V = RegExp(I), G = RegExp("^" + $ + "$"), J = {
    +            ID: RegExp("^#(" + W + ")"),
    +            CLASS: RegExp("^\\.(" + W + ")"),
    +            TAG: RegExp("^(" + W.replace("w", "w*") + ")"),
    +            ATTR: RegExp("^" + B),
    +            PSEUDO: RegExp("^" + I),
    +            CHILD: RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + M + "*(even|odd|(([+-]|)(\\d*)n|)" + M + "*(?:([+-]|)" + M + "*(\\d+)|))" + M + "*\\)|)", "i"),
    +            bool: RegExp("^(?:" + R + ")$", "i"),
    +            needsContext: RegExp("^" + M + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + M + "*((?:-\\d)?\\d*)" + M + "*\\)|)(?=[^-]|$)", "i")
    +        }, Q = /^[^{]+\{\s*\[native \w/, K = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, Z = /^(?:input|select|textarea|button)$/i, et = /^h\d$/i, tt = /'|\\/g, nt = RegExp("\\\\([\\da-f]{1,6}" + M + "?|(" + M + ")|.)", "ig"), rt = function (e, t, n) {
    +            var r = "0x" + t - 65536;
    +            return r !== r || n ? t : 0 > r ? String.fromCharCode(r + 65536) : String.fromCharCode(55296 | r >> 10, 56320 | 1023 & r)
    +        };
    +        try {
    +            O.apply(L = F.call(b.childNodes), b.childNodes), L[b.childNodes.length].nodeType
    +        } catch (it) {
    +            O = {
    +                apply: L.length ? function (e, t) {
    +                    H.apply(e, F.call(t))
    +                } : function (e, t) {
    +                    var n = e.length, r = 0;
    +                    while (e[n++] = t[r++]);
    +                    e.length = n - 1
    +                }
    +            }
    +        }
    +        function ot(e, t, r, i) {
    +            var o, s, a, u, l, f, g, m, x, w;
    +            if ((t ? t.ownerDocument || t : b) !== p && c(t), t = t || p, r = r || [], !e || "string" != typeof e)return r;
    +            if (1 !== (u = t.nodeType) && 9 !== u)return [];
    +            if (h && !i) {
    +                if (o = K.exec(e))if (a = o[1]) {
    +                    if (9 === u) {
    +                        if (s = t.getElementById(a), !s || !s.parentNode)return r;
    +                        if (s.id === a)return r.push(s), r
    +                    } else if (t.ownerDocument && (s = t.ownerDocument.getElementById(a)) && y(t, s) && s.id === a)return r.push(s), r
    +                } else {
    +                    if (o[2])return O.apply(r, t.getElementsByTagName(e)), r;
    +                    if ((a = o[3]) && n.getElementsByClassName && t.getElementsByClassName)return O.apply(r, t.getElementsByClassName(a)), r
    +                }
    +                if (n.qsa && (!d || !d.test(e))) {
    +                    if (m = g = v, x = t, w = 9 === u && e, 1 === u && "object" !== t.nodeName.toLowerCase()) {
    +                        f = gt(e), (g = t.getAttribute("id")) ? m = g.replace(tt, "\\$&") : t.setAttribute("id", m), m = "[id='" + m + "'] ", l = f.length;
    +                        while (l--)f[l] = m + mt(f[l]);
    +                        x = U.test(e) && t.parentNode || t, w = f.join(",")
    +                    }
    +                    if (w)try {
    +                        return O.apply(r, x.querySelectorAll(w)), r
    +                    } catch (T) {
    +                    } finally {
    +                        g || t.removeAttribute("id")
    +                    }
    +                }
    +            }
    +            return kt(e.replace(z, "$1"), t, r, i)
    +        }
    +
    +        function st() {
    +            var e = [];
    +
    +            function t(n, r) {
    +                return e.push(n += " ") > i.cacheLength && delete t[e.shift()], t[n] = r
    +            }
    +
    +            return t
    +        }
    +
    +        function at(e) {
    +            return e[v] = !0, e
    +        }
    +
    +        function ut(e) {
    +            var t = p.createElement("div");
    +            try {
    +                return !!e(t)
    +            } catch (n) {
    +                return !1
    +            } finally {
    +                t.parentNode && t.parentNode.removeChild(t), t = null
    +            }
    +        }
    +
    +        function lt(e, t) {
    +            var n = e.split("|"), r = e.length;
    +            while (r--)i.attrHandle[n[r]] = t
    +        }
    +
    +        function ct(e, t) {
    +            var n = t && e, r = n && 1 === e.nodeType && 1 === t.nodeType && (~t.sourceIndex || D) - (~e.sourceIndex || D);
    +            if (r)return r;
    +            if (n)while (n = n.nextSibling)if (n === t)return -1;
    +            return e ? 1 : -1
    +        }
    +
    +        function pt(e) {
    +            return function (t) {
    +                var n = t.nodeName.toLowerCase();
    +                return "input" === n && t.type === e
    +            }
    +        }
    +
    +        function ft(e) {
    +            return function (t) {
    +                var n = t.nodeName.toLowerCase();
    +                return ("input" === n || "button" === n) && t.type === e
    +            }
    +        }
    +
    +        function ht(e) {
    +            return at(function (t) {
    +                return t = +t, at(function (n, r) {
    +                    var i, o = e([], n.length, t), s = o.length;
    +                    while (s--)n[i = o[s]] && (n[i] = !(r[i] = n[i]))
    +                })
    +            })
    +        }
    +
    +        s = ot.isXML = function (e) {
    +            var t = e && (e.ownerDocument || e).documentElement;
    +            return t ? "HTML" !== t.nodeName : !1
    +        }, n = ot.support = {}, c = ot.setDocument = function (e) {
    +            var t = e ? e.ownerDocument || e : b, r = t.defaultView;
    +            return t !== p && 9 === t.nodeType && t.documentElement ? (p = t, f = t.documentElement, h = !s(t), r && r.attachEvent && r !== r.top && r.attachEvent("onbeforeunload", function () {
    +                c()
    +            }), n.attributes = ut(function (e) {
    +                return e.className = "i", !e.getAttribute("className")
    +            }), n.getElementsByTagName = ut(function (e) {
    +                return e.appendChild(t.createComment("")), !e.getElementsByTagName("*").length
    +            }), n.getElementsByClassName = ut(function (e) {
    +                return e.innerHTML = "
    ", e.firstChild.className = "i", 2 === e.getElementsByClassName("i").length + }), n.getById = ut(function (e) { + return f.appendChild(e).id = v, !t.getElementsByName || !t.getElementsByName(v).length + }), n.getById ? (i.find.ID = function (e, t) { + if (typeof t.getElementById !== j && h) { + var n = t.getElementById(e); + return n && n.parentNode ? [n] : [] + } + }, i.filter.ID = function (e) { + var t = e.replace(nt, rt); + return function (e) { + return e.getAttribute("id") === t + } + }) : (delete i.find.ID, i.filter.ID = function (e) { + var t = e.replace(nt, rt); + return function (e) { + var n = typeof e.getAttributeNode !== j && e.getAttributeNode("id"); + return n && n.value === t + } + }), i.find.TAG = n.getElementsByTagName ? function (e, t) { + return typeof t.getElementsByTagName !== j ? t.getElementsByTagName(e) : undefined + } : function (e, t) { + var n, r = [], i = 0, o = t.getElementsByTagName(e); + if ("*" === e) { + while (n = o[i++])1 === n.nodeType && r.push(n); + return r + } + return o + }, i.find.CLASS = n.getElementsByClassName && function (e, t) { + return typeof t.getElementsByClassName !== j && h ? t.getElementsByClassName(e) : undefined + }, g = [], d = [], (n.qsa = Q.test(t.querySelectorAll)) && (ut(function (e) { + e.innerHTML = "", e.querySelectorAll("[selected]").length || d.push("\\[" + M + "*(?:value|" + R + ")"), e.querySelectorAll(":checked").length || d.push(":checked") + }), ut(function (e) { + var n = t.createElement("input"); + n.setAttribute("type", "hidden"), e.appendChild(n).setAttribute("t", ""), e.querySelectorAll("[t^='']").length && d.push("[*^$]=" + M + "*(?:''|\"\")"), e.querySelectorAll(":enabled").length || d.push(":enabled", ":disabled"), e.querySelectorAll("*,:x"), d.push(",.*:") + })), (n.matchesSelector = Q.test(m = f.webkitMatchesSelector || f.mozMatchesSelector || f.oMatchesSelector || f.msMatchesSelector)) && ut(function (e) { + n.disconnectedMatch = m.call(e, "div"), m.call(e, "[s!='']:x"), g.push("!=", I) + }), d = d.length && RegExp(d.join("|")), g = g.length && RegExp(g.join("|")), y = Q.test(f.contains) || f.compareDocumentPosition ? function (e, t) { + var n = 9 === e.nodeType ? e.documentElement : e, r = t && t.parentNode; + return e === r || !(!r || 1 !== r.nodeType || !(n.contains ? n.contains(r) : e.compareDocumentPosition && 16 & e.compareDocumentPosition(r))) + } : function (e, t) { + if (t)while (t = t.parentNode)if (t === e)return !0; + return !1 + }, S = f.compareDocumentPosition ? function (e, r) { + if (e === r)return E = !0, 0; + var i = r.compareDocumentPosition && e.compareDocumentPosition && e.compareDocumentPosition(r); + return i ? 1 & i || !n.sortDetached && r.compareDocumentPosition(e) === i ? e === t || y(b, e) ? -1 : r === t || y(b, r) ? 1 : l ? P.call(l, e) - P.call(l, r) : 0 : 4 & i ? -1 : 1 : e.compareDocumentPosition ? -1 : 1 + } : function (e, n) { + var r, i = 0, o = e.parentNode, s = n.parentNode, a = [e], u = [n]; + if (e === n)return E = !0, 0; + if (!o || !s)return e === t ? -1 : n === t ? 1 : o ? -1 : s ? 1 : l ? P.call(l, e) - P.call(l, n) : 0; + if (o === s)return ct(e, n); + r = e; + while (r = r.parentNode)a.unshift(r); + r = n; + while (r = r.parentNode)u.unshift(r); + while (a[i] === u[i])i++; + return i ? ct(a[i], u[i]) : a[i] === b ? -1 : u[i] === b ? 1 : 0 + }, t) : p + }, ot.matches = function (e, t) { + return ot(e, null, null, t) + }, ot.matchesSelector = function (e, t) { + if ((e.ownerDocument || e) !== p && c(e), t = t.replace(Y, "='$1']"), !(!n.matchesSelector || !h || g && g.test(t) || d && d.test(t)))try { + var r = m.call(e, t); + if (r || n.disconnectedMatch || e.document && 11 !== e.document.nodeType)return r + } catch (i) { + } + return ot(t, p, null, [e]).length > 0 + }, ot.contains = function (e, t) { + return (e.ownerDocument || e) !== p && c(e), y(e, t) + }, ot.attr = function (e, t) { + (e.ownerDocument || e) !== p && c(e); + var r = i.attrHandle[t.toLowerCase()], o = r && A.call(i.attrHandle, t.toLowerCase()) ? r(e, t, !h) : undefined; + return o === undefined ? n.attributes || !h ? e.getAttribute(t) : (o = e.getAttributeNode(t)) && o.specified ? o.value : null : o + }, ot.error = function (e) { + throw Error("Syntax error, unrecognized expression: " + e) + }, ot.uniqueSort = function (e) { + var t, r = [], i = 0, o = 0; + if (E = !n.detectDuplicates, l = !n.sortStable && e.slice(0), e.sort(S), E) { + while (t = e[o++])t === e[o] && (i = r.push(o)); + while (i--)e.splice(r[i], 1) + } + return e + }, o = ot.getText = function (e) { + var t, n = "", r = 0, i = e.nodeType; + if (i) { + if (1 === i || 9 === i || 11 === i) { + if ("string" == typeof e.textContent)return e.textContent; + for (e = e.firstChild; e; e = e.nextSibling)n += o(e) + } else if (3 === i || 4 === i)return e.nodeValue + } else for (; t = e[r]; r++)n += o(t); + return n + }, i = ot.selectors = { + cacheLength: 50, + createPseudo: at, + match: J, + attrHandle: {}, + find: {}, + relative: { + ">": {dir: "parentNode", first: !0}, + " ": {dir: "parentNode"}, + "+": {dir: "previousSibling", first: !0}, + "~": {dir: "previousSibling"} + }, + preFilter: { + ATTR: function (e) { + return e[1] = e[1].replace(nt, rt), e[3] = (e[4] || e[5] || "").replace(nt, rt), "~=" === e[2] && (e[3] = " " + e[3] + " "), e.slice(0, 4) + }, CHILD: function (e) { + return e[1] = e[1].toLowerCase(), "nth" === e[1].slice(0, 3) ? (e[3] || ot.error(e[0]), e[4] = +(e[4] ? e[5] + (e[6] || 1) : 2 * ("even" === e[3] || "odd" === e[3])), e[5] = +(e[7] + e[8] || "odd" === e[3])) : e[3] && ot.error(e[0]), e + }, PSEUDO: function (e) { + var t, n = !e[5] && e[2]; + return J.CHILD.test(e[0]) ? null : (e[3] && e[4] !== undefined ? e[2] = e[4] : n && V.test(n) && (t = gt(n, !0)) && (t = n.indexOf(")", n.length - t) - n.length) && (e[0] = e[0].slice(0, t), e[2] = n.slice(0, t)), e.slice(0, 3)) + } + }, + filter: { + TAG: function (e) { + var t = e.replace(nt, rt).toLowerCase(); + return "*" === e ? function () { + return !0 + } : function (e) { + return e.nodeName && e.nodeName.toLowerCase() === t + } + }, CLASS: function (e) { + var t = C[e + " "]; + return t || (t = RegExp("(^|" + M + ")" + e + "(" + M + "|$)")) && C(e, function (e) { + return t.test("string" == typeof e.className && e.className || typeof e.getAttribute !== j && e.getAttribute("class") || "") + }) + }, ATTR: function (e, t, n) { + return function (r) { + var i = ot.attr(r, e); + return null == i ? "!=" === t : t ? (i += "", "=" === t ? i === n : "!=" === t ? i !== n : "^=" === t ? n && 0 === i.indexOf(n) : "*=" === t ? n && i.indexOf(n) > -1 : "$=" === t ? n && i.slice(-n.length) === n : "~=" === t ? (" " + i + " ").indexOf(n) > -1 : "|=" === t ? i === n || i.slice(0, n.length + 1) === n + "-" : !1) : !0 + } + }, CHILD: function (e, t, n, r, i) { + var o = "nth" !== e.slice(0, 3), s = "last" !== e.slice(-4), a = "of-type" === t; + return 1 === r && 0 === i ? function (e) { + return !!e.parentNode + } : function (t, n, u) { + var l, c, p, f, h, d, g = o !== s ? "nextSibling" : "previousSibling", m = t.parentNode, y = a && t.nodeName.toLowerCase(), x = !u && !a; + if (m) { + if (o) { + while (g) { + p = t; + while (p = p[g])if (a ? p.nodeName.toLowerCase() === y : 1 === p.nodeType)return !1; + d = g = "only" === e && !d && "nextSibling" + } + return !0 + } + if (d = [s ? m.firstChild : m.lastChild], s && x) { + c = m[v] || (m[v] = {}), l = c[e] || [], h = l[0] === w && l[1], f = l[0] === w && l[2], p = h && m.childNodes[h]; + while (p = ++h && p && p[g] || (f = h = 0) || d.pop())if (1 === p.nodeType && ++f && p === t) { + c[e] = [w, h, f]; + break + } + } else if (x && (l = (t[v] || (t[v] = {}))[e]) && l[0] === w)f = l[1]; else while (p = ++h && p && p[g] || (f = h = 0) || d.pop())if ((a ? p.nodeName.toLowerCase() === y : 1 === p.nodeType) && ++f && (x && ((p[v] || (p[v] = {}))[e] = [w, f]), p === t))break; + return f -= i, f === r || 0 === f % r && f / r >= 0 + } + } + }, PSEUDO: function (e, t) { + var n, r = i.pseudos[e] || i.setFilters[e.toLowerCase()] || ot.error("unsupported pseudo: " + e); + return r[v] ? r(t) : r.length > 1 ? (n = [e, e, "", t], i.setFilters.hasOwnProperty(e.toLowerCase()) ? at(function (e, n) { + var i, o = r(e, t), s = o.length; + while (s--)i = P.call(e, o[s]), e[i] = !(n[i] = o[s]) + }) : function (e) { + return r(e, 0, n) + }) : r + } + }, + pseudos: { + not: at(function (e) { + var t = [], n = [], r = a(e.replace(z, "$1")); + return r[v] ? at(function (e, t, n, i) { + var o, s = r(e, null, i, []), a = e.length; + while (a--)(o = s[a]) && (e[a] = !(t[a] = o)) + }) : function (e, i, o) { + return t[0] = e, r(t, null, o, n), !n.pop() + } + }), has: at(function (e) { + return function (t) { + return ot(e, t).length > 0 + } + }), contains: at(function (e) { + return function (t) { + return (t.textContent || t.innerText || o(t)).indexOf(e) > -1 + } + }), lang: at(function (e) { + return G.test(e || "") || ot.error("unsupported lang: " + e), e = e.replace(nt, rt).toLowerCase(), function (t) { + var n; + do if (n = h ? t.lang : t.getAttribute("xml:lang") || t.getAttribute("lang"))return n = n.toLowerCase(), n === e || 0 === n.indexOf(e + "-"); while ((t = t.parentNode) && 1 === t.nodeType); + return !1 + } + }), target: function (t) { + var n = e.location && e.location.hash; + return n && n.slice(1) === t.id + }, root: function (e) { + return e === f + }, focus: function (e) { + return e === p.activeElement && (!p.hasFocus || p.hasFocus()) && !!(e.type || e.href || ~e.tabIndex) + }, enabled: function (e) { + return e.disabled === !1 + }, disabled: function (e) { + return e.disabled === !0 + }, checked: function (e) { + var t = e.nodeName.toLowerCase(); + return "input" === t && !!e.checked || "option" === t && !!e.selected + }, selected: function (e) { + return e.parentNode && e.parentNode.selectedIndex, e.selected === !0 + }, empty: function (e) { + for (e = e.firstChild; e; e = e.nextSibling)if (e.nodeName > "@" || 3 === e.nodeType || 4 === e.nodeType)return !1; + return !0 + }, parent: function (e) { + return !i.pseudos.empty(e) + }, header: function (e) { + return et.test(e.nodeName) + }, input: function (e) { + return Z.test(e.nodeName) + }, button: function (e) { + var t = e.nodeName.toLowerCase(); + return "input" === t && "button" === e.type || "button" === t + }, text: function (e) { + var t; + return "input" === e.nodeName.toLowerCase() && "text" === e.type && (null == (t = e.getAttribute("type")) || t.toLowerCase() === e.type) + }, first: ht(function () { + return [0] + }), last: ht(function (e, t) { + return [t - 1] + }), eq: ht(function (e, t, n) { + return [0 > n ? n + t : n] + }), even: ht(function (e, t) { + var n = 0; + for (; t > n; n += 2)e.push(n); + return e + }), odd: ht(function (e, t) { + var n = 1; + for (; t > n; n += 2)e.push(n); + return e + }), lt: ht(function (e, t, n) { + var r = 0 > n ? n + t : n; + for (; --r >= 0;)e.push(r); + return e + }), gt: ht(function (e, t, n) { + var r = 0 > n ? n + t : n; + for (; t > ++r;)e.push(r); + return e + }) + } + }, i.pseudos.nth = i.pseudos.eq; + for (t in{radio: !0, checkbox: !0, file: !0, password: !0, image: !0})i.pseudos[t] = pt(t); + for (t in{submit: !0, reset: !0})i.pseudos[t] = ft(t); + function dt() { + } + + dt.prototype = i.filters = i.pseudos, i.setFilters = new dt; + function gt(e, t) { + var n, r, o, s, a, u, l, c = k[e + " "]; + if (c)return t ? 0 : c.slice(0); + a = e, u = [], l = i.preFilter; + while (a) { + (!n || (r = _.exec(a))) && (r && (a = a.slice(r[0].length) || a), u.push(o = [])), n = !1, (r = X.exec(a)) && (n = r.shift(), o.push({ + value: n, + type: r[0].replace(z, " ") + }), a = a.slice(n.length)); + for (s in i.filter)!(r = J[s].exec(a)) || l[s] && !(r = l[s](r)) || (n = r.shift(), o.push({ + value: n, + type: s, + matches: r + }), a = a.slice(n.length)); + if (!n)break + } + return t ? a.length : a ? ot.error(e) : k(e, u).slice(0) + } + + function mt(e) { + var t = 0, n = e.length, r = ""; + for (; n > t; t++)r += e[t].value; + return r + } + + function yt(e, t, n) { + var i = t.dir, o = n && "parentNode" === i, s = T++; + return t.first ? function (t, n, r) { + while (t = t[i])if (1 === t.nodeType || o)return e(t, n, r) + } : function (t, n, a) { + var u, l, c, p = w + " " + s; + if (a) { + while (t = t[i])if ((1 === t.nodeType || o) && e(t, n, a))return !0 + } else while (t = t[i])if (1 === t.nodeType || o)if (c = t[v] || (t[v] = {}), (l = c[i]) && l[0] === p) { + if ((u = l[1]) === !0 || u === r)return u === !0 + } else if (l = c[i] = [p], l[1] = e(t, n, a) || r, l[1] === !0)return !0 + } + } + + function vt(e) { + return e.length > 1 ? function (t, n, r) { + var i = e.length; + while (i--)if (!e[i](t, n, r))return !1; + return !0 + } : e[0] + } + + function xt(e, t, n, r, i) { + var o, s = [], a = 0, u = e.length, l = null != t; + for (; u > a; a++)(o = e[a]) && (!n || n(o, r, i)) && (s.push(o), l && t.push(a)); + return s + } + + function bt(e, t, n, r, i, o) { + return r && !r[v] && (r = bt(r)), i && !i[v] && (i = bt(i, o)), at(function (o, s, a, u) { + var l, c, p, f = [], h = [], d = s.length, g = o || Ct(t || "*", a.nodeType ? [a] : a, []), m = !e || !o && t ? g : xt(g, f, e, a, u), y = n ? i || (o ? e : d || r) ? [] : s : m; + if (n && n(m, y, a, u), r) { + l = xt(y, h), r(l, [], a, u), c = l.length; + while (c--)(p = l[c]) && (y[h[c]] = !(m[h[c]] = p)) + } + if (o) { + if (i || e) { + if (i) { + l = [], c = y.length; + while (c--)(p = y[c]) && l.push(m[c] = p); + i(null, y = [], l, u) + } + c = y.length; + while (c--)(p = y[c]) && (l = i ? P.call(o, p) : f[c]) > -1 && (o[l] = !(s[l] = p)) + } + } else y = xt(y === s ? y.splice(d, y.length) : y), i ? i(null, s, y, u) : O.apply(s, y) + }) + } + + function wt(e) { + var t, n, r, o = e.length, s = i.relative[e[0].type], a = s || i.relative[" "], l = s ? 1 : 0, c = yt(function (e) { + return e === t + }, a, !0), p = yt(function (e) { + return P.call(t, e) > -1 + }, a, !0), f = [function (e, n, r) { + return !s && (r || n !== u) || ((t = n).nodeType ? c(e, n, r) : p(e, n, r)) + }]; + for (; o > l; l++)if (n = i.relative[e[l].type])f = [yt(vt(f), n)]; else { + if (n = i.filter[e[l].type].apply(null, e[l].matches), n[v]) { + for (r = ++l; o > r; r++)if (i.relative[e[r].type])break; + return bt(l > 1 && vt(f), l > 1 && mt(e.slice(0, l - 1).concat({value: " " === e[l - 2].type ? "*" : ""})).replace(z, "$1"), n, r > l && wt(e.slice(l, r)), o > r && wt(e = e.slice(r)), o > r && mt(e)) + } + f.push(n) + } + return vt(f) + } + + function Tt(e, t) { + var n = 0, o = t.length > 0, s = e.length > 0, a = function (a, l, c, f, h) { + var d, g, m, y = [], v = 0, x = "0", b = a && [], T = null != h, C = u, k = a || s && i.find.TAG("*", h && l.parentNode || l), N = w += null == C ? 1 : Math.random() || .1; + for (T && (u = l !== p && l, r = n); null != (d = k[x]); x++) { + if (s && d) { + g = 0; + while (m = e[g++])if (m(d, l, c)) { + f.push(d); + break + } + T && (w = N, r = ++n) + } + o && ((d = !m && d) && v--, a && b.push(d)) + } + if (v += x, o && x !== v) { + g = 0; + while (m = t[g++])m(b, y, l, c); + if (a) { + if (v > 0)while (x--)b[x] || y[x] || (y[x] = q.call(f)); + y = xt(y) + } + O.apply(f, y), T && !a && y.length > 0 && v + t.length > 1 && ot.uniqueSort(f) + } + return T && (w = N, u = C), b + }; + return o ? at(a) : a + } + + a = ot.compile = function (e, t) { + var n, r = [], i = [], o = N[e + " "]; + if (!o) { + t || (t = gt(e)), n = t.length; + while (n--)o = wt(t[n]), o[v] ? r.push(o) : i.push(o); + o = N(e, Tt(i, r)) + } + return o + }; + function Ct(e, t, n) { + var r = 0, i = t.length; + for (; i > r; r++)ot(e, t[r], n); + return n + } + + function kt(e, t, r, o) { + var s, u, l, c, p, f = gt(e); + if (!o && 1 === f.length) { + if (u = f[0] = f[0].slice(0), u.length > 2 && "ID" === (l = u[0]).type && n.getById && 9 === t.nodeType && h && i.relative[u[1].type]) { + if (t = (i.find.ID(l.matches[0].replace(nt, rt), t) || [])[0], !t)return r; + e = e.slice(u.shift().value.length) + } + s = J.needsContext.test(e) ? 0 : u.length; + while (s--) { + if (l = u[s], i.relative[c = l.type])break; + if ((p = i.find[c]) && (o = p(l.matches[0].replace(nt, rt), U.test(u[0].type) && t.parentNode || t))) { + if (u.splice(s, 1), e = o.length && mt(u), !e)return O.apply(r, o), r; + break + } + } + } + return a(e, f)(o, t, !h, r, U.test(e)), r + } + + n.sortStable = v.split("").sort(S).join("") === v, n.detectDuplicates = E, c(), n.sortDetached = ut(function (e) { + return 1 & e.compareDocumentPosition(p.createElement("div")) + }), ut(function (e) { + return e.innerHTML = "", "#" === e.firstChild.getAttribute("href") + }) || lt("type|href|height|width", function (e, t, n) { + return n ? undefined : e.getAttribute(t, "type" === t.toLowerCase() ? 1 : 2) + }), n.attributes && ut(function (e) { + return e.innerHTML = "", e.firstChild.setAttribute("value", ""), "" === e.firstChild.getAttribute("value") + }) || lt("value", function (e, t, n) { + return n || "input" !== e.nodeName.toLowerCase() ? undefined : e.defaultValue + }), ut(function (e) { + return null == e.getAttribute("disabled") + }) || lt(R, function (e, t, n) { + var r; + return n ? undefined : (r = e.getAttributeNode(t)) && r.specified ? r.value : e[t] === !0 ? t.toLowerCase() : null + }), x.find = ot, x.expr = ot.selectors, x.expr[":"] = x.expr.pseudos, x.unique = ot.uniqueSort, x.text = ot.getText, x.isXMLDoc = ot.isXML, x.contains = ot.contains + }(e); + var D = {}; + + function A(e) { + var t = D[e] = {}; + return x.each(e.match(w) || [], function (e, n) { + t[n] = !0 + }), t + } + + x.Callbacks = function (e) { + e = "string" == typeof e ? D[e] || A(e) : x.extend({}, e); + var t, n, r, i, o, s, a = [], u = !e.once && [], l = function (p) { + for (t = e.memory && p, n = !0, s = i || 0, i = 0, o = a.length, r = !0; a && o > s; s++)if (a[s].apply(p[0], p[1]) === !1 && e.stopOnFalse) { + t = !1; + break + } + r = !1, a && (u ? u.length && l(u.shift()) : t ? a = [] : c.disable()) + }, c = { + add: function () { + if (a) { + var n = a.length; + (function s(t) { + x.each(t, function (t, n) { + var r = x.type(n); + "function" === r ? e.unique && c.has(n) || a.push(n) : n && n.length && "string" !== r && s(n) + }) + })(arguments), r ? o = a.length : t && (i = n, l(t)) + } + return this + }, remove: function () { + return a && x.each(arguments, function (e, t) { + var n; + while ((n = x.inArray(t, a, n)) > -1)a.splice(n, 1), r && (o >= n && o--, s >= n && s--) + }), this + }, has: function (e) { + return e ? x.inArray(e, a) > -1 : !(!a || !a.length) + }, empty: function () { + return a = [], o = 0, this + }, disable: function () { + return a = u = t = undefined, this + }, disabled: function () { + return !a + }, lock: function () { + return u = undefined, t || c.disable(), this + }, locked: function () { + return !u + }, fireWith: function (e, t) { + return !a || n && !u || (t = t || [], t = [e, t.slice ? t.slice() : t], r ? u.push(t) : l(t)), this + }, fire: function () { + return c.fireWith(this, arguments), this + }, fired: function () { + return !!n + } + }; + return c + }, x.extend({ + Deferred: function (e) { + var t = [["resolve", "done", x.Callbacks("once memory"), "resolved"], ["reject", "fail", x.Callbacks("once memory"), "rejected"], ["notify", "progress", x.Callbacks("memory")]], n = "pending", r = { + state: function () { + return n + }, always: function () { + return i.done(arguments).fail(arguments), this + }, then: function () { + var e = arguments; + return x.Deferred(function (n) { + x.each(t, function (t, o) { + var s = o[0], a = x.isFunction(e[t]) && e[t]; + i[o[1]](function () { + var e = a && a.apply(this, arguments); + e && x.isFunction(e.promise) ? e.promise().done(n.resolve).fail(n.reject).progress(n.notify) : n[s + "With"](this === r ? n.promise() : this, a ? [e] : arguments) + }) + }), e = null + }).promise() + }, promise: function (e) { + return null != e ? x.extend(e, r) : r + } + }, i = {}; + return r.pipe = r.then, x.each(t, function (e, o) { + var s = o[2], a = o[3]; + r[o[1]] = s.add, a && s.add(function () { + n = a + }, t[1 ^ e][2].disable, t[2][2].lock), i[o[0]] = function () { + return i[o[0] + "With"](this === i ? r : this, arguments), this + }, i[o[0] + "With"] = s.fireWith + }), r.promise(i), e && e.call(i, i), i + }, when: function (e) { + var t = 0, n = d.call(arguments), r = n.length, i = 1 !== r || e && x.isFunction(e.promise) ? r : 0, o = 1 === i ? e : x.Deferred(), s = function (e, t, n) { + return function (r) { + t[e] = this, n[e] = arguments.length > 1 ? d.call(arguments) : r, n === a ? o.notifyWith(t, n) : --i || o.resolveWith(t, n) + } + }, a, u, l; + if (r > 1)for (a = Array(r), u = Array(r), l = Array(r); r > t; t++)n[t] && x.isFunction(n[t].promise) ? n[t].promise().done(s(t, l, n)).fail(o.reject).progress(s(t, u, a)) : --i; + return i || o.resolveWith(l, n), o.promise() + } + }), x.support = function (t) { + var n = o.createElement("input"), r = o.createDocumentFragment(), i = o.createElement("div"), s = o.createElement("select"), a = s.appendChild(o.createElement("option")); + return n.type ? (n.type = "checkbox", t.checkOn = "" !== n.value, t.optSelected = a.selected, t.reliableMarginRight = !0, t.boxSizingReliable = !0, t.pixelPosition = !1, n.checked = !0, t.noCloneChecked = n.cloneNode(!0).checked, s.disabled = !0, t.optDisabled = !a.disabled, n = o.createElement("input"), n.value = "t", n.type = "radio", t.radioValue = "t" === n.value, n.setAttribute("checked", "t"), n.setAttribute("name", "t"), r.appendChild(n), t.checkClone = r.cloneNode(!0).cloneNode(!0).lastChild.checked, t.focusinBubbles = "onfocusin"in e, i.style.backgroundClip = "content-box", i.cloneNode(!0).style.backgroundClip = "", t.clearCloneStyle = "content-box" === i.style.backgroundClip, x(function () { + var n, r, s = "padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box", a = o.getElementsByTagName("body")[0]; + a && (n = o.createElement("div"), n.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px", a.appendChild(n).appendChild(i), i.innerHTML = "", i.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%", x.swap(a, null != a.style.zoom ? {zoom: 1} : {}, function () { + t.boxSizing = 4 === i.offsetWidth + }), e.getComputedStyle && (t.pixelPosition = "1%" !== (e.getComputedStyle(i, null) || {}).top, t.boxSizingReliable = "4px" === (e.getComputedStyle(i, null) || {width: "4px"}).width, r = i.appendChild(o.createElement("div")), r.style.cssText = i.style.cssText = s, r.style.marginRight = r.style.width = "0", i.style.width = "1px", t.reliableMarginRight = !parseFloat((e.getComputedStyle(r, null) || {}).marginRight)), a.removeChild(n)) + }), t) : t + }({}); + var L, q, H = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, O = /([A-Z])/g; + + function F() { + Object.defineProperty(this.cache = {}, 0, { + get: function () { + return {} + } + }), this.expando = x.expando + Math.random() + } + + F.uid = 1, F.accepts = function (e) { + return e.nodeType ? 1 === e.nodeType || 9 === e.nodeType : !0 + }, F.prototype = { + key: function (e) { + if (!F.accepts(e))return 0; + var t = {}, n = e[this.expando]; + if (!n) { + n = F.uid++; + try { + t[this.expando] = {value: n}, Object.defineProperties(e, t) + } catch (r) { + t[this.expando] = n, x.extend(e, t) + } + } + return this.cache[n] || (this.cache[n] = {}), n + }, set: function (e, t, n) { + var r, i = this.key(e), o = this.cache[i]; + if ("string" == typeof t)o[t] = n; else if (x.isEmptyObject(o))x.extend(this.cache[i], t); else for (r in t)o[r] = t[r]; + return o + }, get: function (e, t) { + var n = this.cache[this.key(e)]; + return t === undefined ? n : n[t] + }, access: function (e, t, n) { + var r; + return t === undefined || t && "string" == typeof t && n === undefined ? (r = this.get(e, t), r !== undefined ? r : this.get(e, x.camelCase(t))) : (this.set(e, t, n), n !== undefined ? n : t) + }, remove: function (e, t) { + var n, r, i, o = this.key(e), s = this.cache[o]; + if (t === undefined)this.cache[o] = {}; else { + x.isArray(t) ? r = t.concat(t.map(x.camelCase)) : (i = x.camelCase(t), t in s ? r = [t, i] : (r = i, r = r in s ? [r] : r.match(w) || [])), n = r.length; + while (n--)delete s[r[n]] + } + }, hasData: function (e) { + return !x.isEmptyObject(this.cache[e[this.expando]] || {}) + }, discard: function (e) { + e[this.expando] && delete this.cache[e[this.expando]] + } + }, L = new F, q = new F, x.extend({ + acceptData: F.accepts, hasData: function (e) { + return L.hasData(e) || q.hasData(e) + }, data: function (e, t, n) { + return L.access(e, t, n) + }, removeData: function (e, t) { + L.remove(e, t) + }, _data: function (e, t, n) { + return q.access(e, t, n) + }, _removeData: function (e, t) { + q.remove(e, t) + } + }), x.fn.extend({ + data: function (e, t) { + var n, r, i = this[0], o = 0, s = null; + if (e === undefined) { + if (this.length && (s = L.get(i), 1 === i.nodeType && !q.get(i, "hasDataAttrs"))) { + for (n = i.attributes; n.length > o; o++)r = n[o].name, 0 === r.indexOf("data-") && (r = x.camelCase(r.slice(5)), P(i, r, s[r])); + q.set(i, "hasDataAttrs", !0) + } + return s + } + return "object" == typeof e ? this.each(function () { + L.set(this, e) + }) : x.access(this, function (t) { + var n, r = x.camelCase(e); + if (i && t === undefined) { + if (n = L.get(i, e), n !== undefined)return n; + if (n = L.get(i, r), n !== undefined)return n; + if (n = P(i, r, undefined), n !== undefined)return n + } else this.each(function () { + var n = L.get(this, r); + L.set(this, r, t), -1 !== e.indexOf("-") && n !== undefined && L.set(this, e, t) + }) + }, null, t, arguments.length > 1, null, !0) + }, removeData: function (e) { + return this.each(function () { + L.remove(this, e) + }) + } + }); + function P(e, t, n) { + var r; + if (n === undefined && 1 === e.nodeType)if (r = "data-" + t.replace(O, "-$1").toLowerCase(), n = e.getAttribute(r), "string" == typeof n) { + try { + n = "true" === n ? !0 : "false" === n ? !1 : "null" === n ? null : +n + "" === n ? +n : H.test(n) ? JSON.parse(n) : n + } catch (i) { + } + L.set(e, t, n) + } else n = undefined; + return n + } + + x.extend({ + queue: function (e, t, n) { + var r; + return e ? (t = (t || "fx") + "queue", r = q.get(e, t), n && (!r || x.isArray(n) ? r = q.access(e, t, x.makeArray(n)) : r.push(n)), r || []) : undefined + }, dequeue: function (e, t) { + t = t || "fx"; + var n = x.queue(e, t), r = n.length, i = n.shift(), o = x._queueHooks(e, t), s = function () { + x.dequeue(e, t) + }; + "inprogress" === i && (i = n.shift(), r--), i && ("fx" === t && n.unshift("inprogress"), delete o.stop, i.call(e, s, o)), !r && o && o.empty.fire() + }, _queueHooks: function (e, t) { + var n = t + "queueHooks"; + return q.get(e, n) || q.access(e, n, { + empty: x.Callbacks("once memory").add(function () { + q.remove(e, [t + "queue", n]) + }) + }) + } + }), x.fn.extend({ + queue: function (e, t) { + var n = 2; + return "string" != typeof e && (t = e, e = "fx", n--), n > arguments.length ? x.queue(this[0], e) : t === undefined ? this : this.each(function () { + var n = x.queue(this, e, t); + x._queueHooks(this, e), "fx" === e && "inprogress" !== n[0] && x.dequeue(this, e) + }) + }, dequeue: function (e) { + return this.each(function () { + x.dequeue(this, e) + }) + }, delay: function (e, t) { + return e = x.fx ? x.fx.speeds[e] || e : e, t = t || "fx", this.queue(t, function (t, n) { + var r = setTimeout(t, e); + n.stop = function () { + clearTimeout(r) + } + }) + }, clearQueue: function (e) { + return this.queue(e || "fx", []) + }, promise: function (e, t) { + var n, r = 1, i = x.Deferred(), o = this, s = this.length, a = function () { + --r || i.resolveWith(o, [o]) + }; + "string" != typeof e && (t = e, e = undefined), e = e || "fx"; + while (s--)n = q.get(o[s], e + "queueHooks"), n && n.empty && (r++, n.empty.add(a)); + return a(), i.promise(t) + } + }); + var R, M, W = /[\t\r\n\f]/g, $ = /\r/g, B = /^(?:input|select|textarea|button)$/i; + x.fn.extend({ + attr: function (e, t) { + return x.access(this, x.attr, e, t, arguments.length > 1) + }, removeAttr: function (e) { + return this.each(function () { + x.removeAttr(this, e) + }) + }, prop: function (e, t) { + return x.access(this, x.prop, e, t, arguments.length > 1) + }, removeProp: function (e) { + return this.each(function () { + delete this[x.propFix[e] || e] + }) + }, addClass: function (e) { + var t, n, r, i, o, s = 0, a = this.length, u = "string" == typeof e && e; + if (x.isFunction(e))return this.each(function (t) { + x(this).addClass(e.call(this, t, this.className)) + }); + if (u)for (t = (e || "").match(w) || []; a > s; s++)if (n = this[s], r = 1 === n.nodeType && (n.className ? (" " + n.className + " ").replace(W, " ") : " ")) { + o = 0; + while (i = t[o++])0 > r.indexOf(" " + i + " ") && (r += i + " "); + n.className = x.trim(r) + } + return this + }, removeClass: function (e) { + var t, n, r, i, o, s = 0, a = this.length, u = 0 === arguments.length || "string" == typeof e && e; + if (x.isFunction(e))return this.each(function (t) { + x(this).removeClass(e.call(this, t, this.className)) + }); + if (u)for (t = (e || "").match(w) || []; a > s; s++)if (n = this[s], r = 1 === n.nodeType && (n.className ? (" " + n.className + " ").replace(W, " ") : "")) { + o = 0; + while (i = t[o++])while (r.indexOf(" " + i + " ") >= 0)r = r.replace(" " + i + " ", " "); + n.className = e ? x.trim(r) : "" + } + return this + }, toggleClass: function (e, t) { + var n = typeof e; + return "boolean" == typeof t && "string" === n ? t ? this.addClass(e) : this.removeClass(e) : x.isFunction(e) ? this.each(function (n) { + x(this).toggleClass(e.call(this, n, this.className, t), t) + }) : this.each(function () { + if ("string" === n) { + var t, i = 0, o = x(this), s = e.match(w) || []; + while (t = s[i++])o.hasClass(t) ? o.removeClass(t) : o.addClass(t) + } else(n === r || "boolean" === n) && (this.className && q.set(this, "__className__", this.className), this.className = this.className || e === !1 ? "" : q.get(this, "__className__") || "") + }) + }, hasClass: function (e) { + var t = " " + e + " ", n = 0, r = this.length; + for (; r > n; n++)if (1 === this[n].nodeType && (" " + this[n].className + " ").replace(W, " ").indexOf(t) >= 0)return !0; + return !1 + }, val: function (e) { + var t, n, r, i = this[0]; + { + if (arguments.length)return r = x.isFunction(e), this.each(function (n) { + var i; + 1 === this.nodeType && (i = r ? e.call(this, n, x(this).val()) : e, null == i ? i = "" : "number" == typeof i ? i += "" : x.isArray(i) && (i = x.map(i, function (e) { + return null == e ? "" : e + "" + })), t = x.valHooks[this.type] || x.valHooks[this.nodeName.toLowerCase()], t && "set"in t && t.set(this, i, "value") !== undefined || (this.value = i)) + }); + if (i)return t = x.valHooks[i.type] || x.valHooks[i.nodeName.toLowerCase()], t && "get"in t && (n = t.get(i, "value")) !== undefined ? n : (n = i.value, "string" == typeof n ? n.replace($, "") : null == n ? "" : n) + } + } + }), x.extend({ + valHooks: { + option: { + get: function (e) { + var t = e.attributes.value; + return !t || t.specified ? e.value : e.text + } + }, select: { + get: function (e) { + var t, n, r = e.options, i = e.selectedIndex, o = "select-one" === e.type || 0 > i, s = o ? null : [], a = o ? i + 1 : r.length, u = 0 > i ? a : o ? i : 0; + for (; a > u; u++)if (n = r[u], !(!n.selected && u !== i || (x.support.optDisabled ? n.disabled : null !== n.getAttribute("disabled")) || n.parentNode.disabled && x.nodeName(n.parentNode, "optgroup"))) { + if (t = x(n).val(), o)return t; + s.push(t) + } + return s + }, set: function (e, t) { + var n, r, i = e.options, o = x.makeArray(t), s = i.length; + while (s--)r = i[s], (r.selected = x.inArray(x(r).val(), o) >= 0) && (n = !0); + return n || (e.selectedIndex = -1), o + } + } + }, attr: function (e, t, n) { + var i, o, s = e.nodeType; + if (e && 3 !== s && 8 !== s && 2 !== s)return typeof e.getAttribute === r ? x.prop(e, t, n) : (1 === s && x.isXMLDoc(e) || (t = t.toLowerCase(), i = x.attrHooks[t] || (x.expr.match.bool.test(t) ? M : R)), n === undefined ? i && "get"in i && null !== (o = i.get(e, t)) ? o : (o = x.find.attr(e, t), null == o ? undefined : o) : null !== n ? i && "set"in i && (o = i.set(e, n, t)) !== undefined ? o : (e.setAttribute(t, n + ""), n) : (x.removeAttr(e, t), undefined)) + }, removeAttr: function (e, t) { + var n, r, i = 0, o = t && t.match(w); + if (o && 1 === e.nodeType)while (n = o[i++])r = x.propFix[n] || n, x.expr.match.bool.test(n) && (e[r] = !1), e.removeAttribute(n) + }, attrHooks: { + type: { + set: function (e, t) { + if (!x.support.radioValue && "radio" === t && x.nodeName(e, "input")) { + var n = e.value; + return e.setAttribute("type", t), n && (e.value = n), t + } + } + } + }, propFix: {"for": "htmlFor", "class": "className"}, prop: function (e, t, n) { + var r, i, o, s = e.nodeType; + if (e && 3 !== s && 8 !== s && 2 !== s)return o = 1 !== s || !x.isXMLDoc(e), o && (t = x.propFix[t] || t, i = x.propHooks[t]), n !== undefined ? i && "set"in i && (r = i.set(e, n, t)) !== undefined ? r : e[t] = n : i && "get"in i && null !== (r = i.get(e, t)) ? r : e[t] + }, propHooks: { + tabIndex: { + get: function (e) { + return e.hasAttribute("tabindex") || B.test(e.nodeName) || e.href ? e.tabIndex : -1 + } + } + } + }), M = { + set: function (e, t, n) { + return t === !1 ? x.removeAttr(e, n) : e.setAttribute(n, n), n + } + }, x.each(x.expr.match.bool.source.match(/\w+/g), function (e, t) { + var n = x.expr.attrHandle[t] || x.find.attr; + x.expr.attrHandle[t] = function (e, t, r) { + var i = x.expr.attrHandle[t], o = r ? undefined : (x.expr.attrHandle[t] = undefined) != n(e, t, r) ? t.toLowerCase() : null; + return x.expr.attrHandle[t] = i, o + } + }), x.support.optSelected || (x.propHooks.selected = { + get: function (e) { + var t = e.parentNode; + return t && t.parentNode && t.parentNode.selectedIndex, null + } + }), x.each(["tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable"], function () { + x.propFix[this.toLowerCase()] = this + }), x.each(["radio", "checkbox"], function () { + x.valHooks[this] = { + set: function (e, t) { + return x.isArray(t) ? e.checked = x.inArray(x(e).val(), t) >= 0 : undefined + } + }, x.support.checkOn || (x.valHooks[this].get = function (e) { + return null === e.getAttribute("value") ? "on" : e.value + }) + }); + var I = /^key/, z = /^(?:mouse|contextmenu)|click/, _ = /^(?:focusinfocus|focusoutblur)$/, X = /^([^.]*)(?:\.(.+)|)$/; + + function U() { + return !0 + } + + function Y() { + return !1 + } + + function V() { + try { + return o.activeElement + } catch (e) { + } + } + + x.event = { + global: {}, + add: function (e, t, n, i, o) { + var s, a, u, l, c, p, f, h, d, g, m, y = q.get(e); + if (y) { + n.handler && (s = n, n = s.handler, o = s.selector), n.guid || (n.guid = x.guid++), (l = y.events) || (l = y.events = {}), (a = y.handle) || (a = y.handle = function (e) { + return typeof x === r || e && x.event.triggered === e.type ? undefined : x.event.dispatch.apply(a.elem, arguments) + }, a.elem = e), t = (t || "").match(w) || [""], c = t.length; + while (c--)u = X.exec(t[c]) || [], d = m = u[1], g = (u[2] || "").split(".").sort(), d && (f = x.event.special[d] || {}, d = (o ? f.delegateType : f.bindType) || d, f = x.event.special[d] || {}, p = x.extend({ + type: d, + origType: m, + data: i, + handler: n, + guid: n.guid, + selector: o, + needsContext: o && x.expr.match.needsContext.test(o), + namespace: g.join(".") + }, s), (h = l[d]) || (h = l[d] = [], h.delegateCount = 0, f.setup && f.setup.call(e, i, g, a) !== !1 || e.addEventListener && e.addEventListener(d, a, !1)), f.add && (f.add.call(e, p), p.handler.guid || (p.handler.guid = n.guid)), o ? h.splice(h.delegateCount++, 0, p) : h.push(p), x.event.global[d] = !0); + e = null + } + }, + remove: function (e, t, n, r, i) { + var o, s, a, u, l, c, p, f, h, d, g, m = q.hasData(e) && q.get(e); + if (m && (u = m.events)) { + t = (t || "").match(w) || [""], l = t.length; + while (l--)if (a = X.exec(t[l]) || [], h = g = a[1], d = (a[2] || "").split(".").sort(), h) { + p = x.event.special[h] || {}, h = (r ? p.delegateType : p.bindType) || h, f = u[h] || [], a = a[2] && RegExp("(^|\\.)" + d.join("\\.(?:.*\\.|)") + "(\\.|$)"), s = o = f.length; + while (o--)c = f[o], !i && g !== c.origType || n && n.guid !== c.guid || a && !a.test(c.namespace) || r && r !== c.selector && ("**" !== r || !c.selector) || (f.splice(o, 1), c.selector && f.delegateCount--, p.remove && p.remove.call(e, c)); + s && !f.length && (p.teardown && p.teardown.call(e, d, m.handle) !== !1 || x.removeEvent(e, h, m.handle), delete u[h]) + } else for (h in u)x.event.remove(e, h + t[l], n, r, !0); + x.isEmptyObject(u) && (delete m.handle, q.remove(e, "events")) + } + }, + trigger: function (t, n, r, i) { + var s, a, u, l, c, p, f, h = [r || o], d = y.call(t, "type") ? t.type : t, g = y.call(t, "namespace") ? t.namespace.split(".") : []; + if (a = u = r = r || o, 3 !== r.nodeType && 8 !== r.nodeType && !_.test(d + x.event.triggered) && (d.indexOf(".") >= 0 && (g = d.split("."), d = g.shift(), g.sort()), c = 0 > d.indexOf(":") && "on" + d, t = t[x.expando] ? t : new x.Event(d, "object" == typeof t && t), t.isTrigger = i ? 2 : 3, t.namespace = g.join("."), t.namespace_re = t.namespace ? RegExp("(^|\\.)" + g.join("\\.(?:.*\\.|)") + "(\\.|$)") : null, t.result = undefined, t.target || (t.target = r), n = null == n ? [t] : x.makeArray(n, [t]), f = x.event.special[d] || {}, i || !f.trigger || f.trigger.apply(r, n) !== !1)) { + if (!i && !f.noBubble && !x.isWindow(r)) { + for (l = f.delegateType || d, _.test(l + d) || (a = a.parentNode); a; a = a.parentNode)h.push(a), u = a; + u === (r.ownerDocument || o) && h.push(u.defaultView || u.parentWindow || e) + } + s = 0; + while ((a = h[s++]) && !t.isPropagationStopped())t.type = s > 1 ? l : f.bindType || d, p = (q.get(a, "events") || {})[t.type] && q.get(a, "handle"), p && p.apply(a, n), p = c && a[c], p && x.acceptData(a) && p.apply && p.apply(a, n) === !1 && t.preventDefault(); + return t.type = d, i || t.isDefaultPrevented() || f._default && f._default.apply(h.pop(), n) !== !1 || !x.acceptData(r) || c && x.isFunction(r[d]) && !x.isWindow(r) && (u = r[c], u && (r[c] = null), x.event.triggered = d, r[d](), x.event.triggered = undefined, u && (r[c] = u)), t.result + } + }, + dispatch: function (e) { + e = x.event.fix(e); + var t, n, r, i, o, s = [], a = d.call(arguments), u = (q.get(this, "events") || {})[e.type] || [], l = x.event.special[e.type] || {}; + if (a[0] = e, e.delegateTarget = this, !l.preDispatch || l.preDispatch.call(this, e) !== !1) { + s = x.event.handlers.call(this, e, u), t = 0; + while ((i = s[t++]) && !e.isPropagationStopped()) { + e.currentTarget = i.elem, n = 0; + while ((o = i.handlers[n++]) && !e.isImmediatePropagationStopped())(!e.namespace_re || e.namespace_re.test(o.namespace)) && (e.handleObj = o, e.data = o.data, r = ((x.event.special[o.origType] || {}).handle || o.handler).apply(i.elem, a), r !== undefined && (e.result = r) === !1 && (e.preventDefault(), e.stopPropagation())) + } + return l.postDispatch && l.postDispatch.call(this, e), e.result + } + }, + handlers: function (e, t) { + var n, r, i, o, s = [], a = t.delegateCount, u = e.target; + if (a && u.nodeType && (!e.button || "click" !== e.type))for (; u !== this; u = u.parentNode || this)if (u.disabled !== !0 || "click" !== e.type) { + for (r = [], n = 0; a > n; n++)o = t[n], i = o.selector + " ", r[i] === undefined && (r[i] = o.needsContext ? x(i, this).index(u) >= 0 : x.find(i, this, null, [u]).length), r[i] && r.push(o); + r.length && s.push({elem: u, handlers: r}) + } + return t.length > a && s.push({elem: this, handlers: t.slice(a)}), s + }, + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + fixHooks: {}, + keyHooks: { + props: "char charCode key keyCode".split(" "), filter: function (e, t) { + return null == e.which && (e.which = null != t.charCode ? t.charCode : t.keyCode), e + } + }, + mouseHooks: { + props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function (e, t) { + var n, r, i, s = t.button; + return null == e.pageX && null != t.clientX && (n = e.target.ownerDocument || o, r = n.documentElement, i = n.body, e.pageX = t.clientX + (r && r.scrollLeft || i && i.scrollLeft || 0) - (r && r.clientLeft || i && i.clientLeft || 0), e.pageY = t.clientY + (r && r.scrollTop || i && i.scrollTop || 0) - (r && r.clientTop || i && i.clientTop || 0)), e.which || s === undefined || (e.which = 1 & s ? 1 : 2 & s ? 3 : 4 & s ? 2 : 0), e + } + }, + fix: function (e) { + if (e[x.expando])return e; + var t, n, r, i = e.type, s = e, a = this.fixHooks[i]; + a || (this.fixHooks[i] = a = z.test(i) ? this.mouseHooks : I.test(i) ? this.keyHooks : {}), r = a.props ? this.props.concat(a.props) : this.props, e = new x.Event(s), t = r.length; + while (t--)n = r[t], e[n] = s[n]; + return e.target || (e.target = o), 3 === e.target.nodeType && (e.target = e.target.parentNode), a.filter ? a.filter(e, s) : e + }, + special: { + load: {noBubble: !0}, focus: { + trigger: function () { + return this !== V() && this.focus ? (this.focus(), !1) : undefined + }, delegateType: "focusin" + }, blur: { + trigger: function () { + return this === V() && this.blur ? (this.blur(), !1) : undefined + }, delegateType: "focusout" + }, click: { + trigger: function () { + return "checkbox" === this.type && this.click && x.nodeName(this, "input") ? (this.click(), !1) : undefined + }, _default: function (e) { + return x.nodeName(e.target, "a") + } + }, beforeunload: { + postDispatch: function (e) { + e.result !== undefined && (e.originalEvent.returnValue = e.result) + } + } + }, + simulate: function (e, t, n, r) { + var i = x.extend(new x.Event, n, {type: e, isSimulated: !0, originalEvent: {}}); + r ? x.event.trigger(i, null, t) : x.event.dispatch.call(t, i), i.isDefaultPrevented() && n.preventDefault() + } + }, x.removeEvent = function (e, t, n) { + e.removeEventListener && e.removeEventListener(t, n, !1) + }, x.Event = function (e, t) { + return this instanceof x.Event ? (e && e.type ? (this.originalEvent = e, this.type = e.type, this.isDefaultPrevented = e.defaultPrevented || e.getPreventDefault && e.getPreventDefault() ? U : Y) : this.type = e, t && x.extend(this, t), this.timeStamp = e && e.timeStamp || x.now(), this[x.expando] = !0, undefined) : new x.Event(e, t) + }, x.Event.prototype = { + isDefaultPrevented: Y, + isPropagationStopped: Y, + isImmediatePropagationStopped: Y, + preventDefault: function () { + var e = this.originalEvent; + this.isDefaultPrevented = U, e && e.preventDefault && e.preventDefault() + }, + stopPropagation: function () { + var e = this.originalEvent; + this.isPropagationStopped = U, e && e.stopPropagation && e.stopPropagation() + }, + stopImmediatePropagation: function () { + this.isImmediatePropagationStopped = U, this.stopPropagation() + } + }, x.each({mouseenter: "mouseover", mouseleave: "mouseout"}, function (e, t) { + x.event.special[e] = { + delegateType: t, bindType: t, handle: function (e) { + var n, r = this, i = e.relatedTarget, o = e.handleObj; + return (!i || i !== r && !x.contains(r, i)) && (e.type = o.origType, n = o.handler.apply(this, arguments), e.type = t), n + } + } + }), x.support.focusinBubbles || x.each({focus: "focusin", blur: "focusout"}, function (e, t) { + var n = 0, r = function (e) { + x.event.simulate(t, e.target, x.event.fix(e), !0) + }; + x.event.special[t] = { + setup: function () { + 0 === n++ && o.addEventListener(e, r, !0) + }, teardown: function () { + 0 === --n && o.removeEventListener(e, r, !0) + } + } + }), x.fn.extend({ + on: function (e, t, n, r, i) { + var o, s; + if ("object" == typeof e) { + "string" != typeof t && (n = n || t, t = undefined); + for (s in e)this.on(s, t, n, e[s], i); + return this + } + if (null == n && null == r ? (r = t, n = t = undefined) : null == r && ("string" == typeof t ? (r = n, n = undefined) : (r = n, n = t, t = undefined)), r === !1)r = Y; else if (!r)return this; + return 1 === i && (o = r, r = function (e) { + return x().off(e), o.apply(this, arguments) + }, r.guid = o.guid || (o.guid = x.guid++)), this.each(function () { + x.event.add(this, e, r, n, t) + }) + }, one: function (e, t, n, r) { + return this.on(e, t, n, r, 1) + }, off: function (e, t, n) { + var r, i; + if (e && e.preventDefault && e.handleObj)return r = e.handleObj, x(e.delegateTarget).off(r.namespace ? r.origType + "." + r.namespace : r.origType, r.selector, r.handler), this; + if ("object" == typeof e) { + for (i in e)this.off(i, t, e[i]); + return this + } + return (t === !1 || "function" == typeof t) && (n = t, t = undefined), n === !1 && (n = Y), this.each(function () { + x.event.remove(this, e, n, t) + }) + }, trigger: function (e, t) { + return this.each(function () { + x.event.trigger(e, t, this) + }) + }, triggerHandler: function (e, t) { + var n = this[0]; + return n ? x.event.trigger(e, t, n, !0) : undefined + } + }); + var G = /^.[^:#\[\.,]*$/, J = /^(?:parents|prev(?:Until|All))/, Q = x.expr.match.needsContext, K = { + children: !0, + contents: !0, + next: !0, + prev: !0 + }; + x.fn.extend({ + find: function (e) { + var t, n = [], r = this, i = r.length; + if ("string" != typeof e)return this.pushStack(x(e).filter(function () { + for (t = 0; i > t; t++)if (x.contains(r[t], this))return !0 + })); + for (t = 0; i > t; t++)x.find(e, r[t], n); + return n = this.pushStack(i > 1 ? x.unique(n) : n), n.selector = this.selector ? this.selector + " " + e : e, n + }, has: function (e) { + var t = x(e, this), n = t.length; + return this.filter(function () { + var e = 0; + for (; n > e; e++)if (x.contains(this, t[e]))return !0 + }) + }, not: function (e) { + return this.pushStack(et(this, e || [], !0)) + }, filter: function (e) { + return this.pushStack(et(this, e || [], !1)) + }, is: function (e) { + return !!et(this, "string" == typeof e && Q.test(e) ? x(e) : e || [], !1).length + }, closest: function (e, t) { + var n, r = 0, i = this.length, o = [], s = Q.test(e) || "string" != typeof e ? x(e, t || this.context) : 0; + for (; i > r; r++)for (n = this[r]; n && n !== t; n = n.parentNode)if (11 > n.nodeType && (s ? s.index(n) > -1 : 1 === n.nodeType && x.find.matchesSelector(n, e))) { + n = o.push(n); + break + } + return this.pushStack(o.length > 1 ? x.unique(o) : o) + }, index: function (e) { + return e ? "string" == typeof e ? g.call(x(e), this[0]) : g.call(this, e.jquery ? e[0] : e) : this[0] && this[0].parentNode ? this.first().prevAll().length : -1 + }, add: function (e, t) { + var n = "string" == typeof e ? x(e, t) : x.makeArray(e && e.nodeType ? [e] : e), r = x.merge(this.get(), n); + return this.pushStack(x.unique(r)) + }, addBack: function (e) { + return this.add(null == e ? this.prevObject : this.prevObject.filter(e)) + } + }); + function Z(e, t) { + while ((e = e[t]) && 1 !== e.nodeType); + return e + } + + x.each({ + parent: function (e) { + var t = e.parentNode; + return t && 11 !== t.nodeType ? t : null + }, parents: function (e) { + return x.dir(e, "parentNode") + }, parentsUntil: function (e, t, n) { + return x.dir(e, "parentNode", n) + }, next: function (e) { + return Z(e, "nextSibling") + }, prev: function (e) { + return Z(e, "previousSibling") + }, nextAll: function (e) { + return x.dir(e, "nextSibling") + }, prevAll: function (e) { + return x.dir(e, "previousSibling") + }, nextUntil: function (e, t, n) { + return x.dir(e, "nextSibling", n) + }, prevUntil: function (e, t, n) { + return x.dir(e, "previousSibling", n) + }, siblings: function (e) { + return x.sibling((e.parentNode || {}).firstChild, e) + }, children: function (e) { + return x.sibling(e.firstChild) + }, contents: function (e) { + return e.contentDocument || x.merge([], e.childNodes) + } + }, function (e, t) { + x.fn[e] = function (n, r) { + var i = x.map(this, t, n); + return "Until" !== e.slice(-5) && (r = n), r && "string" == typeof r && (i = x.filter(r, i)), this.length > 1 && (K[e] || x.unique(i), J.test(e) && i.reverse()), this.pushStack(i) + } + }), x.extend({ + filter: function (e, t, n) { + var r = t[0]; + return n && (e = ":not(" + e + ")"), 1 === t.length && 1 === r.nodeType ? x.find.matchesSelector(r, e) ? [r] : [] : x.find.matches(e, x.grep(t, function (e) { + return 1 === e.nodeType + })) + }, dir: function (e, t, n) { + var r = [], i = n !== undefined; + while ((e = e[t]) && 9 !== e.nodeType)if (1 === e.nodeType) { + if (i && x(e).is(n))break; + r.push(e) + } + return r + }, sibling: function (e, t) { + var n = []; + for (; e; e = e.nextSibling)1 === e.nodeType && e !== t && n.push(e); + return n + } + }); + function et(e, t, n) { + if (x.isFunction(t))return x.grep(e, function (e, r) { + return !!t.call(e, r, e) !== n + }); + if (t.nodeType)return x.grep(e, function (e) { + return e === t !== n + }); + if ("string" == typeof t) { + if (G.test(t))return x.filter(t, e, n); + t = x.filter(t, e) + } + return x.grep(e, function (e) { + return g.call(t, e) >= 0 !== n + }) + } + + var tt = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, nt = /<([\w:]+)/, rt = /<|&#?\w+;/, it = /<(?:script|style|link)/i, ot = /^(?:checkbox|radio)$/i, st = /checked\s*(?:[^=]|=\s*.checked.)/i, at = /^$|\/(?:java|ecma)script/i, ut = /^true\/(.*)/, lt = /^\s*\s*$/g, ct = { + option: [1, ""], + thead: [1, "", "
    "], + col: [2, "", "
    "], + tr: [2, "", "
    "], + td: [3, "", "
    "], + _default: [0, "", ""] + }; + ct.optgroup = ct.option, ct.tbody = ct.tfoot = ct.colgroup = ct.caption = ct.thead, ct.th = ct.td, x.fn.extend({ + text: function (e) { + return x.access(this, function (e) { + return e === undefined ? x.text(this) : this.empty().append((this[0] && this[0].ownerDocument || o).createTextNode(e)) + }, null, e, arguments.length) + }, append: function () { + return this.domManip(arguments, function (e) { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { + var t = pt(this, e); + t.appendChild(e) + } + }) + }, prepend: function () { + return this.domManip(arguments, function (e) { + if (1 === this.nodeType || 11 === this.nodeType || 9 === this.nodeType) { + var t = pt(this, e); + t.insertBefore(e, t.firstChild) + } + }) + }, before: function () { + return this.domManip(arguments, function (e) { + this.parentNode && this.parentNode.insertBefore(e, this) + }) + }, after: function () { + return this.domManip(arguments, function (e) { + this.parentNode && this.parentNode.insertBefore(e, this.nextSibling) + }) + }, remove: function (e, t) { + var n, r = e ? x.filter(e, this) : this, i = 0; + for (; null != (n = r[i]); i++)t || 1 !== n.nodeType || x.cleanData(mt(n)), n.parentNode && (t && x.contains(n.ownerDocument, n) && dt(mt(n, "script")), n.parentNode.removeChild(n)); + return this + }, empty: function () { + var e, t = 0; + for (; null != (e = this[t]); t++)1 === e.nodeType && (x.cleanData(mt(e, !1)), e.textContent = ""); + return this + }, clone: function (e, t) { + return e = null == e ? !1 : e, t = null == t ? e : t, this.map(function () { + return x.clone(this, e, t) + }) + }, html: function (e) { + return x.access(this, function (e) { + var t = this[0] || {}, n = 0, r = this.length; + if (e === undefined && 1 === t.nodeType)return t.innerHTML; + if ("string" == typeof e && !it.test(e) && !ct[(nt.exec(e) || ["", ""])[1].toLowerCase()]) { + e = e.replace(tt, "<$1>"); + try { + for (; r > n; n++)t = this[n] || {}, 1 === t.nodeType && (x.cleanData(mt(t, !1)), t.innerHTML = e); + t = 0 + } catch (i) { + } + } + t && this.empty().append(e) + }, null, e, arguments.length) + }, replaceWith: function () { + var e = x.map(this, function (e) { + return [e.nextSibling, e.parentNode] + }), t = 0; + return this.domManip(arguments, function (n) { + var r = e[t++], i = e[t++]; + i && (r && r.parentNode !== i && (r = this.nextSibling), x(this).remove(), i.insertBefore(n, r)) + }, !0), t ? this : this.remove() + }, detach: function (e) { + return this.remove(e, !0) + }, domManip: function (e, t, n) { + e = f.apply([], e); + var r, i, o, s, a, u, l = 0, c = this.length, p = this, h = c - 1, d = e[0], g = x.isFunction(d); + if (g || !(1 >= c || "string" != typeof d || x.support.checkClone) && st.test(d))return this.each(function (r) { + var i = p.eq(r); + g && (e[0] = d.call(this, r, i.html())), i.domManip(e, t, n) + }); + if (c && (r = x.buildFragment(e, this[0].ownerDocument, !1, !n && this), i = r.firstChild, 1 === r.childNodes.length && (r = i), i)) { + for (o = x.map(mt(r, "script"), ft), s = o.length; c > l; l++)a = r, l !== h && (a = x.clone(a, !0, !0), s && x.merge(o, mt(a, "script"))), t.call(this[l], a, l); + if (s)for (u = o[o.length - 1].ownerDocument, x.map(o, ht), l = 0; s > l; l++)a = o[l], at.test(a.type || "") && !q.access(a, "globalEval") && x.contains(u, a) && (a.src ? x._evalUrl(a.src) : x.globalEval(a.textContent.replace(lt, ""))) + } + return this + } + }), x.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" + }, function (e, t) { + x.fn[e] = function (e) { + var n, r = [], i = x(e), o = i.length - 1, s = 0; + for (; o >= s; s++)n = s === o ? this : this.clone(!0), x(i[s])[t](n), h.apply(r, n.get()); + return this.pushStack(r) + } + }), x.extend({ + clone: function (e, t, n) { + var r, i, o, s, a = e.cloneNode(!0), u = x.contains(e.ownerDocument, e); + if (!(x.support.noCloneChecked || 1 !== e.nodeType && 11 !== e.nodeType || x.isXMLDoc(e)))for (s = mt(a), o = mt(e), r = 0, i = o.length; i > r; r++)yt(o[r], s[r]); + if (t)if (n)for (o = o || mt(e), s = s || mt(a), r = 0, i = o.length; i > r; r++)gt(o[r], s[r]); else gt(e, a); + return s = mt(a, "script"), s.length > 0 && dt(s, !u && mt(e, "script")), a + }, buildFragment: function (e, t, n, r) { + var i, o, s, a, u, l, c = 0, p = e.length, f = t.createDocumentFragment(), h = []; + for (; p > c; c++)if (i = e[c], i || 0 === i)if ("object" === x.type(i))x.merge(h, i.nodeType ? [i] : i); else if (rt.test(i)) { + o = o || f.appendChild(t.createElement("div")), s = (nt.exec(i) || ["", ""])[1].toLowerCase(), a = ct[s] || ct._default, o.innerHTML = a[1] + i.replace(tt, "<$1>") + a[2], l = a[0]; + while (l--)o = o.lastChild; + x.merge(h, o.childNodes), o = f.firstChild, o.textContent = "" + } else h.push(t.createTextNode(i)); + f.textContent = "", c = 0; + while (i = h[c++])if ((!r || -1 === x.inArray(i, r)) && (u = x.contains(i.ownerDocument, i), o = mt(f.appendChild(i), "script"), u && dt(o), n)) { + l = 0; + while (i = o[l++])at.test(i.type || "") && n.push(i) + } + return f + }, cleanData: function (e) { + var t, n, r, i, o, s, a = x.event.special, u = 0; + for (; (n = e[u]) !== undefined; u++) { + if (F.accepts(n) && (o = n[q.expando], o && (t = q.cache[o]))) { + if (r = Object.keys(t.events || {}), r.length)for (s = 0; (i = r[s]) !== undefined; s++)a[i] ? x.event.remove(n, i) : x.removeEvent(n, i, t.handle); + q.cache[o] && delete q.cache[o] + } + delete L.cache[n[L.expando]] + } + }, _evalUrl: function (e) { + return x.ajax({url: e, type: "GET", dataType: "script", async: !1, global: !1, "throws": !0}) + } + }); + function pt(e, t) { + return x.nodeName(e, "table") && x.nodeName(1 === t.nodeType ? t : t.firstChild, "tr") ? e.getElementsByTagName("tbody")[0] || e.appendChild(e.ownerDocument.createElement("tbody")) : e + } + + function ft(e) { + return e.type = (null !== e.getAttribute("type")) + "/" + e.type, e + } + + function ht(e) { + var t = ut.exec(e.type); + return t ? e.type = t[1] : e.removeAttribute("type"), e + } + + function dt(e, t) { + var n = e.length, r = 0; + for (; n > r; r++)q.set(e[r], "globalEval", !t || q.get(t[r], "globalEval")) + } + + function gt(e, t) { + var n, r, i, o, s, a, u, l; + if (1 === t.nodeType) { + if (q.hasData(e) && (o = q.access(e), s = q.set(t, o), l = o.events)) { + delete s.handle, s.events = {}; + for (i in l)for (n = 0, r = l[i].length; r > n; n++)x.event.add(t, i, l[i][n]) + } + L.hasData(e) && (a = L.access(e), u = x.extend({}, a), L.set(t, u)) + } + } + + function mt(e, t) { + var n = e.getElementsByTagName ? e.getElementsByTagName(t || "*") : e.querySelectorAll ? e.querySelectorAll(t || "*") : []; + return t === undefined || t && x.nodeName(e, t) ? x.merge([e], n) : n + } + + function yt(e, t) { + var n = t.nodeName.toLowerCase(); + "input" === n && ot.test(e.type) ? t.checked = e.checked : ("input" === n || "textarea" === n) && (t.defaultValue = e.defaultValue) + } + + x.fn.extend({ + wrapAll: function (e) { + var t; + return x.isFunction(e) ? this.each(function (t) { + x(this).wrapAll(e.call(this, t)) + }) : (this[0] && (t = x(e, this[0].ownerDocument).eq(0).clone(!0), this[0].parentNode && t.insertBefore(this[0]), t.map(function () { + var e = this; + while (e.firstElementChild)e = e.firstElementChild; + return e + }).append(this)), this) + }, wrapInner: function (e) { + return x.isFunction(e) ? this.each(function (t) { + x(this).wrapInner(e.call(this, t)) + }) : this.each(function () { + var t = x(this), n = t.contents(); + n.length ? n.wrapAll(e) : t.append(e) + }) + }, wrap: function (e) { + var t = x.isFunction(e); + return this.each(function (n) { + x(this).wrapAll(t ? e.call(this, n) : e) + }) + }, unwrap: function () { + return this.parent().each(function () { + x.nodeName(this, "body") || x(this).replaceWith(this.childNodes) + }).end() + } + }); + var vt, xt, bt = /^(none|table(?!-c[ea]).+)/, wt = /^margin/, Tt = RegExp("^(" + b + ")(.*)$", "i"), Ct = RegExp("^(" + b + ")(?!px)[a-z%]+$", "i"), kt = RegExp("^([+-])=(" + b + ")", "i"), Nt = {BODY: "block"}, Et = { + position: "absolute", + visibility: "hidden", + display: "block" + }, St = { + letterSpacing: 0, + fontWeight: 400 + }, jt = ["Top", "Right", "Bottom", "Left"], Dt = ["Webkit", "O", "Moz", "ms"]; + + function At(e, t) { + if (t in e)return t; + var n = t.charAt(0).toUpperCase() + t.slice(1), r = t, i = Dt.length; + while (i--)if (t = Dt[i] + n, t in e)return t; + return r + } + + function Lt(e, t) { + return e = t || e, "none" === x.css(e, "display") || !x.contains(e.ownerDocument, e) + } + + function qt(t) { + return e.getComputedStyle(t, null) + } + + function Ht(e, t) { + var n, r, i, o = [], s = 0, a = e.length; + for (; a > s; s++)r = e[s], r.style && (o[s] = q.get(r, "olddisplay"), n = r.style.display, t ? (o[s] || "none" !== n || (r.style.display = ""), "" === r.style.display && Lt(r) && (o[s] = q.access(r, "olddisplay", Rt(r.nodeName)))) : o[s] || (i = Lt(r), (n && "none" !== n || !i) && q.set(r, "olddisplay", i ? n : x.css(r, "display")))); + for (s = 0; a > s; s++)r = e[s], r.style && (t && "none" !== r.style.display && "" !== r.style.display || (r.style.display = t ? o[s] || "" : "none")); + return e + } + + x.fn.extend({ + css: function (e, t) { + return x.access(this, function (e, t, n) { + var r, i, o = {}, s = 0; + if (x.isArray(t)) { + for (r = qt(e), i = t.length; i > s; s++)o[t[s]] = x.css(e, t[s], !1, r); + return o + } + return n !== undefined ? x.style(e, t, n) : x.css(e, t) + }, e, t, arguments.length > 1) + }, show: function () { + return Ht(this, !0) + }, hide: function () { + return Ht(this) + }, toggle: function (e) { + return "boolean" == typeof e ? e ? this.show() : this.hide() : this.each(function () { + Lt(this) ? x(this).show() : x(this).hide() + }) + } + }), x.extend({ + cssHooks: { + opacity: { + get: function (e, t) { + if (t) { + var n = vt(e, "opacity"); + return "" === n ? "1" : n + } + } + } + }, + cssNumber: { + columnCount: !0, + fillOpacity: !0, + fontWeight: !0, + lineHeight: !0, + opacity: !0, + order: !0, + orphans: !0, + widows: !0, + zIndex: !0, + zoom: !0 + }, + cssProps: {"float": "cssFloat"}, + style: function (e, t, n, r) { + if (e && 3 !== e.nodeType && 8 !== e.nodeType && e.style) { + var i, o, s, a = x.camelCase(t), u = e.style; + return t = x.cssProps[a] || (x.cssProps[a] = At(u, a)), s = x.cssHooks[t] || x.cssHooks[a], n === undefined ? s && "get"in s && (i = s.get(e, !1, r)) !== undefined ? i : u[t] : (o = typeof n, "string" === o && (i = kt.exec(n)) && (n = (i[1] + 1) * i[2] + parseFloat(x.css(e, t)), o = "number"), null == n || "number" === o && isNaN(n) || ("number" !== o || x.cssNumber[a] || (n += "px"), x.support.clearCloneStyle || "" !== n || 0 !== t.indexOf("background") || (u[t] = "inherit"), s && "set"in s && (n = s.set(e, n, r)) === undefined || (u[t] = n)), undefined) + } + }, + css: function (e, t, n, r) { + var i, o, s, a = x.camelCase(t); + return t = x.cssProps[a] || (x.cssProps[a] = At(e.style, a)), s = x.cssHooks[t] || x.cssHooks[a], s && "get"in s && (i = s.get(e, !0, n)), i === undefined && (i = vt(e, t, r)), "normal" === i && t in St && (i = St[t]), "" === n || n ? (o = parseFloat(i), n === !0 || x.isNumeric(o) ? o || 0 : i) : i + } + }), vt = function (e, t, n) { + var r, i, o, s = n || qt(e), a = s ? s.getPropertyValue(t) || s[t] : undefined, u = e.style; + return s && ("" !== a || x.contains(e.ownerDocument, e) || (a = x.style(e, t)), Ct.test(a) && wt.test(t) && (r = u.width, i = u.minWidth, o = u.maxWidth, u.minWidth = u.maxWidth = u.width = a, a = s.width, u.width = r, u.minWidth = i, u.maxWidth = o)), a + }; + function Ot(e, t, n) { + var r = Tt.exec(t); + return r ? Math.max(0, r[1] - (n || 0)) + (r[2] || "px") : t + } + + function Ft(e, t, n, r, i) { + var o = n === (r ? "border" : "content") ? 4 : "width" === t ? 1 : 0, s = 0; + for (; 4 > o; o += 2)"margin" === n && (s += x.css(e, n + jt[o], !0, i)), r ? ("content" === n && (s -= x.css(e, "padding" + jt[o], !0, i)), "margin" !== n && (s -= x.css(e, "border" + jt[o] + "Width", !0, i))) : (s += x.css(e, "padding" + jt[o], !0, i), "padding" !== n && (s += x.css(e, "border" + jt[o] + "Width", !0, i))); + return s + } + + function Pt(e, t, n) { + var r = !0, i = "width" === t ? e.offsetWidth : e.offsetHeight, o = qt(e), s = x.support.boxSizing && "border-box" === x.css(e, "boxSizing", !1, o); + if (0 >= i || null == i) { + if (i = vt(e, t, o), (0 > i || null == i) && (i = e.style[t]), Ct.test(i))return i; + r = s && (x.support.boxSizingReliable || i === e.style[t]), i = parseFloat(i) || 0 + } + return i + Ft(e, t, n || (s ? "border" : "content"), r, o) + "px" + } + + function Rt(e) { + var t = o, n = Nt[e]; + return n || (n = Mt(e, t), "none" !== n && n || (xt = (xt || x(""; - break; - } - - // position 20070613 - var a = Fe.trim(op.position).toLowerCase().split(/\s/); - var body = Fe.body(); - Fe.show("FeDialog_" + this.hashCode); - if (Fe.isIE && _("FeDialogContent").offsetWidth < 136) - _("FeDialogContent").style.width = "130px"; - if (Fe.isIE && _("FeDialogContent").offsetHeight < 50) - _("FeDialogContent").style.height = "50px"; - var top = (Math.max( - parseInt((body.viewHeight - _("FeDialog").offsetHeight) / 2), 0) + body.scrollTop) - + "px"; - var left = (Math.max( - parseInt((body.viewWidth - _("FeDialog").offsetWidth) / 2), 0) + body.scrollLeft) - + "px"; - if (a.length == 1) { - if (a[0] == "" || a[0] == "center") { - } else if (a[0] == "top") - top = body.scrollTop + "px"; - else if (a[0] == "bottom") - top = (body.scrollTop + body.viewHeight - _("FeDialog").offsetHeight) - + "px"; - else if (a[0] == "left") - left = body.scrollLeft + "px"; - else if (a[0] == "right") - left = (body.scrollLeft + body.viewWidth - _("FeDialog").offsetWidth) - + "px"; - else if (/\d+%/.test(a[0])) - top = a[0]; - else if (/(\d+)(cm|mm|in|pt|pc|px|em|ex)?/.test(a[0])) - top = parseInt(RegExp.$1) + RegExp.$2 || "px"; - } else if (a.length > 1) { - if (/\d+%/.test(a[0])) - top = a[0]; - else if (/(\d+)(cm|mm|in|pt|pc|px|em|ex)?/.test(a[0])) - top = parseInt(RegExp.$1) + RegExp.$2 || "px"; - - if (/\d+%/.test(a[1])) - left = a[1]; - else if (/(\d+)(cm|mm|in|pt|pc|px|em|ex)?/.test(a[1])) - left = parseInt(RegExp.$1) + RegExp.$2 || "px"; - - if (a[0] == "top" || a[1] == "top") - top = body.scrollTop + "px"; - if (a[0] == "bottom" || a[1] == "bottom") - top = (body.scrollTop + body.viewHeight - _("FeDialog").offsetHeight) - + "px"; - if (a[0] == "left" || a[1] == "left") - left = body.scrollLeft + "px"; - if (a[0] == "right" || a[1] == "right") - left = (body.scrollLeft + body.viewWidth - _("FeDialog").offsetWidth) - + "px"; - } - _("FeDialog").style.top = top; - _("FeDialog").style.left = left; - - this.active = true; +Fe.DialogFactory.prototype.show = function (op) { + var me = this; + + function _(id) { + return Fe.G(id + "_" + me.hashCode) + } + + // set property + if (op.icon) { + _("FeDialogCaption").style.background = "url(" + op.icon + ") no-repeat left 3px"; + _("FeDialogCaptionText").style.paddingLeft = "18px"; + } + // * + _("FeDialog").style.font = op.font; + //_("FeDialog").style.fontSize = "12px"; + _("FeDialogCaptionText").innerHTML = op.title; + _("FeDialogCaption").style.display = op.titlebar ? "" : "none"; + _("FeDialogStatusBar").style.display = op.statusbar ? "" : "none"; + _("FeDialogControlBar").style.display = op.controlbar ? "" : "none"; + _("FeDialogButtonBar").style.display = op.buttonbar ? "" : "none"; + _("FeDialogButtonClose").style.display = op.buttonClose ? "" : "none"; + _("FeDialogButtonAccept").style.display = op.buttonAccept ? "" : "none"; + _("FeDialogButtonCancel").style.display = op.buttonCancel ? "" : "none"; + _("FeDialogButtonBar").style.textAlign = op.buttonbarAlign; + _("FeDialogButtonAccept").value = op.buttonAcceptValue; + _("FeDialogButtonCancel").value = op.buttonCancelValue; + with (_("FeDialogContent").style) { + width = op.width; + height = op.height; + overflow = op.overflow; + } + // */ + if (op.contentType.toLowerCase() == "htmlelement" && !Fe.G(op.content)) + op.contentType = "HTMLString"; + switch (op.contentType.toLowerCase()) { + case "htmlstring" : + _("FeDialogContent").innerHTML = op.content; + break; + case "htmlelement" : + var e = Fe.G(op.content); + this.opContentDisplay = e.style.display; + e.insertAdjacentHTML("beforeBegin", ""); + _("FeDialogContent").innerHTML = ""; + e.style.display = ""; + _("FeDialogContent").appendChild(e); + break; + default : + _("FeDialogContent").innerHTML = ""; + break; + } + + // position 20070613 + var a = Fe.trim(op.position).toLowerCase().split(/\s/); + var body = Fe.body(); + Fe.show("FeDialog_" + this.hashCode); + if (Fe.isIE && _("FeDialogContent").offsetWidth < 136) + _("FeDialogContent").style.width = "130px"; + if (Fe.isIE && _("FeDialogContent").offsetHeight < 50) + _("FeDialogContent").style.height = "50px"; + var top = (Math.max( + parseInt((body.viewHeight - _("FeDialog").offsetHeight) / 2), 0) + body.scrollTop) + + "px"; + var left = (Math.max( + parseInt((body.viewWidth - _("FeDialog").offsetWidth) / 2), 0) + body.scrollLeft) + + "px"; + if (a.length == 1) { + if (a[0] == "" || a[0] == "center") { + } else if (a[0] == "top") + top = body.scrollTop + "px"; + else if (a[0] == "bottom") + top = (body.scrollTop + body.viewHeight - _("FeDialog").offsetHeight) + + "px"; + else if (a[0] == "left") + left = body.scrollLeft + "px"; + else if (a[0] == "right") + left = (body.scrollLeft + body.viewWidth - _("FeDialog").offsetWidth) + + "px"; + else if (/\d+%/.test(a[0])) + top = a[0]; + else if (/(\d+)(cm|mm|in|pt|pc|px|em|ex)?/.test(a[0])) + top = parseInt(RegExp.$1) + RegExp.$2 || "px"; + } else if (a.length > 1) { + if (/\d+%/.test(a[0])) + top = a[0]; + else if (/(\d+)(cm|mm|in|pt|pc|px|em|ex)?/.test(a[0])) + top = parseInt(RegExp.$1) + RegExp.$2 || "px"; + + if (/\d+%/.test(a[1])) + left = a[1]; + else if (/(\d+)(cm|mm|in|pt|pc|px|em|ex)?/.test(a[1])) + left = parseInt(RegExp.$1) + RegExp.$2 || "px"; + + if (a[0] == "top" || a[1] == "top") + top = body.scrollTop + "px"; + if (a[0] == "bottom" || a[1] == "bottom") + top = (body.scrollTop + body.viewHeight - _("FeDialog").offsetHeight) + + "px"; + if (a[0] == "left" || a[1] == "left") + left = body.scrollLeft + "px"; + if (a[0] == "right" || a[1] == "right") + left = (body.scrollLeft + body.viewWidth - _("FeDialog").offsetWidth) + + "px"; + } + _("FeDialog").style.top = top; + _("FeDialog").style.left = left; + + this.active = true; }; /** * Fe.DialogFactory\u7684hide\u65b9\u6cd5\uff0c\u9690\u85cf\u4e00\u4e2a\u5bf9\u8bdd\u6846 */ -Fe.DialogFactory.prototype.hide = function(callback) { - Fe.hide("FeDialog_" + this.hashCode); - var me = this; - if (Fe.G("FeDialogFactoryInset_" + me.hashCode)) { - var e = Fe.G("FeDialogFactoryInset_" + me.hashCode); - var t = Fe.G("FeDialogContent_" + me.hashCode).childNodes[0]; - e.parentNode.insertBefore(t, e); - e.parentNode.removeChild(e); - t.style.display = me.opContentDisplay; - } - if ("function" == typeof(callback)) - callback(me); - setTimeout(function() { - me.active = false; - me.setContent(" "); - var e = Fe.G("FeDialogContent_" + me.hashCode); - if (e) { - e.style.width = e.style.height = e.style.overflow = ""; - } - }, 50); - clearTimeout(this.timer); +Fe.DialogFactory.prototype.hide = function (callback) { + Fe.hide("FeDialog_" + this.hashCode); + var me = this; + if (Fe.G("FeDialogFactoryInset_" + me.hashCode)) { + var e = Fe.G("FeDialogFactoryInset_" + me.hashCode); + var t = Fe.G("FeDialogContent_" + me.hashCode).childNodes[0]; + e.parentNode.insertBefore(t, e); + e.parentNode.removeChild(e); + t.style.display = me.opContentDisplay; + } + if ("function" == typeof(callback)) + callback(me); + setTimeout(function () { + me.active = false; + me.setContent(" "); + var e = Fe.G("FeDialogContent_" + me.hashCode); + if (e) { + e.style.width = e.style.height = e.style.overflow = ""; + } + }, 50); + clearTimeout(this.timer); }; /** * Fe.DialogFactory\u7684dispose\u65b9\u6cd5\u3002\u91ca\u653e\u5bf9\u8bdd\u6846\u6240\u7528\u7684\u8d44\u6e90\u3002 */ -Fe.DialogFactory.prototype.dispose = function() { - Fe.DialogFactory.dialogs = Fe.DialogFactory.dialogs.remove(this); - Fe.BaseClass.prototype.dispose.call(this); +Fe.DialogFactory.prototype.dispose = function () { + Fe.DialogFactory.dialogs = Fe.DialogFactory.dialogs.remove(this); + Fe.BaseClass.prototype.dispose.call(this); }; /** * Fe.DialogFactory\u7684setWidth\u65b9\u6cd5\u3002\u8bbe\u7f6e\u5bf9\u8bdd\u6846\u7684\u5bbd\u5ea6\u3002 * @param {Number} w \u9700\u8981\u8bbe\u7f6e\u7684\u5bbd\u5ea6\u503c */ -Fe.DialogFactory.prototype.setWidth = function(w) { - var e; - if (e = Fe.G("FeDialogContent_" + this.hashCode)) { - e.style.width = w; - } +Fe.DialogFactory.prototype.setWidth = function (w) { + var e; + if (e = Fe.G("FeDialogContent_" + this.hashCode)) { + e.style.width = w; + } }; /** * Fe.DialogFactory\u7684setHeight\u65b9\u6cd5\u3002\u8bbe\u7f6e\u5bf9\u8bdd\u6846\u7684\u9ad8\u5ea6\u3002 * @param {Number} h \u9700\u8981\u8bbe\u7f6e\u7684\u9ad8\u5ea6\u503c */ -Fe.DialogFactory.prototype.setHeight = function(h) { - var e; - if (e = Fe.G("FeDialogContent_" + this.hashCode)) { - e.style.height = h; - } +Fe.DialogFactory.prototype.setHeight = function (h) { + var e; + if (e = Fe.G("FeDialogContent_" + this.hashCode)) { + e.style.height = h; + } }; /** * Fe.DialogFactory\u7684setCaption\u65b9\u6cd5\u3002\u8bbe\u7f6e\u5bf9\u8bdd\u6846\u7684\u6807\u9898\u3002 * @param {String} s \u9700\u8981\u8bbe\u7f6e\u7684\u6807\u9898\u7684\u5185\u5bb9 */ -Fe.DialogFactory.prototype.setCaption = function(s) { - Fe.G("FeDialogCaptionText_" + this.hashCode).value = s; +Fe.DialogFactory.prototype.setCaption = function (s) { + Fe.G("FeDialogCaptionText_" + this.hashCode).value = s; } /** * Fe.DialogFactory\u7684setContent\u65b9\u6cd5\u3002\u8bbe\u7f6e\u5bf9\u8bdd\u6846\u7684\u5185\u5bb9\u3002 * @param {String} s \u9700\u8981\u8bbe\u7f6e\u7684\u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 */ -Fe.DialogFactory.prototype.setContent = function(s) { - Fe.G("FeDialogContent_" + this.hashCode).innerHTML = s; +Fe.DialogFactory.prototype.setContent = function (s) { + Fe.G("FeDialogContent_" + this.hashCode).innerHTML = s; } /** * Fe.DialogFactory\u7684setStatus\u65b9\u6cd5\u3002\u8bbe\u7f6e\u5bf9\u8bdd\u6846\u7684\u72b6\u6001\u680f\u4fe1\u606f\u3002 * @param {String} s \u9700\u8981\u8bbe\u7f6e\u7684\u72b6\u6001\u680f\u4fe1\u606f\u7684\u5185\u5bb9 */ -Fe.DialogFactory.prototype.setStatus = function(s) { - Fe.G("FeDialogStatusText_" + this.hashCode).innerHTML = s; +Fe.DialogFactory.prototype.setStatus = function (s) { + Fe.G("FeDialogStatusText_" + this.hashCode).innerHTML = s; } /** * @ignore */ -Fe.DialogFactory.prototype.click = function(e) { - (window.event || e).cancelBubble = true; - this.setActive(); +Fe.DialogFactory.prototype.click = function (e) { + (window.event || e).cancelBubble = true; + this.setActive(); }; /** * Fe.DialogFactory\u7684resizeBy\u65b9\u6cd5\u3002\u8c03\u6574\u5bf9\u8bdd\u6846\u7684\u9ad8\u5ea6\u548c\u5bbd\u5ea6\u3002 */ -Fe.DialogFactory.prototype.resizeBy = function() { - var me = this, - layer = "FeDialogLayer_" + this.hashCode; - Fe.G("FeDialogBgLayer_" + this.hashCode).style.width = Fe.G(layer).offsetWidth + "px"; - Fe.G("FeDialogBgLayer_" + this.hashCode).style.height = Fe.G(layer).offsetHeight + "px"; - if (Fe.isIE && Fe.G("FeDialogBgLayer_" + this.hashCode)) { - if (Fe.isIE < 5.5) { - Fe.G("FeDialogLayer_" + this.hashCode).style.width = "130px"; - Fe.G("FeDialog_" + this.hashCode).style.width = Fe.G("FeDialogLayer_" + this.hashCode).offsetWidth + "px"; - } - var table = Fe.G("FeDialogBgLayer_" + this.hashCode); - if (table.rows[0].cells[0].currentStyle) { - var h1 = parseInt(table.rows[0].cells[0].currentStyle.height); - var h2 = parseInt(table.rows[2].cells[0].currentStyle.height); - if (!isNaN(h1) && !isNaN(h2)) { - table.rows[1].cells[1].style.height = (Math.max(Fe.G(layer).offsetHeight - h1 - h2, 12)) + "px"; - } - } - } - if (window.opera && Fe.G("FeDialogLayerTable_" + this.hashCode).offsetWidth < 130) - Fe.G("FeDialogLayerTable_" + this.hashCode).style.width = "130px"; - this.timer = setTimeout(function() { - me.resizeBy(); - }, 50); +Fe.DialogFactory.prototype.resizeBy = function () { + var me = this, + layer = "FeDialogLayer_" + this.hashCode; + Fe.G("FeDialogBgLayer_" + this.hashCode).style.width = Fe.G(layer).offsetWidth + "px"; + Fe.G("FeDialogBgLayer_" + this.hashCode).style.height = Fe.G(layer).offsetHeight + "px"; + if (Fe.isIE && Fe.G("FeDialogBgLayer_" + this.hashCode)) { + if (Fe.isIE < 5.5) { + Fe.G("FeDialogLayer_" + this.hashCode).style.width = "130px"; + Fe.G("FeDialog_" + this.hashCode).style.width = Fe.G("FeDialogLayer_" + this.hashCode).offsetWidth + "px"; + } + var table = Fe.G("FeDialogBgLayer_" + this.hashCode); + if (table.rows[0].cells[0].currentStyle) { + var h1 = parseInt(table.rows[0].cells[0].currentStyle.height); + var h2 = parseInt(table.rows[2].cells[0].currentStyle.height); + if (!isNaN(h1) && !isNaN(h2)) { + table.rows[1].cells[1].style.height = (Math.max(Fe.G(layer).offsetHeight - h1 - h2, 12)) + "px"; + } + } + } + if (window.opera && Fe.G("FeDialogLayerTable_" + this.hashCode).offsetWidth < 130) + Fe.G("FeDialogLayerTable_" + this.hashCode).style.width = "130px"; + this.timer = setTimeout(function () { + me.resizeBy(); + }, 50); }; /** * Fe.DialogFactory\u7684produce\u65b9\u6cd5\u3002\u521b\u5efa\u4e00\u4e2a\u65b0\u7684Fe.Dialog\u5b9e\u4f8b */ -Fe.DialogFactory.produce = function() { - for (var i = 0, n = Fe.DialogFactory.dialogs.length; i < n; i++) { - if (!Fe.DialogFactory.dialogs[i].active) { - if (i == (n - 1)) - setTimeout(function() { - new Fe.DialogFactory().create(); - }, 20); - return Fe.DialogFactory.dialogs[i]; - } - } - return null; +Fe.DialogFactory.produce = function () { + for (var i = 0, n = Fe.DialogFactory.dialogs.length; i < n; i++) { + if (!Fe.DialogFactory.dialogs[i].active) { + if (i == (n - 1)) + setTimeout(function () { + new Fe.DialogFactory().create(); + }, 20); + return Fe.DialogFactory.dialogs[i]; + } + } + return null; }; // 20071225 -Fe.on(document.body, "onkeydown", function(event) { - var el = event.target || event.srcElement; - if (!el) - return false; - if (el.tagName.toLowerCase() == 'textarea') - return false; - - var key = event.which || event.keyCode; - if (Fe.DialogFactory.currentDialog && Fe.DialogFactory.currentDialog.active) { - if (key == 27) - Fe.DialogFactory.currentDialog.oncancel(); - else if (key == 13) { - Fe.DialogFactory.currentDialog.onaccept(); - // FF2\u6ca1\u6709\u95ee\u9898\uff0cFF3\u51fa\u95ee\u9898\u4e86\uff1f - try { - event.keyCode = 0; - } catch (e) { - } - event.returnValue = false; - } - } +Fe.on(document.body, "onkeydown", function (event) { + var el = event.target || event.srcElement; + if (!el) + return false; + if (el.tagName.toLowerCase() == 'textarea') + return false; + + var key = event.which || event.keyCode; + if (Fe.DialogFactory.currentDialog && Fe.DialogFactory.currentDialog.active) { + if (key == 27) + Fe.DialogFactory.currentDialog.oncancel(); + else if (key == 13) { + Fe.DialogFactory.currentDialog.onaccept(); + // FF2\u6ca1\u6709\u95ee\u9898\uff0cFF3\u51fa\u95ee\u9898\u4e86\uff1f + try { + event.keyCode = 0; + } catch (e) { + } + event.returnValue = false; + } + } }); - - - /** * \u7ed9\u5143\u7d20el\u89e3\u9664\u4e8b\u4ef6(evt)\u7684\u5904\u7406\u51fd\u6570handler\u3002 * \u7528\u6cd5\uff1a @@ -1156,15 +1130,17 @@ Fe.on(document.body, "onkeydown", function(event) { * @param {Function} handler \u4e8b\u4ef6\u7684\u5904\u7406\u51fd\u6570 * @return {DOM} \u7ed1\u5b9a\u4e8b\u4ef6\u7684\u8282\u70b9 */ -Fe.un = function(el, type, handler){ - if(!(el = Fe.G(el))){ return el; } +Fe.un = function (el, type, handler) { + if (!(el = Fe.G(el))) { + return el; + } type = type.replace(/^on/, "").toLowerCase(); - if(el.attachEvent){ + if (el.attachEvent) { el.detachEvent('on' + type, el[type + handler]); el[type + handler] = null; - }else{ + } else { el.removeEventListener(type, handler, false); } @@ -1172,46 +1148,42 @@ Fe.un = function(el, type, handler){ }; - - - - /** @ignore */ function BdLockWindow() { - this.initialize(); + this.initialize(); } /** @ignore */ -BdLockWindow.prototype.initialize = function() { - var div = BdLockWindow.element = document.createElement("DIV"); - div.id = BdLockWindow.id; +BdLockWindow.prototype.initialize = function () { + var div = BdLockWindow.element = document.createElement("DIV"); + div.id = BdLockWindow.id; var style = div.style; - style.zIndex = 1; - style.top = "0px"; + style.zIndex = 1; + style.top = "0px"; style.left = "0px"; - style.width = "100%"; + style.width = "100%"; style.height = "100%"; - style.border = "none"; + style.border = "none"; style.display = "none"; - style.margin = 0; + style.margin = 0; style.padding = 0; - style.position = "absolute"; - style.backgroundColor = "#666699"; - style.backgroundImage = "url(" + Fe.path + "/img/blank.gif)"; + style.position = "absolute"; + style.backgroundColor = "#666699"; + style.backgroundImage = "url(" + Fe.path + "/img/blank.gif)"; document.body.insertBefore(div, document.body.firstChild); - BdLockWindow.onResize(); + BdLockWindow.onResize(); }; /** * \u91cd\u65b0\u8c03\u6574\u906e\u7f69\u5c42\u7684\u5927\u5c0f */ -BdLockWindow.onResize = function() { +BdLockWindow.onResize = function () { BdLockWindow.element.style.width = "100%"; BdLockWindow.element.style.height = "100%"; - setTimeout(function() { + setTimeout(function () { var body = Fe.body(); var W = body.documentWidth; var H = body.documentHeight; @@ -1221,7 +1193,7 @@ BdLockWindow.onResize = function() { }; /**@ignore */ -BdLockWindow._restore = function(TagName) { +BdLockWindow._restore = function (TagName) { var s = document.getElementsByTagName(TagName); for (var i = s.length - 1; i > -1; i--) { s[i].style.visibility = s[i].getAttribute("att_BdLockWindow_v") || ""; @@ -1230,7 +1202,7 @@ BdLockWindow._restore = function(TagName) { }; /**@ignore */ -BdLockWindow._safeguard = function(TagName) { +BdLockWindow._safeguard = function (TagName) { var s = document.getElementsByTagName(TagName); for (var i = s.length - 1; i > -1; i--) { s[i].setAttribute("att_BdLockWindow_v", s[i].style.visibility, 0); @@ -1247,9 +1219,9 @@ BdLockWindow.id = "BdLockWindow_" + new Date().getTime().toString(36); * @config {String} [opacity] \u900f\u660e\u5ea6\uff0c\u4f8b\u59820.5 * @config {String} [zIndex] \u9ad8\u5ea6\u503c */ -BdLockWindow.lock = function(options) { +BdLockWindow.lock = function (options) { var me = this; - if (!me.instance){ + if (!me.instance) { me.instance = new BdLockWindow(); } @@ -1258,17 +1230,17 @@ BdLockWindow.lock = function(options) { var style = me.element.style; me.onResize(); var op = Fe.extend({ - zIndex : 1, - opacity : 0.5 + zIndex: 1, + opacity: 0.5 }, options || {}); style.zIndex = op.zIndex; style.backgroundColor = op.backgroundColor || "#666699"; - if('opacity' in style){ + if ('opacity' in style) { style.opacity = op.opacity; - }else if('MozOpacity' in style){ // Firefox 0.9\u7684\u60c5\u51b5\uff0cFirefox 3.1\u5df2\u7ecf\u4e0d\u652f\u6301\u4e86 + } else if ('MozOpacity' in style) { // Firefox 0.9\u7684\u60c5\u51b5\uff0cFirefox 3.1\u5df2\u7ecf\u4e0d\u652f\u6301\u4e86 style.MozOpacity = op.opacity; - }else if('filter' in style){ + } else if ('filter' in style) { // \u53ea\u80fdQuirks Mode\u4e0b\u9762\u751f\u6548?? style.filter = (style.filter || '').replace(/alpha\([^\)]*\)/gi, "") + (op.opacity == 1 ? "" : "alpha(opacity=" + op.opacity * 100 + ")"); // IE filters only apply to elements with "layout." @@ -1276,11 +1248,11 @@ BdLockWindow.lock = function(options) { } /* - for(var tags = ["SELECT","OBJECT","EMBED"], i = 0, j = tags.length; i < j; i ++){ - this._safeguard(tags[i]) - } - */ - for(var tags = ["SELECT"], i = 0, j = tags.length; i < j; i ++){ + for(var tags = ["SELECT","OBJECT","EMBED"], i = 0, j = tags.length; i < j; i ++){ + this._safeguard(tags[i]) + } + */ + for (var tags = ["SELECT"], i = 0, j = tags.length; i < j; i++) { this._safeguard(tags[i]) } }; @@ -1288,20 +1260,19 @@ BdLockWindow.lock = function(options) { /** * \u5c4f\u5e55\u89e3\u9501 */ -BdLockWindow.unlock = function() { +BdLockWindow.unlock = function () { if (!this.instance) { this.instance = new BdLockWindow(); return; } Fe.hide(this.id); Fe.un(window, "onresize", this.onResize); - for(var tags = ["SELECT","OBJECT","EMBED"], i = 0, j = tags.length; i < j; i ++){ + for (var tags = ["SELECT", "OBJECT", "EMBED"], i = 0, j = tags.length; i < j; i++) { this._restore(tags[i]) } }; - /** * Fe.Dialog \u5bf9\u8bdd\u6846\u7684\u57fa\u7c7b * @constructor @@ -1328,97 +1299,97 @@ BdLockWindow.unlock = function() { * @config {String} [buttonCancelValue] \u53d6\u6d88\u6309\u94ae\u4e0a\u9762\u7684\u6587\u5b57 */ // {contentType title width height scroll resizable help} -Fe.Dialog = function(op) { - Fe.BaseClass.call(this); - // this.drag = true; - this.help = false; - this.font = "normal 12px sans-serif"; - - /** - * \u5bf9\u8bdd\u6846\u7684\u6807\u9898 - * @type String - */ - this.title = "Fe.Dialog"; - /** - * \u5bf9\u8bdd\u6846\u7684\u5bbd\u5ea6 - * @type Number - */ - this.width = ""; - /** - * \u5bf9\u8bdd\u6846\u7684\u9ad8\u5ea6 - * @type Number - */ - this.height = ""; - - this.autofit = false; - /** - * \u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 - * @type String - */ - this.content = " "; - /** - * \u5bf9\u8bdd\u6846\u5185\u5bb9\u6ea2\u51fa\u7684\u65f6\u5019\uff0c\u5982\u4f55\u5904\u7406(visible/hidden) - * @type String - */ - this.overflow = "visible"; - /** - * \u5bf9\u8bdd\u6846\u663e\u793a\u7684\u4f4d\u7f6e(length|percentage|alignment) - * @type String - */ - this.position = "center"; // length|percentage|alignment - /** - * \u662f\u5426\u663e\u793a\u6807\u9898\u680f - * @type Boolean - */ - this.titlebar = true; - this.scrolling = "auto"; - /** - * \u662f\u5426\u663e\u793a\u6309\u94ae\u680f - * @type Boolean - */ - this.buttonbar = false; - /** - * \u662f\u5426\u663e\u793a\u72b6\u6001\u680f - * @type Boolean - */ - this.statusbar = false; - this.resizable = false; - this.controlbar = true; - /** - * \u662f\u5426\u663e\u793a"\u5173\u95ed"\u6309\u94ae - * @type Boolean - */ - this.buttonClose = true; - /** - * \u5bf9\u8bdd\u6846\u7684\u7c7b\u578b(htmlstring,htmlelement,iframe) - * @type String - */ - this.contentType = "HTMLString"; - /** - * \u662f\u5426\u663e\u793a"\u786e\u5b9a"\u6309\u94ae - * @type Boolean - */ - this.buttonAccept = false; - /** - * \u662f\u5426\u663e\u793a"\u53d6\u6d88"\u6309\u94ae - * @type Boolean - */ - this.buttonCancel = false; - /** - * \u5bf9\u8bdd\u6846\u5e95\u90e8\u6309\u94ae\u533a\u57df\u7684\u5bf9\u9f50\u65b9\u5f0f(left, right, center) - * @type String - */ - this.buttonbarAlign = "right"; - /** - * "\u786e\u5b9a"\u6309\u94ae\u4e0a\u9762\u7684\u6587\u5b57 - * @type String - */ - this.buttonAcceptValue = "\u786e \u5b9a"; - /** - * "\u53d6\u6d88"\u6309\u94ae\u4e0a\u9762\u7684\u6587\u5b57 - * @type String - */ - this.buttonCancelValue = "\u53d6 \u6d88"; +Fe.Dialog = function (op) { + Fe.BaseClass.call(this); + // this.drag = true; + this.help = false; + this.font = "normal 12px sans-serif"; + + /** + * \u5bf9\u8bdd\u6846\u7684\u6807\u9898 + * @type String + */ + this.title = "Fe.Dialog"; + /** + * \u5bf9\u8bdd\u6846\u7684\u5bbd\u5ea6 + * @type Number + */ + this.width = ""; + /** + * \u5bf9\u8bdd\u6846\u7684\u9ad8\u5ea6 + * @type Number + */ + this.height = ""; + + this.autofit = false; + /** + * \u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 + * @type String + */ + this.content = " "; + /** + * \u5bf9\u8bdd\u6846\u5185\u5bb9\u6ea2\u51fa\u7684\u65f6\u5019\uff0c\u5982\u4f55\u5904\u7406(visible/hidden) + * @type String + */ + this.overflow = "visible"; + /** + * \u5bf9\u8bdd\u6846\u663e\u793a\u7684\u4f4d\u7f6e(length|percentage|alignment) + * @type String + */ + this.position = "center"; // length|percentage|alignment + /** + * \u662f\u5426\u663e\u793a\u6807\u9898\u680f + * @type Boolean + */ + this.titlebar = true; + this.scrolling = "auto"; + /** + * \u662f\u5426\u663e\u793a\u6309\u94ae\u680f + * @type Boolean + */ + this.buttonbar = false; + /** + * \u662f\u5426\u663e\u793a\u72b6\u6001\u680f + * @type Boolean + */ + this.statusbar = false; + this.resizable = false; + this.controlbar = true; + /** + * \u662f\u5426\u663e\u793a"\u5173\u95ed"\u6309\u94ae + * @type Boolean + */ + this.buttonClose = true; + /** + * \u5bf9\u8bdd\u6846\u7684\u7c7b\u578b(htmlstring,htmlelement,iframe) + * @type String + */ + this.contentType = "HTMLString"; + /** + * \u662f\u5426\u663e\u793a"\u786e\u5b9a"\u6309\u94ae + * @type Boolean + */ + this.buttonAccept = false; + /** + * \u662f\u5426\u663e\u793a"\u53d6\u6d88"\u6309\u94ae + * @type Boolean + */ + this.buttonCancel = false; + /** + * \u5bf9\u8bdd\u6846\u5e95\u90e8\u6309\u94ae\u533a\u57df\u7684\u5bf9\u9f50\u65b9\u5f0f(left, right, center) + * @type String + */ + this.buttonbarAlign = "right"; + /** + * "\u786e\u5b9a"\u6309\u94ae\u4e0a\u9762\u7684\u6587\u5b57 + * @type String + */ + this.buttonAcceptValue = "\u786e \u5b9a"; + /** + * "\u53d6\u6d88"\u6309\u94ae\u4e0a\u9762\u7684\u6587\u5b57 + * @type String + */ + this.buttonCancelValue = "\u53d6 \u6d88"; } Fe.inherit(Fe.Dialog, Fe.BaseClass, "Fe.Dialog"); @@ -1446,248 +1417,228 @@ Fe.inherit(Fe.Dialog, Fe.BaseClass, "Fe.Dialog"); * @config {String} [buttonAcceptValue] \u786e\u5b9a\u6309\u94ae\u4e0a\u9762\u7684\u6587\u5b57 * @config {String} [buttonCancelValue] \u53d6\u6d88\u6309\u94ae\u4e0a\u9762\u7684\u6587\u5b57 */ -Fe.Dialog.prototype.render = function(content, op) { - if ("undefined" != typeof(content)) - this.content = content; - if ("object" == typeof(op)) - Fe.extend(this, op); - // if(!isNaN(parseInt(this.width))) this.width = - // Math.max(parseInt(this.width), 150); - if ("number" == typeof(this.width)) - this.width += "px"; - if ("number" == typeof(this.height)) - this.height += "px"; - var me = this, - d = this.dialog = Fe.DialogFactory.produce(); - - /** @ignore */ - d.onaccept = function() { - me.accept() - }; - /** @ignore */ - d.oncancel = function() { - me.cancel() - }; - /** @ignore */ - d.onclose = function() { - me.close() - }; - /** @ignore */ - d.onhelp = function() { - me.help(); - }; - - d.show(this); - d.setActive(); - if (this.buttonbar && this.buttonAccept) - Fe.G("FeDialogButtonAccept_" + d.hashCode).focus(); - - if (this.locked) { - BdLockWindow.lock({ - opacity : 0.4, - backgroundColor : "#FFFFFF", - zIndex : (52000 - 10) - }); - this.addEventListener("onclose", function() { - BdLockWindow.unlock(); - }); - } - - setTimeout(function() { - me.dispatchEvent(new Fe.BaseEvent("onopen")); - }, 10); +Fe.Dialog.prototype.render = function (content, op) { + if ("undefined" != typeof(content)) + this.content = content; + if ("object" == typeof(op)) + Fe.extend(this, op); + // if(!isNaN(parseInt(this.width))) this.width = + // Math.max(parseInt(this.width), 150); + if ("number" == typeof(this.width)) + this.width += "px"; + if ("number" == typeof(this.height)) + this.height += "px"; + var me = this, + d = this.dialog = Fe.DialogFactory.produce(); + + /** @ignore */ + d.onaccept = function () { + me.accept() + }; + /** @ignore */ + d.oncancel = function () { + me.cancel() + }; + /** @ignore */ + d.onclose = function () { + me.close() + }; + /** @ignore */ + d.onhelp = function () { + me.help(); + }; + + d.show(this); + d.setActive(); + if (this.buttonbar && this.buttonAccept) + Fe.G("FeDialogButtonAccept_" + d.hashCode).focus(); + + if (this.locked) { + BdLockWindow.lock({ + opacity: 0.4, + backgroundColor: "#FFFFFF", + zIndex: (52000 - 10) + }); + this.addEventListener("onclose", function () { + BdLockWindow.unlock(); + }); + } + + setTimeout(function () { + me.dispatchEvent(new Fe.BaseEvent("onopen")); + }, 10); }; /** * Fe.Dialog\u7684setContent\u65b9\u6cd5\uff0c\u7528\u6765\u4fee\u6539\u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 * @param {String} content \u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 */ -Fe.Dialog.prototype.setContent = function(content) { - this.dialog.setContent(content) +Fe.Dialog.prototype.setContent = function (content) { + this.dialog.setContent(content) }; /** * Fe.Dialog\u7684setCaption\u65b9\u6cd5\uff0c\u7528\u6765\u4fee\u6539\u5bf9\u8bdd\u6846\u7684\u6807\u9898 * @param {String} caption \u5bf9\u8bdd\u6846\u7684\u6807\u9898 */ -Fe.Dialog.prototype.setCaption = function(caption) { - this.dialog.setCaption(caption) +Fe.Dialog.prototype.setCaption = function (caption) { + this.dialog.setCaption(caption) }; /** * Fe.Dialog\u7684setWidth\u65b9\u6cd5\uff0c\u7528\u6765\u4fee\u6539\u5bf9\u8bdd\u6846\u7684\u5bbd\u5ea6 * @param {Number} w \u5bf9\u8bdd\u6846\u7684\u5bbd\u5ea6 */ -Fe.Dialog.prototype.setWidth = function(w) { - this.dialog.setWidth(w) +Fe.Dialog.prototype.setWidth = function (w) { + this.dialog.setWidth(w) }; /** * Fe.Dialog\u7684setHeight\u65b9\u6cd5\uff0c\u7528\u6765\u4fee\u6539\u5bf9\u8bdd\u6846\u7684\u5bbd\u5ea6 * @param {Number} h \u5bf9\u8bdd\u6846\u7684\u9ad8\u5ea6 */ -Fe.Dialog.prototype.setHeight = function(h) { - this.dialog.setHeight(h) +Fe.Dialog.prototype.setHeight = function (h) { + this.dialog.setHeight(h) }; /** * Fe.Dialog\u7684getIframe\u65b9\u6cd5\uff0c\u7528\u6765\u83b7\u53d6\u5bf9\u8bdd\u6846\u5185\u90e8iframe\u7684\u5bf9\u8c61\u5f15\u7528 */ -Fe.Dialog.prototype.getIframe = function() { - return Fe.G("FeDialogIframe_" + this.dialog.hashCode); +Fe.Dialog.prototype.getIframe = function () { + return Fe.G("FeDialogIframe_" + this.dialog.hashCode); } /** * Fe.Dialog\u7684close\u65b9\u6cd5\uff0c\u7528\u6765\u5173\u95ed\u5bf9\u8bdd\u6846\uff0c\u5e76\u5206\u53d1onclose\u4e8b\u4ef6 */ -Fe.Dialog.prototype.close = function() { - var me = this, e = new Fe.BaseEvent("onclose"); - me.dispatchEvent(e); - if (!e.returnValue) - return; - this.dialog.hide(function() { - me.dispose(); - }); +Fe.Dialog.prototype.close = function () { + var me = this, e = new Fe.BaseEvent("onclose"); + me.dispatchEvent(e); + if (!e.returnValue) + return; + this.dialog.hide(function () { + me.dispose(); + }); } /** * Fe.Dialog\u7684accept\u65b9\u6cd5\uff0c\u70b9\u51fb\u786e\u5b9a\u6309\u94ae\u7684\u65f6\u5019\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\uff0c\u5e76\u5206\u53d1onaccept\u4e8b\u4ef6 */ -Fe.Dialog.prototype.accept = function() { - var e = new Fe.BaseEvent("onaccept"); - this.dispatchEvent(e); - if (!e.returnValue) - return; - this.close(); +Fe.Dialog.prototype.accept = function () { + var e = new Fe.BaseEvent("onaccept"); + this.dispatchEvent(e); + if (!e.returnValue) + return; + this.close(); }; /** * Fe.Dialog\u7684cancel\u65b9\u6cd5\uff0c\u70b9\u51fb\u53d6\u6d88\u6309\u94ae\u7684\u65f6\u5019\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\uff0c\u5e76\u5206\u53d1oncancel\u4e8b\u4ef6 */ -Fe.Dialog.prototype.cancel = function() { - var e = new Fe.BaseEvent("oncancel"); - this.dispatchEvent(e); - if (!e.returnValue) - return; - this.close(); +Fe.Dialog.prototype.cancel = function () { + var e = new Fe.BaseEvent("oncancel"); + this.dispatchEvent(e); + if (!e.returnValue) + return; + this.close(); }; /** * Fe.Dialog\u7684cancel\u65b9\u6cd5\uff0c\u70b9\u51fb\u6807\u9898\u680f\u4e0a\u9762\u7684\u5e2e\u52a9\u56fe\u6807\u7684\u65f6\u5019\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\uff0c\u5e76\u5206\u53d1onhelp\u4e8b\u4ef6\u3002 * (\u6682\u65f6\u6ca1\u6709\u652f\u6301) */ -Fe.Dialog.prototype.help = function() { - this.dispatchEvent(new Fe.BaseEvent("onhelp")); +Fe.Dialog.prototype.help = function () { + this.dispatchEvent(new Fe.BaseEvent("onhelp")); }; - -if(Fe.isIE && Fe.isIE < 7){ - try{ - document.execCommand("BackgroundImageCache", false, true); - }catch(e){} -}; - +if (Fe.isIE && Fe.isIE < 7) { + try { + document.execCommand("BackgroundImageCache", false, true); + } catch (e) { + } +} +; /** * \u5173\u95ed\u6240\u6709\u7684\u5bf9\u8bdd\u6846 */ -Fe.Dialog.close = function() { - for (var i = 0, n = Fe.DialogFactory.dialogs.length; i < n; i++) { - var dialog = Fe.DialogFactory.dialogs[i]; - if (dialog.active && typeof(dialog.onclose == "function")) { - dialog.onclose(); - } - } +Fe.Dialog.close = function () { + for (var i = 0, n = Fe.DialogFactory.dialogs.length; i < n; i++) { + var dialog = Fe.DialogFactory.dialogs[i]; + if (dialog.active && typeof(dialog.onclose == "function")) { + dialog.onclose(); + } + } }; - - - - /** * Fe.Dialog\u6269\u5c55\u7684\u9759\u6001\u65b9\u6cd5 * \u6253\u5f00\u4e00\u4e2a\u666e\u901a\u7684Dialog * @param {String} content \u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 * @param {Object} op \u5bf9\u8bdd\u6846\u7684\u914d\u7f6e\u4fe1\u606f */ -Fe.Dialog.open = function(content, op) { - var dialog = new Fe.Dialog(); - dialog.render(content, op); - return dialog; +Fe.Dialog.open = function (content, op) { + var dialog = new Fe.Dialog(); + dialog.render(content, op); + return dialog; }; - - - /** * \u6253\u5f00\u4e00\u4e2a\u7c7b\u4f3calert\u5f62\u5f0f\u7684\u5bf9\u8bdd\u6846 * @param {String} content \u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 * @param {Object} op \u5bf9\u8bdd\u6846\u7684\u914d\u7f6e\u4fe1\u606f */ -Fe.Dialog.alert = function(content, op) { - return this.open(content, Fe.extend({ - buttonbar : true, - buttonAccept : true - }, op || {})); +Fe.Dialog.alert = function (content, op) { + return this.open(content, Fe.extend({ + buttonbar: true, + buttonAccept: true + }, op || {})); }; - - - - /** * \u6253\u5f00\u4e00\u4e2a\u7c7b\u4f3cconfirm\u5f62\u5f0f\u7684\u5bf9\u8bdd\u6846 * @param {String} content \u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 * @param {Object} op \u5bf9\u8bdd\u6846\u7684\u914d\u7f6e\u4fe1\u606f */ -Fe.Dialog.confirm = function(content, op) { - return this.open(content, Fe.extend({ - locked : true, - buttonbar : true, - buttonAccept : true, - buttonCancel : true - }, op || {})); +Fe.Dialog.confirm = function (content, op) { + return this.open(content, Fe.extend({ + locked: true, + buttonbar: true, + buttonAccept: true, + buttonCancel: true + }, op || {})); }; - - - - /** * \u6253\u5f00\u4e00\u4e2a\u7c7b\u4f3cshowModalDialog\u5f62\u5f0f\u7684\u5bf9\u8bdd\u6846 * @param {String} content \u5bf9\u8bdd\u6846\u7684\u5185\u5bb9 * @param {Object} op \u5bf9\u8bdd\u6846\u7684\u914d\u7f6e\u4fe1\u606f */ -Fe.Dialog.showModalDialog = function(content, op) { - return this.open(content, Fe.extend({ - locked : true, - position : "center" - }, op || {})); +Fe.Dialog.showModalDialog = function (content, op) { + return this.open(content, Fe.extend({ + locked: true, + position: "center" + }, op || {})); }; - - - - - /** * \u63d0\u4ea4form\u5230\u5bf9\u8bdd\u6846 * @param {Form} form \u5c06form\u63d0\u4ea4\u5230\u5bf9\u8bdd\u6846\u5185\u90e8 * @param {Object} op \u5bf9\u8bdd\u6846\u7684\u914d\u7f6e\u4fe1\u606f */ -Fe.Dialog.submit = function(form, op) { - var dialog = this.open("about:blank", Fe.extend({ - contentType : "page" - }, op || {})); - var target = form.target; - form.target = dialog.getIframe().name; - form.submit(); - form.target = target; - return dialog; +Fe.Dialog.submit = function (form, op) { + var dialog = this.open("about:blank", Fe.extend({ + contentType: "page" + }, op || {})); + var target = form.target; + form.target = dialog.getIframe().name; + form.submit(); + form.target = target; + return dialog; }; \ No newline at end of file diff --git a/src/main/webapp/stat/js/ui/editor/css/editor.css b/src/main/webapp/stat/js/ui/editor/css/editor.css new file mode 100644 index 000000000..9b4706879 --- /dev/null +++ b/src/main/webapp/stat/js/ui/editor/css/editor.css @@ -0,0 +1,388 @@ +.tangram_editor_container { + padding: 5px; + border: 1px solid #D3D3D3; + background: #fff +} + +/* 工具栏 */ +.editor-tools { + height: 30px; + background: #fff url(img/editor-icon.gif) repeat-x; + border: 1px solid #ddd; + border-bottom: 1px solid #7b8982; + position: relative +} + +.editor-tools div, .editor-tools td { + font-size: 12px +} + +.editor-toolbar { + height: 23px; + padding: 4px; + border-bottom: 1px solid #d5d5d5; + position: relative +} + +.editor-toolbar div, .editor-toolbar p, .editor-toolbar span { + position: relative; + display: inline-block; + cursor: default; + vertical-align: middle +} + +* html .editor-toolbar div, * html .editor-toolbar p, * html .editor-toolbar span { + display: inline +} + +*:first-child + html .editor-toolbar div, *:first-child + html .editor-toolbar p, *:first-child + html .editor-toolbar span { + display: inline +} + +.editor-toolbar .btn_hover { + padding: 0 +} + +.editor-toolbar .btn_hover div { + border-top: 1px solid #729bd1; + border-bottom: 1px solid #729bd1; + background: #fff; +} + +.editor-toolbar .btn_hover p { + border-left: 1px solid #729bd1; + border-right: 1px solid #729bd1; + padding: 1px 2px +} + +.editor-toolbar .btn_disabled { + padding: 0 +} + +.editor-toolbar .btn_disabled div { + color: #C8C8C8; + padding: 0 1px; + border-color: #ddd +} + +.editor-toolbar .btn_disabled p { + border-color: #ddd; + padding: 2px +} + +.editor-toolbar .btn_active { + padding: 0 +} + +.editor-toolbar .btn_active div { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + background: #DDE1EB +} + +.editor-toolbar .btn_active p { + border-left: 1px solid #ddd; + border-right: 1px solid #ddd +} + +.editor-toolbar .btn_highlight { + padding: 0 +} + +.editor-toolbar .btn_highlight div { + border-top: 1px solid #729bd1; + border-bottom: 1px solid #729bd1; + background: #dde1eb +} + +.editor-toolbar .btn_highlight p { + border-left: 1px solid #729bd1; + border-right: 1px solid #729bd1; + padding: 1px 2px +} + +.editor-toolbar div { + margin: 0 3px; + *margin-right: 4px; + padding: 0 1px; +} + +.editor-toolbar div div { + margin: 0; + padding: 0 +} + +.editor-toolbar div div p { + margin: 0 -1px; + padding: 2px; + *padding: 3px 2px 3px; + vertical-align: top; + *left: -1px; +} + +.editor-toolbar div .btn_undo { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -35px +} + +.editor-toolbar div .btn_redo { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -56px +} + +.editor-toolbar div .btn_bold { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -78px +} + +.editor-toolbar div .btn_italic { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -100px +} + +.editor-toolbar div .btn_underline { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -119px +} + +.editor-toolbar div .btn_justifyleft { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -162px +} + +.editor-toolbar div .btn_justifycenter { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -183px +} + +.editor-toolbar div .btn_justifyright { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -204px +} + +.editor-toolbar div .btn_image { + width: 17px; + height: 17px; + background: url(img/editor-icon.gif) no-repeat center -224px +} + +.editor-toolbar div .btn_bar { + width: 1px; + height: 17px; + background: #D0D0D0 +} + +.editor-toolbar .btn_disabled .btn_undo { + background-position: center -245px +} + +.editor-toolbar .btn_disabled .btn_redo { + background-position: center -265px +} + +.editor-toolbar .btn_disabled .btn_bold { + background-position: center -288px +} + +.editor-toolbar .btn_disabled .btn_italic { + background-position: center -309px +} + +.editor-toolbar .btn_disabled .btn_underline { + background-position: center -330px +} + +.editor-toolbar .btn_disabled .btn_justifyleft { + background-position: center -372px +} + +.editor-toolbar .btn_disabled .btn_justifycenter { + background-position: center -394px +} + +.editor-toolbar .btn_disabled .btn_justifyright { + background-position: center -415px +} + +.editor-toolbar .btn_disabled .btn_image { + background-position: center -434px +} + +/* 选择框 */ +.editor-toolbar-list { + position: absolute; + border: 1px solid #333333; + border-top-color: #999999; + border-left-color: #999999 /*required*/ +} + +.editor-toolbar-list { + position: absolute; + border: 1px solid #333333; + _margin-left: -10px; + border-top-color: #999999; + border-left-color: #999999 +} + +/*ie6下需复设置*/ +.editor-toolbar-list-item { + padding: 2px 5px; + white-space: nowrap; + overflow: hidden; + cursor: default; + font-size: 12px; + vertical-align: middle; + background-color: #FFFFFF; /*required*/ +} + +.editor-toolbar-list-item { + padding: 2px 5px; +} + +/*ie6下需复设置*/ +.editor-toolbar-list-item-selected { + background-color: #DDDDDD; +} + +.editor-toolbar-list-item span { + display: inline-block; +} + +.editor-toolbar-list-item-hover { + background-color: #3366FF; + color: #FFFFFF; +} + +.editor-toolbar-fontname-list { +} + +.editor-toolbar-forecolor-list { +} + +.editor-toolbar-fontsize-list { +} + +.editor-toolbar-fontname-item { + width: 100px +} + +.editor-toolbar-forecolor-item { + width: 80px +} + +.editor-toolbar-fontsize-item { + width: 65px +} + +/* 字体按钮 */ +.editor-toolbar .editor-toolbar-select-fontfamily { + padding: 0; + text-align: center; +} + +.editor-toolbar .editor-toolbar-select-fontfamily div { + border-top: 1px solid #999; + border-bottom: 1px solid #999; + background: #fff; + padding: 0 +} + +.editor-toolbar .editor-toolbar-select-fontfamily p { + border-left: 1px solid #999; + border-right: 1px solid #999; + padding: 1px 2px +} + +.editor-toolbar .editor-toolbar-select-fontfamily div.editor-toolbar-select-caption { + width: 50px; + overflow: hidden; + vertical-align: middle; + white-space: nowrap; + border: none; + margin-right: 3px +} + +.editor-toolbar .editor-toolbar-select-fontfamily div.editor-toolbar-select-dropdown { + width: 7px; + vertical-align: middle; + background: transparent url(img/editor-icon.gif) no-repeat center -488px; + border: none +} + +/* 字号按钮 */ +.editor-toolbar .editor-toolbar-select-fontsize { + padding: 0; + text-align: center; +} + +.editor-toolbar .editor-toolbar-select-fontsize div { + border-top: 1px solid #999; + border-bottom: 1px solid #999; + background: #fff; + padding: 0 +} + +.editor-toolbar .editor-toolbar-select-fontsize p { + border-left: 1px solid #999; + border-right: 1px solid #999; + padding: 1px 2px +} + +.editor-toolbar .editor-toolbar-select-fontsize div.editor-toolbar-select-caption { + width: 50px; + overflow: hidden; + vertical-align: middle; + white-space: nowrap; + border: none; + margin-right: 3px +} + +.editor-toolbar .editor-toolbar-select-fontsize div.editor-toolbar-select-dropdown { + width: 7px; + vertical-align: middle; + background: transparent url(img/editor-icon.gif) no-repeat center -488px; + border: none +} + +/* 字体颜色按钮 */ +.editor-toolbar .editor-toolbar-select-forecolor { + padding: 0; + text-align: center; +} + +.editor-toolbar .editor-toolbar-select-forecolor div { + border-top: 1px solid #999; + border-bottom: 1px solid #999; + background: #fff; + padding: 0 +} + +.editor-toolbar .editor-toolbar-select-forecolor p { + border-left: 1px solid #999; + border-right: 1px solid #999; + padding: 1px 2px +} + +.editor-toolbar .editor-toolbar-select-forecolor div.editor-toolbar-select-caption { + width: 50px; + overflow: hidden; + vertical-align: middle; + white-space: nowrap; + border: none; + margin-right: 3px +} + +.editor-toolbar .editor-toolbar-select-forecolor div.editor-toolbar-select-dropdown { + width: 7px; + vertical-align: middle; + background: transparent url(img/editor-icon.gif) no-repeat center -488px; + border: none +} diff --git a/src/main/webapp/stat/js/ui/editor/css/editorarea.css b/src/main/webapp/stat/js/ui/editor/css/editorarea.css new file mode 100644 index 000000000..480c49dce --- /dev/null +++ b/src/main/webapp/stat/js/ui/editor/css/editorarea.css @@ -0,0 +1,18 @@ +body { + color: #000; + margin: 0; + padding: 1px; + font-size: 13px; + font-family: Arial +} + +form, h1, h2, h3, h4, ul, li, dl, dt, dd, p { + margin: 0; + padding: 0 +} + +img { + border: 0; + margin: 0; + padding: 0 +} \ No newline at end of file diff --git a/WebContent/stat/js/ui/editor/css/img/editor-icon.gif b/src/main/webapp/stat/js/ui/editor/css/img/editor-icon.gif similarity index 100% rename from WebContent/stat/js/ui/editor/css/img/editor-icon.gif rename to src/main/webapp/stat/js/ui/editor/css/img/editor-icon.gif diff --git a/src/main/webapp/stat/js/ui/editor/js/editor.js b/src/main/webapp/stat/js/ui/editor/js/editor.js new file mode 100644 index 000000000..163e20feb --- /dev/null +++ b/src/main/webapp/stat/js/ui/editor/js/editor.js @@ -0,0 +1,4199 @@ +baidu.on = function (H, F, E, G) { + if (typeof E != "function") { + return H + } + F = F.replace(/^on/i, "").toLowerCase(); + function B(I) { + return I || window.event + } + + var D = function (I) { + E.call(D.src, B(I)) + }; + D.src = H; + var C = baidu.on._listeners; + var A = [H, F, E, D]; + C[C.length] = A; + if (H.attachEvent) { + H.attachEvent("on" + F, D) + } else { + if (H.addEventListener) { + H.addEventListener(F, D, false) + } + } + return H +}; +baidu.on._listeners = []; +baidu.string = baidu.string || {}; +baidu.isString = function (A) { + return (typeof A == "object" && A && A.constructor == String) || typeof A == "string" +}; +baidu.G = function () { + for (var A = [], B = arguments.length - 1; B > -1; B--) { + var C = arguments[B]; + A[B] = null; + if (typeof C == "object" && C && C.dom) { + A[B] = C.dom + } else { + if ((typeof C == "object" && C && C.tagName) || C == window || C == document) { + A[B] = C + } else { + if (baidu.isString(C) && (C = document.getElementById(C))) { + A[B] = C + } + } + } + } + return A.length < 2 ? A[0] : A +}; +(function () { + var B = {}; + baidu.BaseClass = function (C) { + B[(this.guid = (C || baidu.BaseClass.guid()))] = this + }; + var A = 0; + baidu.BaseClass.guid = function () { + return "MZ__" + (A++).toString(36) + }; + baidu.BaseClass.create = function (D) { + var E = new baidu.BaseClass(); + delete B[this.guid]; + for (var C in D) { + E[C] = D[C] + } + return E + }; + window.Instance = baidu.instance = function (C) { + return B[C] + }; + baidu.BaseClass.prototype.dispose = function () { + if (this.guid) { + delete B[this.guid] + } + for (var C in this) { + if (typeof this[C] != "function") { + delete this[C] + } + } + }; + baidu.BaseClass.decontrol = function (C) { + if (C && C.guid) { + delete B[C.guid] + } + }; + baidu.BaseClass.prototype.toString = function () { + return "[object " + (this._className || "Object") + "]" + } +})(); +baidu.BaseEvent = function (A, B) { + this.type = A; + this.returnValue = true; + this.target = B || null; + this.currentTarget = this.srcElement = null +}; +baidu.BaseClass.prototype.addEventListener = function (D, C, B) { + if (typeof C != "function") { + throw ("addEventListener:" + C + " is not a function") + } + if (!this.__listeners) { + this.__listeners = {} + } + var A = this.__listeners, E; + if (typeof B == "string" && B) { + if (/[^\w\-]/.test(B)) { + throw ("nonstandard key:" + B) + } else { + C.hashCode = B; + E = B + } + } + if (D.indexOf("on") != 0) { + D = "on" + D + } + if (typeof A[D] != "object") { + A[D] = {} + } + E = E || baidu.BaseClass.guid(); + C.hashCode = E; + A[D][E] = C +}; +baidu.BaseClass.prototype.removeEventListener = function (C, B) { + if (typeof B == "function") { + B = B.hashCode + } else { + if (typeof B != "string") { + return + } + } + if (!this.__listeners) { + this.__listeners = {} + } + if (C.indexOf("on") != 0) { + C = "on" + C + } + var A = this.__listeners; + if (!A[C]) { + return + } + if (A[C][B]) { + delete A[C][B] + } +}; +baidu.BaseClass.prototype.dispatchEvent = function (C) { + if (!this.__listeners) { + this.__listeners = {} + } + var B, A = this.__listeners, D = C.type; + C.target = C.srcElement = C.target || C.srcElement || this; + C.currentTarget = this; + if (typeof this[D] == "function") { + this[D](C) + } + if (typeof A[D] == "object") { + for (B in A[D]) { + if (typeof A[D][B] == "function") { + A[D][B].call(this, C) + } + } + } + return C.returnValue +}; +baidu.extend = function (C, A) { + if (C && A && typeof (A) == "object") { + for (var B in A) { + C[B] = A[B] + } + } + return C +}; +baidu.trim = function (B, A) { + if (A == "left") { + return B.replace(/(^[\s\t\xa0\u3000]+)/g, "") + } + if (A == "right") { + return B.replace(/([\u3000\xa0\s\t]+$)/g, "") + } + return B.replace(/(^[\s\t\xa0\u3000]+)|([\u3000\xa0\s\t]+$)/g, "") +}; +baidu.addClass = function (A, B) { + if (!(A = baidu.G(A))) { + return + } + B = baidu.trim(B); + if (!new RegExp("(^| )" + B.replace(/(\W)/g, "\\\x241") + "( |\x24)").test(A.className)) { + A.className = baidu.trim(A.className.split(/\s+/).concat(B).join(" ")) + } +}; +baidu.ac = baidu.addClass; +baidu.removeClass = function (A, B) { + if (!(A = baidu.G(A))) { + return + } + B = baidu.trim(B); + var C = A.className.replace(new RegExp("(^| +)" + B.replace(/(\W)/g, "\\\x241") + "( +|\x24)", "g"), "\x242"); + if (A.className != C) { + A.className = baidu.trim(C) + } +}; +baidu.rc = baidu.removeClass; +baidu.ui = baidu.ui || {}; +baidu.editor = { + _register: [], register: function (A) { + this._register[this._register.length] = A + }, _commands: {}, registCommand: function (B, A) { + this._commands[B] = A + }, _queries: {}, registQuery: function (B, A) { + this._queries[B] = A + }, _parser: {}, registParser: function (A, B) { + this._parser[A] = B + } +}; +baidu.editor.EditorConfig = { + docType: "", + skinCSS: "../static/js/ui/editor/css/editorarea.css", + maxUndoCount: 100, + hotkey: {"ctrl+66": "Bold", "meta+66": "Bold", "ctrl+90": "Undo", "ctrl+89": "Redo", "9": "Bold"} +}; +baidu.ie = 0; +if (/MSIE (\d+(\.\d+)?)/.test(navigator.userAgent) && !window.opera) { + baidu.ie = parseFloat(RegExp.$1) +} +baidu.editor.register(function (C) { + var A = baidu.editor.EditorConfig.hotkey; + if (A) { + function B(H) { + var D = H; + H = H.srcElement; + var G = H.keyCode || H.which; + if (H.ctrlKey && G == 86 || H.ctrlKey && G == 88 || H.shiftKey && G == 45 || H.shiftKey && G == 46) { + C.dispatchEvent(new baidu.BaseEvent("onneedsavescene")); + setTimeout(function () { + C.dispatchEvent(new baidu.BaseEvent("onbeforeselectionchange")); + C.dispatchEvent(new baidu.BaseEvent("onselectionchange")); + C.dispatchEvent(new baidu.BaseEvent("onafterselectionchange")); + C.dispatchEvent(new baidu.BaseEvent("onneedsavescene")) + }, 0); + D.returnValue = false; + return false + } + if (baidu.ie && G == 8) { + var I = C.getSelection().getSelectedElement(); + if (I) { + C.dispatchEvent(new baidu.BaseEvent("onneedsavescene")); + baidu.dom.element.remove(I, C.document); + C.dispatchEvent(new baidu.BaseEvent("onneedsavescene")); + if (H.preventDefault) { + H.preventDefault() + } + } + } + for (var F in A) { + if (/^(ctrl|meta)\+(\d+)$/.test(F.toLowerCase()) || /^(\d+)$/.test(F)) { + if ((H[RegExp.$1 + "Key"] && G == RegExp.$2) || G == RegExp.$1) { + try { + C.execCommand(A[F]) + } catch (E) { + } + D.returnValue = H.returnValue = false; + if (H.preventDefault) { + H.preventDefault() + } + return false + } + } + } + return true + } + + C.addEventListener("onbeforekeydown", B) + } +}); +baidu.inherits = function (A, E, D) { + var B, F, H = A.prototype, G = function () { + }; + G.prototype = E.prototype; + F = A.prototype = new G(); + if (typeof D == "string") { + F._className = D + } + for (B in H) { + F[B] = H[B] + } + A.prototype.constructor = H.constructor; + A.superClass = E.prototype; + H = G = null; + return F +}; +(function () { + function A(C, B) { + baidu.BaseClass.call(this); + this.iframe = null; + this.document = null; + this.window = null; + B = B || {}; + this.width = B.width || ""; + this.height = B.height || ""; + this.readyState = 0; + this.ieBakRange = null; + this.temp = {scene: {}}; + this.isBlur = true + } + + baidu.inherits(A, baidu.BaseClass, "baidu.Editor"); + A.prototype.render = function () { + var D = typeof this.width == "number" ? this.width + "px" : this.width; + var B = typeof this.height == "number" ? this.height + "px" : this.height; + B = "height:" + B + ";"; + var C = ["
    "); + C.push("
    "); + this._setReadyState(1); + this.availableIframe(); + return C.join("") + }; + A.prototype.availableIframe = function () { + var B = document.getElementById("tangram_editor_iframe_" + this.guid); + if (B) { + this.iframe = B; + this._setReadyState(3) + } else { + var C = this; + setTimeout(function () { + C.availableIframe() + }, 20) + } + }; + A.prototype.makeEditable = function (F) { + var D = this; + var B = [baidu.editor.EditorConfig.docType]; + B.push(""); + if (baidu.editor.EditorConfig.skinCSS) { + var C = baidu.editor.EditorConfig.skinCSS + (baidu.ie ? "" : "?tmp=" + new Date().getTime()); + B.push("") + } + B.push(""); + B.push(F || ""); + B.push(""); + D.window = D.iframe.contentWindow; + var E = D.document = D.window.document; + E.open(); + E.write(B.join("")); + E.close(); + if (baidu.ie) { + E.body.disabled = true; + E.body.contentEditable = true; + E.body.removeAttribute("disabled"); + D._setReadyState(4) + } else { + setTimeout(function () { + try { + E.body.spellcheck = false; + E.designMode = "on"; + var J = false; + try { + E.execCommand("styleWithCSS", false, J) + } catch (H) { + E.execCommand("useCSS", false, !J) + } + var I = false; + var G = true; + E.execCommand("enableObjectResizing", false, !I); + E.execCommand("enableInlineTableEditing", false, !G) + } catch (H) { + } + D._setReadyState(4) + }, 1) + } + }; + A.prototype.execCommand = function (G, D, E) { + var C = false, F = true; + this.focus(); + if (this.__hasEnterdExecCommand) { + F = false + } else { + this.__hasEnterdExecCommand = true + } + this.dispatchEvent(new baidu.BaseEvent("onbeforeexeccommand", {command: G, topOpearation: F})); + if (typeof G == "string") { + var B = baidu.editor._commands; + if (typeof B[G] == "function") { + C = B[G].apply(null, [this].concat(Array.prototype.slice.call(arguments, 1))) + } else { + C = this.document.execCommand(G, D, E) + } + } else { + if (typeof G == "function") { + C = G.apply(null, [this].concat(Array.prototype.slice.call(arguments, 1))) + } + } + if (F) { + this.__hasEnterdExecCommand = false + } + this.dispatchEvent(new baidu.BaseEvent("onafterexeccommand", {command: G, topOpearation: F})); + this.selectionChangeHandler(null, true); + return C + }; + A.prototype.queryContextState = function (B) { + var C = baidu.editor._parser; + if (typeof C[B] == "function") { + return C[B](this) + } + }; + A.prototype.queryCommandState = function (D) { + var B = baidu.editor._queries; + if (typeof B[D] == "function") { + return B[D](this) + } else { + var C = navigator.userAgent; + if (/(\d+\.\d)\s+safari/i.test(C) && !/chrome/i.test(C) && D.toLowerCase() == "paste") { + return false + } + return this.document.queryCommandEnabled(D) && this.document.queryCommandState(D) + } + }; + A.prototype.getContent = function (B) { + if (!B) { + var C = this.document.body.innerHTML; + return C + } else { + var C = baidu.editor.EditorConfig.docType; + C += ""; + C += this.document.documentElement.innerHTML; + C += ""; + return C + } + }; + A.prototype.setContent = function (C) { + var B = this; + this.document.body.innerHTML = C; + setTimeout(function () { + B.dispatchEvent(new baidu.BaseEvent("onbeforeselectionchange")); + B.dispatchEvent(new baidu.BaseEvent("onselectionchange")); + B.dispatchEvent(new baidu.BaseEvent("onafterselectionchange")) + }, 0) + }; + A.prototype._bindEvent = function () { + var D = this; + + function E(F) { + D.selectionChangeHandler(F) + } + + function B(H) { + H = D.window.event || H; + var G = H.keyCode || H.which, F; + D.dispatchEvent(F = new baidu.BaseEvent("onbeforekeydown", H)); + if (F.returnValue == false) { + return + } + D.dispatchEvent(F = new baidu.BaseEvent("onkeydown", H)); + if (F.returnValue == false) { + return + } + if (G != 27 && G != 16 && G != 17 && G != 18) { + clearTimeout(B.timer); + B.timer = setTimeout(function () { + E() + }, 500) + } + D.dispatchEvent(new baidu.BaseEvent("onafterkeydown", H)) + } + + function C(F) { + clearTimeout(C.timer); + C.timer = setTimeout(function () { + E() + }, 20) + } + + baidu.on(D.document, "mouseup", E); + baidu.on(D.document, "keydown", B); + baidu.on(D.document, "mousemove", C); + baidu.on(D.window, "blur", function () { + D.dispatchEvent(new baidu.BaseEvent("onblur")); + D.isBlur = true + }); + baidu.on(D.window, "focus", function () { + D.dispatchEvent(new baidu.BaseEvent("onfocus")); + D.isBlur = false + }); + if (baidu.ie) { + setInterval(function () { + if (!D.isBlur) { + D.ieBakRange = D.document.selection.createRange(); + D.ieBakRangeType = D.document.selection.type + } + }, 20) + } + this.dispatchEvent(new baidu.BaseEvent("onwysiwygready")) + }; + A.prototype.selectionChangeHandler = function (H) { + var G = this.temp.scene; + var C = this.document.body.innerHTML; + if (this.temp.innerHTML != C) { + this.temp.innerHTML = C; + H = this.window.event || H; + if (H && H.type && H.type.indexOf("key") >= 0) { + var E = H.srcElement || H.target; + if (E) { + if (E.nodeType == 3) { + E = E.parentNode + } + var I = E.getElementsByTagName("*").length; + if (E.tagName != "HTML" && E == G.target && I == G.count) { + return + } + G.target = E; + G.count = I + } + } + } else { + if (window.getSelection) { + var B = this.window.getSelection().getRangeAt(0); + if (B.startContainer == G.startContainer && B.endContainer == G.endContainer) { + if (B.collapsed) { + return + } else { + if (B.startOffset == G.startOffset && B.endOffset == G.endOffset) { + return + } + } + } + G.endOffset = B.endOffset; + G.startOffset = B.startOffset; + G.endContainer = B.endContainer; + G.startContainer = B.startContainer + } else { + if (document.selection) { + var F = this.document.selection; + var B = F.createRange(); + var D = F.type.toLowerCase(); + if (G.type == D) { + if (D == "control" && B(0) == G.control) { + return + } else { + if (G.text == B.text && G.parentElement == B.parentElement()) { + return + } + } + } + G.type = D; + if (D == "control") { + G.control = B(0) + } else { + G.text = B.text; + G.parentElement = B.parentElement() + } + } + } + } + this.dispatchEvent(new baidu.BaseEvent("onbeforeselectionchange")); + this.dispatchEvent(new baidu.BaseEvent("onselectionchange")); + this.dispatchEvent(new baidu.BaseEvent("onafterselectionchange")) + }; + A.prototype._setReadyState = function (B) { + this.readyState = B; + this.dispatchEvent(new baidu.BaseEvent("onreadystatechange", B)) + }; + A.prototype.addToolbarItem = function (B) { + if (B && typeof B.initialize == "function") { + B.initialize() + } + }; + baidu.editor.Editor = A +})(); +baidu.editor.create = function (D, A) { + var E = new baidu.editor.Editor(D, A); + if (typeof D == "string") { + D = document.getElementById(D) + } + var C = ""; + if (D && D.tagName) { + if (D.tagName.toLowerCase() == "textarea") { + C = D.value + } else { + C = D.innerHTML + } + } + if (C == "" && A) { + C = A.content || "" + } + if (!baidu.ie && C == "") { + C = "
    " + } + var B = baidu.BaseClass.guid(); + E.addEventListener("onreadystatechange", function (H) { + var G = H.currentTarget; + switch (G.readyState) { + case 3: + G.makeEditable(C); + break; + case 4: + for (var F = baidu.editor._register.length - 1; F >= 0; F--) { + baidu.editor._register[F](this) + } + G.removeEventListener("onreadystatechange", B); + G._bindEvent(); + break + } + }, B); + return E +}; +baidu.editor.Editor.prototype.focus = function () { + this.window.focus(); + try { + if (baidu.ie && this.ieBakRange) { + this.ieBakRange.select() + } + } catch (A) { + } +}; +baidu.dom = baidu.dom || {}; +baidu.isElement = function (A) { + if (A === undefined || A === null) { + return false + } + return A && A.nodeName && A.nodeType == 1 +}; +baidu.isDocument = function (A) { + if (A === undefined || A === null) { + return false + } + return A && A.nodeType == 9 +}; +baidu.dom.getWindow = function (A) { + if (!baidu.isDocument(A)) { + throw new Error("[baidu.dom.getWindow] param must be Document") + } + return A.parentWindow ? A.parentWindow : (A.defaultView ? A.defaultView : null) +}; +baidu.array = baidu.array || {}; +baidu.array.each = function (F, D) { + var C, E, B, A = F.length; + if ("function" == typeof D) { + for (B = 0; B < A; B++) { + E = F[B]; + C = D.call(F, E, B); + if (C === false) { + break + } + } + } + return F +}; +baidu.each = baidu.array.each; +baidu.isElement = function (A) { + if (A === undefined || A === null) { + return false + } + return A && A.nodeName && A.nodeType == 1 +}; +baidu.isText = function (A) { + if (A === undefined || A === null) { + return false + } + return A && A.nodeType == 3 +}; +baidu.browser = baidu.browser || {}; +(function () { + var A = navigator.userAgent; + baidu.firefox = baidu.browser.firefox = /firefox\/(\d+\.\d)/i.test(A) ? parseFloat(RegExp.$1) : 0; + baidu.ie = baidu.browser.ie = /msie (\d+\.\d)/i.test(A) ? parseFloat(RegExp.$1) : 0; + baidu.opera = baidu.browser.opera = /opera\/(\d+\.\d)/i.test(A) ? parseFloat(RegExp.$1) : 0; + baidu.safari = baidu.browser.safari = (/(\d+\.\d)\s+safari/i.test(A) && !/chrome/i.test(A)) ? parseFloat(RegExp.$1) : 0; + try { + baidu.browser.maxthon = /(\d+\.\d)/.test(external.max_version) ? parseFloat(RegExp.$1) : 0 + } catch (B) { + baidu.browser.maxthon = 0 + } + baidu.maxthon = baidu.browser.maxthon; + baidu.isGecko = baidu.browser.isGecko = /gecko/i.test(A) && !/like gecko/i.test(A); + baidu.isStrict = baidu.browser.isStrict = document.compatMode == "CSS1Compat"; + baidu.isWebkit = baidu.browser.isWebkit = /webkit/i.test(A) +})(); +baidu.dom.getDocument = function (A) { + return A.nodeType == 9 ? A : A.ownerDocument || A.document +}; +baidu.dom.getParent = function (B) { + var A = B.parentNode; + return (A && baidu.isElement(A)) ? A : null +}; +baidu.dom.getParents = function (B) { + var A = []; + do { + A.unshift(B) + } while (B = baidu.dom.getParent(B)); + return A +}; +baidu.dom.getIndex = function (C) { + var B = C.parentNode && C.parentNode.firstChild; + var A = -1; + while (B) { + A++; + if (B == C) { + return A + } + B = B.nextSibling + } + return -1 +}; +baidu.dom.getCommonAncestor = function (B, A) { + B = baidu.isElement(B) ? B : baidu.dom.getParent(B); + A = baidu.isElement(A) ? A : baidu.dom.getParent(A); + if (A === B) { + return B + } + if (baidu.dom.element.contains(A, B)) { + return A + } + do { + if (baidu.dom.element.contains(B, A)) { + return B + } + } while ((B = baidu.dom.getParent(B))); + return null +}; +baidu.dom.insertAfter = function (B, A) { + A.parentNode.insertBefore(B, A.nextSibling); + return A +}; +baidu.dom.clone = function (C, A, D) { + var E = C.cloneNode(A); + if (!D) { + var B = function (G) { + if (!baidu.isElement(G)) { + return + } + G.removeAttribute("id", false); + var H = G.childNodes; + for (var F = 0; F < H.length; F++) { + B(H[F]) + } + }; + B(E) + } + return E +}; +baidu.dom.getNext = function (B, C) { + var A = B.nextSibling; + while (C && A && (baidu.isText(A)) && !baidu.trim(A.nodeValue)) { + A = A.nextSibling + } + return A +}; +baidu.dom.getPrevious = function (B, C) { + var A = B.previousSibling; + while (C && A && (baidu.isText(A)) && !baidu.trim(A.nodeValue)) { + A = A.previousSibling + } + return A ? A : null +}; +baidu.dom.getAddress = function (D, F, G) { + var C = [], E = F.documentElement; + while (D && D != E) { + var A = D.parentNode, B = -1, H = A.firstChild; + while (H) { + if (G && H.nodeType == 3 && H.previousSibling && H.previousSibling.nodeType == 3) { + H = H.nextSibling; + continue + } + B++; + if (H == D) { + break + } + H = H.nextSibling + } + C.unshift(B); + D = D.parentNode + } + return C +}; +baidu.dom.getByAddress = function (G, B, H) { + G = G.documentElement; + for (var D = 0; G && D < B.length; D++) { + var F = B[D]; + if (!H) { + G = G.childNodes[F]; + continue + } + var A = -1; + for (var C = 0; C < G.childNodes.length; C++) { + var E = G.childNodes[C]; + if (H === true && E.nodeType == 3 && E.previousSibling && E.previousSibling.nodeType == 3) { + continue + } + A++; + if (A == F) { + G = E; + break + } + } + } + return G ? G : null +}; +baidu.dom.text = baidu.dom.text || {}; +baidu.dom.text.getLength = function (A) { + return A.nodeValue.length +}; +baidu.dom.text.split = function (E, D, C) { + if (baidu.ie && D == baidu.dom.text.getLength(E)) { + var B = C.createTextNode(""); + baidu.dom.insertAfter(B, E); + return B + } + var A = E.splitText(D); + if (!!document.documentMode) { + baidu.dom.insertAfter(C.createTextNode(""), A) + } + return A +}; +baidu.dom.element = baidu.dom.element || {}; +baidu.dom.element.getChildCount = function (A) { + return A.childNodes.length +}; +baidu.dom.element.getChild = function (B, A) { + if (!A.slice) { + B = B.childNodes[A] + } else { + while (A.length > 0 && B) { + B = B.childNodes[A.shift()] + } + } + return B +}; +baidu.dom.element.getName = function (B) { + var C = B.nodeName.toLowerCase(); + if (baidu.ie) { + var A = B.scopeName; + if (A != "HTML") { + C = A.toLowerCase() + ":" + C + } + } + return C +}; +baidu.dom.element.is = function (C) { + var A = baidu.dom.element.getName(C); + for (var B = 0; B < arguments.length; B++) { + if (arguments[B] == A) { + return true + } + } + return false +}; +baidu.dom.element.append = function (C, B, A) { + if (A) { + C.insertBefore(B, C.firstChild) + } else { + C.appendChild(B) + } + return B +}; +baidu.dom.element.remove = function (A, B) { + if (A && A.parentNode && A.nodeName != "BODY") { + A.parentNode.removeChild(A) + } +}; +baidu.dom.element.contains = baidu.ie || baidu.isWebkit ? function (B, A) { + return !baidu.isElement(A) ? B.contains(baidu.dom.getParent(A)) : B != A && B.contains(A) +} : function (B, A) { + return !!(B.compareDocumentPosition(A) & 16) +}; +baidu.dom.element.setAttr = function (C, A, D) { + var B = { + cellpadding: "cellPadding", + cellspacing: "cellSpacing", + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + height: "height", + width: "width", + usemap: "useMap", + frameborder: "frameBorder" + }; + if (baidu.isString(A)) { + if (A == "style") { + C.style.cssText = D + } else { + if (A == "class") { + C.className = D + } else { + if (A == "for") { + C.htmlFor = D + } else { + if (A in B) { + C.setAttribute(B[A], D) + } else { + C[A] = D + } + } + } + } + } else { + for (var E in A) { + if (typeof A[E] != "function") { + baidu.setAttr(C, E, A[E]) + } + } + } +}; +baidu.dom.element.setStyle = function () { + var C = {}, B = /z-?index|font-?weight|opacity|zoom|line-?height/i, A = function (D, E) { + return E.charAt(1).toUpperCase() + }; + return function (G, D, H) { + if (typeof D == "string") { + var E; + if (!(E = C[D])) { + E = C[D] = D.replace(/(-[a-z])/gi, A) + } + var F = G.style; + if (E == "opacity") { + if ("opacity" in F) { + F.opacity = H + } else { + if ("MozOpacity" in F) { + F.MozOpacity = H + } else { + if ("filter" in F) { + F.filter = (F.filter || "").replace(/alpha\([^\)]*\)/gi, "") + (H == 1 ? "" : "alpha(opacity=" + H * 100 + ")"); + F.zoom = 1 + } + } + } + } else { + if (H && H.constructor == Number && !B.test(D)) { + H = H + "px" + } + F[E] = H + } + } else { + for (var I in D) { + if (typeof D[I] != "function") { + baidu.setStyle(G, I, D[I]) + } + } + } + return + } +}(); +baidu.dom.element.hasAttribute = function (C, B) { + var A = C.attributes.getNamedItem(B); + return !!(A && A.specified) +}; +baidu.editor.Range = function (A) { + var B = this; + B.startContainer = null; + B.startOffset = null; + B.endContainer = null; + B.endOffset = null; + B.document = A; + B.collapsed = true +}; +(function () { + POSITION_AFTER_START = 1; + POSITION_BEFORE_END = 2; + POSITION_BEFORE_START = 3; + POSITION_AFTER_END = 4; + var B = function (C) { + C.collapsed = (C.startContainer && C.endContainer && C.startContainer === C.endContainer && C.startOffset == C.endOffset) + }; + var A = function (M, R, C) { + M.optimizeBookmark(); + var Z = M.startContainer; + var O = M.endContainer; + var T = M.startOffset; + var I = M.endOffset; + var Q; + var J; + if (baidu.isText(O)) { + O = baidu.dom.text.split(O, I, this.document) + } else { + var V; + if ((V = baidu.dom.element.getChildCount(O)) > 0) { + if (I >= V) { + O = baidu.dom.element.append(O, M.document.createTextNode("")); + J = true + } else { + O = baidu.dom.element.getChild(O, I) + } + } + } + if (baidu.isText(Z)) { + baidu.dom.text.split(Z, T, this.document); + if (Z === O) { + O = baidu.dom.getNext(Z) + } + } else { + if (!T) { + Z = Z.insertBefore(M.document.createTextNode(""), Z.firstChild); + Q = true + } else { + if (T >= baidu.dom.element.getChildCount(Z)) { + Z = baidu.dom.element.append(Z, M.document.createTextNode("")); + Q = true + } else { + Z = baidu.dom.getPrevious(baidu.dom.element.getChild(Z, T)) + } + } + } + var W = baidu.dom.getParents(Z); + var E = baidu.dom.getParents(O); + var U, a, Y; + for (U = 0; U < W.length; U++) { + a = W[U]; + Y = E[U]; + if (!(a === Y)) { + break + } + } + var X = C, N, L, G, K; + for (var S = U; S < W.length; S++) { + N = W[S]; + if (X && !(N === Z)) { + L = baidu.dom.element.append(X, baidu.dom.clone(N)) + } + G = baidu.dom.getNext(N); + while (G) { + if (G === E[S] || G === O) { + break + } + K = baidu.dom.getNext(G); + if (R == 2) { + baidu.dom.element.append(X, baidu.dom.clone(G, true)) + } else { + if (R == 1) { + baidu.dom.element.append(X, baidu.dom.clone(G, true)) + } + baidu.dom.element.remove(G, C) + } + G = K + } + if (X) { + X = L + } + } + X = C; + for (var P = U; P < E.length; P++) { + N = E[P]; + if (R > 0 && !(N === O)) { + L = baidu.dom.element.append(X, baidu.dom.clone(N)) + } + if (!W[P] || N.parentNode != W[P].parentNode) { + G = baidu.dom.getPrevious(N); + while (G) { + if (G === W[P] || G === Z) { + break + } + K = baidu.dom.getPrevious(G); + if (R == 2) { + X.insertBefore(G.cloneNode(true), X.firstChild) + } else { + baidu.dom.element.remove(G, C); + if (R == 1) { + X.insertBefore(G, X.firstChild) + } + } + G = K + } + } + if (X) { + X = L + } + } + if (R == 2) { + var D = M.startContainer; + if (baidu.isText(D)) { + D.data += D.nextSibling.data; + D.parentNode.removeChild(D.nextSibling) + } + var H = M.endContainer; + if (baidu.isText(H) && H.nextSibling) { + H.data += H.nextSibling.data; + H.parentNode.removeChild(H.nextSibling) + } + } else { + if (a && Y && (Z.parentNode != a.parentNode || O.parentNode != Y.parentNode)) { + var F = baidu.dom.getIndex(Y); + if (Q && Y.parentNode == Z.parentNode) { + F-- + } + M.setStart(baidu.dom.getParent(Y), F) + } + M.collapse(true) + } + if (Q) { + baidu.dom.element.remove(Z, C) + } + if (J && O.parentNode) { + baidu.dom.element.remove(O, C) + } + }; + baidu.editor.Range.prototype = { + deleteContents: function () { + var C = this.document.createDocumentFragment(); + if (this.collapsed) { + return + } + A(this, 0, C) + }, cloneContents: function () { + var C = this.document.createDocumentFragment(); + if (!this.collapsed) { + A(this, 2, C) + } + return C + }, extractContents: function () { + var C = this.document.createDocumentFragment(); + if (!this.collapsed) { + A(this, 1, C) + } + return C + }, clone: function () { + var C = new baidu.editor.Range(this.document); + C.startContainer = this.startContainer; + C.startOffset = this.startOffset; + C.endContainer = this.endContainer; + C.endOffset = this.endOffset; + C.collapsed = this.collapsed; + return C + }, collapse: function (C) { + if (C) { + this.endContainer = this.startContainer; + this.endOffset = this.startOffset + } else { + this.startContainer = this.endContainer; + this.startOffset = this.endOffset + } + this.collapsed = true + }, select: baidu.ie ? function () { + var G = this.collapsed; + var C; + var H; + var K = this.createBookmark(); + var E = K.startNode; + var I; + if (!G) { + I = K.endNode + } + var D = this.document.body.createTextRange(); + D.moveToElementText(E); + D.moveStart("character", 1); + if (I) { + var J = this.document.body.createTextRange(); + J.moveToElementText(I); + D.setEndPoint("EndToEnd", J); + D.moveEnd("character", -1) + } else { + H = this.document.createElement("span"); + H.innerHTML = ""; + E.parentNode.insertBefore(H, E); + var F = this.document.createTextNode("\ufeff"); + E.parentNode.insertBefore(F, E) + } + this.setStartBefore(E); + baidu.dom.element.remove(E, this.document); + if (G) { + D.moveStart("character", -1); + D.select(); + this.document.selection.clear(); + baidu.dom.element.remove(H, this.document) + } else { + this.setEndBefore(I); + baidu.dom.element.remove(I, this.document); + D.select() + } + } : function () { + var D = this.startContainer; + if (this.collapsed && baidu.isElement(D) && !baidu.dom.element.getChildCount(D)) { + baidu.dom.element.append(D, this.document.createTextNode("")) + } + var E = this.document.createRange(); + E.setStart(D, this.startOffset); + try { + E.setEnd(this.endContainer, this.endOffset) + } catch (F) { + if (F.toString().indexOf("NS_ERROR_ILLEGAL_VALUE") >= 0) { + this.collapse(true); + E.setEnd(this.endContainer, this.endOffset) + } else { + throw (F) + } + } + var C = baidu.dom.getWindow(this.document).getSelection(); + C.removeAllRanges(); + C.addRange(E) + }, createBookmark: function (F) { + var E, C; + var D; + var G; + E = this.document.createElement("span"); + baidu.dom.element.setAttr(E, "_BaiduEditor_bm", 1); + baidu.dom.element.setStyle(E, "display", "none"); + E.innerHTML = " "; + if (F) { + D = "_BaiduEditor_bm" + Math.floor(Math.random() * 2147483648).toString(36); + baidu.dom.element.setAttr(E, "id", D + "S") + } + if (!this.collapsed) { + C = baidu.dom.clone(E); + C.innerHTML = " "; + if (F) { + baidu.dom.element.setAttr(C, "id", D + "E") + } + G = this.clone(); + G.collapse(); + G.insertNode(C) + } + G = this.clone(); + G.collapse(true); + G.insertNode(E); + if (C) { + this.setStartAfter(E); + this.setEndBefore(C) + } else { + this.moveToPosition(E, POSITION_AFTER_END) + } + return {startNode: F ? D + "S" : E, endNode: F ? D + "E" : C, serializable: F} + }, moveToPosition: function (D, C) { + this.setStartAt(D, C); + this.collapse(true) + }, createBookmark2: function (I) { + var G = this.startContainer, H = this.endContainer; + var C = this.startOffset, E = this.endOffset; + var J, F; + if (!G || !H) { + return {start: 0, end: 0} + } + if (I) { + if (baidu.isElement(G)) { + J = baidu.dom.element.getChild(G, C); + if (J && baidu.isText(J) && C > 0 && baidu.isText(baidu.dom.getPrevious(J))) { + G = J; + C = 0 + } + } + while (baidu.isText(G) && (F = baidu.dom.getPrevious(G)) && baidu.isText(F)) { + G = F; + C += baidu.dom.text.getLength(F) + } + if (!this.isCollapsed) { + if (baidu.isElement(H)) { + J = baidu.dom.element.getChild(H, E); + if (J && baidu.isText(J) && E > 0 && baidu.isText(baidu.dom.getPrevious(J))) { + H = J; + E = 0 + } + } + while (baidu.isText(H) && (F = baidu.dom.getPrevious(H)) && baidu.isText(F)) { + H = F; + E += baidu.dom.text.getLength(F) + } + } + } + var D = baidu.dom.getAddress(G, this.document, I); + return { + start: D, + end: this.isCollapsed ? D : baidu.dom.getAddress(H, this.document, I), + startOffset: C, + endOffset: E, + normalized: I, + is2: true + } + }, moveToBookmark: function (H) { + if (H.is2) { + var I = baidu.dom.getByAddress(this.document, H.start, H.normalized), D = H.startOffset; + var J = H.end && baidu.dom.getByAddress(this.document, H.end, H.normalized), F = H.endOffset; + this.setStart(I, D); + if (J) { + this.setEnd(J, F) + } else { + this.collapse(true) + } + } else { + var G = H.serializable, E = G ? this.document.getElementById(H.startNode) : H.startNode, C = G ? this.document.getElementById(H.endNode) : H.endNode; + this.setStartBefore(E); + baidu.dom.element.remove(E, this.document); + if (C) { + this.setEndBefore(C); + baidu.dom.element.remove(C, this.document) + } else { + this.collapse(true) + } + } + }, setStart: function (D, C) { + this.startContainer = D; + this.startOffset = C; + if (!this.endContainer) { + this.endContainer = D; + this.endOffset = C + } + B(this) + }, setEnd: function (C, D) { + this.endContainer = C; + this.endOffset = D; + if (!this.startContainer) { + this.startContainer = C; + this.startOffset = D + } + B(this) + }, setStartBefore: function (C) { + this.setStart(baidu.dom.getParent(C), baidu.dom.getIndex(C)) + }, setStartAfter: function (C) { + this.setStart(baidu.dom.getParent(C), baidu.dom.getIndex(C) + 1) + }, setEndAfter: function (C) { + this.setEnd(baidu.dom.getParent(C), baidu.dom.getIndex(C) + 1) + }, setEndBefore: function (C) { + this.setEnd(baidu.dom.getParent(C), baidu.dom.getIndex(C)) + }, setStartAt: function (D, C) { + switch (C) { + case POSITION_AFTER_START: + this.setStart(D, 0); + break; + case POSITION_BEFORE_END: + if (baidu.isText(D)) { + this.setStart(D, baidu.dom.text.getLength(D)) + } else { + this.setStart(D, baidu.dom.element.getChildCount(D)) + } + break; + case POSITION_BEFORE_START: + this.setStartBefore(D); + break; + case POSITION_AFTER_END: + this.setStartAfter(D) + } + B(this) + }, setEndAt: function (D, C) { + switch (C) { + case POSITION_AFTER_START: + this.setEnd(D, 0); + break; + case POSITION_BEFORE_END: + if (baidu.isText(D)) { + this.setEnd(D, baidu.dom.text.getLength(D)) + } else { + this.setEnd(D, baidu.dom.element.getChildCount(D)) + } + break; + case POSITION_BEFORE_START: + this.setEndBefore(D); + break; + case POSITION_AFTER_END: + this.setEndAfter(D) + } + B(this) + }, getCommonAncestor: function (D, F) { + var G = this.startContainer, C = this.endContainer, E; + if (G === C) { + if (D && baidu.isElement(G) && this.startOffset == this.endOffset - 1) { + E = baidu.dom.element.getChild(G, this.startOffset) + } else { + E = G + } + } else { + E = baidu.dom.getCommonAncestor(G, C) + } + return F && !baidu.isElement(E) ? baidu.dom.getParent(E) : E + }, optimizeBookmark: function () { + var D = this.startContainer, C = this.endContainer; + if (baidu.isElement(D) && baidu.dom.element.is(D, "span") && baidu.dom.element.hasAttribute(D, "_BaiduEditor_bm")) { + this.setStartAt(D, POSITION_BEFORE_START) + } + if (C && baidu.isElement(C) && baidu.dom.element.is(C, "span") && baidu.dom.element.hasAttribute(C, "_BaiduEditor_bm")) { + this.setEndAt(C, POSITION_AFTER_END) + } + }, trim: function (F, I) { + var G = this.startContainer, C = this.startOffset, J = this.collapsed; + if ((!F || J) && G && baidu.isText(G)) { + if (!C) { + C = baidu.dom.getIndex(G); + G = baidu.dom.getParent(G) + } else { + if (C >= baidu.dom.text.getLength(G)) { + C = baidu.dom.getIndex(G) + 1; + G = baidu.dom.getParent(G) + } else { + var E = baidu.dom.text.split(G, C, this.document); + C = baidu.dom.getIndex(G) + 1; + G = baidu.dom.getParent(G); + if (!J && this.startContainer === this.endContainer) { + this.setEnd(E, this.endOffset - this.startOffset) + } + } + } + this.setStart(G, C); + if (J) { + this.collapse(true) + } + } + var H = this.endContainer; + var D = this.endOffset; + if (!(I || J) && H && baidu.isText(H)) { + if (!D) { + D = baidu.dom.getIndex(H); + H = baidu.dom.getParent(H) + } else { + if (D >= baidu.dom.text.getLength(H)) { + D = baidu.dom.getIndex(H) + 1; + H = baidu.dom.getParent(H) + } else { + baidu.dom.text.split(H, D, this.document); + D = baidu.dom.getIndex(H) + 1; + H = baidu.dom.getParent(H) + } + } + this.setEnd(H, D) + } + }, insertNode: function (F) { + this.optimizeBookmark(); + this.trim(false, true); + var E = this.startContainer; + var D = this.startOffset; + var C = baidu.dom.element.getChild(E, D); + if (C) { + C.parentNode.insertBefore(F, C) + } else { + E.appendChild(F) + } + if (baidu.dom.getParent(F) === this.endContainer) { + this.endOffset++ + } + this.setStartBefore(F) + }, getTouchedStartNode: function () { + var C = this.startContainer; + if (this.collapsed || !baidu.isElement(C)) { + return C + } + return baidu.dom.element.getChild(C, this.startOffset) || C + }, getTouchedEndNode: function () { + var C = this.endContainer; + if (this.collapsed || !baidu.isElement(C)) { + return C + } + return baidu.dom.element.getChild(this.endOffset - 1) || C + }, optimize: function () { + var C = this.startContainer; + var D = this.startOffset; + if (!baidu.isElement(C)) { + if (!D) { + this.setStartBefore(C) + } else { + if (D >= baidu.dom.text.getLength(C)) { + this.setStartAfter(C) + } + } + } + C = this.endContainer; + D = this.endOffset; + if (!baidu.isElement(C)) { + if (!D) { + this.setEndBefore(C) + } else { + if (D >= baidu.dom.text.getLength(C)) { + this.setEndAfter(C) + } + } + } + }, walk: function (L) { + var E = this.startContainer, H = this.startOffset, M = this.endContainer, I = this.endOffset, K = [{ + n: baidu.firefox && this.startContainer.nodeName.toUpperCase() == "TR" ? baidu.dom.getParent(this.getCommonAncestor(0, 1)) : this.getCommonAncestor(0, 1), + i: 0 + }], G, J = false; + + function D(P, O, N) { + try { + if (J == -1 && !baidu.dom.element.contains(P, E)) { + J = true + } + if (!J && (baidu.dom.getParent(P) == E && O == H)) { + J = true + } + if (baidu.isText(P) && P == E) { + if (baidu.dom.text.getLength(P) == H) { + J = -1 + } else { + if (!J) { + J = true + } + } + } + if (!N) { + return + } + if (baidu.isText(P) && P == M && I == 0) { + J = false + } + if (J == true || (J == -2 && P == M)) { + L(P) + } + if (baidu.dom.getParent(P) == M && O + 1 == I) { + J = -2 + } + if (baidu.isText(P) && P == M) { + J = false + } + } catch (Q) { + } + } + + while (G = K.pop()) { + var C = G.n, F = cri = G.i; + D(C, cri, false); + while (C.childNodes[cri] != undefined) { + K.push({n: C, i: cri}); + C = C.childNodes[cri]; + D(C, cri, false); + F = cri; + cri = 0 + } + D(C, F, true); + if (K.length) { + K[K.length - 1].i++ + } + } + }, dispose: function () { + for (var C in this) { + if (typeof this[C] != "function") { + delete this[C] + } + } + } + } +})(); +var SELECTION_NONE = 0; +var SELECTION_TEXT = 2; +var SELECTION_CONTROL = 3; +var styleObjectElements = { + img: 1, + hr: 1, + li: 1, + table: 1, + tr: 1, + td: 1, + embed: 1, + object: 1, + ol: 1, + ul: 1, + a: 1, + input: 1, + form: 1, + select: 1, + textarea: 1, + button: 1, + fieldset: 1, + th: 1, + thead: 1, + tfoot: 1 +}; +baidu.editor.Editor.prototype.getSelection = function () { + var B = this; + if (!B.selection) { + var A = B.document; + B.selection = { + getNative: baidu.ie ? function () { + return A.selection + } : function () { + return baidu.dom.getWindow(A).getSelection() + }, getNativeRange: function () { + if (baidu.ie) { + var C = this.getNative(), D = C.createRange(); + if (C.type.toUpperCase() != "CONTROL" && baidu.dom.getDocument(D.parentElement()) != B.document) { + range = B.ieBakRange; + if (range) { + return range + } + } + return D + } else { + throw new Error("[baidu.editor.selection.getNativeRange] only support ie now!") + } + }, getType: baidu.ie ? function () { + var C = SELECTION_NONE; + try { + var E = this.getNative(), F = E.type; + if (E.createRange().parentElement) { + C = SELECTION_TEXT + } + if (F.toUpperCase() != "CONTROL" && baidu.dom.getDocument(E.createRange().parentElement()) != B.document) { + if (!B.ieBakRange) { + return SELECTION_NONE + } + F = B.ieBakRangeType + } + if (F == "Text") { + C = SELECTION_TEXT + } + if (F == "Control") { + C = SELECTION_CONTROL + } + } catch (D) { + } + return C + } : function () { + var D = SELECTION_TEXT; + var F = this.getNative(); + if (!F) { + D = SELECTION_NONE + } else { + if (F.rangeCount == 1) { + var C = F.getRangeAt(0), E = C.startContainer; + if (E == C.endContainer && E.nodeType == 1 && (C.endOffset - C.startOffset) == 1 && styleObjectElements[E.childNodes[C.startOffset].nodeName.toLowerCase()]) { + D = SELECTION_CONTROL + } + } + } + return D + }, getRanges: baidu.ie ? (function () { + var C = function (I, E) { + I = I.duplicate(); + I.collapse(E); + var K = I.parentElement(); + var F = K.firstChild; + var G, H = 0; + while (F) { + if (F.nodeType == 1) { + G = I.duplicate(); + G.moveToElementText(F); + G.collapse(); + var L = G.compareEndPoints("StartToStart", I); + if (L > 0) { + break + } else { + if (L === 0) { + return {container: K, offset: H} + } + } + G = null + } + F = F.nextSibling; + H++ + } + if (!G) { + G = I.duplicate(); + G.moveToElementText(K); + G.collapse(false) + } + G.setEndPoint("StartToStart", I); + var D = G.text.length; + var J = K.childNodes; + while (D > 0 && H--) { + F = J[H]; + D -= F.nodeValue ? F.nodeValue.length : 0 + } + if (D === 0) { + return {container: K, offset: H} + } else { + if (D > 0) { + return {container: K, offset: 0} + } else { + return {container: J[H], offset: -D} + } + } + }; + return function () { + var F = this.getNative(), K = F && F.createRange(), L = this.getType(), J; + if (!F) { + return [] + } + if (L != SELECTION_CONTROL && F.createRange().parentElement().ownerDocument != B.document) { + K = B.ieBakRange; + if (!K) { + return [] + } + L = B.ieBakRangeType.toUpperCase() == "CONTROL" ? SELECTION_CONTROL : (B.ieBakRangeType.toUpperCase() == "TEXT" ? SELECTION_TEXT : SELECTION_NONE) + } + if (L === SELECTION_TEXT) { + J = this.createRange(); + var D = C(K, true); + J.setStart(D.container, D.offset); + D = C(K); + J.setEnd(D.container, D.offset); + return [J] + } else { + if (L == SELECTION_CONTROL) { + var E = []; + for (var H = 0; H < K.length; H++) { + var I = K.item(H), M = I.parentNode, G = 0; + J = this.createRange(); + for (; G < M.childNodes.length && M.childNodes[G] != I; G++) { + } + J.setStart(M, G); + J.setEnd(M, G + 1); + E.push(J) + } + return E + } + } + return [] + } + })() : function () { + var C = []; + var G = this.getNative(); + if (!G) { + return [] + } + for (var E = 0; E < G.rangeCount; E++) { + var F = G.getRangeAt(E); + var D = this.createRange(); + D.setStart(F.startContainer, F.startOffset); + D.setEnd(F.endContainer, F.endOffset); + C.push(D) + } + return C + }, createRange: function () { + return new baidu.editor.Range(A) + }, selectRanges: function (C) { + if (baidu.ie) { + if (C[0]) { + C[0].select() + } + } else { + var G = this.getNative(); + G.removeAllRanges(); + for (var E = 0; E < C.length; E++) { + var D = C[E]; + var F = A.createRange(); + F.setStart(D.startContainer, D.startOffset); + F.setEnd(D.endContainer, D.endOffset); + G.addRange(F) + } + } + }, setCursor: function (E, C) { + var D = this.createRange(A); + D.setStartAt(E, C); + D.collapse(true); + this.selectRanges([D]) + }, selectElement: function (C) { + var D = this; + if (baidu.ie) { + D.getNative().empty(); + try { + range = A.body.createControlRange(); + range.addElement(C); + range.select() + } catch (F) { + range = A.body.createTextRange(); + range.moveToElementText(C); + range.select() + } + } else { + range = A.createRange(); + range.selectNode(C); + var E = D.getNative(); + E.removeAllRanges(); + E.addRange(range) + } + }, pasteElements: function (F, C) { + var E = this; + range = E.getRanges()[0]; + range.deleteContents(); + for (var D = F.length - 1; D >= 0; D--) { + range.insertNode(F[D]) + } + if (C) { + range.setStartBefore(F[F.length - 1]); + range.setEndAfter(F[0]); + range.select() + } else { + E.setCursor(F[F.length - 1], 4) + } + }, pasteElement: function (E, D) { + var F = this, C = F.getRanges()[0]; + C.deleteContents(); + C.insertNode(E); + if (D) { + B.selection.selectElement(E) + } else { + F.setCursor(E, 4) + } + }, getText: function (C) { + if (baidu.ie) { + var D = B.document.selection.createRange(), E = C ? D.text : baidu.trim(D.text); + return E.replace("\r\n", "") + } else { + var D = B.window.getSelection().getRangeAt(0), E = C ? D.toString() : baidu.trim(D.toString()); + return E.replace("\n", "") + } + }, getTextNodes: function () { + var E = this; + var C = E.getRanges(); + var F = []; + for (var D = 0; D < C.length; D++) { + C[D].walk(function (G) { + if (G.nodeType == 3) { + F.push(G) + } + }) + } + return F + }, getSelectedElement: function () { + var D; + if (this.getType() == SELECTION_CONTROL) { + var E = this.getNative(); + if (baidu.ie) { + try { + D = E.createRange().item(0) + } catch (F) { + } + } else { + var C = E.getRangeAt(0); + D = C.startContainer.childNodes[C.startOffset] + } + } + return D + } + } + } + return B.selection +}; +baidu.editor.Editor.prototype.undo = function () { + this.execCommand("Undo") +}; +baidu.editor.Editor.prototype.redo = function () { + this.execCommand("Redo") +}; +(function () { + function B(E) { + var D = this; + D.editor = E; + E.addEventListener("onneedsavescene", function (F) { + D.save(false) + }) + } + + B.prototype.undoList = []; + B.prototype.undoIndex = 0; + B.prototype.getScene = function () { + var F = {bookmarks: []}; + var D = this.editor.getSelection().getRanges(); + for (var E = D.length - 1; E >= 0; E--) { + if (D[E]) { + F.bookmarks.push(D[E].createBookmark2(true)) + } else { + F.bookmarks.push(false) + } + } + F.content = this.editor.getContent(); + return F + }; + B.prototype.applyScene = function (G) { + if (!G) { + return + } + this.editor.setContent(G.content); + var D = []; + for (var F = G.bookmarks.length - 1; F >= 0; F--) { + if (G.bookmarks[F]) { + var E = this.editor.getSelection().createRange(); + E.moveToBookmark(G.bookmarks[F]); + D.push(E) + } + } + this.editor.getSelection().selectRanges(D); + this.undoIndex = G.index; + this.currentScene = G; + this.fireChange() + }; + B.prototype.save = function (E, G, H) { + var F = this.currentScene; + if (!G) { + G = this.getScene() + } + if (E && F && F.content == G.content) { + return + } + this.undoList = this.undoList.slice(0, this.undoIndex + 1); + this.undoList.push(G); + var D = this.undoList.length; + if (D > baidu.editor.EditorConfig.maxUndoCount) { + this.undoList = this.undoList.slice(D - baidu.editor.EditorConfig.maxUndoCount, D) + } + this.undoIndex = this.undoList.length - 1; + this.currentScene = G; + if (H !== false) { + this.fireChange() + } + return true + }; + B.prototype.getNextScene = function (E) { + var D = this.undoList, G = this.currentScene, H, F; + if (G) { + if (E) { + for (F = this.undoIndex - 1; F >= 0; F--) { + H = D[F]; + if (G.content != H.content) { + H.index = F; + return H + } + } + } else { + for (F = this.undoIndex + 1; F < D.length; F++) { + H = D[F]; + if (G.content != H.content) { + H.index = F; + return H + } + } + } + } + return null + }; + B.prototype.fireChange = function () { + this.hasUndo = !!this.getNextScene(true); + this.hasRedo = !!this.getNextScene(false); + this.resetType() + }; + B.prototype.resetType = function () { + this.typing = false; + delete this.lastKeystroke; + this.typesCount = 0; + this.modifiersCount = 0 + }; + baidu.editor.register(function (F) { + var E = new B(F); + F.undoMan = E; + function D(I) { + var I = F.window.event || I; + var H = I.keyCode || I.which; + modifierCodes = { + 8: 1, + 46: 1 + }, isModifier = H in modifierCodes, wasModifier = E.lastKeyCode in modifierCodes, lastWasSameModifier = isModifier && H == E.lastKeyCode, resetTypingCodes = { + 37: 1, + 38: 1, + 39: 1, + 40: 1 + }, isReset = H in resetTypingCodes, wasReset = E.lastKeyCode in resetTypingCodes, isContent = (!isModifier && !isReset), modifierSnapshot = (isModifier && !lastWasSameModifier), startedTyping = !E.typing || (isContent && (wasModifier || wasReset)); + if (startedTyping || modifierSnapshot) { + var G = E.getScene(); + + function J() { + var K = F.getContent(); + if (G.content != K) { + if (!E.save(true, G, false)) { + E.undoList = E.undoList.slice(0, E.undoIndex + 1) + } + E.hasUndo = true; + E.hasRedo = false; + E.typesCount = 1; + E.modifiersCount = 1 + } + } + + setTimeout(function () { + J() + }, 0) + } + E.lastKeyCode = H; + if (isModifier) { + E.typesCount = 0; + E.modifiersCount++; + if (E.modifiersCount > 25) { + E.save(true); + E.modifiersCount = 1 + } + } else { + if (!isReset) { + E.modifiersCount = 0; + E.typesCount++; + if (E.typesCount > 25) { + E.save(true); + E.typesCount = 1 + } + } + } + E.typing = true + } + + F.addEventListener("onkeydown", D, false); + F.addEventListener("onbeforeexeccommand", function (G) { + if (!G.target.topOpearation || G.target.command == "Undo" || G.target.command == "Redo") { + return + } + E.save(false) + }); + F.addEventListener("onafterexeccommand", function (G) { + if (!G.target.topOpearation || G.target.command == "Undo" || G.target.command == "Redo") { + return + } + E.save(false) + }); + E.save(true) + }); + function C(D) { + if (!D.undoMan.hasUndo) { + return + } + if (D.undoMan.undoIndex == D.undoMan.undoList.length - 1) { + D.undoMan.save(false) + } + D.undoMan.applyScene(D.undoMan.getNextScene(true)) + } + + function A(D) { + if (!D.undoMan.hasRedo) { + return + } + if (D.undoMan.undoIndex == D.undoMan.undoList.length - 1) { + return + } + D.undoMan.applyScene(D.undoMan.getNextScene(false)) + } + + baidu.editor.registCommand("Undo", function (D) { + C(D) + }); + baidu.editor.registCommand("Redo", function (D) { + A(D) + }); + baidu.editor.registQuery("Undo", function (D) { + return D.undoMan.hasUndo + }); + baidu.editor.registQuery("Redo", function (D) { + return D.undoMan.hasRedo + }) +})(); +baidu.editor.Editor.prototype.bold = function () { + this.execCommand("Bold"); + this.dispatchEvent(new baidu.BaseEvent("onbold")) +}; +(function () { + var J = {}; + var H = 1, B = 2, G = 3, E = 4, F = 5, I = 6; + + function K(N, M, L) { + var O = this; + O.context = M, O.range = L; + O.nodeInRange = function (P) { + O.context.contains.push(P); + var Q = P.lastChild; + while (Q) { + O.context.contains.push(Q); + Q = Q.previousSibling + } + }; + O.nodePartlyInRange = function (P, Q) { + O.context.partlyContains.push(P); + if (Q) { + var R = P.lastChild; + while (R) { + if (O.process(R) == E) { + break + } + R = R.previousSibling + } + } else { + var R = P.firstChild; + while (R) { + if (O.process(R) == G) { + break + } + R = R.nextSibling + } + } + }; + O.rangeInNode = function (T, U, Q) { + if (O.context.parents[0] != T) { + O.context.parents.unshift(T) + } + var P = Math.floor((Q + U) / 2); + while (Q >= U) { + var S = T.childNodes[P], R = O.compareRangeWithNode(S, L); + if (R == G) { + Q = P - 1 + } else { + if (R == E) { + U = P + 1 + } else { + if (R == I) { + O.rangeInNode(S, 0, S.childNodes.length - 1); + break + } else { + if (R == F) { + O.nodeInRange(S); + if (U <= P - 1) { + O.rangeInNode(T, U, P - 1) + } + if (P + 1 <= Q) { + O.rangeInNode(T, P + 1, Q) + } + break + } else { + if (R == H) { + O.nodePartlyInRange(S, true); + U = P + 1 + } else { + if (R == B) { + O.nodePartlyInRange(S, false); + Q = P - 1 + } + } + } + } + } + } + P = Math.floor((Q + U) / 2) + } + }; + O.process = function (P) { + var Q = O.compareRangeWithNode(P, O.range); + if (Q == F) { + O.nodeInRange(P) + } else { + if (Q == H || Q == B) { + O.nodePartlyInRange(P, Q == H) + } else { + if (Q == I) { + O.rangeInNode(P, 0, P.childNodes.length - 1) + } + } + } + return Q + }; + O.compareRangeWithNode = function (U, Q) { + if (baidu.ie) { + var T = N.document.body.createTextRange(); + if (U.nodeType == 1) { + T.moveToElementText(U) + } else { + var R = N.document.createElement("a"); + U.parentNode.insertBefore(R, U); + var a = N.document.body.createTextRange(); + a.moveToElementText(R); + R.parentNode.removeChild(R); + T.setEndPoint("StartToStart", a); + R = N.document.createElement("a"); + U.parentNode.insertBefore(R, U.nextSibling); + var a = N.document.body.createTextRange(); + a.moveToElementText(R); + R.parentNode.removeChild(R); + T.setEndPoint("EndToStart", a) + } + var S = Q.compareEndPoints("StartToStart", T), Y = Q.compareEndPoints("EndToStart", T), P = Q.compareEndPoints("StartToEnd", T), V = Q.compareEndPoints("EndToEnd", T) + } else { + var Z = N.document.createRange(); + if (baidu.isText(U) && U.parentNode.childNodes.length == 1) { + U = U.parentNode + } + Z.selectNode(U); + var X = N.document.createRange(); + X.selectNodeContents(U); + var W; + var S = (W = Q.compareBoundaryPoints(Range.START_TO_START, Z)) == Q.compareBoundaryPoints(Range.START_TO_START, X) ? W : 0, P = (W = Q.compareBoundaryPoints(Range.END_TO_START, Z)) == Q.compareBoundaryPoints(Range.END_TO_START, X) ? W : 0, Y = (W = Q.compareBoundaryPoints(Range.START_TO_END, Z)) == Q.compareBoundaryPoints(Range.START_TO_END, X) ? W : 0, V = (W = Q.compareBoundaryPoints(Range.END_TO_END, Z)) == Q.compareBoundaryPoints(Range.END_TO_END, X) ? W : 0 + } + if (S <= 0 && V >= 0) { + return F + } + if (S >= 0 && V <= 0) { + return I + } + if (S * Y == -1) { + return B + } + if (P * V == -1) { + return H + } + if (S <= 0 && Y <= 0) { + return G + } + if (P >= 0 && V >= 0) { + return E + } + } + } + + J.w3cParser = function (Q) { + function R(T) { + if (T.startContainer.nodeType == 3 && T.startContainer.nodeValue.length == T.startOffset) { + T.setStartAfter(T.startContainer) + } + if (T.endContainer.nodeType == 3 && T.endOffset == 0) { + T.setEndBefore(T.endContainer) + } + return T + } + + var S = new Array(), P = Q.window.getSelection(); + for (var N = 0; N < P.rangeCount; N++) { + var L = R(P.getRangeAt(N)); + context = {parents: [], collapsed: false, contains: [], partlyContains: []}; + if (L.collapsed) { + context.collapsed = true; + var O = L.startContainer; + do { + context.parents.push(O); + O = O.parentNode + } while (O.parentNode && O.nodeName != "HTML") + } else { + var M = L.commonAncestorContainer, O = baidu.isText(M) ? baidu.dom.getParent(M) : M; + do { + context.parents.push(O); + O = O.parentNode + } while (O.parentNode && O.nodeName != "HTML"); + (new K(Q, context, L)).process(M) + } + S.push(context) + } + return S + }; + J.ieParser = function (P) { + var M = "CONTROL", O = P.document.selection, N = O.type, L, Q = [{ + collapsed: [], + parents: [], + contains: [], + partlyContains: [] + }]; + if (N.toUpperCase() != M && O.createRange().parentElement().ownerDocument != P.document) { + L = P.ieBakRange; + if (!L) { + return Q + } + N = P.ieBakRangeType + } else { + L = O.createRange() + } + if (N.toUpperCase() == M) { + return C(P, L) + } else { + return A(P, L) + } + }; + function C(P, M) { + var Q = M.commonParentElement(), O = P.document.selection, N = { + collapsed: false, + parents: [], + contains: [], + partlyContains: [] + }; + do { + N.parents.push(Q); + Q = Q.parentNode + } while (Q.nodeName.toUpperCase() != "HTML"); + var L = []; + L.push(M.item(0)); + while (L.length > 0) { + var Q = L.pop(), R = Q.lastChild; + while (R) { + L.push(R); + R = R.previousSibling + } + N.contains.push(Q) + } + return [N] + } + + function A(M, L) { + var O = new Array(); + context = {collapsed: false, parents: [], contains: [], partlyContains: []}; + if (D(L)) { + context.collapsed = true + } + O.push(context); + var N = L.parentElement(); + do { + context.parents.push(N); + N = N.parentNode + } while (N.nodeName.toUpperCase() != "HTML"); + (new K(M, context, L)).process(L.parentElement()); + return O + } + + function D(M) { + try { + var L = M.duplicate(), O = M.duplicate(); + L.collapse(true); + O.collapse(false); + return L.inRange(O) + } catch (N) { + return false + } + } + + baidu.editor.Editor.prototype.getContexts = function () { + var N = this; + if (!N.contextParserInit) { + function L() { + var O; + if (baidu.ie) { + O = J.ieParser(N) + } else { + O = J.w3cParser(N) + } + if (O) { + N.contextsInfo = O + } + } + + N.addEventListener("onbeforeselectionchange", function (O) { + L() + }); + L(); + N.contextParserInit = true + } + if (!N.contextsObj) { + N.contextsObj = { + containNode: function (U, V) { + function O(g, a, c) { + var Y = [], f = -1; + for (var Z = a.length - 1; Z >= 0; Z--) { + Y = Y.concat(a[Z]) + } + a = Y; + if (!a) { + return f + } + for (var Z = a.length - 1; Z >= 0; Z--) { + var b = a[Z]; + try { + if (b.ownerDocument != N.document) { + continue + } + } catch (d) { + continue + } + if (baidu.isText(b)) { + if (baidu.trim(b.nodeValue)) { + b = baidu.dom.getParent(b) + } + } + if (!b) { + continue + } + if (c.toLowerCase().indexOf("," + b.nodeName.toLowerCase() + ",") != -1) { + continue + } + if (g.toLowerCase().indexOf("," + b.nodeName.toLowerCase() + ",") == -1) { + if (f == 1) { + return 2 + } + f = 0 + } else { + if (f == 0) { + return 2 + } + f = 1 + } + } + return f + } + + U = "," + U + ","; + V = "," + V + ","; + var Q = this; + var S = false, T = false; + for (var R = Q.contains.length - 1; R >= 0; R--) { + if (Q.contains[R].length) { + S = true + } + if (Q.partlyContains[R].length) { + T = true + } + } + if (S || T) { + var X = O(U, Q.contains, V), W = O(U, Q.partlyContains, V); + if ((W == 2) && (X == -1 || X == 0)) { + return 2 + } + if ((W != -1 || X != -1) && (X == 1 || X == -1) && (W == 1 || W == -1)) { + return 1 + } + if (W > 0 || X > 0) { + return 2 + } + } + var P = O(U, Q.parents, V); + if (P == 2 || P == 1) { + return 3 + } + return 0 + }, walkTextNode: function (Q) { + var T = this, O = []; + + function P(W) { + for (var V = W.length - 1; V >= 0; V--) { + for (var U = W[V].length - 1; U >= 0; U--) { + if (baidu.isText(W[V][U]) && baidu.trim(W[V][U].nodeValue)) { + O.push(W[V][U]) + } + } + } + } + + P(T.contains); + P(T.partlyContains); + for (var R = T.parents.length - 1; R >= 0; R--) { + try { + if (T.parents[R][0].ownerDocument != N.document) { + continue + } + } catch (S) { + continue + } + if (baidu.isText(T.parents[R][0]) && baidu.trim(T.parents[R][0].nodeValue)) { + O.push(T.parents[R][0]) + } + } + for (var R = O.length - 1; R >= 0; R--) { + Q(O[R]) + } + } + } + } + N.contextsObj.collapsed = []; + N.contextsObj.parents = []; + N.contextsObj.contains = []; + N.contextsObj.partlyContains = []; + for (var M = N.contextsInfo.length - 1; M >= 0; M--) { + N.contextsObj.collapsed.push(N.contextsInfo[M].collapsed); + N.contextsObj.parents.push(N.contextsInfo[M].parents); + N.contextsObj.contains.push(N.contextsInfo[M].contains); + N.contextsObj.partlyContains.push(N.contextsInfo[M].partlyContains) + } + return N.contextsObj + } +})(); +baidu.getStyle = function (C, A) { + if (C = baidu.G(C)) { + var B = baidu.isString(A); + A = B ? [A] : A; + var G = []; + var H = function (M, N) { + return N.charAt(1).toUpperCase() + }; + var J = function (M) { + var Q = M.split(","); + var P = "#", O; + for (var N = 0; O = Q[N]; N++) { + O = O.replace(/[^\d]/gi, ""); + O = parseInt(O, 10); + O = O.toString(16); + if (O.length == 1) { + O = "0" + O + } + P += O + } + return P.toUpperCase() + }; + for (var F = 0, D; F < A.length; F = F + 1) { + var E = A[F].replace(/(-[a-z])/gi, H); + if ("float" == E) { + E = baidu.isIE ? "styleFloat" : "cssFloat" + } + if ("opacity" == E && baidu.isIE) { + var L = C.style.filter; + D = L && L.indexOf("opacity=") >= 0 ? (parseFloat(L.match(/opacity=([^)]*)/)[1]) / 100) + "" : "1" + } + if (D = C.style[E]) { + G[F] = D + } else { + if (C.currentStyle) { + D = C.currentStyle[E] + } else { + var I = C.nodeType == 9 ? C : C.ownerDocument || C.document; + if (I.defaultView && I.defaultView.getComputedStyle) { + var K = I.defaultView.getComputedStyle(C, ""); + if (K) { + D = K[E] + } + } + } + } + if (/color/i.test(E) && D.indexOf("rgb(") != -1) { + D = J(D) + } + G[F] = D + } + if (B) { + G = G[0] + } + return G + } +}; +baidu.editor.registParser("bold", function (A) { + var B = -1; + A.getContexts().walkTextNode(function (C) { + var D = baidu.getStyle(baidu.dom.getParent(C), "font-weight"); + if (((parseInt(D) > 400 || D == "bold") && (C.parentNode.tagName.indexOf("H") !== 0)) && (B == -1 || B == 1)) { + B = 1 + } else { + B = 0 + } + }); + if (B == -1) { + B = 0 + } + return B +}); +baidu.editor.Editor.prototype.italic = function () { + this.execCommand("Italic"); + this.dispatchEvent(new baidu.BaseEvent("onitalic")) +}; +baidu.editor.registParser("italic", function (A) { + var B = -1; + A.getContexts().walkTextNode(function (C) { + var D = baidu.getStyle(baidu.dom.getParent(C), "font-style"); + if (D == "italic" && (B == -1 || B == 1)) { + B = 1 + } else { + B = 0 + } + }); + if (B == -1) { + B = 0 + } + return B +}); +baidu.editor.Editor.prototype.underline = function () { + this.execCommand("Underline"); + this.dispatchEvent(new baidu.BaseEvent("onunderline")) +}; +baidu.editor.registParser("underline", function (A) { + return A.getContexts().containNode("u") +}); +baidu.editor.Editor.prototype.fontname = function (A) { + this.execCommand("FontName", false, A); + this.dispatchEvent(new baidu.BaseEvent("onfontname")) +}; +(function () { + baidu.editor.Editor.prototype.queryFontname = function () { + var I = this; + var B = I.getSelection().getRanges(); + var H = []; + if (B.length == 1 && B[0].collapsed) { + var G = B[0]; + var F = G.startContainer; + while (F.nodeType == 3 && F.parentNode) { + F = F.parentNode + } + var E = baidu.getStyle(F, "font-family"); + return A(E) + } + for (var C = 0; C < B.length; C++) { + var G = B[C]; + G.walk(function (J) { + if (J.nodeType == 3) { + H.push(J) + } + }) + } + var E = null; + for (var C = 0; C < H.length; C++) { + var F = H[C]; + var D = A(baidu.getStyle(F.parentNode, "font-family")); + if (D && E && D != E) { + return null + } else { + if (E == null && D) { + E = D + } + } + } + return E + }; + function A(B) { + return B && B.replace(/\'/gi, "") + } +})(); +baidu.editor.Editor.prototype.fontsize = function (A) { + this.window.focus(); + this.execCommand("FontSize", false, A); + this.dispatchEvent(new baidu.BaseEvent("onfontsize")) +}; +(function () { + baidu.editor.Editor.prototype.queryFontsize = function () { + var I = this; + var D = I.getSelection().getRanges(); + var H = []; + if (D.length == 1 && D[0].collapsed) { + var G = D[0]; + var F = G.startContainer; + while (F.nodeType == 3 && F.parentNode) { + F = F.parentNode + } + var C = baidu.getStyle(F, "font-size"); + return A(C) + } + for (var E = 0; E < D.length; E++) { + var G = D[E]; + G.walk(function (J) { + if (J.nodeType == 3) { + H.push(J) + } + }) + } + var C = null; + for (var E = 0; E < H.length; E++) { + var F = H[E]; + var B = A(baidu.getStyle(F.parentNode, "font-size")); + if (B && C && B != C) { + return null + } else { + if (C == null && B) { + C = B + } + } + } + return C + }; + function A(C) { + var D = {"10px": 1, "13px": 2, "16px": 3, "18px": 4, "24px": 5, "32px": 6, "48px": 7}; + var B = {"x-small": 1, small: 2, medium: 3, large: 4, "x-large": 5, "xx-large": 6, "-webkit-xxx-large": 7}; + if (!C) { + return null + } else { + C = C.toLowerCase(); + if (C.indexOf("px") >= 0) { + return D[C] + } else { + if (/^\d+/g.test(C)) { + return C + } else { + return B[C] + } + } + } + } +})(); +baidu.editor.Editor.prototype.foreColor = function (A) { + this.execCommand("ForeColor", false, A); + this.dispatchEvent(new baidu.BaseEvent("onforecolor")) +}; +(function () { + baidu.editor.Editor.prototype.queryForeColor = function () { + var H = this, C = H.getSelection(), E = false, F = false, B = C.getRanges(), J = A || function (L) { + return L + }; + + function K(M) { + var L; + while (M.parentNode && !(L = J(baidu.getStyle(M, "color")))) { + M = M.parentNode + } + return L + } + + if (B.length == 1 && B[0].collapsed) { + var D = B[0].startContainer; + if (baidu.isText(D)) { + D = baidu.dom.getParent(D) + } + E = K(D) + } else { + var I = C.getTextNodes(); + for (var G = 0; G < I.length; G++) { + var F = K(I[G]); + if (F && E && F != E) { + return false + } else { + if (!E && F) { + E = F + } + } + } + } + return E + }; + function A(C) { + var B = { + aqua: "00FFFF", + black: "000000", + blue: "0000FF", + fuchsia: "FF00FF", + gray: "808080", + green: "008000", + lime: "00FF00", + maroon: "800000", + navy: "000080", + olive: "808000", + purple: "800080", + red: "FF0000", + silver: "C0C0C0", + teal: "008080", + white: "FFFFFF", + yellow: "FFFF00", + transparent: "" + }; + if (B[C] == undefined) { + return C + } + return B[C] ? "#" + B[C] : "" + } +})(); +baidu.editor.Editor.prototype.justifyLeft = function () { + this.execCommand("JustifyLeft", false); + this.dispatchEvent(new baidu.BaseEvent("onjustifyleft")) +}; +baidu.editor.Editor.prototype.justifyCenter = function () { + this.execCommand("JustifyCenter", false); + this.dispatchEvent(new baidu.BaseEvent("onjustifycenter")) +}; +baidu.editor.Editor.prototype.justifyRight = function () { + this.execCommand("JustifyRight", false); + this.dispatchEvent(new baidu.BaseEvent("onjustifyright")) +}; +baidu.editor.Editor.prototype.insertImage = function (A) { + this.execCommand("insertImage", A); + this.dispatchEvent(new baidu.BaseEvent("oninsertimage")) +}; +(function () { + function B(E, C) { + var D = E.document.createElement("IMG"); + D.src = C.src; + if (C.width) { + D.width = C.width + } + if (C.height) { + D.height = C.height + } + E.getSelection().pasteElement(D, true) + } + + function A(E) { + var C = E.getSelection().getRanges()[0], D; + D = C.startContainer; + if (D.nodeName != "IMG") { + D = baidu.dom.element.getChild(C.startContainer, C.startOffset) + } + if (D && D.nodeName == "IMG") { + return {src: D.style.backgroundImage || D.src} + } + } + + baidu.editor.Editor.prototype.getImage = function () { + return A(this) + }; + baidu.editor.registCommand("insertImage", B) +})(); +baidu.editor.registParser("image", function (A) { + return A.getContexts().containNode("img", "p") +}); +baidu.editor.toolbar = {}; +baidu.editor.toolbar.createElement = function (A) { + var B = document.createElement(A); + B.style.MozUserSelect = "none"; + B.unselectable = "on"; + return B +}; +function ItemBase(A) { + baidu.BaseClass.call(this); + this.name = ""; + this.editor = A +} +baidu.inherits(ItemBase, baidu.BaseClass, "biadu.editor.toolbar.ItemBase"); +baidu.editor.toolbar.ItemBase = ItemBase; +baidu.editor.toolbar.Bold = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "Bold"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.Bold, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.Bold"); +baidu.editor.toolbar.Bold.prototype.initialize = function () { + var B = this; + var A = B.editor; + var C = false; + this.button.addEventListener("onconfirm", function () { + A.bold() + }); + A.addEventListener("onselectionchange", function (E) { + var D = A.queryContextState("bold"); + switch (D) { + case 0: + C = false; + break; + case 1: + C = true; + break; + case 2: + C = false; + break; + case 3: + C = true; + break + } + }); + A.addEventListener("onbeforeselectionchange", function (D) { + A.tools.bold.enable() + }); + A.addEventListener("onafterselectionchange", function (D) { + if (C) { + B.button.highlight() + } else { + B.button.removeHighlight() + } + }) +}; +baidu.editor.toolbar.Italic = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "Italic"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.Italic, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.Italic"); +baidu.editor.toolbar.Italic.prototype.initialize = function () { + var B = this; + var A = B.editor; + var C = false; + this.button.addEventListener("onconfirm", function () { + A.italic() + }); + A.addEventListener("onselectionchange", function (E) { + var D = A.queryContextState("italic"); + switch (D) { + case 0: + C = false; + break; + case 1: + C = true; + break; + case 2: + C = false; + break; + case 3: + C = true; + break + } + }); + A.addEventListener("onbeforeselectionchange", function (D) { + A.tools.italic.enable() + }); + A.addEventListener("onafterselectionchange", function (D) { + if (C) { + B.button.highlight() + } else { + B.button.removeHighlight() + } + }) +}; +baidu.editor.toolbar.Underline = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "Underline"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.Underline, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.Underline"); +baidu.editor.toolbar.Underline.prototype.initialize = function () { + var A = this; + this.button.addEventListener("onconfirm", function () { + A.editor.underline() + }); + A.editor.addEventListener("onselectionchange", function (B) { + var C = A.editor.queryContextState("underline"); + if (C == 1 || C == 3) { + isHightlight = true + } else { + isHightlight = false + } + }); + A.editor.addEventListener("onafterselectionchange", function (B) { + if (isHightlight) { + A.button.highlight() + } else { + A.button.removeHighlight() + } + }) +}; +baidu.editor.toolbar.Undo = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "Undo"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.Undo, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.Undo"); +baidu.editor.toolbar.Undo.prototype.initialize = function () { + var B = this; + var A = B.editor; + this.button.addEventListener("onconfirm", function () { + A.undo() + }); + A.addEventListener("onselectionchange", function (C) { + if (A.queryCommandState("Undo")) { + A.tools.undo.enable() + } else { + A.tools.undo.disable() + } + }) +}; +baidu.editor.toolbar.Redo = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "Redo"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.Redo, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.Redo"); +baidu.editor.toolbar.Redo.prototype.initialize = function () { + var B = this; + var A = B.editor; + this.button.addEventListener("onconfirm", function () { + A.redo() + }); + A.addEventListener("onselectionchange", function (C) { + if (A.queryCommandState("Redo")) { + A.tools.redo.enable() + } else { + A.tools.redo.disable() + } + }) +}; +baidu.editor.toolbar.JustifyLeft = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "JustifyLeft"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.JustifyLeft, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.JustifyLeft"); +baidu.editor.toolbar.JustifyLeft.prototype.initialize = function () { + var A = this; + this.button.addEventListener("onconfirm", function () { + A.editor.justifyLeft() + }); + A.editor.addEventListener("onselectionchange", function (B) { + A.editor.document.queryCommandState("JustifyLeft") ? A.button.highlight() : A.button.removeHighlight() + }) +}; +baidu.editor.toolbar.JustifyCenter = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "JustifyCenter"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.JustifyCenter, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.JustifyCenter"); +baidu.editor.toolbar.JustifyCenter.prototype.initialize = function () { + var A = this; + this.button.addEventListener("onconfirm", function () { + A.editor.justifyCenter() + }); + A.editor.addEventListener("onselectionchange", function (B) { + A.editor.queryCommandState("JustifyCenter") ? A.button.highlight() : A.button.removeHighlight() + }) +}; +baidu.editor.toolbar.JustifyRight = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "JustifyRight"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.JustifyRight, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.JustifyRight"); +baidu.editor.toolbar.JustifyRight.prototype.initialize = function () { + var A = this; + this.button.addEventListener("onconfirm", function () { + A.editor.justifyRight() + }); + A.editor.addEventListener("onselectionchange", function (B) { + A.editor.queryCommandState("JustifyRight") ? A.button.highlight() : A.button.removeHighlight() + }) +}; +baidu.editor.toolbar.FontName = function (A, B) { + baidu.editor.toolbar.ItemBase.call(this, A); + this.name = "FontName"; + this.combo = B +}; +baidu.inherits(baidu.editor.toolbar.FontName, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.FontName"); +baidu.editor.toolbar.FontName.prototype.initialize = function () { + var A = this; + this.combo.addEventListener("onchange", function () { + var B = A.combo.getValue(); + A.editor.fontname(B) + }); + A.editor.addEventListener("onselectionchange", function (C) { + var B = A.editor.queryFontname(); + A.combo.setValue(B) + }) +}; +baidu.editor.toolbar.FontSize = function (A, B) { + baidu.editor.toolbar.ItemBase.call(this, A); + this.name = "FontSize"; + this.combo = B +}; +baidu.inherits(baidu.editor.toolbar.FontSize, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.FontSize"); +baidu.editor.toolbar.FontSize.prototype.initialize = function () { + var A = this; + this.combo.addEventListener("onchange", function () { + var B = A.combo.getValue(); + A.editor.fontsize(B) + }); + A.editor.addEventListener("onselectionchange", function (B) { + var C = A.editor.queryFontsize(); + A.combo.setValue(C) + }) +}; +baidu.editor.toolbar.ForeColor = function (A, B) { + baidu.editor.toolbar.ItemBase.call(this, A); + this.name = "ForeColor"; + this.combo = B +}; +baidu.inherits(baidu.editor.toolbar.ForeColor, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.ForeColor"); +baidu.editor.toolbar.ForeColor.prototype.initialize = function () { + var A = this; + A.combo.addEventListener("onchange", function () { + A.editor.foreColor(A.combo.getValue()) + }); + A.editor.addEventListener("onselectionchange", function (C) { + var B = A.editor.queryForeColor("color"); + A.combo.setValue(B ? B.toUpperCase() : "") + }) +}; +baidu.editor.toolbar.Image = function (B, A) { + baidu.editor.toolbar.ItemBase.call(this, B); + this.name = "Image"; + this.button = A +}; +baidu.inherits(baidu.editor.toolbar.Image, baidu.editor.toolbar.ItemBase, "baidu.editor.toolbar.Image"); +baidu.editor.toolbar.Image.prototype.initialize = function () { + var B = this; + var A = B.editor; + var C = false; + this.button.addEventListener("onconfirm", function () { + var G = this; + var E = null; + if (A.queryContextState("image")) { + E = A.getImage() + } + if (!E) { + var H = A.maxPicNum || 10; + var I = A.document.getElementsByTagName("img"); + if (I && I.length >= H) { + var D; + if (H == 10) { + D = Fe.Dialog.alert("对不起,图片总数限制为" + H + "张:( !", {title: "提示", locked: true}) + } else { + D = Fe.Dialog.alert("对不起,图片总数限制为" + H + "张:( !", {title: "提示", locked: true}) + } + D.onopen = function () { + document.body.focus() + }; + D.onclose = function () { + A.focus() + }; + return + } + } + var F; + if (E) { + F = E.src + } + G.dialog = Fe.Dialog.open("../common/uploadRichTextImage.action" + (E != null ? "#imgUrlValue=" + encodeURIComponent(F) : ""), { + title: "添加或修改图片", + width: "380px", + height: "125px", + buttonbar: true, + buttonAccept: true, + buttonCancel: true, + locked: true, + contentType: "HTMLUrl" + }); + G.dialog.afterUpload = function (J) { + A.insertImage(J); + G.dialog.close(); + B.uploadNum++ + }; + G.dialog.onaccept = function (K) { + var J = G.dialog.window, J = G.dialog.window = (!J) ? G.dialog.getIframe().contentWindow : J, L = J.document; + J.startUpload(G); + K.returnValue = false + }; + G.dialog.onclose = function () { + A.focus() + } + }); + A.addEventListener("onselectionchange", function (E) { + var D = A.queryContextState("image"); + switch (D) { + case 0: + C = false; + break; + case 1: + C = true; + break; + case 2: + C = false; + break; + case 3: + C = true; + break + } + }); + A.addEventListener("onbeforeselectionchange", function (D) { + A.tools.image.enable() + }); + A.addEventListener("onafterselectionchange", function (D) { + if (C) { + B.button.highlight() + } else { + B.button.removeHighlight() + } + }) +}; +(function () { + baidu.editor.Editor.prototype.getFilter = function () { + var C = this; + if (!C._filter) { + var B = C._filter = new (function () { + var E = {}, F; + this.add = function (H, G) { + G = G || "key_" + (new Date()).getTime(); + E[G] = H + }; + this.remove = function (G) { + delete E[G] + }; + var D = this.builder = new A(C); + this.filter = function (H) { + D._process(H); + for (var G in E) { + E[G](H) + } + }; + updateTagCount = function (G) { + F = C.document.getElementsByTagName("*").length + }; + C.addEventListener("onafterexeccommand", updateTagCount); + C.addEventListener("onwysiwygready", updateTagCount); + C.addEventListener("onselectionchange", function (K) { + var G = C.document.getElementsByTagName("*").length, J, I, H; + if (baidu.ie) { + J = C.document.selection.createRange() + } else { + J = C.window.getSelection().getRangeAt(0) + } + if (G == F) { + return + } else { + if (G <= F * 0.8 || G >= F * 1.2) { + F = G; + I = C.document.body + } else { + F = G; + if (!baidu.ie) { + I = baidu.dom.getCommonAncestor(J.startContainer, J.endContainer) + } else { + H = C.document.selection; + if (H.type.toUpperCase() != "CONTROL") { + I = J.parentElement(); + if (baidu.dom.getDocument(I) != C.document) { + I = C.document.body + } + } else { + I = C.document.body + } + } + } + } + B.filter(I) + }) + })() + } + return C._filter + }; + var A = function (E) { + var D = {}; + var B = {}; + var C = []; + var G = function () { + this.attribute = {}; + this.allow = {}; + this.except = {}; + this.text = false; + this.html = false; + this.delegates = [] + }; + var F = false; + this.element = function (J) { + F = true; + C = []; + var I = J.split(","); + for (var H = 0; H < I.length; H++) { + I[H] = I[H].replace(/(^\s+|\s+$)/ig, "").toLowerCase(); + C.push(I[H]); + if (!D[I[H]]) { + D[I[H]] = new G() + } + } + return this + }; + this.allow = function (K) { + var J = K.split(","); + for (var I = 0; I < J.length; I++) { + J[I] = J[I].replace(/(^\s+|\s+$)/ig, "").toLowerCase(); + for (var H = 0; H < C.length; H++) { + D[C[H]].allow[J[I]] = true + } + } + return this + }; + this.except = function (K) { + var J = K.split(","); + for (var I = 0; I < J.length; I++) { + J[I] = J[I].replace(/(^\s+|\s+$)/ig, "").toLowerCase(); + for (var H = 0; H < C.length; H++) { + D[C[H]].except[J[I]] = true + } + } + return this + }; + this.attribute = function (K) { + var H = K.split(","); + for (var J = 0; J < H.length; J++) { + H[J] = H[J].replace(/(^\s+|\s+$)/ig, "").toLowerCase(); + for (var I = 0; I < C.length; I++) { + D[C[I]].attribute[H[J]] = true + } + } + return this + }; + this.text = function () { + for (var H = 0; H < C.length; H++) { + D[C[H]].text = true + } + return this + }; + this.html = function () { + for (var H = 0; H < C.length; H++) { + D[C[H]].html = true + } + return this + }; + this.delegate = function (I) { + for (var H = 0; H < C.length; H++) { + D[C[H]].delegates.push(I) + } + return this + }; + this.eliminate = function (J) { + F = true; + C = []; + var I = J.split(","); + for (var H = 0; H < I.length; H++) { + I[H] = I[H].replace(/(^\s+|\s+$)/ig, "").toLowerCase(); + if (!B[I[H]]) { + B[I[H]] = true + } + } + return this + }; + this._process = function (M) { + if (!F) { + return + } + var L = M.tagName ? D[M.tagName.toLowerCase()] : null; + while (!L && M.parentNode && M != E.document.body) { + M = M.parentNode; + L = M.tagName ? D[M.tagName.toLowerCase()] : null + } + L = M.tagName ? D[M.tagName.toLowerCase()] : null; + if (!L) { + return + } + var P = L.delegates.length; + for (var N = 0; N < P; N++) { + L.delegates[N](M) + } + var K = M.attributes; + for (var N = K.length - 1; N >= 0; N--) { + var J = K[N]; + if (!L.attribute[J.name.toLowerCase()]) { + M.removeAttribute(J.name) + } + } + if (M.className && !L.attribute["class"]) { + M.className = "" + } + var I = M.lastChild; + while (I) { + var Q = I.previousSibling; + switch (I.nodeType) { + case 1: + var H = I.tagName.toLowerCase(); + if (((L.html && D[H]) || L.allow[H]) && !L.except[H] && !B[H]) { + arguments.callee(I) + } else { + if (L.text && !B[H]) { + var O = I.innerHTML; + for (key in B) { + O = O.replace(new RegExp("<" + key + "[\\s\\S]*?>[\\s\\S]*?", "ig"), "") + } + O = O.replace(/<[\s\S]*?>/ig, "").replace(/ /g, " ").replace(/"/g, '"').replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&"); + M.insertBefore(E.document.createTextNode(O), I); + M.removeChild(I) + } else { + M.removeChild(I) + } + } + break; + case 3: + if (!L.text) { + M.removeChild(I) + } + break + } + I = Q + } + } + } +})(); +baidu.editor.register(function (A) { + A.getFilter().builder.element("body").attribute("contentEditable,style").html().text().element("span").attribute("style").html().text().element("pre").attribute("style").html().text().element("center").attribute("style").html().text().element("ul").attribute("style").html().text().element("ol").attribute("style").html().text().element("li").attribute("style").html().text().element("a").attribute("style, href, target").html().text().element("br").element("div").attribute("style, align").html().text().element("h1, h2, h3, h4, h5, h6").attribute("style, align").html().text().element("table").html("tbody, thead, tfoot, tr").attribute("style, cellpadding, cellspacing, border, align").element("tbody").html("thead, tfoot, tr").attribute("style").element("thead, tfoot").html("tr").attribute("style").element("tr").html("th", "td").attribute("style").element("th, td").attribute("style, colspan, rowspan, align").html().text().element("b,strong").attribute("style").html().text().element("i,em").attribute("style").html().text().element("u").attribute("style").html().text().element("font").attribute("face, size, color, style").html().text().element("p").attribute("style,align").html().text().element("img").attribute("src, style, width, height").eliminate("script, style, object, embed, applet, select, input, textarea") +}); +function ce(A) { + var B = document.createElement(A); + B.style.MozUserSelect = "none"; + B.unselectable = "on"; + return B +} +function stopEvent(A) { + if (A) { + A.cancelBubble = true; + if (A.stopPropagation) { + A.stopPropagation() + } + } +} +function preventDefault(A) { + A.returnValue = false; + if (A.preventDefault) { + A.preventDefault() + } +} +function Toolbar(B) { + var A = this; + A.id = B; + A.dom = baidu.G(B); + A.create() +} +baidu.extend(Toolbar.prototype, { + create: function () { + this.dom.style.MozUserSelect = "none"; + this.dom.unselectable = "on" + }, addButton: function (A) { + if (A && A.getDomObj) { + this.dom.appendChild(A.getDomObj()) + } + }, addBar: function () { + var B = ce("div"); + var A = ce("span"); + baidu.addClass(A, "btn_bar"); + B.appendChild(A); + A.style.MozUserSelect = "none"; + A.unselectable = "on"; + B.style.MozUserSelect = "none"; + B.unselectable = "on"; + this.dom.appendChild(B) + } +}); +Button.config = { + hover: "btn_hover", + active: "btn_active", + disabled: "btn_disabled", + highlight: "btn_highlight", + defaultClassName: "", + textButton: "btn_text btn_default", + idPrefix: "toolbar-button-" +}; +var buttonCounter = 0; +function Button(A) { + var B = this; + buttonCounter++; + baidu.BaseClass.call(B); + A = A || {}; + B.id = A.id || Button.config.idPrefix + buttonCounter; + B.className = A.className || Button.config.defaultClassName; + B._onclick = A.onclick; + B.label = A.label; + B.title = A.title; + B.button = null; + B.inner = null; + B.isDisabled = false; + B.isHighlight = false; + B._createWraper() +} +baidu.inherits(Button, baidu.BaseClass, "Button"); +baidu.extend(Button.prototype, { + _createWraper: function () { + var D = this; + var C = D.button = ce("div"); + C.id = D.id; + if (D.label) { + baidu.addClass(C, Button.config.textButton) + } + var B = ce("div"); + var A = D.inner = ce("p"); + C.appendChild(B); + B.appendChild(A); + B.title = D.title; + C.style.MozUserSelect = "none"; + B.style.MozUserSelect = "none"; + A.style.MozUserSelect = "none"; + C.unselectable = "on"; + B.unselectable = "on"; + A.unselectable = "on"; + D.createInner(); + D.registerHandlers(); + return D + }, createInner: function () { + var B = this; + var A = ce("span"); + baidu.addClass(A, B.className); + A.style.MozUserSelect = "none"; + A.unselectable = "on"; + B.addContent(A); + if (B.label) { + A.innerHTML = B.label + } + }, addContent: function (A) { + this.inner.appendChild(A) + }, registerHandlers: function () { + var B = this; + var A = B.button; + baidu.on(A, "mouseover", function (C) { + if (B.isDisabled) { + return + } + baidu.addClass(A, Button.config.hover) + }); + baidu.on(A, "mouseout", function (C) { + if (B.isDisabled) { + return + } + baidu.removeClass(A, Button.config.hover); + baidu.removeClass(A, Button.config.active) + }); + baidu.on(A, "mousedown", function (C) { + if (B.isDisabled) { + return + } + baidu.addClass(A, Button.config.active) + }); + baidu.on(A, "mouseup", function (C) { + if (B.isDisabled) { + return + } + baidu.removeClass(A, Button.config.active) + }); + baidu.on(A, "click", function (C) { + if (B.isDisabled) { + return + } + if (B._onclick && typeof B._onclick == "function") { + B._onclick() + } else { + B.confirm() + } + }) + }, getDomObj: function () { + return this.button + }, highlight: function () { + this.isHighlight = true; + baidu.addClass(this.button, Button.config.highlight) + }, disable: function () { + this.isDisabled = true; + baidu.removeClass(this.button, Button.config.highlight); + baidu.removeClass(this.button, Button.config.hover); + baidu.addClass(this.button, Button.config.disabled) + }, removeHighlight: function () { + this.isHighlight = false; + baidu.removeClass(this.button, Button.config.highlight) + }, enable: function () { + this.isDisabled = false; + baidu.removeClass(this.button, Button.config.disabled) + }, confirm: function () { + this.dispatchEvent(new baidu.BaseEvent("onconfirm")) + } +}); +Select.config = { + select: "editor-toolbar-select", + caption: "editor-toolbar-select-caption", + dropdown: "editor-toolbar-select-dropdown", + inline: "editor-toolbar-select-inline" +}; +var selectListCounter = 0; +baidu.extend(Select.config, Button.config); +function Select(A) { + var B = this; + A = A || {}; + B.caption = A.caption || "SELECT"; + B.options = A; + if (A.list) { + B.list = A.list + } else { + if (A.items) { + B.list = new List({ + id: (B.id ? "editor-select-list" + B.id : "editor-select-list" + selectListCounter++), + items: A.items, + listClassName: A.listClassName, + itemClassName: A.itemClassName + }) + } else { + return false + } + } + B.className = A.className; + B._onchange = A.onchange; + Button.call(B, A) +} +baidu.inherits(Select, Button, "Select"); +baidu.extend(Select.prototype, { + createInner: function () { + var B = this; + baidu.addClass(B.button, Select.config.select); + if (B.className) { + baidu.addClass(B.button, B.className) + } + var A = B.oCaption = ce("div"); + baidu.addClass(A, Select.config.inline); + baidu.addClass(A, Select.config.caption); + A.innerHTML = B.caption; + var C = ce("div"); + baidu.addClass(C, Select.config.inline); + baidu.addClass(C, Select.config.dropdown); + C.innerHTML = " "; + A.unselectable = "on"; + C.unselectable = "on"; + A.MozUserSelect = "none"; + C.MozUserSelect = "none"; + B.addContent(A); + B.addContent(C); + B._registerHanlders() + }, _registerHanlders: function () { + var A = this; + baidu.on(A.button, "mousedown", function (B) { + if (A.isDisabled) { + return + } + var C = baidu.getPosition(A.button); + A.list.setPosition({left: C.left, top: (C.top + A.button.offsetHeight)}); + A.list.toggle(); + stopEvent(B) + }); + baidu.on(A.button, "mouseup", function (B) { + if (A.isDisabled) { + return + } + stopEvent(B) + }); + A.list._onclick = function () { + A.list.hide(); + var B = A.list.getValue(); + A._setCaption(B) + }; + A.list.addEventListener("onchange", function () { + A.dispatchEvent(new baidu.BaseEvent("onchange")) + }) + }, _setCaption: function (B) { + var A = this; + if (!B) { + return false + } + if (A.options._setCaption) { + A.options._setCaption(A.oCaption, B); + return false + } + if (baidu.ie) { + this.oCaption.innerText = B ? B : this.caption + } else { + this.oCaption.innerHTML = B ? B : this.caption + } + }, setValue: function (B, C) { + var A = this; + A.list.setValue(B, C); + A._setCaption(B) + }, getValue: function () { + return this.list.getValue() + } +}); +List.config = { + wraper: "editor-toolbar-list", + outer: "editor-toolbar-list-item", + hover: "editor-toolbar-list-item-hover", + selected: "editor-toolbar-list-item-selected", + idPrefix: "editor-toolbar-list-" +}; +List.lists = []; +List.hideAll = function () { + for (var B = 0; B < List.lists.length; B++) { + var A = List.lists[B]; + if (A.isShow) { + A.hide() + } + } +}; +var listCounter = 0; +function List(A) { + var B = this; + baidu.BaseClass.call(B); + listCounter++; + A = A || {}; + B.items = A.items || []; + B.listClassName = A.listClassName; + B.itemClassName = A.itemClassName; + B.id = A.id || List.config.idPrefix + listCounter; + B._onclick = A.onclick; + B.list = null; + B._items = []; + B.isShow = false; + B.selectedIndex; + B._createDom(); + List.lists.push(this) +} +baidu.inherits(List, baidu.BaseClass, "List"); +baidu.extend(List.prototype, { + _createDom: function () { + var D = this; + var E = D.list = ce("div"); + baidu.addClass(E, List.config.wraper); + baidu.setStyle(E, "position", "absolute"); + baidu.setStyle(E, "background", "#FFF"); + E.id = D.id; + if (D.listClassName && typeof D.listClassName == "string") { + baidu.addClass(E, D.listClassName) + } + for (var C = 0, A = D.items.length; C < A; C++) { + var B = ce("div"); + baidu.addClass(B, List.config.outer); + if (D.itemClassName && typeof D.itemClassName == "string") { + baidu.addClass(B, D.itemClassName) + } + B.innerHTML = D.items[C].content; + B.value = D.items[C].value; + D._items.push({value: D.items[C].value, dom: B}); + B.style.MozUserSelect = "none"; + B.unselectable = "on"; + E.appendChild(B); + D._registerItemHandlers(C) + } + D._registerHandlers(); + D.hide(); + setTimeout(function () { + document.body.appendChild(E) + }, 1) + }, _registerItemHandlers: function (A) { + var C = this; + var B = C._items[A]; + baidu.on(B.dom, "mouseover", function (D) { + baidu.addClass(B.dom, List.config.hover) + }); + baidu.on(B.dom, "mouseout", function (D) { + baidu.removeClass(B.dom, List.config.hover) + }); + baidu.on(B.dom, "click", function (D) { + C._setItemSelected(A, true); + if (C._onclick && typeof C._onclick == "function") { + C._onclick() + } else { + C.confirm() + } + stopEvent(D) + }) + }, _registerHandlers: function () { + var A = this; + baidu.on(document, "mousedown", function (B) { + A.hide() + }); + baidu.on(document, "mouseup", function (B) { + A.hide() + }); + baidu.on(A.list, "mousedown", function (B) { + stopEvent(B) + }); + baidu.on(A.list, "mouseup", function (B) { + stopEvent(B) + }) + }, show: function () { + List.hideAll(); + this.list.style.display = ""; + this.isShow = true + }, hide: function () { + this.list.style.display = "none"; + this.isShow = false + }, toggle: function () { + if (this.isShow) { + this.hide() + } else { + this.show() + } + }, setPosition: function (A) { + this.list.style.left = typeof A.left == "number" ? A.left + "px" : A.left; + this.list.style.top = typeof A.top == "number" ? A.top + "px" : A.top + }, _setItemSelected: function (B, D) { + var C = this; + var A = B != C.selectedIndex; + if (C.selectedIndex != undefined) { + baidu.removeClass(C._items[C.selectedIndex].dom, List.config.selected) + } + if (B != undefined && B >= 0 && B < C._items.length) { + baidu.addClass(C._items[B].dom, List.config.selected); + C.selectedIndex = B + } else { + C.selectedIndex = undefined + } + if (A && D) { + C.dispatchEvent(new baidu.BaseEvent("onchange")) + } + }, setValue: function (F, G) { + var E = this; + var B = E._items; + var C; + for (var D = 0, A = B.length; D < A; D++) { + if (F == B[D].value) { + C = D; + break + } + } + E._setItemSelected(C, G) + }, getValue: function () { + var A = this; + if (A.selectedIndex != undefined) { + return A._items[A.selectedIndex].value + } else { + return null + } + }, confirm: function () { + this.dispatchEvent(new baidu.BaseEvent("onconfirm")) + } +}); +Menu.config = {menu: "toolbar-menu", idPrefix: "menu-"}; +var menuCounter = 0; +Menu.menus = []; +function Menu(A) { + var B = this; + baidu.BaseClass.call(B); + menuCounter++; + A = A || {}; + B.id = A.id || Menu.config.idPrefix + menuCounter; + B.menu = null; + B._menuitems = []; + B.isShow = false; + B._createDom(); + Menu.menus.push(this) +} +baidu.inherits(Menu, baidu.BaseClass, "Menu"); +baidu.extend(Menu.prototype, { + _createDom: function () { + var A = this; + var B = A.menu = ce("div"); + baidu.addClass(B, Menu.config.menu); + B.id = A.id; + A.hide(); + document.body.appendChild(B); + A._registerHandlers() + }, _registerHandlers: function () { + var A = this; + baidu.on(document, "mousedown", function (B) { + A.hide() + }); + baidu.on(document, "mouseup", function (B) { + A.hide() + }); + baidu.on(A.menu, "mousedown", function (B) { + stopEvent(B) + }); + baidu.on(A.menu, "mouseup", function (B) { + stopEvent(B) + }) + }, show: function () { + this.menu.style.display = ""; + this.isShow = true + }, hide: function () { + this.menu.style.display = "none"; + this.isShow = false + }, toggle: function () { + if (this.menu.style.display == "") { + this.hide() + } else { + this.show() + } + }, setPosition: function (A) { + this.menu.style.left = typeof A.left == "number" ? A.left + "px" : A.left; + this.menu.style.top = typeof A.top == "number" ? A.top + "px" : A.top + }, addMenuitem: function (B) { + if (!B || !B.getDom || !B.getDom()) { + return + } + var A = this; + A.menu.appendChild(B.getDom()); + B.addEventListener("onclick", function () { + A.hide() + }) + } +}); +MenuItem.config = { + menuitem: "menuitem", + hover: "menuitem-hover", + disabled: "menuitem-disabled", + idPrefix: "toolbar-menuitem-" +}; +var menuitemCounter = 0; +function MenuItem(A) { + var B = this; + menuitemCounter++; + A = A || {}; + B.label = A.label || "Menu Item "; + B.className = A.className; + B._onclick = A.onclick; + B.id = A.id || MenuItem.config.idPrefix + menuitemCounter; + B.button = null; + B.isDisabled = false; + baidu.BaseClass.call(B); + B._createDom() +} +baidu.inherits(MenuItem, baidu.BaseClass, "MenuItem"); +baidu.extend(MenuItem.prototype, { + _createDom: function () { + var B = this; + var A = B.button = ce("div"); + baidu.addClass(A, MenuItem.config.menuitem); + A.id = B.id; + if (B.className) { + baidu.addClass(A, B.className) + } + var C = document.createTextNode(B.label); + A.appendChild(C); + B._registerHandlers() + }, _registerHandlers: function () { + var B = this; + var A = B.button; + baidu.on(A, "mouseover", function (D) { + if (B.isDisabled) { + return + } + if (B.id == "insertTable") { + var D = D || window.event; + var G = D.target || D.srcElement; + baidu.addClass(A, "menuitem-arrow"); + setTablePanel.showTablePanel(); + var F = parseInt(G.parentNode.style.left); + var E = parseInt(G.parentNode.style.top); + var C = baidu.G("bdMenuInsertTable"); + C.style.left = F + G.offsetWidth + "px"; + C.style.top = E + "px" + } else { + baidu.addClass(A, MenuItem.config.hover) + } + }); + baidu.on(A, "mouseout", function () { + if (B.id == "insertTable") { + baidu.removeClass(A, "menuitem-arrow"); + setTablePanel.hiddenTablePanel() + } + baidu.removeClass(A, MenuItem.config.hover) + }); + baidu.on(A, "click", function () { + if (B.isDisabled) { + return + } + B.clicked(); + if (B._onclick && typeof B._onclick == "function") { + B._onclick() + } else { + B.confirm() + } + }) + }, getDom: function () { + return this.button + }, disable: function () { + var B = this; + var A = B.button; + this.isDisabled = true; + if (B.id == "insertTable") { + baidu.removeClass(A, "menuitem-arrow") + } + baidu.addClass(this.button, MenuItem.config.disabled) + }, enable: function () { + this.isDisabled = false; + baidu.removeClass(this.button, MenuItem.config.disabled) + }, confirm: function () { + this.dispatchEvent(new baidu.BaseEvent("onconfirm")) + }, clicked: function () { + this.dispatchEvent(new baidu.BaseEvent("onclick")) + } +}); +baidu.isElement = function (A) { + return A && A.nodeType == 1 +}; +baidu.isFirefox = /Firefox(\s|\/)(\d+(\.\d+)?)/.test(navigator.userAgent) ? RegExp.$2 : 0; +baidu.isIE = /MSIE (\d+(\.\d+)?)/.test(navigator.userAgent) ? RegExp.$1 : 0; +baidu.isWebkit = (navigator.userAgent.indexOf("KHTML") > -1 && /AppleWebKit\/([^\s]*)/.test(navigator.userAgent)) ? RegExp.$1 : 0; +baidu.isOpera = (window.opera && /Opera(\s|\/)(\d+(\.\d+)?)/.test(navigator.userAgent)) ? RegExp.$2 : 0; +baidu.isSafari = (navigator.userAgent.indexOf("Safari") > -1 && /Version\/(\d+(\.\d+)?)/.test(navigator.userAgent)) ? RegExp.$1 : 0; +baidu.isGecko = (navigator.userAgent.indexOf("Gecko") > -1 && navigator.userAgent.indexOf("KHTML") == -1 && /rv\:(\d+(\.\d+)?)/.test(navigator.userAgent)) ? RegExp.$1 : 0; +baidu.isStrict = (document.compatMode == "CSS1Compat"); +baidu.css = function (C, G) { + if (!C || !G) { + return null + } + C = typeof C == "string" ? document.getElementById(C) : C; + var B = !window.opera && navigator.userAgent.indexOf("MSIE") != -1; + if (G == "float") { + G = B ? "styleFloat" : "cssFloat" + } + G = G.replace(/(-[a-z])/gi, function (H, I) { + return I.charAt(1).toUpperCase() + }); + if ("opacity" == G && B) { + var A = C.style.filter; + return A && A.indexOf("opacity=") >= 0 ? (parseFloat(A.match(/opacity=([^)]*)/)[1]) / 100) + "" : "1" + } + var F = null; + if (F = C.style[G]) { + return F + } + if (C.currentStyle) { + return C.currentStyle[G] + } else { + var E = C.nodeType == 9 ? C : C.ownerDocument || C.document; + if (E.defaultView && E.defaultView.getComputedStyle) { + var D = E.defaultView.getComputedStyle(C, ""); + if (D) { + return D[G] + } + } + } + return null +}; +baidu.dom.getStyle = function (B, A) { + return baidu.css(B, A) +}; +baidu.dom.getPosition = function (D) { + D = baidu.G(D); + if (!baidu.isElement(D)) { + throw new Error("[baidu.dom.getPosition] param must be Element") + } + var G = baidu.dom.getDocument(D); + var F = baidu.isGecko > 0 && G.getBoxObjectFor && baidu.dom.getStyle(D, "position") == "absolute" && (D.style.top === "" || D.style.left === ""); + var H = {left: 0, top: 0}; + var B = (baidu.isIE && !baidu.isStrict) ? G.body : G.documentElement; + if (D == B) { + return H + } + var C = null; + var E; + if (D.getBoundingClientRect) { + E = D.getBoundingClientRect(); + H.left = E.left + Math.max(G.documentElement.scrollLeft, G.body.scrollLeft); + H.top = E.top + Math.max(G.documentElement.scrollTop, G.body.scrollTop); + H.left -= G.documentElement.clientLeft; + H.top -= G.documentElement.clientTop; + if (baidu.isIE && !baidu.isStrict) { + H.left -= 2; + H.top -= 2 + } + } else { + if (G.getBoxObjectFor && !F) { + E = G.getBoxObjectFor(D); + var A = G.getBoxObjectFor(B); + H.left = E.screenX - A.screenX; + H.top = E.screenY - A.screenY + } else { + C = D; + do { + H.left += C.offsetLeft; + H.top += C.offsetTop; + if (baidu.isWebkit > 0 && baidu.dom.getStyle(C, "position") == "fixed") { + H.left += G.body.scrollLeft; + H.top += G.body.scrollTop; + break + } + C = C.offsetParent + } while (C && C != D); + if (baidu.isOpera > 0 || (baidu.isWebkit > 0 && baidu.dom.getStyle(D, "position") == "absolute")) { + H.top -= G.body.offsetTop + } + C = D.offsetParent; + while (C && C != G.body) { + H.left -= C.scrollLeft; + if (!baidu.isOpera || C.tagName != "TR") { + H.top -= C.scrollTop + } + C = C.offsetParent + } + } + } + return H +}; +MenuButton.config = { + label: "toolbar-menu-button-label", + dropdown: "toolbar-menu-button-dropdown", + menubutton: "toolbar-menu-button" +}; +baidu.extend(MenuButton.config, Button.config); +function MenuButton(A) { + var B = this; + A = A || {}; + B.label = A.label || "MenuButton"; + B.items = []; + B.menu = new Menu(); + Button.call(B, A) +} +baidu.inherits(MenuButton, Button, "MenuButton"); +baidu.extend(MenuButton.prototype, { + createInner: function () { + var B = this; + baidu.addClass(B.button, MenuButton.config.textButton); + var A = ce("span"); + baidu.addClass(A, B.className); + A.innerHTML = B.label; + A.unselectable = "on"; + A.MozUserSelect = "none"; + B.addContent(A); + B._registerHandlers() + }, _registerHandlers: function () { + var A = this; + baidu.on(A.button, "mousedown", function (B) { + if (A.isDisabled) { + return + } + var C = baidu.dom.getPosition(A.button); + A.menu.setPosition({left: C.left, top: (C.top + A.button.offsetHeight)}); + A.menu.toggle(); + window.focus(); + stopEvent(B) + }); + baidu.on(A.button, "mouseup", function (B) { + if (A.isDisabled) { + return + } + stopEvent(B) + }) + }, addMenuitem: function (A) { + this.menu.addMenuitem(A) + } +}); +var EditorTools = function (F) { + this.undo; + this.redo; + this.bold; + this.italic; + this.image; + var E = new Toolbar(F); + this.undo = new Button({className: "btn_undo", title: "撤销"}); + E.addButton(this.undo); + this.redo = new Button({className: "btn_redo", title: "重做"}); + E.addButton(this.redo); + E.addBar(); + this.bold = new Button({className: "btn_bold", title: "加粗"}); + E.addButton(this.bold); + this.italic = new Button({className: "btn_italic", title: "斜体"}); + E.addButton(this.italic); + this.underline = new Button({className: "btn_underline", title: "下划线"}); + E.addButton(this.underline); + var L = [["黑色", "black", "000000"], ["红色", "red", "FF0000"], ["蓝色", "blue", "0000FF"], ["绿色", "green", "008000"], ["紫色", "purple", "800080"], ["黄色", "yellow", "FFFF00"], ["灰色", "gray", "808080"], ["浅绿色", "aqua", "00FFFF"], ["紫红色", "fuchsia", "FF00FF"], ["褐紫色", "maroon", "800000"], ["藏青色", "navy", "000080"], ["黄褐色", "olive", "808000"], ["银白色", "silver", "C0C0C0"]]; + var B = { + "000000": "黑色", + FF0000: "红色", + "0000FF": "蓝色", + "008000": "绿色", + "800080": "紫色", + FFFF00: "黄色", + "808080": "灰色", + "00FFFF": "浅绿色", + FF00FF: "紫红色", + "800000": "褐紫色", + "000080": "藏青色", + "808000": "黄褐色", + C0C0C0: "银白色" + }; + var A = []; + for (var J in B) { + var K = {}; + K.value = J; + K.content = '' + B[J] + ""; + A.push(K) + } + this.forecolor = new Select({ + caption: "字体颜色", + title: "字体颜色", + className: "editor-toolbar-select-forecolor", + items: A, + listClassName: "editor-toolbar-forecolor-list", + itemClassName: "editor-toolbar-forecolor-item", + _setCaption: function (M, O) { + if (!O) { + return false + } + var O = O.replace("#", ""); + O = O == "000" ? "000000" : O; + var N = B[O]; + N = N || "字体颜色"; + baidu.ie ? M.innerText = N : M.innerHTML = N + } + }); + E.addButton(this.forecolor); + E.addBar(); + this.justifyleft = new Button({className: "btn_justifyleft", title: "居左"}); + E.addButton(this.justifyleft); + this.justifycenter = new Button({className: "btn_justifycenter", title: "居中"}); + E.addButton(this.justifycenter); + this.justifyright = new Button({className: "btn_justifyright", title: "居右"}); + E.addButton(this.justifyright); + var H = ["sans-serif", "宋体", "黑体", "幼圆", "楷体_GB2312", "仿宋_GB2312", "Arial", "Comic Sans MS", "Courier New", "Tahoma", "Times New Roman", "Verdana"]; + var I = []; + for (var C = 0; C < H.length; C++) { + var K = {}; + K.value = H[C]; + K.content = '' + H[C] + ""; + I.push(K) + } + this.fontname = new Select({ + caption: "选择字体", + title: "字体", + className: "editor-toolbar-select-fontfamily", + listClassName: "editor-toolbar-fontname-list", + itemClassName: "editor-toolbar-fontname-item", + items: I + }); + E.addButton(this.fontname); + var D = {"1": "10", "2": "13", "3": "16", "4": "18", "5": "24", "6": "32", "7": "48"}; + var G = []; + for (var J in D) { + var K = {}; + K.value = J; + K.content = '' + D[J] + ""; + G.push(K) + } + this.fontsize = new Select({ + caption: "选择字号", + title: "字号", + className: "editor-toolbar-select-fontsize", + items: G, + listClassName: "editor-toolbar-fontsize-list", + itemClassName: "editor-toolbar-fontsize-item", + _setCaption: function (M, N) { + if (!N) { + return false + } + var O = D[N]; + O = O || "选择字号"; + baidu.ie ? M.innerText = O : M.innerHTML = O + } + }); + E.addButton(this.fontsize); + E.addBar(); + this.image = new Button({className: "btn_image", title: "插入/编辑图片"}); + E.addButton(this.image); + this.buttonDisable() +}; +EditorTools.prototype.buttonEnable = function () { + this.bold.enable(); + this.italic.enable(); + this.image.enable(); + this.underline.enable(); + this.justifyleft.enable(); + this.justifycenter.enable(); + this.justifyright.enable(); + this.fontname.enable(); + this.fontsize.enable(); + this.forecolor.enable() +}; +EditorTools.prototype.buttonDisable = function () { + this.undo.disable(); + this.redo.disable(); + this.bold.disable(); + this.italic.disable(); + this.image.disable(); + this.underline.disable(); + this.justifyleft.disable(); + this.justifycenter.disable(); + this.justifyright.disable(); + this.fontname.disable(); + this.fontsize.disable(); + this.forecolor.disable() +}; +function editorInit(A) { + var B = A.tools; + A.addToolbarItem(new baidu.editor.toolbar.Undo(A, B.undo)); + A.addToolbarItem(new baidu.editor.toolbar.Redo(A, B.redo)); + A.addToolbarItem(new baidu.editor.toolbar.Bold(A, B.bold)); + A.addToolbarItem(new baidu.editor.toolbar.Italic(A, B.italic)); + A.addToolbarItem(new baidu.editor.toolbar.Underline(A, B.underline)); + A.addToolbarItem(new baidu.editor.toolbar.JustifyLeft(A, B.justifyleft)); + A.addToolbarItem(new baidu.editor.toolbar.JustifyCenter(A, B.justifycenter)); + A.addToolbarItem(new baidu.editor.toolbar.JustifyRight(A, B.justifyright)); + A.addToolbarItem(new baidu.editor.toolbar.Image(A, B.image)); + A.addToolbarItem(new baidu.editor.toolbar.FontName(A, B.fontname)); + A.addToolbarItem(new baidu.editor.toolbar.FontSize(A, B.fontsize)); + A.addToolbarItem(new baidu.editor.toolbar.ForeColor(A, B.forecolor)) +} +(function () { + baidu.getPosition = function (C) { + return {left: A(C), top: B(C)} + }; + function A(D) { + var C = 0; + while (D != null) { + C += D.offsetLeft; + D = D.offsetParent + } + return C + } + + function B(D) { + var C = 0; + while (D != null) { + C += D.offsetTop; + D = D.offsetParent + } + return C + } +})(); +(function () { + baidu.getPointer = function (C) { + var B = document.documentElement, A = document.body || {scrollLeft: 0, scrollTop: 0}; + return { + x: C.pageX || (C.clientX + (B.scrollLeft || A.scrollLeft) - (B.clientLeft || 0)), + y: C.pageY || (C.clientY + (B.scrollTop || A.scrollTop) - (B.clientTop || 0)) + } + } +})(); \ No newline at end of file diff --git a/WebContent/stat/js/ui/editor/js/editorPlugin.js b/src/main/webapp/stat/js/ui/editor/js/editorPlugin.js similarity index 61% rename from WebContent/stat/js/ui/editor/js/editorPlugin.js rename to src/main/webapp/stat/js/ui/editor/js/editorPlugin.js index 644afd034..d50cb2d32 100644 --- a/WebContent/stat/js/ui/editor/js/editorPlugin.js +++ b/src/main/webapp/stat/js/ui/editor/js/editorPlugin.js @@ -5,27 +5,27 @@ var esEditor = window.esEditor || {}; * @return {String} 去除html标签等后的字符串 */ esEditor.getEditorText = function (html) { - html = html.replace(/]*>(.*?)<\/embed>/ig,""); - html = html.replace(/]*>(.*?)<\/object>/ig,""); - html = html.replace(/]*>(.*?)<\/applet>/ig,""); - html = html.replace(/]*>(.*?)<\/script>/ig,""); - html = html.replace(/]*>(.*?)<\/style>/ig,""); - html = html.replace(//ig,""); - html = html.replace(//ig,""); - html = html.replace(/\r/g,""); - html = html.replace(/\n/g,""); - html = html.replace(//ig,""); - html = html.replace(/<\/p>/ig,"
    "); - html = html.replace(/
    /ig,""); - html = html.replace(/
    /ig,""); + html = html.replace(/]*>(.*?)<\/embed>/ig, ""); + html = html.replace(/]*>(.*?)<\/object>/ig, ""); + html = html.replace(/]*>(.*?)<\/applet>/ig, ""); + html = html.replace(/]*>(.*?)<\/script>/ig, ""); + html = html.replace(/]*>(.*?)<\/style>/ig, ""); + html = html.replace(//ig, ""); + html = html.replace(//ig, ""); + html = html.replace(/\r/g, ""); + html = html.replace(/\n/g, ""); + html = html.replace(//ig, ""); + html = html.replace(/<\/p>/ig, "
    "); + html = html.replace(/
    /ig, ""); + html = html.replace(/
    /ig, ""); html = html.replace(/<[^<>]*>/gi, ""); - html = html.replace(/>/g,">"); - html = html.replace(/</g,"<"); - html = html.replace(/ /ig," "); - html = html.replace(/&/g,"&"); - html = html.replace(/'/g,"\'"); - html = html.replace(/"/g,"\""); - html = html.replace(/\r\n  /g,""); + html = html.replace(/>/g, ">"); + html = html.replace(/</g, "<"); + html = html.replace(/ /ig, " "); + html = html.replace(/&/g, "&"); + html = html.replace(/'/g, "\'"); + html = html.replace(/"/g, "\""); + html = html.replace(/\r\n  /g, ""); html = baidu.trim(html); return html; }; @@ -55,13 +55,13 @@ esEditor.disableEditor = function (editorSuffix) { baidu.show(shadeDivEl); baidu.setStyles(shadeDivEl, { - "position" : "absolute", - "height" : height, - "width" : width, - "left" : 0, - "top" : 0, - "background" : "#000", - "opacity" : 0.3 + "position": "absolute", + "height": height, + "width": width, + "left": 0, + "top": 0, + "background": "#000", + "opacity": 0.3 }); }; @@ -80,7 +80,7 @@ esEditor.enableEditor = function (editorSuffix) { */ esEditor.getImgNum = function (editor) { var imgNum = 0; - if(!editor) { + if (!editor) { return imgNum; } var imgEls = editor.document.getElementsByTagName("img"); diff --git a/WebContent/stat/js/ui/floater/.svn/all-wcprops b/src/main/webapp/stat/js/ui/floater/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/floater/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/floater/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/floater/.svn/entries b/src/main/webapp/stat/js/ui/floater/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/floater/.svn/entries rename to src/main/webapp/stat/js/ui/floater/.svn/entries diff --git a/WebContent/stat/js/ui/floater/css/.svn/all-wcprops b/src/main/webapp/stat/js/ui/floater/css/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/floater/css/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/floater/css/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/floater/css/.svn/entries b/src/main/webapp/stat/js/ui/floater/css/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/floater/css/.svn/entries rename to src/main/webapp/stat/js/ui/floater/css/.svn/entries diff --git a/WebContent/stat/js/ui/floater/css/.svn/text-base/floater.css.svn-base b/src/main/webapp/stat/js/ui/floater/css/.svn/text-base/floater.css.svn-base similarity index 100% rename from WebContent/stat/js/ui/floater/css/.svn/text-base/floater.css.svn-base rename to src/main/webapp/stat/js/ui/floater/css/.svn/text-base/floater.css.svn-base diff --git a/src/main/webapp/stat/js/ui/floater/css/floater.css b/src/main/webapp/stat/js/ui/floater/css/floater.css new file mode 100644 index 000000000..74ce671c7 --- /dev/null +++ b/src/main/webapp/stat/js/ui/floater/css/floater.css @@ -0,0 +1,93 @@ +.floaterd { + padding-top: 3px; +} + +.floaterd-top { + background: #3B5C55 +} + +.floaterd-bottom { + display: none +} + +.floater { + position: absolute !important; + border-radius: 6px; + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .2); + outline: none; + border: none; +} + +.ec-form.floater { + padding-top: 52px; +} + +.floater-title { + cursor: move; + border-radius: 6px 6px 0 0; + position: absolute; + left: 0; + top: 0; + height: 52px; + padding: 4px 10px 0 18px; + font-size: 18px; + color: #333; + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; + font-weight: bold; + position: absolute +} + +.floater-close { + position: absolute; + right: 18px; + top: 14px; + font-size: 1px; + font-size: 22px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: .2; + cursor: pointer; +} + +.floater-close:after { + content: '×'; +} + +.floater-close:hover { + opacity: .4; +} + +.floater-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + background-color: #fff; + background-clip: padding-box; + border-radius: 0 0 6px 6px; + outline: none; +} + +.floater-inner { + overflow-y: auto; + overflow-x: hidden +} + +.floater-corner { + background: #fff +} + +.div-floater-control { + padding: 15px 20px 2px; + margin-top: 20px; + text-align: right; + border-top: 1px solid #e5e5e5; + margin-left: -19px; + margin-right: -19px; +} \ No newline at end of file diff --git a/WebContent/stat/js/ui/floater/css/img/.svn/all-wcprops b/src/main/webapp/stat/js/ui/floater/css/img/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/floater/css/img/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/floater/css/img/.svn/entries b/src/main/webapp/stat/js/ui/floater/css/img/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/.svn/entries rename to src/main/webapp/stat/js/ui/floater/css/img/.svn/entries diff --git a/WebContent/stat/js/ui/floater/css/img/.svn/prop-base/btn.gif.svn-base b/src/main/webapp/stat/js/ui/floater/css/img/.svn/prop-base/btn.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/.svn/prop-base/btn.gif.svn-base rename to src/main/webapp/stat/js/ui/floater/css/img/.svn/prop-base/btn.gif.svn-base diff --git a/WebContent/stat/js/ui/floater/css/img/.svn/prop-base/close.gif.svn-base b/src/main/webapp/stat/js/ui/floater/css/img/.svn/prop-base/close.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/.svn/prop-base/close.gif.svn-base rename to src/main/webapp/stat/js/ui/floater/css/img/.svn/prop-base/close.gif.svn-base diff --git a/WebContent/stat/js/ui/floater/css/img/.svn/prop-base/global_bg.png.svn-base b/src/main/webapp/stat/js/ui/floater/css/img/.svn/prop-base/global_bg.png.svn-base similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/.svn/prop-base/global_bg.png.svn-base rename to src/main/webapp/stat/js/ui/floater/css/img/.svn/prop-base/global_bg.png.svn-base diff --git a/WebContent/stat/js/ui/floater/css/img/.svn/text-base/btn.gif.svn-base b/src/main/webapp/stat/js/ui/floater/css/img/.svn/text-base/btn.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/.svn/text-base/btn.gif.svn-base rename to src/main/webapp/stat/js/ui/floater/css/img/.svn/text-base/btn.gif.svn-base diff --git a/WebContent/stat/js/ui/floater/css/img/.svn/text-base/close.gif.svn-base b/src/main/webapp/stat/js/ui/floater/css/img/.svn/text-base/close.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/.svn/text-base/close.gif.svn-base rename to src/main/webapp/stat/js/ui/floater/css/img/.svn/text-base/close.gif.svn-base diff --git a/WebContent/stat/js/ui/floater/css/img/.svn/text-base/global_bg.png.svn-base b/src/main/webapp/stat/js/ui/floater/css/img/.svn/text-base/global_bg.png.svn-base similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/.svn/text-base/global_bg.png.svn-base rename to src/main/webapp/stat/js/ui/floater/css/img/.svn/text-base/global_bg.png.svn-base diff --git a/WebContent/stat/js/ui/floater/css/img/btn.gif b/src/main/webapp/stat/js/ui/floater/css/img/btn.gif similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/btn.gif rename to src/main/webapp/stat/js/ui/floater/css/img/btn.gif diff --git a/WebContent/stat/js/ui/floater/css/img/close.gif b/src/main/webapp/stat/js/ui/floater/css/img/close.gif similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/close.gif rename to src/main/webapp/stat/js/ui/floater/css/img/close.gif diff --git a/WebContent/stat/js/ui/floater/css/img/global_bg.png b/src/main/webapp/stat/js/ui/floater/css/img/global_bg.png similarity index 100% rename from WebContent/stat/js/ui/floater/css/img/global_bg.png rename to src/main/webapp/stat/js/ui/floater/css/img/global_bg.png diff --git a/WebContent/stat/js/ui/floater/js/.svn/all-wcprops b/src/main/webapp/stat/js/ui/floater/js/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/floater/js/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/floater/js/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/floater/js/.svn/entries b/src/main/webapp/stat/js/ui/floater/js/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/floater/js/.svn/entries rename to src/main/webapp/stat/js/ui/floater/js/.svn/entries diff --git a/WebContent/stat/js/ui/floater/js/.svn/text-base/floater.js.svn-base b/src/main/webapp/stat/js/ui/floater/js/.svn/text-base/floater.js.svn-base similarity index 100% rename from WebContent/stat/js/ui/floater/js/.svn/text-base/floater.js.svn-base rename to src/main/webapp/stat/js/ui/floater/js/.svn/text-base/floater.js.svn-base diff --git a/WebContent/stat/js/ui/floater/js/floater.js b/src/main/webapp/stat/js/ui/floater/js/floater.js similarity index 93% rename from WebContent/stat/js/ui/floater/js/floater.js rename to src/main/webapp/stat/js/ui/floater/js/floater.js index bc468a469..499ca506c 100644 --- a/WebContent/stat/js/ui/floater/js/floater.js +++ b/src/main/webapp/stat/js/ui/floater/js/floater.js @@ -18,11 +18,11 @@ ecui.ui.Form.prototype.showModal = function (opacity) { } var ecFloater = { - /** - * 显示指定的浮动层 + /** + * 显示指定的浮动层 * @param {String} ecId 获取ec控件需要的id - */ - show : function(ecId) { + */ + show: function (ecId) { var floater = ecui.get(ecId); floater.showModal(); @@ -39,5 +39,5 @@ var ecFloater = { var y = parseInt((viewHeight - elHeight) / 2 + scrollHeight, 10); floater.setPosition(x, y); - } + } }; diff --git a/WebContent/stat/js/ui/foldable/.svn/all-wcprops b/src/main/webapp/stat/js/ui/foldable/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/foldable/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/foldable/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/foldable/.svn/entries b/src/main/webapp/stat/js/ui/foldable/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/foldable/.svn/entries rename to src/main/webapp/stat/js/ui/foldable/.svn/entries diff --git a/WebContent/stat/js/ui/foldable/css/.svn/all-wcprops b/src/main/webapp/stat/js/ui/foldable/css/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/foldable/css/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/foldable/css/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/foldable/css/.svn/entries b/src/main/webapp/stat/js/ui/foldable/css/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/foldable/css/.svn/entries rename to src/main/webapp/stat/js/ui/foldable/css/.svn/entries diff --git a/WebContent/stat/js/ui/foldable/css/.svn/text-base/foldable.css.svn-base b/src/main/webapp/stat/js/ui/foldable/css/.svn/text-base/foldable.css.svn-base similarity index 100% rename from WebContent/stat/js/ui/foldable/css/.svn/text-base/foldable.css.svn-base rename to src/main/webapp/stat/js/ui/foldable/css/.svn/text-base/foldable.css.svn-base diff --git a/src/main/webapp/stat/js/ui/foldable/css/foldable.css b/src/main/webapp/stat/js/ui/foldable/css/foldable.css new file mode 100644 index 000000000..c93766385 --- /dev/null +++ b/src/main/webapp/stat/js/ui/foldable/css/foldable.css @@ -0,0 +1,52 @@ +/*.ec-foldable {border:solid 1px #000}*/ +.ec-foldable-title { + padding: 2px 0 4px 20px; + cursor: pointer; + border-bottom: 1px solid #DFF4CD; + color: #356502; + font-size: 14px; +} + +/*.ec-foldable-title-over {background-color:#EEE}*/ +/*.ec-foldable-title-press {background-color:#CCC}*/ +.ec-foldable-handler { + float: right; + margin: 3px 3px 0 0 +} + +.ec-foldable-title-fold .ec-foldable-handler, .ec-foldable-title-unfold .ec-foldable-handler { + width: 16px; + height: 16px +} + +.ec-foldable-title-fold .ec-foldable-handler { + background: url("img/remove.gif") no-repeat scroll 0 0 transparent; +} + +.ec-foldable-title-unfold .ec-foldable-handler { + background: url("img/add.gif") no-repeat scroll 0 0 transparent; +} + +.icon-a .ec-foldable-title, .icon-b .ec-foldable-title, .icon-c .ec-foldable-title, .icon-d .ec-foldable-title, .icon-e .ec-foldable-title { + background: url("img/icon.gif") no-repeat scroll 0 -145px transparent; +} + +.icon-b .ec-foldable-title { + background-position: 0 -170px; +} + +.icon-c .ec-foldable-title { + background-position: 0 -195px; +} + +.icon-d .ec-foldable-title { + background-position: 0 -248px; +} + +.icon-e .ec-foldable-title { + background-position: 0 -273px; +} + +.ec-foldable-content { + margin: 5px +} diff --git a/WebContent/stat/js/ui/foldable/css/img/.svn/all-wcprops b/src/main/webapp/stat/js/ui/foldable/css/img/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/foldable/css/img/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/foldable/css/img/.svn/entries b/src/main/webapp/stat/js/ui/foldable/css/img/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/.svn/entries rename to src/main/webapp/stat/js/ui/foldable/css/img/.svn/entries diff --git a/WebContent/stat/js/ui/foldable/css/img/.svn/prop-base/add.gif.svn-base b/src/main/webapp/stat/js/ui/foldable/css/img/.svn/prop-base/add.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/.svn/prop-base/add.gif.svn-base rename to src/main/webapp/stat/js/ui/foldable/css/img/.svn/prop-base/add.gif.svn-base diff --git a/WebContent/stat/js/ui/foldable/css/img/.svn/prop-base/icon.gif.svn-base b/src/main/webapp/stat/js/ui/foldable/css/img/.svn/prop-base/icon.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/.svn/prop-base/icon.gif.svn-base rename to src/main/webapp/stat/js/ui/foldable/css/img/.svn/prop-base/icon.gif.svn-base diff --git a/WebContent/stat/js/ui/foldable/css/img/.svn/prop-base/remove.gif.svn-base b/src/main/webapp/stat/js/ui/foldable/css/img/.svn/prop-base/remove.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/.svn/prop-base/remove.gif.svn-base rename to src/main/webapp/stat/js/ui/foldable/css/img/.svn/prop-base/remove.gif.svn-base diff --git a/WebContent/stat/js/ui/foldable/css/img/.svn/text-base/add.gif.svn-base b/src/main/webapp/stat/js/ui/foldable/css/img/.svn/text-base/add.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/.svn/text-base/add.gif.svn-base rename to src/main/webapp/stat/js/ui/foldable/css/img/.svn/text-base/add.gif.svn-base diff --git a/WebContent/stat/js/ui/foldable/css/img/.svn/text-base/icon.gif.svn-base b/src/main/webapp/stat/js/ui/foldable/css/img/.svn/text-base/icon.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/.svn/text-base/icon.gif.svn-base rename to src/main/webapp/stat/js/ui/foldable/css/img/.svn/text-base/icon.gif.svn-base diff --git a/WebContent/stat/js/ui/foldable/css/img/.svn/text-base/remove.gif.svn-base b/src/main/webapp/stat/js/ui/foldable/css/img/.svn/text-base/remove.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/.svn/text-base/remove.gif.svn-base rename to src/main/webapp/stat/js/ui/foldable/css/img/.svn/text-base/remove.gif.svn-base diff --git a/WebContent/stat/js/ui/foldable/css/img/add.gif b/src/main/webapp/stat/js/ui/foldable/css/img/add.gif similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/add.gif rename to src/main/webapp/stat/js/ui/foldable/css/img/add.gif diff --git a/WebContent/stat/js/ui/foldable/css/img/icon.gif b/src/main/webapp/stat/js/ui/foldable/css/img/icon.gif similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/icon.gif rename to src/main/webapp/stat/js/ui/foldable/css/img/icon.gif diff --git a/WebContent/stat/js/ui/foldable/css/img/remove.gif b/src/main/webapp/stat/js/ui/foldable/css/img/remove.gif similarity index 100% rename from WebContent/stat/js/ui/foldable/css/img/remove.gif rename to src/main/webapp/stat/js/ui/foldable/css/img/remove.gif diff --git a/WebContent/stat/js/ui/foldable/js/.svn/all-wcprops b/src/main/webapp/stat/js/ui/foldable/js/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/foldable/js/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/foldable/js/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/foldable/js/.svn/entries b/src/main/webapp/stat/js/ui/foldable/js/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/foldable/js/.svn/entries rename to src/main/webapp/stat/js/ui/foldable/js/.svn/entries diff --git a/WebContent/stat/js/ui/foldable/js/.svn/text-base/ecomui.foldable.js.svn-base b/src/main/webapp/stat/js/ui/foldable/js/.svn/text-base/ecomui.foldable.js.svn-base similarity index 100% rename from WebContent/stat/js/ui/foldable/js/.svn/text-base/ecomui.foldable.js.svn-base rename to src/main/webapp/stat/js/ui/foldable/js/.svn/text-base/ecomui.foldable.js.svn-base diff --git a/src/main/webapp/stat/js/ui/foldable/js/ecomui.foldable.js b/src/main/webapp/stat/js/ui/foldable/js/ecomui.foldable.js new file mode 100644 index 000000000..fc7d57e2d --- /dev/null +++ b/src/main/webapp/stat/js/ui/foldable/js/ecomui.foldable.js @@ -0,0 +1,66 @@ +var ecomui = ecomui || {}; + +(function () { + var lib = baidu, + core = ecui, + dom = core.dom, + ui = core.ui, + util = core.util, + inherits = util.inherits, + copy = util.copy, + + children = dom.children, + createDom = dom.create, + $fastCreate = core.$fastCreate, + setText = dom.setText, + + DOCUMENT = document, + UI_CONTROL = ui.Control, + ECOM_FOLDABLE_CLASS; + + ecomui.Foldable = ui.Foldable = function (el, params) { + var typeClass = params.type, + contentEl = children(el)[0]; + titleEl = createDom(typeClass + "-title"), + handlerEl = createDom(typeClass + "-handler"); + + el.insertBefore(titleEl, contentEl); + setText(titleEl, params.title || ""); + titleEl.insertBefore(handlerEl, titleEl.firstChild); + + params.capture = false; + + UI_CONTROL.call(this, el, params); + + this._uTitle = $fastCreate(UI_CONTROL, titleEl, this); + this._uContent = $fastCreate(UI_CONTROL, contentEl, this, {capture: false}); + this._uHandler = $fastCreate(UI_CONTROL, handlerEl, this._uTitle, {capture: false}); + + this._uTitle["on" + (params.trigger || "click")] = ECOM_FOLDABLE_TITLECLICK; + + ECOM_FOLDABLE_TOGGLECONTENT.call(this._uTitle, params.initFold || false); + }; + + function ECOM_FOLDABLE_TITLECLICK() { + ECOM_FOLDABLE_TOGGLECONTENT.call(this); + } + + function ECOM_FOLDABLE_TOGGLECONTENT(fold) { + var control = this.getParent(), + content = control._uContent, + handler = control._uHandler, + handlerEl = handler.getBase(), + isShow = fold !== undefined ? fold : content.isShow(); + + isShow ? content.hide() : content.show(); + handlerEl.setAttribute("title", isShow ? "点击展开" : "点击折叠"); + + this.$alterClass(isShow ? "unfold" : "fold"); + this.$alterClass(isShow ? "fold" : "unfold", true); + + control.$resize(); + } + + ECOM_FOLDABLE_CLASS = inherits(ui.Foldable, UI_CONTROL); + +})(); diff --git a/WebContent/stat/js/ui/popup/css/img/popup_bg.jpg b/src/main/webapp/stat/js/ui/popup/css/img/popup_bg.jpg similarity index 100% rename from WebContent/stat/js/ui/popup/css/img/popup_bg.jpg rename to src/main/webapp/stat/js/ui/popup/css/img/popup_bg.jpg diff --git a/WebContent/stat/js/ui/popup/css/img/popup_more.jpg b/src/main/webapp/stat/js/ui/popup/css/img/popup_more.jpg similarity index 100% rename from WebContent/stat/js/ui/popup/css/img/popup_more.jpg rename to src/main/webapp/stat/js/ui/popup/css/img/popup_more.jpg diff --git a/WebContent/stat/js/ui/popup/css/img/popup_more_over.jpg b/src/main/webapp/stat/js/ui/popup/css/img/popup_more_over.jpg similarity index 100% rename from WebContent/stat/js/ui/popup/css/img/popup_more_over.jpg rename to src/main/webapp/stat/js/ui/popup/css/img/popup_more_over.jpg diff --git a/WebContent/stat/js/ui/popup/css/img/popup_more_over_oh.jpg b/src/main/webapp/stat/js/ui/popup/css/img/popup_more_over_oh.jpg similarity index 100% rename from WebContent/stat/js/ui/popup/css/img/popup_more_over_oh.jpg rename to src/main/webapp/stat/js/ui/popup/css/img/popup_more_over_oh.jpg diff --git a/WebContent/stat/js/ui/popup/css/img/popup_over.jpg b/src/main/webapp/stat/js/ui/popup/css/img/popup_over.jpg similarity index 100% rename from WebContent/stat/js/ui/popup/css/img/popup_over.jpg rename to src/main/webapp/stat/js/ui/popup/css/img/popup_over.jpg diff --git a/WebContent/stat/js/ui/popup/css/img/popup_over_oh.jpg b/src/main/webapp/stat/js/ui/popup/css/img/popup_over_oh.jpg similarity index 100% rename from WebContent/stat/js/ui/popup/css/img/popup_over_oh.jpg rename to src/main/webapp/stat/js/ui/popup/css/img/popup_over_oh.jpg diff --git a/WebContent/stat/js/ui/popup/css/img/popup_tb.jpg b/src/main/webapp/stat/js/ui/popup/css/img/popup_tb.jpg similarity index 100% rename from WebContent/stat/js/ui/popup/css/img/popup_tb.jpg rename to src/main/webapp/stat/js/ui/popup/css/img/popup_tb.jpg diff --git a/WebContent/stat/js/ui/popup/css/img/select.jpg b/src/main/webapp/stat/js/ui/popup/css/img/select.jpg similarity index 100% rename from WebContent/stat/js/ui/popup/css/img/select.jpg rename to src/main/webapp/stat/js/ui/popup/css/img/select.jpg diff --git a/src/main/webapp/stat/js/ui/popup/css/popup.css b/src/main/webapp/stat/js/ui/popup/css/popup.css new file mode 100644 index 000000000..771399928 --- /dev/null +++ b/src/main/webapp/stat/js/ui/popup/css/popup.css @@ -0,0 +1,150 @@ +.popupdtr { + padding-top: 9px; + padding-bottom: 9px +} + +.popupdtr-top { + background: url(img/popup_tb.jpg) top left no-repeat; + overflow: hidden; + font-size: 0px +} + +.popupdtr-bottom { + background: url(img/popup_tb.jpg) 0px -9px no-repeat; + font-size: 0px +} + +.ec-popup { + padding-right: 13px; + border-width: auto; + border: none; + background: url(img/popup_bg.jpg) top left repeat-y; + width: 267px; + overflow-y: auto; + overflow-x: hidden +} + +.ec-popup .ec-item { + padding: auto; + height: 22px; + margin-left: 3px; + margin-right: 3px; + padding-left: 32px; + line-height: 22px; + cursor: default; + border-width: auto; + border: none +} + +.ec-popup-item { + padding: auto; + height: 22px; + margin-left: 3px; + margin-right: 3px; + padding-left: 32px; + line-height: 22px; + cursor: default; + background: none; + border-bottom: none +} + +.ec-popup-item-over { + background: url(img/popup_over.jpg) top left no-repeat +} + +.ec-popup-item-complex { + background: url(img/popup_more.jpg) 245px 7px no-repeat +} + +.ec-popup-item-complex-over { + background: url(img/popup_more_over.jpg) left top no-repeat +} + +.ec-scpopup { + padding-right: 13px; + border-width: auto; + border: none; + background: url(img/popup_bg.jpg) top left repeat-y; + width: 267px +} + +.ec-scpopup-layout { + width: 260px; + height: 100%; + overflow-y: auto; + overflow-x: hidden +} + +.ec-scpopup .ec-item { + padding: auto; + height: 22px; + margin-left: 3px; + margin-right: 3px; + padding-left: 10px; + line-height: 22px; + cursor: default; + border-width: auto; + border: none +} + +.ec-scpopup-item { + padding: auto; + height: 22px; + margin-left: 3px; + margin-right: 3px; + padding-left: 10px; + line-height: 22px; + cursor: default; + background: none; + border-bottom: none +} + +.ec-scpopup-item-over { + background: url(img/popup_over.jpg) top left no-repeat +} + +.ec-scpopup-item-complex { + background: url(img/popup_more.jpg) 244px 7px no-repeat +} + +.ec-scpopup-item-complex-over { + background: url(img/popup_more_over.jpg) left top no-repeat +} + +.ec-scpopup-layout-overheight .ec-scpopup-item-complex { + background: url(img/popup_more.jpg) 227px 7px no-repeat +} + +.ec-scpopup-layout-overheight .ec-scpopup-item-complex-over { + background: url(img/popup_more_over_oh.jpg) left top no-repeat +} + +.ec-scpopup-layout-overheight .ec-scpopup-item-over { + background: url(img/popup_over_oh.jpg) top left no-repeat +} + +.ec-ecombox { + top: 5px; + width: 120px; + height: 17px; + border: 1px solid #CCC; + background: #FFF +} + +.ec-ecombox-button { + top: 0px; + right: 0px; + width: 17px; + height: 17px; + background: url(img/select.jpg) 0px 0px no-repeat +} + +.ec-ecombox-over .ec-ecombox-button { + background: url(img/select.jpg) -17px 0px no-repeat +} + +.ec-ecombox-press .ec-ecombox-button { + background: url(img/select.jpg) -34px 0px no-repeat +} + + diff --git a/src/main/webapp/stat/js/ui/popup/js/ecpopup.js b/src/main/webapp/stat/js/ui/popup/js/ecpopup.js new file mode 100644 index 000000000..2a4ebe656 --- /dev/null +++ b/src/main/webapp/stat/js/ui/popup/js/ecpopup.js @@ -0,0 +1,246 @@ +(function () { + var core = ecui, + dom = core.dom, + ui = core.ui, + util = core.util, + ext = core.ext, + + createControl = core.create, + inherits = util.inherits, + getView = util.getView, + getPosition = dom.getPosition, + first = dom.first, + copy = util.copy, + blank = core.blank, + restore = core.restore, + trim = core.string.trim, + setStyles = dom.setStyles, + insertFloor = dom.insertFloor, + mask = core.mask, + removeDom = dom.remove, + getChild = dom.children, + setText = dom.setText, + getText = dom.getText, + createDom = dom.create, + moveElements = dom.moveElements, + + DOCUMENT = document, + + + UI_EDIT = ui.Edit, + UI_ITEM = ui.Item, + UI_CONTROL = ui.Control, + UI_CONTROL_CLASS = UI_CONTROL.prototype, + UI_EDIT_CLASS = UI_EDIT.prototype, + UI_POPUP = ui.Popup, + UI_POPUP_CLASS = UI_POPUP.prototype; + + var UI_ECOMBOX = ui.Ecombox = function (el, params) { + var me = this, + typeClass = params.type, + items; + + me._uPopup = createControl( + 'Scpopup', + { + 'element': first(el) + } + ); + me._uPopup.$setParent(me); + items = me._uPopup.getItems(); + + for (var i = 0, item; item = items[i]; i++) { + UI_ECOMBOX_ATTACHHANDLER(item); + } + + + UI_EDIT.call(me, el, params); + + (params.maxlength) && (this.getInput().maxLength = params.maxlength); + this.getInput().style.position = 'absolute'; + + (me._uButton = createControl( + 'Control', + { + 'base': typeClass + '-button', + 'parent': me, + 'capture': false + } + )).getOuter().style.position = 'absolute'; + + el.style.position = 'relative'; + }, + + UI_ECOMBOX_CLASS = inherits(UI_ECOMBOX, UI_EDIT); + + UI_ECOMBOX_CLASS.$click = function (event) { + var target = event.target; + UI_EDIT_CLASS.$click.call(this, event); + if (target.getControl && target.getControl() == this._uButton) { + this.showPopup(); + } + }; + + UI_ECOMBOX_CLASS.setValue = function (text) { + if (this.getInput().value != text) { + UI_EDIT_CLASS.setValue.call(this, text); + return true; + } + else { + return false; + } + }; + + UI_ECOMBOX_CLASS.showPopup = function () { + var pos = getPosition(this.getOuter()), + o = this._uPopup, + popupTop = pos.top + this.getHeight(), + items; + + o.setPosition( + pos.left, + popupTop + o.getHeight() <= getView().bottom ? popupTop : pos.top - o.getHeight() + ); + + items = o.getItems(); + for (var i = 0, item; item = items[i]; i++) { + (item._cPopup) && (item._cPopup.paint()); + } + + mask(0.05); + o.show(); + o.onhide = UI_ECOMBOX_HIDEMASK; + }; + + UI_ECOMBOX_CLASS.$setSize = function (width, height) { + UI_EDIT_CLASS.$setSize.call(this, width, height); + + width = this.getBodyWidth() - height; + this.getInput().style.width = width + 'px' + setStyles(this.getInput(), {'width': width + 'px', 'height': height + 'px'}); + }; + + function UI_ECOMBOX_HIDEMASK() { + mask(); + } + + function UI_ECOMBOX_SETVALUE() { + var el = this.getBody(), + value = el.getAttribute('value'), + text = trim(el.getAttribute('title') ? el.getAttribute('title') : el.innerHTML), + con = this; + + while ((con = con.getParent()) && !(con instanceof UI_ECOMBOX)) { + } + + if ((con) && (con.setValue(text)) && (con.onpostdata)) { + con.onpostdata(value); + } + + } + + function UI_ECOMBOX_ATTACHHANDLER(item) { + var childs = item.getChildItems(); + if (childs.length == 0) { + return; + } + for (var i = 0, child; child = childs[i]; i++) { + child.onclick = UI_ECOMBOX_SETVALUE; + UI_ECOMBOX_ATTACHHANDLER(child); + } + } + + var UI_SCPOPUP = ui.Scpopup = function (el, params) { + var i = 0, + o; + + UI_CONTROL.call(this, el, params); + + o = createDom(); + moveElements(o, el); + el.appendChild(o); + this._eBody = o; + this._eBody.className = params.type + '-layout'; + + this._nMaxHeight = params.maxheight || 300; + this._nMaxTextLen = params.maxTextLen || 20; + + /* 初始化菜单项 */ + //this.setParent(DOCUMENT.body); + DOCUMENT.body.appendChild(el); + this.$initItems(); + this.$alterItems(); + + el = this.getOuter().style; + el.display = 'none'; + el.position = 'absolute'; + + /* 弹出菜单初始化完成后就不允许改变父对象 */ + this.setParent = blank; + + /* 初始化子弹出菜单 */ + for (el = this.getItems(); o = el[i++];) { + o._cPopup && o.setClass(params.base + '-item-complex'); + } + + /* 修正文字长度不能超过限制 */ + for (i = 0, el = getChild(this._eBody); o = el[i++];) { + if (first(o) && first(o).tagName.toLowerCase() == 'label') { + o = first(o); + } + if ((getText(o).length) > this._nMaxTextLen) { + o.setAttribute('title', getText(o)); + setText(o, getText(o).substring(0, this._nMaxTextLen - 3) + '...'); + } + } + }, + + UI_SCPOPUP_CLASS = inherits(UI_SCPOPUP, UI_POPUP); + + UI_SCPOPUP_CLASS.$createChild = function (item, el) { + var popup; + if (trim(el.innerHTML) == '') { + removeDom(el); + return false; + } + popup = item._cPopup = createControl( + 'Scpopup', + { + base: item.getParent().getClass(), + element: el + } + ); + + popup.$setParent(item); + return popup; + }; + + UI_SCPOPUP_CLASS.$create = function () { + new ext.TBDecorator(this, 'popupdtr'); + UI_CONTROL_CLASS.$create.call(this); + }; + + UI_SCPOPUP_CLASS.$setSize = function (width, height) { + var el = this._eBody; + if (height > this._nMaxHeight) { + height = this._nMaxHeight; + if (el.className.indexOf('overheight') < 0) { + el.className = el.className + ' ' + this.getBaseClass() + '-layout-overheight'; + } + } + UI_CONTROL_CLASS.$setSize.call(this, width, height); + }; + + UI_SCPOPUP_CLASS.$forcibly = function (event) { + var con = event.getTarget(), find = false; + while (con) { + if (con == this) { + find = true; + break; + } + con = con.getParent(); + } + (!find) && (UI_POPUP_CLASS.$forcibly.call(this)); + return false; + } +})() diff --git a/WebContent/stat/js/ui/scroll/css/img/hscroll.jpg b/src/main/webapp/stat/js/ui/scroll/css/img/hscroll.jpg similarity index 100% rename from WebContent/stat/js/ui/scroll/css/img/hscroll.jpg rename to src/main/webapp/stat/js/ui/scroll/css/img/hscroll.jpg diff --git a/WebContent/stat/js/ui/scroll/css/img/scroll.jpg b/src/main/webapp/stat/js/ui/scroll/css/img/scroll.jpg similarity index 100% rename from WebContent/stat/js/ui/scroll/css/img/scroll.jpg rename to src/main/webapp/stat/js/ui/scroll/css/img/scroll.jpg diff --git a/src/main/webapp/stat/js/ui/scroll/css/scroll.css b/src/main/webapp/stat/js/ui/scroll/css/scroll.css new file mode 100644 index 000000000..4264d1e00 --- /dev/null +++ b/src/main/webapp/stat/js/ui/scroll/css/scroll.css @@ -0,0 +1,141 @@ +.ec-vscroll { + background: #F0F0F0; + width: auto; + padding: 15px 0px 15px 0px; + font-size: 0px +} + +.ec-hscroll { + background: #F0F0F0; + height: auto; + padding: 0px 15px 0px 15px; + font-size: 0px +} + +.ec-hscroll-block { + background: url(img/hscroll.jpg) -2px -30px repeat-x +} + +.ec-vscroll-block { + background: url(img/scroll.jpg) 0px 0px repeat-y +} + +.ec-hscroll-block-over { + background: url(img/hscroll.jpg) -0px -45px repeat-x +} + +.ec-hscroll-block-press { + background: url(img/hscroll.jpg) -0px -60px repeat-x +} + +.ec-vscroll-block-over { + background: url(img/scroll.jpg) -15px 0px repeat-y +} + +.ec-vscroll-block-press { + background: url(img/scroll.jpg) -30px 0px repeat-y +} + +.ec-vscroll-prev { + background: url(img/scroll.jpg) -45px -40px no-repeat; +} + +.ec-vscroll-prev-over { + background: url(img/scroll.jpg) -75px -40px no-repeat; +} + +.ec-vscroll-prev-press { + background: url(img/scroll.jpg) -60px -40px no-repeat; +} + +.ec-vscroll-next { + background: url(img/scroll.jpg) -45px -55px no-repeat; +} + +.ec-vscroll-next-over { + background: url(img/scroll.jpg) -75px -55px no-repeat; +} + +.ec-vscroll-next-press { + background: url(img/scroll.jpg) -60px -55px no-repeat; +} + +.ec-hscroll-prev { + background: url(img/scroll.jpg) -45px -85px no-repeat; +} + +.ec-hscroll-prev-over { + background: url(img/scroll.jpg) -75px -85px no-repeat; +} + +.ec-hscroll-prev-press { + background: url(img/scroll.jpg) -60px -85px no-repeat; +} + +.ec-hscroll-next { + background: url(img/scroll.jpg) -45px -70px no-repeat; +} + +.ec-hscroll-next-over { + background: url(img/scroll.jpg) -75px -70px no-repeat; +} + +.ec-hscroll-next-press { + background: url(img/scroll.jpg) -60px -70px no-repeat; +} + +.vsblockdtr { + padding: 2px 0px +} + +.vsblockdtr-top { + background: url(img/scroll.jpg) -45px 0px no-repeat +} + +.vsblockdtr-bottom { + background: url(img/scroll.jpg) -45px -18px no-repeat +} + +.vsblockdtr-over .vsblockdtr-top { + background: url(img/scroll.jpg) -45px -20px no-repeat +} + +.vsblockdtr-over .vsblockdtr-bottom { + background: url(img/scroll.jpg) -45px -38px no-repeat +} + +.vsblockdtr-press .vsblockdtr-top { + background: url(img/scroll.jpg) -60px 0px no-repeat +} + +.vsblockdtr-press .vsblockdtr-bottom { + background: url(img/scroll.jpg) -60px -38px no-repeat +} + +.hsblockdtr { + padding: 0px 2px +} + +.hsblockdtr-left { + background: url(img/hscroll.jpg) -60px 0px no-repeat +} + +.hsblockdtr-right { + background: url(img/hscroll.jpg) -18px 0px no-repeat +} + +.hsblockdtr-over .hsblockdtr-left { + background: url(img/hscroll.jpg) -40px -0px no-repeat +} + +.hsblockdtr-over .hsblockdtr-right { + background: url(img/hscroll.jpg) -38px -0px no-repeat +} + +.hsblockdtr-press .hsblockdtr-left { + background: url(img/hscroll.jpg) -40px -15px no-repeat +} + +.hsblockdtr-press .hsblockdtr-right { + background: url(img/hscroll.jpg) -38px -15px no-repeat +} diff --git a/WebContent/stat/js/ui/selectbox/.svn/all-wcprops b/src/main/webapp/stat/js/ui/selectbox/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/selectbox/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/selectbox/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/selectbox/.svn/entries b/src/main/webapp/stat/js/ui/selectbox/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/selectbox/.svn/entries rename to src/main/webapp/stat/js/ui/selectbox/.svn/entries diff --git a/WebContent/stat/js/ui/selectbox/css/.svn/all-wcprops b/src/main/webapp/stat/js/ui/selectbox/css/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/selectbox/css/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/selectbox/css/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/selectbox/css/.svn/entries b/src/main/webapp/stat/js/ui/selectbox/css/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/selectbox/css/.svn/entries rename to src/main/webapp/stat/js/ui/selectbox/css/.svn/entries diff --git a/WebContent/stat/js/ui/selectbox/css/.svn/text-base/selectbox.css.svn-base b/src/main/webapp/stat/js/ui/selectbox/css/.svn/text-base/selectbox.css.svn-base similarity index 100% rename from WebContent/stat/js/ui/selectbox/css/.svn/text-base/selectbox.css.svn-base rename to src/main/webapp/stat/js/ui/selectbox/css/.svn/text-base/selectbox.css.svn-base diff --git a/WebContent/stat/js/ui/selectbox/css/img/.svn/all-wcprops b/src/main/webapp/stat/js/ui/selectbox/css/img/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/selectbox/css/img/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/selectbox/css/img/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/selectbox/css/img/.svn/entries b/src/main/webapp/stat/js/ui/selectbox/css/img/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/selectbox/css/img/.svn/entries rename to src/main/webapp/stat/js/ui/selectbox/css/img/.svn/entries diff --git a/WebContent/stat/js/ui/selectbox/css/img/.svn/prop-base/scroll_bg.gif.svn-base b/src/main/webapp/stat/js/ui/selectbox/css/img/.svn/prop-base/scroll_bg.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/selectbox/css/img/.svn/prop-base/scroll_bg.gif.svn-base rename to src/main/webapp/stat/js/ui/selectbox/css/img/.svn/prop-base/scroll_bg.gif.svn-base diff --git a/WebContent/stat/js/ui/selectbox/css/img/.svn/text-base/scroll_bg.gif.svn-base b/src/main/webapp/stat/js/ui/selectbox/css/img/.svn/text-base/scroll_bg.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/selectbox/css/img/.svn/text-base/scroll_bg.gif.svn-base rename to src/main/webapp/stat/js/ui/selectbox/css/img/.svn/text-base/scroll_bg.gif.svn-base diff --git a/WebContent/stat/js/ui/selectbox/css/img/scroll_bg.gif b/src/main/webapp/stat/js/ui/selectbox/css/img/scroll_bg.gif similarity index 100% rename from WebContent/stat/js/ui/selectbox/css/img/scroll_bg.gif rename to src/main/webapp/stat/js/ui/selectbox/css/img/scroll_bg.gif diff --git a/src/main/webapp/stat/js/ui/selectbox/css/selectbox.css b/src/main/webapp/stat/js/ui/selectbox/css/selectbox.css new file mode 100644 index 000000000..0270394c6 --- /dev/null +++ b/src/main/webapp/stat/js/ui/selectbox/css/selectbox.css @@ -0,0 +1,79 @@ +.ec-panel { + z-index: 9000; + height: 100px; + width: 137px; + background: #fff +} + +.ec-panel-corner { + background: #F0F0F0; + font-size: 1px; +} + +.ec-panel-layout { + border: 1px solid #CCC; + line-height: 20px; + padding: 3px; +} + +.select-box .ec-panel-layout { + text-align: left; + margin-top: 1px; + background: #fff; +} + +.select-box .ec-vscroll { + border-right: 1px #ccc solid; + cursor: pointer; + cursor: hand; +} + +.select-box button { + margin: 5px 0; +} + +.select-box .ec-edit { + padding-right: 15px; + height: 15px; + background: #fff url("img/scroll_bg.gif") no-repeat right -15px; + border: 1px #ccc solid; + cursor: pointer; + cursor: hand; +} + +.ec-panel-corner { + background: #F0F0F0; + font-size: 1px; +} + +.ec-panel-layout { + background: #fff; + border: 1px solid #CCC; + line-height: 20px; + padding: 3px; +} + +.select-box .ec-panel-layout { + text-align: left; + margin-top: 1px; + background: #fff; +} + +.select-box .ec-vscroll { + border-right: 1px #ccc solid; + cursor: pointer; + cursor: hand; +} + +.select-box button { + margin: 5px 0; +} + +.sel-edit { + z-index: 9000; + padding-right: 13px; + background: #fff url("img/scroll_bg.gif") no-repeat right -14px; + border: 1px #ccc solid; + cursor: pointer; + cursor: hand; +} diff --git a/WebContent/stat/js/ui/selectbox/js/.svn/all-wcprops b/src/main/webapp/stat/js/ui/selectbox/js/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/selectbox/js/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/selectbox/js/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/selectbox/js/.svn/entries b/src/main/webapp/stat/js/ui/selectbox/js/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/selectbox/js/.svn/entries rename to src/main/webapp/stat/js/ui/selectbox/js/.svn/entries diff --git a/WebContent/stat/js/ui/selectbox/js/.svn/text-base/selectbox.js.svn-base b/src/main/webapp/stat/js/ui/selectbox/js/.svn/text-base/selectbox.js.svn-base similarity index 100% rename from WebContent/stat/js/ui/selectbox/js/.svn/text-base/selectbox.js.svn-base rename to src/main/webapp/stat/js/ui/selectbox/js/.svn/text-base/selectbox.js.svn-base diff --git a/src/main/webapp/stat/js/ui/selectbox/js/selectbox.js b/src/main/webapp/stat/js/ui/selectbox/js/selectbox.js new file mode 100644 index 000000000..2dc4e4c1c --- /dev/null +++ b/src/main/webapp/stat/js/ui/selectbox/js/selectbox.js @@ -0,0 +1,142 @@ +//按钮的点击事件 +function wrapHide(tg) { + var wrap = baidu.dom.getAncestorByClass(tg, "ec-panel"); + wrap = wrap.getControl(); + var selectBox = wrap.getParent(); + var edit = selectBox._uEdit.getInput(); + var allBox = selectBox._uPanel.getOuter().getElementsByTagName("input") + var str = ""; + for (var i = 0, j = 0; i < allBox.length && j < 4; i++) { + if (allBox[i].checked) { + j++; + show = baidu.dom.next(allBox[i]).innerHTML; + if (j == 1) { + str += show + } + else if (j < 4) { + str += "," + show + } + else { + str += "," + show + "..." + } + } + } + edit.value = str; + wrap.hide(); +} + +//以下为多选下拉用到的js +var ecomui = ecomui || {}; +(function () { + var core = ecui, + ui = core.ui, + util = core.util; + inherits = util.inherits, + UI_CONTROL = ui.Control; + + /** + * --------------------- + * 多选下拉构造函数 + * --------------------- + */ + ecomui.SelectBox = ui.SelectBox = function (el, params) { + UI_CONTROL.call(this, el, params); + var id = this.getUID(), body = this.getBody(); + var panelHTML = '
    '; + panelHTML += '
    '; + body.innerHTML = panelHTML; + core.init(body); + this.setClass("select-box"); + + this._uHeight = params.pHeight || 30 + this._uCol = params.col || 1; + this._uName = params.name; + this._uEdit = core.get("edit-" + id); + this._uPanel = core.get("panel-" + id); + + //最开始隐藏下拉层 + this._uPanel.hide(); + this.init(); + //绑定事件 + this._uEdit.onclick = SELECT_BOX_CLASS.oneditclick; + } + + //原型继承至基础控件 + SELECT_BOX_CLASS = inherits(ui.SelectBox, UI_CONTROL); + + + //点击输入框弹出下拉层 + SELECT_BOX_CLASS.oneditclick = function () { + var wrap = this.getParent() + var panelDom = wrap._uPanel.getBase(); + baidu.dom.toggle(panelDom); + + } + + //屏蔽点击事件,返回给控件 + SELECT_BOX_CLASS.$pressend = function () { + ecui.forcibly(this); + mask(0, 65534); + } + + //重写$forcibly方法 + SELECT_BOX_CLASS.$forcibly = function () { + var wrap = this.getParent() + var panelDom = wrap._uPanel.getBase(); + baidu.dom.toggle(panelDom); + } + + + //设置下拉面板的可见高度 + SELECT_BOX_CLASS.setPHeight = function () { + var pHeight = this._uHeight; + var pStyle = this._uPanel.getOuter().style; + pStyle.height = pHeight; + + } + + //控件初始化 + SELECT_BOX_CLASS.init = function () { + this.setPst(); + this.setPHeight(); + } + + //根据edit定位下拉层 + SELECT_BOX_CLASS.setPst = function () { + var edit = this._uEdit.getBase(); + var editX = baidu.dom.getPosition(edit).left; + var editY = baidu.dom.getPosition(edit).top; + var pStyle = this._uPanel.getBase(); + pStyle.style.position = "absolute"; + this._uPanel.setPosition(editX, editY + 15); + } + + SELECT_BOX_CLASS.updata = function () { + var allBox = this._uPanel; + alert(allBox) + + + } + + //滚动条不因后面的内容增加而出现 TODO + //设置下拉框中的内容,根据数据构造多个checkbox + SELECT_BOX_CLASS.setData = function (data) { + var sData = data; + var Fname = this._uName; + var Fcol = this._uCol; + var optionHTML = ""; + var checkboxIndex = 1; + var panelContent = this._uPanel.getBody(); + baidu.array.each(sData, function (item, i) { + Schecked = item.isChecked ? 'checked="checked"' : ""; + optionHTML += ''; + optionHTML += ''; + if (checkboxIndex % Fcol == 0) optionHTML += '
    '; + checkboxIndex++; + }); + optionHTML += '
    ' + panelContent.innerHTML = optionHTML; + } + + +})() \ No newline at end of file diff --git a/WebContent/stat/js/ui/table/.svn/all-wcprops b/src/main/webapp/stat/js/ui/table/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/table/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/table/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/table/.svn/entries b/src/main/webapp/stat/js/ui/table/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/table/.svn/entries rename to src/main/webapp/stat/js/ui/table/.svn/entries diff --git a/WebContent/stat/js/ui/table/css/.svn/all-wcprops b/src/main/webapp/stat/js/ui/table/css/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/table/css/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/table/css/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/table/css/.svn/entries b/src/main/webapp/stat/js/ui/table/css/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/table/css/.svn/entries rename to src/main/webapp/stat/js/ui/table/css/.svn/entries diff --git a/WebContent/stat/js/ui/table/css/.svn/text-base/table.css.svn-base b/src/main/webapp/stat/js/ui/table/css/.svn/text-base/table.css.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/.svn/text-base/table.css.svn-base rename to src/main/webapp/stat/js/ui/table/css/.svn/text-base/table.css.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/all-wcprops b/src/main/webapp/stat/js/ui/table/css/img/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/table/css/img/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/table/css/img/.svn/entries b/src/main/webapp/stat/js/ui/table/css/img/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/entries rename to src/main/webapp/stat/js/ui/table/css/img/.svn/entries diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/cr.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/cr.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/cr.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/cr.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/hscroll.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/hscroll.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/hscroll.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/hscroll.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/hscroll_blue.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/hscroll_blue.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/hscroll_blue.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/hscroll_blue.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/hscroll_bluegray.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/hscroll_bluegray.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/hscroll_bluegray.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/hscroll_bluegray.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/loading.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/loading.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/loading.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/loading.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/scroll.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/scroll.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/scroll.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/scroll.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/scroll_blue.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/scroll_blue.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/scroll_blue.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/scroll_blue.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/scroll_bluegray.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/scroll_bluegray.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/scroll_bluegray.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/scroll_bluegray.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/table.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/table.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/table.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/table.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/table_blue.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/table_blue.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/table_blue.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/table_blue.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/prop-base/table_bluegray.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/table_bluegray.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/prop-base/table_bluegray.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/prop-base/table_bluegray.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/cr.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/cr.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/cr.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/cr.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/hscroll.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/hscroll.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/hscroll.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/hscroll.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/hscroll_blue.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/hscroll_blue.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/hscroll_blue.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/hscroll_blue.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/hscroll_bluegray.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/hscroll_bluegray.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/hscroll_bluegray.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/hscroll_bluegray.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/loading.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/loading.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/loading.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/loading.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/scroll.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/scroll.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/scroll.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/scroll.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/scroll_blue.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/scroll_blue.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/scroll_blue.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/scroll_blue.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/scroll_bluegray.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/scroll_bluegray.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/scroll_bluegray.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/scroll_bluegray.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/table.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/table.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/table.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/table.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/table_blue.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/table_blue.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/table_blue.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/table_blue.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/.svn/text-base/table_bluegray.gif.svn-base b/src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/table_bluegray.gif.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/css/img/.svn/text-base/table_bluegray.gif.svn-base rename to src/main/webapp/stat/js/ui/table/css/img/.svn/text-base/table_bluegray.gif.svn-base diff --git a/WebContent/stat/js/ui/table/css/img/cr.gif b/src/main/webapp/stat/js/ui/table/css/img/cr.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/cr.gif rename to src/main/webapp/stat/js/ui/table/css/img/cr.gif diff --git a/WebContent/stat/js/ui/table/css/img/hscroll.gif b/src/main/webapp/stat/js/ui/table/css/img/hscroll.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/hscroll.gif rename to src/main/webapp/stat/js/ui/table/css/img/hscroll.gif diff --git a/WebContent/stat/js/ui/table/css/img/hscroll_blue.gif b/src/main/webapp/stat/js/ui/table/css/img/hscroll_blue.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/hscroll_blue.gif rename to src/main/webapp/stat/js/ui/table/css/img/hscroll_blue.gif diff --git a/WebContent/stat/js/ui/table/css/img/hscroll_bluegray.gif b/src/main/webapp/stat/js/ui/table/css/img/hscroll_bluegray.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/hscroll_bluegray.gif rename to src/main/webapp/stat/js/ui/table/css/img/hscroll_bluegray.gif diff --git a/WebContent/stat/js/ui/table/css/img/loading.gif b/src/main/webapp/stat/js/ui/table/css/img/loading.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/loading.gif rename to src/main/webapp/stat/js/ui/table/css/img/loading.gif diff --git a/WebContent/stat/js/ui/table/css/img/scroll.gif b/src/main/webapp/stat/js/ui/table/css/img/scroll.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/scroll.gif rename to src/main/webapp/stat/js/ui/table/css/img/scroll.gif diff --git a/WebContent/stat/js/ui/table/css/img/scroll_blue.gif b/src/main/webapp/stat/js/ui/table/css/img/scroll_blue.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/scroll_blue.gif rename to src/main/webapp/stat/js/ui/table/css/img/scroll_blue.gif diff --git a/WebContent/stat/js/ui/table/css/img/scroll_bluegray.gif b/src/main/webapp/stat/js/ui/table/css/img/scroll_bluegray.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/scroll_bluegray.gif rename to src/main/webapp/stat/js/ui/table/css/img/scroll_bluegray.gif diff --git a/WebContent/stat/js/ui/table/css/img/table.gif b/src/main/webapp/stat/js/ui/table/css/img/table.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/table.gif rename to src/main/webapp/stat/js/ui/table/css/img/table.gif diff --git a/WebContent/stat/js/ui/table/css/img/table_blue.gif b/src/main/webapp/stat/js/ui/table/css/img/table_blue.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/table_blue.gif rename to src/main/webapp/stat/js/ui/table/css/img/table_blue.gif diff --git a/WebContent/stat/js/ui/table/css/img/table_bluegray.gif b/src/main/webapp/stat/js/ui/table/css/img/table_bluegray.gif similarity index 100% rename from WebContent/stat/js/ui/table/css/img/table_bluegray.gif rename to src/main/webapp/stat/js/ui/table/css/img/table_bluegray.gif diff --git a/src/main/webapp/stat/js/ui/table/css/table.css b/src/main/webapp/stat/js/ui/table/css/table.css new file mode 100644 index 000000000..6e22dff4c --- /dev/null +++ b/src/main/webapp/stat/js/ui/table/css/table.css @@ -0,0 +1,600 @@ +/* FOR OPERA */ +div { + border: 0; +} + +.ec-ecom-table .ec-vscroll { + background: #F2F8EE; + width: 15px; + padding: 15px 0px 15px 0px; + font-size: 1px +} + +.ec-ecom-table .ec-hscroll { + background: #F2F8EE; + height: 15px; + padding: 0px 15px 0px 15px; + font-size: 1px +} + +.ec-ecom-table .ec-hscroll-block { + background: url("img/hscroll.gif") -2px -30px repeat-x; + border: 1px solid #76A258; + border-width: 0 1px +} + +.ec-ecom-table .ec-vscroll-block { + background: url("img/scroll.gif") 0px 0px repeat-y; + border: 1px solid #76A258; + border-width: 1px 0 +} + +.ec-ecom-table .ec-hscroll-block-over { + background: url("img/hscroll.gif") -0px -45px repeat-x +} + +.ec-ecom-table .ec-hscroll-block-press { + background: url("img/hscroll.gif") -0px -60px repeat-x +} + +.ec-ecom-table .ec-vscroll-block-over { + background: url("img/scroll.gif") -15px 0px repeat-y +} + +.ec-ecom-table .ec-vscroll-block-press { + background: url("img/scroll.gif") -30px 0px repeat-y +} + +.ec-ecom-table .ec-vscroll-prev { + background: url("img/scroll.gif") -45px -40px no-repeat; +} + +.ec-ecom-table .ec-vscroll-prev-over { + background: url("img/scroll.gif") -75px -40px no-repeat; +} + +.ec-ecom-table .ec-vscroll-prev-press { + background: url("img/scroll.gif") -60px -40px no-repeat; +} + +.ec-ecom-table .ec-vscroll-next { + background: url("img/scroll.gif") -45px -55px no-repeat; +} + +.ec-ecom-table .ec-vscroll-next-over { + background: url("img/scroll.gif") -75px -55px no-repeat; +} + +.ec-ecom-table .ec-vscroll-next-press { + background: url("img/scroll.gif") -60px -55px no-repeat; +} + +.ec-ecom-table .ec-hscroll-prev { + background: url("img/scroll.gif") -45px -85px no-repeat; +} + +.ec-ecom-table .ec-hscroll-prev-over { + background: url("img/scroll.gif") -75px -85px no-repeat; +} + +.ec-ecom-table .ec-hscroll-prev-press { + background: url("img/scroll.gif") -60px -85px no-repeat; +} + +.ec-ecom-table .ec-hscroll-next { + background: url("img/scroll.gif") -45px -70px no-repeat; +} + +.ec-ecom-table .ec-hscroll-next-over { + background: url("img/scroll.gif") -75px -70px no-repeat; +} + +.ec-ecom-table .ec-hscroll-next-press { + background: url("img/scroll.gif") -60px -70px no-repeat; +} + +.ec-ecom-table .vsblockdtr { + padding: 2px 0px +} + +.ec-ecom-table .vsblockdtr-top { + background: url("img/scroll.gif") -45px 0px no-repeat +} + +.ec-ecom-table .vsblockdtr-bottom { + background: url("img/scroll.gif") -45px -18px no-repeat +} + +.ec-ecom-table .vsblockdtr-over .vsblockdtr-top { + background: url("img/scroll.gif") -45px -20px no-repeat +} + +.ec-ecom-table .vsblockdtr-over .vsblockdtr-bottom { + background: url("img/scroll.gif") -45px -38px no-repeat +} + +.ec-ecom-table .vsblockdtr-press .vsblockdtr-top { + background: url("img/scroll.gif") -60px 0px no-repeat +} + +.ec-ecom-table .vsblockdtr-press .vsblockdtr-bottom { + background: url("img/scroll.gif") -60px -38px no-repeat +} + +.ec-ecom-table .ec-panel-disabled .vsblockdtr div { + display: none +} + +.ec-ecom-table .hsblockdtr { + padding: 0px 2px +} + +.ec-ecom-table .hsblockdtr-left { + background: url("img/hscroll.gif") -60px 0px no-repeat +} + +.ec-ecom-table .hsblockdtr-right { + background: url("img/hscroll.gif") -18px 0px no-repeat +} + +.ec-ecom-table .hsblockdtr-over .hsblockdtr-left { + background: url("img/hscroll.gif") -40px -0px no-repeat +} + +.ec-ecom-table .hsblockdtr-over .hsblockdtr-right { + background: url("img/hscroll.gif") -38px -0px no-repeat +} + +.ec-ecom-table .hsblockdtr-press .hsblockdtr-left { + background: url("img/hscroll.gif") -40px -15px no-repeat +} + +.ec-ecom-table .hsblockdtr-press .hsblockdtr-right { + background: url("img/hscroll.gif") -38px -15px no-repeat +} + +.ec-ecom-table .ec-panel-disabled .hsblockdtr div { + display: none +} + +.ec-ecom-table { + border: 1px solid #9CD167; + padding-top: 23px; + background-color: #DCEFD1 +} + +.ec-ecom-table .checkbox { + padding-left: 0px; + padding-right: 0px; +} + +.ec-ecom-table .checkbox-item { + padding-left: 0px; + padding-right: 0px; +} + +.ec-ecom-table .checkbox-disabled { + background: url(img/cr.gif) -68px 0px no-repeat; + width: 17px; + height: 17px;; + margin-right: 5px +} + +.ec-ecom-table table { + border-collapse: collapse; + border-spacing: 0px +} + +.ec-ecom-table-layout { + background: #FFF; + color: #333 +} + +.ec-ecom-table-head, .ec-print-table th { + font-weight: normal; + color: #326700; + padding: 6px 5px; + padding-right: 12px; + line-height: 15px; + border: 0; + border-left: 1px solid #CCE9B9; + border-bottom: 1px solid #9CD167; + overflow: hidden; + white-space: nowrap; + word-wrap: normal; + word-break: keep-all +} + +.ec-ecom-table-item, .ec-print-table td { + line-height: 15px; + border: 0; + padding: 5px 5px; + padding-right: 12px; + border-left: 1px solid #CCE9B9; + word-break: break-all; + white-space: normal; + word-wrap: break-word; + overflow: hidden +} + +.ec-ecom-table .od td { + background-color: #FFF; +} + +.ec-ecom-table .ev td { + background-color: #F2F8EE; +} + +.ec-ecom-table .od td.dk { + background-color: #EAF1E2; +} + +.ec-ecom-table .ev td.dk { + background-color: #DDE9D0; +} + +.ec-ecom-table-row-focus td.ec-ecom-table-item, +.ec-ecom-table-row-over td.ec-ecom-table-item, +.ec-ecom-table .ec-ecom-table-row-focus td.dk, +.ec-ecom-table .ec-ecom-table-row-over td.dk { + background-color: #FFFCE2 +} + +/* +.ec-ecom-table-row-over .ev .ec-ecom-table-item, +.ec-ecom-table-row-over .ev td.dk, +.ec-ecom-table-row-over .od .ec-ecom-table-item, +.ec-ecom-table-row-over .od td.dk, +.ec-ecom-table-row-focus .ev .ec-ecom-table-item, +.ec-ecom-table-row-focus .ev td.dk, +.ec-ecom-table-row-focus .od .ec-ecom-table-item, +.ec-ecom-table-row-focus .od td.dk, +.ec-ecom-table-row-focus .ec-ecom-table-item, +.ec-ecom-table-row-over .ec-ecom-table-item {background-color:#FFFCE2} +*/ +/*排序*/ +.ec-ecom-table-area .sort, .ec-ecom-table-area .sort-over, .ec-ecom-table-area .sort-focus { + text-align: left; + cursor: pointer; + background: url("img/table.gif") no-repeat 93% -33px; +} + +.ec-ecom-table-area .sort-over { + background-color: #F6FFB8; +} + +.ec-ecom-table-area .sort-up, .ec-ecom-table-area .sort-down { + cursor: pointer; /*text-align:right;*/ + background: #F6FFB8 url("img/table.gif") no-repeat 93% -33px; +} + +.ec-ecom-table-area .sort-up { + background-position: 93% -63px; +} + +.ec-ecom-table-area .sort-down { + background-position: 93% -93px; +} + +.ec-ecom-table-row .op { + text-align: center; + border: 0 none; + border-left: 1px solid #9CD167 +} + +/*复选框*/ +.ec-checkbox { + background: url("img/cr.gif") 0px 0px no-repeat; + width: 17px; + height: 15px +} + +.ec-checkbox-display { + background: url("img/cr.gif") -34px 0px no-repeat; +} + +.ec-checkbox-over { + background: url("img/cr.gif") -17px 0px no-repeat; +} + +.ec-checkbox-checked { + background: url("img/cr.gif") -34px 0px no-repeat +} + +.ec-checkbox-checked-over { + background: url("img/cr.gif") -51px 0px no-repeat +} + +.ec-checkbox-part { + background: url("img/cr.gif") -102px 0px no-repeat +} + +/*展开按钮(上)*/ +.ec-col-toggler, .ec-col-toggler-o { + width: 17px; + height: 20px; + position: absolute; + top: 2px; + right: 0; + background: #DCEFD1 url("img/table.gif") no-repeat 0px 0px; + cursor: pointer; +} + +.ec-col-toggler-o { + background-position: -22px 0px +} + +/*展开按钮(下)*/ +.ec-v-toggler { + width: 15px; + background: #DDE9D0; + position: absolute; + right: 0; + bottom: 0; + _right: -1px; + cursor: pointer; + border-left: 1px solid #9CD167; /*border-right:1px solid #9CD167;*/ +} + +.ec-v-toggler div { + width: 9px; + height: 10px; + overflow: hidden; + background: url("img/table.gif") no-repeat -8px -22px; + position: absolute; + right: 3px; + bottom: 50%; + _padding-top: 50%; + cursor: pointer; +} + +.ec-v-toggler-over { + background-color: #EAF1E2 +} + +/*验证*/ +.valid-error td.ec-ecom-table-item { + background-color: pink !important; +} + +/* *分页 *囧, 有同名的list宏,需转义 */ +.ec-page a, .ec-page b { + margin: 0; + text-indent: 0; + display: inline-block; + *display: inline; + zoom: 1; + height: 20px; + line-height: 20px; + background: url("img/table.gif") repeat-x 0 -150px; + border: 1px solid #9CD167; + padding: 0 3px; + text-decoration: none; + color: #326700; +} + +.ec-page a:hover { + background-position: 0 -176px; +} + +.ec-page .page-n { + /*width:20px;*/ + text-align: center; /*padding:0;*/ + padding: 0 5px; +} + +.ec-page b { + background-image: none; + color: #666; + background-color: #EEE; + font-weight: normal; +} + +.ec-page b.page-n { + background-image: none; + background-color: #FFF; + color: #000; + font-weight: bold; +} + +.ec-page { + color: #326700; + margin-top: 10px +} + +.ec-page em { + font-style: normal; + color: #000; + padding: 0 3px; +} + +.target-page { + width: 25px; +} + +/* 弹出菜单 */ +.ec-popup { + background-color: #DCEFD1; + border: 1px solid #9CD167; + border-width: 1px 1px 0 1px; + width: 70px; +} + +.ec-popup-item { + background-color: #DCEFD1; /* width:70px; */ + height: 25px; + line-height: 25px; + border-bottom: 1px solid #9CD167; + padding-left: 24px; + cursor: pointer; + vertical-align: bottom; + position: relative; +} + +.ec-popup-item-over { + background-color: #FFFCE2; +} + +.ec-popup-item .ec-checkbox { + /*float:left;*/ + /*margin:4px 4px 0 4px;*/ + position: absolute; + top: 4px; + left: 4px; + border: 0 none; /*text-indent: 14px;*/ +} + +.cb-ctnr { + background: #DCEFD1 url("img/table.gif") 0 -200px; + height: 14px; + margin: 0; + border: 0 none; + width: 15px; + position: absolute; + top: 7px; + cursor: pointer; +} + +/* 提示信息显示 */ +.tb-msg { + visibility: hidden; + margin: 0 0 4px 0; +} + +.tb-msg .tb-msg-txt { + background: #FFFCE2; + color: #D2691E; + font-weight: bold; + padding: 0 4px; + display: inline-block; + *display: inline; + zoom: 1; + height: 20px; + line-height: 20px; +} + +.tb-msg .clo-btn { + font-weight: normal; + margin: 0 0 0 14px; + cursor: pointer; +} + +/* 二次屏蔽的提示框 */ +.ectable-modal-tip { + background: #FFF; + position: absolute; + width: 200px; + height: 50px; + border: 2px solid #CCC +} + +.ectable-modal-tip-title { + position: absolute; + height: 20px; + line-height: 20px; + text-indent: 5px; + margin: 0; + display: block; + top: 0; + left: 0; + background: #CCC; + width: 100% +} + +.ectable-modal-tip-cont { + padding: 25px 5px 5px 25px; + background: transparent url(img/loading.gif) no-repeat scroll 5px 25px +} + +/* 打印 */ +@media screen { + .ec-print-table { + border: 1px solid #9CD167; + border-width: 1px; + border-collapse: collapse; + background-color: #DCEFD1 + } + + .ec-print-table th, .ec-print-table td { + border: 1px solid #9CD167; + border-width: 0 0 1px 1px; + } + + .ec-print-table td { + background-color: #FFF; + } +} + +@media print { + body { + font-family: "微软雅黑", "黑体"; + font-size: 10px; + } + + .strik-info { + color: #000; + } + + .noprint, .nav { + display: none; + } + + .area-v, .area-w { + display: none; + } + + .area { + border: 1px solid #ddd; + margin-top: 6px; + background: #fff; + } + + .mess-query .area-inner { + background: none; + border: 0; + } + + .mess-query .area { + border: 0; + } + + .area h5 { + border: 0; + } + + .area h5 b { + background: none; + border: 0; + color: #000; + } + + .old td { + background: #ddd; + } + + .ec-print-table { + border: 1px solid #666; + border-width: 1px 0 1px 1px; + border-collapse: collapse + } + + .ec-print-table th { + padding: 2px; + text-align: center; + border-right: 1px solid #666; + border-color: #666 + } + + .ec-print-table td { + padding: 2px 6px; + border: 1px solid #666; + border-width: 1px 1px 0 0; + border-color: #666 + } + + * { + word-wrap: break-word; + word-break: break-all; + } +} + diff --git a/WebContent/stat/js/ui/table/js/.svn/all-wcprops b/src/main/webapp/stat/js/ui/table/js/.svn/all-wcprops similarity index 100% rename from WebContent/stat/js/ui/table/js/.svn/all-wcprops rename to src/main/webapp/stat/js/ui/table/js/.svn/all-wcprops diff --git a/WebContent/stat/js/ui/table/js/.svn/entries b/src/main/webapp/stat/js/ui/table/js/.svn/entries similarity index 100% rename from WebContent/stat/js/ui/table/js/.svn/entries rename to src/main/webapp/stat/js/ui/table/js/.svn/entries diff --git a/WebContent/stat/js/ui/table/js/.svn/text-base/ecomui.table.js.svn-base b/src/main/webapp/stat/js/ui/table/js/.svn/text-base/ecomui.table.js.svn-base similarity index 100% rename from WebContent/stat/js/ui/table/js/.svn/text-base/ecomui.table.js.svn-base rename to src/main/webapp/stat/js/ui/table/js/.svn/text-base/ecomui.table.js.svn-base diff --git a/src/main/webapp/stat/js/ui/table/js/ecomui.table.js b/src/main/webapp/stat/js/ui/table/js/ecomui.table.js new file mode 100644 index 000000000..1ac6cc02a --- /dev/null +++ b/src/main/webapp/stat/js/ui/table/js/ecomui.table.js @@ -0,0 +1,571 @@ +var ecomui = ecomui || {}; + +// IE 6 背景图片缓存 +try { + document.execCommand("BackgroundImageCache", false, true); +} catch (e) { +} + +(function () { + var lib = baidu, + core = ecui, + dom = core.dom, + ui = core.ui, + util = core.util, + inherits = util.inherits, + copy = util.copy, + toNumber = util.toNumber, + get = core.get, + query = core.query, + setStyles = lib.dom.setStyles, + getPosition = dom.getPosition, + calcHeightRevise = core.calcHeightRevise, + + DOCUMENT = document, + UI_TABLE = ui.LockedTable, + UI_TABLE_CLASS = UI_TABLE.prototype, + UI_CONTROL = ui.Control, + ECOM_TABLE_CLASS; + + ecomui.Table = ui.EcomTable = function (el, params) { + /* + * 计算表格宽度 + */ + var tbEl = el.getElementsByTagName("table")[0]; + if (!tbEl.style.width) { + var colEls = tbEl.rows[0].cells; + var tbOldWidth = tbEl.offsetWidth; + var tbWidth = 0; + + for (var i = 0, len = colEls.length; i < len; i++) { + var o = colEls[i].style.width; + tbWidth += (o !== undefined) ? + (/px$/.test(o) ? parseInt(o, 10) : tbOldWidth * (parseFloat(o) / 100)) : + 130; + } + tbEl.style.width = Math.max(el.offsetWidth * 0.99, tbWidth) + "px"; + } + + //隐藏待渲染的表格, 在vm里定义visibility=hidden + //渲染表格 + UI_TABLE.call(this, el, params); + + //显示渲染好的表格 + this.getOuter().style.visibility = "visible"; + + //记录表格索引 + this._nTbId = params.tbid; + + //是否有选择整列表按钮 + this._bCustom = params.custom; + + var colToggler, verticalBar, showOpColumn, colCount; + + showOpColumn = params.rightLock; + + //如果有操作列 + if (showOpColumn) { + //初始操作列是展开的 + this._bOpColumnUnfolded = true; + + var base = this.getBase(); + + //记住操作列和前一列 + //TODO 倒数第二列不能作为部件, 因为不是表格不可缺少的 + //在使用时取一下 + //colCount = this._aCol.length - 1; + //this._uOpColumn = this.getCol(colCount); + + //收缩按钮 + var el = DOCUMENT.createElement("div"); + el.className = "ec-col-toggler"; + base.appendChild(el); + colToggler = this._uColToggler + = core.$fastCreate( + UI_CONTROL, + el, + this, + {} + ); + + //竖条 + var el = DOCUMENT.createElement("div"); + el.innerHTML = "
    "; + el.className = "ec-v-toggler"; + base.appendChild(el); + verticalBar = this._uVerticalBar + = core.$fastCreate( + UI_CONTROL, + el, + this, + {} + ); + verticalBar.hide(); + + //如果有纵向滚动条, 调整收缩按钮的位置 + //FIXME 此时VScroll总是有的 + var vScroll = this.$getSection("VScroll"); + colToggler.getOuter().style.right = 2 + + ((vScroll && vScroll.isShow()) ? vScroll.getWidth() : 0) + "px"; + //绑定事件 + colToggler.onclick = colTogglerClick; + verticalBar.onclick = vBarClick; + verticalBar.show = vBarShow; + + } + + //浮动表头 + if (params.floatthead) { + var self = this; + self._bFloatThead = true; + lib.event.on(window, "scroll", function () { + floatThead(self); + }); + } + + + }; + + ECOM_TABLE_CLASS = inherits(ui.EcomTable, UI_TABLE); + + /* + * 此处获得操作列 + */ + ECOM_TABLE_CLASS.$init = function () { + UI_TABLE_CLASS.$init.call(this); + if (this._nRightLock) { + this._uOpColumn = this.getCol(this._aCol.length - 1); + } + + //整列表选择按钮 + if (this._bCustom) { + var customBtn = core.get("cbCtnr_" + this._nTbId); + customBtn && initCustomBtn(customBtn, this); + } + }; + + /** + * 展开/收起按钮点击 + * @private + */ + function colTogglerClick() { + //this为按钮 + var table = this.getParent(), + vBar = table.$getSection("VerticalBar"); + + if (table._bOpColumnUnfolded) { + //收起操作列 + foldOpColumn(table); + vBar.show(); + this.alterClass("o"); + } else { + //展开操作列 + unfoldOpColumn(table); + vBar.hide(); + this.alterClass("o", true); + } + } + + /** + * 竖条点击 + * @private + */ + function vBarClick() { + //this 为竖条 + var table = this.getParent(); + + //展开操作列 + unfoldOpColumn(table); + + this.hide(); + } + + /** + * 收起操作列 + * @private + */ + function foldOpColumn(table) { + var tableWidth = table.getWidth(), + tableBodyWidth = table.getBody().offsetWidth; + + table._uOpColumn.hide(); + + //设置倒数第二列的宽度 + var col = table.getCol(table.getCols().length - 2); + col.setSize(col.getWidth() + table._uOpColumn.getWidth()); + + table._bOpColumnUnfolded = false; + }; + + /** + * 展开操作列 + * @private + */ + function unfoldOpColumn(table) { + var prevCol = getSndLastCol(table); + + //恢复倒数第二列恢复原来的宽度 + var col = table.getCol(table.getCols().length - 2); + col.setSize(col.getWidth() - table._uOpColumn.getWidth()); + + table._uOpColumn.show(); + + + table._bOpColumnUnfolded = true; + }; + + /** + * 获得倒数第二列 + * @private + */ + function getSndLastCol(table) { + var colCount = table._aCol.length - 1, + ret; + while (colCount--) { + ret = table.getCol(colCount); + if (ret.isShow()) { + break; + } + } + return ret; + } + + /** + * 展开/收缩操作列时设置表格宽度 + * @private + */ + function setTableWidth(table, tableWidth, tableBodyWidth) { + var oldWidth = table._nOldWidth = table.getWidth(); + if (tableWidth > tableBodyWidth) { + table.setSize(oldWidth + table) + } + } + + /** + * 显示竖条 + * @private + */ + function vBarShow() { + UI_CONTROL.prototype.show.call(this); + setVBarPosition(this); + setVBarHeight(this); + } + + /** + * 设置竖条定位 + * @private + */ + function setVBarPosition(vBar) { + var table = vBar.getParent(), + vBarWidth = vBar.getWidth(), + vs = table.$getSection("VScroll"), + style = table.getBase().style, + contentWidth = table.getWidth() + - (toNumber(style.borderLeftWidth) + toNumber(style.borderRightWidth)); + + vBar.getOuter().style.left = contentWidth - vBarWidth + - ((vs && vs.isShow()) ? vs.getWidth() : 0) + + "px"; + } + + + /** + * 在竖条显示时设置其高度 + * @private + */ + function setVBarHeight(vBar) { + var table = vBar.getParent(), + hs = table.$getSection("HScroll"), + th = table.$getSection("Head"), + hscrValue; + + if (hs && hs.isShow()) {//存在水平滚动条 + hs.setValue(hs.getTotal()); + hscrValue = hs.isShow() ? hs.getHeight() : 0; + } + else { + hscrValue = 0; + } + + //TODO -2 用 sumStyle算边框值 + vBar.setSize(0, table.getHeight() - th.getHeight() - 2 - hscrValue); + var style = vBar.getOuter().style; + style.bottom = hscrValue + "px"; + } + + /** + * 表头随浏览器滚动条锁定 + * @private + */ + function floatThead(t) { + var headEl = t._uHead.getOuter(), + lockedHeadEl = t._uLockedHead.getOuter(), + lockedMainEl = t._uLockedMain.getOuter(); + + if (t._uColToggler) { + var colTogglerEl = t._uColToggler.getOuter(); + } + + var outer = t.getOuter(); + + var scrollTop = DOCUMENT.body.scrollTop || DOCUMENT.documentElement.scrollTop, + pos = getPosition(outer), + top = pos.top + 1, + left = pos.left; + + var headHeight = headEl.offsetHeight + calcHeightRevise(headEl), + tbHeightDelta = t.getHeight() - headHeight, + relativeTop = scrollTop - top; + + var floatStyles = { + position: "absolute", + top: relativeTop + "px", + zIndex: 999 + }; + + if (scrollTop + && relativeTop > 0 + && relativeTop < tbHeightDelta) { + setStyles(headEl, floatStyles); + setStyles(lockedHeadEl, floatStyles); + setStyles(lockedMainEl, {top: headHeight + "px"}); + + //TODO 此处性能优化 + //ecui 1.1.0 fix + setStyles(lockedHeadEl, {width: lockedHeadEl.getElementsByTagName("table")[0].style.width}); + + if (colTogglerEl) { + setStyles(colTogglerEl, {top: 2 + relativeTop + "px", zIndex: 999}); + } + } + + else { + setStyles(headEl, {top: 0, zIndex: 0}); + setStyles(lockedHeadEl, {position: "static", zIndex: 0}); + setStyles(lockedMainEl, {top: ""}); + + if (colTogglerEl) { + setStyles(colTogglerEl, {top: "", zIndex: 0}); + } + } + }; + + /** + * 初始化整列表选择按钮 + */ + function initCustomBtn(customBtn, table) { + var tbId = table._nTbId; + + var popup = core.get("cbPop_" + tbId), + popupItems = core.query({"parent": popup}), + popupItemsLen = popupItems.length; + + var cbCurList = core.get("cball_" + tbId), + cbWholeList = core.get("cbsall_" + tbId), + cbCurInferiors = cbCurList.getInferiors(); + + DOCUMENT.body.appendChild(popup.getOuter()); + + customBtn.onclick = function () { + var containerOuter = this.getOuter(); + containerPos = getPosition(containerOuter); + + popup.setPosition( + containerPos.left + this.getBodyWidth(), + containerPos.top + ); + + popup.show(); + }; + + cbWholeList.onclick = (function () { + var checked = false; + return function () { + var i = cbCurInferiors.length, + msg = [ + "已选择整列表, 子项目不能取消选择", + "已取消选择整列表" + ]; + + var msgBox = table.setMsg((!checked) ? msg[0] : msg[1]); + + msgBox.parentNode.parentNode.style.visibility = "visible"; + + var hcbsall = lib.dom.g("hcbsall_" + tbId); + while (i--) { + cbCurInferiors[i].setChecked(!checked); + cbCurList.setEnabled(checked); + cbCurInferiors[i].setEnabled(checked); + hcbsall.value = checked ? 0 : 1; + } + + checked = !checked; + } + })(); + + while (popupItemsLen--) { + popupItems[popupItemsLen].onclick = function () { + var cb = core.query({"parent": this})[0]; + cb.click(); + }; + } + } + + /** + * 改写$resize方法 + */ + ECOM_TABLE_CLASS.$resize = function () { + UI_TABLE_CLASS.$resize.call(this); + + //如果存在竖条并且竖条显示, 重设其高度 + var vBar = this._uVerticalBar; + if (vBar && vBar.isShow()) { + setVBarHeight(vBar); + setVBarPosition(vBar); + } + + //修正浮动表头的位置 + if (this._bFloatThead) { + floatThead(this); + } + }; + + /** + * 找出table中被选中行 + * @public + * + * @return {Array} 被选中行 + */ + ECOM_TABLE_CLASS.getChecked = function () { + var ret = []; + try { + var col = this.getCol(0), + cbs = core.get("cball_" + this._nTbId), + cbs = (cbs instanceof core.ui.Checkbox) ? cbs : core.query({"parent": cbs})[0], + cbs = cbs.getInferiors(), + i = cbs.length; + + while (i--) { + if (cbs[i].isChecked()) { + ret.push(cbs[i].getParent()); + } + } + } catch (e) { + } + return ret; + }; + + /** + * 找出table中被选中行个数 + * @public + * + * @return {Number} 被选中行的个数 + */ + ECOM_TABLE_CLASS.getCheckedCount = function () { + return this.getChecked().length; + }; + + /** + * 设置消息 + * @public + * + * @return {HTMLElement} 消息div元素 + */ + ECOM_TABLE_CLASS.setMsg = function (msg) { + var msgBox = lib.dom.g("tbMsg_" + this._nTbId); + dom.setText(msgBox, msg); + return msgBox; + }; +})(); + +/* + * 排序 + */ +var defaultSort = (function () { + // 屏蔽二次点击标志 + var dbClickFlag = false; + + return function () { + if (!dbClickFlag) { + window.sortClick(this.getBase().getAttribute('sort')); + dbClickFlag = true; + } + else { + ecTable.showModal("正在排序, 请稍候..."); + } + } +})(); + +/** + * 为兼容以前版本加的补丁 + */ +var ecTable = { + getChecked: function (table) { + return ecomui.Table.prototype.getChecked.call(table, table); + }, + getCheckedCount: function (table) { + return ecomui.Table.prototype.getCheckedCount.call(table, table); + } +}; + +ecui.getChildren = function (control) { + return ecui.query({parent: control}); +}; + +/** + * 整体遮罩, 用于屏蔽二次点击 + */ +var ecTable = ecTable || {}; + +ecTable.showModalTip = function (text) { + var modalCtrl = baidu.dom.g("ecTableModalTip"); + modalCtrl = modalCtrl && modalCtrl.getControl(); + + // 创建提示信息窗体 + if (!modalCtrl) { + modalCtrl = document.createElement("div"); + modalCtrl.id = "ecTableModalTip" + modalCtrl.className = "ectable-modal-tip"; + modalCtrl.style.visibility = "hidden"; + modalCtrl.innerHTML = [ + '', + '
    ' + ].join(""); + document.body.appendChild(modalCtrl); + + modalCtrl = ecui.$fastCreate( + ecui.ui.Form, + modalCtrl, + null, + {hide: true} + ); + } + + // 给窗体设置文字并显示 + var contEl = modalCtrl.getBody().getElementsByTagName("div")[0]; + ecui.dom.setText(contEl, text); + modalCtrl.getOuter().style.zIndex = 32768; + + + // 窗体居中 + var viewWidth = baidu.page.getViewWidth(), + viewHeight = baidu.page.getViewHeight(), + width = modalCtrl.getWidth(), + height = modalCtrl.getHeight(); + + baidu.setStyles(modalCtrl.getOuter(), { + position: "absolute", + left: Math.max(viewWidth - width, 0) / 2, + top: Math.max(viewHeight - height, 0) / 2 + }); + + modalCtrl.getOuter().style.visibility = ""; + ecui.mask(0.03); + + // 五秒没反应显示刷新链接 + setTimeout(function () { + contEl.innerHTML = '好像没响应? 请刷新'; + }, 5000); + +}; + diff --git a/src/main/webapp/stat/js/ui/table/js/table.js b/src/main/webapp/stat/js/ui/table/js/table.js new file mode 100644 index 000000000..fe35a7fac --- /dev/null +++ b/src/main/webapp/stat/js/ui/table/js/table.js @@ -0,0 +1,323 @@ +/** + *@file support_table.js + *@description 支持模块使用ecui实现的列表 + * + * 修改记录 + * 2010.01.07 加入当前页或者整列表的选择(样式) + */ + +/* + * IE 6 背景图片缓存 + */ +try { + document.execCommand("BackgroundImageCache", false, true); +} catch (e) { +} + +/* + *滚动条装饰器 + */ +ecui.ui.VScroll.prototype.$create = function () { + var me = this, + block = this.$getSection('Block'); + new ecui.ext.TBDecorator(block, 'vsblockdtr'); + ecui.ui.Control.prototype.$create.call(this); +}; + +ecui.ui.HScroll.prototype.$create = function () { + var block = this.$getSection('Block'); + new ecui.ext.LRDecorator(block, 'hsblockdtr'); + ecui.ui.Control.prototype.$create.call(this); +}; + + +function initEcuiTable(table) { + var t = table || ecui.get(table), + vs = t.$getSection('VScroll'), + hs = t.$getSection('HScroll'), + th = t.$getSection('Head'), + cCount = t._aCol.length - 1, + col = t.getCol(cCount), + prevCol = t.getCol(cCount - 1); + + //此时重绘,防止火狐下高度异常 + //t.paint(); + + /* + * 展开/收起按钮 + */ + //TODO 判断是否含有操作列 + if (col.getBase().parentNode != prevCol.getBase().parentNode) { + //收缩按钮 + var ct = ecui.create('Control', { + type: 'ec-col-toggler', + parent: t.getBase() + }), + + //竖条 + h = ecui.create('Control', { + type: 'ec-v-toggler', + parent: t.getBase() + }), + + cw = col.getWidth(), + pw = prevCol.getWidth(), + hscrValue; + + h.getBody().innerHTML = '
    ' + h.hide(); + h.onclick = function () { + ct.click(); + }; + + ct.onclick = function () { + toggleStatus(this); + vs && vs.paint(); + //col.paint(); + }; + ct.onpaint = function () { + setHbarHeight(h); + //alert("paint col toggler") + } + + //根据是否有滚动条设置按钮位置 + if (vs && vs.isShow()) { + ct.getBase().style.right = vs.getWidth() + "px"; + } + /* + * 设置竖条高度 + */ + var setHbarHeight = function (hbar) { + if (hs) {//存在水平滚动条 + hs.setValue(hs.getTotal()); + hscrValue = hs.isShow() ? hs.getHeight() : 0; + } + else { + hscrValue = 0; + } + hbar.setSize(undefined, t.getHeight() - th.getHeight() - 2 - hscrValue); + var style = hbar.getOuter().style; + if (vs && vs.isShow()) style.right = vs.getWidth() + "px"; + style.bottom = hscrValue + "px"; + } + + /* + * 点击'收起按钮'的回调函数 + */ + var toggleStatus = function (ct) { + + //hack:避免第一次隐藏列后对不齐 + prevCol.setSize(pw); + + if (col.isShow()) { + _autoSize(t, prevCol, pw); + ct.alterClass('o'); + col.hide(); + setHbarHeight(h); + h.show(); + } else { + prevCol.setSize(pw); + ct.alterClass('o', true); + //console.log(hscrValue); + col.show(); + h.hide(); + hs && hs.setValue(hs.getTotal()); + } + + col.paint(); + }; + + /* + * 表格列自适应宽度 + */ + var _autoSize = function (t, c, ow) { + var tw = t.getWidth(), + tcw = t.getBody().offsetWidth; + if (tw > tcw) { + c.setSize(tw - tcw + ow); + } + }; + } + + /* + * 垂直滚动条高度 + + if (vs) { + _setVSHeight = function(vs) { + vs.setSize(undefined, vs.getHeight() - th.getHeight()); + vs.getBase().style.top = ""; + vs.getBase().style.bottom = vs.getWidth() + "px"; + } + vs.onpaint = function() { + this.$paint(); + _setVSHeight(this); + document.body.className = document.body.className; + return false; + } + _setVSHeight(vs); + } + */ + + /* + * 排序-记录水平位置 + + var ectable_xpos = baidu.cookie.getRaw('ectable_xpos'); + if (ectable_xpos) { + hs.setValue(ectable_xpos); + baidu.cookie.remove('ectable_xpos'); + } + */ + + /* + * 排序 + */ + var defaultSort = function () { + window.sortClick(this.getBase().getAttribute('sort')); + baidu.cookie.setRaw('ectable_xpos', hs.getValue()); + }; + + for (var i = 0, cCount = t._aCol.length; i < cCount; i++) { + var col = t.getCol(i); + if (col.getBase().className.match(/\s*sort\s*/)) { + col.onclick = defaultSort; + } + } + + //hack for ie 8 + //document.body.className = document.body.className; + + + /* + * custom checkbox处理 + */ + + var popupContainer = ecui.query({"parent": t.getCol(0)})[0]; + + if (popupContainer) { + var ctrlIdx = popupContainer.getBase().id + .replace(/^s+|s+$/, '') + .match(/cbCtnr_([0-9a-zA-Z_]+)/)[1], + //弹出菜单容器和弹出菜单 + popup = document.getElementById('cbPop_' + ctrlIdx).getControl(), + popupItems = ecui.query({"parent": popup}), + popupItemsLen = popupItems.length, + + //checkbox 控件 + cbCurList = document.getElementById("cbCurList").getControl(), + cbWholeList = document.getElementById("cbWholeList").getControl(), + cbCurInferiors = cbCurList.getInferiors(); + //msgBox = document.getElementById('tbMsg_' + ctrlIdx); + + + popupContainer.onclick = function () { + var containerOuter = this.getOuter(); + containerPos = ecui.dom.getPosition(containerOuter); + + popup.setPosition(containerPos.left + this.getBodyWidth(), containerPos.top); + + popup.show(); + }; + + cbWholeList.onclick = (function () { + var checked = false; + return function () { + //console.log("xx"); + var i = cbCurInferiors.length, + msg = [ + "已选择整列表, 子项目不能取消选择", + "已取消选择整列表" + ]; + + var msgBox = ecTable.setMsg(t, (!checked) ? msg[0] : msg[1]); + msgBox.style.visibility = "visible"; + + while (i--) { + cbCurInferiors[i].setChecked(!checked); + cbCurList.setEnabled(checked); + cbCurInferiors[i].setEnabled(checked); + } + + checked = !checked; + } + })(); + + while (popupItemsLen--) { + popupItems[popupItemsLen].onclick = function () { + var cb = ecui.query({"parent": this})[0]; + cb.click(); + }; + } + + } +} +var ecTable = { + /** + * 给表格的消息框设置 + * @param {ecTable} table + * @param {String} msg + * @return {String} 消息框 + */ + setMsg: function (table, msg) { + var msgBox = table.getBase(), + first = ecui.dom.first; + + do { + msgBox = msgBox.previousSibling; + } while (msgBox.nodeType != 1) + + first(first(msgBox)).innerHTML = msg; + return msgBox; + }, + + /** + *找出table中被选中条目 + *@param {ecTable} table + *@return {Array} 被选中行 + */ + getChecked: function (table) { + var col = table.getCol(0), + cbs = ecui.query({"parent": col})[0], + cbs = (cbs instanceof ecui.ui.Checkbox) ? cbs : ecui.query({"parent": cbs})[0], + cbs = cbs.getInferiors(), + i = cbs.length, + ret = []; + + while (i--) { + if (cbs[i].isChecked()) { + ret.push(cbs[i].getParent()); + } + } + + return ret; + }, + /** + *获得table中有选中条目个数 + *@param {EcTable} table + *@return {Number} 选中条目个数 + */ + getCheckedCount: function (table) { + return ecTable.getChecked(table).length; + }, + + /** + * 获得当前页面所有table + * @return 包含所有table的数组 + */ + getTables: function () { + return ecui.query({"type": ecui.ui.Table}); + }, + + /** + *初始化当前页所有列表 + */ + init: function () { + var tables = ecTable.getTables(), + len = tables.length; + + while (len--) { + initEcuiTable(tables[len]); + } + } +}; + +ecui.dom.ready(ecTable.init); diff --git a/WebContent/stat/js/ui/wick/css/wick.css b/src/main/webapp/stat/js/ui/wick/css/wick.css similarity index 80% rename from WebContent/stat/js/ui/wick/css/wick.css rename to src/main/webapp/stat/js/ui/wick/css/wick.css index 97315c382..ca456051a 100644 --- a/WebContent/stat/js/ui/wick/css/wick.css +++ b/src/main/webapp/stat/js/ui/wick/css/wick.css @@ -14,35 +14,40 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ .wickFloater { -position:absolute; -z-index:2; -display:none; -padding:0; + position: absolute; + z-index: 2; + display: none; + padding: 0; } .wickFloater td { -background-color:white; -border:1px inset #979797; -color:black; + background-color: white; + border: 1px inset #979797; + color: black; } .matchedSmartInputItem { -font-size:12px; -padding: 5px 10px 1px 5px; -margin:0; -cursor:pointer; + font-size: 12px; + padding: 5px 10px 1px 5px; + margin: 0; + cursor: pointer; } .selectedSmartInputItem { -color:white; -background-color:#3875D7; + color: white; + background-color: #3875D7; } #smartInputResults { -padding:0;margin:0; + padding: 0; + margin: 0; } .siwCredit { -margin:0;padding:0;margin-top:10px;font-size:12px;color:black; + margin: 0; + padding: 0; + margin-top: 10px; + font-size: 12px; + color: black; } diff --git a/src/main/webapp/stat/js/ui/wick/js/wick.js b/src/main/webapp/stat/js/ui/wick/js/wick.js new file mode 100644 index 000000000..d164cf5ae --- /dev/null +++ b/src/main/webapp/stat/js/ui/wick/js/wick.js @@ -0,0 +1,482 @@ +function freezeEvent(e) { + if (e.preventDefault) e.preventDefault(); + e.returnValue = false; + e.cancelBubble = true; + if (e.stopPropagation) e.stopPropagation(); + return false; +}//freezeEvent + +function isWithinNode(e, i, c, t, obj) { + answer = false; + te = e; + while (te && !answer) { + if ((te.id && (te.id == i)) || (te.className && (te.className == i + "Class")) + || (!t && c && te.className && (te.className == c)) + || (!t && c && te.className && (te.className.indexOf(c) != -1)) + || (t && te.tagName && (te.tagName.toLowerCase() == t)) + || (obj && (te == obj)) + ) { + answer = te; + } else { + te = te.parentNode; + } + } + return te; +}//isWithinNode + +function getEvent(event) { + return (event ? event : window.event); +}//getEvent() + +function getEventElement(e) { + return (e.srcElement ? e.srcElement : (e.target ? e.target : e.currentTarget)); +}//getEventElement() + +function findElementPosX(obj) { + curleft = 0; + if (obj.offsetParent) { + while (obj.offsetParent) { + curleft += obj.offsetLeft; + obj = obj.offsetParent; + } + }//if offsetParent exists + else if (obj.x) + curleft += obj.x + return curleft; +}//findElementPosX + +function findElementPosY(obj) { + curtop = 0; + if (obj.offsetParent) { + while (obj.offsetParent) { + curtop += obj.offsetTop; + obj = obj.offsetParent; + } + }//if offsetParent exists + else if (obj.y) + curtop += obj.y + return curtop; +}//findElementPosY + +/* end dhtml building blocks */ + +function handleKeyPress(event) { + e = getEvent(event); + eL = getEventElement(e); + + upEl = isWithinNode(eL, null, "wickEnabled", null, null); + + kc = e["keyCode"]; + + if (siw && ((kc == 13) || (kc == 9))) { + siw.selectingSomething = true; + if (siw.isSafari) siw.inputBox.blur(); //hack to "wake up" safari + siw.inputBox.focus(); + siw.inputBox.value = siw.inputBox.value.replace(/[ \r\n\t\f\s]+$/gi, ' '); + hideSmartInputFloater(); + } else if (upEl && (kc != 38) && (kc != 40) && (kc != 37) && (kc != 39) && (kc != 13) && (kc != 27)) { + if (!siw || (siw && !siw.selectingSomething)) { + processSmartInput(upEl); + } + } else if (siw && siw.inputBox) { + siw.inputBox.focus(); //kinda part of the hack. + } + +}//handleKeyPress() + + +function handleKeyDown(event) { + e = getEvent(event); + eL = getEventElement(e); + + if (siw && (kc = e["keyCode"])) { + if (kc == 40) { + siw.selectingSomething = true; + freezeEvent(e); + if (siw.isGecko) siw.inputBox.blur(); + /* Gecko hack */ + selectNextSmartInputMatchItem(); + } else if (kc == 38) { + siw.selectingSomething = true; + freezeEvent(e); + if (siw.isGecko) siw.inputBox.blur(); + selectPreviousSmartInputMatchItem(); + } else if ((kc == 13) || (kc == 9)) { + siw.selectingSomething = true; + activateCurrentSmartInputMatch(); + freezeEvent(e); + } else if (kc == 27) { + hideSmartInputFloater(); + freezeEvent(e); + } else { + siw.selectingSomething = false; + } + } + +}//handleKeyDown() + +function handleFocus(event) { + e = getEvent(event); + eL = getEventElement(e); + if (focEl = isWithinNode(eL, null, "wickEnabled", null, null)) { + if (!siw || (siw && !siw.selectingSomething)) processSmartInput(focEl); + } +}//handleFocus() + +function handleBlur(event) { + e = getEvent(event); + eL = getEventElement(e); + if (blurEl = isWithinNode(eL, null, "wickEnabled", null, null)) { + if (siw && !siw.selectingSomething) hideSmartInputFloater(); + } +}//handleBlur() + +function handleClick(event) { + e2 = getEvent(event); + eL2 = getEventElement(e2); + if (siw && siw.selectingSomething) { + selectFromMouseClick(); + } +}//handleClick() + +function handleMouseOver(event) { + e = getEvent(event); + eL = getEventElement(e); + if (siw && (mEl = isWithinNode(eL, null, "matchedSmartInputItem", null, null))) { + siw.selectingSomething = true; + selectFromMouseOver(mEl); + } else if (isWithinNode(eL, null, "siwCredit", null, null)) { + siw.selectingSomething = true; + } else if (siw) { + siw.selectingSomething = false; + } +}//handleMouseOver + +function showSmartInputFloater() { + if (!siw.floater.style.display || (siw.floater.style.display == "none")) { + if (!siw.customFloater) { + x = findElementPosX(siw.inputBox); + y = findElementPosY(siw.inputBox) + siw.inputBox.offsetHeight; + //hack: browser-specific adjustments. + if (!siw.isGecko && !siw.isWinIE) x += 8; + if (!siw.isGecko && !siw.isWinIE) y += 10; + siw.floater.style.left = x; + siw.floater.style.top = y; + } else { + //you may + //do additional things for your custom floater + //beyond setting display and visibility + } + siw.floater.style.display = "block"; + siw.floater.style.visibility = "visible"; + } +}//showSmartInputFloater() + +function hideSmartInputFloater() { + if (siw) { + siw.floater.style.display = "none"; + siw.floater.style.visibility = "hidden"; + siw = null; + }//siw exists +}//hideSmartInputFloater + +function processSmartInput(inputBox) { + if (!siw) siw = new smartInputWindow(); + siw.inputBox = inputBox; + + classData = inputBox.className.split(" "); + siwDirectives = null; + for (i = 0; (!siwDirectives && classData[i]); i++) { + if (classData[i].indexOf("wickEnabled") != -1) + siwDirectives = classData[i]; + } + + if (siwDirectives && (siwDirectives.indexOf(":") != -1)) { + siw.customFloater = true; + newFloaterId = siwDirectives.split(":")[1]; + siw.floater = document.getElementById(newFloaterId); + siw.floaterContent = siw.floater.getElementsByTagName("div")[0]; + } + + + setSmartInputData(); + if (siw.matchCollection && (siw.matchCollection.length > 0)) selectSmartInputMatchItem(0); + var content = content || null; + content = getSmartInputBoxContent(); + if (content) { + modifySmartInputBoxContent(content); + showSmartInputFloater(); + } else { + hideSmartInputFloater(); + } +}//processSmartInput() + +function smartInputMatch(cleanValue, value) { + this.cleanValue = cleanValue; + this.value = value; + this.isSelected = false; +}//smartInputMatch + +function simplify(s) { + return s.toLowerCase().replace(/^[ \s\f\t\n\r]+/, '').replace(/[ \s\f\t\n\r]+$/, ''); +//.replace(/[?,?,?,?,\u00E9,\u00E8,\u00EA,\u00EB]/gi,"e").replace(/[?,?,\u00E0,\u00E2]/gi,"a"). +}//simplify + +function getUserInputToMatch(s) { + a = s; + fields = s.split(","); + if (fields.length > 0) a = fields[fields.length - 1]; + return a; +}//getUserInputToMatch + +function getUserInputBase() { + s = siw.inputBox.value; + a = s; + if ((lastComma = s.lastIndexOf(",")) != -1) { + a = a.replace(/^(.*\,[ \r\n\t\f\s]*).*$/i, '$1'); + } + else { + a = ""; + } + return a; +}//getUserInputBase() + +function runMatchingLogic(userInput, standalone) { + userInput = simplify(userInput); + uifc = userInput.charAt(0).toLowerCase(); + if (uifc == '"') uifc = (n = userInput.charAt(1)) ? n.toLowerCase() : "z"; + if (standalone) userInput = uifc; + if (siw) siw.matchCollection = new Array(); + pointerToCollectionToUse = collection; + if (siw && siw.revisedCollection && (siw.revisedCollection.length > 0) && siw.lastUserInput && (userInput.indexOf(siw.lastUserInput) == 0)) { + pointerToCollectionToUse = siw.revisedCollection; + } else if (collectionIndex[userInput] && (collectionIndex[userInput].length > 0)) { + pointerToCollectionToUse = collectionIndex[userInput]; + } else if (collectionIndex[uifc] && (collectionIndex[uifc].length > 0)) { + pointerToCollectionToUse = collectionIndex[uifc]; + } else if (siw && (userInput.length == 1) && (!collectionIndex[uifc])) { + siw.buildIndex = true; + } else if (siw) { + siw.buildIndex = false; + } + + tempCollection = new Array(); + + re1m = new RegExp("^([ \"\>\<\-]*)(" + userInput + ")", "i"); + re2m = new RegExp("([ \"\>\<\-]+)(" + userInput + ")", "i"); + re1 = new RegExp("^([ \"\}\{\-]*)(" + userInput + ")", "gi"); + re2 = new RegExp("([ \"\}\{\-]+)(" + userInput + ")", "gi"); + + for (i = 0, j = 0; (i < pointerToCollectionToUse.length); i++) { + displayMatches = ((!standalone) && (j < siw.MAX_MATCHES)); + entry = pointerToCollectionToUse[i]; + mEntry = simplify(entry); + if (!standalone && (mEntry.indexOf(userInput) == 0)) { + userInput = userInput.replace(/\>/gi, '\\}').replace(/\< ?/gi, '\\{'); + re = new RegExp("(" + userInput + ")", "i"); + if (displayMatches) { + siw.matchCollection[j] = new smartInputMatch(entry, mEntry.replace(/\>/gi, '}').replace(/\< ?/gi, '{').replace(re, "$1")); + } + tempCollection[j] = entry; + j++; + } else if (mEntry.match(re1m) || mEntry.match(re2m)) { + if (!standalone && displayMatches) { + siw.matchCollection[j] = new smartInputMatch(entry, mEntry.replace(/\>/gi, '}').replace(/\$2").replace(re2, "$1$2")); + } + tempCollection[j] = entry; + j++; + } + }//loop thru collection + if (siw) { + siw.lastUserInput = userInput; + siw.revisedCollection = tempCollection.join(",").split(","); + collectionIndex[userInput] = tempCollection.join(",").split(","); + } + if (standalone || siw.buildIndex) { + collectionIndex[uifc] = tempCollection.join(",").split(","); + if (siw) siw.buildIndex = false; + } +}//runMatchingLogic + +function setSmartInputData() { + if (siw) { + orgUserInput = siw.inputBox.value; + orgUserInput = getUserInputToMatch(orgUserInput); + userInput = orgUserInput.toLowerCase().replace(/[\r\n\t\f\s]+/gi, ' ').replace(/^ +/gi, '').replace(/ +$/gi, '').replace(/ +/gi, ' ').replace(/\\/gi, '').replace(/\[/gi, '').replace(/\(/gi, '').replace(/\./gi, '\.').replace(/\?/gi, ''); + if (userInput && (userInput != "") && (userInput != '"')) { + runMatchingLogic(userInput); + }//if userinput not blank and is meaningful + else { + siw.matchCollection = null; + } + }//siw exists ... uhmkaaayyyyy +}//setSmartInputData + +function getSmartInputBoxContent() { + a = null; + if (siw && siw.matchCollection && (siw.matchCollection.length > 0)) { + a = ''; + for (i = 0; i < siw.matchCollection.length; i++) { + selectedString = siw.matchCollection[i].isSelected ? ' selectedSmartInputItem' : ''; + a += '

    ' + siw.matchCollection[i].value.replace(/\{ */gi, "<").replace(/\} */gi, ">") + '

    '; + }// + }//siw exists + return a; +}//getSmartInputBoxContent + +function modifySmartInputBoxContent(content) { + //todo: remove credits 'cuz no one gives a shit ;] - done + siw.floaterContent.innerHTML = '
    ' + content + (siw.showCredit ? ('

    Powered By: Chris Holland

    ') : '') + '
    '; + siw.matchListDisplay = document.getElementById("smartInputResults"); +}//modifySmartInputBoxContent() + +function selectFromMouseOver(o) { + currentIndex = getCurrentlySelectedSmartInputItem(); + if (currentIndex != null) deSelectSmartInputMatchItem(currentIndex); + newIndex = getIndexFromElement(o); + selectSmartInputMatchItem(newIndex); + modifySmartInputBoxContent(getSmartInputBoxContent()); +}//selectFromMouseOver + +function selectFromMouseClick() { + activateCurrentSmartInputMatch(); + siw.inputBox.focus(); + hideSmartInputFloater(); +}//selectFromMouseClick + +function getIndexFromElement(o) { + index = 0; + while (o = o.previousSibling) { + index++; + }// + return index; +}//getIndexFromElement + +function getCurrentlySelectedSmartInputItem() { + answer = null; + for (i = 0; ((i < siw.matchCollection.length) && !answer); i++) { + if (siw.matchCollection[i].isSelected) + answer = i; + }// + return answer; +}//getCurrentlySelectedSmartInputItem + +function selectSmartInputMatchItem(index) { + siw.matchCollection[index].isSelected = true; +}//selectSmartInputMatchItem() + +function deSelectSmartInputMatchItem(index) { + siw.matchCollection[index].isSelected = false; +}//deSelectSmartInputMatchItem() + +function selectNextSmartInputMatchItem() { + currentIndex = getCurrentlySelectedSmartInputItem(); + if (currentIndex != null) { + deSelectSmartInputMatchItem(currentIndex); + if ((currentIndex + 1) < siw.matchCollection.length) + selectSmartInputMatchItem(currentIndex + 1); + else + selectSmartInputMatchItem(0); + } else { + selectSmartInputMatchItem(0); + } + modifySmartInputBoxContent(getSmartInputBoxContent()); +}//selectNextSmartInputMatchItem + +function selectPreviousSmartInputMatchItem() { + currentIndex = getCurrentlySelectedSmartInputItem(); + if (currentIndex != null) { + deSelectSmartInputMatchItem(currentIndex); + if ((currentIndex - 1) >= 0) + selectSmartInputMatchItem(currentIndex - 1); + else + selectSmartInputMatchItem(siw.matchCollection.length - 1); + } else { + selectSmartInputMatchItem(siw.matchCollection.length - 1); + } + modifySmartInputBoxContent(getSmartInputBoxContent()); +}//selectPreviousSmartInputMatchItem + +function activateCurrentSmartInputMatch() { + baseValue = getUserInputBase(); + if ((selIndex = getCurrentlySelectedSmartInputItem()) != null) { + addedValue = siw.matchCollection[selIndex].cleanValue; + theString = (baseValue ? baseValue : "") + addedValue + ", "; + siw.inputBox.value = theString; + runMatchingLogic(addedValue, true); + } +}//activateCurrentSmartInputMatch + +function smartInputWindow() { + this.customFloater = false; + this.floater = document.getElementById("smartInputFloater"); + this.floaterContent = document.getElementById("smartInputFloaterContent"); + this.selectedSmartInputItem = null; + this.MAX_MATCHES = 15; + this.isGecko = (navigator.userAgent.indexOf("Gecko/200") != -1); + this.isSafari = (navigator.userAgent.indexOf("Safari") != -1); + this.isWinIE = ((navigator.userAgent.indexOf("Win") != -1 ) && (navigator.userAgent.indexOf("MSIE") != -1 )); + this.showCredit = false; +}//smartInputWindow Object + +function registerSmartInputListeners() { + inputs = document.getElementsByTagName("input"); + texts = document.getElementsByTagName("textarea"); + allinputs = new Array(); + z = 0; + y = 0; + while (inputs[z]) { + allinputs[z] = inputs[z]; + z++; + }// + while (texts[y]) { + allinputs[z] = texts[y]; + z++; + y++; + }// + + for (i = 0; i < allinputs.length; i++) { + if ((c = allinputs[i].className) && (c == "wickEnabled")) { + allinputs[i].setAttribute("autocomplete", "OFF"); + allinputs[i].onfocus = handleFocus; + allinputs[i].onblur = handleBlur; + allinputs[i].onkeydown = handleKeyDown; + allinputs[i].onkeyup = handleKeyPress; + } + }//loop thru inputs +}//registerSmartInputListeners + +siw = null; + +if (document.addEventListener) { + document.addEventListener("keydown", handleKeyDown, false); + document.addEventListener("keyup", handleKeyPress, false); + document.addEventListener("mouseup", handleClick, false); + document.addEventListener("mouseover", handleMouseOver, false); +} else { + document.onkeydown = handleKeyDown; + document.onkeyup = handleKeyPress; + document.onmouseup = handleClick; + document.onmouseover = handleMouseOver; +} + +registerSmartInputListeners(); + +document.write( + ']", "i"), bv = /^(?:checkbox|radio)$/, bw = /checked\s*(?:[^=]|=\s*.checked.)/i, bx = /\/(java|ecma)script/i, by = /^\s*\s*$/g, bz = { + option: [1, ""], + legend: [1, "
    ", "
    "], + thead: [1, "
    ' + + '<\/td><\/tr><\/table>' +); + +//note: instruct users to the fact that no commas should be present in entries. +//it would make things insanely messy. +//this is why i'm filtering commas here: +for (x = 0; x < collection.length; x++) { + collection[x] = collection[x].replace(/\,/gi, ''); +}// + +collectionIndex = new Array(); + +ds = ""; +function debug(s) { + ds += ( s + "\n"); +} diff --git a/src/main/webapp/stat/js/util/console-compability.js b/src/main/webapp/stat/js/util/console-compability.js new file mode 100644 index 000000000..beaa9ba6c --- /dev/null +++ b/src/main/webapp/stat/js/util/console-compability.js @@ -0,0 +1,22 @@ +!function () { + if (typeof window.console === 'undefined') { + window.console = {}; + } + + var mockConsoleKeys = ['log', 'info', 'error', 'dir']; + + var k = ''; + for (var i = 0; i < mockConsoleKeys.length; i++) { + k = mockConsoleKeys[i]; + if (typeof console[k] === 'undefined') { + console[k] = genereateConsoleMethod(k); + } + } + + function genereateConsoleMethod(key) { + return function (msg) { + if (window.showConsoleMsg) + document.body.innerHTML += '
    [' + key + ']:' + msg; + }; + } +}(); \ No newline at end of file diff --git a/src/main/webapp/stat/js/util/dateFormat.min.js b/src/main/webapp/stat/js/util/dateFormat.min.js new file mode 100644 index 000000000..a8734e330 --- /dev/null +++ b/src/main/webapp/stat/js/util/dateFormat.min.js @@ -0,0 +1,194 @@ +/*! jquery-dateFormat 10-05-2014 */ +var DateFormat = {}; +!function (a) { + var b = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], c = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], d = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], e = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], f = { + Jan: "01", + Feb: "02", + Mar: "03", + Apr: "04", + May: "05", + Jun: "06", + Jul: "07", + Aug: "08", + Sep: "09", + Oct: "10", + Nov: "11", + Dec: "12" + }, g = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.?\d{0,3}[Z\-+]?(\d{2}:?\d{2})?/; + a.format = function () { + function a(a) { + return b[parseInt(a, 10)] || a + } + + function h(a) { + return c[parseInt(a, 10)] || a + } + + function i(a) { + var b = parseInt(a, 10) - 1; + return d[b] || a + } + + function j(a) { + var b = parseInt(a, 10) - 1; + return e[b] || a + } + + function k(a) { + return f[a] || a + } + + function l(a) { + var b, c, d, e, f, g = a, h = ""; + return -1 !== g.indexOf(".") && (e = g.split("."), g = e[0], h = e[1]), f = g.split(":"), 3 === f.length ? (b = f[0], c = f[1], d = f[2].replace(/\s.+/, "").replace(/[a-z]/gi, ""), g = g.replace(/\s.+/, "").replace(/[a-z]/gi, ""), { + time: g, + hour: b, + minute: c, + second: d, + millis: h + }) : {time: "", hour: "", minute: "", second: "", millis: ""} + } + + function m(a, b) { + for (var c = b - String(a).length, d = 0; c > d; d++)a = "0" + a; + return a + } + + return { + parseDate: function (a) { + var b = {date: null, year: null, month: null, dayOfMonth: null, dayOfWeek: null, time: null}; + if ("number" == typeof a)return this.parseDate(new Date(a)); + if ("function" == typeof a.getFullYear)b.year = String(a.getFullYear()), b.month = String(a.getMonth() + 1), b.dayOfMonth = String(a.getDate()), b.time = l(a.toTimeString()); else if (-1 != a.search(g))values = a.split(/[T\+-]/), b.year = values[0], b.month = values[1], b.dayOfMonth = values[2], b.time = l(values[3].split(".")[0]); else switch (values = a.split(" "), 6 === values.length && isNaN(values[5]) && (values[values.length] = "()"), values.length) { + case 6: + b.year = values[5], b.month = k(values[1]), b.dayOfMonth = values[2], b.time = l(values[3]); + break; + case 2: + subValues = values[0].split("-"), b.year = subValues[0], b.month = subValues[1], b.dayOfMonth = subValues[2], b.time = l(values[1]); + break; + case 7: + case 9: + case 10: + b.year = values[3], b.month = k(values[1]), b.dayOfMonth = values[2], b.time = l(values[4]); + break; + case 1: + subValues = values[0].split(""), b.year = subValues[0] + subValues[1] + subValues[2] + subValues[3], b.month = subValues[5] + subValues[6], b.dayOfMonth = subValues[8] + subValues[9], b.time = l(subValues[13] + subValues[14] + subValues[15] + subValues[16] + subValues[17] + subValues[18] + subValues[19] + subValues[20]); + break; + default: + return null + } + return b.date = new Date(b.year, b.month - 1, b.dayOfMonth), b.dayOfWeek = String(b.date.getDay()), b + }, date: function (b, c) { + try { + var d = this.parseDate(b); + if (null === d)return b; + for (var e = (d.date, d.year), f = d.month, g = d.dayOfMonth, k = d.dayOfWeek, l = d.time, n = "", o = "", p = "", q = !1, r = 0; r < c.length; r++) { + var s = c.charAt(r), t = c.charAt(r + 1); + if (q)"'" == s ? (o += "" === n ? "'" : n, n = "", q = !1) : n += s; else switch (n += s, p = "", n) { + case"ddd": + o += a(k), n = ""; + break; + case"dd": + if ("d" === t)break; + o += m(g, 2), n = ""; + break; + case"d": + if ("d" === t)break; + o += parseInt(g, 10), n = ""; + break; + case"D": + g = 1 == g || 21 == g || 31 == g ? parseInt(g, 10) + "st" : 2 == g || 22 == g ? parseInt(g, 10) + "nd" : 3 == g || 23 == g ? parseInt(g, 10) + "rd" : parseInt(g, 10) + "th", o += g, n = ""; + break; + case"MMMM": + o += j(f), n = ""; + break; + case"MMM": + if ("M" === t)break; + o += i(f), n = ""; + break; + case"MM": + if ("M" === t)break; + o += m(f, 2), n = ""; + break; + case"M": + if ("M" === t)break; + o += parseInt(f, 10), n = ""; + break; + case"y": + case"yyy": + if ("y" === t)break; + o += n, n = ""; + break; + case"yy": + if ("y" === t)break; + o += String(e).slice(-2), n = ""; + break; + case"yyyy": + o += e, n = ""; + break; + case"HH": + o += m(l.hour, 2), n = ""; + break; + case"H": + if ("H" === t)break; + o += parseInt(l.hour, 10), n = ""; + break; + case"hh": + hour = 0 === parseInt(l.hour, 10) ? 12 : l.hour < 13 ? l.hour : l.hour - 12, o += m(hour, 2), n = ""; + break; + case"h": + if ("h" === t)break; + hour = 0 === parseInt(l.hour, 10) ? 12 : l.hour < 13 ? l.hour : l.hour - 12, o += parseInt(hour, 10), n = ""; + break; + case"mm": + o += m(l.minute, 2), n = ""; + break; + case"m": + if ("m" === t)break; + o += l.minute, n = ""; + break; + case"ss": + o += m(l.second.substring(0, 2), 2), n = ""; + break; + case"s": + if ("s" === t)break; + o += l.second, n = ""; + break; + case"S": + case"SS": + if ("S" === t)break; + o += n, n = ""; + break; + case"SSS": + o += l.millis.substring(0, 3), n = ""; + break; + case"a": + o += l.hour >= 12 ? "PM" : "AM", n = ""; + break; + case"p": + o += l.hour >= 12 ? "p.m." : "a.m.", n = ""; + break; + case"E": + o += h(k), n = ""; + break; + case"'": + n = "", q = !0; + break; + default: + o += s, n = "" + } + } + return o += p + } catch (u) { + return console && console.log && console.log(u), b + } + }, prettyDate: function (a) { + var b, c, d; + return ("string" == typeof a || "number" == typeof a) && (b = new Date(a)), "object" == typeof a && (b = new Date(a.toString())), c = ((new Date).getTime() - b.getTime()) / 1e3, d = Math.floor(c / 86400), isNaN(d) || 0 > d ? void 0 : 60 > c ? "just now" : 120 > c ? "1 minute ago" : 3600 > c ? Math.floor(c / 60) + " minutes ago" : 7200 > c ? "1 hour ago" : 86400 > c ? Math.floor(c / 3600) + " hours ago" : 1 === d ? "Yesterday" : 7 > d ? d + " days ago" : 31 > d ? Math.ceil(d / 7) + " weeks ago" : d >= 31 ? "more than 5 weeks ago" : void 0 + }, toBrowserTimeZone: function (a, b) { + return this.date(new Date(a), b || "MM/dd/yyyy HH:mm:ss") + } + } + }() +}(DateFormat), function (a) { + a.format = DateFormat.format +}(jQuery); \ No newline at end of file diff --git a/src/main/webapp/stat/js/util/dist/mock-min.map b/src/main/webapp/stat/js/util/dist/mock-min.map new file mode 100644 index 000000000..7a692a400 --- /dev/null +++ b/src/main/webapp/stat/js/util/dist/mock-min.map @@ -0,0 +1 @@ +{"version":3,"file":"dist/mock-min.js","sources":["dist/mock.js"],"names":["undefined","Mock","version","_mocked","Util","extend","options","name","src","copy","clone","target","arguments","i","length","this","isArray","isObject","each","obj","iterator","context","key","type","call","String","Object","prototype","toString","match","toLowerCase","split","value","isObjectOrArray","isNumeric","isNaN","parseFloat","isFinite","heredoc","fn","replace","noop","Random","boolean","min","max","cur","parseInt","Math","random","bool","natural","round","integer","int","float","dmin","dmax","ret","dcount","character","pool","pools","lower","upper","number","symbol","alpha","charAt","char","string","text","str","range","start","stop","step","len","ceil","idx","Array","patternLetters","yyyy","yy","date","getFullYear","slice","y","MM","m","getMonth","M","dd","d","getDate","HH","h","getHours","H","hh","mm","getMinutes","ss","s","getSeconds","SS","ms","getMilliseconds","S","A","a","rformat","RegExp","re","push","join","format","$0","flag","callee","randomDate","Date","getTime","time","datetime","ad_size","screen_size","video_size","image","size","background","foreground","pick","indexOf","img","apply","brandColors","4ormat","500px","About.me (blue)","About.me (yellow)","Addvocate","Adobe","Aim","Amazon","Android","Angie's List","AOL","Atlassian","Behance","Big Cartel","bitly","Blogger","Boeing","Booking.com","Carbonmade","Cheddar","Code School","Delicious","Dell","Designmoo","Deviantart","Designer News","Devour","DEWALT","Disqus (blue)","Disqus (orange)","Dribbble","Dropbox","Drupal","Dunked","eBay","Ember","Engadget","Envato","Etsy","Evernote","Fab.com","Facebook","Firefox","Flickr (blue)","Flickr (pink)","Forrst","Foursquare","Garmin","GetGlue","Gimmebar","GitHub","Google Blue","Google Green","Google Red","Google Yellow","Google+","Grooveshark","Groupon","Hacker News","HelloWallet","Heroku (light)","Heroku (dark)","HootSuite","Houzz","HTML5","IKEA","IMDb","Instagram","Intel","Intuit","Kickstarter","kippt","Kodery","LastFM","LinkedIn","Livestream","Lumo","Mixpanel","Meetup","Nokia","NVIDIA","Opera","Path","PayPal (dark)","PayPal (light)","Pinboard","Pinterest","PlayStation","Pocket","Prezi","Pusha","Quora","QUOTE.fm","Rdio","Readability","Red Hat","Resource","Rockpack","Roon","RSS","Salesforce","Samsung","Shopify","Skype","Snagajob","Softonic","SoundCloud","Space Box","Spotify","Sprint","Squarespace","StackOverflow","Staples","Status Chart","Stripe","StudyBlue","StumbleUpon","T-Mobile","Technorati","The Next Web","Treehouse","Trulia","Tumblr","Twitch.tv","Twitter","TYPO3","Ubuntu","Ustream","Verizon","Vimeo","Vine","Virb","Virgin Media","Wooga","WordPress (blue)","WordPress (orange)","WordPress (grey)","Wunderlist","XBOX","XING","Yahoo!","Yandex","Yelp","YouTube","Zalongo","Zendesk","Zerply","Zootool","brands","b","dataImageHolder","dataImage","canvas","document","createElement","ctx","getContext","width","height","text_height","font","textAlign","textBaseline","fillStyle","fillRect","fillText","toDataURL","color","colour","floor","capitalize","word","toUpperCase","substr","arr","shuffle","old","result","index","splice","paragraph","sentence","title","first","names","concat","last","middle","url","domain","tld","email","ip","tlds","areas","area","regions","region","address","city","phone","areacode","street","street_suffixes","street_suffix","states","state","zip","todo","d4","d6","d8","d12","d20","d100","guid","id","sum","rank","autoIncrementInteger","increment","inc","rkey","rrange","rplaceholder","mock","rurl","rtype","template","Handle","gen","parameters","count","decimal","point","array","j","object","parts","placeholders","ph","phed","test","placeholder","_all","exec","lkey","okey","params","handle","mockjax","jQuery","mockxhr","open","send","getAllResponseHeaders","readyState","status","convert","isFunction","prefilter","surl","dataFilter","converters","xhr","ajaxPrefilter","KISSY","add","_original_ajax","io","responseText","responseXML","statusText","timeoutTimer","console","log","data","success","complete","module","exports","define","amd","cmd","requires","Mock4Tpl","tpl","input","helpers","partials","parse","Handlebars","debug","node","isString","ast","parseOptions","__path","group","JSON","stringify","preLength","groupEnd","ma","option","rComment","comments","lastIndex","Function","val","def","Error","mocked","program","statements","mustache","currentContext","contextLength","unshift","isHelper","hash","block","inverse","Helpers","custom","pop","shift","pair","pairs","ID","prev","valType","preOptions","depth","partial","partialName","content","PARTIAL_NAME","DATA","STRING","INTEGER","BOOLEAN","comment","unless","XTemplate","Mock4XTpl","use","T","xtpl","xparse","compiler","RunTime","commands","subTpls","other","hold","parseVal","expr","queryArray","prop","query","queryObject","set","if","with","path","_","__","___","include","tplExpression","expression","unaryExpression","multiplicativeExpression","additiveExpression","op1","op2","pow","relationalExpression","equalityExpression","conditionalAndExpression","conditionalOrExpression","fix"],"mappings":"CAEA,SAAUA,GACN,GAAIC,IACAC,QAAS,QACTC,YAGAC,EAAO,WACP,GAAIA,KA4DJ,OA3DAA,GAAKC,OAAS,WACV,GAAmEC,GAASC,EAAMC,EAAKC,EAAMC,EAAzFC,EAASC,UAAU,OAAUC,EAAI,EAAGC,EAASF,UAAUE,MAK3D,KAJe,IAAXA,IACAH,EAASI,KACTF,EAAI,GAEEC,EAAJD,EAAYA,IAEd,GADAP,EAAUM,UAAUC,GAEpB,IAAKN,IAAQD,GACTE,EAAMG,EAAOJ,GACbE,EAAOH,EAAQC,GACXI,IAAWF,GACXA,IAAST,IACTI,EAAKY,QAAQP,IAASL,EAAKa,SAASR,IAChCL,EAAKY,QAAQP,KAAOC,EAAQF,GAAOJ,EAAKY,QAAQR,GAAOA,MACvDJ,EAAKa,SAASR,KAAOC,EAAQF,GAAOJ,EAAKa,SAAST,GAAOA,MAC7DG,EAAOJ,GAAQH,EAAKC,OAAOK,EAAOD,IAElCE,EAAOJ,GAAQE,EAI3B,OAAOE,IAEXP,EAAKc,KAAO,SAAcC,EAAKC,EAAUC,GACrC,GAAIR,GAAGS,CACP,IAAuB,WAAnBP,KAAKQ,KAAKJ,GACV,IAAKN,EAAI,EAAOM,EAAJN,EAASA,IACjBO,EAASP,EAAGA,OAEb,IAAIM,EAAIL,UAAYK,EAAIL,OAC3B,IAAKD,EAAI,EAAGA,EAAIM,EAAIL,QACZM,EAASI,KAAKH,EAASF,EAAIN,GAAIA,EAAGM,MAAS,EADvBN,SAI5B,KAAKS,IAAOH,GACR,GAAIC,EAASI,KAAKH,EAASF,EAAIG,GAAMA,EAAKH,MAAS,EAAO,OAItEf,EAAKmB,KAAO,SAAcJ,GACtB,MAAe,QAARA,GAAgBA,IAAQnB,EAAYyB,OAAON,GAAOO,OAAOC,UAAUC,SAASJ,KAAKL,GAAKU,MAAM,oBAAoB,GAAGC,eAE9H1B,EAAKc,KAAK,sCAAsCa,MAAM,KAAM,SAASC,GACjE5B,EAAK,KAAO4B,GAAS,SAASb,GAC1B,MAAOf,GAAKmB,KAAKJ,KAASa,EAAMF,iBAGxC1B,EAAK6B,gBAAkB,SAASD,GAC5B,MAAO5B,GAAKa,SAASe,IAAU5B,EAAKY,QAAQgB,IAEhD5B,EAAK8B,UAAY,SAASF,GACtB,OAAQG,MAAMC,WAAWJ,KAAWK,SAASL,IAEjD5B,EAAKkC,QAAU,SAAiBC,GAC5B,MAAOA,GAAGX,WAAWY,QAAQ,gBAAiB,IAAIA,QAAQ,cAAe,IAAIA,QAAQ,aAAc,IAAIA,QAAQ,aAAc,KAEjIpC,EAAKqC,KAAO,aACLrC,KAGPsC,EAAS,WACT,GAAIA,IACArC,OAAQD,EAAKC,OAkkBjB,OAhkBAqC,GAAOrC,QACHsC,UAAW,SAASC,EAAKC,EAAKC,GAC1B,MAAIA,KAAQ9C,GACR4C,EAAqB,mBAARA,IAAwBT,MAAMS,GAA2B,EAApBG,SAASH,EAAK,IAChEC,EAAqB,mBAARA,IAAwBV,MAAMU,GAA2B,EAApBE,SAASF,EAAK,IACzDG,KAAKC,SAAW,GAAKL,EAAMC,GAAOD,GAAOE,EAAMA,GAEnDE,KAAKC,UAAY,IAE5BC,KAAM,SAASN,EAAKC,EAAKC,GACrB,MAAO/B,MAAK4B,QAAQC,EAAKC,EAAKC,IAElCK,QAAS,SAASP,EAAKC,GAGnB,MAFAD,GAAqB,mBAARA,GAAsBG,SAASH,EAAK,IAAM,EACvDC,EAAqB,mBAARA,GAAsBE,SAASF,EAAK,IAAM,iBAChDG,KAAKI,MAAMJ,KAAKC,UAAYJ,EAAMD,IAAQA,GAErDS,QAAS,SAAST,EAAKC,GAGnB,MAFAD,GAAqB,mBAARA,GAAsBG,SAASH,EAAK,IAAM,kBACvDC,EAAqB,mBAARA,GAAsBE,SAASF,EAAK,IAAM,iBAChDG,KAAKI,MAAMJ,KAAKC,UAAYJ,EAAMD,IAAQA,GAErDU,MAAO,SAASV,EAAKC,GACjB,MAAO9B,MAAKsC,QAAQT,EAAKC,IAE7BU,QAAS,SAASX,EAAKC,EAAKW,EAAMC,GAC9BD,EAAOA,IAASxD,EAAY,EAAIwD,EAChCA,EAAOR,KAAKH,IAAIG,KAAKJ,IAAIY,EAAM,IAAK,GACpCC,EAAOA,IAASzD,EAAY,GAAKyD,EACjCA,EAAOT,KAAKH,IAAIG,KAAKJ,IAAIa,EAAM,IAAK,EAEpC,KAAK,GADDC,GAAM3C,KAAKsC,QAAQT,EAAKC,GAAO,IAC1BhC,EAAI,EAAG8C,EAAS5C,KAAKoC,QAAQK,EAAMC,GAAWE,EAAJ9C,EAAYA,IAC3D6C,GAAO3C,KAAK6C,UAAU,SAE1B,OAAOxB,YAAWsB,EAAK,KAE3BE,UAAW,SAASC,GAChB,GAAIC,IACAC,MAAO,6BACPC,MAAO,6BACPC,OAAQ,aACRC,OAAQ,eAKZ,OAHAJ,GAAMK,MAAQL,EAAMC,MAAQD,EAAME,MAClCF,EAAiB,UAAIA,EAAMC,MAAQD,EAAME,MAAQF,EAAMG,OAASH,EAAMI,OACtEL,EAAOC,GAAO,GAAKD,GAAM/B,gBAAkB+B,EACpCA,EAAKO,OAAO1B,EAAOS,QAAQ,EAAGU,EAAK/C,OAAS,KAEvDuD,OAAQ,SAASR,GACb,MAAO9C,MAAK6C,UAAUC,IAE1BS,OAAQ,SAAST,EAAMjB,EAAKC,GACxB,GAAI/B,EACqB,KAArBF,UAAUE,SACVA,EAAS4B,EAAOS,QAAQP,EAAKC,IAER,IAArBjC,UAAUE,SACkB,gBAAjBF,WAAU,GACjBE,EAAS8B,GAET9B,EAAS4B,EAAOS,QAAQU,EAAMjB,GAC9BiB,EAAO7D,IAGU,IAArBY,UAAUE,SACVA,EAAS+C,EACTA,EAAO7D,GAEc,IAArBY,UAAUE,SACVA,EAAS4B,EAAOS,QAAQ,EAAG,GAG/B,KAAK,GADDoB,GAAO,GACF1D,EAAI,EAAOC,EAAJD,EAAYA,IACxB0D,GAAQ7B,EAAOkB,UAAUC,EAE7B,OAAOU,IAEXC,IAAK,SAASX,EAAMjB,EAAKC,GACrB,MAAO9B,MAAKuD,OAAOT,EAAMjB,EAAKC,IAElC4B,MAAO,SAASC,EAAOC,EAAMC,GACrBhE,UAAUE,QAAU,IACpB6D,EAAOD,GAAS,EAChBA,EAAQ,GAEZE,EAAOhE,UAAU,IAAM,CAIvB,KAHA,GAAIiE,GAAM7B,KAAKH,IAAIG,KAAK8B,MAAMH,EAAOD,GAASE,GAAO,GACjDG,EAAM,EACNN,EAAQ,GAAIO,OAAMH,GACTA,EAANE,GACHN,EAAMM,KAASL,EACfA,GAASE,CAEb,OAAOH,MAGf/B,EAAOrC,QACH4E,gBACIC,KAAM,cACNC,GAAI,SAASC,GACT,OAAQ,GAAKA,EAAKC,eAAeC,MAAM,IAE3CC,EAAG,KACHC,GAAI,SAASJ,GACT,GAAIK,GAAIL,EAAKM,WAAa,CAC1B,OAAW,IAAJD,EAAS,IAAMA,EAAIA,GAE9BE,EAAG,SAASP,GACR,MAAOA,GAAKM,WAAa,GAE7BE,GAAI,SAASR,GACT,GAAIS,GAAIT,EAAKU,SACb,OAAW,IAAJD,EAAS,IAAMA,EAAIA,GAE9BA,EAAG,UACHE,GAAI,SAASX,GACT,GAAIY,GAAIZ,EAAKa,UACb,OAAW,IAAJD,EAAS,IAAMA,EAAIA,GAE9BE,EAAG,WACHC,GAAI,SAASf,GACT,GAAIY,GAAIZ,EAAKa,WAAa,EAC1B,OAAW,IAAJD,EAAS,IAAMA,EAAIA,GAE9BA,EAAG,SAASZ,GACR,MAAOA,GAAKa,WAAa,IAE7BG,GAAI,SAAShB,GACT,GAAIK,GAAIL,EAAKiB,YACb,OAAW,IAAJZ,EAAS,IAAMA,EAAIA,GAE9BA,EAAG,aACHa,GAAI,SAASlB,GACT,GAAImB,GAAInB,EAAKoB,YACb,OAAW,IAAJD,EAAS,IAAMA,EAAIA,GAE9BA,EAAG,aACHE,GAAI,SAASrB,GACT,GAAIsB,GAAKtB,EAAKuB,iBACd,OAAY,IAALD,GAAW,KAAOA,GAAW,IAALA,GAAY,IAAMA,GAAMA,GAE3DE,EAAG,kBACHC,EAAG,SAASzB,GACR,MAAOA,GAAKa,WAAa,GAAK,KAAO,MAEzCa,EAAG,SAAS1B,GACR,MAAOA,GAAKa,WAAa,GAAK,KAAO,SAIjDvD,EAAOrC,QACH0G,QAAS,GAAIC,QAAO,WAChB,GAAIC,KACJ,KAAK,GAAIpG,KAAK6B,GAAOuC,eAAgBgC,EAAGC,KAAKrG,EAC7C,OAAO,IAAMoG,EAAGE,KAAK,KAAO,OAC3B,KACLC,OAAQ,SAAShC,EAAMgC,GACnB,GAAInC,GAAiBvC,EAAOuC,eAAgB8B,EAAUrE,EAAOqE,OAC7D,OAAOK,GAAO5E,QAAQuE,EAAS,SAASM,EAAIC,GACxC,MAAuC,kBAAzBrC,GAAeqC,GAAuBrC,EAAeqC,GAAMlC,GAAQH,EAAeqC,IAASrC,GAAiBrE,UAAU2G,OAAOF,EAAIpC,EAAeqC,IAASlC,EAAKH,EAAeqC,SAGnME,WAAY,SAAS5E,EAAKC,GAGtB,MAFAD,GAAMA,IAAQ5C,EAAY,GAAIyH,MAAK,GAAK7E,EACxCC,EAAMA,IAAQ7C,EAAY,GAAIyH,MAAS5E,EAChC,GAAI4E,MAAKzE,KAAKC,UAAYJ,EAAI6E,UAAY9E,EAAI8E,aAEzDtC,KAAM,SAASgC,GAEX,MADAA,GAASA,GAAU,aACZrG,KAAKqG,OAAOrG,KAAKyG,aAAcJ,IAE1CO,KAAM,SAASP,GAEX,MADAA,GAASA,GAAU,WACZrG,KAAKqG,OAAOrG,KAAKyG,aAAcJ,IAE1CQ,SAAU,SAASR,GAEf,MADAA,GAASA,GAAU,sBACZrG,KAAKqG,OAAOrG,KAAKyG,aAAcJ,MAG9C1E,EAAOrC,QACHwH,SAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,SAAU,SAAU,QAAS,SAAU,SAAU,UAAW,UAAW,SAAU,UAAW,UAAW,WACpLC,aAAe,UAAW,UAAW,UAAW,UAAW,UAAW,WAAY,WAAY,WAAY,WAAY,YAAa,aACnIC,YAAc,UAAW,UAAW,WAAY,aAChDC,MAAO,SAASC,EAAMC,EAAYC,EAAYf,EAAQ7C,GAYlD,MAXyB,KAArB3D,UAAUE,SACVyD,EAAO6C,EACPA,EAASpH,GAEY,IAArBY,UAAUE,SACVyD,EAAO4D,EACPA,EAAanI,GAEZiI,IAAMA,EAAOlH,KAAKqH,KAAKrH,KAAK8G,UAC7BK,IAAeA,EAAWG,QAAQ,OAAMH,EAAaA,EAAW5C,MAAM,IACtE6C,IAAeA,EAAWE,QAAQ,OAAMF,EAAaA,EAAW7C,MAAM,IACnE,yBAA2B2C,GAAQC,EAAa,IAAMA,EAAa,KAAOC,EAAa,IAAMA,EAAa,KAAOf,EAAS,IAAMA,EAAS,KAAO7C,EAAO,SAAWA,EAAO,KAEpL+D,IAAK,WACD,MAAOvH,MAAKiH,MAAMO,MAAMxH,KAAMH,cAGtC8B,EAAOrC,QACHmI,aACIC,SAAU,UACVC,QAAS,UACTC,kBAAmB,UACnBC,oBAAqB,UACrBC,UAAW,UACXC,MAAO,UACPC,IAAK,UACLC,OAAQ,UACRC,QAAS,UACTC,eAAgB,UAChBC,IAAK,UACLC,UAAW,UACXC,QAAS,UACTC,aAAc,UACdC,MAAO,UACPC,QAAS,UACTC,OAAQ,UACRC,cAAe,UACfC,WAAY,UACZC,QAAS,UACTC,cAAe,UACfC,UAAW,UACXC,KAAM,UACNC,UAAW,UACXC,WAAY,UACZC,gBAAiB,UACjBC,OAAQ,UACRC,OAAQ,UACRC,gBAAiB,UACjBC,kBAAmB,UACnBC,SAAU,UACVC,QAAS,UACTC,OAAQ,UACRC,OAAQ,UACRC,KAAM,UACNC,MAAO,UACPC,SAAU,UACVC,OAAQ,UACRC,KAAM,UACNC,SAAU,UACVC,UAAW,UACXC,SAAU,UACVC,QAAS,UACTC,gBAAiB,UACjBC,gBAAiB,UACjBC,OAAQ,UACRC,WAAY,UACZC,OAAQ,UACRC,QAAS,UACTC,SAAU,UACVC,OAAQ,UACRC,cAAe,UACfC,eAAgB,UAChBC,aAAc,UACdC,gBAAiB,UACjBC,UAAW,UACXC,YAAa,UACbC,QAAS,UACTC,cAAe,UACfC,YAAa,UACbC,iBAAkB,UAClBC,gBAAiB,UACjBC,UAAW,UACXC,MAAO,UACPC,MAAO,UACPC,KAAM,UACNC,KAAM,UACNC,UAAW,UACXC,MAAO,UACPC,OAAQ,UACRC,YAAa,UACbC,MAAO,UACPC,OAAQ,UACRC,OAAQ,UACRC,SAAU,UACVC,WAAY,UACZC,KAAM,UACNC,SAAU,UACVC,OAAQ,UACRC,MAAO,UACPC,OAAQ,UACRC,MAAO,UACPC,KAAM,UACNC,gBAAiB,UACjBC,iBAAkB,UAClBC,SAAU,UACVC,UAAW,UACXC,YAAa,UACbC,OAAQ,UACRC,MAAO,UACPC,MAAO,UACPC,MAAO,UACPC,WAAY,UACZC,KAAM,UACNC,YAAa,UACbC,UAAW,UACXC,SAAU,UACVC,SAAU,UACVC,KAAM,UACNC,IAAK,UACLC,WAAY,UACZC,QAAS,UACTC,QAAS,UACTC,MAAO,UACPC,SAAU,UACVC,SAAU,UACVC,WAAY,UACZC,YAAa,UACbC,QAAS,UACTC,OAAQ,UACRC,YAAa,UACbC,cAAe,UACfC,QAAS,UACTC,eAAgB,UAChBC,OAAQ,UACRC,UAAW,UACXC,YAAa,UACbC,WAAY,UACZC,WAAY,UACZC,eAAgB,UAChBC,UAAW,UACXC,OAAQ,UACRC,OAAQ,UACRC,YAAa,UACbC,QAAS,UACTC,MAAO,UACPC,OAAQ,UACRC,QAAS,UACTC,QAAS,UACTC,MAAO,UACPC,KAAM,UACNC,KAAM,UACNC,eAAgB,UAChBC,MAAO,UACPC,mBAAoB,UACpBC,qBAAsB,UACtBC,mBAAoB,UACpBC,WAAY,UACZC,KAAM,UACNC,KAAM,UACNC,SAAU,UACVC,OAAQ,UACRC,KAAM,UACNC,QAAS,UACTC,QAAS,UACTC,QAAS,UACTC,OAAQ,UACRC,QAAS,WAEbC,OAAQ,WACJ,GAAIA,KACJ,KAAK,GAAIC,KAAK/Q,MAAKyH,YACfqJ,EAAO3K,KAAK4K,EAEhB,OAAOD,IAEXE,gBAAiB,SAAS9J,GACtB,MAAO,aAAeA,GAE1B+J,UAAW,SAAS/J,EAAM1D,GACtB,GAAI0N,GAA6B,mBAAbC,WAA4BA,SAASC,cAAc,UAAWC,EAAMH,GAAUA,EAAOI,YAAcJ,EAAOI,WAAW,KACzI,KAAKJ,IAAWG,EAAK,MAAO,EACvBnK,KAAMA,EAAOlH,KAAKqH,KAAKrH,KAAK8G,UACjCtD,EAAOA,IAASvE,EAAYuE,EAAO0D,EACnCA,EAAOA,EAAKlG,MAAM,IAClB,IAAIuQ,GAAQvP,SAASkF,EAAK,GAAI,IAAKsK,EAASxP,SAASkF,EAAK,GAAI,IAAKC,EAAanH,KAAKyH,YAAYzH,KAAKqH,KAAKrH,KAAK8Q,WAAY1J,EAAa,OAAQqK,EAAc,GAAIC,EAAO,YAU1K,OATAR,GAAOK,MAAQA,EACfL,EAAOM,OAASA,EAChBH,EAAIM,UAAY,SAChBN,EAAIO,aAAe,SACnBP,EAAIQ,UAAY1K,EAChBkK,EAAIS,SAAS,EAAG,EAAGP,EAAOC,GAC1BH,EAAIQ,UAAYzK,EAChBiK,EAAIK,KAAO,QAAUD,EAAc,MAAQC,EAC3CL,EAAIU,SAASvO,EAAM+N,EAAQ,EAAGC,EAAS,EAAGD,GACnCL,EAAOc,UAAU,gBAGhCrQ,EAAOrC,QACH2S,MAAO,WACH,GAAIC,GAASjQ,KAAKkQ,MAAsB,SAAhBlQ,KAAKC,UAA8CrB,SAAS,GAEpF,OADAqR,GAAS,KAAO,SAAWA,GAAQ3N,MAAM,OAIjD5C,EAAOrC,QACH8S,WAAY,SAASC,GACjB,MAAOA,GAAKhP,OAAO,GAAGiP,cAAgBD,EAAKE,OAAO,IAEtDtP,MAAO,SAASQ,GACZ,MAAOA,GAAI6O,eAEftP,MAAO,SAASS,GACZ,MAAOA,GAAI1C,eAEfsG,KAAM,SAASmL,GACX,MAAOA,GAAIxS,KAAKoC,QAAQ,EAAGoQ,EAAIzS,OAAS,KAE5C0S,QAAS,SAASD,GAEd,IAAK,GADDE,GAAMF,EAAIjO,MAAM,GAAIoO,KAAaC,EAAQ,EAAG7S,EAAS2S,EAAI3S,OACpDD,EAAI,EAAOC,EAAJD,EAAYA,IACxB8S,EAAQ5S,KAAKoC,QAAQ,EAAGsQ,EAAI3S,OAAS,GACrC4S,EAAOxM,KAAKuM,EAAIE,IAChBF,EAAIG,OAAOD,EAAO,EAEtB,OAAOD,MAGfhR,EAAOrC,QACHwT,UAAW,SAASjR,EAAKC,GACrB,GAAIgC,EACqB,KAArBjE,UAAUE,SAAc+D,EAAMnC,EAAOS,QAAQ,EAAG,IAC3B,IAArBvC,UAAUE,SAAc+D,EAAMhC,EAAMD,GACf,IAArBhC,UAAUE,SACV8B,EAAMG,SAASH,EAAK,IACpBC,EAAME,SAASF,EAAK,IACpBgC,EAAMnC,EAAOS,QAAQP,EAAKC,GAG9B,KAAK,GADD0Q,MACK1S,EAAI,EAAOgE,EAAJhE,EAASA,IACrB0S,EAAIrM,KAAKxE,EAAOoR,WAEpB,OAAOP,GAAIpM,KAAK,MAEpB2M,SAAU,SAASlR,EAAKC,GACpB,GAAIgC,EACqB,KAArBjE,UAAUE,SAAc+D,EAAMnC,EAAOS,QAAQ,GAAI,KAC5B,IAArBvC,UAAUE,SAAc+D,EAAMhC,EAAMD,GACf,IAArBhC,UAAUE,SACV8B,EAAMG,SAASH,EAAK,IACpBC,EAAME,SAASF,EAAK,IACpBgC,EAAMnC,EAAOS,QAAQP,EAAKC,GAG9B,KAAK,GADD0Q,MACK1S,EAAI,EAAOgE,EAAJhE,EAASA,IACrB0S,EAAIrM,KAAKxE,EAAO0Q,OAEpB,OAAO1Q,GAAOyQ,WAAWI,EAAIpM,KAAK,MAAQ,KAE9CiM,KAAM,SAASxQ,EAAKC,GAChB,GAAIgC,EACqB,KAArBjE,UAAUE,SAAc+D,EAAMnC,EAAOS,QAAQ,EAAG,KAC3B,IAArBvC,UAAUE,SAAc+D,EAAMhC,EAAMD,GACf,IAArBhC,UAAUE,SACV8B,EAAMG,SAASH,EAAK,IACpBC,EAAME,SAASF,EAAK,IACpBgC,EAAMnC,EAAOS,QAAQP,EAAKC,GAG9B,KAAK,GADD6Q,GAAS,GACJ7S,EAAI,EAAOgE,EAAJhE,EAASA,IACrB6S,GAAUhR,EAAOkB,UAAU,QAE/B,OAAO8P,IAEXK,MAAO,SAASnR,EAAKC,GACjB,GAAIgC,GAAK6O,IACgB,KAArB9S,UAAUE,SAAc+D,EAAMnC,EAAOS,QAAQ,EAAG,IAC3B,IAArBvC,UAAUE,SAAc+D,EAAMhC,EAAMD,GACf,IAArBhC,UAAUE,SACV8B,EAAMG,SAASH,EAAK,IACpBC,EAAME,SAASF,EAAK,IACpBgC,EAAMnC,EAAOS,QAAQP,EAAKC,GAE9B,KAAK,GAAIhC,GAAI,EAAOgE,EAAJhE,EAASA,IACrB6S,EAAOxM,KAAKnG,KAAKoS,WAAWpS,KAAKqS,QAErC,OAAOM,GAAOvM,KAAK,QAG3BzE,EAAOrC,QACH2T,MAAO,WACH,GAAIC,IAAU,QAAS,OAAQ,SAAU,UAAW,UAAW,QAAS,UAAW,UAAW,SAAU,SAAU,cAAe,SAAU,OAAQ,OAAQ,SAAU,SAAU,UAAW,SAAU,SAAU,QAAS,SAAU,UAAW,QAAS,QAAS,UAAW,OAAQ,UAAW,OAAQ,QAAS,UAAW,QAAS,QAAS,QAASC,QAAS,OAAQ,WAAY,QAAS,UAAW,YAAa,WAAY,QAAS,QAAS,WAAY,UAAW,OAAQ,QAAS,QAAS,QAAS,QAAS,SAAU,QAAS,QAAS,OAAQ,SAAU,WAAY,QAAS,QAAS,WAAY,UAAW,UAAW,UAAW,UAAW,SAAU,UAAW,SAAU,MAAO,QAC5pB,OAAOnT,MAAKqH,KAAK6L,IAGrBE,KAAM,WACF,GAAIF,IAAU,QAAS,UAAW,WAAY,QAAS,QAAS,SAAU,QAAS,SAAU,YAAa,SAAU,WAAY,WAAY,SAAU,SAAU,YAAa,QAAS,SAAU,UAAW,WAAY,QAAS,QAAS,MAAO,WAAY,SAAU,QAAS,QAAS,WAAY,SAAU,QAAS,OAAQ,QAAS,QACxU,OAAOlT,MAAKqH,KAAK6L,IAGrB1T,KAAM,SAAS6T,GACX,MAAOrT,MAAKiT,QAAU,KAAOI,EAASrT,KAAKiT,QAAU,IAAM,IAAMjT,KAAKoT,UAG9EzR,EAAOrC,QACHgU,IAAK,WACD,MAAO,UAAYtT,KAAKuT,SAAW,IAAMvT,KAAKqS,QAElDkB,OAAQ,SAASC,GACb,MAAOxT,MAAKqS,OAAS,KAAOmB,GAAOxT,KAAKwT,QAE5CC,MAAO,SAASF,GACZ,MAAOvT,MAAK6C,UAAU,SAAW,IAAM7C,KAAKoT,OAAOrS,cAAgB,IAAMf,KAAKoT,OAAOrS,cAAgB,IAAMf,KAAKwT,OAGpHE,GAAI,WACA,MAAO1T,MAAKoC,QAAQ,EAAG,KAAO,IAAMpC,KAAKoC,QAAQ,EAAG,KAAO,IAAMpC,KAAKoC,QAAQ,EAAG,KAAO,IAAMpC,KAAKoC,QAAQ,EAAG,MAElHuR,MAAQ,MAAO,MAAO,MAAO,MAAO,QAAS,MAAO,MACpDH,IAAK,WACD,MAAOxT,MAAKqH,KAAKrH,KAAK2T,SAG9BhS,EAAOrC,QACHsU,OAAS,KAAM,KAAM,KAAM,KAAM,KAAM,KAAM,MAC7CC,KAAM,WACF,MAAO7T,MAAKqH,KAAKrH,KAAK4T,QAE1BE,SAAW,aAAc,aAAc,aAAc,aAAc,gBAAiB,aAAc,aAAc,cAAe,aAAc,aAAc,aAAc,aAAc,aAAc,aAAc,aAAc,aAAc,aAAc,aAAc,aAAc,iBAAkB,aAAc,aAAc,aAAc,aAAc,aAAc,eAAgB,aAAc,aAAc,aAAc,iBAAkB,kBAAmB,kBAAmB,aAAc,iBAAkB,kBACngBC,OAAQ,WACJ,MAAO/T,MAAKqH,KAAKrH,KAAK8T,SAAS9S,MAAM,KAAK,IAE9CgT,QAAS,aACTC,KAAM,aACNC,MAAO,aACPC,SAAU,aACVC,OAAQ,aACRC,gBAAiB,aACjBC,cAAe,aACfC,OAAQ,aACRC,MAAO,aACPC,IAAK,SAAS3Q,GAEV,IAAK,GADD2Q,GAAM,GACD3U,EAAI,GAAQgE,GAAO,GAAZhE,EAAgBA,IAAK2U,GAAOzU,KAAKoC,QAAQ,EAAG,EAC5D,OAAOqS,MAGf9S,EAAOrC,QACHoV,KAAM,WACF,MAAO,UAGf/S,EAAOrC,QACHqV,GAAI,WACA,MAAO3U,MAAKoC,QAAQ,EAAG,IAE3BwS,GAAI,WACA,MAAO5U,MAAKoC,QAAQ,EAAG,IAE3ByS,GAAI,WACA,MAAO7U,MAAKoC,QAAQ,EAAG,IAE3B0S,IAAK,WACD,MAAO9U,MAAKoC,QAAQ,EAAG,KAE3B2S,IAAK,WACD,MAAO/U,MAAKoC,QAAQ,EAAG,KAE3B4S,KAAM,WACF,MAAOhV,MAAKoC,QAAQ,EAAG,MAE3B6S,KAAM,WACF,GAAInS,GAAO,mBAAoBmS,EAAOjV,KAAKuD,OAAOT,EAAM,GAAK,IAAM9C,KAAKuD,OAAOT,EAAM,GAAK,IAAM9C,KAAKuD,OAAOT,EAAM,GAAK,IAAM9C,KAAKuD,OAAOT,EAAM,GAAK,IAAM9C,KAAKuD,OAAOT,EAAM,GAC5K,OAAOmS,IAEXC,GAAI,WACA,GAAIA,GAAIC,EAAM,EAAGC,GAAS,IAAK,IAAK,KAAM,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,KAAM,IAAK,IAAK,IAAK,KAAOhC,GAAS,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAAK,IAC9K8B,GAAKlV,KAAKqH,KAAKrH,KAAK8T,SAAS9S,MAAM,KAAK,GAAKhB,KAAKqE,KAAK,YAAcrE,KAAKuD,OAAO,SAAU,EAC3F,KAAK,GAAIzD,GAAI,EAAGA,EAAIoV,EAAGnV,OAAQD,IAC3BqV,GAAOD,EAAGpV,GAAKsV,EAAKtV,EAGxB,OADAoV,IAAM9B,EAAK+B,EAAM,KAGrBE,qBAAsB,EACtBC,UAAW,SAASzR,GAChB,MAAO7D,MAAKqV,uBAAyBxR,GAAQ,GAEjD0R,IAAK,SAAS1R,GACV,MAAO7D,MAAKsV,UAAUzR,MAGvBlC,KAGP6T,EAAO,iDAAkDC,EAAS,gBAAiBC,EAAe,yCACtGxW,GAAKI,OAASD,EAAKC,OACnBJ,EAAKyW,KAAO,SAASC,EAAMC,EAAOC,GAC9B,MAAyB,KAArBjW,UAAUE,OAAqBgW,EAAOC,IAAIJ,IACrB,IAArB/V,UAAUE,SACV+V,EAAWD,EACXA,EAAQ5W,GAEZC,EAAKE,QAAQwW,GAAQC,GAAS,MAC1BD,KAAMA,EACNC,MAAOA,EACPC,SAAUA,GAEP5W,GAEX,IAAI6W,IACAzW,OAAQD,EAAKC,OAEjByW,GAAOC,IAAM,SAASF,EAAUtW,EAAMY,GAClC,GAAslBuS,GAAllBsD,GAAczW,EAAOA,GAAQ,IAAIsB,MAAM0U,GAAO9R,EAAQuS,GAAcA,EAAW,IAAMA,EAAW,GAAGnV,MAAM2U,GAAS5T,EAAM6B,GAAS1B,SAAS0B,EAAM,GAAI,IAAK5B,EAAM4B,GAAS1B,SAAS0B,EAAM,GAAI,IAAKwS,EAAQxS,GAASA,EAAM,IAAM1B,SAAS0B,EAAM,GAAI,KAAO/B,EAAOW,QAAQT,EAAKC,GAAO,EAAGqU,EAAUF,GAAcA,EAAW,IAAMA,EAAW,GAAGnV,MAAM2U,GAAShT,EAAO0T,GAAWnU,SAASmU,EAAQ,GAAI,IAAKzT,EAAOyT,GAAWnU,SAASmU,EAAQ,GAAI,IAAKvT,EAASuT,GAAWA,EAAQ,IAAMnU,SAASmU,EAAQ,GAAI,KAAOxU,EAAOW,QAAQG,EAAMC,GAAQ,EAAG0T,EAAQH,GAAcA,EAAW,GAAIzV,EAAOnB,EAAKmB,KAAKsV,EAC3kB,OAAIC,GAAOvV,GACPmS,EAASoD,EAAOvV,IACZA,KAAMA,EACNsV,SAAUA,EACVtW,KAAMA,EACNY,IAAKA,EACL6V,WAAYA,EACZvS,MAAOA,EACP7B,IAAKA,EACLC,IAAKA,EACLoU,MAAOA,EACPC,QAASA,EACT1T,KAAMA,EACNC,KAAMA,EACNE,OAAQA,EACRwT,MAAOA,IAIRN,GAEXC,EAAOzW,QACH+W,MAAO,SAAS9W,GACZ,GAAiBO,GAAGwW,EAAhB3D,IACJ,IAAKpT,EAAQ0W,WAKT,GAAsB,IAAlB1W,EAAQ2W,OAAe3W,EAAQuW,SAAS/V,OAAS,EACjD4S,EAAShR,EAAO0F,KAAK0O,EAAOC,IAAIzW,EAAQuW,eAExC,KAAKhW,EAAI,EAAGA,EAAIP,EAAQ2W,MAAOpW,IAAK,CAChCwW,EAAI,CACJ,GACI3D,GAAOxM,KAAK4P,EAAOC,IAAIzW,EAAQuW,SAASQ,aACnCA,EAAI/W,EAAQuW,SAAS/V,YAXtC,KAAKD,EAAI,EAAGA,EAAIP,EAAQuW,SAAS/V,OAAQD,IACrC6S,EAAOxM,KAAK4P,EAAOC,IAAIzW,EAAQuW,SAAShW,IAchD,OAAO6S,IAEX4D,OAAQ,SAAShX,GACb,GAAiBgB,GAAKgV,EAAlB5C,IACJ,KAAKpS,IAAOhB,GAAQuW,SAChBnD,EAAOpS,EAAIkB,QAAQ+T,EAAM,OAASO,EAAOC,IAAIzW,EAAQuW,SAASvV,GAAMA,EAAKoS,GACzE4C,EAAMhV,EAAIO,MAAM0U,GACZD,GAAOA,EAAI,IAA2C,WAArClW,EAAKmB,KAAKjB,EAAQuW,SAASvV,MAC5ChB,EAAQuW,SAASvV,IAAQyB,SAASuT,EAAI,GAAI,IAGlD,OAAO5C,IAEXzP,OAAQ,SAAS3D,GACb,GAAIoT,GAAQ6D,EAAO1W,CACnB,IAAIP,EAAQ6W,MAAO,CAKf,IAJA7W,EAAQuW,UAAY,GACpBU,EAAQjX,EAAQuW,SAAS9U,MAAM,KAC/BwV,EAAM,GAAKjX,EAAQmE,MAAQnE,EAAQ2W,MAAQM,EAAM,GACjDA,EAAM,IAAMA,EAAM,IAAM,IAAIjS,MAAM,EAAGhF,EAAQqD,QACxC9C,EAAI,EAAG0W,EAAM,GAAGzW,OAASR,EAAQqD,OAAQ9C,IAC1C0W,EAAM,IAAM7U,EAAOkB,UAAU,SAEjC8P,GAAStR,WAAWmV,EAAMpQ,KAAK,KAAM,QAErCuM,GAASpT,EAAQmE,QAAUnE,EAAQ0W,WAAW,GAAK1W,EAAQ2W,MAAQ3W,EAAQuW,QAE/E,OAAOnD,IAEX/Q,UAAW,SAASrC,GAChB,GAAIoT,EAEJ,OADAA,GAASpT,EAAQ0W,WAAatU,EAAOQ,KAAK5C,EAAQsC,IAAKtC,EAAQuC,IAAKvC,EAAQuW,UAAYvW,EAAQuW,UAGpGvS,OAAQ,SAAShE,GACb,GAAiBO,GAAG2W,EAAcC,EAAIC,EAAlChE,EAAS,EACb,IAAIpT,EAAQuW,SAAS/V,OAAQ,CACzB,IAAKD,EAAI,EAAGA,EAAIP,EAAQ2W,MAAOpW,IAC3B6S,GAAUpT,EAAQuW,QAGtB,KADAW,EAAe9D,EAAO7R,MAAM4U,OACvB5V,EAAI,EAAGA,EAAI2W,EAAa1W,OAAQD,IAEjC,GADA4W,EAAKD,EAAa3W,GACd,MAAM8W,KAAKF,GACXD,EAAa5D,OAAO/S,IAAK,OAD7B,CAKA,GADA6W,EAAOZ,EAAOc,YAAYH,EAAInX,EAAQa,KACV,IAAxBqW,EAAa1W,QAAgB2W,IAAO/D,EAAQ,CAC5C,GAAItT,EAAK8B,UAAUwV,GAAO,CACtBhE,EAAStR,WAAWsV,EAAM,GAC1B,OAEJ,GAAI,iBAAiBC,KAAKD,GAAO,CAC7BhE,EAAkB,SAATgE,GAAkB,EAAgB,UAATA,GAAmB,EAAQA,CAC7D,QAGRhE,EAASA,EAAOlR,QAAQiV,EAAIC,QAGhChE,GAASpT,EAAQmE,MAAQ/B,EAAO4B,OAAOhE,EAAQ2W,OAAS3W,EAAQuW,QAEpE,OAAOnD,MAGfoD,EAAOzW,QACHwX,KAAM,WACF,GAAI5Q,KACJ,KAAK,GAAI3F,KAAOoB,GAAQuE,EAAG3F,EAAIQ,eAAiBR,CAChD,OAAO2F,IAEX2Q,YAAa,SAASA,EAAazW,GAC/BsV,EAAaqB,KAAK,GAClB,IAAIP,GAAQd,EAAaqB,KAAKF,GAActW,EAAMiW,GAASA,EAAM,GAAIQ,EAAOzW,GAAOA,EAAIQ,cAAekW,EAAOjX,KAAK8W,OAAOE,GAAOE,EAASV,GAASA,EAAM,GAAKA,EAAM,GAAGxV,MAAM,UAC5K,IAAIZ,GAAOG,IAAOH,GAAK,MAAOA,GAAIG,EAClC,MAAMA,IAAOoB,IAAaqV,IAAQrV,IAAasV,IAAQtV,IAAS,MAAOkV,EACvE,KAAK,GAAI/W,GAAI,EAAGA,EAAIoX,EAAOnX,OAAQD,IAC/B4V,EAAaqB,KAAK,IACdrB,EAAakB,KAAKM,EAAOpX,MACzBoX,EAAOpX,GAAKiW,EAAOc,YAAYK,EAAOpX,GAAIM,GAGlD,IAAI+W,GAASxV,EAAOpB,IAAQoB,EAAOqV,IAASrV,EAAOsV,EACnD,QAAQ5X,EAAKmB,KAAK2W,IAChB,IAAK,QACH,MAAOxV,GAAO0F,KAAK8P,EAErB,KAAK,WACH,GAAIjR,GAAKiR,EAAO3P,MAAM7F,EAAQuV,EAE9B,OADIhR,KAAOjH,IAAWiH,EAAK,IACpBA,MAKnBhH,EAAKkY,QAAU,SAAiBC,GAC5B,QAASC,KACL,OACIC,KAAMF,EAAO3V,KACb8V,KAAMH,EAAO3V,KACb+V,sBAAuBJ,EAAO3V,KAC9BgW,WAAY,EACZC,OAAQ,KAGhB,QAASC,GAAQjC,GACb,MAAO,YACH,MAAOzW,GAAKyW,KAAK0B,EAAOQ,WAAWlC,EAAKG,UAAYH,EAAKG,WAAaH,EAAKG,WAGnF,QAASgC,GAAUvY,GACf,IAAK,GAAIwY,KAAQ7Y,GAAKE,QAAS,CAC3B,GAAIuW,GAAOzW,EAAKE,QAAQ2Y,EACxB,KAA+B,WAA3BV,EAAO7W,KAAKmV,EAAKC,OACbD,EAAKC,OAASrW,EAAQ+T,OAEC,WAA3B+D,EAAO7W,KAAKmV,EAAKC,OACZD,EAAKC,KAAKgB,KAAKrX,EAAQ+T,MADhC,CAGA/T,EAAQyY,WAAaJ,EAAQjC,GAC7BpW,EAAQ0Y,WAAW,aAAeL,EAAQjC,GAC1CpW,EAAQ2Y,IAAMZ,CACd,SAMR,MAHAD,GAAOc,cAAc,IAAKL,GAC1BT,EAAOc,cAAc,OAAQL,GAC7BT,EAAOc,cAAc,QAASL,GACvB5Y,GAEU,mBAAVmY,SAAuBnY,EAAKkY,QAAQC,QAC3B,mBAATe,QAAwBA,MAAMC,MACrCnZ,EAAKkY,QAAU,SAAiBgB,GAC5B,GAAIE,GAAiBF,EAAMG,GACvBL,GACAR,WAAY,EACZc,aAAc,GACdC,YAAa,KACbjE,MAAO,EACPmD,OAAQ,IACRe,WAAY,UACZC,aAAc,KAElBP,GAAMG,GAAK,SAAShZ,GAChB,IAAK,GAAIwY,KAAQ7Y,GAAKE,QAAS,CAC3B,GAAIuW,GAAOzW,EAAKE,QAAQ2Y,EACxB,KAA8B,WAA1BK,EAAM5X,KAAKmV,EAAKC,OACZD,EAAKC,OAASrW,EAAQ+T,OAEA,WAA1B8E,EAAM5X,KAAKmV,EAAKC,OACXD,EAAKC,KAAKgB,KAAKrX,EAAQ+T,MADhC,CAGAsF,QAAQC,IAAI,SAAUtZ,EAAQ+T,IAAK,IAAKqC,EAAKC,KAC7C,IAAIkD,GAAO5Z,EAAKyW,KAAKA,EAAKG,SAI1B,OAHA8C,SAAQC,IAAI,SAAUC,GAClBvZ,EAAQwZ,SAASxZ,EAAQwZ,QAAQD,EAAM,UAAWZ,GAClD3Y,EAAQyZ,UAAUzZ,EAAQyZ,SAASF,EAAM,UAAWZ,GACjDE,GAEX,MAAOE,GAAe9Q,MAAMxH,KAAMH,cAK9CX,EAAKG,KAAOA,EACZH,EAAKyC,OAASA,EACdzC,EAAKqC,QAAUlC,EAAKkC,QACE,gBAAX0X,SAAuBA,OAAOC,QACrCD,OAAOC,QAAUha,EACQ,kBAAXia,SAAyBA,OAAOC,IAC9CD,OAAO,WACH,MAAOja,KAEc,kBAAXia,SAAyBA,OAAOE,KAC9CF,OAAO,WACH,MAAOja,KAGfc,KAAKd,KAAOA,EACZc,KAAK2B,OAASA,EACM,mBAATyW,QACP/Y,EAAKc,MAAO,OAAQ,wBAAyB,iBAAkB,2BAA4B,4BAA8B,SAAkBX,GACvI4Y,MAAMC,IAAI7Y,EAAM,SAASqG,GAErB,MADA3G,GAAKkY,QAAQvR,GACN3G,IAEPoa,UAAY,YAKxB,SAAUra,GACN,GAAIsa,IACApa,QAAS,QAERa,MAAKd,OAAM+Z,OAAOC,QAAUK,GACjCra,EAAKsa,IAAM,SAASC,EAAOla,EAASma,EAASC,GACzC,MAAOJ,GAAS5D,KAAK8D,EAAOla,EAASma,EAASC,IAElDza,EAAK0a,MAAQ,SAASH,GAClB,MAAOI,YAAWD,MAAMH,IAE5BF,EAAS5D,KAAO,SAAS8D,EAAOla,EAASma,EAASC,GAG9C,MAFAD,GAAUA,EAAUra,EAAKC,UAAWoa,EAASG,WAAWH,SAAWG,WAAWH,QAC9EC,EAAWA,EAAWta,EAAKC,UAAWqa,EAAUE,WAAWF,UAAYE,WAAWF,SAC3E5D,EAAOC,IAAIyD,EAAO,KAAMla,EAASma,EAASC,GAErD,IAAI5D,IACA+D,MAAOP,EAASO,QAAS,EACzBxa,OAAQD,EAAKC,OAEjByW,GAAOC,IAAM,SAAS+D,EAAMzZ,EAASf,EAASma,EAASC,GACnD,GAAIta,EAAK2a,SAASD,GAAO,CACrB,GAAIE,GAAMJ,WAAWD,MAAMG,EAC3Bxa,GAAUwW,EAAOmE,aAAaH,EAAMxa,EACpC,IAAIuZ,GAAO/C,EAAOC,IAAIiE,EAAK3Z,EAASf,EAASma,EAASC,EACtD,OAAOb,GAIX,GAFAxY,EAAUA,QACVf,EAAUA,MACNS,KAAK+Z,EAAKvZ,QAAUnB,EAAKqC,KAA7B,CACAnC,EAAQ4a,OAAS5a,EAAQ4a,YACrBZ,EAASO,OAAS/D,EAAO+D,SACzBlB,QAAQC,MACRD,QAAQwB,MAAM,IAAML,EAAKvZ,KAAO,IAAK6Z,KAAKC,UAAUP,IACpDnB,QAAQC,IAAI,YAAatZ,EAAQ4a,OAAOpa,OAAQsa,KAAKC,UAAU/a,IAEnE,IAAIgb,GAAYhb,EAAQ4a,OAAOpa,MAM/B,OALAC,MAAK+Z,EAAKvZ,MAAMuZ,EAAMzZ,EAASf,EAASma,EAASC,GACjDpa,EAAQ4a,OAAOtH,OAAO0H,IAClBhB,EAASO,OAAS/D,EAAO+D,QACzBlB,QAAQ4B,WAELla,EAAQA,EAAQP,OAAS,KAEpCgW,EAAOmE,aAAe,SAAST,EAAOla,GAClC,GACgDO,GAAG2a,EAAIC,EADnDC,EAAW,2CACXC,EAAWnB,EAAM3Y,MAAM6Z,GAAWhY,IACtC,KAAK7C,EAAI,EAAG8a,GAAY9a,EAAI8a,EAAS7a,OAAQD,IACzC6a,EAASE,UAAY,EACrBJ,EAAKE,EAAS5D,KAAK6D,EAAS9a,IACxB2a,IACAC,EAAS,GAAII,UAAS,UAAYL,EAAG,IACrCC,EAASA,IACTrb,EAAKC,OAAOqD,EAAK+X,GAGzB,OAAOrb,GAAKC,OAAOqD,EAAKpD,IAE5BwW,EAAOgF,IAAM,SAASvb,EAAMD,EAASe,EAAS0a,GAC1C,GAAIxb,IAASD,EAAQ4a,OAAO5a,EAAQ4a,OAAOpa,OAAS,GAAI,KAAM,IAAIkb,OAAMzb,EAAO,MAAQD,EAAQ4a,OAG/F,KAFIZ,EAASO,OAAS/D,EAAO+D,QAAOlB,QAAQC,IAAI,YAAarZ,EAAMD,EAAQ4a,QACvEa,IAAQ/b,IAAW+b,EAAM9b,EAAKyW,KAAKqF,IACnCzb,EAAS,CACT,GAAI2b,GAAShc,EAAKyW,KAAKpW,EACvB,IAAIF,EAAK2a,SAASkB,GAAS,MAAOA,EAClC,IAAI1b,IAAQ0b,GACR,MAAOA,GAAO1b,GAGtB,MAAIH,GAAKY,QAAQK,EAAQ,OAClB0a,IAAQ/b,EAAY+b,EAAMxb,GAAQmC,EAAO0Q,QAEpD0D,EAAOoF,QAAU,SAASpB,EAAMzZ,EAASf,EAASma,EAASC,GACvD,IAAK,GAAI7Z,GAAI,EAAGA,EAAIia,EAAKqB,WAAWrb,OAAQD,IACxCE,KAAKgW,IAAI+D,EAAKqB,WAAWtb,GAAIQ,EAASf,EAASma,EAASC,IAGhE5D,EAAOsF,SAAW,SAAStB,EAAMzZ,EAASf,EAASma,EAASC,GACxD,GAAI7Z,GAAGwb,EAAiBhb,EAAQ,GAAIib,EAAgBjb,EAAQP,MAM5D,IALkC,UAA9BV,EAAKmB,KAAK8a,KACVA,EAAenV,SACfmV,EAAiBA,EAAeA,EAAevb,OAAS,GACxDO,EAAQkb,QAAQF,IAEhBvB,EAAK0B,UAAY/B,GAAWA,EAAQK,EAAK7E,GAAG3R,QAAS,CACrD,GAA2B,IAAvBwW,EAAK7C,OAAOnX,YACZ,KAAKD,EAAI,EAAGA,EAAIia,EAAK7C,OAAOnX,OAAQD,IAChCE,KAAKgW,IAAI+D,EAAK7C,OAAOpX,GAAIQ,EAASf,EAASma,EAASC,EAGxDI,GAAK2B,MAAM1b,KAAKgW,IAAI+D,EAAK2B,KAAMpb,EAASf,EAASma,EAASC,OAE9D3Z,MAAKgW,IAAI+D,EAAK7E,GAAI5U,EAASf,EAASma,EAASC,EAE7CrZ,GAAQP,OAASwb,GAAejb,EAAQuS,OAAO,EAAGvS,EAAQP,OAASwb,IAE3ExF,EAAO4F,MAAQ,SAAS5B,EAAMzZ,EAASf,EAASma,EAASC,GACrD,GAAoC7Z,GAAGgE,EAAK/B,EAAKgZ,EAAKva,EAAlDgW,EAAQuD,EAAKsB,SAASnG,GAAGsB,MAA+B8E,EAAiBhb,EAAQ,GAAIib,EAAgBjb,EAAQP,MAEjH,IADIga,EAAK6B,QACL7B,EAAKsB,SAASI,UAAY/B,GAAWA,EAAQK,EAAKsB,SAASnG,GAAG3R,QAC9D/C,EAAOgW,EAAM,GACbuE,GAAOc,EAAQrb,IAASqb,EAAQC,QAAQtU,MAAMxH,KAAMH,WACpDyb,EAAiBhb,EAAQ,OAEzB,KAAKR,EAAI,EAAGA,EAAI0W,EAAMzW,OAAQD,IAC1BP,EAAQ4a,OAAOhU,KAAKqQ,EAAM1W,IAC1BiC,EAAMyU,EAAM1W,GACZib,EAAM/a,KAAK+a,IAAIhZ,EAAKxC,EAASe,MAC7Bgb,EAAevZ,GAAO1C,EAAKY,QAAQ8a,QAAcA,EACjDva,EAAOnB,EAAKmB,KAAK8a,EAAevZ,KACnB,WAATvB,GAA8B,UAATA,KACrB8a,EAAiBA,EAAevZ,GAChCzB,EAAQkb,QAAQF,GAI5B,IAAIvB,EAAKoB,QACL,GAAkC,UAA9B9b,EAAKmB,KAAK8a,GAEV,IADAxX,EAAMiX,EAAIhb,QAAU4B,EAAOW,QAAQ,EAAG,GACjCxC,EAAI,EAAOgE,EAAJhE,EAASA,IACjBwb,EAAenV,KAAuB,mBAAX4U,GAAIjb,GAAqBib,EAAIjb,OACxDP,EAAQ4a,OAAOhU,KAAK,MACpB7F,EAAQkb,QAAQF,EAAeA,EAAevb,OAAS,IACvDC,KAAKgW,IAAI+D,EAAKoB,QAAS7a,EAASf,EAASma,EAASC,GAClDpa,EAAQ4a,OAAO4B,MACfzb,EAAQ0b,YAEThc,MAAKgW,IAAI+D,EAAKoB,QAAS7a,EAASf,EAASma,EAASC,EAEzDrZ,GAAQP,OAASwb,GAAejb,EAAQuS,OAAO,EAAGvS,EAAQP,OAASwb,IAE3ExF,EAAO2F,KAAO,SAAS3B,EAAMzZ,EAASf,EAASma,EAASC,GACpD,GAAwBsC,GAAMnc,EAAGwW,EAA7B4F,EAAQnC,EAAKmC,KACjB,KAAKpc,EAAI,EAAGA,EAAIoc,EAAMnc,OAAQD,IAE1B,IADAmc,EAAOC,EAAMpc,GACRwW,EAAI,EAAGA,EAAI2F,EAAKlc,OAAQuW,IACzBtW,KAAKgW,IAAIiG,EAAK3F,GAAIhW,EAASf,EAASma,EAASC,IAIzD5D,EAAOoG,GAAK,SAASpC,EAAMzZ,EAASf,GAChC,GAAwBO,GAAGgE,EAAK/B,EAAKqa,EAAMpB,EAAKD,EAAKva,EAAM6b,EAASC,EAAhE9F,EAAQuD,EAAKvD,MAA+D8E,EAAiBhb,EAAQyZ,EAAKwC,OAAQhB,EAAgBjb,EAAQP,MAE9I,IADIV,EAAKY,QAAQqb,KAAiBA,EAAiBhb,EAAQyZ,EAAKwC,MAAQ,IACnE/F,EAAMzW,OACP,IAAKD,EAAI,EAAGgE,EAAM0S,EAAMzW,OAAY+D,EAAJhE,EAASA,IACrCP,EAAQ4a,OAAOhU,KAAKqQ,EAAM1W,IAC1BiC,EAAMyU,EAAM1W,GACZsc,EAAO5F,EAAM1W,EAAI,GACjBwc,EAAa/c,EAAQ6c,GACrBpB,EAAMlb,IAAMgE,EAAM,EAAIwX,EAAevZ,MACrCgZ,EAAM/a,KAAK+a,IAAIhZ,EAAKxC,EAASe,EAAS0a,GACtCxa,EAAOnB,EAAKmB,KAAK8a,EAAevZ,IAChCsa,EAAUhd,EAAKmB,KAAKua,GACP,cAATva,EAEI8a,EAAevZ,GADX+B,EAAM,EAAVhE,GAA2B,WAAZuc,GAAoC,UAAZA,KAGjBhd,EAAKY,QAAQ8a,QAAcA,EAG7CjX,EAAM,EAAVhE,GAAwB,WAATU,GAA8B,UAATA,IACpC8a,EAAevZ,GAAO1C,EAAKY,QAAQ8a,YAG3Cva,EAAOnB,EAAKmB,KAAK8a,EAAevZ,KACnB,WAATvB,GAA8B,UAATA,KACrB8a,EAAiBA,EAAevZ,GAChCzB,EAAQkb,QAAQF,SAIxBhb,EAAQP,OAASwb,GAAejb,EAAQuS,OAAO,EAAGvS,EAAQP,OAASwb,IAE3ExF,EAAOyG,QAAU,SAASzC,EAAMzZ,EAASf,EAASma,EAASC,GACvD,GAAIna,GAAOua,EAAK0C,YAAYjd,KAAMgd,EAAU7C,GAAYA,EAASna,GAAO+b,EAAgBjb,EAAQP,MAC5Fyc,IAASzG,EAAOC,IAAIwG,EAASlc,EAASf,EAASma,EAASC,GACxDrZ,EAAQP,OAASwb,GAAejb,EAAQuS,OAAO,EAAGvS,EAAQP,OAASwb,IAE3ExF,EAAO2G,QAAUrd,EAAKqC,KACtBqU,EAAO4G,aAAetd,EAAKqC,KAC3BqU,EAAO6G,KAAOvd,EAAKqC,KACnBqU,EAAO8G,OAASxd,EAAKqC,KACrBqU,EAAO+G,QAAUzd,EAAKqC,KACtBqU,EAAOgH,QAAU1d,EAAKqC,KACtBqU,EAAOiH,QAAU3d,EAAKqC,IACtB,IAAIma,KACJA,GAAQ1b,KAAO,SAAS4Z,EAAMzZ,EAASf,GACnC,GAAIO,GAAGgE,EAAK/B,EAAKgZ,EAAKvE,EAAOwE,EAAKxa,EAAM8a,EAAiBhb,EAAQ,EAEjE,KADAkW,EAAQuD,EAAKsB,SAASnE,OAAO,GAAGV,MAC3B1W,EAAI,EAAGgE,EAAM0S,EAAMzW,OAAY+D,EAAJhE,EAASA,IACrCP,EAAQ4a,OAAOhU,KAAKqQ,EAAM1W,IAC1BiC,EAAMyU,EAAM1W,GACZkb,EAAMlb,IAAMgE,EAAM,QAClBiX,EAAM/a,KAAK+a,IAAIhZ,EAAKxC,EAASe,EAAS0a,GACtCM,EAAevZ,GAAO1C,EAAKY,QAAQ8a,QAAcA,EACjDva,EAAOnB,EAAKmB,KAAK8a,EAAevZ,KACnB,WAATvB,GAA8B,UAATA,KACrB8a,EAAiBA,EAAevZ,GAChCzB,EAAQkb,QAAQF,GAGxB,OAAOP,IAEXc,EAAQ,MAAQA,EAAQoB,OAAS,SAASlD,EAAMzZ,EAASf,GACrD,GAAmCO,GAAGwW,EAAGvU,EAAKgZ,EAAKvE,EAAOwE,EAAKxa,EAA3D0W,EAAS6C,EAAKsB,SAASnE,OAA0CoE,EAAiBhb,EAAQ,EAC9F,KAAKR,EAAI,EAAGA,EAAIoX,EAAOnX,OAAQD,IAE3B,IADA0W,EAAQU,EAAOpX,GAAG0W,MACbF,EAAI,EAAGA,EAAIE,EAAMzW,OAAQuW,IAChB,IAANxW,GAASP,EAAQ4a,OAAOhU,KAAKqQ,EAAMF,IACvCvU,EAAMyU,EAAMF,GACZ0E,EAAM1E,IAAME,EAAMzW,OAAS,EAAI,qBAC/Bgb,EAAM/a,KAAK+a,IAAIhZ,EAAKxC,EAASe,EAAS0a,GAClC1E,IAAME,EAAMzW,OAAS,IACrBgb,EAAc,SAARA,GAAiB,EAAe,UAARA,GAAkB,EAAQA,GAE5DO,EAAevZ,GAAO1C,EAAKY,QAAQ8a,MAAYA,EAC/Cva,EAAOnB,EAAKmB,KAAK8a,EAAevZ,KACnB,WAATvB,GAA8B,UAATA,KACrB8a,EAAiBA,EAAevZ,GAChCzB,EAAQkb,QAAQF,GAI5B,OAAOP,IAEXc,EAAQ,QAAU,SAAS9B,EAAMzZ,EAASf,GACtC,GAAIO,GAAGiC,EAAKgZ,EAAKvE,EAAOwE,EAAKM,EAAiBhb,EAAQ,EAEtD,KADAkW,EAAQuD,EAAKsB,SAASnE,OAAO,GAAGV,MAC3B1W,EAAI,EAAGA,EAAI0W,EAAMzW,OAAQD,IAC1BP,EAAQ4a,OAAOhU,KAAKqQ,EAAM1W,IAC1BiC,EAAMyU,EAAM1W,GACZkb,KACAD,EAAM/a,KAAK+a,IAAIhZ,EAAKxC,EAASe,EAAS0a,GACtCM,EAAiBA,EAAevZ,GAAOgZ,EACvCza,EAAQkb,QAAQF,EAEpB,OAAOP,IAEXc,EAAQhD,IAAM,aACdgD,EAAQC,OAAS,SAAS/B,EAAMzZ,EAASf,GACrC,GAAIO,GAAGgE,EAAK/B,EAAKgZ,EAAKvE,EAAOwE,EAAKxa,EAAM8a,EAAiBhb,EAAQ,EACjE,IAAoC,IAAhCyZ,EAAKsB,SAASnE,OAAOnX,OAAzB,CAcI,IADAyW,EAAQuD,EAAKsB,SAASnE,OAAO,GAAGV,MAC3B1W,EAAI,EAAGgE,EAAM0S,EAAMzW,OAAY+D,EAAJhE,EAASA,IACrCP,EAAQ4a,OAAOhU,KAAKqQ,EAAM1W,IAC1BiC,EAAMyU,EAAM1W,GACZkb,EAAMlb,IAAMgE,EAAM,QAClBiX,EAAM/a,KAAK+a,IAAIhZ,EAAKxC,EAASe,EAAS0a,GACtCM,EAAevZ,GAAO1C,EAAKY,QAAQ8a,QAAcA,EACjDva,EAAOnB,EAAKmB,KAAK8a,EAAevZ,KACnB,WAATvB,GAA8B,UAATA,KACrB8a,EAAiBA,EAAevZ,GAChCzB,EAAQkb,QAAQF,GAI5B,OAAOP,MAEZta,KAAKT,MAER,SAAUf,GACN,GAAqB,mBAAVmZ,OAAX,CACA,GAGI8E,GAHAC,GACArD,OAAO,EAGX1B,OAAMgF,IAAI,YAAa,SAASvX,EAAGwX,GAC/BH,EAAYG,IAEXrd,KAAKd,OAAM+Z,OAAOC,QAAUiE,GACjCje,EAAKoe,KAAO,SAAS7D,EAAOla,EAASma,EAASC,GAC1C,MAAOwD,GAAUxH,KAAK8D,EAAOla,EAASma,EAASC,IAEnDza,EAAKqe,OAAS,SAAS9D,GACnB,MAAOyD,GAAUM,SAAS5D,MAAMH,IAEpC0D,EAAUxH,KAAO,SAAS8D,EAAOla,EAASma,EAASC,GAG/C,MAFAD,GAAUA,EAAUra,EAAKC,UAAWoa,EAASwD,EAAUO,QAAQC,UAAYR,EAAUO,QAAQC,SAC7F/D,EAAWA,EAAWta,EAAKC,UAAWqa,EAAUuD,EAAUO,QAAQE,SAAWT,EAAUO,QAAQE,QACxF3d,KAAKgW,IAAIyD,EAAO,KAAMla,EAASma,EAASC,OAEnDwD,EAAUvD,MAAQ,SAASH,GACvB,MAAOyD,GAAUM,SAAS5D,MAAMH,IAEpC0D,EAAUnH,IAAM,SAAS+D,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GAChE,GAAoB,gBAAT7D,GAAmB,CACtBoD,EAAUrD,OACVlB,QAAQC,IAAI,cAAekB,EAE/B,IAAIE,GAAMja,KAAK4Z,MAAMG,EACrBxa,GAAUS,KAAKka,aAAaH,EAAMxa,EAClC,IAAIuZ,GAAO9Y,KAAKgW,IAAIiE,EAAK3Z,EAASf,EAASma,EAASC,EAAUiE,EAC9D,OAAO9E,GAKX,GAHAxY,EAAUA,QACVf,EAAUA,MACVwa,EAAKvZ,KAAOuZ,EAAKvZ,KACbR,KAAK+Z,EAAKvZ,QAAUnB,EAAKqC,KAA7B,CACAnC,EAAQ4a,OAAS5a,EAAQ4a,WACrBgD,EAAUrD,QACVlB,QAAQC,MACRD,QAAQwB,MAAM,IAAML,EAAKvZ,KAAO,IAAK6Z,KAAKC,UAAUP,IACpDnB,QAAQC,IAAI,YAAa,WAAYvY,EAAQP,OAAQsa,KAAKC,UAAUha,IACpEsY,QAAQC,IAAI,YAAa,WAAYtZ,EAAQ4a,OAAOpa,OAAQsa,KAAKC,UAAU/a,IAC3EqZ,QAAQC,IAAI,YAAa,WAAYwB,KAAKC,UAAUsD,IAExD,IAAIrD,GAAYhb,EAAQ4a,OAAOpa,MAY/B,OAXAC,MAAK+Z,EAAKvZ,MAAMuZ,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GACvDT,EAAUrD,OACVlB,QAAQC,IAAI,YAAa,WAAYtZ,EAAQ4a,UAE5CyD,EAAMC,MAA8B,kBAAfD,GAAMC,OAAwBD,EAAMC,KAAK9D,EAAMxa,EAASe,KAC9Ef,EAAQ4a,OAAOtH,OAAO0H,GAEtB4C,EAAUrD,QACVlB,QAAQC,IAAI,YAAa,WAAYvY,EAAQP,OAAQsa,KAAKC,UAAUha,IACpEsY,QAAQ4B,YAELla,EAAQA,EAAQP,OAAS,KAEpCod,EAAUjD,aAAe,SAAST,EAAOla,GACrC,GACgDO,GAAG2a,EAAIC,EADnDC,EAAW,2CACXC,EAAWnB,EAAM3Y,MAAM6Z,GAAWhY,IACtC,KAAK7C,EAAI,EAAG8a,GAAY9a,EAAI8a,EAAS7a,OAAQD,IACzC6a,EAASE,UAAY,EACrBJ,EAAKE,EAAS5D,KAAK6D,EAAS9a,IACxB2a,IACAC,EAAS,GAAII,UAAS,UAAYL,EAAG,IACrCC,EAASA,IACTrb,EAAKC,OAAOqD,EAAK+X,GAGzB,OAAOrb,GAAKC,OAAOqD,EAAKpD,IAE5B4d,EAAUW,SAAW,SAASC,EAAMxH,GAChC,QAASyH,GAAWC,EAAM3d,GACtB,GAAuB,gBAAZA,IAAwB2d,IAAQ3d,GAAS,OAASA,EAAQ2d,GAErE,KAAK,GADDtb,MACK7C,EAAI,EAAGA,EAAIQ,EAAQP,OAAQD,IAChC6C,EAAIwD,KAAKqB,MAAM7E,EAAKub,EAAMD,GAAQ3d,EAAQR,KAE9C,OAAO6C,GAEX,QAASwb,GAAYF,EAAM3d,GACvB,GAAuB,gBAAZA,IAAwB2d,IAAQ3d,GAAS,OAASA,EAAQ2d,GACrE,IAAItb,KACJ,KAAK,GAAIpC,KAAOD,GACZqC,EAAIwD,KAAKqB,MAAM7E,EAAKub,EAAMD,GAAQ3d,EAAQC,KAE9C,OAAOoC,GAEX,QAASub,GAAMD,EAAMG,GAEjB,IAAK,GADDzb,MACK7C,EAAI,EAAGA,EAAIse,EAAIre,OAAQD,IACN,gBAAXse,GAAIte,KACXme,IAAQG,GAAIte,GAAI6C,EAAIwD,KAAKiY,EAAIte,GAAGme,IAChCtb,EAAIwD,KAAKqB,MAAM7E,EAAKtD,EAAKY,QAAQme,EAAIte,IAAMke,EAAWC,EAAMG,EAAIte,IAAMqe,EAAYF,EAAMG,EAAIte,KAGpG,OAAO6C,GAEX,QAASiX,GAAMmE,EAAMzd,GAEjB,IADA,GAAIkW,GAAwB,gBAATuH,GAAoBA,EAAK/c,MAAM,KAAO+c,EAAKxZ,MAAM,GAAI6Z,GAAQ9d,GACzEkW,EAAMzW,QACTqe,EAAMF,EAAM1H,EAAMwF,QAASoC,EAE/B,OAAOA,GAEX,MAAOxE,GAAMmE,EAAMxH,IAEvB4G,EAAUpC,IAAM,SAASvb,EAAMD,EAASe,EAAS0a,GAC7C,GAAIxb,IAASD,EAAQ4a,OAAO5a,EAAQ4a,OAAOpa,OAAS,GAAI,KAAM,IAAIkb,OAAMzb,EAAO,MAAQD,EAAQ4a,OAE/F,IADIa,IAAQ/b,IAAW+b,EAAM9b,EAAKyW,KAAKqF,IACnCzb,EAAS,CACT,GAAI2b,GAAShc,EAAKyW,KAAKpW,EACvB,IAAIF,EAAK2a,SAASkB,GAAS,MAAOA,EAClC,IAAIvY,GAAMwa,EAAUW,SAASve,EAAQ4a,OAAQe,EAC7C,IAAIvY,EAAI5C,OAAS,EAAG,MAAO4C,GAAI,EAC/B,IAAInD,IAAQ0b,GACR,MAAOA,GAAO1b,GAGtB,MAAIH,GAAKY,QAAQK,EAAQ,OAClB0a,IAAQ/b,EAAY+b,EAAMxb,GAErC2d,EAAUhC,QAAU,SAASpB,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GACpE,IAAK,GAAI9d,GAAI,EAAGA,EAAIia,EAAKqB,WAAWrb,OAAQD,IACxCE,KAAKgW,IAAI+D,EAAKqB,WAAWtb,GAAIQ,EAASf,EAASma,EAASC,EAAUiE,EAEtE,KAAK,GAAItH,GAAI,EAAGyD,EAAK6B,SAAWtF,EAAIyD,EAAK6B,QAAQ7b,OAAQuW,IACrDtW,KAAKgW,IAAI+D,EAAK6B,QAAQtF,GAAIhW,EAASf,EAASma,EAASC,EAAUiE,IAGvET,EAAUxB,MAAQ,SAAS5B,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GAClE,GAAIrC,GAAgBjb,EAAQP,MAC5BC,MAAKgW,IAAI+D,EAAKP,IAAKlZ,EAASf,EAASma,EAASC,EAAUta,EAAKC,UAAWse,GACpE5C,OACA6C,MAAM,IAEV,IAAiC3C,GAAQpb,EAAGgE,EAAxCwX,EAAiBhb,EAAQ,EAC7B,IAAkC,UAA9BjB,EAAKmB,KAAK8a,GAGV,IAFAJ,EAASlb,KAAK+a,IAAIxb,EAAQ4a,OAAO5a,EAAQ4a,OAAOpa,OAAS,GAAIR,EAASe,GACtEwD,EAAMoX,GAAUA,EAAOnb,QAAU4B,EAAOW,QAAQ,EAAG,GAC9CxC,EAAI,EAAOgE,EAAJhE,EAASA,IACjBwb,EAAenV,KAAK+U,GAAUA,EAAOpb,KAAOb,EAAYic,EAAOpb,OAC/DP,EAAQ4a,OAAOhU,KAAKrG,GACpBQ,EAAQkb,QAAQF,EAAeA,EAAevb,OAAS,IACvDC,KAAKgW,IAAI+D,EAAKoB,QAAS7a,EAASf,EAASma,EAASC,EAAUiE,GAC5Dre,EAAQ4a,OAAO4B,MACfzb,EAAQ0b,YAEThc,MAAKgW,IAAI+D,EAAKoB,QAAS7a,EAASf,EAASma,EAASC,EAAUiE,KAC9DA,EAAMC,MAA8B,kBAAfD,GAAMC,OAAwBD,EAAMC,KAAK9D,EAAMxa,EAASe,KAC9EA,EAAQuS,OAAO,EAAGvS,EAAQP,OAASwb,IAG3C4B,EAAU3D,IAAM,SAASO,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GAChE,GAAI7D,EAAK7C,QAAU6C,EAAK7C,OAAOnX,OAAQ,CACnC6d,EAAQve,EAAKC,UAAWse,GACpB5C,KACI7a,QACAke,KAAM,kBACNpB,OAAQ,mBACRqB,WACFvE,EAAKwE,KAAKhb,QACZsa,MACI1d,MAAM,EACNke,KAAM,SAASG,EAAGC,EAAIC,EAAKlf,EAAMyB,GAC7B,MAAwB,gBAAVA,IAElBgc,OAAQ,SAASuB,EAAGC,EAAIC,EAAKlf,EAAMyB,GAC/B,MAAwB,gBAAVA,IAElBqd,QAAQ,EACRK,SAAS,GACX5E,EAAKwE,KAAKhb,SAEhB,KAAK,GAAWkW,GAAP3Z,EAAI,EAAUA,EAAIia,EAAK7C,OAAOnX,OAAQD,IAEvC2Z,EADqB,YAArBM,EAAKwE,KAAKhb,OACFoW,GAAYA,EAASI,EAAK7C,OAAOpX,GAAGmB,OACjC8Y,EAAK7C,OAAOpX,GACvB2Z,GAAOzZ,KAAKgW,IAAIyD,EAAOnZ,EAASf,EAASma,EAASC,EAAUiE,EAEhE7D,GAAK2B,MACL1b,KAAKgW,IAAI+D,EAAK2B,KAAMpb,EAASf,EAASma,EAASC,EAAUiE,OAG7D5d,MAAKgW,IAAI+D,EAAKwE,KAAMje,EAASf,EAASma,EAASC,EAAUiE,IAGjET,EAAUyB,cAAgB,SAAS7E,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GAC1E5d,KAAKgW,IAAI+D,EAAK8E,WAAYve,EAASf,EAASma,EAASC,EAAUiE,IAEnET,EAAUT,QAAUrd,EAAKqC,KACzByb,EAAU2B,gBAAkBzf,EAAKqC,KACjCyb,EAAU4B,yBAA2B5B,EAAU6B,mBAAqB,SAASjF,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GACpH5d,KAAKgW,IAAI+D,EAAKkF,IAAK3e,EAASf,EAASma,EAASC,EAAUta,EAAKC,UAAWse,GACpE5C,IAAK,WACD,MAAyB,WAAlBjB,EAAKmF,IAAI1e,KAAoBuZ,EAAKmF,IAAIje,MAAMqG,QAAQ,KAAO,GAAK3F,EAAOa,OAAOP,KAAKkd,IAAI,GAAI,IAAKld,KAAKkd,IAAI,GAAI,IAAK,EAAGld,KAAKkd,IAAI,GAAI,IAAMxd,EAAOW,UAAYrD,QAG1Ke,KAAKgW,IAAI+D,EAAKmF,IAAK5e,EAASf,EAASma,EAASC,EAAUta,EAAKC,UAAWse,GACpE5C,IAAK,WACD,MAAyB,WAAlBjB,EAAKkF,IAAIze,KAAoBuZ,EAAKkF,IAAIhe,MAAMqG,QAAQ,KAAO,GAAK3F,EAAOa,OAAOP,KAAKkd,IAAI,GAAI,IAAKld,KAAKkd,IAAI,GAAI,IAAK,EAAGld,KAAKkd,IAAI,GAAI,IAAMxd,EAAOW,UAAYrD,SAI9Kke,EAAUiC,qBAAuB,SAASrF,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GACjF5d,KAAKgW,IAAI+D,EAAKkF,IAAK3e,EAASf,EAASma,EAASC,EAAUiE,GACxD5d,KAAKgW,IAAI+D,EAAKmF,IAAK5e,EAASf,EAASma,EAASC,EAAUiE,IAE5DT,EAAUkC,mBAAqBhgB,EAAKqC,KACpCyb,EAAUmC,yBAA2BjgB,EAAKqC,KAC1Cyb,EAAUoC,wBAA0BlgB,EAAKqC,KACzCyb,EAAU5Z,OAASlE,EAAKqC,KACxByb,EAAUja,OAAS7D,EAAKqC,KACxByb,EAAUvb,QAAUvC,EAAKqC,KACzByb,EAAUzB,KAAO,SAAS3B,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GACjE,GAAwBrd,GAApB2b,EAAQnC,EAAK9Y,KACjB,KAAKV,IAAO2b,GACRlc,KAAKgW,IAAIkG,EAAM3b,GAAMD,EAASf,EAASma,EAASC,EAAUiE,IAGlET,EAAUjI,GAAK,SAAS6E,EAAMzZ,EAASf,EAASma,EAASC,EAAUiE,GAG/D,QAAS4B,GAAIlE,EAAgB1I,EAAO7S,EAAQP,EAAMub,GAC9C,GAAIva,GAAOnB,EAAKmB,KAAK8a,EAAe9b,IAAQ6c,EAAUhd,EAAKmB,KAAKua,EAiBhE,OAhBAA,GAAc,SAARA,GAAiB,EAAe,UAARA,GAAkB,EAAQA,EAC3C,cAATva,EAEI8a,EAAe9b,GADPO,EAAS,EAAjB6S,IAAuBvT,EAAK6B,gBAAgB6Z,MAGrB1b,EAAKY,QAAQ8a,QAAcA,EAG1Chb,EAAS,EAAjB6S,GAA+B,WAATpS,GAA8B,UAATA,EAC3C8a,EAAe9b,GAAQH,EAAKY,QAAQ8a,WAEvB,WAATva,GAA8B,UAATA,GAAgC,WAAZ6b,GAAoC,UAAZA,IACjEf,EAAe9b,GAAQub,GAI5BO,EAAe9b,GApB1B,GAC8DM,GAAGgE,EAAK/B,EAAKiZ,EAAKD,EAD5EQ,EAAgBjb,EAAQP,OACxByW,EAAQuD,EAAKvD,MAAO8E,EAAiBhb,EAAQyZ,EAAKwC,MAsBtD,KADIld,EAAKY,QAAQqb,KAAiBA,EAAiBhb,EAAQyZ,EAAKwC,MAAQ,IACnEzc,EAAI,EAAGgE,EAAM0S,EAAMzW,OAAY+D,EAAJhE,EAASA,KAC3B,IAANA,GAAwB,SAAb0W,EAAM1W,MACjB,yBAAyB8W,KAAKJ,EAAM1W,KAC9B,IAANA,GAAmB,IAARgE,GAAa0S,EAAM1W,IAAM4Z,KACxCna,EAAQ4a,OAAOhU,KAAKqQ,EAAM1W,IAC1BiC,EAAMyU,EAAM1W,GACZkb,EAAMlb,IAAMgE,EAAM,EAAI8Z,EAAM5C,MAAQ/b,EAAY2e,EAAM5C,IAAM1a,EAAQ,GAAGyB,MACvEgZ,EAAM/a,KAAK+a,IAAIhZ,EAAKxC,EAASe,EAAS0a,GAClCmC,EAAUrD,QACVlB,QAAQC,IAAI,YAAawB,KAAKC,UAAUU,IACxCpC,QAAQC,IAAI,YAAawB,KAAKC,UAAUS,KAE5CA,EAAMyE,EAAIlE,EAAgBxb,EAAGgE,EAAK/B,EAAKgZ,GACnC1b,EAAK6B,gBAAgBoa,EAAevZ,KACpCzB,EAAQkb,QAAQF,EAAiBA,EAAevZ,QAGnD6b,EAAMC,MAA8B,kBAAfD,GAAMC,OAAwBD,EAAMC,KAAK9D,EAAMxa,EAASe,EAASyB,EAAKgZ,KAC5Fza,EAAQuS,OAAO,EAAGvS,EAAQP,OAASwb,MAG5C9a,KAAKT,QACTS,KAAKT"} \ No newline at end of file diff --git a/src/main/webapp/stat/js/util/jquery-rapped.js b/src/main/webapp/stat/js/util/jquery-rapped.js new file mode 100644 index 000000000..ebbc3da41 --- /dev/null +++ b/src/main/webapp/stat/js/util/jquery-rapped.js @@ -0,0 +1,2807 @@ +define('jquery', [], function (require) { + + /*! jQuery v1.8.2 jquery.com | jquery.org/license */ + (function (a, b) { + function G(a) { + var b = F[a] = {}; + return p.each(a.split(s), function (a, c) { + b[c] = !0 + }), b + } + + function J(a, c, d) { + if (d === b && a.nodeType === 1) { + var e = "data-" + c.replace(I, "-$1").toLowerCase(); + d = a.getAttribute(e); + if (typeof d == "string") { + try { + d = d === "true" ? !0 : d === "false" ? !1 : d === "null" ? null : +d + "" === d ? +d : H.test(d) ? p.parseJSON(d) : d + } catch (f) { + } + p.data(a, c, d) + } else d = b + } + return d + } + + function K(a) { + var b; + for (b in a) { + if (b === "data" && p.isEmptyObject(a[b]))continue; + if (b !== "toJSON")return !1 + } + return !0 + } + + function ba() { + return !1 + } + + function bb() { + return !0 + } + + function bh(a) { + return !a || !a.parentNode || a.parentNode.nodeType === 11 + } + + function bi(a, b) { + do a = a[b]; while (a && a.nodeType !== 1); + return a + } + + function bj(a, b, c) { + b = b || 0; + if (p.isFunction(b))return p.grep(a, function (a, d) { + var e = !!b.call(a, d, a); + return e === c + }); + if (b.nodeType)return p.grep(a, function (a, d) { + return a === b === c + }); + if (typeof b == "string") { + var d = p.grep(a, function (a) { + return a.nodeType === 1 + }); + if (be.test(b))return p.filter(b, d, !c); + b = p.filter(b, d) + } + return p.grep(a, function (a, d) { + return p.inArray(a, b) >= 0 === c + }) + } + + function bk(a) { + var b = bl.split("|"), c = a.createDocumentFragment(); + if (c.createElement)while (b.length)c.createElement(b.pop()); + return c + } + + function bC(a, b) { + return a.getElementsByTagName(b)[0] || a.appendChild(a.ownerDocument.createElement(b)) + } + + function bD(a, b) { + if (b.nodeType !== 1 || !p.hasData(a))return; + var c, d, e, f = p._data(a), g = p._data(b, f), h = f.events; + if (h) { + delete g.handle, g.events = {}; + for (c in h)for (d = 0, e = h[c].length; d < e; d++)p.event.add(b, c, h[c][d]) + } + g.data && (g.data = p.extend({}, g.data)) + } + + function bE(a, b) { + var c; + if (b.nodeType !== 1)return; + b.clearAttributes && b.clearAttributes(), b.mergeAttributes && b.mergeAttributes(a), c = b.nodeName.toLowerCase(), c === "object" ? (b.parentNode && (b.outerHTML = a.outerHTML), p.support.html5Clone && a.innerHTML && !p.trim(b.innerHTML) && (b.innerHTML = a.innerHTML)) : c === "input" && bv.test(a.type) ? (b.defaultChecked = b.checked = a.checked, b.value !== a.value && (b.value = a.value)) : c === "option" ? b.selected = a.defaultSelected : c === "input" || c === "textarea" ? b.defaultValue = a.defaultValue : c === "script" && b.text !== a.text && (b.text = a.text), b.removeAttribute(p.expando) + } + + function bF(a) { + return typeof a.getElementsByTagName != "undefined" ? a.getElementsByTagName("*") : typeof a.querySelectorAll != "undefined" ? a.querySelectorAll("*") : [] + } + + function bG(a) { + bv.test(a.type) && (a.defaultChecked = a.checked) + } + + function bY(a, b) { + if (b in a)return b; + var c = b.charAt(0).toUpperCase() + b.slice(1), d = b, e = bW.length; + while (e--) { + b = bW[e] + c; + if (b in a)return b + } + return d + } + + function bZ(a, b) { + return a = b || a, p.css(a, "display") === "none" || !p.contains(a.ownerDocument, a) + } + + function b$(a, b) { + var c, d, e = [], f = 0, g = a.length; + for (; f < g; f++) { + c = a[f]; + if (!c.style)continue; + e[f] = p._data(c, "olddisplay"), b ? (!e[f] && c.style.display === "none" && (c.style.display = ""), c.style.display === "" && bZ(c) && (e[f] = p._data(c, "olddisplay", cc(c.nodeName)))) : (d = bH(c, "display"), !e[f] && d !== "none" && p._data(c, "olddisplay", d)) + } + for (f = 0; f < g; f++) { + c = a[f]; + if (!c.style)continue; + if (!b || c.style.display === "none" || c.style.display === "")c.style.display = b ? e[f] || "" : "none" + } + return a + } + + function b_(a, b, c) { + var d = bP.exec(b); + return d ? Math.max(0, d[1] - (c || 0)) + (d[2] || "px") : b + } + + function ca(a, b, c, d) { + var e = c === (d ? "border" : "content") ? 4 : b === "width" ? 1 : 0, f = 0; + for (; e < 4; e += 2)c === "margin" && (f += p.css(a, c + bV[e], !0)), d ? (c === "content" && (f -= parseFloat(bH(a, "padding" + bV[e])) || 0), c !== "margin" && (f -= parseFloat(bH(a, "border" + bV[e] + "Width")) || 0)) : (f += parseFloat(bH(a, "padding" + bV[e])) || 0, c !== "padding" && (f += parseFloat(bH(a, "border" + bV[e] + "Width")) || 0)); + return f + } + + function cb(a, b, c) { + var d = b === "width" ? a.offsetWidth : a.offsetHeight, e = !0, f = p.support.boxSizing && p.css(a, "boxSizing") === "border-box"; + if (d <= 0 || d == null) { + d = bH(a, b); + if (d < 0 || d == null)d = a.style[b]; + if (bQ.test(d))return d; + e = f && (p.support.boxSizingReliable || d === a.style[b]), d = parseFloat(d) || 0 + } + return d + ca(a, b, c || (f ? "border" : "content"), e) + "px" + } + + function cc(a) { + if (bS[a])return bS[a]; + var b = p("<" + a + ">").appendTo(e.body), c = b.css("display"); + b.remove(); + if (c === "none" || c === "") { + bI = e.body.appendChild(bI || p.extend(e.createElement("iframe"), { + frameBorder: 0, + width: 0, + height: 0 + })); + if (!bJ || !bI.createElement)bJ = (bI.contentWindow || bI.contentDocument).document, bJ.write(""), bJ.close(); + b = bJ.body.appendChild(bJ.createElement(a)), c = bH(b, "display"), e.body.removeChild(bI) + } + return bS[a] = c, c + } + + function ci(a, b, c, d) { + var e; + if (p.isArray(b))p.each(b, function (b, e) { + c || ce.test(a) ? d(a, e) : ci(a + "[" + (typeof e == "object" ? b : "") + "]", e, c, d) + }); else if (!c && p.type(b) === "object")for (e in b)ci(a + "[" + e + "]", b[e], c, d); else d(a, b) + } + + function cz(a) { + return function (b, c) { + typeof b != "string" && (c = b, b = "*"); + var d, e, f, g = b.toLowerCase().split(s), h = 0, i = g.length; + if (p.isFunction(c))for (; h < i; h++)d = g[h], f = /^\+/.test(d), f && (d = d.substr(1) || "*"), e = a[d] = a[d] || [], e[f ? "unshift" : "push"](c) + } + } + + function cA(a, c, d, e, f, g) { + f = f || c.dataTypes[0], g = g || {}, g[f] = !0; + var h, i = a[f], j = 0, k = i ? i.length : 0, l = a === cv; + for (; j < k && (l || !h); j++)h = i[j](c, d, e), typeof h == "string" && (!l || g[h] ? h = b : (c.dataTypes.unshift(h), h = cA(a, c, d, e, h, g))); + return (l || !h) && !g["*"] && (h = cA(a, c, d, e, "*", g)), h + } + + function cB(a, c) { + var d, e, f = p.ajaxSettings.flatOptions || {}; + for (d in c)c[d] !== b && ((f[d] ? a : e || (e = {}))[d] = c[d]); + e && p.extend(!0, a, e) + } + + function cC(a, c, d) { + var e, f, g, h, i = a.contents, j = a.dataTypes, k = a.responseFields; + for (f in k)f in d && (c[k[f]] = d[f]); + while (j[0] === "*")j.shift(), e === b && (e = a.mimeType || c.getResponseHeader("content-type")); + if (e)for (f in i)if (i[f] && i[f].test(e)) { + j.unshift(f); + break + } + if (j[0]in d)g = j[0]; else { + for (f in d) { + if (!j[0] || a.converters[f + " " + j[0]]) { + g = f; + break + } + h || (h = f) + } + g = g || h + } + if (g)return g !== j[0] && j.unshift(g), d[g] + } + + function cD(a, b) { + var c, d, e, f, g = a.dataTypes.slice(), h = g[0], i = {}, j = 0; + a.dataFilter && (b = a.dataFilter(b, a.dataType)); + if (g[1])for (c in a.converters)i[c.toLowerCase()] = a.converters[c]; + for (; e = g[++j];)if (e !== "*") { + if (h !== "*" && h !== e) { + c = i[h + " " + e] || i["* " + e]; + if (!c)for (d in i) { + f = d.split(" "); + if (f[1] === e) { + c = i[h + " " + f[0]] || i["* " + f[0]]; + if (c) { + c === !0 ? c = i[d] : i[d] !== !0 && (e = f[0], g.splice(j--, 0, e)); + break + } + } + } + if (c !== !0)if (c && a["throws"])b = c(b); else try { + b = c(b) + } catch (k) { + return {state: "parsererror", error: c ? k : "No conversion from " + h + " to " + e} + } + } + h = e + } + return {state: "success", data: b} + } + + function cL() { + try { + return new a.XMLHttpRequest + } catch (b) { + } + } + + function cM() { + try { + return new a.ActiveXObject("Microsoft.XMLHTTP") + } catch (b) { + } + } + + function cU() { + return setTimeout(function () { + cN = b + }, 0), cN = p.now() + } + + function cV(a, b) { + p.each(b, function (b, c) { + var d = (cT[b] || []).concat(cT["*"]), e = 0, f = d.length; + for (; e < f; e++)if (d[e].call(a, b, c))return + }) + } + + function cW(a, b, c) { + var d, e = 0, f = 0, g = cS.length, h = p.Deferred().always(function () { + delete i.elem + }), i = function () { + var b = cN || cU(), c = Math.max(0, j.startTime + j.duration - b), d = 1 - (c / j.duration || 0), e = 0, f = j.tweens.length; + for (; e < f; e++)j.tweens[e].run(d); + return h.notifyWith(a, [j, d, c]), d < 1 && f ? c : (h.resolveWith(a, [j]), !1) + }, j = h.promise({ + elem: a, + props: p.extend({}, b), + opts: p.extend(!0, {specialEasing: {}}, c), + originalProperties: b, + originalOptions: c, + startTime: cN || cU(), + duration: c.duration, + tweens: [], + createTween: function (b, c, d) { + var e = p.Tween(a, j.opts, b, c, j.opts.specialEasing[b] || j.opts.easing); + return j.tweens.push(e), e + }, + stop: function (b) { + var c = 0, d = b ? j.tweens.length : 0; + for (; c < d; c++)j.tweens[c].run(1); + return b ? h.resolveWith(a, [j, b]) : h.rejectWith(a, [j, b]), this + } + }), k = j.props; + cX(k, j.opts.specialEasing); + for (; e < g; e++) { + d = cS[e].call(j, a, k, j.opts); + if (d)return d + } + return cV(j, k), p.isFunction(j.opts.start) && j.opts.start.call(a, j), p.fx.timer(p.extend(i, { + anim: j, + queue: j.opts.queue, + elem: a + })), j.progress(j.opts.progress).done(j.opts.done, j.opts.complete).fail(j.opts.fail).always(j.opts.always) + } + + function cX(a, b) { + var c, d, e, f, g; + for (c in a) { + d = p.camelCase(c), e = b[d], f = a[c], p.isArray(f) && (e = f[1], f = a[c] = f[0]), c !== d && (a[d] = f, delete a[c]), g = p.cssHooks[d]; + if (g && "expand"in g) { + f = g.expand(f), delete a[d]; + for (c in f)c in a || (a[c] = f[c], b[c] = e) + } else b[d] = e + } + } + + function cY(a, b, c) { + var d, e, f, g, h, i, j, k, l = this, m = a.style, n = {}, o = [], q = a.nodeType && bZ(a); + c.queue || (j = p._queueHooks(a, "fx"), j.unqueued == null && (j.unqueued = 0, k = j.empty.fire, j.empty.fire = function () { + j.unqueued || k() + }), j.unqueued++, l.always(function () { + l.always(function () { + j.unqueued--, p.queue(a, "fx").length || j.empty.fire() + }) + })), a.nodeType === 1 && ("height"in b || "width"in b) && (c.overflow = [m.overflow, m.overflowX, m.overflowY], p.css(a, "display") === "inline" && p.css(a, "float") === "none" && (!p.support.inlineBlockNeedsLayout || cc(a.nodeName) === "inline" ? m.display = "inline-block" : m.zoom = 1)), c.overflow && (m.overflow = "hidden", p.support.shrinkWrapBlocks || l.done(function () { + m.overflow = c.overflow[0], m.overflowX = c.overflow[1], m.overflowY = c.overflow[2] + })); + for (d in b) { + f = b[d]; + if (cP.exec(f)) { + delete b[d]; + if (f === (q ? "hide" : "show"))continue; + o.push(d) + } + } + g = o.length; + if (g) { + h = p._data(a, "fxshow") || p._data(a, "fxshow", {}), q ? p(a).show() : l.done(function () { + p(a).hide() + }), l.done(function () { + var b; + p.removeData(a, "fxshow", !0); + for (b in n)p.style(a, b, n[b]) + }); + for (d = 0; d < g; d++)e = o[d], i = l.createTween(e, q ? h[e] : 0), n[e] = h[e] || p.style(a, e), e in h || (h[e] = i.start, q && (i.end = i.start, i.start = e === "width" || e === "height" ? 1 : 0)) + } + } + + function cZ(a, b, c, d, e) { + return new cZ.prototype.init(a, b, c, d, e) + } + + function c$(a, b) { + var c, d = {height: a}, e = 0; + b = b ? 1 : 0; + for (; e < 4; e += 2 - b)c = bV[e], d["margin" + c] = d["padding" + c] = a; + return b && (d.opacity = d.width = a), d + } + + function da(a) { + return p.isWindow(a) ? a : a.nodeType === 9 ? a.defaultView || a.parentWindow : !1 + } + + var c, d, e = a.document, f = a.location, g = a.navigator, h = a.jQuery, i = a.$, j = Array.prototype.push, k = Array.prototype.slice, l = Array.prototype.indexOf, m = Object.prototype.toString, n = Object.prototype.hasOwnProperty, o = String.prototype.trim, p = function (a, b) { + return new p.fn.init(a, b, c) + }, q = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source, r = /\S/, s = /\s+/, t = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, u = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, v = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, w = /^[\],:{}\s]*$/, x = /(?:^|:|,)(?:\s*\[)+/g, y = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, z = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g, A = /^-ms-/, B = /-([\da-z])/gi, C = function (a, b) { + return (b + "").toUpperCase() + }, D = function () { + e.addEventListener ? (e.removeEventListener("DOMContentLoaded", D, !1), p.ready()) : e.readyState === "complete" && (e.detachEvent("onreadystatechange", D), p.ready()) + }, E = {}; + p.fn = p.prototype = { + constructor: p, init: function (a, c, d) { + var f, g, h, i; + if (!a)return this; + if (a.nodeType)return this.context = this[0] = a, this.length = 1, this; + if (typeof a == "string") { + a.charAt(0) === "<" && a.charAt(a.length - 1) === ">" && a.length >= 3 ? f = [null, a, null] : f = u.exec(a); + if (f && (f[1] || !c)) { + if (f[1])return c = c instanceof p ? c[0] : c, i = c && c.nodeType ? c.ownerDocument || c : e, a = p.parseHTML(f[1], i, !0), v.test(f[1]) && p.isPlainObject(c) && this.attr.call(a, c, !0), p.merge(this, a); + g = e.getElementById(f[2]); + if (g && g.parentNode) { + if (g.id !== f[2])return d.find(a); + this.length = 1, this[0] = g + } + return this.context = e, this.selector = a, this + } + return !c || c.jquery ? (c || d).find(a) : this.constructor(c).find(a) + } + return p.isFunction(a) ? d.ready(a) : (a.selector !== b && (this.selector = a.selector, this.context = a.context), p.makeArray(a, this)) + }, selector: "", jquery: "1.8.2", length: 0, size: function () { + return this.length + }, toArray: function () { + return k.call(this) + }, get: function (a) { + return a == null ? this.toArray() : a < 0 ? this[this.length + a] : this[a] + }, pushStack: function (a, b, c) { + var d = p.merge(this.constructor(), a); + return d.prevObject = this, d.context = this.context, b === "find" ? d.selector = this.selector + (this.selector ? " " : "") + c : b && (d.selector = this.selector + "." + b + "(" + c + ")"), d + }, each: function (a, b) { + return p.each(this, a, b) + }, ready: function (a) { + return p.ready.promise().done(a), this + }, eq: function (a) { + return a = +a, a === -1 ? this.slice(a) : this.slice(a, a + 1) + }, first: function () { + return this.eq(0) + }, last: function () { + return this.eq(-1) + }, slice: function () { + return this.pushStack(k.apply(this, arguments), "slice", k.call(arguments).join(",")) + }, map: function (a) { + return this.pushStack(p.map(this, function (b, c) { + return a.call(b, c, b) + })) + }, end: function () { + return this.prevObject || this.constructor(null) + }, push: j, sort: [].sort, splice: [].splice + }, p.fn.init.prototype = p.fn, p.extend = p.fn.extend = function () { + var a, c, d, e, f, g, h = arguments[0] || {}, i = 1, j = arguments.length, k = !1; + typeof h == "boolean" && (k = h, h = arguments[1] || {}, i = 2), typeof h != "object" && !p.isFunction(h) && (h = {}), j === i && (h = this, --i); + for (; i < j; i++)if ((a = arguments[i]) != null)for (c in a) { + d = h[c], e = a[c]; + if (h === e)continue; + k && e && (p.isPlainObject(e) || (f = p.isArray(e))) ? (f ? (f = !1, g = d && p.isArray(d) ? d : []) : g = d && p.isPlainObject(d) ? d : {}, h[c] = p.extend(k, g, e)) : e !== b && (h[c] = e) + } + return h + }, p.extend({ + noConflict: function (b) { + return a.$ === p && (a.$ = i), b && a.jQuery === p && (a.jQuery = h), p + }, isReady: !1, readyWait: 1, holdReady: function (a) { + a ? p.readyWait++ : p.ready(!0) + }, ready: function (a) { + if (a === !0 ? --p.readyWait : p.isReady)return; + if (!e.body)return setTimeout(p.ready, 1); + p.isReady = !0; + if (a !== !0 && --p.readyWait > 0)return; + d.resolveWith(e, [p]), p.fn.trigger && p(e).trigger("ready").off("ready") + }, isFunction: function (a) { + return p.type(a) === "function" + }, isArray: Array.isArray || function (a) { + return p.type(a) === "array" + }, isWindow: function (a) { + return a != null && a == a.window + }, isNumeric: function (a) { + return !isNaN(parseFloat(a)) && isFinite(a) + }, type: function (a) { + return a == null ? String(a) : E[m.call(a)] || "object" + }, isPlainObject: function (a) { + if (!a || p.type(a) !== "object" || a.nodeType || p.isWindow(a))return !1; + try { + if (a.constructor && !n.call(a, "constructor") && !n.call(a.constructor.prototype, "isPrototypeOf"))return !1 + } catch (c) { + return !1 + } + var d; + for (d in a); + return d === b || n.call(a, d) + }, isEmptyObject: function (a) { + var b; + for (b in a)return !1; + return !0 + }, error: function (a) { + throw new Error(a) + }, parseHTML: function (a, b, c) { + var d; + return !a || typeof a != "string" ? null : (typeof b == "boolean" && (c = b, b = 0), b = b || e, (d = v.exec(a)) ? [b.createElement(d[1])] : (d = p.buildFragment([a], b, c ? null : []), p.merge([], (d.cacheable ? p.clone(d.fragment) : d.fragment).childNodes))) + }, parseJSON: function (b) { + if (!b || typeof b != "string")return null; + b = p.trim(b); + if (a.JSON && a.JSON.parse)return a.JSON.parse(b); + if (w.test(b.replace(y, "@").replace(z, "]").replace(x, "")))return (new Function("return " + b))(); + p.error("Invalid JSON: " + b) + }, parseXML: function (c) { + var d, e; + if (!c || typeof c != "string")return null; + try { + a.DOMParser ? (e = new DOMParser, d = e.parseFromString(c, "text/xml")) : (d = new ActiveXObject("Microsoft.XMLDOM"), d.async = "false", d.loadXML(c)) + } catch (f) { + d = b + } + return (!d || !d.documentElement || d.getElementsByTagName("parsererror").length) && p.error("Invalid XML: " + c), d + }, noop: function () { + }, globalEval: function (b) { + b && r.test(b) && (a.execScript || function (b) { + a.eval.call(a, b) + })(b) + }, camelCase: function (a) { + return a.replace(A, "ms-").replace(B, C) + }, nodeName: function (a, b) { + return a.nodeName && a.nodeName.toLowerCase() === b.toLowerCase() + }, each: function (a, c, d) { + var e, f = 0, g = a.length, h = g === b || p.isFunction(a); + if (d) { + if (h) { + for (e in a)if (c.apply(a[e], d) === !1)break + } else for (; f < g;)if (c.apply(a[f++], d) === !1)break + } else if (h) { + for (e in a)if (c.call(a[e], e, a[e]) === !1)break + } else for (; f < g;)if (c.call(a[f], f, a[f++]) === !1)break; + return a + }, trim: o && !o.call("聽") ? function (a) { + return a == null ? "" : o.call(a) + } : function (a) { + return a == null ? "" : (a + "").replace(t, "") + }, makeArray: function (a, b) { + var c, d = b || []; + return a != null && (c = p.type(a), a.length == null || c === "string" || c === "function" || c === "regexp" || p.isWindow(a) ? j.call(d, a) : p.merge(d, a)), d + }, inArray: function (a, b, c) { + var d; + if (b) { + if (l)return l.call(b, a, c); + d = b.length, c = c ? c < 0 ? Math.max(0, d + c) : c : 0; + for (; c < d; c++)if (c in b && b[c] === a)return c + } + return -1 + }, merge: function (a, c) { + var d = c.length, e = a.length, f = 0; + if (typeof d == "number")for (; f < d; f++)a[e++] = c[f]; else while (c[f] !== b)a[e++] = c[f++]; + return a.length = e, a + }, grep: function (a, b, c) { + var d, e = [], f = 0, g = a.length; + c = !!c; + for (; f < g; f++)d = !!b(a[f], f), c !== d && e.push(a[f]); + return e + }, map: function (a, c, d) { + var e, f, g = [], h = 0, i = a.length, j = a instanceof p || i !== b && typeof i == "number" && (i > 0 && a[0] && a[i - 1] || i === 0 || p.isArray(a)); + if (j)for (; h < i; h++)e = c(a[h], h, d), e != null && (g[g.length] = e); else for (f in a)e = c(a[f], f, d), e != null && (g[g.length] = e); + return g.concat.apply([], g) + }, guid: 1, proxy: function (a, c) { + var d, e, f; + return typeof c == "string" && (d = a[c], c = a, a = d), p.isFunction(a) ? (e = k.call(arguments, 2), f = function () { + return a.apply(c, e.concat(k.call(arguments))) + }, f.guid = a.guid = a.guid || p.guid++, f) : b + }, access: function (a, c, d, e, f, g, h) { + var i, j = d == null, k = 0, l = a.length; + if (d && typeof d == "object") { + for (k in d)p.access(a, c, k, d[k], 1, g, e); + f = 1 + } else if (e !== b) { + i = h === b && p.isFunction(e), j && (i ? (i = c, c = function (a, b, c) { + return i.call(p(a), c) + }) : (c.call(a, e), c = null)); + if (c)for (; k < l; k++)c(a[k], d, i ? e.call(a[k], k, c(a[k], d)) : e, h); + f = 1 + } + return f ? a : j ? c.call(a) : l ? c(a[0], d) : g + }, now: function () { + return (new Date).getTime() + } + }), p.ready.promise = function (b) { + if (!d) { + d = p.Deferred(); + if (e.readyState === "complete")setTimeout(p.ready, 1); else if (e.addEventListener)e.addEventListener("DOMContentLoaded", D, !1), a.addEventListener("load", p.ready, !1); else { + e.attachEvent("onreadystatechange", D), a.attachEvent("onload", p.ready); + var c = !1; + try { + c = a.frameElement == null && e.documentElement + } catch (f) { + } + c && c.doScroll && function g() { + if (!p.isReady) { + try { + c.doScroll("left") + } catch (a) { + return setTimeout(g, 50) + } + p.ready() + } + }() + } + } + return d.promise(b) + }, p.each("Boolean Number String Function Array Date RegExp Object".split(" "), function (a, b) { + E["[object " + b + "]"] = b.toLowerCase() + }), c = p(e); + var F = {}; + p.Callbacks = function (a) { + a = typeof a == "string" ? F[a] || G(a) : p.extend({}, a); + var c, d, e, f, g, h, i = [], j = !a.once && [], k = function (b) { + c = a.memory && b, d = !0, h = f || 0, f = 0, g = i.length, e = !0; + for (; i && h < g; h++)if (i[h].apply(b[0], b[1]) === !1 && a.stopOnFalse) { + c = !1; + break + } + e = !1, i && (j ? j.length && k(j.shift()) : c ? i = [] : l.disable()) + }, l = { + add: function () { + if (i) { + var b = i.length; + (function d(b) { + p.each(b, function (b, c) { + var e = p.type(c); + e === "function" && (!a.unique || !l.has(c)) ? i.push(c) : c && c.length && e !== "string" && d(c) + }) + })(arguments), e ? g = i.length : c && (f = b, k(c)) + } + return this + }, remove: function () { + return i && p.each(arguments, function (a, b) { + var c; + while ((c = p.inArray(b, i, c)) > -1)i.splice(c, 1), e && (c <= g && g--, c <= h && h--) + }), this + }, has: function (a) { + return p.inArray(a, i) > -1 + }, empty: function () { + return i = [], this + }, disable: function () { + return i = j = c = b, this + }, disabled: function () { + return !i + }, lock: function () { + return j = b, c || l.disable(), this + }, locked: function () { + return !j + }, fireWith: function (a, b) { + return b = b || [], b = [a, b.slice ? b.slice() : b], i && (!d || j) && (e ? j.push(b) : k(b)), this + }, fire: function () { + return l.fireWith(this, arguments), this + }, fired: function () { + return !!d + } + }; + return l + }, p.extend({ + Deferred: function (a) { + var b = [["resolve", "done", p.Callbacks("once memory"), "resolved"], ["reject", "fail", p.Callbacks("once memory"), "rejected"], ["notify", "progress", p.Callbacks("memory")]], c = "pending", d = { + state: function () { + return c + }, always: function () { + return e.done(arguments).fail(arguments), this + }, then: function () { + var a = arguments; + return p.Deferred(function (c) { + p.each(b, function (b, d) { + var f = d[0], g = a[b]; + e[d[1]](p.isFunction(g) ? function () { + var a = g.apply(this, arguments); + a && p.isFunction(a.promise) ? a.promise().done(c.resolve).fail(c.reject).progress(c.notify) : c[f + "With"](this === e ? c : this, [a]) + } : c[f]) + }), a = null + }).promise() + }, promise: function (a) { + return a != null ? p.extend(a, d) : d + } + }, e = {}; + return d.pipe = d.then, p.each(b, function (a, f) { + var g = f[2], h = f[3]; + d[f[1]] = g.add, h && g.add(function () { + c = h + }, b[a ^ 1][2].disable, b[2][2].lock), e[f[0]] = g.fire, e[f[0] + "With"] = g.fireWith + }), d.promise(e), a && a.call(e, e), e + }, when: function (a) { + var b = 0, c = k.call(arguments), d = c.length, e = d !== 1 || a && p.isFunction(a.promise) ? d : 0, f = e === 1 ? a : p.Deferred(), g = function (a, b, c) { + return function (d) { + b[a] = this, c[a] = arguments.length > 1 ? k.call(arguments) : d, c === h ? f.notifyWith(b, c) : --e || f.resolveWith(b, c) + } + }, h, i, j; + if (d > 1) { + h = new Array(d), i = new Array(d), j = new Array(d); + for (; b < d; b++)c[b] && p.isFunction(c[b].promise) ? c[b].promise().done(g(b, j, c)).fail(f.reject).progress(g(b, i, h)) : --e + } + return e || f.resolveWith(j, c), f.promise() + } + }), p.support = function () { + var b, c, d, f, g, h, i, j, k, l, m, n = e.createElement("div"); + n.setAttribute("className", "t"), n.innerHTML = "
    a", c = n.getElementsByTagName("*"), d = n.getElementsByTagName("a")[0], d.style.cssText = "top:1px;float:left;opacity:.5"; + if (!c || !c.length)return {}; + f = e.createElement("select"), g = f.appendChild(e.createElement("option")), h = n.getElementsByTagName("input")[0], b = { + leadingWhitespace: n.firstChild.nodeType === 3, + tbody: !n.getElementsByTagName("tbody").length, + htmlSerialize: !!n.getElementsByTagName("link").length, + style: /top/.test(d.getAttribute("style")), + hrefNormalized: d.getAttribute("href") === "/a", + opacity: /^0.5/.test(d.style.opacity), + cssFloat: !!d.style.cssFloat, + checkOn: h.value === "on", + optSelected: g.selected, + getSetAttribute: n.className !== "t", + enctype: !!e.createElement("form").enctype, + html5Clone: e.createElement("nav").cloneNode(!0).outerHTML !== "<:nav>", + boxModel: e.compatMode === "CSS1Compat", + submitBubbles: !0, + changeBubbles: !0, + focusinBubbles: !1, + deleteExpando: !0, + noCloneEvent: !0, + inlineBlockNeedsLayout: !1, + shrinkWrapBlocks: !1, + reliableMarginRight: !0, + boxSizingReliable: !0, + pixelPosition: !1 + }, h.checked = !0, b.noCloneChecked = h.cloneNode(!0).checked, f.disabled = !0, b.optDisabled = !g.disabled; + try { + delete n.test + } catch (o) { + b.deleteExpando = !1 + } + !n.addEventListener && n.attachEvent && n.fireEvent && (n.attachEvent("onclick", m = function () { + b.noCloneEvent = !1 + }), n.cloneNode(!0).fireEvent("onclick"), n.detachEvent("onclick", m)), h = e.createElement("input"), h.value = "t", h.setAttribute("type", "radio"), b.radioValue = h.value === "t", h.setAttribute("checked", "checked"), h.setAttribute("name", "t"), n.appendChild(h), i = e.createDocumentFragment(), i.appendChild(n.lastChild), b.checkClone = i.cloneNode(!0).cloneNode(!0).lastChild.checked, b.appendChecked = h.checked, i.removeChild(h), i.appendChild(n); + if (n.attachEvent)for (k in{ + submit: !0, + change: !0, + focusin: !0 + })j = "on" + k, l = j in n, l || (n.setAttribute(j, "return;"), l = typeof n[j] == "function"), b[k + "Bubbles"] = l; + return p(function () { + var c, d, f, g, h = "padding:0;margin:0;border:0;display:block;overflow:hidden;", i = e.getElementsByTagName("body")[0]; + if (!i)return; + c = e.createElement("div"), c.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px", i.insertBefore(c, i.firstChild), d = e.createElement("div"), c.appendChild(d), d.innerHTML = "
    t
    ", f = d.getElementsByTagName("td"), f[0].style.cssText = "padding:0;margin:0;border:0;display:none", l = f[0].offsetHeight === 0, f[0].style.display = "", f[1].style.display = "none", b.reliableHiddenOffsets = l && f[0].offsetHeight === 0, d.innerHTML = "", d.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;", b.boxSizing = d.offsetWidth === 4, b.doesNotIncludeMarginInBodyOffset = i.offsetTop !== 1, a.getComputedStyle && (b.pixelPosition = (a.getComputedStyle(d, null) || {}).top !== "1%", b.boxSizingReliable = (a.getComputedStyle(d, null) || {width: "4px"}).width === "4px", g = e.createElement("div"), g.style.cssText = d.style.cssText = h, g.style.marginRight = g.style.width = "0", d.style.width = "1px", d.appendChild(g), b.reliableMarginRight = !parseFloat((a.getComputedStyle(g, null) || {}).marginRight)), typeof d.style.zoom != "undefined" && (d.innerHTML = "", d.style.cssText = h + "width:1px;padding:1px;display:inline;zoom:1", b.inlineBlockNeedsLayout = d.offsetWidth === 3, d.style.display = "block", d.style.overflow = "visible", d.innerHTML = "
    ", d.firstChild.style.width = "5px", b.shrinkWrapBlocks = d.offsetWidth !== 3, c.style.zoom = 1), i.removeChild(c), c = d = f = g = null + }), i.removeChild(n), c = d = f = g = h = i = n = null, b + }(); + var H = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, I = /([A-Z])/g; + p.extend({ + cache: {}, + deletedIds: [], + uuid: 0, + expando: "jQuery" + (p.fn.jquery + Math.random()).replace(/\D/g, ""), + noData: {embed: !0, object: "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", applet: !0}, + hasData: function (a) { + return a = a.nodeType ? p.cache[a[p.expando]] : a[p.expando], !!a && !K(a) + }, + data: function (a, c, d, e) { + if (!p.acceptData(a))return; + var f, g, h = p.expando, i = typeof c == "string", j = a.nodeType, k = j ? p.cache : a, l = j ? a[h] : a[h] && h; + if ((!l || !k[l] || !e && !k[l].data) && i && d === b)return; + l || (j ? a[h] = l = p.deletedIds.pop() || p.guid++ : l = h), k[l] || (k[l] = {}, j || (k[l].toJSON = p.noop)); + if (typeof c == "object" || typeof c == "function")e ? k[l] = p.extend(k[l], c) : k[l].data = p.extend(k[l].data, c); + return f = k[l], e || (f.data || (f.data = {}), f = f.data), d !== b && (f[p.camelCase(c)] = d), i ? (g = f[c], g == null && (g = f[p.camelCase(c)])) : g = f, g + }, + removeData: function (a, b, c) { + if (!p.acceptData(a))return; + var d, e, f, g = a.nodeType, h = g ? p.cache : a, i = g ? a[p.expando] : p.expando; + if (!h[i])return; + if (b) { + d = c ? h[i] : h[i].data; + if (d) { + p.isArray(b) || (b in d ? b = [b] : (b = p.camelCase(b), b in d ? b = [b] : b = b.split(" "))); + for (e = 0, f = b.length; e < f; e++)delete d[b[e]]; + if (!(c ? K : p.isEmptyObject)(d))return + } + } + if (!c) { + delete h[i].data; + if (!K(h[i]))return + } + g ? p.cleanData([a], !0) : p.support.deleteExpando || h != h.window ? delete h[i] : h[i] = null + }, + _data: function (a, b, c) { + return p.data(a, b, c, !0) + }, + acceptData: function (a) { + var b = a.nodeName && p.noData[a.nodeName.toLowerCase()]; + return !b || b !== !0 && a.getAttribute("classid") === b + } + }), p.fn.extend({ + data: function (a, c) { + var d, e, f, g, h, i = this[0], j = 0, k = null; + if (a === b) { + if (this.length) { + k = p.data(i); + if (i.nodeType === 1 && !p._data(i, "parsedAttrs")) { + f = i.attributes; + for (h = f.length; j < h; j++)g = f[j].name, g.indexOf("data-") || (g = p.camelCase(g.substring(5)), J(i, g, k[g])); + p._data(i, "parsedAttrs", !0) + } + } + return k + } + return typeof a == "object" ? this.each(function () { + p.data(this, a) + }) : (d = a.split(".", 2), d[1] = d[1] ? "." + d[1] : "", e = d[1] + "!", p.access(this, function (c) { + if (c === b)return k = this.triggerHandler("getData" + e, [d[0]]), k === b && i && (k = p.data(i, a), k = J(i, a, k)), k === b && d[1] ? this.data(d[0]) : k; + d[1] = c, this.each(function () { + var b = p(this); + b.triggerHandler("setData" + e, d), p.data(this, a, c), b.triggerHandler("changeData" + e, d) + }) + }, null, c, arguments.length > 1, null, !1)) + }, removeData: function (a) { + return this.each(function () { + p.removeData(this, a) + }) + } + }), p.extend({ + queue: function (a, b, c) { + var d; + if (a)return b = (b || "fx") + "queue", d = p._data(a, b), c && (!d || p.isArray(c) ? d = p._data(a, b, p.makeArray(c)) : d.push(c)), d || [] + }, dequeue: function (a, b) { + b = b || "fx"; + var c = p.queue(a, b), d = c.length, e = c.shift(), f = p._queueHooks(a, b), g = function () { + p.dequeue(a, b) + }; + e === "inprogress" && (e = c.shift(), d--), e && (b === "fx" && c.unshift("inprogress"), delete f.stop, e.call(a, g, f)), !d && f && f.empty.fire() + }, _queueHooks: function (a, b) { + var c = b + "queueHooks"; + return p._data(a, c) || p._data(a, c, { + empty: p.Callbacks("once memory").add(function () { + p.removeData(a, b + "queue", !0), p.removeData(a, c, !0) + }) + }) + } + }), p.fn.extend({ + queue: function (a, c) { + var d = 2; + return typeof a != "string" && (c = a, a = "fx", d--), arguments.length < d ? p.queue(this[0], a) : c === b ? this : this.each(function () { + var b = p.queue(this, a, c); + p._queueHooks(this, a), a === "fx" && b[0] !== "inprogress" && p.dequeue(this, a) + }) + }, dequeue: function (a) { + return this.each(function () { + p.dequeue(this, a) + }) + }, delay: function (a, b) { + return a = p.fx ? p.fx.speeds[a] || a : a, b = b || "fx", this.queue(b, function (b, c) { + var d = setTimeout(b, a); + c.stop = function () { + clearTimeout(d) + } + }) + }, clearQueue: function (a) { + return this.queue(a || "fx", []) + }, promise: function (a, c) { + var d, e = 1, f = p.Deferred(), g = this, h = this.length, i = function () { + --e || f.resolveWith(g, [g]) + }; + typeof a != "string" && (c = a, a = b), a = a || "fx"; + while (h--)d = p._data(g[h], a + "queueHooks"), d && d.empty && (e++, d.empty.add(i)); + return i(), f.promise(c) + } + }); + var L, M, N, O = /[\t\r\n]/g, P = /\r/g, Q = /^(?:button|input)$/i, R = /^(?:button|input|object|select|textarea)$/i, S = /^a(?:rea|)$/i, T = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, U = p.support.getSetAttribute; + p.fn.extend({ + attr: function (a, b) { + return p.access(this, p.attr, a, b, arguments.length > 1) + }, removeAttr: function (a) { + return this.each(function () { + p.removeAttr(this, a) + }) + }, prop: function (a, b) { + return p.access(this, p.prop, a, b, arguments.length > 1) + }, removeProp: function (a) { + return a = p.propFix[a] || a, this.each(function () { + try { + this[a] = b, delete this[a] + } catch (c) { + } + }) + }, addClass: function (a) { + var b, c, d, e, f, g, h; + if (p.isFunction(a))return this.each(function (b) { + p(this).addClass(a.call(this, b, this.className)) + }); + if (a && typeof a == "string") { + b = a.split(s); + for (c = 0, d = this.length; c < d; c++) { + e = this[c]; + if (e.nodeType === 1)if (!e.className && b.length === 1)e.className = a; else { + f = " " + e.className + " "; + for (g = 0, h = b.length; g < h; g++)f.indexOf(" " + b[g] + " ") < 0 && (f += b[g] + " "); + e.className = p.trim(f) + } + } + } + return this + }, removeClass: function (a) { + var c, d, e, f, g, h, i; + if (p.isFunction(a))return this.each(function (b) { + p(this).removeClass(a.call(this, b, this.className)) + }); + if (a && typeof a == "string" || a === b) { + c = (a || "").split(s); + for (h = 0, i = this.length; h < i; h++) { + e = this[h]; + if (e.nodeType === 1 && e.className) { + d = (" " + e.className + " ").replace(O, " "); + for (f = 0, g = c.length; f < g; f++)while (d.indexOf(" " + c[f] + " ") >= 0)d = d.replace(" " + c[f] + " ", " "); + e.className = a ? p.trim(d) : "" + } + } + } + return this + }, toggleClass: function (a, b) { + var c = typeof a, d = typeof b == "boolean"; + return p.isFunction(a) ? this.each(function (c) { + p(this).toggleClass(a.call(this, c, this.className, b), b) + }) : this.each(function () { + if (c === "string") { + var e, f = 0, g = p(this), h = b, i = a.split(s); + while (e = i[f++])h = d ? h : !g.hasClass(e), g[h ? "addClass" : "removeClass"](e) + } else if (c === "undefined" || c === "boolean")this.className && p._data(this, "__className__", this.className), this.className = this.className || a === !1 ? "" : p._data(this, "__className__") || "" + }) + }, hasClass: function (a) { + var b = " " + a + " ", c = 0, d = this.length; + for (; c < d; c++)if (this[c].nodeType === 1 && (" " + this[c].className + " ").replace(O, " ").indexOf(b) >= 0)return !0; + return !1 + }, val: function (a) { + var c, d, e, f = this[0]; + if (!arguments.length) { + if (f)return c = p.valHooks[f.type] || p.valHooks[f.nodeName.toLowerCase()], c && "get"in c && (d = c.get(f, "value")) !== b ? d : (d = f.value, typeof d == "string" ? d.replace(P, "") : d == null ? "" : d); + return + } + return e = p.isFunction(a), this.each(function (d) { + var f, g = p(this); + if (this.nodeType !== 1)return; + e ? f = a.call(this, d, g.val()) : f = a, f == null ? f = "" : typeof f == "number" ? f += "" : p.isArray(f) && (f = p.map(f, function (a) { + return a == null ? "" : a + "" + })), c = p.valHooks[this.type] || p.valHooks[this.nodeName.toLowerCase()]; + if (!c || !("set"in c) || c.set(this, f, "value") === b)this.value = f + }) + } + }), p.extend({ + valHooks: { + option: { + get: function (a) { + var b = a.attributes.value; + return !b || b.specified ? a.value : a.text + } + }, select: { + get: function (a) { + var b, c, d, e, f = a.selectedIndex, g = [], h = a.options, i = a.type === "select-one"; + if (f < 0)return null; + c = i ? f : 0, d = i ? f + 1 : h.length; + for (; c < d; c++) { + e = h[c]; + if (e.selected && (p.support.optDisabled ? !e.disabled : e.getAttribute("disabled") === null) && (!e.parentNode.disabled || !p.nodeName(e.parentNode, "optgroup"))) { + b = p(e).val(); + if (i)return b; + g.push(b) + } + } + return i && !g.length && h.length ? p(h[f]).val() : g + }, set: function (a, b) { + var c = p.makeArray(b); + return p(a).find("option").each(function () { + this.selected = p.inArray(p(this).val(), c) >= 0 + }), c.length || (a.selectedIndex = -1), c + } + } + }, + attrFn: {}, + attr: function (a, c, d, e) { + var f, g, h, i = a.nodeType; + if (!a || i === 3 || i === 8 || i === 2)return; + if (e && p.isFunction(p.fn[c]))return p(a)[c](d); + if (typeof a.getAttribute == "undefined")return p.prop(a, c, d); + h = i !== 1 || !p.isXMLDoc(a), h && (c = c.toLowerCase(), g = p.attrHooks[c] || (T.test(c) ? M : L)); + if (d !== b) { + if (d === null) { + p.removeAttr(a, c); + return + } + return g && "set"in g && h && (f = g.set(a, d, c)) !== b ? f : (a.setAttribute(c, d + ""), d) + } + return g && "get"in g && h && (f = g.get(a, c)) !== null ? f : (f = a.getAttribute(c), f === null ? b : f) + }, + removeAttr: function (a, b) { + var c, d, e, f, g = 0; + if (b && a.nodeType === 1) { + d = b.split(s); + for (; g < d.length; g++)e = d[g], e && (c = p.propFix[e] || e, f = T.test(e), f || p.attr(a, e, ""), a.removeAttribute(U ? e : c), f && c in a && (a[c] = !1)) + } + }, + attrHooks: { + type: { + set: function (a, b) { + if (Q.test(a.nodeName) && a.parentNode)p.error("type property can't be changed"); else if (!p.support.radioValue && b === "radio" && p.nodeName(a, "input")) { + var c = a.value; + return a.setAttribute("type", b), c && (a.value = c), b + } + } + }, value: { + get: function (a, b) { + return L && p.nodeName(a, "button") ? L.get(a, b) : b in a ? a.value : null + }, set: function (a, b, c) { + if (L && p.nodeName(a, "button"))return L.set(a, b, c); + a.value = b + } + } + }, + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + prop: function (a, c, d) { + var e, f, g, h = a.nodeType; + if (!a || h === 3 || h === 8 || h === 2)return; + return g = h !== 1 || !p.isXMLDoc(a), g && (c = p.propFix[c] || c, f = p.propHooks[c]), d !== b ? f && "set"in f && (e = f.set(a, d, c)) !== b ? e : a[c] = d : f && "get"in f && (e = f.get(a, c)) !== null ? e : a[c] + }, + propHooks: { + tabIndex: { + get: function (a) { + var c = a.getAttributeNode("tabindex"); + return c && c.specified ? parseInt(c.value, 10) : R.test(a.nodeName) || S.test(a.nodeName) && a.href ? 0 : b + } + } + } + }), M = { + get: function (a, c) { + var d, e = p.prop(a, c); + return e === !0 || typeof e != "boolean" && (d = a.getAttributeNode(c)) && d.nodeValue !== !1 ? c.toLowerCase() : b + }, set: function (a, b, c) { + var d; + return b === !1 ? p.removeAttr(a, c) : (d = p.propFix[c] || c, d in a && (a[d] = !0), a.setAttribute(c, c.toLowerCase())), c + } + }, U || (N = {name: !0, id: !0, coords: !0}, L = p.valHooks.button = { + get: function (a, c) { + var d; + return d = a.getAttributeNode(c), d && (N[c] ? d.value !== "" : d.specified) ? d.value : b + }, set: function (a, b, c) { + var d = a.getAttributeNode(c); + return d || (d = e.createAttribute(c), a.setAttributeNode(d)), d.value = b + "" + } + }, p.each(["width", "height"], function (a, b) { + p.attrHooks[b] = p.extend(p.attrHooks[b], { + set: function (a, c) { + if (c === "")return a.setAttribute(b, "auto"), c + } + }) + }), p.attrHooks.contenteditable = { + get: L.get, set: function (a, b, c) { + b === "" && (b = "false"), L.set(a, b, c) + } + }), p.support.hrefNormalized || p.each(["href", "src", "width", "height"], function (a, c) { + p.attrHooks[c] = p.extend(p.attrHooks[c], { + get: function (a) { + var d = a.getAttribute(c, 2); + return d === null ? b : d + } + }) + }), p.support.style || (p.attrHooks.style = { + get: function (a) { + return a.style.cssText.toLowerCase() || b + }, set: function (a, b) { + return a.style.cssText = b + "" + } + }), p.support.optSelected || (p.propHooks.selected = p.extend(p.propHooks.selected, { + get: function (a) { + var b = a.parentNode; + return b && (b.selectedIndex, b.parentNode && b.parentNode.selectedIndex), null + } + })), p.support.enctype || (p.propFix.enctype = "encoding"), p.support.checkOn || p.each(["radio", "checkbox"], function () { + p.valHooks[this] = { + get: function (a) { + return a.getAttribute("value") === null ? "on" : a.value + } + } + }), p.each(["radio", "checkbox"], function () { + p.valHooks[this] = p.extend(p.valHooks[this], { + set: function (a, b) { + if (p.isArray(b))return a.checked = p.inArray(p(a).val(), b) >= 0 + } + }) + }); + var V = /^(?:textarea|input|select)$/i, W = /^([^\.]*|)(?:\.(.+)|)$/, X = /(?:^|\s)hover(\.\S+|)\b/, Y = /^key/, Z = /^(?:mouse|contextmenu)|click/, $ = /^(?:focusinfocus|focusoutblur)$/, _ = function (a) { + return p.event.special.hover ? a : a.replace(X, "mouseenter$1 mouseleave$1") + }; + p.event = { + add: function (a, c, d, e, f) { + var g, h, i, j, k, l, m, n, o, q, r; + if (a.nodeType === 3 || a.nodeType === 8 || !c || !d || !(g = p._data(a)))return; + d.handler && (o = d, d = o.handler, f = o.selector), d.guid || (d.guid = p.guid++), i = g.events, i || (g.events = i = {}), h = g.handle, h || (g.handle = h = function (a) { + return typeof p != "undefined" && (!a || p.event.triggered !== a.type) ? p.event.dispatch.apply(h.elem, arguments) : b + }, h.elem = a), c = p.trim(_(c)).split(" "); + for (j = 0; j < c.length; j++) { + k = W.exec(c[j]) || [], l = k[1], m = (k[2] || "").split(".").sort(), r = p.event.special[l] || {}, l = (f ? r.delegateType : r.bindType) || l, r = p.event.special[l] || {}, n = p.extend({ + type: l, + origType: k[1], + data: e, + handler: d, + guid: d.guid, + selector: f, + needsContext: f && p.expr.match.needsContext.test(f), + namespace: m.join(".") + }, o), q = i[l]; + if (!q) { + q = i[l] = [], q.delegateCount = 0; + if (!r.setup || r.setup.call(a, e, m, h) === !1)a.addEventListener ? a.addEventListener(l, h, !1) : a.attachEvent && a.attachEvent("on" + l, h) + } + r.add && (r.add.call(a, n), n.handler.guid || (n.handler.guid = d.guid)), f ? q.splice(q.delegateCount++, 0, n) : q.push(n), p.event.global[l] = !0 + } + a = null + }, + global: {}, + remove: function (a, b, c, d, e) { + var f, g, h, i, j, k, l, m, n, o, q, r = p.hasData(a) && p._data(a); + if (!r || !(m = r.events))return; + b = p.trim(_(b || "")).split(" "); + for (f = 0; f < b.length; f++) { + g = W.exec(b[f]) || [], h = i = g[1], j = g[2]; + if (!h) { + for (h in m)p.event.remove(a, h + b[f], c, d, !0); + continue + } + n = p.event.special[h] || {}, h = (d ? n.delegateType : n.bindType) || h, o = m[h] || [], k = o.length, j = j ? new RegExp("(^|\\.)" + j.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null; + for (l = 0; l < o.length; l++)q = o[l], (e || i === q.origType) && (!c || c.guid === q.guid) && (!j || j.test(q.namespace)) && (!d || d === q.selector || d === "**" && q.selector) && (o.splice(l--, 1), q.selector && o.delegateCount--, n.remove && n.remove.call(a, q)); + o.length === 0 && k !== o.length && ((!n.teardown || n.teardown.call(a, j, r.handle) === !1) && p.removeEvent(a, h, r.handle), delete m[h]) + } + p.isEmptyObject(m) && (delete r.handle, p.removeData(a, "events", !0)) + }, + customEvent: {getData: !0, setData: !0, changeData: !0}, + trigger: function (c, d, f, g) { + if (!f || f.nodeType !== 3 && f.nodeType !== 8) { + var h, i, j, k, l, m, n, o, q, r, s = c.type || c, t = []; + if ($.test(s + p.event.triggered))return; + s.indexOf("!") >= 0 && (s = s.slice(0, -1), i = !0), s.indexOf(".") >= 0 && (t = s.split("."), s = t.shift(), t.sort()); + if ((!f || p.event.customEvent[s]) && !p.event.global[s])return; + c = typeof c == "object" ? c[p.expando] ? c : new p.Event(s, c) : new p.Event(s), c.type = s, c.isTrigger = !0, c.exclusive = i, c.namespace = t.join("."), c.namespace_re = c.namespace ? new RegExp("(^|\\.)" + t.join("\\.(?:.*\\.|)") + "(\\.|$)") : null, m = s.indexOf(":") < 0 ? "on" + s : ""; + if (!f) { + h = p.cache; + for (j in h)h[j].events && h[j].events[s] && p.event.trigger(c, d, h[j].handle.elem, !0); + return + } + c.result = b, c.target || (c.target = f), d = d != null ? p.makeArray(d) : [], d.unshift(c), n = p.event.special[s] || {}; + if (n.trigger && n.trigger.apply(f, d) === !1)return; + q = [[f, n.bindType || s]]; + if (!g && !n.noBubble && !p.isWindow(f)) { + r = n.delegateType || s, k = $.test(r + s) ? f : f.parentNode; + for (l = f; k; k = k.parentNode)q.push([k, r]), l = k; + l === (f.ownerDocument || e) && q.push([l.defaultView || l.parentWindow || a, r]) + } + for (j = 0; j < q.length && !c.isPropagationStopped(); j++)k = q[j][0], c.type = q[j][1], o = (p._data(k, "events") || {})[c.type] && p._data(k, "handle"), o && o.apply(k, d), o = m && k[m], o && p.acceptData(k) && o.apply && o.apply(k, d) === !1 && c.preventDefault(); + return c.type = s, !g && !c.isDefaultPrevented() && (!n._default || n._default.apply(f.ownerDocument, d) === !1) && (s !== "click" || !p.nodeName(f, "a")) && p.acceptData(f) && m && f[s] && (s !== "focus" && s !== "blur" || c.target.offsetWidth !== 0) && !p.isWindow(f) && (l = f[m], l && (f[m] = null), p.event.triggered = s, f[s](), p.event.triggered = b, l && (f[m] = l)), c.result + } + return + }, + dispatch: function (c) { + c = p.event.fix(c || a.event); + var d, e, f, g, h, i, j, l, m, n, o = (p._data(this, "events") || {})[c.type] || [], q = o.delegateCount, r = k.call(arguments), s = !c.exclusive && !c.namespace, t = p.event.special[c.type] || {}, u = []; + r[0] = c, c.delegateTarget = this; + if (t.preDispatch && t.preDispatch.call(this, c) === !1)return; + if (q && (!c.button || c.type !== "click"))for (f = c.target; f != this; f = f.parentNode || this)if (f.disabled !== !0 || c.type !== "click") { + h = {}, j = []; + for (d = 0; d < q; d++)l = o[d], m = l.selector, h[m] === b && (h[m] = l.needsContext ? p(m, this).index(f) >= 0 : p.find(m, this, null, [f]).length), h[m] && j.push(l); + j.length && u.push({elem: f, matches: j}) + } + o.length > q && u.push({elem: this, matches: o.slice(q)}); + for (d = 0; d < u.length && !c.isPropagationStopped(); d++) { + i = u[d], c.currentTarget = i.elem; + for (e = 0; e < i.matches.length && !c.isImmediatePropagationStopped(); e++) { + l = i.matches[e]; + if (s || !c.namespace && !l.namespace || c.namespace_re && c.namespace_re.test(l.namespace))c.data = l.data, c.handleObj = l, g = ((p.event.special[l.origType] || {}).handle || l.handler).apply(i.elem, r), g !== b && (c.result = g, g === !1 && (c.preventDefault(), c.stopPropagation())) + } + } + return t.postDispatch && t.postDispatch.call(this, c), c.result + }, + props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + fixHooks: {}, + keyHooks: { + props: "char charCode key keyCode".split(" "), filter: function (a, b) { + return a.which == null && (a.which = b.charCode != null ? b.charCode : b.keyCode), a + } + }, + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function (a, c) { + var d, f, g, h = c.button, i = c.fromElement; + return a.pageX == null && c.clientX != null && (d = a.target.ownerDocument || e, f = d.documentElement, g = d.body, a.pageX = c.clientX + (f && f.scrollLeft || g && g.scrollLeft || 0) - (f && f.clientLeft || g && g.clientLeft || 0), a.pageY = c.clientY + (f && f.scrollTop || g && g.scrollTop || 0) - (f && f.clientTop || g && g.clientTop || 0)), !a.relatedTarget && i && (a.relatedTarget = i === a.target ? c.toElement : i), !a.which && h !== b && (a.which = h & 1 ? 1 : h & 2 ? 3 : h & 4 ? 2 : 0), a + } + }, + fix: function (a) { + if (a[p.expando])return a; + var b, c, d = a, f = p.event.fixHooks[a.type] || {}, g = f.props ? this.props.concat(f.props) : this.props; + a = p.Event(d); + for (b = g.length; b;)c = g[--b], a[c] = d[c]; + return a.target || (a.target = d.srcElement || e), a.target.nodeType === 3 && (a.target = a.target.parentNode), a.metaKey = !!a.metaKey, f.filter ? f.filter(a, d) : a + }, + special: { + load: {noBubble: !0}, + focus: {delegateType: "focusin"}, + blur: {delegateType: "focusout"}, + beforeunload: { + setup: function (a, b, c) { + p.isWindow(this) && (this.onbeforeunload = c) + }, teardown: function (a, b) { + this.onbeforeunload === b && (this.onbeforeunload = null) + } + } + }, + simulate: function (a, b, c, d) { + var e = p.extend(new p.Event, c, {type: a, isSimulated: !0, originalEvent: {}}); + d ? p.event.trigger(e, null, b) : p.event.dispatch.call(b, e), e.isDefaultPrevented() && c.preventDefault() + } + }, p.event.handle = p.event.dispatch, p.removeEvent = e.removeEventListener ? function (a, b, c) { + a.removeEventListener && a.removeEventListener(b, c, !1) + } : function (a, b, c) { + var d = "on" + b; + a.detachEvent && (typeof a[d] == "undefined" && (a[d] = null), a.detachEvent(d, c)) + }, p.Event = function (a, b) { + if (this instanceof p.Event)a && a.type ? (this.originalEvent = a, this.type = a.type, this.isDefaultPrevented = a.defaultPrevented || a.returnValue === !1 || a.getPreventDefault && a.getPreventDefault() ? bb : ba) : this.type = a, b && p.extend(this, b), this.timeStamp = a && a.timeStamp || p.now(), this[p.expando] = !0; else return new p.Event(a, b) + }, p.Event.prototype = { + preventDefault: function () { + this.isDefaultPrevented = bb; + var a = this.originalEvent; + if (!a)return; + a.preventDefault ? a.preventDefault() : a.returnValue = !1 + }, stopPropagation: function () { + this.isPropagationStopped = bb; + var a = this.originalEvent; + if (!a)return; + a.stopPropagation && a.stopPropagation(), a.cancelBubble = !0 + }, stopImmediatePropagation: function () { + this.isImmediatePropagationStopped = bb, this.stopPropagation() + }, isDefaultPrevented: ba, isPropagationStopped: ba, isImmediatePropagationStopped: ba + }, p.each({mouseenter: "mouseover", mouseleave: "mouseout"}, function (a, b) { + p.event.special[a] = { + delegateType: b, bindType: b, handle: function (a) { + var c, d = this, e = a.relatedTarget, f = a.handleObj, g = f.selector; + if (!e || e !== d && !p.contains(d, e))a.type = f.origType, c = f.handler.apply(this, arguments), a.type = b; + return c + } + } + }), p.support.submitBubbles || (p.event.special.submit = { + setup: function () { + if (p.nodeName(this, "form"))return !1; + p.event.add(this, "click._submit keypress._submit", function (a) { + var c = a.target, d = p.nodeName(c, "input") || p.nodeName(c, "button") ? c.form : b; + d && !p._data(d, "_submit_attached") && (p.event.add(d, "submit._submit", function (a) { + a._submit_bubble = !0 + }), p._data(d, "_submit_attached", !0)) + }) + }, postDispatch: function (a) { + a._submit_bubble && (delete a._submit_bubble, this.parentNode && !a.isTrigger && p.event.simulate("submit", this.parentNode, a, !0)) + }, teardown: function () { + if (p.nodeName(this, "form"))return !1; + p.event.remove(this, "._submit") + } + }), p.support.changeBubbles || (p.event.special.change = { + setup: function () { + if (V.test(this.nodeName)) { + if (this.type === "checkbox" || this.type === "radio")p.event.add(this, "propertychange._change", function (a) { + a.originalEvent.propertyName === "checked" && (this._just_changed = !0) + }), p.event.add(this, "click._change", function (a) { + this._just_changed && !a.isTrigger && (this._just_changed = !1), p.event.simulate("change", this, a, !0) + }); + return !1 + } + p.event.add(this, "beforeactivate._change", function (a) { + var b = a.target; + V.test(b.nodeName) && !p._data(b, "_change_attached") && (p.event.add(b, "change._change", function (a) { + this.parentNode && !a.isSimulated && !a.isTrigger && p.event.simulate("change", this.parentNode, a, !0) + }), p._data(b, "_change_attached", !0)) + }) + }, handle: function (a) { + var b = a.target; + if (this !== b || a.isSimulated || a.isTrigger || b.type !== "radio" && b.type !== "checkbox")return a.handleObj.handler.apply(this, arguments) + }, teardown: function () { + return p.event.remove(this, "._change"), !V.test(this.nodeName) + } + }), p.support.focusinBubbles || p.each({focus: "focusin", blur: "focusout"}, function (a, b) { + var c = 0, d = function (a) { + p.event.simulate(b, a.target, p.event.fix(a), !0) + }; + p.event.special[b] = { + setup: function () { + c++ === 0 && e.addEventListener(a, d, !0) + }, teardown: function () { + --c === 0 && e.removeEventListener(a, d, !0) + } + } + }), p.fn.extend({ + on: function (a, c, d, e, f) { + var g, h; + if (typeof a == "object") { + typeof c != "string" && (d = d || c, c = b); + for (h in a)this.on(h, c, d, a[h], f); + return this + } + d == null && e == null ? (e = c, d = c = b) : e == null && (typeof c == "string" ? (e = d, d = b) : (e = d, d = c, c = b)); + if (e === !1)e = ba; else if (!e)return this; + return f === 1 && (g = e, e = function (a) { + return p().off(a), g.apply(this, arguments) + }, e.guid = g.guid || (g.guid = p.guid++)), this.each(function () { + p.event.add(this, a, e, d, c) + }) + }, one: function (a, b, c, d) { + return this.on(a, b, c, d, 1) + }, off: function (a, c, d) { + var e, f; + if (a && a.preventDefault && a.handleObj)return e = a.handleObj, p(a.delegateTarget).off(e.namespace ? e.origType + "." + e.namespace : e.origType, e.selector, e.handler), this; + if (typeof a == "object") { + for (f in a)this.off(f, c, a[f]); + return this + } + if (c === !1 || typeof c == "function")d = c, c = b; + return d === !1 && (d = ba), this.each(function () { + p.event.remove(this, a, d, c) + }) + }, bind: function (a, b, c) { + return this.on(a, null, b, c) + }, unbind: function (a, b) { + return this.off(a, null, b) + }, live: function (a, b, c) { + return p(this.context).on(a, this.selector, b, c), this + }, die: function (a, b) { + return p(this.context).off(a, this.selector || "**", b), this + }, delegate: function (a, b, c, d) { + return this.on(b, a, c, d) + }, undelegate: function (a, b, c) { + return arguments.length === 1 ? this.off(a, "**") : this.off(b, a || "**", c) + }, trigger: function (a, b) { + return this.each(function () { + p.event.trigger(a, b, this) + }) + }, triggerHandler: function (a, b) { + if (this[0])return p.event.trigger(a, b, this[0], !0) + }, toggle: function (a) { + var b = arguments, c = a.guid || p.guid++, d = 0, e = function (c) { + var e = (p._data(this, "lastToggle" + a.guid) || 0) % d; + return p._data(this, "lastToggle" + a.guid, e + 1), c.preventDefault(), b[e].apply(this, arguments) || !1 + }; + e.guid = c; + while (d < b.length)b[d++].guid = c; + return this.click(e) + }, hover: function (a, b) { + return this.mouseenter(a).mouseleave(b || a) + } + }), p.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "), function (a, b) { + p.fn[b] = function (a, c) { + return c == null && (c = a, a = null), arguments.length > 0 ? this.on(b, null, a, c) : this.trigger(b) + }, Y.test(b) && (p.event.fixHooks[b] = p.event.keyHooks), Z.test(b) && (p.event.fixHooks[b] = p.event.mouseHooks) + }), function (a, b) { + function bc(a, b, c, d) { + c = c || [], b = b || r; + var e, f, i, j, k = b.nodeType; + if (!a || typeof a != "string")return c; + if (k !== 1 && k !== 9)return []; + i = g(b); + if (!i && !d)if (e = P.exec(a))if (j = e[1]) { + if (k === 9) { + f = b.getElementById(j); + if (!f || !f.parentNode)return c; + if (f.id === j)return c.push(f), c + } else if (b.ownerDocument && (f = b.ownerDocument.getElementById(j)) && h(b, f) && f.id === j)return c.push(f), c + } else { + if (e[2])return w.apply(c, x.call(b.getElementsByTagName(a), 0)), c; + if ((j = e[3]) && _ && b.getElementsByClassName)return w.apply(c, x.call(b.getElementsByClassName(j), 0)), c + } + return bp(a.replace(L, "$1"), b, c, d, i) + } + + function bd(a) { + return function (b) { + var c = b.nodeName.toLowerCase(); + return c === "input" && b.type === a + } + } + + function be(a) { + return function (b) { + var c = b.nodeName.toLowerCase(); + return (c === "input" || c === "button") && b.type === a + } + } + + function bf(a) { + return z(function (b) { + return b = +b, z(function (c, d) { + var e, f = a([], c.length, b), g = f.length; + while (g--)c[e = f[g]] && (c[e] = !(d[e] = c[e])) + }) + }) + } + + function bg(a, b, c) { + if (a === b)return c; + var d = a.nextSibling; + while (d) { + if (d === b)return -1; + d = d.nextSibling + } + return 1 + } + + function bh(a, b) { + var c, d, f, g, h, i, j, k = C[o][a]; + if (k)return b ? 0 : k.slice(0); + h = a, i = [], j = e.preFilter; + while (h) { + if (!c || (d = M.exec(h)))d && (h = h.slice(d[0].length)), i.push(f = []); + c = !1; + if (d = N.exec(h))f.push(c = new q(d.shift())), h = h.slice(c.length), c.type = d[0].replace(L, " "); + for (g in e.filter)(d = W[g].exec(h)) && (!j[g] || (d = j[g](d, r, !0))) && (f.push(c = new q(d.shift())), h = h.slice(c.length), c.type = g, c.matches = d); + if (!c)break + } + return b ? h.length : h ? bc.error(a) : C(a, i).slice(0) + } + + function bi(a, b, d) { + var e = b.dir, f = d && b.dir === "parentNode", g = u++; + return b.first ? function (b, c, d) { + while (b = b[e])if (f || b.nodeType === 1)return a(b, c, d) + } : function (b, d, h) { + if (!h) { + var i, j = t + " " + g + " ", k = j + c; + while (b = b[e])if (f || b.nodeType === 1) { + if ((i = b[o]) === k)return b.sizset; + if (typeof i == "string" && i.indexOf(j) === 0) { + if (b.sizset)return b + } else { + b[o] = k; + if (a(b, d, h))return b.sizset = !0, b; + b.sizset = !1 + } + } + } else while (b = b[e])if (f || b.nodeType === 1)if (a(b, d, h))return b + } + } + + function bj(a) { + return a.length > 1 ? function (b, c, d) { + var e = a.length; + while (e--)if (!a[e](b, c, d))return !1; + return !0 + } : a[0] + } + + function bk(a, b, c, d, e) { + var f, g = [], h = 0, i = a.length, j = b != null; + for (; h < i; h++)if (f = a[h])if (!c || c(f, d, e))g.push(f), j && b.push(h); + return g + } + + function bl(a, b, c, d, e, f) { + return d && !d[o] && (d = bl(d)), e && !e[o] && (e = bl(e, f)), z(function (f, g, h, i) { + if (f && e)return; + var j, k, l, m = [], n = [], o = g.length, p = f || bo(b || "*", h.nodeType ? [h] : h, [], f), q = a && (f || !b) ? bk(p, m, a, h, i) : p, r = c ? e || (f ? a : o || d) ? [] : g : q; + c && c(q, r, h, i); + if (d) { + l = bk(r, n), d(l, [], h, i), j = l.length; + while (j--)if (k = l[j])r[n[j]] = !(q[n[j]] = k) + } + if (f) { + j = a && r.length; + while (j--)if (k = r[j])f[m[j]] = !(g[m[j]] = k) + } else r = bk(r === g ? r.splice(o, r.length) : r), e ? e(null, g, r, i) : w.apply(g, r) + }) + } + + function bm(a) { + var b, c, d, f = a.length, g = e.relative[a[0].type], h = g || e.relative[" "], i = g ? 1 : 0, j = bi(function (a) { + return a === b + }, h, !0), k = bi(function (a) { + return y.call(b, a) > -1 + }, h, !0), m = [function (a, c, d) { + return !g && (d || c !== l) || ((b = c).nodeType ? j(a, c, d) : k(a, c, d)) + }]; + for (; i < f; i++)if (c = e.relative[a[i].type])m = [bi(bj(m), c)]; else { + c = e.filter[a[i].type].apply(null, a[i].matches); + if (c[o]) { + d = ++i; + for (; d < f; d++)if (e.relative[a[d].type])break; + return bl(i > 1 && bj(m), i > 1 && a.slice(0, i - 1).join("").replace(L, "$1"), c, i < d && bm(a.slice(i, d)), d < f && bm(a = a.slice(d)), d < f && a.join("")) + } + m.push(c) + } + return bj(m) + } + + function bn(a, b) { + var d = b.length > 0, f = a.length > 0, g = function (h, i, j, k, m) { + var n, o, p, q = [], s = 0, u = "0", x = h && [], y = m != null, z = l, A = h || f && e.find.TAG("*", m && i.parentNode || i), B = t += z == null ? 1 : Math.E; + y && (l = i !== r && i, c = g.el); + for (; (n = A[u]) != null; u++) { + if (f && n) { + for (o = 0; p = a[o]; o++)if (p(n, i, j)) { + k.push(n); + break + } + y && (t = B, c = ++g.el) + } + d && ((n = !p && n) && s--, h && x.push(n)) + } + s += u; + if (d && u !== s) { + for (o = 0; p = b[o]; o++)p(x, q, i, j); + if (h) { + if (s > 0)while (u--)!x[u] && !q[u] && (q[u] = v.call(k)); + q = bk(q) + } + w.apply(k, q), y && !h && q.length > 0 && s + b.length > 1 && bc.uniqueSort(k) + } + return y && (t = B, l = z), x + }; + return g.el = 0, d ? z(g) : g + } + + function bo(a, b, c, d) { + var e = 0, f = b.length; + for (; e < f; e++)bc(a, b[e], c, d); + return c + } + + function bp(a, b, c, d, f) { + var g, h, j, k, l, m = bh(a), n = m.length; + if (!d && m.length === 1) { + h = m[0] = m[0].slice(0); + if (h.length > 2 && (j = h[0]).type === "ID" && b.nodeType === 9 && !f && e.relative[h[1].type]) { + b = e.find.ID(j.matches[0].replace(V, ""), b, f)[0]; + if (!b)return c; + a = a.slice(h.shift().length) + } + for (g = W.POS.test(a) ? -1 : h.length - 1; g >= 0; g--) { + j = h[g]; + if (e.relative[k = j.type])break; + if (l = e.find[k])if (d = l(j.matches[0].replace(V, ""), R.test(h[0].type) && b.parentNode || b, f)) { + h.splice(g, 1), a = d.length && h.join(""); + if (!a)return w.apply(c, x.call(d, 0)), c; + break + } + } + } + return i(a, m)(d, b, f, c, R.test(a)), c + } + + function bq() { + } + + var c, d, e, f, g, h, i, j, k, l, m = !0, n = "undefined", o = ("sizcache" + Math.random()).replace(".", ""), q = String, r = a.document, s = r.documentElement, t = 0, u = 0, v = [].pop, w = [].push, x = [].slice, y = [].indexOf || function (a) { + var b = 0, c = this.length; + for (; b < c; b++)if (this[b] === a)return b; + return -1 + }, z = function (a, b) { + return a[o] = b == null || b, a + }, A = function () { + var a = {}, b = []; + return z(function (c, d) { + return b.push(c) > e.cacheLength && delete a[b.shift()], a[c] = d + }, a) + }, B = A(), C = A(), D = A(), E = "[\\x20\\t\\r\\n\\f]", F = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", G = F.replace("w", "w#"), H = "([*^$|!~]?=)", I = "\\[" + E + "*(" + F + ")" + E + "*(?:" + H + E + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + G + ")|)|)" + E + "*\\]", J = ":(" + F + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + I + ")|[^:]|\\\\.)*|.*))\\)|)", K = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + E + "*((?:-\\d)?\\d*)" + E + "*\\)|)(?=[^-]|$)", L = new RegExp("^" + E + "+|((?:^|[^\\\\])(?:\\\\.)*)" + E + "+$", "g"), M = new RegExp("^" + E + "*," + E + "*"), N = new RegExp("^" + E + "*([\\x20\\t\\r\\n\\f>+~])" + E + "*"), O = new RegExp(J), P = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, Q = /^:not/, R = /[\x20\t\r\n\f]*[+~]/, S = /:not\($/, T = /h\d/i, U = /input|select|textarea|button/i, V = /\\(?!\\)/g, W = { + ID: new RegExp("^#(" + F + ")"), + CLASS: new RegExp("^\\.(" + F + ")"), + NAME: new RegExp("^\\[name=['\"]?(" + F + ")['\"]?\\]"), + TAG: new RegExp("^(" + F.replace("w", "w*") + ")"), + ATTR: new RegExp("^" + I), + PSEUDO: new RegExp("^" + J), + POS: new RegExp(K, "i"), + CHILD: new RegExp("^:(only|nth|first|last)-child(?:\\(" + E + "*(even|odd|(([+-]|)(\\d*)n|)" + E + "*(?:([+-]|)" + E + "*(\\d+)|))" + E + "*\\)|)", "i"), + needsContext: new RegExp("^" + E + "*[>+~]|" + K, "i") + }, X = function (a) { + var b = r.createElement("div"); + try { + return a(b) + } catch (c) { + return !1 + } finally { + b = null + } + }, Y = X(function (a) { + return a.appendChild(r.createComment("")), !a.getElementsByTagName("*").length + }), Z = X(function (a) { + return a.innerHTML = "", a.firstChild && typeof a.firstChild.getAttribute !== n && a.firstChild.getAttribute("href") === "#" + }), $ = X(function (a) { + a.innerHTML = ""; + var b = typeof a.lastChild.getAttribute("multiple"); + return b !== "boolean" && b !== "string" + }), _ = X(function (a) { + return a.innerHTML = "", !a.getElementsByClassName || !a.getElementsByClassName("e").length ? !1 : (a.lastChild.className = "e", a.getElementsByClassName("e").length === 2) + }), ba = X(function (a) { + a.id = o + 0, a.innerHTML = "
    ", s.insertBefore(a, s.firstChild); + var b = r.getElementsByName && r.getElementsByName(o).length === 2 + r.getElementsByName(o + 0).length; + return d = !r.getElementById(o), s.removeChild(a), b + }); + try { + x.call(s.childNodes, 0)[0].nodeType + } catch (bb) { + x = function (a) { + var b, c = []; + for (; b = this[a]; a++)c.push(b); + return c + } + } + bc.matches = function (a, b) { + return bc(a, null, null, b) + }, bc.matchesSelector = function (a, b) { + return bc(b, null, null, [a]).length > 0 + }, f = bc.getText = function (a) { + var b, c = "", d = 0, e = a.nodeType; + if (e) { + if (e === 1 || e === 9 || e === 11) { + if (typeof a.textContent == "string")return a.textContent; + for (a = a.firstChild; a; a = a.nextSibling)c += f(a) + } else if (e === 3 || e === 4)return a.nodeValue + } else for (; b = a[d]; d++)c += f(b); + return c + }, g = bc.isXML = function (a) { + var b = a && (a.ownerDocument || a).documentElement; + return b ? b.nodeName !== "HTML" : !1 + }, h = bc.contains = s.contains ? function (a, b) { + var c = a.nodeType === 9 ? a.documentElement : a, d = b && b.parentNode; + return a === d || !!(d && d.nodeType === 1 && c.contains && c.contains(d)) + } : s.compareDocumentPosition ? function (a, b) { + return b && !!(a.compareDocumentPosition(b) & 16) + } : function (a, b) { + while (b = b.parentNode)if (b === a)return !0; + return !1 + }, bc.attr = function (a, b) { + var c, d = g(a); + return d || (b = b.toLowerCase()), (c = e.attrHandle[b]) ? c(a) : d || $ ? a.getAttribute(b) : (c = a.getAttributeNode(b), c ? typeof a[b] == "boolean" ? a[b] ? b : null : c.specified ? c.value : null : null) + }, e = bc.selectors = { + cacheLength: 50, + createPseudo: z, + match: W, + attrHandle: Z ? {} : { + href: function (a) { + return a.getAttribute("href", 2) + }, type: function (a) { + return a.getAttribute("type") + } + }, + find: { + ID: d ? function (a, b, c) { + if (typeof b.getElementById !== n && !c) { + var d = b.getElementById(a); + return d && d.parentNode ? [d] : [] + } + } : function (a, c, d) { + if (typeof c.getElementById !== n && !d) { + var e = c.getElementById(a); + return e ? e.id === a || typeof e.getAttributeNode !== n && e.getAttributeNode("id").value === a ? [e] : b : [] + } + }, TAG: Y ? function (a, b) { + if (typeof b.getElementsByTagName !== n)return b.getElementsByTagName(a) + } : function (a, b) { + var c = b.getElementsByTagName(a); + if (a === "*") { + var d, e = [], f = 0; + for (; d = c[f]; f++)d.nodeType === 1 && e.push(d); + return e + } + return c + }, NAME: ba && function (a, b) { + if (typeof b.getElementsByName !== n)return b.getElementsByName(name) + }, CLASS: _ && function (a, b, c) { + if (typeof b.getElementsByClassName !== n && !c)return b.getElementsByClassName(a) + } + }, + relative: { + ">": {dir: "parentNode", first: !0}, + " ": {dir: "parentNode"}, + "+": {dir: "previousSibling", first: !0}, + "~": {dir: "previousSibling"} + }, + preFilter: { + ATTR: function (a) { + return a[1] = a[1].replace(V, ""), a[3] = (a[4] || a[5] || "").replace(V, ""), a[2] === "~=" && (a[3] = " " + a[3] + " "), a.slice(0, 4) + }, CHILD: function (a) { + return a[1] = a[1].toLowerCase(), a[1] === "nth" ? (a[2] || bc.error(a[0]), a[3] = +(a[3] ? a[4] + (a[5] || 1) : 2 * (a[2] === "even" || a[2] === "odd")), a[4] = +(a[6] + a[7] || a[2] === "odd")) : a[2] && bc.error(a[0]), a + }, PSEUDO: function (a) { + var b, c; + if (W.CHILD.test(a[0]))return null; + if (a[3])a[2] = a[3]; else if (b = a[4])O.test(b) && (c = bh(b, !0)) && (c = b.indexOf(")", b.length - c) - b.length) && (b = b.slice(0, c), a[0] = a[0].slice(0, c)), a[2] = b; + return a.slice(0, 3) + } + }, + filter: { + ID: d ? function (a) { + return a = a.replace(V, ""), function (b) { + return b.getAttribute("id") === a + } + } : function (a) { + return a = a.replace(V, ""), function (b) { + var c = typeof b.getAttributeNode !== n && b.getAttributeNode("id"); + return c && c.value === a + } + }, TAG: function (a) { + return a === "*" ? function () { + return !0 + } : (a = a.replace(V, "").toLowerCase(), function (b) { + return b.nodeName && b.nodeName.toLowerCase() === a + }) + }, CLASS: function (a) { + var b = B[o][a]; + return b || (b = B(a, new RegExp("(^|" + E + ")" + a + "(" + E + "|$)"))), function (a) { + return b.test(a.className || typeof a.getAttribute !== n && a.getAttribute("class") || "") + } + }, ATTR: function (a, b, c) { + return function (d, e) { + var f = bc.attr(d, a); + return f == null ? b === "!=" : b ? (f += "", b === "=" ? f === c : b === "!=" ? f !== c : b === "^=" ? c && f.indexOf(c) === 0 : b === "*=" ? c && f.indexOf(c) > -1 : b === "$=" ? c && f.substr(f.length - c.length) === c : b === "~=" ? (" " + f + " ").indexOf(c) > -1 : b === "|=" ? f === c || f.substr(0, c.length + 1) === c + "-" : !1) : !0 + } + }, CHILD: function (a, b, c, d) { + return a === "nth" ? function (a) { + var b, e, f = a.parentNode; + if (c === 1 && d === 0)return !0; + if (f) { + e = 0; + for (b = f.firstChild; b; b = b.nextSibling)if (b.nodeType === 1) { + e++; + if (a === b)break + } + } + return e -= d, e === c || e % c === 0 && e / c >= 0 + } : function (b) { + var c = b; + switch (a) { + case"only": + case"first": + while (c = c.previousSibling)if (c.nodeType === 1)return !1; + if (a === "first")return !0; + c = b; + case"last": + while (c = c.nextSibling)if (c.nodeType === 1)return !1; + return !0 + } + } + }, PSEUDO: function (a, b) { + var c, d = e.pseudos[a] || e.setFilters[a.toLowerCase()] || bc.error("unsupported pseudo: " + a); + return d[o] ? d(b) : d.length > 1 ? (c = [a, a, "", b], e.setFilters.hasOwnProperty(a.toLowerCase()) ? z(function (a, c) { + var e, f = d(a, b), g = f.length; + while (g--)e = y.call(a, f[g]), a[e] = !(c[e] = f[g]) + }) : function (a) { + return d(a, 0, c) + }) : d + } + }, + pseudos: { + not: z(function (a) { + var b = [], c = [], d = i(a.replace(L, "$1")); + return d[o] ? z(function (a, b, c, e) { + var f, g = d(a, null, e, []), h = a.length; + while (h--)if (f = g[h])a[h] = !(b[h] = f) + }) : function (a, e, f) { + return b[0] = a, d(b, null, f, c), !c.pop() + } + }), + has: z(function (a) { + return function (b) { + return bc(a, b).length > 0 + } + }), + contains: z(function (a) { + return function (b) { + return (b.textContent || b.innerText || f(b)).indexOf(a) > -1 + } + }), + enabled: function (a) { + return a.disabled === !1 + }, + disabled: function (a) { + return a.disabled === !0 + }, + checked: function (a) { + var b = a.nodeName.toLowerCase(); + return b === "input" && !!a.checked || b === "option" && !!a.selected + }, + selected: function (a) { + return a.parentNode && a.parentNode.selectedIndex, a.selected === !0 + }, + parent: function (a) { + return !e.pseudos.empty(a) + }, + empty: function (a) { + var b; + a = a.firstChild; + while (a) { + if (a.nodeName > "@" || (b = a.nodeType) === 3 || b === 4)return !1; + a = a.nextSibling + } + return !0 + }, + header: function (a) { + return T.test(a.nodeName) + }, + text: function (a) { + var b, c; + return a.nodeName.toLowerCase() === "input" && (b = a.type) === "text" && ((c = a.getAttribute("type")) == null || c.toLowerCase() === b) + }, + radio: bd("radio"), + checkbox: bd("checkbox"), + file: bd("file"), + password: bd("password"), + image: bd("image"), + submit: be("submit"), + reset: be("reset"), + button: function (a) { + var b = a.nodeName.toLowerCase(); + return b === "input" && a.type === "button" || b === "button" + }, + input: function (a) { + return U.test(a.nodeName) + }, + focus: function (a) { + var b = a.ownerDocument; + return a === b.activeElement && (!b.hasFocus || b.hasFocus()) && (!!a.type || !!a.href) + }, + active: function (a) { + return a === a.ownerDocument.activeElement + }, + first: bf(function (a, b, c) { + return [0] + }), + last: bf(function (a, b, c) { + return [b - 1] + }), + eq: bf(function (a, b, c) { + return [c < 0 ? c + b : c] + }), + even: bf(function (a, b, c) { + for (var d = 0; d < b; d += 2)a.push(d); + return a + }), + odd: bf(function (a, b, c) { + for (var d = 1; d < b; d += 2)a.push(d); + return a + }), + lt: bf(function (a, b, c) { + for (var d = c < 0 ? c + b : c; --d >= 0;)a.push(d); + return a + }), + gt: bf(function (a, b, c) { + for (var d = c < 0 ? c + b : c; ++d < b;)a.push(d); + return a + }) + } + }, j = s.compareDocumentPosition ? function (a, b) { + return a === b ? (k = !0, 0) : (!a.compareDocumentPosition || !b.compareDocumentPosition ? a.compareDocumentPosition : a.compareDocumentPosition(b) & 4) ? -1 : 1 + } : function (a, b) { + if (a === b)return k = !0, 0; + if (a.sourceIndex && b.sourceIndex)return a.sourceIndex - b.sourceIndex; + var c, d, e = [], f = [], g = a.parentNode, h = b.parentNode, i = g; + if (g === h)return bg(a, b); + if (!g)return -1; + if (!h)return 1; + while (i)e.unshift(i), i = i.parentNode; + i = h; + while (i)f.unshift(i), i = i.parentNode; + c = e.length, d = f.length; + for (var j = 0; j < c && j < d; j++)if (e[j] !== f[j])return bg(e[j], f[j]); + return j === c ? bg(a, f[j], -1) : bg(e[j], b, 1) + }, [0, 0].sort(j), m = !k, bc.uniqueSort = function (a) { + var b, c = 1; + k = m, a.sort(j); + if (k)for (; b = a[c]; c++)b === a[c - 1] && a.splice(c--, 1); + return a + }, bc.error = function (a) { + throw new Error("Syntax error, unrecognized expression: " + a) + }, i = bc.compile = function (a, b) { + var c, d = [], e = [], f = D[o][a]; + if (!f) { + b || (b = bh(a)), c = b.length; + while (c--)f = bm(b[c]), f[o] ? d.push(f) : e.push(f); + f = D(a, bn(e, d)) + } + return f + }, r.querySelectorAll && function () { + var a, b = bp, c = /'|\\/g, d = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, e = [":focus"], f = [":active", ":focus"], h = s.matchesSelector || s.mozMatchesSelector || s.webkitMatchesSelector || s.oMatchesSelector || s.msMatchesSelector; + X(function (a) { + a.innerHTML = "", a.querySelectorAll("[selected]").length || e.push("\\[" + E + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)"), a.querySelectorAll(":checked").length || e.push(":checked") + }), X(function (a) { + a.innerHTML = "

    ", a.querySelectorAll("[test^='']").length && e.push("[*^$]=" + E + "*(?:\"\"|'')"), a.innerHTML = "", a.querySelectorAll(":enabled").length || e.push(":enabled", ":disabled") + }), e = new RegExp(e.join("|")), bp = function (a, d, f, g, h) { + if (!g && !h && (!e || !e.test(a))) { + var i, j, k = !0, l = o, m = d, n = d.nodeType === 9 && a; + if (d.nodeType === 1 && d.nodeName.toLowerCase() !== "object") { + i = bh(a), (k = d.getAttribute("id")) ? l = k.replace(c, "\\$&") : d.setAttribute("id", l), l = "[id='" + l + "'] ", j = i.length; + while (j--)i[j] = l + i[j].join(""); + m = R.test(a) && d.parentNode || d, n = i.join(",") + } + if (n)try { + return w.apply(f, x.call(m.querySelectorAll(n), 0)), f + } catch (p) { + } finally { + k || d.removeAttribute("id") + } + } + return b(a, d, f, g, h) + }, h && (X(function (b) { + a = h.call(b, "div"); + try { + h.call(b, "[test!='']:sizzle"), f.push("!=", J) + } catch (c) { + } + }), f = new RegExp(f.join("|")), bc.matchesSelector = function (b, c) { + c = c.replace(d, "='$1']"); + if (!g(b) && !f.test(c) && (!e || !e.test(c)))try { + var i = h.call(b, c); + if (i || a || b.document && b.document.nodeType !== 11)return i + } catch (j) { + } + return bc(c, null, null, [b]).length > 0 + }) + }(), e.pseudos.nth = e.pseudos.eq, e.filters = bq.prototype = e.pseudos, e.setFilters = new bq, bc.attr = p.attr, p.find = bc, p.expr = bc.selectors, p.expr[":"] = p.expr.pseudos, p.unique = bc.uniqueSort, p.text = bc.getText, p.isXMLDoc = bc.isXML, p.contains = bc.contains + }(a); + var bc = /Until$/, bd = /^(?:parents|prev(?:Until|All))/, be = /^.[^:#\[\.,]*$/, bf = p.expr.match.needsContext, bg = { + children: !0, + contents: !0, + next: !0, + prev: !0 + }; + p.fn.extend({ + find: function (a) { + var b, c, d, e, f, g, h = this; + if (typeof a != "string")return p(a).filter(function () { + for (b = 0, c = h.length; b < c; b++)if (p.contains(h[b], this))return !0 + }); + g = this.pushStack("", "find", a); + for (b = 0, c = this.length; b < c; b++) { + d = g.length, p.find(a, this[b], g); + if (b > 0)for (e = d; e < g.length; e++)for (f = 0; f < d; f++)if (g[f] === g[e]) { + g.splice(e--, 1); + break + } + } + return g + }, has: function (a) { + var b, c = p(a, this), d = c.length; + return this.filter(function () { + for (b = 0; b < d; b++)if (p.contains(this, c[b]))return !0 + }) + }, not: function (a) { + return this.pushStack(bj(this, a, !1), "not", a) + }, filter: function (a) { + return this.pushStack(bj(this, a, !0), "filter", a) + }, is: function (a) { + return !!a && (typeof a == "string" ? bf.test(a) ? p(a, this.context).index(this[0]) >= 0 : p.filter(a, this).length > 0 : this.filter(a).length > 0) + }, closest: function (a, b) { + var c, d = 0, e = this.length, f = [], g = bf.test(a) || typeof a != "string" ? p(a, b || this.context) : 0; + for (; d < e; d++) { + c = this[d]; + while (c && c.ownerDocument && c !== b && c.nodeType !== 11) { + if (g ? g.index(c) > -1 : p.find.matchesSelector(c, a)) { + f.push(c); + break + } + c = c.parentNode + } + } + return f = f.length > 1 ? p.unique(f) : f, this.pushStack(f, "closest", a) + }, index: function (a) { + return a ? typeof a == "string" ? p.inArray(this[0], p(a)) : p.inArray(a.jquery ? a[0] : a, this) : this[0] && this[0].parentNode ? this.prevAll().length : -1 + }, add: function (a, b) { + var c = typeof a == "string" ? p(a, b) : p.makeArray(a && a.nodeType ? [a] : a), d = p.merge(this.get(), c); + return this.pushStack(bh(c[0]) || bh(d[0]) ? d : p.unique(d)) + }, addBack: function (a) { + return this.add(a == null ? this.prevObject : this.prevObject.filter(a)) + } + }), p.fn.andSelf = p.fn.addBack, p.each({ + parent: function (a) { + var b = a.parentNode; + return b && b.nodeType !== 11 ? b : null + }, parents: function (a) { + return p.dir(a, "parentNode") + }, parentsUntil: function (a, b, c) { + return p.dir(a, "parentNode", c) + }, next: function (a) { + return bi(a, "nextSibling") + }, prev: function (a) { + return bi(a, "previousSibling") + }, nextAll: function (a) { + return p.dir(a, "nextSibling") + }, prevAll: function (a) { + return p.dir(a, "previousSibling") + }, nextUntil: function (a, b, c) { + return p.dir(a, "nextSibling", c) + }, prevUntil: function (a, b, c) { + return p.dir(a, "previousSibling", c) + }, siblings: function (a) { + return p.sibling((a.parentNode || {}).firstChild, a) + }, children: function (a) { + return p.sibling(a.firstChild) + }, contents: function (a) { + return p.nodeName(a, "iframe") ? a.contentDocument || a.contentWindow.document : p.merge([], a.childNodes) + } + }, function (a, b) { + p.fn[a] = function (c, d) { + var e = p.map(this, b, c); + return bc.test(a) || (d = c), d && typeof d == "string" && (e = p.filter(d, e)), e = this.length > 1 && !bg[a] ? p.unique(e) : e, this.length > 1 && bd.test(a) && (e = e.reverse()), this.pushStack(e, a, k.call(arguments).join(",")) + } + }), p.extend({ + filter: function (a, b, c) { + return c && (a = ":not(" + a + ")"), b.length === 1 ? p.find.matchesSelector(b[0], a) ? [b[0]] : [] : p.find.matches(a, b) + }, dir: function (a, c, d) { + var e = [], f = a[c]; + while (f && f.nodeType !== 9 && (d === b || f.nodeType !== 1 || !p(f).is(d)))f.nodeType === 1 && e.push(f), f = f[c]; + return e + }, sibling: function (a, b) { + var c = []; + for (; a; a = a.nextSibling)a.nodeType === 1 && a !== b && c.push(a); + return c + } + }); + var bl = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", bm = / jQuery\d+="(?:null|\d+)"/g, bn = /^\s+/, bo = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, bp = /<([\w:]+)/, bq = /
    ", "
    "], + tr: [2, "", "
    "], + td: [3, "", "
    "], + col: [2, "", "
    "], + area: [1, "", ""], + _default: [0, "", ""] + }, bA = bk(e), bB = bA.appendChild(e.createElement("div")); + bz.optgroup = bz.option, bz.tbody = bz.tfoot = bz.colgroup = bz.caption = bz.thead, bz.th = bz.td, p.support.htmlSerialize || (bz._default = [1, "X
    ", "
    "]), p.fn.extend({ + text: function (a) { + return p.access(this, function (a) { + return a === b ? p.text(this) : this.empty().append((this[0] && this[0].ownerDocument || e).createTextNode(a)) + }, null, a, arguments.length) + }, wrapAll: function (a) { + if (p.isFunction(a))return this.each(function (b) { + p(this).wrapAll(a.call(this, b)) + }); + if (this[0]) { + var b = p(a, this[0].ownerDocument).eq(0).clone(!0); + this[0].parentNode && b.insertBefore(this[0]), b.map(function () { + var a = this; + while (a.firstChild && a.firstChild.nodeType === 1)a = a.firstChild; + return a + }).append(this) + } + return this + }, wrapInner: function (a) { + return p.isFunction(a) ? this.each(function (b) { + p(this).wrapInner(a.call(this, b)) + }) : this.each(function () { + var b = p(this), c = b.contents(); + c.length ? c.wrapAll(a) : b.append(a) + }) + }, wrap: function (a) { + var b = p.isFunction(a); + return this.each(function (c) { + p(this).wrapAll(b ? a.call(this, c) : a) + }) + }, unwrap: function () { + return this.parent().each(function () { + p.nodeName(this, "body") || p(this).replaceWith(this.childNodes) + }).end() + }, append: function () { + return this.domManip(arguments, !0, function (a) { + (this.nodeType === 1 || this.nodeType === 11) && this.appendChild(a) + }) + }, prepend: function () { + return this.domManip(arguments, !0, function (a) { + (this.nodeType === 1 || this.nodeType === 11) && this.insertBefore(a, this.firstChild) + }) + }, before: function () { + if (!bh(this[0]))return this.domManip(arguments, !1, function (a) { + this.parentNode.insertBefore(a, this) + }); + if (arguments.length) { + var a = p.clean(arguments); + return this.pushStack(p.merge(a, this), "before", this.selector) + } + }, after: function () { + if (!bh(this[0]))return this.domManip(arguments, !1, function (a) { + this.parentNode.insertBefore(a, this.nextSibling) + }); + if (arguments.length) { + var a = p.clean(arguments); + return this.pushStack(p.merge(this, a), "after", this.selector) + } + }, remove: function (a, b) { + var c, d = 0; + for (; (c = this[d]) != null; d++)if (!a || p.filter(a, [c]).length)!b && c.nodeType === 1 && (p.cleanData(c.getElementsByTagName("*")), p.cleanData([c])), c.parentNode && c.parentNode.removeChild(c); + return this + }, empty: function () { + var a, b = 0; + for (; (a = this[b]) != null; b++) { + a.nodeType === 1 && p.cleanData(a.getElementsByTagName("*")); + while (a.firstChild)a.removeChild(a.firstChild) + } + return this + }, clone: function (a, b) { + return a = a == null ? !1 : a, b = b == null ? a : b, this.map(function () { + return p.clone(this, a, b) + }) + }, html: function (a) { + return p.access(this, function (a) { + var c = this[0] || {}, d = 0, e = this.length; + if (a === b)return c.nodeType === 1 ? c.innerHTML.replace(bm, "") : b; + if (typeof a == "string" && !bs.test(a) && (p.support.htmlSerialize || !bu.test(a)) && (p.support.leadingWhitespace || !bn.test(a)) && !bz[(bp.exec(a) || ["", ""])[1].toLowerCase()]) { + a = a.replace(bo, "<$1>"); + try { + for (; d < e; d++)c = this[d] || {}, c.nodeType === 1 && (p.cleanData(c.getElementsByTagName("*")), c.innerHTML = a); + c = 0 + } catch (f) { + } + } + c && this.empty().append(a) + }, null, a, arguments.length) + }, replaceWith: function (a) { + return bh(this[0]) ? this.length ? this.pushStack(p(p.isFunction(a) ? a() : a), "replaceWith", a) : this : p.isFunction(a) ? this.each(function (b) { + var c = p(this), d = c.html(); + c.replaceWith(a.call(this, b, d)) + }) : (typeof a != "string" && (a = p(a).detach()), this.each(function () { + var b = this.nextSibling, c = this.parentNode; + p(this).remove(), b ? p(b).before(a) : p(c).append(a) + })) + }, detach: function (a) { + return this.remove(a, !0) + }, domManip: function (a, c, d) { + a = [].concat.apply([], a); + var e, f, g, h, i = 0, j = a[0], k = [], l = this.length; + if (!p.support.checkClone && l > 1 && typeof j == "string" && bw.test(j))return this.each(function () { + p(this).domManip(a, c, d) + }); + if (p.isFunction(j))return this.each(function (e) { + var f = p(this); + a[0] = j.call(this, e, c ? f.html() : b), f.domManip(a, c, d) + }); + if (this[0]) { + e = p.buildFragment(a, this, k), g = e.fragment, f = g.firstChild, g.childNodes.length === 1 && (g = f); + if (f) { + c = c && p.nodeName(f, "tr"); + for (h = e.cacheable || l - 1; i < l; i++)d.call(c && p.nodeName(this[i], "table") ? bC(this[i], "tbody") : this[i], i === h ? g : p.clone(g, !0, !0)) + } + g = f = null, k.length && p.each(k, function (a, b) { + b.src ? p.ajax ? p.ajax({ + url: b.src, + type: "GET", + dataType: "script", + async: !1, + global: !1, + "throws": !0 + }) : p.error("no ajax") : p.globalEval((b.text || b.textContent || b.innerHTML || "").replace(by, "")), b.parentNode && b.parentNode.removeChild(b) + }) + } + return this + } + }), p.buildFragment = function (a, c, d) { + var f, g, h, i = a[0]; + return c = c || e, c = !c.nodeType && c[0] || c, c = c.ownerDocument || c, a.length === 1 && typeof i == "string" && i.length < 512 && c === e && i.charAt(0) === "<" && !bt.test(i) && (p.support.checkClone || !bw.test(i)) && (p.support.html5Clone || !bu.test(i)) && (g = !0, f = p.fragments[i], h = f !== b), f || (f = c.createDocumentFragment(), p.clean(a, c, f, d), g && (p.fragments[i] = h && f)), { + fragment: f, + cacheable: g + } + }, p.fragments = {}, p.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" + }, function (a, b) { + p.fn[a] = function (c) { + var d, e = 0, f = [], g = p(c), h = g.length, i = this.length === 1 && this[0].parentNode; + if ((i == null || i && i.nodeType === 11 && i.childNodes.length === 1) && h === 1)return g[b](this[0]), this; + for (; e < h; e++)d = (e > 0 ? this.clone(!0) : this).get(), p(g[e])[b](d), f = f.concat(d); + return this.pushStack(f, a, g.selector) + } + }), p.extend({ + clone: function (a, b, c) { + var d, e, f, g; + p.support.html5Clone || p.isXMLDoc(a) || !bu.test("<" + a.nodeName + ">") ? g = a.cloneNode(!0) : (bB.innerHTML = a.outerHTML, bB.removeChild(g = bB.firstChild)); + if ((!p.support.noCloneEvent || !p.support.noCloneChecked) && (a.nodeType === 1 || a.nodeType === 11) && !p.isXMLDoc(a)) { + bE(a, g), d = bF(a), e = bF(g); + for (f = 0; d[f]; ++f)e[f] && bE(d[f], e[f]) + } + if (b) { + bD(a, g); + if (c) { + d = bF(a), e = bF(g); + for (f = 0; d[f]; ++f)bD(d[f], e[f]) + } + } + return d = e = null, g + }, clean: function (a, b, c, d) { + var f, g, h, i, j, k, l, m, n, o, q, r, s = b === e && bA, t = []; + if (!b || typeof b.createDocumentFragment == "undefined")b = e; + for (f = 0; (h = a[f]) != null; f++) { + typeof h == "number" && (h += ""); + if (!h)continue; + if (typeof h == "string")if (!br.test(h))h = b.createTextNode(h); else { + s = s || bk(b), l = b.createElement("div"), s.appendChild(l), h = h.replace(bo, "<$1>"), i = (bp.exec(h) || ["", ""])[1].toLowerCase(), j = bz[i] || bz._default, k = j[0], l.innerHTML = j[1] + h + j[2]; + while (k--)l = l.lastChild; + if (!p.support.tbody) { + m = bq.test(h), n = i === "table" && !m ? l.firstChild && l.firstChild.childNodes : j[1] === "" && !m ? l.childNodes : []; + for (g = n.length - 1; g >= 0; --g)p.nodeName(n[g], "tbody") && !n[g].childNodes.length && n[g].parentNode.removeChild(n[g]) + } + !p.support.leadingWhitespace && bn.test(h) && l.insertBefore(b.createTextNode(bn.exec(h)[0]), l.firstChild), h = l.childNodes, l.parentNode.removeChild(l) + } + h.nodeType ? t.push(h) : p.merge(t, h) + } + l && (h = l = s = null); + if (!p.support.appendChecked)for (f = 0; (h = t[f]) != null; f++)p.nodeName(h, "input") ? bG(h) : typeof h.getElementsByTagName != "undefined" && p.grep(h.getElementsByTagName("input"), bG); + if (c) { + q = function (a) { + if (!a.type || bx.test(a.type))return d ? d.push(a.parentNode ? a.parentNode.removeChild(a) : a) : c.appendChild(a) + }; + for (f = 0; (h = t[f]) != null; f++)if (!p.nodeName(h, "script") || !q(h))c.appendChild(h), typeof h.getElementsByTagName != "undefined" && (r = p.grep(p.merge([], h.getElementsByTagName("script")), q), t.splice.apply(t, [f + 1, 0].concat(r)), f += r.length) + } + return t + }, cleanData: function (a, b) { + var c, d, e, f, g = 0, h = p.expando, i = p.cache, j = p.support.deleteExpando, k = p.event.special; + for (; (e = a[g]) != null; g++)if (b || p.acceptData(e)) { + d = e[h], c = d && i[d]; + if (c) { + if (c.events)for (f in c.events)k[f] ? p.event.remove(e, f) : p.removeEvent(e, f, c.handle); + i[d] && (delete i[d], j ? delete e[h] : e.removeAttribute ? e.removeAttribute(h) : e[h] = null, p.deletedIds.push(d)) + } + } + } + }), function () { + var a, b; + p.uaMatch = function (a) { + a = a.toLowerCase(); + var b = /(chrome)[ \/]([\w.]+)/.exec(a) || /(webkit)[ \/]([\w.]+)/.exec(a) || /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a) || /(msie) ([\w.]+)/.exec(a) || a.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a) || []; + return {browser: b[1] || "", version: b[2] || "0"} + }, a = p.uaMatch(g.userAgent), b = {}, a.browser && (b[a.browser] = !0, b.version = a.version), b.chrome ? b.webkit = !0 : b.webkit && (b.safari = !0), p.browser = b, p.sub = function () { + function a(b, c) { + return new a.fn.init(b, c) + } + + p.extend(!0, a, this), a.superclass = this, a.fn = a.prototype = this(), a.fn.constructor = a, a.sub = this.sub, a.fn.init = function c(c, d) { + return d && d instanceof p && !(d instanceof a) && (d = a(d)), p.fn.init.call(this, c, d, b) + }, a.fn.init.prototype = a.fn; + var b = a(e); + return a + } + }(); + var bH, bI, bJ, bK = /alpha\([^)]*\)/i, bL = /opacity=([^)]*)/, bM = /^(top|right|bottom|left)$/, bN = /^(none|table(?!-c[ea]).+)/, bO = /^margin/, bP = new RegExp("^(" + q + ")(.*)$", "i"), bQ = new RegExp("^(" + q + ")(?!px)[a-z%]+$", "i"), bR = new RegExp("^([-+])=(" + q + ")", "i"), bS = {}, bT = { + position: "absolute", + visibility: "hidden", + display: "block" + }, bU = { + letterSpacing: 0, + fontWeight: 400 + }, bV = ["Top", "Right", "Bottom", "Left"], bW = ["Webkit", "O", "Moz", "ms"], bX = p.fn.toggle; + p.fn.extend({ + css: function (a, c) { + return p.access(this, function (a, c, d) { + return d !== b ? p.style(a, c, d) : p.css(a, c) + }, a, c, arguments.length > 1) + }, show: function () { + return b$(this, !0) + }, hide: function () { + return b$(this) + }, toggle: function (a, b) { + var c = typeof a == "boolean"; + return p.isFunction(a) && p.isFunction(b) ? bX.apply(this, arguments) : this.each(function () { + (c ? a : bZ(this)) ? p(this).show() : p(this).hide() + }) + } + }), p.extend({ + cssHooks: { + opacity: { + get: function (a, b) { + if (b) { + var c = bH(a, "opacity"); + return c === "" ? "1" : c + } + } + } + }, + cssNumber: { + fillOpacity: !0, + fontWeight: !0, + lineHeight: !0, + opacity: !0, + orphans: !0, + widows: !0, + zIndex: !0, + zoom: !0 + }, + cssProps: {"float": p.support.cssFloat ? "cssFloat" : "styleFloat"}, + style: function (a, c, d, e) { + if (!a || a.nodeType === 3 || a.nodeType === 8 || !a.style)return; + var f, g, h, i = p.camelCase(c), j = a.style; + c = p.cssProps[i] || (p.cssProps[i] = bY(j, i)), h = p.cssHooks[c] || p.cssHooks[i]; + if (d === b)return h && "get"in h && (f = h.get(a, !1, e)) !== b ? f : j[c]; + g = typeof d, g === "string" && (f = bR.exec(d)) && (d = (f[1] + 1) * f[2] + parseFloat(p.css(a, c)), g = "number"); + if (d == null || g === "number" && isNaN(d))return; + g === "number" && !p.cssNumber[i] && (d += "px"); + if (!h || !("set"in h) || (d = h.set(a, d, e)) !== b)try { + j[c] = d + } catch (k) { + } + }, + css: function (a, c, d, e) { + var f, g, h, i = p.camelCase(c); + return c = p.cssProps[i] || (p.cssProps[i] = bY(a.style, i)), h = p.cssHooks[c] || p.cssHooks[i], h && "get"in h && (f = h.get(a, !0, e)), f === b && (f = bH(a, c)), f === "normal" && c in bU && (f = bU[c]), d || e !== b ? (g = parseFloat(f), d || p.isNumeric(g) ? g || 0 : f) : f + }, + swap: function (a, b, c) { + var d, e, f = {}; + for (e in b)f[e] = a.style[e], a.style[e] = b[e]; + d = c.call(a); + for (e in b)a.style[e] = f[e]; + return d + } + }), a.getComputedStyle ? bH = function (b, c) { + var d, e, f, g, h = a.getComputedStyle(b, null), i = b.style; + return h && (d = h[c], d === "" && !p.contains(b.ownerDocument, b) && (d = p.style(b, c)), bQ.test(d) && bO.test(c) && (e = i.width, f = i.minWidth, g = i.maxWidth, i.minWidth = i.maxWidth = i.width = d, d = h.width, i.width = e, i.minWidth = f, i.maxWidth = g)), d + } : e.documentElement.currentStyle && (bH = function (a, b) { + var c, d, e = a.currentStyle && a.currentStyle[b], f = a.style; + return e == null && f && f[b] && (e = f[b]), bQ.test(e) && !bM.test(b) && (c = f.left, d = a.runtimeStyle && a.runtimeStyle.left, d && (a.runtimeStyle.left = a.currentStyle.left), f.left = b === "fontSize" ? "1em" : e, e = f.pixelLeft + "px", f.left = c, d && (a.runtimeStyle.left = d)), e === "" ? "auto" : e + }), p.each(["height", "width"], function (a, b) { + p.cssHooks[b] = { + get: function (a, c, d) { + if (c)return a.offsetWidth === 0 && bN.test(bH(a, "display")) ? p.swap(a, bT, function () { + return cb(a, b, d) + }) : cb(a, b, d) + }, set: function (a, c, d) { + return b_(a, c, d ? ca(a, b, d, p.support.boxSizing && p.css(a, "boxSizing") === "border-box") : 0) + } + } + }), p.support.opacity || (p.cssHooks.opacity = { + get: function (a, b) { + return bL.test((b && a.currentStyle ? a.currentStyle.filter : a.style.filter) || "") ? .01 * parseFloat(RegExp.$1) + "" : b ? "1" : "" + }, set: function (a, b) { + var c = a.style, d = a.currentStyle, e = p.isNumeric(b) ? "alpha(opacity=" + b * 100 + ")" : "", f = d && d.filter || c.filter || ""; + c.zoom = 1; + if (b >= 1 && p.trim(f.replace(bK, "")) === "" && c.removeAttribute) { + c.removeAttribute("filter"); + if (d && !d.filter)return + } + c.filter = bK.test(f) ? f.replace(bK, e) : f + " " + e + } + }), p(function () { + p.support.reliableMarginRight || (p.cssHooks.marginRight = { + get: function (a, b) { + return p.swap(a, {display: "inline-block"}, function () { + if (b)return bH(a, "marginRight") + }) + } + }), !p.support.pixelPosition && p.fn.position && p.each(["top", "left"], function (a, b) { + p.cssHooks[b] = { + get: function (a, c) { + if (c) { + var d = bH(a, b); + return bQ.test(d) ? p(a).position()[b] + "px" : d + } + } + } + }) + }), p.expr && p.expr.filters && (p.expr.filters.hidden = function (a) { + return a.offsetWidth === 0 && a.offsetHeight === 0 || !p.support.reliableHiddenOffsets && (a.style && a.style.display || bH(a, "display")) === "none" + }, p.expr.filters.visible = function (a) { + return !p.expr.filters.hidden(a) + }), p.each({margin: "", padding: "", border: "Width"}, function (a, b) { + p.cssHooks[a + b] = { + expand: function (c) { + var d, e = typeof c == "string" ? c.split(" ") : [c], f = {}; + for (d = 0; d < 4; d++)f[a + bV[d] + b] = e[d] || e[d - 2] || e[0]; + return f + } + }, bO.test(a) || (p.cssHooks[a + b].set = b_) + }); + var cd = /%20/g, ce = /\[\]$/, cf = /\r?\n/g, cg = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, ch = /^(?:select|textarea)/i; + p.fn.extend({ + serialize: function () { + return p.param(this.serializeArray()) + }, serializeArray: function () { + return this.map(function () { + return this.elements ? p.makeArray(this.elements) : this + }).filter(function () { + return this.name && !this.disabled && (this.checked || ch.test(this.nodeName) || cg.test(this.type)) + }).map(function (a, b) { + var c = p(this).val(); + return c == null ? null : p.isArray(c) ? p.map(c, function (a, c) { + return {name: b.name, value: a.replace(cf, "\r\n")} + }) : {name: b.name, value: c.replace(cf, "\r\n")} + }).get() + } + }), p.param = function (a, c) { + var d, e = [], f = function (a, b) { + b = p.isFunction(b) ? b() : b == null ? "" : b, e[e.length] = encodeURIComponent(a) + "=" + encodeURIComponent(b) + }; + c === b && (c = p.ajaxSettings && p.ajaxSettings.traditional); + if (p.isArray(a) || a.jquery && !p.isPlainObject(a))p.each(a, function () { + f(this.name, this.value) + }); else for (d in a)ci(d, a[d], c, f); + return e.join("&").replace(cd, "+") + }; + var cj, ck, cl = /#.*$/, cm = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, cn = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/, co = /^(?:GET|HEAD)$/, cp = /^\/\//, cq = /\?/, cr = /)<[^<]*)*<\/script>/gi, cs = /([?&])_=[^&]*/, ct = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, cu = p.fn.load, cv = {}, cw = {}, cx = ["*/"] + ["*"]; + try { + ck = f.href + } catch (cy) { + ck = e.createElement("a"), ck.href = "", ck = ck.href + } + cj = ct.exec(ck.toLowerCase()) || [], p.fn.load = function (a, c, d) { + if (typeof a != "string" && cu)return cu.apply(this, arguments); + if (!this.length)return this; + var e, f, g, h = this, i = a.indexOf(" "); + return i >= 0 && (e = a.slice(i, a.length), a = a.slice(0, i)), p.isFunction(c) ? (d = c, c = b) : c && typeof c == "object" && (f = "POST"), p.ajax({ + url: a, + type: f, + dataType: "html", + data: c, + complete: function (a, b) { + d && h.each(d, g || [a.responseText, b, a]) + } + }).done(function (a) { + g = arguments, h.html(e ? p("
    ").append(a.replace(cr, "")).find(e) : a) + }), this + }, p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), function (a, b) { + p.fn[b] = function (a) { + return this.on(b, a) + } + }), p.each(["get", "post"], function (a, c) { + p[c] = function (a, d, e, f) { + return p.isFunction(d) && (f = f || e, e = d, d = b), p.ajax({ + type: c, + url: a, + data: d, + success: e, + dataType: f + }) + } + }), p.extend({ + getScript: function (a, c) { + return p.get(a, b, c, "script") + }, + getJSON: function (a, b, c) { + return p.get(a, b, c, "json") + }, + ajaxSetup: function (a, b) { + return b ? cB(a, p.ajaxSettings) : (b = a, a = p.ajaxSettings), cB(a, b), a + }, + ajaxSettings: { + url: ck, + isLocal: cn.test(cj[1]), + global: !0, + type: "GET", + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + processData: !0, + async: !0, + accepts: { + xml: "application/xml, text/xml", + html: "text/html", + text: "text/plain", + json: "application/json, text/javascript", + "*": cx + }, + contents: {xml: /xml/, html: /html/, json: /json/}, + responseFields: {xml: "responseXML", text: "responseText"}, + converters: {"* text": a.String, "text html": !0, "text json": p.parseJSON, "text xml": p.parseXML}, + flatOptions: {context: !0, url: !0} + }, + ajaxPrefilter: cz(cv), + ajaxTransport: cz(cw), + ajax: function (a, c) { + function y(a, c, f, i) { + var k, s, t, u, w, y = c; + if (v === 2)return; + v = 2, h && clearTimeout(h), g = b, e = i || "", x.readyState = a > 0 ? 4 : 0, f && (u = cC(l, x, f)); + if (a >= 200 && a < 300 || a === 304)l.ifModified && (w = x.getResponseHeader("Last-Modified"), w && (p.lastModified[d] = w), w = x.getResponseHeader("Etag"), w && (p.etag[d] = w)), a === 304 ? (y = "notmodified", k = !0) : (k = cD(l, u), y = k.state, s = k.data, t = k.error, k = !t); else { + t = y; + if (!y || a)y = "error", a < 0 && (a = 0) + } + x.status = a, x.statusText = (c || y) + "", k ? o.resolveWith(m, [s, y, x]) : o.rejectWith(m, [x, y, t]), x.statusCode(r), r = b, j && n.trigger("ajax" + (k ? "Success" : "Error"), [x, l, k ? s : t]), q.fireWith(m, [x, y]), j && (n.trigger("ajaxComplete", [x, l]), --p.active || p.event.trigger("ajaxStop")) + } + + typeof a == "object" && (c = a, a = b), c = c || {}; + var d, e, f, g, h, i, j, k, l = p.ajaxSetup({}, c), m = l.context || l, n = m !== l && (m.nodeType || m instanceof p) ? p(m) : p.event, o = p.Deferred(), q = p.Callbacks("once memory"), r = l.statusCode || {}, t = {}, u = {}, v = 0, w = "canceled", x = { + readyState: 0, + setRequestHeader: function (a, b) { + if (!v) { + var c = a.toLowerCase(); + a = u[c] = u[c] || a, t[a] = b + } + return this + }, + getAllResponseHeaders: function () { + return v === 2 ? e : null + }, + getResponseHeader: function (a) { + var c; + if (v === 2) { + if (!f) { + f = {}; + while (c = cm.exec(e))f[c[1].toLowerCase()] = c[2] + } + c = f[a.toLowerCase()] + } + return c === b ? null : c + }, + overrideMimeType: function (a) { + return v || (l.mimeType = a), this + }, + abort: function (a) { + return a = a || w, g && g.abort(a), y(0, a), this + } + }; + o.promise(x), x.success = x.done, x.error = x.fail, x.complete = q.add, x.statusCode = function (a) { + if (a) { + var b; + if (v < 2)for (b in a)r[b] = [r[b], a[b]]; else b = a[x.status], x.always(b) + } + return this + }, l.url = ((a || l.url) + "").replace(cl, "").replace(cp, cj[1] + "//"), l.dataTypes = p.trim(l.dataType || "*").toLowerCase().split(s), l.crossDomain == null && (i = ct.exec(l.url.toLowerCase()) || !1, l.crossDomain = i && i.join(":") + (i[3] ? "" : i[1] === "http:" ? 80 : 443) !== cj.join(":") + (cj[3] ? "" : cj[1] === "http:" ? 80 : 443)), l.data && l.processData && typeof l.data != "string" && (l.data = p.param(l.data, l.traditional)), cA(cv, l, c, x); + if (v === 2)return x; + j = l.global, l.type = l.type.toUpperCase(), l.hasContent = !co.test(l.type), j && p.active++ === 0 && p.event.trigger("ajaxStart"); + if (!l.hasContent) { + l.data && (l.url += (cq.test(l.url) ? "&" : "?") + l.data, delete l.data), d = l.url; + if (l.cache === !1) { + var z = p.now(), A = l.url.replace(cs, "$1_=" + z); + l.url = A + (A === l.url ? (cq.test(l.url) ? "&" : "?") + "_=" + z : "") + } + } + (l.data && l.hasContent && l.contentType !== !1 || c.contentType) && x.setRequestHeader("Content-Type", l.contentType), l.ifModified && (d = d || l.url, p.lastModified[d] && x.setRequestHeader("If-Modified-Since", p.lastModified[d]), p.etag[d] && x.setRequestHeader("If-None-Match", p.etag[d])), x.setRequestHeader("Accept", l.dataTypes[0] && l.accepts[l.dataTypes[0]] ? l.accepts[l.dataTypes[0]] + (l.dataTypes[0] !== "*" ? ", " + cx + "; q=0.01" : "") : l.accepts["*"]); + for (k in l.headers)x.setRequestHeader(k, l.headers[k]); + if (!l.beforeSend || l.beforeSend.call(m, x, l) !== !1 && v !== 2) { + w = "abort"; + for (k in{success: 1, error: 1, complete: 1})x[k](l[k]); + g = cA(cw, l, c, x); + if (!g)y(-1, "No Transport"); else { + x.readyState = 1, j && n.trigger("ajaxSend", [x, l]), l.async && l.timeout > 0 && (h = setTimeout(function () { + x.abort("timeout") + }, l.timeout)); + try { + v = 1, g.send(t, y) + } catch (B) { + if (v < 2)y(-1, B); else throw B + } + } + return x + } + return x.abort() + }, + active: 0, + lastModified: {}, + etag: {} + }); + var cE = [], cF = /\?/, cG = /(=)\?(?=&|$)|\?\?/, cH = p.now(); + p.ajaxSetup({ + jsonp: "callback", jsonpCallback: function () { + var a = cE.pop() || p.expando + "_" + cH++; + return this[a] = !0, a + } + }), p.ajaxPrefilter("json jsonp", function (c, d, e) { + var f, g, h, i = c.data, j = c.url, k = c.jsonp !== !1, l = k && cG.test(j), m = k && !l && typeof i == "string" && !(c.contentType || "").indexOf("application/x-www-form-urlencoded") && cG.test(i); + if (c.dataTypes[0] === "jsonp" || l || m)return f = c.jsonpCallback = p.isFunction(c.jsonpCallback) ? c.jsonpCallback() : c.jsonpCallback, g = a[f], l ? c.url = j.replace(cG, "$1" + f) : m ? c.data = i.replace(cG, "$1" + f) : k && (c.url += (cF.test(j) ? "&" : "?") + c.jsonp + "=" + f), c.converters["script json"] = function () { + return h || p.error(f + " was not called"), h[0] + }, c.dataTypes[0] = "json", a[f] = function () { + h = arguments + }, e.always(function () { + a[f] = g, c[f] && (c.jsonpCallback = d.jsonpCallback, cE.push(f)), h && p.isFunction(g) && g(h[0]), h = g = b + }), "script" + }), p.ajaxSetup({ + accepts: {script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"}, + contents: {script: /javascript|ecmascript/}, + converters: { + "text script": function (a) { + return p.globalEval(a), a + } + } + }), p.ajaxPrefilter("script", function (a) { + a.cache === b && (a.cache = !1), a.crossDomain && (a.type = "GET", a.global = !1) + }), p.ajaxTransport("script", function (a) { + if (a.crossDomain) { + var c, d = e.head || e.getElementsByTagName("head")[0] || e.documentElement; + return { + send: function (f, g) { + c = e.createElement("script"), c.async = "async", a.scriptCharset && (c.charset = a.scriptCharset), c.src = a.url, c.onload = c.onreadystatechange = function (a, e) { + if (e || !c.readyState || /loaded|complete/.test(c.readyState))c.onload = c.onreadystatechange = null, d && c.parentNode && d.removeChild(c), c = b, e || g(200, "success") + }, d.insertBefore(c, d.firstChild) + }, abort: function () { + c && c.onload(0, 1) + } + } + } + }); + var cI, cJ = a.ActiveXObject ? function () { + for (var a in cI)cI[a](0, 1) + } : !1, cK = 0; + p.ajaxSettings.xhr = a.ActiveXObject ? function () { + return !this.isLocal && cL() || cM() + } : cL, function (a) { + p.extend(p.support, {ajax: !!a, cors: !!a && "withCredentials"in a}) + }(p.ajaxSettings.xhr()), p.support.ajax && p.ajaxTransport(function (c) { + if (!c.crossDomain || p.support.cors) { + var d; + return { + send: function (e, f) { + var g, h, i = c.xhr(); + c.username ? i.open(c.type, c.url, c.async, c.username, c.password) : i.open(c.type, c.url, c.async); + if (c.xhrFields)for (h in c.xhrFields)i[h] = c.xhrFields[h]; + c.mimeType && i.overrideMimeType && i.overrideMimeType(c.mimeType), !c.crossDomain && !e["X-Requested-With"] && (e["X-Requested-With"] = "XMLHttpRequest"); + try { + for (h in e)i.setRequestHeader(h, e[h]) + } catch (j) { + } + i.send(c.hasContent && c.data || null), d = function (a, e) { + var h, j, k, l, m; + try { + if (d && (e || i.readyState === 4)) { + d = b, g && (i.onreadystatechange = p.noop, cJ && delete cI[g]); + if (e)i.readyState !== 4 && i.abort(); else { + h = i.status, k = i.getAllResponseHeaders(), l = {}, m = i.responseXML, m && m.documentElement && (l.xml = m); + try { + l.text = i.responseText + } catch (a) { + } + try { + j = i.statusText + } catch (n) { + j = "" + } + !h && c.isLocal && !c.crossDomain ? h = l.text ? 200 : 404 : h === 1223 && (h = 204) + } + } + } catch (o) { + e || f(-1, o) + } + l && f(h, j, l, k) + }, c.async ? i.readyState === 4 ? setTimeout(d, 0) : (g = ++cK, cJ && (cI || (cI = {}, p(a).unload(cJ)), cI[g] = d), i.onreadystatechange = d) : d() + }, abort: function () { + d && d(0, 1) + } + } + } + }); + var cN, cO, cP = /^(?:toggle|show|hide)$/, cQ = new RegExp("^(?:([-+])=|)(" + q + ")([a-z%]*)$", "i"), cR = /queueHooks$/, cS = [cY], cT = { + "*": [function (a, b) { + var c, d, e = this.createTween(a, b), f = cQ.exec(b), g = e.cur(), h = +g || 0, i = 1, j = 20; + if (f) { + c = +f[2], d = f[3] || (p.cssNumber[a] ? "" : "px"); + if (d !== "px" && h) { + h = p.css(e.elem, a, !0) || c || 1; + do i = i || ".5", h = h / i, p.style(e.elem, a, h + d); while (i !== (i = e.cur() / g) && i !== 1 && --j) + } + e.unit = d, e.start = h, e.end = f[1] ? h + (f[1] + 1) * c : c + } + return e + }] + }; + p.Animation = p.extend(cW, { + tweener: function (a, b) { + p.isFunction(a) ? (b = a, a = ["*"]) : a = a.split(" "); + var c, d = 0, e = a.length; + for (; d < e; d++)c = a[d], cT[c] = cT[c] || [], cT[c].unshift(b) + }, prefilter: function (a, b) { + b ? cS.unshift(a) : cS.push(a) + } + }), p.Tween = cZ, cZ.prototype = { + constructor: cZ, init: function (a, b, c, d, e, f) { + this.elem = a, this.prop = c, this.easing = e || "swing", this.options = b, this.start = this.now = this.cur(), this.end = d, this.unit = f || (p.cssNumber[c] ? "" : "px") + }, cur: function () { + var a = cZ.propHooks[this.prop]; + return a && a.get ? a.get(this) : cZ.propHooks._default.get(this) + }, run: function (a) { + var b, c = cZ.propHooks[this.prop]; + return this.options.duration ? this.pos = b = p.easing[this.easing](a, this.options.duration * a, 0, 1, this.options.duration) : this.pos = b = a, this.now = (this.end - this.start) * b + this.start, this.options.step && this.options.step.call(this.elem, this.now, this), c && c.set ? c.set(this) : cZ.propHooks._default.set(this), this + } + }, cZ.prototype.init.prototype = cZ.prototype, cZ.propHooks = { + _default: { + get: function (a) { + var b; + return a.elem[a.prop] == null || !!a.elem.style && a.elem.style[a.prop] != null ? (b = p.css(a.elem, a.prop, !1, ""), !b || b === "auto" ? 0 : b) : a.elem[a.prop] + }, set: function (a) { + p.fx.step[a.prop] ? p.fx.step[a.prop](a) : a.elem.style && (a.elem.style[p.cssProps[a.prop]] != null || p.cssHooks[a.prop]) ? p.style(a.elem, a.prop, a.now + a.unit) : a.elem[a.prop] = a.now + } + } + }, cZ.propHooks.scrollTop = cZ.propHooks.scrollLeft = { + set: function (a) { + a.elem.nodeType && a.elem.parentNode && (a.elem[a.prop] = a.now) + } + }, p.each(["toggle", "show", "hide"], function (a, b) { + var c = p.fn[b]; + p.fn[b] = function (d, e, f) { + return d == null || typeof d == "boolean" || !a && p.isFunction(d) && p.isFunction(e) ? c.apply(this, arguments) : this.animate(c$(b, !0), d, e, f) + } + }), p.fn.extend({ + fadeTo: function (a, b, c, d) { + return this.filter(bZ).css("opacity", 0).show().end().animate({opacity: b}, a, c, d) + }, animate: function (a, b, c, d) { + var e = p.isEmptyObject(a), f = p.speed(b, c, d), g = function () { + var b = cW(this, p.extend({}, a), f); + e && b.stop(!0) + }; + return e || f.queue === !1 ? this.each(g) : this.queue(f.queue, g) + }, stop: function (a, c, d) { + var e = function (a) { + var b = a.stop; + delete a.stop, b(d) + }; + return typeof a != "string" && (d = c, c = a, a = b), c && a !== !1 && this.queue(a || "fx", []), this.each(function () { + var b = !0, c = a != null && a + "queueHooks", f = p.timers, g = p._data(this); + if (c)g[c] && g[c].stop && e(g[c]); else for (c in g)g[c] && g[c].stop && cR.test(c) && e(g[c]); + for (c = f.length; c--;)f[c].elem === this && (a == null || f[c].queue === a) && (f[c].anim.stop(d), b = !1, f.splice(c, 1)); + (b || !d) && p.dequeue(this, a) + }) + } + }), p.each({ + slideDown: c$("show"), + slideUp: c$("hide"), + slideToggle: c$("toggle"), + fadeIn: {opacity: "show"}, + fadeOut: {opacity: "hide"}, + fadeToggle: {opacity: "toggle"} + }, function (a, b) { + p.fn[a] = function (a, c, d) { + return this.animate(b, a, c, d) + } + }), p.speed = function (a, b, c) { + var d = a && typeof a == "object" ? p.extend({}, a) : { + complete: c || !c && b || p.isFunction(a) && a, + duration: a, + easing: c && b || b && !p.isFunction(b) && b + }; + d.duration = p.fx.off ? 0 : typeof d.duration == "number" ? d.duration : d.duration in p.fx.speeds ? p.fx.speeds[d.duration] : p.fx.speeds._default; + if (d.queue == null || d.queue === !0)d.queue = "fx"; + return d.old = d.complete, d.complete = function () { + p.isFunction(d.old) && d.old.call(this), d.queue && p.dequeue(this, d.queue) + }, d + }, p.easing = { + linear: function (a) { + return a + }, swing: function (a) { + return .5 - Math.cos(a * Math.PI) / 2 + } + }, p.timers = [], p.fx = cZ.prototype.init, p.fx.tick = function () { + var a, b = p.timers, c = 0; + for (; c < b.length; c++)a = b[c], !a() && b[c] === a && b.splice(c--, 1); + b.length || p.fx.stop() + }, p.fx.timer = function (a) { + a() && p.timers.push(a) && !cO && (cO = setInterval(p.fx.tick, p.fx.interval)) + }, p.fx.interval = 13, p.fx.stop = function () { + clearInterval(cO), cO = null + }, p.fx.speeds = { + slow: 600, + fast: 200, + _default: 400 + }, p.fx.step = {}, p.expr && p.expr.filters && (p.expr.filters.animated = function (a) { + return p.grep(p.timers, function (b) { + return a === b.elem + }).length + }); + var c_ = /^(?:body|html)$/i; + p.fn.offset = function (a) { + if (arguments.length)return a === b ? this : this.each(function (b) { + p.offset.setOffset(this, a, b) + }); + var c, d, e, f, g, h, i, j = {top: 0, left: 0}, k = this[0], l = k && k.ownerDocument; + if (!l)return; + return (d = l.body) === k ? p.offset.bodyOffset(k) : (c = l.documentElement, p.contains(c, k) ? (typeof k.getBoundingClientRect != "undefined" && (j = k.getBoundingClientRect()), e = da(l), f = c.clientTop || d.clientTop || 0, g = c.clientLeft || d.clientLeft || 0, h = e.pageYOffset || c.scrollTop, i = e.pageXOffset || c.scrollLeft, { + top: j.top + h - f, + left: j.left + i - g + }) : j) + }, p.offset = { + bodyOffset: function (a) { + var b = a.offsetTop, c = a.offsetLeft; + return p.support.doesNotIncludeMarginInBodyOffset && (b += parseFloat(p.css(a, "marginTop")) || 0, c += parseFloat(p.css(a, "marginLeft")) || 0), { + top: b, + left: c + } + }, setOffset: function (a, b, c) { + var d = p.css(a, "position"); + d === "static" && (a.style.position = "relative"); + var e = p(a), f = e.offset(), g = p.css(a, "top"), h = p.css(a, "left"), i = (d === "absolute" || d === "fixed") && p.inArray("auto", [g, h]) > -1, j = {}, k = {}, l, m; + i ? (k = e.position(), l = k.top, m = k.left) : (l = parseFloat(g) || 0, m = parseFloat(h) || 0), p.isFunction(b) && (b = b.call(a, c, f)), b.top != null && (j.top = b.top - f.top + l), b.left != null && (j.left = b.left - f.left + m), "using"in b ? b.using.call(a, j) : e.css(j) + } + }, p.fn.extend({ + position: function () { + if (!this[0])return; + var a = this[0], b = this.offsetParent(), c = this.offset(), d = c_.test(b[0].nodeName) ? { + top: 0, + left: 0 + } : b.offset(); + return c.top -= parseFloat(p.css(a, "marginTop")) || 0, c.left -= parseFloat(p.css(a, "marginLeft")) || 0, d.top += parseFloat(p.css(b[0], "borderTopWidth")) || 0, d.left += parseFloat(p.css(b[0], "borderLeftWidth")) || 0, { + top: c.top - d.top, + left: c.left - d.left + } + }, offsetParent: function () { + return this.map(function () { + var a = this.offsetParent || e.body; + while (a && !c_.test(a.nodeName) && p.css(a, "position") === "static")a = a.offsetParent; + return a || e.body + }) + } + }), p.each({scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function (a, c) { + var d = /Y/.test(c); + p.fn[a] = function (e) { + return p.access(this, function (a, e, f) { + var g = da(a); + if (f === b)return g ? c in g ? g[c] : g.document.documentElement[e] : a[e]; + g ? g.scrollTo(d ? p(g).scrollLeft() : f, d ? f : p(g).scrollTop()) : a[e] = f + }, a, e, arguments.length, null) + } + }), p.each({Height: "height", Width: "width"}, function (a, c) { + p.each({padding: "inner" + a, content: c, "": "outer" + a}, function (d, e) { + p.fn[e] = function (e, f) { + var g = arguments.length && (d || typeof e != "boolean"), h = d || (e === !0 || f === !0 ? "margin" : "border"); + return p.access(this, function (c, d, e) { + var f; + return p.isWindow(c) ? c.document.documentElement["client" + a] : c.nodeType === 9 ? (f = c.documentElement, Math.max(c.body["scroll" + a], f["scroll" + a], c.body["offset" + a], f["offset" + a], f["client" + a])) : e === b ? p.css(c, d, e, h) : p.style(c, d, e, h) + }, c, g ? e : b, g, null) + } + }) + }), a.jQuery = a.$ = p, typeof define == "function" && define.amd && define.amd.jQuery && define("jquery", [], function () { + return p + }) + })(window); + + // wrap for RAP + if (window.wrapJQueryForRAP) { + window.wrapJQueryForRAP($); + } + $.providedByRAP = true; + return $.noConflict(true); +}); \ No newline at end of file diff --git a/src/main/webapp/stat/js/util/jsformat.js b/src/main/webapp/stat/js/util/jsformat.js new file mode 100644 index 000000000..d34cb0adb --- /dev/null +++ b/src/main/webapp/stat/js/util/jsformat.js @@ -0,0 +1,57 @@ +String.prototype.toHtml = function () { + return this.replace(/\&/g, '&').replace(/\/g, '>').replace(/\x20/g, ' ').replace(/(\r\n|\r|\n)/g, '
    ') +}; +String.prototype.formatJS = function () { + var s = this; + var index = 0, brch = 0; + var keywords = ['abstract', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'const', 'continue', 'default', 'delete', 'do', 'double', 'else', 'extends', 'false', 'final', 'finally', 'float', 'for', 'function', 'goto', 'if', 'implements', 'import', 'in', 'instanceof', 'int', 'interface', 'long', 'native', 'new', 'null', 'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'super', 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'true', 'try', 'typeof', 'var', 'void', 'while', 'with']; + var objects = ['Anchor', 'anchors', 'Applet', 'applets', 'Area', 'Array', 'arguments', 'Button', 'Checkbox', 'Date', 'document', 'FileUpload', 'Form', 'forms', 'Frame', 'frames', 'Function', 'Hidden', 'history', 'Image', 'images', 'Link', 'links', 'Area', 'location', 'Math', 'MimeType', 'mimeTypes', 'navigator', 'options', 'Password', 'Plugin', 'plugins', 'Radio', 'Reset', 'RegExp', 'Select', 'String', 'Submit', 'Text', 'Textarea', 'window']; + var specials = ['prototype', 'callee', 'caller', 'apply', 'call', 'encodeURIComponent', 'decodeURIComponent', 'parseInt', 'parseFloat', '__defineGetter__', '__defineSetter__']; + var blocks = []; + var indent = "", indent_fix = ""; + s = s.replace(/\t/g, ' ').replace(/\r\n|\r/g, "\n").replace(/(\/\/[^\n]*(\n|$)|\/\*(\*(?!\/)|[^\*])*\*+\/|\"(\\\"|\\\\|[^\"\n])*\"|\'(\\\'|\\\\|[^\'\n])*\'|([=!\(\:\{\[\;&|^]\s*)\/(\\.|[^\/\n])+\/[igm]*)/g, function ($0) { + var color = "#CCCCCC", ret = "'"; + var kkk = $0; + if (kkk.charAt(0) == '"')color = "#FF00FF"; else if (kkk.charAt(0) == "'")color = "#9900FF"; else if (kkk.match(/^(?:[=!\(\:\{\[&|^]\s*)(\/(\\.|[^\/\n])+\/[igm]*$)/)) { + ret = kkk.replace(/^([=!\(\:\{\[&|^]\s*)(\/(\\.|[^\/\n])+\/[igm]*$)/, "$1'"); + kkk = kkk.replace(/^([=!\(\:\{\[&|^]\s*)(\/(\\.|[^\/\n])+\/[igm]*$)/, "$2"); + color = "#6666CC" + } + blocks[blocks.length] = "" + kkk.toHtml() + ""; + return ret + }).replace(/(\}?[\n ]*;[\n ]*)/g, function ($0, $1) { + return $1.replace(/[\n ]/g, '') + "\n" + }).replace(/\b(else)\b/g, "$1\n").replace(/\b((case|default)[^:]*\:)/g, "$1\n").replace(/(\{[\n ]*)((([A-Za-z\$\_][0-9A-Za-z\$\_]*|`)[\n ]*\:[\n ]*[^,\}]+,?)+)([\n ]*\})/g, function ($0, $1, $2, $3, $4, $5) { + return $1 + $2.replace(/[\n ]+/g, ' ').replace(/(([A-Za-z\$\_][0-9A-Za-z\$\_]*|`)\:[^,\}]+,?)/g, "$1\n") + $5 + }).replace(/[\n ]*(\{|\};?)[\n ]*/g, function ($0, $1) { + if ($1.charAt(0) == '}')brch--; + var ss = "\n"; + for (var i = 0; i < brch; i++)ss += " "; + if ($1 == '{')brch++; + return ss + $1 + "\n" + }).replace(/[\n ]*\{[\n ]*\}/g, '{}').replace(/^[ ]*([^\{\}])/g, "$1").replace(/(\n\s*for\b[^\n]*\;\s*)\n/g, '$1').replace(/(\n\s*for\b[^\n]*\;\s*)\n/g, '$1').replace(/\n\s*(for|while|if|switch)\b[^\n]*; *\n/g, function ($0, $1) { + var le = 0; + for (var i = 0; i < $0.length; i++)if ($0.charAt(i) == '(')le++; else if ($0.charAt(i) == ')') { + le--; + if (le == 0)return $0.substr(0, i + 1) + "\n" + $0.substr(i + 1, $0.length) + } + }).replace(/(\n *)*(\n *)/g, "$2").replace(/(`\s*)\+(?=\s*`)/g, "$1\n+").replace(/( *)([^\n]*)\n/g, function ($0, space, text) { + var ret = $0; + if (text.match(/^\{/)) { + indent = space + " "; + indent_fix = "" + } else if (text.match(/^\}/)) { + indent = space; + indent_fix = "" + } else { + if (text.match(/^(case|default)\b/))ret = indent.substr(0, indent.length - 4) + text; else ret = indent + indent_fix + text; + if (text.match(/^(if|for|else|var|while)\b/) && !text.match(/\;\s*$/))indent_fix = " "; else if (!text.match(/[^\;]\s*$/))indent_fix = ""; + if (text.charAt(0) == '+')ret = " " + ret; + ret += "\n" + } + return ret + }).replace(/\&/g, '&').replace(/\/g, '>').replace(/\x20/g, ' ').replace(eval('/\\b(' + keywords.join('|') + ')\\b/g'), '$1').replace(eval('/\\b(' + objects.join('|') + ')\\b/g'), '$1').replace(eval('/\\b(' + specials.join('|') + ')\\b/g'), '$1').replace(/\n/g, '
    ').replace(/\'/g, function ($0) { + return blocks[index++] + }); + return s +} diff --git a/src/resource/mockjs.js b/src/main/webapp/stat/js/util/mock-min.js similarity index 81% rename from src/resource/mockjs.js rename to src/main/webapp/stat/js/util/mock-min.js index 220e7adbb..fdf3ac71c 100644 --- a/src/resource/mockjs.js +++ b/src/main/webapp/stat/js/util/mock-min.js @@ -1,8 +1,6 @@ -/*! mockjs 30-12-2013 */ -/*! src/mock-prefix.js */ (function(undefined) { var Mock = { - version: "0.1.1", + version: "0.1.9", _mocked: {} }; /*! src/util.js */ @@ -63,6 +61,20 @@ Util.isNumeric = function(value) { return !isNaN(parseFloat(value)) && isFinite(value); }; + Util.keys = function(obj) { + var keys = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) keys.push(key); + } + return keys; + }; + Util.values = function(obj) { + var values = []; + for (var key in obj) { + if (obj.hasOwnProperty(key)) values.push(obj[key]); + } + return values; + }; Util.heredoc = function heredoc(fn) { return fn.toString().replace(/^[^\/]+\/\*!?/, "").replace(/\*\/[^\/]+$/, "").replace(/^[\s\xA0]+/, "").replace(/[\s\xA0]+$/, ""); }; @@ -160,6 +172,7 @@ start = 0; } step = arguments[2] || 1; + start = +start, stop = +stop, step = +step; var len = Math.max(Math.ceil((stop - start) / step), 0); var idx = 0; var range = new Array(len); @@ -221,7 +234,8 @@ }, a: function(date) { return date.getHours() < 12 ? "am" : "pm"; - } + }, + T: "getTime" } }); Random.extend({ @@ -252,6 +266,42 @@ datetime: function(format) { format = format || "yyyy-MM-dd HH:mm:ss"; return this.format(this.randomDate(), format); + }, + now: function(unit, format) { + if (arguments.length === 1) { + if (!/year|month|week|day|hour|minute|second|week/.test(unit)) { + format = unit; + unit = ""; + } + } + unit = (unit || "").toLowerCase(); + format = format || "yyyy-MM-dd HH:mm:ss"; + var date = new Date(); + switch (unit) { + case "year": + date.setMonth(0); + + case "month": + date.setDate(1); + + case "week": + case "day": + date.setHours(0); + + case "hour": + date.setMinutes(0); + + case "minute": + date.setSeconds(0); + + case "second": + date.setMilliseconds(0); + } + switch (unit) { + case "week": + date.setDate(date.getDate() - date.getDay()); + } + return this.format(date, format); } }); Random.extend({ @@ -434,9 +484,6 @@ } return brands; }, - dataImageHolder: function(size) { - return "holder.js/" + size; - }, dataImage: function(size, text) { var canvas = typeof document !== "undefined" && document.createElement("canvas"), ctx = canvas && canvas.getContext && canvas.getContext("2d"); if (!canvas || !ctx) return ""; @@ -465,18 +512,20 @@ }); Random.extend({ capitalize: function(word) { - return word.charAt(0).toUpperCase() + word.substr(1); + return (word + "").charAt(0).toUpperCase() + (word + "").substr(1); }, upper: function(str) { - return str.toUpperCase(); + return (str + "").toUpperCase(); }, lower: function(str) { - return str.toLowerCase(); + return (str + "").toLowerCase(); }, pick: function(arr) { + arr = arr || []; return arr[this.natural(0, arr.length - 1)]; }, shuffle: function(arr) { + arr = arr || []; var old = arr.slice(0), result = [], index = 0, length = old.length; for (var i = 0; i < length; i++) { index = this.natural(0, old.length - 1); @@ -551,15 +600,26 @@ first: function() { var names = [ "James", "John", "Robert", "Michael", "William", "David", "Richard", "Charles", "Joseph", "Thomas", "Christopher", "Daniel", "Paul", "Mark", "Donald", "George", "Kenneth", "Steven", "Edward", "Brian", "Ronald", "Anthony", "Kevin", "Jason", "Matthew", "Gary", "Timothy", "Jose", "Larry", "Jeffrey", "Frank", "Scott", "Eric" ].concat([ "Mary", "Patricia", "Linda", "Barbara", "Elizabeth", "Jennifer", "Maria", "Susan", "Margaret", "Dorothy", "Lisa", "Nancy", "Karen", "Betty", "Helen", "Sandra", "Donna", "Carol", "Ruth", "Sharon", "Michelle", "Laura", "Sarah", "Kimberly", "Deborah", "Jessica", "Shirley", "Cynthia", "Angela", "Melissa", "Brenda", "Amy", "Anna" ]); return this.pick(names); - return this.capitalize(this.word()); }, last: function() { var names = [ "Smith", "Johnson", "Williams", "Brown", "Jones", "Miller", "Davis", "Garcia", "Rodriguez", "Wilson", "Martinez", "Anderson", "Taylor", "Thomas", "Hernandez", "Moore", "Martin", "Jackson", "Thompson", "White", "Lopez", "Lee", "Gonzalez", "Harris", "Clark", "Lewis", "Robinson", "Walker", "Perez", "Hall", "Young", "Allen" ]; return this.pick(names); - return this.capitalize(this.word()); }, name: function(middle) { return this.first() + " " + (middle ? this.first() + " " : "") + this.last(); + }, + chineseName: function(count) { + var familyNames = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐".split(""); + var names = "贵福生龙元全国胜学祥才发武新利清飞彬富顺信子杰涛昌成康星光天达安岩中茂进林有坚和彪博绍功松善厚庆磊民友裕河哲江超浩亮政谦亨奇固之轮翰朗伯宏言若鸣朋斌梁栋维启克伦翔旭鹏月莺媛艳瑞凡佳嘉琼勤珍贞莉桂娣叶璧璐娅琦晶妍茜秋珊莎锦黛青倩婷姣婉娴瑾颖露瑶怡婵雁蓓".split(""); + if (typeof count !== "number") { + count = Math.random() > .66 ? 2 : 3; + } + var familyName = this.pick(familyNames); + var name = ""; + for (var i = 0; i < count; i++) { + name += this.pick(names); + } + return familyName + name; } }); Random.extend({ @@ -571,7 +631,6 @@ }, email: function(domain) { return this.character("lower") + "." + this.last().toLowerCase() + "@" + this.last().toLowerCase() + "." + this.tld(); - return this.word() + "@" + (domain || this.domain()); }, ip: function() { return this.natural(0, 255) + "." + this.natural(0, 255) + "." + this.natural(0, 255) + "." + this.natural(0, 255); @@ -582,11 +641,11 @@ } }); Random.extend({ - areas: [ "涓滃寳", "鍗庡寳", "鍗庝笢", "鍗庝腑", "鍗庡崡", "瑗垮崡", "瑗垮寳" ], + areas: [ "东北", "华北", "华东", "华中", "华南", "西南", "西北" ], area: function() { return this.pick(this.areas); }, - regions: [ "110000 鍖椾含甯�", "120000 澶╂触甯�", "130000 娌冲寳鐪�", "140000 灞辫タ鐪�", "150000 鍐呰挋鍙よ嚜娌诲尯", "210000 杈藉畞鐪�", "220000 鍚夋灄鐪�", "230000 榛戦緳姹熺渷", "310000 涓婃捣甯�", "320000 姹熻嫃鐪�", "330000 娴欐睙鐪�", "340000 瀹夊窘鐪�", "350000 绂忓缓鐪�", "360000 姹熻タ鐪�", "370000 灞变笢鐪�", "410000 娌冲崡鐪�", "420000 婀栧寳鐪�", "430000 婀栧崡鐪�", "440000 骞夸笢鐪�", "450000 骞胯タ澹棌鑷不鍖�", "460000 娴峰崡鐪�", "500000 閲嶅簡甯�", "510000 鍥涘窛鐪�", "520000 璐靛窞鐪�", "530000 浜戝崡鐪�", "540000 瑗胯棌鑷不鍖�", "610000 闄曡タ鐪�", "620000 鐢樿們鐪�", "630000 闈掓捣鐪�", "640000 瀹佸鍥炴棌鑷不鍖�", "650000 鏂扮枂缁村惥灏旇嚜娌诲尯", "650000 鏂扮枂缁村惥灏旇嚜娌诲尯", "710000 鍙版咕鐪�", "810000 棣欐腐鐗瑰埆琛屾斂鍖�", "820000 婢抽棬鐗瑰埆琛屾斂鍖�" ], + regions: [ "110000 北京市", "120000 天津市", "130000 河北省", "140000 山西省", "150000 内蒙古自治区", "210000 辽宁省", "220000 吉林省", "230000 黑龙江省", "310000 上海市", "320000 江苏省", "330000 浙江省", "340000 安徽省", "350000 福建省", "360000 江西省", "370000 山东省", "410000 河南省", "420000 湖北省", "430000 湖南省", "440000 广东省", "450000 广西壮族自治区", "460000 海南省", "500000 重庆市", "510000 四川省", "520000 贵州省", "530000 云南省", "540000 西藏自治区", "610000 陕西省", "620000 甘肃省", "630000 青海省", "640000 宁夏回族自治区", "650000 新疆维吾尔自治区", "650000 新疆维吾尔自治区", "710000 台湾省", "810000 香港特别行政区", "820000 澳门特别行政区" ], region: function() { return this.pick(this.regions).split(" ")[1]; }, @@ -653,10 +712,12 @@ return Random; }(); /*! src/mock.js */ - var rkey = /(.+)\|(?:\+(\d+)|(\d+-?\d*)?(?:\.(\d+-?\d*))?)/, rrange = /(\d+)-?(\d+)?/, rplaceholder = /\\*@([^@#%&()\?\s\/\.]+)(?:\((.*?)\))?/g; + var rkey = /(.+)\|(?:\+(\d+)|([\+\-]?\d+-?[\+\-]?\d*)?(?:\.(\d+-?\d*))?)/, rrange = /([\+\-]?\d+)-?([\+\-]?\d+)?/, rplaceholder = /\\*@([^@#%&()\?\s\/\.]+)(?:\((.*?)\))?/g; Mock.extend = Util.extend; Mock.mock = function(rurl, rtype, template) { - if (arguments.length === 1) return Handle.gen(rurl); + if (arguments.length === 1) { + return Handle.gen(rurl); + } if (arguments.length === 2) { template = rtype; rtype = undefined; @@ -671,41 +732,71 @@ var Handle = { extend: Util.extend }; - Handle.gen = function(template, name, obj) { - var parameters = (name = name || "").match(rkey), range = parameters && parameters[3] && parameters[3].match(rrange), min = range && parseInt(range[1], 10), max = range && parseInt(range[2], 10), count = range ? !range[2] && parseInt(range[1], 10) || Random.integer(min, max) : 1, decimal = parameters && parameters[4] && parameters[4].match(rrange), dmin = decimal && parseInt(decimal[1], 10), dmax = decimal && parseInt(decimal[2], 10), dcount = decimal ? !decimal[2] && parseInt(decimal[1], 10) || Random.integer(dmin, dmax) : 0, point = parameters && parameters[4], type = Util.type(template), result; + Handle.rule = function(name) { + name = (name || "") + ""; + var parameters = (name || "").match(rkey), range = parameters && parameters[3] && parameters[3].match(rrange), min = range && parseInt(range[1], 10), max = range && parseInt(range[2], 10), count = range ? !range[2] && parseInt(range[1], 10) || Random.integer(min, max) : 1, decimal = parameters && parameters[4] && parameters[4].match(rrange), dmin = decimal && parseInt(decimal[1], 10), dmax = decimal && parseInt(decimal[2], 10), dcount = decimal ? !decimal[2] && parseInt(decimal[1], 10) || Random.integer(dmin, dmax) : 0, point = parameters && parameters[4]; + return { + parameters: parameters, + range: range, + min: min, + max: max, + count: count, + decimal: decimal, + dmin: dmin, + dmax: dmax, + dcount: dcount, + point: point + }; + }; + Handle.gen = function(template, name, context) { + name = name = (name || "") + ""; + context = context || {}; + context = { + path: context.path || [], + templatePath: context.templatePath || [], + currentContext: context.currentContext, + templateCurrentContext: context.templateCurrentContext || template, + root: context.root, + templateRoot: context.templateRoot + }; + var rule = Handle.rule(name); + var type = Util.type(template); if (Handle[type]) { - result = Handle[type]({ + return Handle[type]({ type: type, template: template, name: name, - obj: obj, - parameters: parameters, - range: range, - min: min, - max: max, - count: count, - decimal: decimal, - dmin: dmin, - dmax: dmax, - dcount: dcount, - point: point + parsedName: name ? name.replace(rkey, "$1") : name, + rule: rule, + context: context }); - return result; } return template; }; Handle.extend({ array: function(options) { var result = [], i, j; - if (!options.parameters) { + if (!options.rule.parameters) { for (i = 0; i < options.template.length; i++) { - result.push(Handle.gen(options.template[i])); + options.context.path.push(i); + result.push(Handle.gen(options.template[i], i, { + currentContext: result, + templateCurrentContext: options.template, + path: options.context.path + })); + options.context.path.pop(); } } else { - if (options.count === 1 && options.template.length > 1) { - result = Random.pick(Handle.gen(options.template)); + if (options.rule.count === 1 && options.template.length > 1) { + options.context.path.push(options.name); + result = Random.pick(Handle.gen(options.template, undefined, { + currentContext: result, + templateCurrentContext: options.template, + path: options.context.path + })); + options.context.path.pop(); } else { - for (i = 0; i < options.count; i++) { + for (i = 0; i < options.rule.count; i++) { j = 0; do { result.push(Handle.gen(options.template[j++])); @@ -716,41 +807,72 @@ return result; }, object: function(options) { - var result = {}, key, inc; - for (key in options.template) { - result[key.replace(rkey, "$1")] = Handle.gen(options.template[key], key, result); - inc = key.match(rkey); - if (inc && inc[2] && Util.type(options.template[key]) === "number") { - options.template[key] += parseInt(inc[2], 10); + var result = {}, keys, fnKeys, key, parsedKey, inc, i; + if (options.rule.min) { + keys = Util.keys(options.template); + keys = Random.shuffle(keys); + keys = keys.slice(0, options.rule.count); + for (i = 0; i < keys.length; i++) { + key = keys[i]; + parsedKey = key.replace(rkey, "$1"); + options.context.path.push(parsedKey); + result[parsedKey] = Handle.gen(options.template[key], key, { + currentContext: result, + templateCurrentContext: options.template, + path: options.context.path + }); + options.context.path.pop(); + } + } else { + keys = []; + fnKeys = []; + for (key in options.template) { + (typeof options.template[key] === "function" ? fnKeys : keys).push(key); + } + keys = keys.concat(fnKeys); + for (i = 0; i < keys.length; i++) { + key = keys[i]; + parsedKey = key.replace(rkey, "$1"); + options.context.path.push(parsedKey); + result[parsedKey] = Handle.gen(options.template[key], key, { + currentContext: result, + templateCurrentContext: options.template, + path: options.context.path + }); + options.context.path.pop(); + inc = key.match(rkey); + if (inc && inc[2] && Util.type(options.template[key]) === "number") { + options.template[key] += parseInt(inc[2], 10); + } } } return result; }, number: function(options) { var result, parts, i; - if (options.point) { + if (options.rule.point) { options.template += ""; parts = options.template.split("."); - parts[0] = options.range ? options.count : parts[0]; - parts[1] = (parts[1] || "").slice(0, options.dcount); - for (i = 0; parts[1].length < options.dcount; i++) { + parts[0] = options.rule.range ? options.rule.count : parts[0]; + parts[1] = (parts[1] || "").slice(0, options.rule.dcount); + for (i = 0; parts[1].length < options.rule.dcount; i++) { parts[1] += Random.character("number"); } result = parseFloat(parts.join("."), 10); } else { - result = options.range && !options.parameters[2] ? options.count : options.template; + result = options.rule.range && !options.rule.parameters[2] ? options.rule.count : options.template; } return result; }, "boolean": function(options) { var result; - result = options.parameters ? Random.bool(options.min, options.max, options.template) : options.template; + result = options.rule.parameters ? Random.bool(options.rule.min, options.rule.max, options.template) : options.template; return result; }, string: function(options) { var result = "", i, placeholders, ph, phed; if (options.template.length) { - for (i = 0; i < options.count; i++) { + for (i = 0; i < options.rule.count; i++) { result += options.template; } placeholders = result.match(rplaceholder) || []; @@ -760,23 +882,20 @@ placeholders.splice(i--, 1); continue; } - phed = Handle.placeholder(ph, options.obj); - if (placeholders.length === 1 && ph === result) { - if (Util.isNumeric(phed)) { - result = parseFloat(phed, 10); - break; - } - if (/^(true|false)$/.test(phed)) { - result = phed === "true" ? true : phed === "false" ? false : phed; - break; - } + phed = Handle.placeholder(ph, options.context.currentContext, options.context.templateCurrentContext); + if (placeholders.length === 1 && ph === result && typeof phed !== typeof result) { + result = phed; + break; } result = result.replace(ph, phed); } } else { - result = options.range ? Random.string(options.count) : options.template; + result = options.rule.range ? Random.string(options.rule.count) : options.template; } return result; + }, + "function": function(options) { + return options.template.call(options.context.currentContext); } }); Handle.extend({ @@ -785,10 +904,22 @@ for (var key in Random) re[key.toLowerCase()] = key; return re; }, - placeholder: function(placeholder, obj) { + placeholder: function(placeholder, obj, templateContext) { rplaceholder.exec(""); - var parts = rplaceholder.exec(placeholder), key = parts && parts[1], lkey = key && key.toLowerCase(), okey = this._all()[lkey], params = parts && parts[2] ? parts[2].split(/,\s*/) : []; + var parts = rplaceholder.exec(placeholder), key = parts && parts[1], lkey = key && key.toLowerCase(), okey = this._all()[lkey], params = parts && parts[2] || ""; + try { + params = eval("(function(){ return [].splice.call(arguments, 0 ) })(" + params + ")"); + } catch (error) { + params = parts[2].split(/,\s*/); + } if (obj && key in obj) return obj[key]; + if (templateContext && typeof templateContext === "object" && key in templateContext && placeholder !== templateContext[key]) { + templateContext[key] = Handle.gen(templateContext[key], key, { + currentContext: obj, + templateCurrentContext: templateContext + }); + return templateContext[key]; + } if (!(key in Random) && !(lkey in Random) && !(okey in Random)) return placeholder; for (var i = 0; i < params.length; i++) { rplaceholder.exec(""); @@ -798,53 +929,92 @@ } var handle = Random[key] || Random[lkey] || Random[okey]; switch (Util.type(handle)) { - case "array": - return Random.pick(handle); + case "array": + return Random.pick(handle); - case "function": - var re = handle.apply(Random, params); - if (re === undefined) re = ""; - return re; + case "function": + var re = handle.apply(Random, params); + if (re === undefined) re = ""; + return re; } } }); /*! src/mockjax.js */ + function find(options) { + for (var sUrlType in Mock._mocked) { + var item = Mock._mocked[sUrlType]; + if ((!item.rurl || match(item.rurl, options.url)) && (!item.rtype || match(item.rtype, options.type.toLowerCase()))) { + return item; + } + } + function match(expected, actual) { + if (Util.type(expected) === "string") { + return expected === actual; + } + if (Util.type(expected) === "regexp") { + return expected.test(actual); + } + } + } + function convert(item, options) { + return Util.isFunction(item.template) ? item.template(options) : Mock.mock(item.template); + } Mock.mockjax = function mockjax(jQuery) { function mockxhr() { return { + readyState: 4, + status: 200, + statusText: "", open: jQuery.noop, - send: jQuery.noop, + send: function() { + if (this.onload) this.onload(); + }, + setRequestHeader: jQuery.noop, getAllResponseHeaders: jQuery.noop, - readyState: 4, - status: 200 - }; - } - function convert(mock) { - return function() { - return Mock.mock(jQuery.isFunction(mock.template) ? mock.template() : mock.template); + getResponseHeader: jQuery.noop, + statusCode: jQuery.noop, + abort: jQuery.noop }; } - function prefilter(options) { - for (var surl in Mock._mocked) { - var mock = Mock._mocked[surl]; - if (jQuery.type(mock.rurl) === "string") { - if (mock.rurl !== options.url) continue; - } - if (jQuery.type(mock.rurl) === "regexp") { - if (!mock.rurl.test(options.url)) continue; - } - options.dataFilter = convert(mock); - options.converters["text json"] = convert(mock); + function prefilter(options, originalOptions, jqXHR) { + var item = find(options); + if (item) { + options.dataFilter = options.converters["text json"] = options.converters["text jsonp"] = options.converters["text script"] = options.converters["script json"] = function() { + return convert(item, options); + }; options.xhr = mockxhr; - break; + if (originalOptions.dataType !== "script") return "json"; } } - jQuery.ajaxPrefilter("*", prefilter); - jQuery.ajaxPrefilter("json", prefilter); - jQuery.ajaxPrefilter("jsonp", prefilter); + jQuery.ajaxPrefilter("json jsonp script", prefilter); return Mock; }; if (typeof jQuery != "undefined") Mock.mockjax(jQuery); + if (typeof Zepto != "undefined") { + Mock.mockjax = function(Zepto) { + var __original_ajax = Zepto.ajax; + var xhr = { + readyState: 4, + responseText: "", + responseXML: null, + state: 2, + status: 200, + statusText: "success", + timeoutTimer: null + }; + Zepto.ajax = function(options) { + var item = find(options); + if (item) { + var data = Mock.mock(item.template); + if (options.success) options.success(data, xhr, options); + if (options.complete) options.complete(xhr.status, xhr, options); + return xhr; + } + return __original_ajax.call(Zepto, options); + }; + }; + Mock.mockjax(Zepto); + } if (typeof KISSY != "undefined" && KISSY.add) { Mock.mockjax = function mockjax(KISSY) { var _original_ajax = KISSY.io; @@ -858,23 +1028,18 @@ timeoutTimer: null }; KISSY.io = function(options) { - for (var surl in Mock._mocked) { - var mock = Mock._mocked[surl]; - if (KISSY.type(mock.rurl) === "string") { - if (mock.rurl !== options.url) continue; - } - if (KISSY.type(mock.rurl) === "regexp") { - if (!mock.rurl.test(options.url)) continue; - } - console.log("[mock]", options.url, ">", mock.rurl); - var data = Mock.mock(mock.template); - console.log("[mock]", data); - if (options.success) options.success(data, "success", xhr); - if (options.complete) options.complete(data, "success", xhr); - return KISSY; + var item = find(options); + if (item) { + var data = Mock.mock(item.template); + if (options.success) options.success(data, xhr, options); + if (options.complete) options.complete(xhr.status, xhr, options); + return xhr; } return _original_ajax.apply(this, arguments); }; + for (var name in _original_ajax) { + KISSY.io[name] = _original_ajax[name]; + } }; } /*! src/expose.js */ @@ -884,7 +1049,10 @@ if (typeof module === "object" && module.exports) { module.exports = Mock; } else if (typeof define === "function" && define.amd) { - define(function() { + define("mock", [], function() { + return Mock; + }); + define("mockjs", [], function() { return Mock; }); } else if (typeof define === "function" && define.cmd) { @@ -895,7 +1063,7 @@ this.Mock = Mock; this.Random = Random; if (typeof KISSY != "undefined") { - Util.each([ "mock", "components/mock/index", "mock/dist/mock", "gallery/Mock/0.1.1/index", "gallery/Mock/0.1.2/index" ], function register(name) { + Util.each([ "mock", "components/mock/", "mock/dist/mock", "gallery/Mock/0.1.9/" ], function register(name) { KISSY.add(name, function(S) { Mock.mockjax(S); return Mock; diff --git a/src/main/webapp/stat/js/util/mock.plugin.js b/src/main/webapp/stat/js/util/mock.plugin.js new file mode 100644 index 000000000..0875dd65e --- /dev/null +++ b/src/main/webapp/stat/js/util/mock.plugin.js @@ -0,0 +1,551 @@ + +(function (window, undefined) { + var node = null; + var blackList = []; + var whiteList = [#foreach($url in $urlList)#if ($velocityCount > 1),#end"$url"#end]; + + var ROOT = "$!consts.DOMAIN_URL"; + var LOST = "LOST"; + var PREFIX = "/mockjs/"; + var EMPTY_ARRAY = "EMPTY_ARRAY"; + var TYPE_NOT_EQUAL = "TYPE_NOT_EQUAL"; + + /** + * mode value range: 0-disabled 1-intercept all requests 2-black list + * strategy 3-white list strategy + */ + var mode = 3; + var modeStr = "$!utils.escapeInJ($mode)"; + if (modeStr != "" && (+modeStr >= 0 && +modeStr <= 3)) { + mode = +modeStr; + } + var modeList = [0, 1, 2, 3]; + var projectId = $!projectId; + var seajsEnabled = $!seajs; + var enable = $!enable; + var disableLog = $!disableLog; + + console.log('Current RAP work mode:', mode, "(0-disabled, 1-intercept all requests, 2-black list, 3-white list)"); + + function wrapJQuery(jQuery, pId, rootStr) { + if (pId) { + projectId = pId; + } + if (rootStr) { + ROOT = rootStr; + } + if (jQuery._rap_wrapped) { + return; + } + jQuery._rap_wrapped = true; + + var ajax = jQuery.ajax; + jQuery.ajax = function () { + var oOptions = arguments[0]; + + // process ajax(url, options) condition + if (typeof arguments[0] === 'string' && + typeof arguments[1] === 'object' && + arguments[1].url === undefined) { + + oOptions = arguments[1]; + oOptions.url = arguments[0]; + arguments[0] = oOptions; + + } else if (typeof arguments[0] === 'string' && + typeof arguments[1] === undefined) { + // process ajax(url) + oOptions = arguments[0] = { + url: arguments[0] + }; + } + + function doit(data) { + data = Mock.mock(data); + if (data.__root__ != undefined) { + data = data.__root__; + } + if (!disableLog) { + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + } + return data + } + + var url = oOptions.url; + var routePassed = route(url) && projectId; + if (routePassed) { + rapUrlConverterJQuery(oOptions); + var oldSuccess1 = oOptions.success; + oldSuccess1 && (oOptions.success = function (data) { + if (PREFIX == '/mockjs/') { + data = doit(data) + } + oldSuccess1.apply(this, arguments); + }); + } else if (isInWhiteList(url) && !oOptions.RAP_NOT_TRACK) { + var checkerOptions = {url: oOptions.url}; + rapUrlConverterJQuery(checkerOptions); + checkerOptions.RAP_NOT_TRACK = true; + checkerOptions.success = checkerHandler; + // real data checking + var oldSuccess2 = oOptions.success; + oOptions.success = function () { + var realData = arguments[0]; + checkerOptions.context = { + data: realData, + url: oOptions.url + }; + // perform real data check + ajax.apply(jQuery, [checkerOptions]); + oldSuccess2.apply(this, arguments); + }; + } + var rv = ajax.apply(this, arguments); + if (routePassed) { + var oldDone = rv.done; + oldDone && (rv.done = function () { + var oldCb = arguments[0]; + var args = arguments; + if (oldCb) { + args[0] = function (data) { + if (PREFIX == '/mockjs/') { + data = doit(data) + } + oldCb.apply(this, arguments); + }; + } + oldDone.apply(this, args); + return rv; + }); + var oldThen = rv.then; + oldThen && (rv.then = function () { + var oldCb = arguments[0]; + var args = arguments; + if (oldCb) { + args[0] = function (data) { + if (PREFIX == '/mockjs/') { + data = doit(data) + } + oldCb.apply(this, arguments); + }; + } + oldThen.apply(this, args); + return rv; + }); + } + return rv; + }; + } + + window.wrapJQueryForRAP = wrapJQuery; + + if (enable) { + /** + * jQuery override + */ + if (window.jQuery) { + wrapJQuery(window.jQuery); + } + + /** + * kissy override + */ + if (window.KISSY) { + KISSY.oldUse = KISSY.use; + KISSY.oldAdd = KISSY.add; + + KISSY.add('rap_io', function (S, IO) { + var oldIO = IO; + var key; + var fn = KISSY.io = KISSY.IO = KISSY.ajax = function (options) { + var oOptions, url; + if (arguments[0]) { + oOptions = arguments[0]; + url = oOptions.url; + if (route(url) && !oOptions.RAP_NOT_TRACK) { + rapUrlConverterKissy(oOptions); + var oldSuccess1 = oOptions.success; + oldSuccess1 && (oOptions.success = function (data) { + if (PREFIX == '/mockjs/') { + data = Mock.mock(data); + if (data.__root__ != undefined) { + data = data.__root__; + } + if (!disableLog) { + console.log('请求' + url + '返回的Mock数据:'); + console.dir(data); + } + } + oldSuccess1.apply(this, arguments); + }); + } else if (isInWhiteList(url) && !oOptions.RAP_NOT_TRACK) { + var checkerOptions = {url: oOptions.url}; + rapUrlConverterKissy(checkerOptions); + checkerOptions.RAP_NOT_TRACK = true; + checkerOptions.success = checkerHandler; + // real data checking + var oldSuccess2 = oOptions.success; + oOptions.success = function () { + var realData = arguments[0]; + checkerOptions.context = { + data: realData, + url: oOptions.url + }; + // perform real data check + IO(checkerOptions); + oldSuccess2.apply(this, arguments); + }; + } + } + IO.apply(this, arguments); + }; + + for (key in oldIO) { + if (oldIO.hasOwnProperty(key)) { + fn[key] = oldIO[key]; + } + } + + return fn; + }, { + requires: ['ajax'] + }); + + + KISSY.use = function (modules, callback) { + var args = arguments; + if (modules instanceof Array || typeof modules === 'string') { + args[0] = replace(modules); + } + KISSY.oldUse.apply(this, args); + }; + + KISSY.add = function (name, fn, options) { + if (options && options.requires) { + + for (var i = 0, l = options.requires.length; i < l; i++) { + var current = options.requires[i].toLowerCase(); + + if (current == 'io' || current == 'ajax') { + options.requires[i] = 'rap_io'; + } + } + } + + KISSY.oldAdd.apply(this, arguments); + }; + + if (KISSY.IO || KISSY.io || KISSY.ajax) { + KISSY.use('rap_io', function () {}); + } + } + } + + if (window.seajs && window.seajs.use && window.define && window.define.cmd && seajsEnabled != 'false') { + + !function () { + var oldSeajsUse = seajs.use; + var initialized = false; + seajs.use = function () { + var handler = arguments[arguments.length - 1]; + arguments[arguments.length - 1] = function () { + if (!initialized) { + for (var i = 0; i < arguments.length; i++) { + if (arguments[i] && typeof arguments[i] === 'function' && arguments[i].prototype && + arguments[i].prototype.jquery + ) { + wrapJQueryForRAP(arguments[i]); + } + } + + initialized = true; + } + handler.apply(this, arguments); + }; + oldSeajsUse.apply(seajs, arguments); + } + }(); + + + var data = seajs.config().data; + data.alias = data.alias || {}; + var path = 'http://' + ROOT + '/stat/js/util/jquery-rapped.js'; + data.alias.jquery = data.alias.jQuery = data.alias.jq = data.alias.jQ = data.alias.$ = path; + } + + function replace(modules) { + var splited = modules; + if (KISSY.isString(modules)) { + splited = modules.split(','); + } + var index = -1; + for (var i = 0, l = splited.length; i < l; i++) { + var name = KISSY.trim(splited[i]).toLowerCase(); + if (name === 'ajax' || name === 'io') { + splited[i] = 'rap_io'; + } + } + return splited.join(','); + } + + + function checkerHandler(mockData) { + if (PREFIX == '/mockjs/') { + mockData = Mock.mock(mockData); + if (mockData.__root__ != undefined) { + mockData = mockData.__root__; + } + } + var realData = this.data; + var validator = new StructureValidator(realData, mockData); + var result = validator.getResult(); + var realDataResult = result.left; + var rapDataResult = result.right; + var i; + var log = []; + var error = false; + + if (realDataResult.length === 0 && rapDataResult.length === 0) { + log.push('接口结构校验完毕,未发现问题。'); + } else { + error = true; + if (this.url) { + log.push('在校验接口' + this.url + '时发现错误:'); + } + for (i = 0; i < realDataResult.length; i++) { + log.push(validatorResultLog(realDataResult[i])); + } + for (i = 0; i < rapDataResult.length; i++) { + log.push(validatorResultLog(rapDataResult[i], true)); + } + } + + console.info(log.join('\n')); + if (error === true) { + console.log('真实数据:'); + console.dir(this.data); + } + } + + /** + * is in white list + * + */ + function isInWhiteList(url) { + var i; + var o; + for (i = 0; i < whiteList.length; i++) { + o = whiteList[i]; + if (typeof o === 'string' && (url.indexOf(o) >= 0 || o.indexOf(url) >= 0)) { + return true; + } else if (typeof o === 'object' && o instanceof RegExp && o.test(url)) { + return true; + } + } + return false; + } + + + /** + * router + * + * @param {string} url + * @return {boolean} true if route to RAP MOCK, other wise do nothing. + */ + function route(url, ignoreMode) { + if (url && url.indexOf('?') !== -1) { + url = url.substring(0, url.indexOf('?')) + } + var i; + var o; + var blackMode; + var list; + + url = convertUrlToRelative(url); + + if (!url || typeof url !== 'string') { + console.warn("Illegal url:", url); + return false; + } + + /** + * disabled + */ + if (mode === 0) { + return false; + } + /** + * intercept all requests + */ + else if (mode == 1) { + return true; + } + /** + * black/white list mode + */ + else if (mode === 2 || mode === 3) { + blackMode = mode === 2; + list = blackMode ? blackList : whiteList; + for (i = 0; i < list.length; i++) { + o = convertUrlToRelative(list[i]); + if (typeof o === 'string' && (url.indexOf(o) >= 0 || o.indexOf(url) >= 0)) { + return !blackMode; + } else if (typeof o === 'object' && o instanceof RegExp && o.test(url)) { + return !blackMode; + } + } + return blackMode; + } + + return false; + } + + function validatorResultLog(item, isReverse) { + + var eventName; + if (item.type === LOST) { + eventName = isReverse ? '未在接口文档中未定义。' : '缺失'; + } else if (item.type === EMPTY_ARRAY) { + eventName = '数组为空,无法判断其内部的结构。'; + return; // 暂时忽略此种情况 + } else if (item.type === TYPE_NOT_EQUAL) { + eventName = '数据类型与接口文档中的定义不符'; + } + + return '参数 ' + item.namespace + "." + item.property + ' ' + eventName; + + } + + /** + * convert url from absolute to relative + */ + function convertUrlToRelative(url) { + if (url instanceof RegExp) { + return url; + } + if (!url) { + throw Error('Illegal url:' + url); + } + if (url.indexOf('http://') > -1) { + url = url.substring(url.indexOf('/', 7) + 1); + } else if (url.indexOf('https://') > -1) { + url = url.substring(url.indexOf('/', 8) + 1); + } + if (url.charAt(0) != '/') { + url = '/' + url; + } + return url; + } + + /** + * convert url to rap mock url (KISSY version) + * example: www.baidu.com/a => {domain}/mock/106/a + */ + function rapUrlConverterKissy(options) { + var url = options.url; + if (!options || typeof options !== 'object') { + throw Error('illegal option object:' + options); + } + options.type = "get"; + options.jsonp = '_c'; + options.dataType = 'jsonp'; + url = convertUrlToRelative(url); + url = "http://" + ROOT + PREFIX + projectId + url; + options.url = url; + return options; + } + + /** + * convert url to rap mock url (jQuery version) + * example: www.baidu.com/a => {domain}/mock/106/a + */ + function rapUrlConverterJQuery(options) { + var url = options.url; + if (!options || typeof options !== 'object') { + throw Error('illegal option object:' + options); + } + options.jsonp = '_c'; + options.dataType = 'jsonp'; + url = convertUrlToRelative(url); + url = "http://" + ROOT + PREFIX + projectId + url; + options.url = url; + return options; + } + + window.RAP = { + initList: function (list) { + var PARAM_REG = /\/:[^\/]*/g; + var i, n = list.length, item; + for (i = 0; i < n; i++) { + item = list[i]; + if (typeof item === 'string') { + if (PARAM_REG.test(item)) { + item = new RegExp(item.replace(PARAM_REG, '/\\d+')); + list[i] = item; + } else if (item.indexOf('reg:') !== -1) { + item = item.replace('reg:', ''); + item = new RegExp(item); + list[i] = item; + } + } + } + return list; + }, + setBlackList: function (arr) { + if (arr && arr instanceof Array) { + blackList = this.initList(arr); + } + }, + setWhiteList: function (arr) { + if (arr && arr instanceof Array) { + whiteList = this.initList(arr); + } + }, + getBlackList: function () { + return blackList; + }, + getWhiteList: function () { + return whiteList; + }, + getMode: function () { + return mode; + }, + setMode: function (m) { + m = +m; + if (m in modeList) { + mode = m; + console.log('RAP work mode switched to ', m); + } else { + console.warn('Illegal mode id. Please check.'); + } + }, + setHost: function (h) { + ROOT = h; + }, + getHost: function () { + return ROOT; + }, + setPrefix: function (p) { + PREFIX = p; + }, + getPrefix: function (p) { + return PREFIX; + }, + setProjectId: function (id) { + projectId = id; + }, + getProjectId: function () { + return projectId; + }, + router: function (url) { + return route(url); + }, + checkerHandler: function () { + return checkerHandler.apply(this, arguments); + } + }; + + RAP.initList(whiteList); + RAP.wrapJQuery = window.wrapJQueryForRAP; +})(this); \ No newline at end of file diff --git a/WebContent/stat/js/util/mock.plugin.js b/src/main/webapp/stat/js/util/mock.plugin.js.backup similarity index 72% rename from WebContent/stat/js/util/mock.plugin.js rename to src/main/webapp/stat/js/util/mock.plugin.js.backup index 55c9dc4f7..633360c1b 100644 --- a/WebContent/stat/js/util/mock.plugin.js +++ b/src/main/webapp/stat/js/util/mock.plugin.js.backup @@ -1,9 +1,17 @@ -/*! rap.plugin Mar.10th 2014 */ -(function() { +/** + * RAP plugin for browsers + * Functions: 1). IO mock data, 2). IO format check, 3). route manage + * Supports: 1). jQuery, 2). KISSY + * + * @createDate Mar. 10th 2014 + * @updateDate Apr. 14th 2015 + */ +(function(window, undefined) { var node = null; var blackList = []; var whiteList = [#foreach($url in $urlList)#if($velocityCount>1),#end"$url"#end]; - var ROOT = 'rap.alibaba-inc.com'; + + var ROOT = "$!consts.DOMAIN_URL"; var LOST = "LOST"; var PREFIX = "/mockjs/"; var EMPTY_ARRAY = "EMPTY_ARRAY"; @@ -14,60 +22,43 @@ * strategy 3-white list strategy */ var mode = 3; - var modeList = [0, 1, 2, 3]; - var projectId = 0; - - // console handler - if (typeof window.console === 'undefined') { - window.console = { - log : function(){}, - warn : function(){}, - info : function(){} - }; + var modeStr = "$!utils.escapeInJ($mode)"; + if (modeStr != "" && (+modeStr >= 0 && +modeStr <= 3)) { + mode = +modeStr; } + var modeList = [0, 1, 2, 3]; + var projectId = $!projectId; + var seajsEnabled = $!seajs; + var enable = $!enable; + var disableLog = $!disableLog; - if (!node) { - var nodes = document.getElementsByTagName('script'); - node = nodes[nodes.length - 1]; - } - var ms = node.src.match(/(?:\?|&)projectId=([^&]+)(?:&|$)/); - if (ms) { - projectId = ms[1]; - } - var modePattern = node.src.match(/(?:\?|&)mode=([^&]+)(?:&|$)/); - if (modePattern) { - mode = +modePattern[1]; - if (!(mode in modeList)) { - mode = 1; - } - } + console.log('Current RAP work mode:', mode, "(0-disabled, 1-intercept all requests, 2-black list, 3-white list)"); - var rootPattern = node.src.match(/(?:\?|&)root=([^&]+)(?:&|$)/); - if (rootPattern) { - ROOT = rootPattern[1]; - } + function wrapJQuery(jQuery, pId, rootStr) { + if (pId) { + projectId = pId; + } + if (rootStr) { + ROOT = rootStr; + } + if (jQuery._rap_wrapped) { + return; + } + jQuery._rap_wrapped = true; - var enable = true; - console.log('Current RAP work mode:', mode, "(0-disabled, 1-intercept all requests, 2-black list, 3-white list)"); - var ens = node.src.match(/(?:\?|&)enable=([^&]+)(?:&|$)/); - if (ens) { - enable = ens[1] == 'true'; - } - if (enable) { - /** - * jQuery override - */ - if (window.jQuery) { - var ajax = jQuery.ajax; - jQuery.ajax = function() { - var oOptions = arguments[0]; + if (jQuery.ajaxPrefilter) { + jQuery.ajaxPrefilter(function(oOptions, originalOptions, jqXHR) { var url = oOptions.url; - if (route(url) && projectId) { + var routePassed = route(url) && projectId; + if (routePassed) { rapUrlConverterJQuery(oOptions); var oldSuccess1 = oOptions.success; oldSuccess1 && (oOptions.success = function(data) { if (PREFIX == '/mockjs/') { data = Mock.mock(data); + disableLog || console.log('请求' + url + '返回的Mock数据:'); + disableLog || console.dir(data); + } oldSuccess1.apply(this, arguments); }); @@ -76,6 +67,9 @@ oldComplete && (oOptions.complete = function(data) { if (PREFIX == '/mockjs/') { data = Mock.mock(data); + disableLog || console.log('请求' + url + '返回的Mock数据:'); + disableLog || console.dir(data); + } oldComplete.apply(this, arguments); }); @@ -93,12 +87,24 @@ url : oOptions.url }; // perform real data check - ajax.apply(jQuery, [checkerOptions]); + jQuery.ajax(checkerOptions); oldSuccess2.apply(this,arguments); }; } - ajax.apply(this, arguments); - }; + }); + } else { + throw new Error('Can not find jQuery.ajaxPrefilter method!'); + } + } + + window.wrapJQueryForRAP = wrapJQuery; + + if (enable) { + /** + * jQuery override + */ + if (window.jQuery) { + wrapJQuery(window.jQuery); } @@ -123,6 +129,8 @@ oldSuccess1 && (oOptions.success = function(data) { if (PREFIX == '/mockjs/') { data = Mock.mock(data); + disableLog || console.log('请求' + url + '返回的Mock数据:'); + disableLog || console.dir(data); } oldSuccess1.apply(this, arguments); }); @@ -130,6 +138,9 @@ oldComplete && (oOptions.complete = function(data) { if (PREFIX == '/mockjs/') { data = Mock.mock(data); + disableLog || console.log('请求' + url + '返回的Mock数据:'); + disableLog || console.dir(data); + } oldComplete.apply(this, arguments); }); @@ -196,7 +207,39 @@ } } + } + + if (window.seajs && window.seajs.use && window.define && window.define.cmd && seajsEnabled != 'false') { + + !function() { + var oldSeajsUse = seajs.use; + var initialized = false; + seajs.use = function() { + var handler = arguments[arguments.length - 1]; + arguments[arguments.length - 1] = function() { + if (!initialized) { + for (var i = 0; i < arguments.length; i++) { + if (arguments[i] && typeof arguments[i] === 'function' && arguments[i].prototype && + arguments[i].prototype.jquery + ) { + wrapJQueryForRAP(arguments[i]); + } + } + + initialized = true; + } + handler.apply(this, arguments); + }; + oldSeajsUse.apply(seajs, arguments); + } + }(); + + + var data = seajs.config().data; + data.alias = data.alias || {}; + var path = 'http://' + ROOT + '/stat/js/util/jquery-rapped.js'; + data.alias.jquery = data.alias.jQuery = data.alias.jq = data.alias.jQ = data.alias.$ = path; } function replace(modules) { @@ -245,8 +288,8 @@ console.info(log.join('\n')); if (error === true) { - console.log('真实数据:'); - console.dir(this.data); + disableLog || console.log('真实数据:'); + disableLog || console.dir(this.data); } } @@ -254,7 +297,7 @@ * is in white list * */ - function isInWhiteList(url) { + function isInWhiteList(url) { var i; var o; for (i = 0; i < whiteList.length; i++) { @@ -266,7 +309,7 @@ } } return false; - } + } /** @@ -276,6 +319,9 @@ * @return {boolean} true if route to RAP MOCK, other wise do nothing. */ function route(url, ignoreMode) { + if (url && url.indexOf('?') !== -1) { + url = url.substring(0, url.indexOf('?')) + } var i; var o; var blackMode; @@ -340,6 +386,9 @@ * convert url from absolute to relative */ function convertUrlToRelative(url) { + if (url instanceof RegExp) { + return url; + } if (!url) { throw Error('Illegal url:' + url); } @@ -356,7 +405,7 @@ /** * convert url to rap mock url (KISSY version) - * example: www.baidu.com/a => alibaba-inc.com/mock/106/a + * example: www.baidu.com/a => {domain}/mock/106/a */ function rapUrlConverterKissy(options) { var url = options.url; @@ -374,7 +423,7 @@ /** * convert url to rap mock url (jQuery version) - * example: www.baidu.com/a => alibaba-inc.com/mock/106/a + * example: www.baidu.com/a => {domain}/mock/106/a */ function rapUrlConverterJQuery(options) { var url = options.url; @@ -390,14 +439,32 @@ } window.RAP = { + initList : function(list) { + var PARAM_REG = /\/:[^\/]*/g; + var i, n = list.length, item; + for (i = 0; i < n; i++) { + item = list[i]; + if (typeof item === 'string') { + if (PARAM_REG.test(item)) { + item = new RegExp(item.replace(PARAM_REG, '/\\d+')); + list[i] = item; + } else if (item.indexOf('reg:') !== -1) { + item = item.replace('reg:', ''); + item = new RegExp(item); + list[i] = item; + } + } + } + return list; + }, setBlackList : function(arr) { if (arr && arr instanceof Array) { - blackList = arr; + blackList = this.initList(arr); } }, setWhiteList : function(arr) { if (arr && arr instanceof Array) { - whiteList = arr; + whiteList = this.initList(arr); } }, getBlackList : function() { @@ -429,6 +496,21 @@ }, getPrefix: function(p) { return PREFIX; + }, + setProjectId: function(id) { + projectId = id; + }, + getProjectId: function() { + return projectId; + }, + router: function(url) { + return route(url); + }, + checkerHandler: function() { + return checkerHandler.apply(this, arguments); } }; -})(); + + RAP.initList(whiteList); + RAP.wrapJQuery = window.wrapJQueryForRAP; +})(this); \ No newline at end of file diff --git a/src/main/webapp/stat/js/util/structureValidator.js b/src/main/webapp/stat/js/util/structureValidator.js new file mode 100644 index 000000000..aee698943 --- /dev/null +++ b/src/main/webapp/stat/js/util/structureValidator.js @@ -0,0 +1,194 @@ +!function () { + var global = this; + var LOST = "LOST"; + var EMPTY_ARRAY = "EMPTY_ARRAY"; + var TYPE_NOT_EQUAL = "TYPE_NOT_EQUAL"; + + function StructureValidator(o1, o2, leftName, rightName) { + if (typeof o1 === 'string') { + try { + o1 = JSON.parse(o1); + } catch (ex) { + } + } + if (typeof o2 === 'string') { + try { + o2 = JSON.parse(o2); + } catch (ex) { + } + } + + if (!leftName) { + leftName = 'obj'; + } + if (!rightName) { + rightName = 'obj'; + } + if (this === global) { + throw Error('Please use "new StructureValidator(o1, o2);"'); + } + this.o1 = o1; + this.o2 = o2; + this._check(o2, o1, 'left', leftName, true); + this._check(o1, o2, 'right', rightName); + } + + StructureValidator.prototype.getResult = function () { + return { + left: this.left, + right: this.right + }; + }; + + StructureValidator.prototype.getResultStr = function () { + var result = this.getResult(); + var left = result.left; + var right = result.right; + var i; + var log = []; + + if (left.length === 0 && right.length === 0) { + log.push('接口结构校验完毕,未发现问题。'); + } else { + if (this.url) { + log.push('在校验接口' + this.url + '时发现错误:'); + } + for (i = 0; i < left.length; i++) { + log.push(validatorResultLog(left[i])); + } + for (i = 0; i < right.length; i++) { + log.push(validatorResultLog(right[i], true)); + } + } + + return log.join("\n"); + + function validatorResultLog(item, isReverse) { + var eventName; + if (item.type === LOST) { + eventName = isReverse ? '未在接口文档中未定义。' : '缺失'; + } else if (item.type === EMPTY_ARRAY) { + eventName = '数组为空,无法判断其内部的结构。'; + return; // 暂时忽略此种情况 + } else if (item.type === TYPE_NOT_EQUAL) { + eventName = '数据类型与接口文档中的定义不符'; + } + return '参数 ' + item.namespace + "." + item.property + ' ' + eventName; + } + } + + StructureValidator.prototype._check = function (o1, o2, key, keyName, isReverseCheck) { + var result = []; + + function typeEqual(a, b) { + if (typeof a != typeof b) { + return false; + } + var m = {}.toString; + if (m.apply(a) != m.apply(b)) { + return false; + } + return true; + } + + function isObject(o) { + return o && typeof o === 'object'; + } + + function isArrayObject(o) { + return isObject(o) && {}.toString.apply(o) === "[object Array]"; + } + + function checkStructure(oa, ob, ns) { + var p; + var l, r; + for (p in oa) { + if (oa.hasOwnProperty(p)) { + if (!ob.hasOwnProperty(p)) { + result.push({ + type: LOST, + property: p, + namespace: ns + }); + } else if (!typeEqual(oa[p], ob[p])) { + if (!isReverseCheck) { + result.push({ + type: TYPE_NOT_EQUAL, + property: p, + namespace: ns + }); + } + } else if (isArrayObject(oa[p]) && isArrayObject(ob[p])) { + var la = oa[p]; + var lb = ob[p]; + + var length = la.length > lb.length ? la.length : lb.length; + + + for (var i = 0; i < length; i++) { + // if la[i] is null, using the first element instead + l = la[i] ? la[i] : la[0]; + r = lb[i] ? lb[i] : lb[0]; + if (l && r && isObject(l) && isObject(r)) { + checkStructure(l, r, ns + '.' + p + '[' + i + ']'); + } else if (l && !r) { + result.push({ + type: EMPTY_ARRAY, + property: p, + namespace: ns + }); + } + } + + } else if (isObject(oa[p]) && isObject(ob[p])) { + checkStructure(oa[p], ob[p], ns + '.' + p); + } + } + } + } + + checkStructure(o1, o2, keyName, result); + this[key] = result; + }; + + global.StructureValidator = StructureValidator; + + function tester() { + + var o1 = { + p1: 1, + p2: 2, + p3: 3, + p4: 8, + obj: [{ + op3: 3, + op6: 6, + op7: 7 + }] + }; + var o2 = { + p1: 1, + p2: 5, + p3: 3, + p4: 4, + obj: [{ + op3: 3, + op6: 6, + op7: 7 + }, { + op3: 3, + op6: 6, + op77: 7 + }] + }; + + var validator = new StructureValidator(o1, o2); + console.log('result:'); + console.dir(validator.getResult()); + console.log('resultStr:'); + console.dir(validator.getResultStr()); + } + + //tester(); + +}(); diff --git a/WebContent/stat/qunit/async.js b/src/main/webapp/stat/qunit/async.js similarity index 87% rename from WebContent/stat/qunit/async.js rename to src/main/webapp/stat/qunit/async.js index 899bd3e99..934505327 100644 --- a/WebContent/stat/qunit/async.js +++ b/src/main/webapp/stat/qunit/async.js @@ -7,7 +7,7 @@ root = this; if (root != null) { - previous_async = root.async; + previous_async = root.async; } async.noConflict = function () { @@ -17,7 +17,7 @@ function only_once(fn) { var called = false; - return function() { + return function () { if (called) throw new Error("Callback was already called."); called = true; fn.apply(root, arguments); @@ -91,8 +91,8 @@ async.nextTick = process.nextTick; if (typeof setImmediate !== 'undefined') { async.setImmediate = function (fn) { - // not a direct alias for IE10 compatibility - setImmediate(fn); + // not a direct alias for IE10 compatibility + setImmediate(fn); }; } else { @@ -101,7 +101,8 @@ } async.each = function (arr, iterator, callback) { - callback = callback || function () {}; + callback = callback || function () { + }; if (!arr.length) { return callback(); } @@ -110,7 +111,8 @@ iterator(x, only_once(function (err) { if (err) { callback(err); - callback = function () {}; + callback = function () { + }; } else { completed += 1; @@ -124,7 +126,8 @@ async.forEach = async.each; async.eachSeries = function (arr, iterator, callback) { - callback = callback || function () {}; + callback = callback || function () { + }; if (!arr.length) { return callback(); } @@ -133,7 +136,8 @@ iterator(arr[completed], function (err) { if (err) { callback(err); - callback = function () {}; + callback = function () { + }; } else { completed += 1; @@ -159,7 +163,8 @@ var _eachLimit = function (limit) { return function (arr, iterator, callback) { - callback = callback || function () {}; + callback = callback || function () { + }; if (!arr.length || limit <= 0) { return callback(); } @@ -167,7 +172,7 @@ var started = 0; var running = 0; - (function replenish () { + (function replenish() { if (completed >= arr.length) { return callback(); } @@ -178,7 +183,8 @@ iterator(arr[started - 1], function (err) { if (err) { callback(err); - callback = function () {}; + callback = function () { + }; } else { completed += 1; @@ -203,7 +209,7 @@ return fn.apply(null, [async.each].concat(args)); }; }; - var doParallelLimit = function(limit, fn) { + var doParallelLimit = function (limit, fn) { return function () { var args = Array.prototype.slice.call(arguments); return fn.apply(null, [_eachLimit(limit)].concat(args)); @@ -237,7 +243,7 @@ return _mapLimit(limit)(arr, iterator, callback); }; - var _mapLimit = function(limit) { + var _mapLimit = function (limit) { return doParallelLimit(limit, _asyncMap); }; @@ -321,7 +327,8 @@ iterator(x, function (result) { if (result) { main_callback(x); - main_callback = function () {}; + main_callback = function () { + }; } else { callback(); @@ -339,7 +346,8 @@ iterator(x, function (v) { if (v) { main_callback(true); - main_callback = function () {}; + main_callback = function () { + }; } callback(); }); @@ -355,7 +363,8 @@ iterator(x, function (v) { if (!v) { main_callback(false); - main_callback = function () {}; + main_callback = function () { + }; } callback(); }); @@ -393,7 +402,8 @@ }; async.auto = function (tasks, callback) { - callback = callback || function () {}; + callback = callback || function () { + }; var keys = _keys(tasks); if (!keys.length) { return callback(null); @@ -422,12 +432,13 @@ addListener(function () { if (_keys(results).length === keys.length) { callback(null, results); - callback = function () {}; + callback = function () { + }; } }); _each(keys, function (k) { - var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var task = (tasks[k] instanceof Function) ? [tasks[k]] : tasks[k]; var taskCallback = function (err) { var args = Array.prototype.slice.call(arguments, 1); if (args.length <= 1) { @@ -435,13 +446,14 @@ } if (err) { var safeResults = {}; - _each(_keys(results), function(rkey) { + _each(_keys(results), function (rkey) { safeResults[rkey] = results[rkey]; }); safeResults[k] = args; callback(err, safeResults); // stop subsequent errors hitting callback multiple times - callback = function () {}; + callback = function () { + }; } else { results[k] = args; @@ -451,8 +463,8 @@ var requires = task.slice(0, Math.abs(task.length - 1)) || []; var ready = function () { return _reduce(requires, function (a, x) { - return (a && results.hasOwnProperty(x)); - }, true) && !results.hasOwnProperty(k); + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); }; if (ready()) { task[task.length - 1](taskCallback, results); @@ -470,10 +482,11 @@ }; async.waterfall = function (tasks, callback) { - callback = callback || function () {}; + callback = callback || function () { + }; if (tasks.constructor !== Array) { - var err = new Error('First argument to waterfall must be an array of functions'); - return callback(err); + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); } if (!tasks.length) { return callback(); @@ -482,7 +495,8 @@ return function (err) { if (err) { callback.apply(null, arguments); - callback = function () {}; + callback = function () { + }; } else { var args = Array.prototype.slice.call(arguments, 1); @@ -502,8 +516,9 @@ wrapIterator(async.iterator(tasks))(); }; - var _parallel = function(eachfn, tasks, callback) { - callback = callback || function () {}; + var _parallel = function (eachfn, tasks, callback) { + callback = callback || function () { + }; if (tasks.constructor === Array) { eachfn.map(tasks, function (fn, callback) { if (fn) { @@ -535,15 +550,16 @@ }; async.parallel = function (tasks, callback) { - _parallel({ map: async.map, each: async.each }, tasks, callback); + _parallel({map: async.map, each: async.each}, tasks, callback); }; - async.parallelLimit = function(tasks, limit, callback) { - _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + async.parallelLimit = function (tasks, limit, callback) { + _parallel({map: _mapLimit(limit), each: _eachLimit(limit)}, tasks, callback); }; async.series = function (tasks, callback) { - callback = callback || function () {}; + callback = callback || function () { + }; if (tasks.constructor === Array) { async.mapSeries(tasks, function (fn, callback) { if (fn) { @@ -583,7 +599,7 @@ return fn.next(); }; fn.next = function () { - return (index < tasks.length - 1) ? makeCallback(index + 1): null; + return (index < tasks.length - 1) ? makeCallback(index + 1) : null; }; return fn; }; @@ -674,26 +690,26 @@ concurrency = 1; } function _insert(q, data, pos, callback) { - if(data.constructor !== Array) { - data = [data]; - } - _each(data, function(task) { - var item = { - data: task, - callback: typeof callback === 'function' ? callback : null - }; - - if (pos) { - q.tasks.unshift(item); - } else { - q.tasks.push(item); - } - - if (q.saturated && q.tasks.length === concurrency) { - q.saturated(); - } - async.setImmediate(q.process); - }); + if (data.constructor !== Array) { + data = [data]; + } + _each(data, function (task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); } var workers = 0; @@ -704,10 +720,10 @@ empty: null, drain: null, push: function (data, callback) { - _insert(q, data, false, callback); + _insert(q, data, false, callback); }, unshift: function (data, callback) { - _insert(q, data, true, callback); + _insert(q, data, true, callback); }, process: function () { if (workers < q.concurrency && q.tasks.length) { @@ -741,8 +757,8 @@ }; async.cargo = function (worker, payload) { - var working = false, - tasks = []; + var working = false, + tasks = []; var cargo = { tasks: tasks, @@ -751,10 +767,10 @@ empty: null, drain: null, push: function (data, callback) { - if(data.constructor !== Array) { + if (data.constructor !== Array) { data = [data]; } - _each(data, function(task) { + _each(data, function (task) { tasks.push({ data: task, callback: typeof callback === 'function' ? callback : null @@ -768,19 +784,19 @@ process: function process() { if (working) return; if (tasks.length === 0) { - if(cargo.drain) cargo.drain(); + if (cargo.drain) cargo.drain(); return; } var ts = typeof payload === 'number' - ? tasks.splice(0, payload) - : tasks.splice(0); + ? tasks.splice(0, payload) + : tasks.splice(0); var ds = _map(ts, function (task) { return task.data; }); - if(cargo.empty) cargo.empty(); + if (cargo.empty) cargo.empty(); working = true; worker(ds, function () { working = false; @@ -828,15 +844,15 @@ async.log = _console_fn('log'); async.dir = _console_fn('dir'); /*async.info = _console_fn('info'); - async.warn = _console_fn('warn'); - async.error = _console_fn('error');*/ + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ async.memoize = function (fn, hasher) { var memo = {}; var queues = {}; hasher = hasher || function (x) { - return x; - }; + return x; + }; var memoized = function () { var args = Array.prototype.slice.call(arguments); var callback = args.pop(); @@ -854,7 +870,7 @@ var q = queues[key]; delete queues[key]; for (var i = 0, l = q.length; i < l; i++) { - q[i].apply(null, arguments); + q[i].apply(null, arguments); } }])); } @@ -865,9 +881,9 @@ }; async.unmemoize = function (fn) { - return function () { - return (fn.unmemoized || fn).apply(null, arguments); - }; + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; }; async.times = function (count, iterator, callback) { @@ -893,15 +909,15 @@ var args = Array.prototype.slice.call(arguments); var callback = args.pop(); async.reduce(fns, args, function (newargs, fn, cb) { - fn.apply(that, newargs.concat([function () { - var err = arguments[0]; - var nextargs = Array.prototype.slice.call(arguments, 1); - cb(err, nextargs); - }])) - }, - function (err, results) { - callback.apply(that, [err].concat(results)); - }); + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); }; }; @@ -911,9 +927,9 @@ var args = Array.prototype.slice.call(arguments); var callback = args.pop(); return eachfn(fns, function (fn, cb) { - fn.apply(that, args.concat([cb])); - }, - callback); + fn.apply(that, args.concat([cb])); + }, + callback); }; if (arguments.length > 2) { var args = Array.prototype.slice.call(arguments, 2); @@ -936,6 +952,7 @@ } fn(next); } + next(); }; diff --git a/src/main/webapp/stat/qunit/qunit.css b/src/main/webapp/stat/qunit/qunit.css new file mode 100644 index 000000000..b6c7c443b --- /dev/null +++ b/src/main/webapp/stat/qunit/qunit.css @@ -0,0 +1,272 @@ +/*! + * QUnit 1.14.1pre + * http://qunitjs.com/ + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-03-12T10:25Z + */ + +/** Font Family and Sizes */ + +#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { + font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; +} + +#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { + font-size: small; +} + +#qunit-tests { + font-size: smaller; +} + +/** Resets */ + +#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { + margin: 0; + padding: 0; +} + +/** Header */ + +#qunit-header { + padding: 0.5em 0 0.5em 1em; + + color: #8699A4; + background-color: #0D3349; + + font-size: 1.5em; + line-height: 1em; + font-weight: 400; + + border-radius: 5px 5px 0 0; +} + +#qunit-header a { + text-decoration: none; + color: #C2CCD1; +} + +#qunit-header a:hover, +#qunit-header a:focus { + color: #FFF; +} + +#qunit-testrunner-toolbar label { + display: inline-block; + padding: 0 0.5em 0 0.1em; +} + +#qunit-banner { + height: 5px; +} + +#qunit-testrunner-toolbar { + padding: 0.5em 1em 0.5em 1em; + color: #5E740B; + background-color: #EEE; + overflow: hidden; +} + +#qunit-userAgent { + padding: 0.5em 1em 0.5em 1em; + background-color: #2B81AF; + color: #FFF; + text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; +} + +#qunit-modulefilter-container { + float: right; +} + +/** Tests: Pass/Fail */ + +#qunit-tests { + list-style-position: inside; +} + +#qunit-tests li { + padding: 0.4em 1em 0.4em 1em; + border-bottom: 1px solid #FFF; + list-style-position: inside; +} + +#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { + display: none; +} + +#qunit-tests li strong { + cursor: pointer; +} + +#qunit-tests li a { + padding: 0.5em; + color: #C2CCD1; + text-decoration: none; +} + +#qunit-tests li a:hover, +#qunit-tests li a:focus { + color: #000; +} + +#qunit-tests li .runtime { + float: right; + font-size: smaller; +} + +.qunit-assert-list { + margin-top: 0.5em; + padding: 0.5em; + + background-color: #FFF; + + border-radius: 5px; +} + +.qunit-collapsed { + display: none; +} + +#qunit-tests table { + border-collapse: collapse; + margin-top: 0.2em; +} + +#qunit-tests th { + text-align: right; + vertical-align: top; + padding: 0 0.5em 0 0; +} + +#qunit-tests td { + vertical-align: top; +} + +#qunit-tests pre { + margin: 0; + white-space: pre-wrap; + word-wrap: break-word; +} + +#qunit-tests del { + background-color: #E0F2BE; + color: #374E0C; + text-decoration: none; +} + +#qunit-tests ins { + background-color: #FFCACA; + color: #500; + text-decoration: none; +} + +/*** Test Counts */ + +#qunit-tests b.counts { + color: #000; +} + +#qunit-tests b.passed { + color: #5E740B; +} + +#qunit-tests b.failed { + color: #710909; +} + +#qunit-tests li li { + padding: 5px; + background-color: #FFF; + border-bottom: none; + list-style-position: inside; +} + +/*** Passing Styles */ + +#qunit-tests li li.pass { + color: #3C510C; + background-color: #FFF; + border-left: 10px solid #C6E746; +} + +#qunit-tests .pass { + color: #528CE0; + background-color: #D2E0E6; +} + +#qunit-tests .pass .test-name { + color: #366097; +} + +#qunit-tests .pass .test-actual, +#qunit-tests .pass .test-expected { + color: #999; +} + +#qunit-banner.qunit-pass { + background-color: #C6E746; +} + +/*** Failing Styles */ + +#qunit-tests li li.fail { + color: #710909; + background-color: #FFF; + border-left: 10px solid #EE5757; + white-space: pre; +} + +#qunit-tests > li:last-child { + border-radius: 0 0 5px 5px; +} + +#qunit-tests .fail { + color: #000; + background-color: #EE5757; +} + +#qunit-tests .fail .test-name, +#qunit-tests .fail .module-name { + color: #000; +} + +#qunit-tests .fail .test-actual { + color: #EE5757; +} + +#qunit-tests .fail .test-expected { + color: #008000; +} + +#qunit-banner.qunit-fail { + background-color: #EE5757; +} + +/** Result */ + +#qunit-testresult { + padding: 0.5em 1em 0.5em 1em; + + color: #2B81AF; + background-color: #D2E0E6; + + border-bottom: 1px solid #FFF; +} + +#qunit-testresult .module-name { + font-weight: 700; +} + +/** Fixture */ + +#qunit-fixture { + position: absolute; + top: -10000px; + left: -10000px; + width: 1000px; + height: 1000px; +} \ No newline at end of file diff --git a/src/main/webapp/stat/qunit/qunit.js b/src/main/webapp/stat/qunit/qunit.js new file mode 100644 index 000000000..71db38396 --- /dev/null +++ b/src/main/webapp/stat/qunit/qunit.js @@ -0,0 +1,2301 @@ +/*! + * QUnit 1.14.1pre + * http://qunitjs.com/ + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2014-03-12T10:25Z + */ + + +(function (window) { + + var QUnit, + assert, + config, + onErrorFnPrev, + testId = 0, + fileName = (sourceFromStacktrace(0) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""), + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + // Keep a local reference to Date (GH-283) + Date = window.Date, + setTimeout = window.setTimeout, + clearTimeout = window.clearTimeout, + defined = { + document: typeof window.document !== "undefined", + setTimeout: typeof window.setTimeout !== "undefined", + sessionStorage: (function () { + var x = "qunit-test-string"; + try { + sessionStorage.setItem(x, x); + sessionStorage.removeItem(x); + return true; + } catch (e) { + return false; + } + }()) + }, + /** + * Provides a normalized error string, correcting an issue + * with IE 7 (and prior) where Error.prototype.toString is + * not properly implemented + * + * Based on http://es5.github.com/#x15.11.4.4 + * + * @param {String|Error} error + * @return {String} error message + */ + errorString = function (error) { + var name, message, + errorString = error.toString(); + if (errorString.substring(0, 7) === "[object") { + name = error.name ? error.name.toString() : "Error"; + message = error.message ? error.message.toString() : ""; + if (name && message) { + return name + ": " + message; + } else if (name) { + return name; + } else if (message) { + return message; + } else { + return "Error"; + } + } else { + return errorString; + } + }, + /** + * Makes a clone of an object using only Array or Object as base, + * and copies over the own enumerable properties. + * + * @param {Object} obj + * @return {Object} New object with only the own properties (recursively). + */ + objectValues = function (obj) { + // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392. + /*jshint newcap: false */ + var key, val, + vals = QUnit.is("array", obj) ? [] : {}; + for (key in obj) { + if (hasOwn.call(obj, key)) { + val = obj[key]; + vals[key] = val === Object(val) ? objectValues(val) : val; + } + } + return vals; + }; + + +// Root QUnit object. +// `QUnit` initialized at top of scope + QUnit = { + + // call on start of module test to prepend name to all tests + module: function (name, testEnvironment) { + config.currentModule = name; + config.currentModuleTestEnvironment = testEnvironment; + config.modules[name] = true; + }, + + asyncTest: function (testName, expected, callback) { + if (arguments.length === 2) { + callback = expected; + expected = null; + } + + QUnit.test(testName, expected, callback, true); + }, + + test: function (testName, expected, callback, async) { + var test, + nameHtml = "" + escapeText(testName) + ""; + + if (arguments.length === 2) { + callback = expected; + expected = null; + } + + if (config.currentModule) { + nameHtml = "" + escapeText(config.currentModule) + ": " + nameHtml; + } + + test = new Test({ + nameHtml: nameHtml, + testName: testName, + expected: expected, + async: async, + callback: callback, + module: config.currentModule, + moduleTestEnvironment: config.currentModuleTestEnvironment, + stack: sourceFromStacktrace(2) + }); + + if (!validTest(test)) { + return; + } + + test.queue(); + }, + + // Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through. + expect: function (asserts) { + if (arguments.length === 1) { + config.current.expected = asserts; + } else { + return config.current.expected; + } + }, + + start: function (count) { + // QUnit hasn't been initialized yet. + // Note: RequireJS (et al) may delay onLoad + if (config.semaphore === undefined) { + QUnit.begin(function () { + // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first + setTimeout(function () { + QUnit.start(count); + }); + }); + return; + } + + config.semaphore -= count || 1; + // don't start until equal number of stop-calls + if (config.semaphore > 0) { + return; + } + // ignore if start is called more often then stop + if (config.semaphore < 0) { + config.semaphore = 0; + QUnit.pushFailure("Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2)); + return; + } + // A slight delay, to avoid any current callbacks + if (defined.setTimeout) { + setTimeout(function () { + if (config.semaphore > 0) { + return; + } + if (config.timeout) { + clearTimeout(config.timeout); + } + + config.blocking = false; + process(true); + }, 13); + } else { + config.blocking = false; + process(true); + } + }, + + stop: function (count) { + config.semaphore += count || 1; + config.blocking = true; + + if (config.testTimeout && defined.setTimeout) { + clearTimeout(config.timeout); + config.timeout = setTimeout(function () { + QUnit.ok(false, "Test timed out"); + config.semaphore = 1; + QUnit.start(); + }, config.testTimeout); + } + } + }; + +// We use the prototype to distinguish between properties that should +// be exposed as globals (and in exports) and those that shouldn't + (function () { + function F() { + } + + F.prototype = QUnit; + QUnit = new F(); + // Make F QUnit's constructor so that we can add to the prototype later + QUnit.constructor = F; + }()); + + /** + * Config object: Maintain internal state + * Later exposed as QUnit.config + * `config` initialized at top of scope + */ + config = { + // The queue of tests to run + queue: [], + + // block until document ready + blocking: true, + + // when enabled, show only failing tests + // gets persisted through sessionStorage and can be changed in UI via checkbox + hidepassed: false, + + // by default, run previously failed tests first + // very useful in combination with "Hide passed tests" checked + reorder: true, + + // by default, modify document.title when suite is done + altertitle: true, + + // by default, scroll to top of the page when suite is done + scrolltop: true, + + // when enabled, all tests must call expect() + requireExpects: false, + + // add checkboxes that are persisted in the query-string + // when enabled, the id is set to `true` as a `QUnit.config` property + urlConfig: [ + { + id: "noglobals", + label: "Check for Globals", + tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings." + }, + { + id: "notrycatch", + label: "No try-catch", + tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings." + } + ], + + // Set of all modules. + modules: {}, + + // logging callback queues + begin: [], + done: [], + log: [], + testStart: [], + testDone: [], + moduleStart: [], + moduleDone: [] + }; + +// Initialize more QUnit.config and QUnit.urlParams + (function () { + var i, current, + location = window.location || {search: "", protocol: "file:"}, + params = location.search.slice(1).split("&"), + length = params.length, + urlParams = {}; + + if (params[0]) { + for (i = 0; i < length; i++) { + current = params[i].split("="); + current[0] = decodeURIComponent(current[0]); + + // allow just a key to turn on a flag, e.g., test.html?noglobals + current[1] = current[1] ? decodeURIComponent(current[1]) : true; + if (urlParams[current[0]]) { + urlParams[current[0]] = [].concat(urlParams[current[0]], current[1]); + } else { + urlParams[current[0]] = current[1]; + } + } + } + + QUnit.urlParams = urlParams; + + // String search anywhere in moduleName+testName + config.filter = urlParams.filter; + + // Exact match of the module name + config.module = urlParams.module; + + config.testNumber = []; + if (urlParams.testNumber) { + + // Ensure that urlParams.testNumber is an array + urlParams.testNumber = [].concat(urlParams.testNumber); + for (i = 0; i < urlParams.testNumber.length; i++) { + current = urlParams.testNumber[i]; + config.testNumber.push(parseInt(current, 10)); + } + } + + // Figure out if we're running the tests from a server or not + QUnit.isLocal = location.protocol === "file:"; + }()); + + extend(QUnit, { + + config: config, + + // Initialize the configuration options + init: function () { + extend(config, { + stats: {all: 0, bad: 0}, + moduleStats: {all: 0, bad: 0}, + started: +new Date(), + updateRate: 1000, + blocking: false, + autostart: true, + autorun: false, + filter: "", + queue: [], + semaphore: 1 + }); + + var tests, banner, result, + qunit = id("qunit"); + + if (qunit) { + qunit.innerHTML = + "

    " + escapeText(document.title) + "

    " + + "

    " + + "
    " + + "

    " + + "
      "; + } + + tests = id("qunit-tests"); + banner = id("qunit-banner"); + result = id("qunit-testresult"); + + if (tests) { + tests.innerHTML = ""; + } + + if (banner) { + banner.className = ""; + } + + if (result) { + result.parentNode.removeChild(result); + } + + if (tests) { + result = document.createElement("p"); + result.id = "qunit-testresult"; + result.className = "result"; + tests.parentNode.insertBefore(result, tests); + result.innerHTML = "Running...
       "; + } + }, + + // Resets the test setup. Useful for tests that modify the DOM. + /* + DEPRECATED: Use multiple tests instead of resetting inside a test. + Use testStart or testDone for custom cleanup. + This method will throw an error in 2.0, and will be removed in 2.1 + */ + reset: function () { + var fixture = id("qunit-fixture"); + if (fixture) { + fixture.innerHTML = config.fixture; + } + }, + + // Safe object type checking + is: function (type, obj) { + return QUnit.objectType(obj) === type; + }, + + objectType: function (obj) { + if (typeof obj === "undefined") { + return "undefined"; + } + + // Consider: typeof null === object + if (obj === null) { + return "null"; + } + + var match = toString.call(obj).match(/^\[object\s(.*)\]$/), + type = match && match[1] || ""; + + switch (type) { + case "Number": + if (isNaN(obj)) { + return "nan"; + } + return "number"; + case "String": + case "Boolean": + case "Array": + case "Date": + case "RegExp": + case "Function": + return type.toLowerCase(); + } + if (typeof obj === "object") { + return "object"; + } + return undefined; + }, + + push: function (result, actual, expected, message) { + if (!config.current) { + throw new Error("assertion outside test context, was " + sourceFromStacktrace()); + } + + var output, source, + details = { + module: config.current.module, + name: config.current.testName, + result: result, + message: message, + actual: actual, + expected: expected + }; + + message = escapeText(message) || ( result ? "okay" : "failed" ); + message = "" + message + ""; + output = message; + + if (!result) { + expected = escapeText(QUnit.jsDump.parse(expected)); + actual = escapeText(QUnit.jsDump.parse(actual)); + output += "
      "; + + if (actual !== expected) { + output += ""; + output += ""; + } + + source = sourceFromStacktrace(); + + if (source) { + details.source = source; + output += ""; + } + + output += "
      Expected:
      " + expected + "
      Result:
      " + actual + "
      Diff:
      " + QUnit.diff(expected, actual) + "
      Source:
      " + escapeText(source) + "
      "; + } + + runLoggingCallbacks("log", QUnit, details); + + config.current.assertions.push({ + result: !!result, + message: output + }); + }, + + pushFailure: function (message, source, actual) { + if (!config.current) { + throw new Error("pushFailure() assertion outside test context, was " + sourceFromStacktrace(2)); + } + + var output, + details = { + module: config.current.module, + name: config.current.testName, + result: false, + message: message + }; + + message = escapeText(message) || "error"; + message = "" + message + ""; + output = message; + + output += ""; + + if (actual) { + output += ""; + } + + if (source) { + details.source = source; + output += ""; + } + + output += "
      Result:
      " + escapeText(actual) + "
      Source:
      " + escapeText(source) + "
      "; + + runLoggingCallbacks("log", QUnit, details); + + config.current.assertions.push({ + result: false, + message: output + }); + }, + + url: function (params) { + params = extend(extend({}, QUnit.urlParams), params); + var key, + querystring = "?"; + + for (key in params) { + if (hasOwn.call(params, key)) { + querystring += encodeURIComponent(key) + "=" + + encodeURIComponent(params[key]) + "&"; + } + } + return window.location.protocol + "//" + window.location.host + + window.location.pathname + querystring.slice(0, -1); + }, + + extend: extend, + id: id, + addEvent: addEvent, + addClass: addClass, + hasClass: hasClass, + removeClass: removeClass + // load, equiv, jsDump, diff: Attached later + }); + + /** + * @deprecated: Created for backwards compatibility with test runner that set the hook function + * into QUnit.{hook}, instead of invoking it and passing the hook function. + * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here. + * Doing this allows us to tell if the following methods have been overwritten on the actual + * QUnit object. + */ + extend(QUnit.constructor.prototype, { + + // Logging callbacks; all receive a single argument with the listed properties + // run test/logs.html for any related changes + begin: registerLoggingCallback("begin"), + + // done: { failed, passed, total, runtime } + done: registerLoggingCallback("done"), + + // log: { result, actual, expected, message } + log: registerLoggingCallback("log"), + + // testStart: { name } + testStart: registerLoggingCallback("testStart"), + + // testDone: { name, failed, passed, total, runtime } + testDone: registerLoggingCallback("testDone"), + + // moduleStart: { name } + moduleStart: registerLoggingCallback("moduleStart"), + + // moduleDone: { name, failed, passed, total } + moduleDone: registerLoggingCallback("moduleDone") + }); + + if (!defined.document || document.readyState === "complete") { + config.autorun = true; + } + + QUnit.load = function () { + runLoggingCallbacks("begin", QUnit, {}); + + // Initialize the config, saving the execution queue + var banner, filter, i, j, label, len, main, ol, toolbar, val, selection, + urlConfigContainer, moduleFilter, userAgent, + numModules = 0, + moduleNames = [], + moduleFilterHtml = "", + urlConfigHtml = "", + oldconfig = extend({}, config); + + QUnit.init(); + extend(config, oldconfig); + + config.blocking = false; + + len = config.urlConfig.length; + + for (i = 0; i < len; i++) { + val = config.urlConfig[i]; + if (typeof val === "string") { + val = { + id: val, + label: val + }; + } + config[val.id] = QUnit.urlParams[val.id]; + if (!val.value || typeof val.value === "string") { + urlConfigHtml += ""; + } else { + urlConfigHtml += ""; + } + } + for (i in config.modules) { + if (config.modules.hasOwnProperty(i)) { + moduleNames.push(i); + } + } + numModules = moduleNames.length; + moduleNames.sort(function (a, b) { + return a.localeCompare(b); + }); + moduleFilterHtml += ""; + + // `userAgent` initialized at top of scope + userAgent = id("qunit-userAgent"); + if (userAgent) { + userAgent.innerHTML = navigator.userAgent; + } + + // `banner` initialized at top of scope + banner = id("qunit-header"); + if (banner) { + banner.innerHTML = "" + banner.innerHTML + " "; + } + + // `toolbar` initialized at top of scope + toolbar = id("qunit-testrunner-toolbar"); + if (toolbar) { + // `filter` initialized at top of scope + filter = document.createElement("input"); + filter.type = "checkbox"; + filter.id = "qunit-filter-pass"; + + addEvent(filter, "click", function () { + var tmp, + ol = id("qunit-tests"); + + if (filter.checked) { + ol.className = ol.className + " hidepass"; + } else { + tmp = " " + ol.className.replace(/[\n\t\r]/g, " ") + " "; + ol.className = tmp.replace(/ hidepass /, " "); + } + if (defined.sessionStorage) { + if (filter.checked) { + sessionStorage.setItem("qunit-filter-passed-tests", "true"); + } else { + sessionStorage.removeItem("qunit-filter-passed-tests"); + } + } + }); + + if (config.hidepassed || defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests")) { + filter.checked = true; + // `ol` initialized at top of scope + ol = id("qunit-tests"); + ol.className = ol.className + " hidepass"; + } + toolbar.appendChild(filter); + + // `label` initialized at top of scope + label = document.createElement("label"); + label.setAttribute("for", "qunit-filter-pass"); + label.setAttribute("title", "Only show tests and assertions that fail. Stored in sessionStorage."); + label.innerHTML = "Hide passed tests"; + toolbar.appendChild(label); + + urlConfigContainer = document.createElement("span"); + urlConfigContainer.innerHTML = urlConfigHtml; + // For oldIE support: + // * Add handlers to the individual elements instead of the container + // * Use "click" instead of "change" for checkboxes + // * Fallback from event.target to event.srcElement + addEvents(urlConfigContainer.getElementsByTagName("input"), "click", function (event) { + var params = {}, + target = event.target || event.srcElement; + params[target.name] = target.checked ? + target.defaultValue || true : + undefined; + window.location = QUnit.url(params); + }); + addEvents(urlConfigContainer.getElementsByTagName("select"), "change", function (event) { + var params = {}, + target = event.target || event.srcElement; + params[target.name] = target.options[target.selectedIndex].value || undefined; + window.location = QUnit.url(params); + }); + toolbar.appendChild(urlConfigContainer); + + if (numModules > 1) { + moduleFilter = document.createElement("span"); + moduleFilter.setAttribute("id", "qunit-modulefilter-container"); + moduleFilter.innerHTML = moduleFilterHtml; + addEvent(moduleFilter.lastChild, "change", function () { + var selectBox = moduleFilter.getElementsByTagName("select")[0], + selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value); + + window.location = QUnit.url({ + module: ( selectedModule === "" ) ? undefined : selectedModule, + // Remove any existing filters + filter: undefined, + testNumber: undefined + }); + }); + toolbar.appendChild(moduleFilter); + } + } + + // `main` initialized at top of scope + main = id("qunit-fixture"); + if (main) { + config.fixture = main.innerHTML; + } + + if (config.autostart) { + QUnit.start(); + } + }; + + if (defined.document) { + addEvent(window, "load", QUnit.load); + } + +// `onErrorFnPrev` initialized at top of scope +// Preserve other handlers + onErrorFnPrev = window.onerror; + +// Cover uncaught exceptions +// Returning true will suppress the default browser handler, +// returning false will let it run. + window.onerror = function (error, filePath, linerNr) { + var ret = false; + if (onErrorFnPrev) { + ret = onErrorFnPrev(error, filePath, linerNr); + } + + // Treat return value as window.onerror itself does, + // Only do our handling if not suppressed. + if (ret !== true) { + if (QUnit.config.current) { + if (QUnit.config.current.ignoreGlobalErrors) { + return true; + } + QUnit.pushFailure(error, filePath + ":" + linerNr); + } else { + QUnit.test("global failure", extend(function () { + QUnit.pushFailure(error, filePath + ":" + linerNr); + }, {validTest: validTest})); + } + return false; + } + + return ret; + }; + + function done() { + config.autorun = true; + + // Log the last module results + if (config.previousModule) { + runLoggingCallbacks("moduleDone", QUnit, { + name: config.previousModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + }); + } + delete config.previousModule; + + var i, key, + banner = id("qunit-banner"), + tests = id("qunit-tests"), + runtime = +new Date() - config.started, + passed = config.stats.all - config.stats.bad, + html = [ + "Tests completed in ", + runtime, + " milliseconds.
      ", + "", + passed, + " assertions of ", + config.stats.all, + " passed, ", + config.stats.bad, + " failed." + ].join(""); + + if (banner) { + banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" ); + } + + if (tests) { + id("qunit-testresult").innerHTML = html; + } + + if (config.altertitle && defined.document && document.title) { + // show ✖ for good, ✔ for bad suite result in title + // use escape sequences in case file gets loaded with non-utf-8-charset + document.title = [ + ( config.stats.bad ? "\u2716" : "\u2714" ), + document.title.replace(/^[\u2714\u2716] /i, "") + ].join(" "); + } + + // clear own sessionStorage items if all tests passed + if (config.reorder && defined.sessionStorage && config.stats.bad === 0) { + // `key` & `i` initialized at top of scope + for (i = 0; i < sessionStorage.length; i++) { + key = sessionStorage.key(i++); + if (key.indexOf("qunit-test-") === 0) { + sessionStorage.removeItem(key); + } + } + } + + // scroll back to top to show results + if (config.scrolltop && window.scrollTo) { + window.scrollTo(0, 0); + } + + runLoggingCallbacks("done", QUnit, { + failed: config.stats.bad, + passed: passed, + total: config.stats.all, + runtime: runtime + }); + } + + /** @return Boolean: true if this test should be ran */ + function validTest(test) { + var include, + filter = config.filter && config.filter.toLowerCase(), + module = config.module && config.module.toLowerCase(), + fullName = ( test.module + ": " + test.testName ).toLowerCase(); + + // Internally-generated tests are always valid + if (test.callback && test.callback.validTest === validTest) { + delete test.callback.validTest; + return true; + } + + if (config.testNumber.length > 0) { + if (inArray(test.testNumber, config.testNumber) < 0) { + return false; + } + } + + if (module && ( !test.module || test.module.toLowerCase() !== module )) { + return false; + } + + if (!filter) { + return true; + } + + include = filter.charAt(0) !== "!"; + if (!include) { + filter = filter.slice(1); + } + + // If the filter matches, we need to honour include + if (fullName.indexOf(filter) !== -1) { + return include; + } + + // Otherwise, do the opposite + return !include; + } + +// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions) +// Later Safari and IE10 are supposed to support error.stack as well +// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack + function extractStacktrace(e, offset) { + offset = offset === undefined ? 3 : offset; + + var stack, include, i; + + if (e.stacktrace) { + // Opera + return e.stacktrace.split("\n")[offset + 3]; + } else if (e.stack) { + // Firefox, Chrome + stack = e.stack.split("\n"); + if (/^error$/i.test(stack[0])) { + stack.shift(); + } + if (fileName) { + include = []; + for (i = offset; i < stack.length; i++) { + if (stack[i].indexOf(fileName) !== -1) { + break; + } + include.push(stack[i]); + } + if (include.length) { + return include.join("\n"); + } + } + return stack[offset]; + } else if (e.sourceURL) { + // Safari, PhantomJS + // hopefully one day Safari provides actual stacktraces + // exclude useless self-reference for generated Error objects + if (/qunit.js$/.test(e.sourceURL)) { + return; + } + // for actual exceptions, this is useful + return e.sourceURL + ":" + e.line; + } + } + + function sourceFromStacktrace(offset) { + try { + throw new Error(); + } catch (e) { + return extractStacktrace(e, offset); + } + } + + /** + * Escape text for attribute or text content. + */ + function escapeText(s) { + if (!s) { + return ""; + } + s = s + ""; + // Both single quotes and double quotes (for attributes) + return s.replace(/['"<>&]/g, function (s) { + switch (s) { + case "'": + return "'"; + case "\"": + return """; + case "<": + return "<"; + case ">": + return ">"; + case "&": + return "&"; + } + }); + } + + function synchronize(callback, last) { + config.queue.push(callback); + + if (config.autorun && !config.blocking) { + process(last); + } + } + + function process(last) { + function next() { + process(last); + } + + var start = new Date().getTime(); + config.depth = config.depth ? config.depth + 1 : 1; + + while (config.queue.length && !config.blocking) { + if (!defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate )) { + config.queue.shift()(); + } else { + setTimeout(next, 13); + break; + } + } + config.depth--; + if (last && !config.blocking && !config.queue.length && config.depth === 0) { + done(); + } + } + + function saveGlobal() { + config.pollution = []; + + if (config.noglobals) { + for (var key in window) { + if (hasOwn.call(window, key)) { + // in Opera sometimes DOM element ids show up here, ignore them + if (/^qunit-test-output/.test(key)) { + continue; + } + config.pollution.push(key); + } + } + } + } + + function checkPollution() { + var newGlobals, + deletedGlobals, + old = config.pollution; + + saveGlobal(); + + newGlobals = diff(config.pollution, old); + if (newGlobals.length > 0) { + QUnit.pushFailure("Introduced global variable(s): " + newGlobals.join(", ")); + } + + deletedGlobals = diff(old, config.pollution); + if (deletedGlobals.length > 0) { + QUnit.pushFailure("Deleted global variable(s): " + deletedGlobals.join(", ")); + } + } + +// returns a new Array with the elements that are in a but not in b + function diff(a, b) { + var i, j, + result = a.slice(); + + for (i = 0; i < result.length; i++) { + for (j = 0; j < b.length; j++) { + if (result[i] === b[j]) { + result.splice(i, 1); + i--; + break; + } + } + } + return result; + } + + function extend(a, b) { + for (var prop in b) { + if (hasOwn.call(b, prop)) { + // Avoid "Member not found" error in IE8 caused by messing with window.constructor + if (!( prop === "constructor" && a === window )) { + if (b[prop] === undefined) { + delete a[prop]; + } else { + a[prop] = b[prop]; + } + } + } + } + + return a; + } + + /** + * @param {HTMLElement} elem + * @param {string} type + * @param {Function} fn + */ + function addEvent(elem, type, fn) { + if (elem.addEventListener) { + + // Standards-based browsers + elem.addEventListener(type, fn, false); + } else if (elem.attachEvent) { + + // support: IE <9 + elem.attachEvent("on" + type, fn); + } else { + + // Caller must ensure support for event listeners is present + throw new Error("addEvent() was called in a context without event listener support"); + } + } + + /** + * @param {Array|NodeList} elems + * @param {string} type + * @param {Function} fn + */ + function addEvents(elems, type, fn) { + var i = elems.length; + while (i--) { + addEvent(elems[i], type, fn); + } + } + + function hasClass(elem, name) { + return (" " + elem.className + " ").indexOf(" " + name + " ") > -1; + } + + function addClass(elem, name) { + if (!hasClass(elem, name)) { + elem.className += (elem.className ? " " : "") + name; + } + } + + function removeClass(elem, name) { + var set = " " + elem.className + " "; + // Class name may appear multiple times + while (set.indexOf(" " + name + " ") > -1) { + set = set.replace(" " + name + " ", " "); + } + // If possible, trim it for prettiness, but not necessarily + elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, ""); + } + + function id(name) { + return defined.document && document.getElementById && document.getElementById(name); + } + + function registerLoggingCallback(key) { + return function (callback) { + config[key].push(callback); + }; + } + +// Supports deprecated method of completely overwriting logging callbacks + function runLoggingCallbacks(key, scope, args) { + var i, callbacks; + if (QUnit.hasOwnProperty(key)) { + QUnit[key].call(scope, args); + } else { + callbacks = config[key]; + for (i = 0; i < callbacks.length; i++) { + callbacks[i].call(scope, args); + } + } + } + +// from jquery.js + function inArray(elem, array) { + if (array.indexOf) { + return array.indexOf(elem); + } + + for (var i = 0, length = array.length; i < length; i++) { + if (array[i] === elem) { + return i; + } + } + + return -1; + } + + function Test(settings) { + extend(this, settings); + this.assertions = []; + this.testNumber = ++Test.count; + } + + Test.count = 0; + + Test.prototype = { + init: function () { + var a, b, li, + tests = id("qunit-tests"); + + if (tests) { + b = document.createElement("strong"); + b.innerHTML = this.nameHtml; + + // `a` initialized at top of scope + a = document.createElement("a"); + a.innerHTML = "Rerun"; + a.href = QUnit.url({testNumber: this.testNumber}); + + li = document.createElement("li"); + li.appendChild(b); + li.appendChild(a); + li.className = "running"; + li.id = this.id = "qunit-test-output" + testId++; + + tests.appendChild(li); + } + }, + setup: function () { + if ( + // Emit moduleStart when we're switching from one module to another + this.module !== config.previousModule || + // They could be equal (both undefined) but if the previousModule property doesn't + // yet exist it means this is the first test in a suite that isn't wrapped in a + // module, in which case we'll just emit a moduleStart event for 'undefined'. + // Without this, reporters can get testStart before moduleStart which is a problem. + !hasOwn.call(config, "previousModule") + ) { + if (hasOwn.call(config, "previousModule")) { + runLoggingCallbacks("moduleDone", QUnit, { + name: config.previousModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + }); + } + config.previousModule = this.module; + config.moduleStats = {all: 0, bad: 0}; + runLoggingCallbacks("moduleStart", QUnit, { + name: this.module + }); + } + + config.current = this; + + this.testEnvironment = extend({ + setup: function () { + }, + teardown: function () { + } + }, this.moduleTestEnvironment); + + this.started = +new Date(); + runLoggingCallbacks("testStart", QUnit, { + name: this.testName, + module: this.module + }); + + /*jshint camelcase:false */ + + + /** + * Expose the current test environment. + * + * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead. + */ + QUnit.current_testEnvironment = this.testEnvironment; + + /*jshint camelcase:true */ + + if (!config.pollution) { + saveGlobal(); + } + if (config.notrycatch) { + this.testEnvironment.setup.call(this.testEnvironment, QUnit.assert); + return; + } + try { + this.testEnvironment.setup.call(this.testEnvironment, QUnit.assert); + } catch (e) { + QUnit.pushFailure("Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace(e, 1)); + } + }, + run: function () { + config.current = this; + + var running = id("qunit-testresult"); + + if (running) { + running.innerHTML = "Running:
      " + this.nameHtml; + } + + if (this.async) { + QUnit.stop(); + } + + this.callbackStarted = +new Date(); + + if (config.notrycatch) { + this.callback.call(this.testEnvironment, QUnit.assert); + this.callbackRuntime = +new Date() - this.callbackStarted; + return; + } + + try { + this.callback.call(this.testEnvironment, QUnit.assert); + this.callbackRuntime = +new Date() - this.callbackStarted; + } catch (e) { + this.callbackRuntime = +new Date() - this.callbackStarted; + + QUnit.pushFailure("Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace(e, 0)); + // else next test will carry the responsibility + saveGlobal(); + + // Restart the tests if they're blocking + if (config.blocking) { + QUnit.start(); + } + } + }, + teardown: function () { + config.current = this; + if (config.notrycatch) { + if (typeof this.callbackRuntime === "undefined") { + this.callbackRuntime = +new Date() - this.callbackStarted; + } + this.testEnvironment.teardown.call(this.testEnvironment, QUnit.assert); + return; + } else { + try { + this.testEnvironment.teardown.call(this.testEnvironment, QUnit.assert); + } catch (e) { + QUnit.pushFailure("Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace(e, 1)); + } + } + checkPollution(); + }, + finish: function () { + config.current = this; + if (config.requireExpects && this.expected === null) { + QUnit.pushFailure("Expected number of assertions to be defined, but expect() was not called.", this.stack); + } else if (this.expected !== null && this.expected !== this.assertions.length) { + QUnit.pushFailure("Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack); + } else if (this.expected === null && !this.assertions.length) { + QUnit.pushFailure("Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack); + } + + var i, assertion, a, b, time, li, ol, + test = this, + good = 0, + bad = 0, + tests = id("qunit-tests"); + + this.runtime = +new Date() - this.started; + config.stats.all += this.assertions.length; + config.moduleStats.all += this.assertions.length; + + if (tests) { + ol = document.createElement("ol"); + ol.className = "qunit-assert-list"; + + for (i = 0; i < this.assertions.length; i++) { + assertion = this.assertions[i]; + + li = document.createElement("li"); + li.className = assertion.result ? "pass" : "fail"; + li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" ); + ol.appendChild(li); + + if (assertion.result) { + good++; + } else { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + + // store result when possible + if (QUnit.config.reorder && defined.sessionStorage) { + if (bad) { + sessionStorage.setItem("qunit-test-" + this.module + "-" + this.testName, bad); + } else { + sessionStorage.removeItem("qunit-test-" + this.module + "-" + this.testName); + } + } + + if (bad === 0) { + addClass(ol, "qunit-collapsed"); + } + + // `b` initialized at top of scope + b = document.createElement("strong"); + b.innerHTML = this.nameHtml + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; + + addEvent(b, "click", function () { + var next = b.parentNode.lastChild, + collapsed = hasClass(next, "qunit-collapsed"); + ( collapsed ? removeClass : addClass )(next, "qunit-collapsed"); + }); + + addEvent(b, "dblclick", function (e) { + var target = e && e.target ? e.target : window.event.srcElement; + if (target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b") { + target = target.parentNode; + } + if (window.location && target.nodeName.toLowerCase() === "strong") { + window.location = QUnit.url({testNumber: test.testNumber}); + } + }); + + // `time` initialized at top of scope + time = document.createElement("span"); + time.className = "runtime"; + time.innerHTML = this.runtime + " ms"; + + // `li` initialized at top of scope + li = id(this.id); + li.className = bad ? "fail" : "pass"; + li.removeChild(li.firstChild); + a = li.firstChild; + li.appendChild(b); + li.appendChild(a); + li.appendChild(time); + li.appendChild(ol); + + } else { + for (i = 0; i < this.assertions.length; i++) { + if (!this.assertions[i].result) { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + } + + runLoggingCallbacks("testDone", QUnit, { + name: this.testName, + module: this.module, + failed: bad, + passed: this.assertions.length - bad, + total: this.assertions.length, + runtime: this.runtime, + // DEPRECATED: this property will be removed in 2.0.0, use runtime instead + duration: this.runtime + }); + + QUnit.reset(); + + config.current = undefined; + }, + + queue: function () { + var bad, + test = this; + + synchronize(function () { + test.init(); + }); + function run() { + // each of these can by async + synchronize(function () { + test.setup(); + }); + synchronize(function () { + test.run(); + }); + synchronize(function () { + test.teardown(); + }); + synchronize(function () { + test.finish(); + }); + } + + // `bad` initialized at top of scope + // defer when previous test run passed, if storage is available + bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-test-" + this.module + "-" + this.testName); + + if (bad) { + run(); + } else { + synchronize(run, true); + } + } + }; + +// `assert` initialized at top of scope +// Assert helpers +// All of these must either call QUnit.push() or manually do: +// - runLoggingCallbacks( "log", .. ); +// - config.current.assertions.push({ .. }); + assert = QUnit.assert = { + /** + * Asserts rough true-ish result. + * @name ok + * @function + * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); + */ + ok: function (result, msg) { + if (!config.current) { + throw new Error("ok() assertion outside test context, was " + sourceFromStacktrace(2)); + } + result = !!result; + msg = msg || ( result ? "okay" : "failed" ); + + var source, + details = { + module: config.current.module, + name: config.current.testName, + result: result, + message: msg + }; + + msg = "" + escapeText(msg) + ""; + + if (!result) { + source = sourceFromStacktrace(2); + if (source) { + details.source = source; + msg += "
      Source:
      " +
      +                        escapeText(source) +
      +                        "
      "; + } + } + runLoggingCallbacks("log", QUnit, details); + config.current.assertions.push({ + result: result, + message: msg + }); + }, + + /** + * Assert that the first two arguments are equal, with an optional message. + * Prints out both actual and expected values. + * @name equal + * @function + * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" ); + */ + equal: function (actual, expected, message) { + /*jshint eqeqeq:false */ + QUnit.push(expected == actual, actual, expected, message); + }, + + /** + * @name notEqual + * @function + */ + notEqual: function (actual, expected, message) { + /*jshint eqeqeq:false */ + QUnit.push(expected != actual, actual, expected, message); + }, + + /** + * @name propEqual + * @function + */ + propEqual: function (actual, expected, message) { + actual = objectValues(actual); + expected = objectValues(expected); + QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); + }, + + /** + * @name notPropEqual + * @function + */ + notPropEqual: function (actual, expected, message) { + actual = objectValues(actual); + expected = objectValues(expected); + QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message); + }, + + /** + * @name deepEqual + * @function + */ + deepEqual: function (actual, expected, message) { + QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); + }, + + /** + * @name notDeepEqual + * @function + */ + notDeepEqual: function (actual, expected, message) { + QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message); + }, + + /** + * @name strictEqual + * @function + */ + strictEqual: function (actual, expected, message) { + QUnit.push(expected === actual, actual, expected, message); + }, + + /** + * @name notStrictEqual + * @function + */ + notStrictEqual: function (actual, expected, message) { + QUnit.push(expected !== actual, actual, expected, message); + }, + + "throws": function (block, expected, message) { + var actual, + expectedOutput = expected, + ok = false; + + // 'expected' is optional + if (!message && typeof expected === "string") { + message = expected; + expected = null; + } + + config.current.ignoreGlobalErrors = true; + try { + block.call(config.current.testEnvironment); + } catch (e) { + actual = e; + } + config.current.ignoreGlobalErrors = false; + + if (actual) { + + // we don't want to validate thrown error + if (!expected) { + ok = true; + expectedOutput = null; + + // expected is an Error object + } else if (expected instanceof Error) { + ok = actual instanceof Error && + actual.name === expected.name && + actual.message === expected.message; + + // expected is a regexp + } else if (QUnit.objectType(expected) === "regexp") { + ok = expected.test(errorString(actual)); + + // expected is a string + } else if (QUnit.objectType(expected) === "string") { + ok = expected === errorString(actual); + + // expected is a constructor + } else if (actual instanceof expected) { + ok = true; + + // expected is a validation function which returns true is validation passed + } else if (expected.call({}, actual) === true) { + expectedOutput = null; + ok = true; + } + + QUnit.push(ok, actual, expectedOutput, message); + } else { + QUnit.pushFailure(message, null, "No exception was thrown."); + } + } + }; + + /** + * @deprecated since 1.8.0 + * Kept assertion helpers in root for backwards compatibility. + */ + extend(QUnit.constructor.prototype, assert); + + /** + * @deprecated since 1.9.0 + * Kept to avoid TypeErrors for undefined methods. + */ + QUnit.constructor.prototype.raises = function () { + QUnit.push(false, false, false, "QUnit.raises has been deprecated since 2012 (fad3c1ea), use QUnit.throws instead"); + }; + + /** + * @deprecated since 1.0.0, replaced with error pushes since 1.3.0 + * Kept to avoid TypeErrors for undefined methods. + */ + QUnit.constructor.prototype.equals = function () { + QUnit.push(false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead"); + }; + QUnit.constructor.prototype.same = function () { + QUnit.push(false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead"); + }; + +// Test for equality any JavaScript type. +// Author: Philippe Rathé + QUnit.equiv = (function () { + + // Call the o related callback with the given arguments. + function bindCallbacks(o, callbacks, args) { + var prop = QUnit.objectType(o); + if (prop) { + if (QUnit.objectType(callbacks[prop]) === "function") { + return callbacks[prop].apply(callbacks, args); + } else { + return callbacks[prop]; // or undefined + } + } + } + + // the real equiv function + var innerEquiv, + // stack to decide between skip/abort functions + callers = [], + // stack to avoiding loops from circular referencing + parents = [], + parentsB = [], + + getProto = Object.getPrototypeOf || function (obj) { + /* jshint camelcase: false, proto: true */ + return obj.__proto__; + }, + callbacks = (function () { + + // for string, boolean, number and null + function useStrictEquality(b, a) { + /*jshint eqeqeq:false */ + if (b instanceof a.constructor || a instanceof b.constructor) { + // to catch short annotation VS 'new' annotation of a + // declaration + // e.g. var i = 1; + // var j = new Number(1); + return a == b; + } else { + return a === b; + } + } + + return { + "string": useStrictEquality, + "boolean": useStrictEquality, + "number": useStrictEquality, + "null": useStrictEquality, + "undefined": useStrictEquality, + + "nan": function (b) { + return isNaN(b); + }, + + "date": function (b, a) { + return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf(); + }, + + "regexp": function (b, a) { + return QUnit.objectType(b) === "regexp" && + // the regex itself + a.source === b.source && + // and its modifiers + a.global === b.global && + // (gmi) ... + a.ignoreCase === b.ignoreCase && + a.multiline === b.multiline && + a.sticky === b.sticky; + }, + + // - skip when the property is a method of an instance (OOP) + // - abort otherwise, + // initial === would have catch identical references anyway + "function": function () { + var caller = callers[callers.length - 1]; + return caller !== Object && typeof caller !== "undefined"; + }, + + "array": function (b, a) { + var i, j, len, loop, aCircular, bCircular; + + // b could be an object literal here + if (QUnit.objectType(b) !== "array") { + return false; + } + + len = a.length; + if (len !== b.length) { + // safe and faster + return false; + } + + // track reference to avoid circular references + parents.push(a); + parentsB.push(b); + for (i = 0; i < len; i++) { + loop = false; + for (j = 0; j < parents.length; j++) { + aCircular = parents[j] === a[i]; + bCircular = parentsB[j] === b[i]; + if (aCircular || bCircular) { + if (a[i] === b[i] || aCircular && bCircular) { + loop = true; + } else { + parents.pop(); + parentsB.pop(); + return false; + } + } + } + if (!loop && !innerEquiv(a[i], b[i])) { + parents.pop(); + parentsB.pop(); + return false; + } + } + parents.pop(); + parentsB.pop(); + return true; + }, + + "object": function (b, a) { + /*jshint forin:false */ + var i, j, loop, aCircular, bCircular, + // Default to true + eq = true, + aProperties = [], + bProperties = []; + + // comparing constructors is more strict than using + // instanceof + if (a.constructor !== b.constructor) { + // Allow objects with no prototype to be equivalent to + // objects with Object as their constructor. + if (!(( getProto(a) === null && getProto(b) === Object.prototype ) || + ( getProto(b) === null && getProto(a) === Object.prototype ) )) { + return false; + } + } + + // stack constructor before traversing properties + callers.push(a.constructor); + + // track reference to avoid circular references + parents.push(a); + parentsB.push(b); + + // be strict: don't ensure hasOwnProperty and go deep + for (i in a) { + loop = false; + for (j = 0; j < parents.length; j++) { + aCircular = parents[j] === a[i]; + bCircular = parentsB[j] === b[i]; + if (aCircular || bCircular) { + if (a[i] === b[i] || aCircular && bCircular) { + loop = true; + } else { + eq = false; + break; + } + } + } + aProperties.push(i); + if (!loop && !innerEquiv(a[i], b[i])) { + eq = false; + break; + } + } + + parents.pop(); + parentsB.pop(); + callers.pop(); // unstack, we are done + + for (i in b) { + bProperties.push(i); // collect b's properties + } + + // Ensures identical properties name + return eq && innerEquiv(aProperties.sort(), bProperties.sort()); + } + }; + }()); + + innerEquiv = function () { // can take multiple arguments + var args = [].slice.apply(arguments); + if (args.length < 2) { + return true; // end transition + } + + return (function (a, b) { + if (a === b) { + return true; // catch the most you can + } else if (a === null || b === null || typeof a === "undefined" || + typeof b === "undefined" || + QUnit.objectType(a) !== QUnit.objectType(b)) { + return false; // don't lose time with error prone cases + } else { + return bindCallbacks(a, callbacks, [b, a]); + } + + // apply transition with (1..n) arguments + }(args[0], args[1]) && innerEquiv.apply(this, args.splice(1, args.length - 1)) ); + }; + + return innerEquiv; + }()); + + /** + * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | + * http://flesler.blogspot.com Licensed under BSD + * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008 + * + * @projectDescription Advanced and extensible data dumping for Javascript. + * @version 1.0.0 + * @author Ariel Flesler + * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html} + */ + QUnit.jsDump = (function () { + function quote(str) { + return "\"" + str.toString().replace(/"/g, "\\\"") + "\""; + } + + function literal(o) { + return o + ""; + } + + function join(pre, arr, post) { + var s = jsDump.separator(), + base = jsDump.indent(), + inner = jsDump.indent(1); + if (arr.join) { + arr = arr.join("," + s + inner); + } + if (!arr) { + return pre + post; + } + return [pre, inner + arr, base + post].join(s); + } + + function array(arr, stack) { + var i = arr.length, ret = new Array(i); + this.up(); + while (i--) { + ret[i] = this.parse(arr[i], undefined, stack); + } + this.down(); + return join("[", ret, "]"); + } + + var reName = /^function (\w+)/, + jsDump = { + // type is used mostly internally, you can fix a (custom)type in advance + parse: function (obj, type, stack) { + stack = stack || []; + var inStack, res, + parser = this.parsers[type || this.typeOf(obj)]; + + type = typeof parser; + inStack = inArray(obj, stack); + + if (inStack !== -1) { + return "recursion(" + (inStack - stack.length) + ")"; + } + if (type === "function") { + stack.push(obj); + res = parser.call(this, obj, stack); + stack.pop(); + return res; + } + return ( type === "string" ) ? parser : this.parsers.error; + }, + typeOf: function (obj) { + var type; + if (obj === null) { + type = "null"; + } else if (typeof obj === "undefined") { + type = "undefined"; + } else if (QUnit.is("regexp", obj)) { + type = "regexp"; + } else if (QUnit.is("date", obj)) { + type = "date"; + } else if (QUnit.is("function", obj)) { + type = "function"; + } else if (typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined") { + type = "window"; + } else if (obj.nodeType === 9) { + type = "document"; + } else if (obj.nodeType) { + type = "node"; + } else if ( + // native arrays + toString.call(obj) === "[object Array]" || + // NodeList objects + ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item(0) === null && typeof obj[0] === "undefined" ) ) ) + ) { + type = "array"; + } else if (obj.constructor === Error.prototype.constructor) { + type = "error"; + } else { + type = typeof obj; + } + return type; + }, + separator: function () { + return this.multiline ? this.HTML ? "
      " : "\n" : this.HTML ? " " : " "; + }, + // extra can be a number, shortcut for increasing-calling-decreasing + indent: function (extra) { + if (!this.multiline) { + return ""; + } + var chr = this.indentChar; + if (this.HTML) { + chr = chr.replace(/\t/g, " ").replace(/ /g, " "); + } + return new Array(this.depth + ( extra || 0 )).join(chr); + }, + up: function (a) { + this.depth += a || 1; + }, + down: function (a) { + this.depth -= a || 1; + }, + setParser: function (name, parser) { + this.parsers[name] = parser; + }, + // The next 3 are exposed so you can use them + quote: quote, + literal: literal, + join: join, + // + depth: 1, + // This is the list of parsers, to modify them, use jsDump.setParser + parsers: { + window: "[Window]", + document: "[Document]", + error: function (error) { + return "Error(\"" + error.message + "\")"; + }, + unknown: "[Unknown]", + "null": "null", + "undefined": "undefined", + "function": function (fn) { + var ret = "function", + // functions never have name in IE + name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1]; + + if (name) { + ret += " " + name; + } + ret += "( "; + + ret = [ret, QUnit.jsDump.parse(fn, "functionArgs"), "){"].join(""); + return join(ret, QUnit.jsDump.parse(fn, "functionCode"), "}"); + }, + array: array, + nodelist: array, + "arguments": array, + object: function (map, stack) { + /*jshint forin:false */ + var ret = [], keys, key, val, i; + QUnit.jsDump.up(); + keys = []; + for (key in map) { + keys.push(key); + } + keys.sort(); + for (i = 0; i < keys.length; i++) { + key = keys[i]; + val = map[key]; + ret.push(QUnit.jsDump.parse(key, "key") + ": " + QUnit.jsDump.parse(val, undefined, stack)); + } + QUnit.jsDump.down(); + return join("{", ret, "}"); + }, + node: function (node) { + var len, i, val, + open = QUnit.jsDump.HTML ? "<" : "<", + close = QUnit.jsDump.HTML ? ">" : ">", + tag = node.nodeName.toLowerCase(), + ret = open + tag, + attrs = node.attributes; + + if (attrs) { + for (i = 0, len = attrs.length; i < len; i++) { + val = attrs[i].nodeValue; + // IE6 includes all attributes in .attributes, even ones not explicitly set. + // Those have values like undefined, null, 0, false, "" or "inherit". + if (val && val !== "inherit") { + ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse(val, "attribute"); + } + } + } + ret += close; + + // Show content of TextNode or CDATASection + if (node.nodeType === 3 || node.nodeType === 4) { + ret += node.nodeValue; + } + + return ret + open + "/" + tag + close; + }, + // function calls it internally, it's the arguments part of the function + functionArgs: function (fn) { + var args, + l = fn.length; + + if (!l) { + return ""; + } + + args = new Array(l); + while (l--) { + // 97 is 'a' + args[l] = String.fromCharCode(97 + l); + } + return " " + args.join(", ") + " "; + }, + // object calls it internally, the key part of an item in a map + key: quote, + // function calls it internally, it's the content of the function + functionCode: "[code]", + // node calls it internally, it's an html attribute value + attribute: quote, + string: quote, + date: quote, + regexp: literal, + number: literal, + "boolean": literal + }, + // if true, entities are escaped ( <, >, \t, space and \n ) + HTML: false, + // indentation unit + indentChar: " ", + // if true, items in a collection, are separated by a \n, else just a space. + multiline: true + }; + + return jsDump; + }()); + + /* + * Javascript Diff Algorithm + * By John Resig (http://ejohn.org/) + * Modified by Chu Alan "sprite" + * + * Released under the MIT license. + * + * More Info: + * http://ejohn.org/projects/javascript-diff-algorithm/ + * + * Usage: QUnit.diff(expected, actual) + * + * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick brown fox jumped jumps over" + */ + QUnit.diff = (function () { + /*jshint eqeqeq:false, eqnull:true */ + function diff(o, n) { + var i, + ns = {}, + os = {}; + + for (i = 0; i < n.length; i++) { + if (!hasOwn.call(ns, n[i])) { + ns[n[i]] = { + rows: [], + o: null + }; + } + ns[n[i]].rows.push(i); + } + + for (i = 0; i < o.length; i++) { + if (!hasOwn.call(os, o[i])) { + os[o[i]] = { + rows: [], + n: null + }; + } + os[o[i]].rows.push(i); + } + + for (i in ns) { + if (hasOwn.call(ns, i)) { + if (ns[i].rows.length === 1 && hasOwn.call(os, i) && os[i].rows.length === 1) { + n[ns[i].rows[0]] = { + text: n[ns[i].rows[0]], + row: os[i].rows[0] + }; + o[os[i].rows[0]] = { + text: o[os[i].rows[0]], + row: ns[i].rows[0] + }; + } + } + } + + for (i = 0; i < n.length - 1; i++) { + if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && + n[i + 1] == o[n[i].row + 1]) { + + n[i + 1] = { + text: n[i + 1], + row: n[i].row + 1 + }; + o[n[i].row + 1] = { + text: o[n[i].row + 1], + row: i + 1 + }; + } + } + + for (i = n.length - 1; i > 0; i--) { + if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && + n[i - 1] == o[n[i].row - 1]) { + + n[i - 1] = { + text: n[i - 1], + row: n[i].row - 1 + }; + o[n[i].row - 1] = { + text: o[n[i].row - 1], + row: i - 1 + }; + } + } + + return { + o: o, + n: n + }; + } + + return function (o, n) { + o = o.replace(/\s+$/, ""); + n = n.replace(/\s+$/, ""); + + var i, pre, + str = "", + out = diff(o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/)), + oSpace = o.match(/\s+/g), + nSpace = n.match(/\s+/g); + + if (oSpace == null) { + oSpace = [" "]; + } + else { + oSpace.push(" "); + } + + if (nSpace == null) { + nSpace = [" "]; + } + else { + nSpace.push(" "); + } + + if (out.n.length === 0) { + for (i = 0; i < out.o.length; i++) { + str += "" + out.o[i] + oSpace[i] + ""; + } + } + else { + if (out.n[0].text == null) { + for (n = 0; n < out.o.length && out.o[n].text == null; n++) { + str += "" + out.o[n] + oSpace[n] + ""; + } + } + + for (i = 0; i < out.n.length; i++) { + if (out.n[i].text == null) { + str += "" + out.n[i] + nSpace[i] + ""; + } + else { + // `pre` initialized at top of scope + pre = ""; + + for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { + pre += "" + out.o[n] + oSpace[n] + ""; + } + str += " " + out.n[i].text + nSpace[i] + pre; + } + } + } + + return str; + }; + }()); + +// For browser, export only select globals + if (typeof window !== "undefined") { + extend(window, QUnit.constructor.prototype); + window.QUnit = QUnit; + } + +// For CommonJS environments, export everything + if (typeof module !== "undefined" && module.exports) { + module.exports = QUnit; + } + + +// Get a reference to the global object, like window in browsers +}((function () { + return this; +})())); \ No newline at end of file diff --git a/src/database/initialize.sql b/src/main/webapp/status.taobao similarity index 100% rename from src/database/initialize.sql rename to src/main/webapp/status.taobao diff --git a/src/main/webapp/systembusy.html b/src/main/webapp/systembusy.html new file mode 100644 index 000000000..5754f71af --- /dev/null +++ b/src/main/webapp/systembusy.html @@ -0,0 +1,11 @@ + + + + + + + +系统繁忙,系统比你都忙。请谅解。
      快去 GitHub Issues 开贴提问... +木有设计师,开发又懒...所以这个页面酱紫 + + \ No newline at end of file diff --git a/src/main/webapp/tcom/const.inc.vm b/src/main/webapp/tcom/const.inc.vm new file mode 100644 index 000000000..de4369d53 --- /dev/null +++ b/src/main/webapp/tcom/const.inc.vm @@ -0,0 +1,100 @@ +#*** + * 该文件主要用于定义前端页面常量、请求action地址等 + * 建议前端定义的常量以f(f-front)开头。如:$fFoobar + *# +##----------------------前端定义的常量------------------------------- +## 引号 +#set($dQuote = '"') +#set($sQuote = "'") +## 精确到秒 +#set($timeFormat = 'yyyy-MM-dd HH:mm:ss') +## 精确到天 +#set($dateFormat = 'yyyy-MM-dd') +## 时间戳 +#set($timeStamp = '20151111.v0.14.0') +##----------------------页面请求action地址------------------------------- +## 配置工程的上下文路径 +#set($projectContext = "$!link.getContextPath()") +##set($projectContext = "$!link.getContextPath()/rap") +## 配置静态资源请求的路径 +#set($staticRoot = "$!projectContext/stat") +#set($newUrl = { + "home":"$projectContext/org/index.do" +}) +#set($accountUrl = { + "login":"$projectContext/account/login.do", + "doLogin":"$projectContext/account/doLogin.do", + "doLogout":"$projectContext/account/doLogout.do", + "register":"$projectContext/account/register.do", + "doRegister":"$projectContext/account/doRegister.do", + "myAccount":"$projectContext/account/myAccount.do", + "mySetting":"$projectContext/account/mySetting.do", + "updateProfile":"$projectContext/account/updateProfile.do", + "doUpdateProfile":"$projectContext/account/doUpdateProfile.do", + "doChangeProfile":"$projectContext/account/doChangeProfile.do", + "myHome":"$projectContext/org/index.do", + "logData":"$projectContext/account/logData.do" +}) +#set($projectUrl = { + "myProjectList":"$projectContext/project/myProjectList.do", + "removeProject":"$projectContext/project/removeProject.do", + "addProject":"$projectContext/project/addProject.do", + "myProject":"$projectContext/project/myProject.do", + "projectDetailAjax":"$projectContext/project/projectDetailAjax.do", + "addOrUpdateProject":"$projectContext/project/addOrUpdateProject.do", + "allProductlineList":"$projectContext/org/productline.do", + "updateReleatedIds":"$projectContext/project/updateReleatedIds.do" +}) +#set($workspaceUrl = { + "myWorkspace":"$projectContext/workspace/myWorkspace.do", + "loadWorkspace":"$projectContext/workspace/loadWorkspace.do", + "getModuleHtmlAjax":"$projectContext/workspace/getModuleHtmlAjax.do", + "updateCurrentSave":"$projectContext/workspace/updateCurrentSave.do", + "updateSave":"$projectContext/workspace/updateSave.do", + "querySave":"$projectContext/workspace/querySave.do", + "removeSave":"$projectContext/workspace/removeSave.do", + "checkIn":"$projectContext/workspace/checkIn.do", + "checkOut":"$projectContext/workspace/checkOut.do", + "ping":"$projectContext/workspace/ping.do", + "queryVersion":"$projectContext/workspace/queryVersion.do", + "switchVersion":"$projectContext/workspace/switchVersion.do", + "lock":"$projectContext/workspace/lock.do", + "unlock":"$projectContext/workspace/unlock.do", + "export":"$projectContext/workspace/export.do" +}) +#set($platformUrl = { + "home":"$projectContext/platform/home.do", + "document":"$projectContext/platform/document.do", + "about":"$projectContext/platform/about.do", + "status":"$projectContext/platform/status.do", + "help":"$!projectContext/platform/help.do", + "test":"$!projectContext/platform/test.do", + "doc":"https://github.com/thx/RAP/wiki/home_cn", + "study":"http://thx.github.io/RAP/study.html", + "log":"$!projectContext/platform/log.do", + "realtimeUpdate":"$!projectContext/platform/realtimeUpdate.do", + "teamLog":"$!projectContext/platform/teamLog.do" +}) +#set($testerUrl = { + "pageTester":"$projectContext/tester/pageTester.do" +}) +#set($teamUrl = { + "teams" : "$projectContext/org/team/teams.do", + "manage":"$projectContext/org/team/manage.do" +}) + +#set($groupUrl = { + "group" : "$projectContext/org/group.do" +}) + +#set($productlineUrl = { + "productline":"$projectContext/org/productline.do" +}) + +#set($mockUrl = { + "queryMockData":"$projectContext/mock/queryMockData.do" +}) + +#set($openAPI = { + "queryRAPModel" : "$projectContext/api/queryRAPModel.do" +}) \ No newline at end of file diff --git a/src/main/webapp/tcom/mod.macro.vm b/src/main/webapp/tcom/mod.macro.vm new file mode 100644 index 000000000..ad6508223 --- /dev/null +++ b/src/main/webapp/tcom/mod.macro.vm @@ -0,0 +1,61 @@ +#macro (includeEditorStatic) + + + + +#end + +#macro (createEditor $suffix $textareaName $editorWidth $editorHeight $selfInit) + #set($editorAreaWidth = $editorWidth - 10) +
      + +
      +
      +
      +
      + + + + +
      +#end \ No newline at end of file diff --git a/WebContent/tcom/report.macro.vm b/src/main/webapp/tcom/report.macro.vm similarity index 58% rename from WebContent/tcom/report.macro.vm rename to src/main/webapp/tcom/report.macro.vm index ddead9a4b..291c8cc80 100644 --- a/WebContent/tcom/report.macro.vm +++ b/src/main/webapp/tcom/report.macro.vm @@ -1,7 +1,7 @@ #parse('/tcom/mod.macro.vm') #** - * @desc : 报表组件 + * @desc : 报表组件 * @param {String} id 标识, 相应的textarea和checkbox的id为textarea-{id}, checkbox-{id} * @param {String} checkboxName * @param {String} editorName @@ -13,88 +13,94 @@ *# #set($editorNO = 0) #macro (reportCom $id $checkboxName $editorName $title $type $data $content $isEnabled) -#if ($isEnabled) - #set( $isDisabled = false ) -#else - #set( $isDisabled = true ) -#end + #if ($isEnabled) + #set( $isDisabled = false ) + #else + #set( $isDisabled = true ) + #end -#if ($type == "") - #set( $hasFlash = false) -#else - #set( $hasFlash = true) -#end + #if ($type == "") + #set( $hasFlash = false) + #else + #set( $hasFlash = true) + #end -#if (!$flag) - #set( $flag = true ) - #initReportCom() -#end - - - -

      $!title

      -#if ($hasFlash)
      - -#end + #if (!$flag) + #set( $flag = true ) + #initReportCom() + #end + + + +

      $!title

      + #if ($hasFlash) +
      + + #end
       
      - #createEditor("$id" "$editorName" 650 215 true) + #createEditor("$id" "$editorName" 650 215 true) -#set($editorNO = $editorNO + 1) + #set($editorNO = $editorNO + 1) #end #macro (initReportCom) - #includeEditorStatic +#includeEditorStatic + + + + #if(!$hide) + + #end +
      +#end +## master page end +#macro (bodyEnd) +
      +

      + - + 人在使用 RAP,今日 Mock 服务被调用 + - + + 旺旺群支持:582755829 + + 感谢阿里云赞助 + + +

      +
      + +
      + + + + + + + +#end diff --git a/src/main/webapp/tcom/utils.macro.vm b/src/main/webapp/tcom/utils.macro.vm new file mode 100644 index 000000000..fa60da238 --- /dev/null +++ b/src/main/webapp/tcom/utils.macro.vm @@ -0,0 +1,577 @@ +#parse('/tcom/const.inc.vm') + + +## 权限字符串 + +#macro (getRoleStr $roleId)#if($roleId==1)超级管理员#elseif($roleId==2)管理员#else 普通用户 #end #end + +## 分页 +#macro (pager $curPagerNum $pagerSize $totalNum $url) +

      + #set($totalPage = ($totalNum - 1) / $pagerSize + 1) + + #set($currentPager = $curPagerNum) + + #set($pagerStart = 1) + #set($pagerEnd = $totalPage) + + #if($currentPager >= $totalPage) + #set($currentPager = $totalPage) + #set($pagerEnd = $totalPage) + #end + + #if($currentPager < 1) + #set($currentPager = 1) + #end + + #if($currentPager > 1) + 首页 + «上一页 + #else + 首页 + «上一页 + #end + + #if($totalPage > 11) + #if($currentPager > 5) + #set($pagerStart = $currentPager - 5) + #set($pagerEnd = $currentPager + 5) + #else + #set($pagerEnd = 10) + #end + #if($pagerEnd > $totalPage) + #set($pagerStart = $totalPage - 9) + #set($pagerEnd = $totalPage) + #end + #end + + #foreach($item in [${pageStart}..${pageEnd}]) + #if($item == $currentPager) + $item + #else + $item + #end + #end + + #if($currentPager < $totalPage) + 下一页» + 尾页 + #else + 下一页» + 尾页 + #end + 跳转 +       共$!totalPage页,$!totalNum条记录   +

      + #if($totalNum == 0) + + #end +#end +#macro (table $lstConfigs $data $options) +#* + * 表格控件 + * + * @params {List} $lstConfigs [必填]列表表头数据,列样式(宽度,自定义属性等) + * @params {List} $data [必填]表格内容数据 + * @params {List} $options 表格其他参数 + * lstTitles {list} [选填]表头, 可以由RD设置, 一般情况下就取${lstConfigs}的值 + * checkbox {String} [选填]用户自行选择的checkbox的name值 + * checkboxVal {String} [选填]用户自行选择的checkbox的id值 + * hasOp {Boolean} [选填]参数为true, 表示有操作列 + * custom {Boolean} [选填]全选是否可以针对整表,依赖于选项checkbox + * style {String} [选填]表格采用的样式, 默认为"default" + * url {String} [选填]分页请求的URL, 默认为"" + * id {String} [选填]列表的id, 命名建议[0-9a-zA-Z_]+ + * needPrint {Boolean} [选填]是否需要打印, 默认不需要打印 + * page {list} [选填]每页记录数 + * @todo 修改id - 固定 + *# + #if($options.id) + #set($tbId = $options.id) + #else + #if($tbId) + #set($tbId = $tbId + 1) + #else + #set($tbId = 0) + #end + #end + + #set($tbNoData = false) + #if(!$data || $data.size() == 0) + #set($tbNoData = true) + #end + + + + #if ($pager || $options.pager) +
      + #if($options.pager) + #pager($options.pager.curPagerNum + $options.pager.pagerSize + $options.pager.totalRecNum + $options.url) + #else + #pager($pager.curPagerNum + $pager.pagerSize + $pager.totalRecNum + $options.url) + #end + + #end + +#end +#** + * @desc : 适用于数据确定的下拉列表、单选组、多选组,数据类型为List型 + * @param {String} name 表单项name属性值 + * @param {List} data 填充表单项value和label属性的值 + * @param {String} curVal 当前选中值 + * @param {String} flag 哪个类型的表单项(radio/select/checkbox) + * @param {String} attrs 表单项其它的属性 + *# +#set($fieldIndex = 0) +#macro (list $name $data $curVal $flag $attrs) + #if($flag == "select") + + #elseif($flag == "checkbox") + #foreach($item in $data) + + #set($fieldIndex = $fieldIndex + 1) + #end + #elseif($flag == "radio") + #foreach($item in $data) + + #set($fieldIndex = $fieldIndex + 1) + #end + #end +#end +#** + * @desc : 层级下拉框 + * @param {String} fName 下拉框fName属性值 + * @param {List} fData 填充下拉框value和label属性及层级关系的值 + * @param {String} fCurVal 当前选中值 + * @param {String} fAttrs 表单项其它的属性 + *# +#macro (levelSelect $fName $fData $fCurVal $fAttrs) + +#end +#** + * @desc : 层级下拉框(数据源无序) + * @param {String} fName 下拉框fName属性值 + * @param {List} fData 填充下拉框value和label属性及层级关系的值 + * @param {String} fCurVal 当前选中值 + * @param {String} fAttrs 表单项其它的属性 + *# +#macro (levelSelect2 $fName $fData $fCurVal $fAttrs) + + +#end +#** + * @desc : 统一引入错误提示 + *# +#macro (globalMsg) + #if($errors && $errors.globalMsg) +
      +
      +
      +
      +
      $!errors.globalMsg
      +
      +
      +
      +
      + #end +#end +#** + * @desc : 单日历 + * @param {String} name 表单项name属性值 + * @param {String} value 默认时间 + * @param {list} options 可选项 支持的参数有 range设定可操作范围 ecid设置ecid + * @demo #singleCal("cal-demo" "2012-01-12") + *# +#macro (singleCal $name $value $options) + +#end +#** + * @desc : 双日历 + * @param {String} name 表单项name属性值 + * @param {String} value 默认时间 + * @param {list} options 可选项 支持的参数有 range设定可操作范围 ecid设置ecid + * @demo #rangeCal("2012-01-11" "2012-02-23") + *# +#macro (rangeCal $bVal $eVal $options) + +#end +#** + * @desc : 浮动层开头部分代码 + * @param {String} ecId ecui控件Id,在ecFloater.show(ecId)调用使用 + * @param {String} title 浮动层标题名称 + * @param {Number} width 浮动层的宽度值 + * @param {Number} height 浮动层的高度值 + * @demo + * #startFloater("floater1" "标题" 500 300) + * 浮动层里面的HTML代码 + * #endFloater + *# +#macro (startFloater $ecId $title $width $height) + +#end +#** + * @desc : 初始本地存储模块 + * @param {String} ecId 可选,默认为localStorage。ecui控件Id,用户获取ecui本地存储控件。 + * @demo #storageInit() 或 #storageInit("myLocalStorage") + *# +#macro (storageInit $ecId) + #if(!$ecId) + #set($ecId = "localStorage") + #end +
      +#end +#** + * @desc : 提交查询表单时本地保存内容 + * @param {String} ecId 可选,默认为localStorage。ecui控件Id,用户获取ecui本地存储控件。 + * @demo #storageSave() 或 #storageSave("myLocalStorage") + *# +#macro (storageSave $ecId) + #if(!$ecId) + #set($ecId = "localStorage") + #end +this.localDataId.value = ecui.get('$!ecId').save(this); +#end +#** + * @desc : navBar 方案制作导航条 + *# +#macro (navBar $curTab $curCTab) + #set($commURL = "$common.stepController?type=current&schemeId=$!schemeId¤tStep=") + + + +#end + + +#macro(breadcrumb $styles) + +#end + +#** + * @desc : includeNewRapStatic 新版统一引入静态资源 + *# +#macro (includeNewRapStatic) + + + + + + + + + + + + + + + + + + + + + +#end \ No newline at end of file diff --git a/src/main/webapp/tester/pageTester.js b/src/main/webapp/tester/pageTester.js new file mode 100644 index 000000000..c0c17c770 --- /dev/null +++ b/src/main/webapp/tester/pageTester.js @@ -0,0 +1,249 @@ +if (!window.console) { + window.console = { + log: function () { + }, + warn: function () { + }, + err: function () { + } + }; +} + +function wrapHref(url) { + return '' + url + ''; +} + +YUI().use('handlebars', 'node', 'event', 'jsonp', 'jsonp-url', 'json-stringify', 'datasource', function (Y) { + window.Y = Y; + var source = Y.one("#resBoard-template"), + divLog = document.getElementById("divResBoardLog"), + ERROR = -1, WARN = -2, // log type + LIGHT_GRAY = '#999', RED = 'red', ORANGE = 'orange', // colors + _rootUrl = '', + logLine = 1; + + log('tester initializing...'); + Y.timeLog = {}; + Y.all('.form').each(function (form) { + + // form start + form.one('.btn-run').on('click', function (e) { + Y.one('#divResBoardJson').setHTML('加载中,请稍后...'); + var url = ''; + var qArr = []; + var i = 0; + var fields = form.all('.field'); + var baseUrl = Y.one('#txtRootPath').get('value'); + var baseUrlOrigin = Y.one('#txtRootPath').get('value'); + var rapUrl = RAP_ROOT; + var path = form.getAttribute('path'); + + if (~path.indexOf('http')) { + path = path.substring(7); + path = path.substring(path.indexOf("/")); + } + + if (path[0] !== '/') { + path = '/' + path; + } + + baseUrl += path; + rapUrl += path; + fields.each(function (field) { + var name = field.get('name'), + value = field.get('value'); + qArr[i++] = name + '=' + encodeURIComponent(value); + }); + + if (!~baseUrl.indexOf('http://')) { + baseUrl = "http://" + baseUrl; + } + if (!~rapUrl.indexOf('http://')) { + rapUrl = "http://" + rapUrl; + } + + url = baseUrl + (baseUrl.indexOf('?') === -1 ? '?' : '&') + qArr.join('&'); + url = urlProcess(url); + log('request starting, url: ' + color(wrapHref(url), LIGHT_GRAY)); + Y.timeLog.time = new Date().getTime(); + try { + Y.jsonp(rapUrl, { + on: { + success: function (response) { + testResHandler.apply(this, [response]) + }, + timeout: function () { + log(color('timeout', RED) + '... so long time to response!'); + }, + failure: function (e) { + console.log(color('error occurred!', RED) + color(', detail:' + e.errors[0].error, LIGHT_GRAY)); + } + }, + timeout: 10000 + }); + } catch (ex) { + alert(ex); + } + }); + // form end + }); + + + function sortObj(obj) { + if (!obj) { + return obj; + } + if (jQuery.isArray(obj)) { + var newArray = []; + for (var k = 0; k < obj.length; k++) { + newArray.push(sortObj(obj[k])); + } + return newArray; + } else if (jQuery.isPlainObject(obj)) { + var result = {}, keys = []; + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + keys.push(prop); + } + } + keys = keys.sort(); + for (var i = 0, l = keys.length; i < l; i++) { + result[keys[i]] = sortObj(obj[keys[i]]); + } + return result; + } else { + return obj; + } + } + + function testResHandler(response, form, btn) { + var obj = response; + var jsonString; + + + var path = Y.one('#txtRootPath').get('value'); + obj = sortObj(obj); + if (btn != 'rule' && path.indexOf('mockjs') != -1) { + obj = Mock.mock(obj); + } + + jsonString = JSON.stringify(obj, function (key, val) { + if (typeof val === 'function') { + return ""; + } else { + return val; + } + }); + + var beginTime = Y.timeLog.time; + if (!beginTime) return; + var endTime = new Date().getTime(); + log('request end in:' + color(endTime - beginTime, RED) + 'ms.'); + Y.one('#divResBoardJson').setHTML(jsonString.formatJS()); + + return obj; + } + + function log(msg, type) { + var arr = [], + i = 0; + arr[i++] = color(logLine++, ORANGE); + if (type === ERROR) { + arr[i++] = color('  ERR!', RED); + } + arr[i++] = '  ' + msg + "
      "; + arr[i++] = divLog.innerHTML; + divLog.innerHTML = arr.join(''); + } + + function color(t, c) { + return '' + t + ''; + } + + function initUrl() { + var path = Y.one('#txtRootPath').get('value'), + root = ''; + if (path.indexOf('/') != -1) { + root = 'http://' + path.substring(0, path.indexOf('/')); + } + + _rootUrl = root; + } + + + initUrl(); + + Y.one('#txtRootPath').on('change', initUrl); + + + setTimeout(function () { + var logContainer = $('#divResBoardLog'); + $(document).delegate('#up-trigger', 'click', function () { + logContainer.animate({ + 'height': 500 + }); + }).delegate('#expand-trigger', 'click', function () { + logContainer.animate({ + 'width': '98%' + }); + $('body').css('padding-bottom', '110px'); + }).delegate('#down-trigger', 'click', function () { + logContainer.animate({ + 'height': 100 + }); + }).delegate('#close-trigger', 'click', function () { + logContainer.hide('slow'); + $('#show-trigger').show('slow'); + }).delegate('#show-trigger', 'click', function () { + logContainer.show('slow'); + $('#show-trigger').hide('slow'); + }); + }, 500); + + $('.btn-run-real').on('click', function (e) { + $(this).toggleClass('active'); + $(this).parents('.tools').find('.real-options').toggle(); + }); + + $('.btn-run-do-real').on('click', function (e) { + $('#divResBoardJson').html('正在进行测试,请稍候...'); + }); + log('tester ready.'); + + function urlProcess(url) { + url = url.replace(/[{}]/g, ""); + url = url.replace(/\/:[^\/]*/g, "/100"); + + // remove repeated parameters + if (url && url.indexOf("?") > -1) { + var baseUrl = url.substring(0, url.indexOf("?")); + var paramString = url.substring(url.indexOf("?") + 1); + var paramArray = paramString.split("&"); + var paramObj = {}; + var i, key, value, item; + for (i = 0; i < paramArray.length; i++) { + item = paramArray[i]; + key = item.split("=")[0]; + value = item.split("=")[1]; + if (key && value) { + paramObj[key] = value; + } + } + paramArray = []; + for (key in paramObj) { + if (paramObj.hasOwnProperty(key)) { + paramArray.push(key + "=" + paramObj[key]); + } + } + url = baseUrl + "?" + paramArray.join("&"); + } + + + if (url.indexOf('reg:') !== -1) { + log(color('控制台暂时不支持正则RESTful API(也就是包含reg:的URL)', RED)); + } + + return url; + } + +}); diff --git a/src/main/webapp/tester/pageTester.vm b/src/main/webapp/tester/pageTester.vm new file mode 100644 index 000000000..dff4c32fb --- /dev/null +++ b/src/main/webapp/tester/pageTester.vm @@ -0,0 +1,101 @@ + + + #parse('/tcom/template.rap.vm') + + + RAP - $!utils.escapeInH($page.name)控制台 + + + #includeNewRapStatic + + + + + + + +#bodyNewStart +
      +

      +    + $!utils.escapeInH($page.name) 页面控制台 +

      + +
      + + +
      +
      + +
      + #foreach($action in $page.actionList) +
      +
      + + +
      +
      请求标识: $action.id
      +
      请求地址: $!utils.escapeInH($action.requestUrl)
      +
      +
      + #foreach($para in $action.requestParameterList) +
      + $!utils.escapeInH($para.identifier) + + 说明 +
      +
      - 变量名:$!utils.escapeInH($para.name)
      +
      - 备注:$!utils.escapeInH($para.remark)
      +
      +
      +
      + #end +
      +
      + +
      +
      +
      + #end +
      +
      +
      +
      ready
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      +
      + + +
      +#bodyEnd + + + + + diff --git a/WebContent/tester/template/pageTester.tbl.html b/src/main/webapp/tester/template/pageTester.tbl.html similarity index 100% rename from WebContent/tester/template/pageTester.tbl.html rename to src/main/webapp/tester/template/pageTester.tbl.html diff --git a/src/main/webapp/unit-tests/errors/bugfix-list.js b/src/main/webapp/unit-tests/errors/bugfix-list.js new file mode 100644 index 000000000..d1a7a730c --- /dev/null +++ b/src/main/webapp/unit-tests/errors/bugfix-list.js @@ -0,0 +1,114 @@ +module('bugfix-BOSN', { + setup: function () { + this.oldProjectId = RAP.getProjectId(), + this.oldMode = RAP.getMode(); + // 项目ID设置为“Bosn修复BUG专用”的ID + RAP.setProjectId(189); + // 拦截所有请求 + RAP.setMode(1); + }, + teardown: function () { + RAP.setProjectId(this.oldProjectId); + RAP.setMode(this.oldMode); + } +}); + +test('dataTypeBug fix', function () { + stop(); + KISSY.use('io', function (S, IO) { + IO({ + url: 'dataTypeBug.do', + dataType: 'json', + success: function (data) { + ok(KISSY.isArray(data.numberArray), 'numberArray is array'); + ok(KISSY.isNumber(data.numberArray[0]), 'numberArray[0] is number'); + ok(KISSY.isArray(data.stringArray), 'stringArray is array'); + ok(KISSY.isString(data.stringArray[0]), 'stringArray[0] is string'); + start(); + } + }) + }) +}) + + +test('paramMockJsTemplate fix', function () { + stop(2); + KISSY.use('io', function (S, IO) { + IO({ + url: 'paramMockJsTemplate.do', + dataType: 'json', + success: function (data) { + console.log(data); + equal(data.result, 'page is 1008, num is okokok', 'data origin: page is 1008, num is okokok'); + equal(data.result2, '', 'data origin: 1') + start(1); + + IO({ + url: 'paramMockJsTemplate.do', + data: { + num: 111, + page: 222 + }, + dataType: 'json', + success: function (data) { + equal(data.result, 'page is 222, num is 111', 'data changed: page is 222, num is 111'); + equal(data.result2, 222, 'data changed: 222') + start(1); + } + }) + } + }) + }) +}) + + +test('unicode fix', function () { + stop(); + KISSY.use('io', function (S, IO) { + IO({ + url: 'unicode.do', + dataType: 'json', + success: function (data) { + ok(KISSY.isString(data.string1), 'params are string'); + ok(KISSY.isString(data.string2), 'params are string'); + ok(KISSY.isString(data.string3), 'params are string'); + equal(data.string1, '1233打发打发..*(&(@#*&@(*#&*(', 'string1 is ok'); + equal(data.string2, '9832749802374098324782937flakdsjfldaskjf啊死了都快放假啊老师的看风景阿斯蒂芬(*&(*&', 'string2 is ok'); + equal(data.string3, '哈哈深度开发回家啊说的发来了空间啊说的饭卡上的减肥快乐的撒娇放假', 'string3 is ok'); + start(); + } + }) + }) +}) + + +test('copyFunc fix', function () { + stop(); + KISSY.use('io', function (S, IO) { + IO({ + url: 'copyFunc', + dataType: 'json', + success: function (data) { + console.log(data); + ok(KISSY.isArray(data.obj), 'data.obj is array'); + ok(KISSY.isArray(data.objCopy), 'data.objCopy is array'); + var a = data.obj[0], b = data.objCopy[0]; + for (var prop in a) { + ok(prop in b, 'b has ' + prop + ' too'); + } + for (var prop in b) { + ok(prop in a, 'a has ' + prop + ' too'); + } + for (var prop in a.item) { + ok(prop in b.item, 'b.item has ' + prop + ' too'); + equal(typeof a.item[prop], typeof b.item[prop], 'value type is the same.') + } + for (var prop in b.item) { + ok(prop in a.item, 'a.item has ' + prop + ' too'); + equal(typeof a.item[prop], typeof b.item[prop], 'value type is the same.') + } + start(); + } + }) + }) +}) diff --git a/src/main/webapp/unit-tests/errors/rap-plugin-error.js b/src/main/webapp/unit-tests/errors/rap-plugin-error.js new file mode 100644 index 000000000..173304cd8 --- /dev/null +++ b/src/main/webapp/unit-tests/errors/rap-plugin-error.js @@ -0,0 +1,46 @@ +module('bugfix'); + +test('without io: KISSY.use("node", function(S, A) {})', function () { + stop(4); + KISSY.use('node', function (S, Node) { + start(1); + ok(S.config, 'still has S.config'); + }); + + KISSY.use('node, io', function (S, Node) { + start(1); + ok(S.config, 'still has S.config'); + }); + + KISSY.use('node, io', function (S, Node, IO) { + start(1); + ok(S.config, 'still has S.config'); + }); + + KISSY.use('node, io, node', function (S, Node, IO, Node) { + start(1); + ok(S.config, 'still has S.config'); + }); +}) + +test('KISSY.add using IO', function () { + stop(); + KISSY.add('tester/module', function (S, Node, IO) { + ok(KISSY.io != undefined, 'got KISSY.io'); + ok(KISSY.ajax != undefined, 'got KISSY.ajax'); + ok(KISSY.IO != undefined, 'got KISSY.IO'); + + IO({ + url: '/base', + dataType: 'json', + success: function (data) { + equal(typeof data.a, 'number', 'get data ok'); + start(); + } + }) + }, {requires: ['node', 'io']}) + + KISSY.use('tester/module', function (S, A) { + + }) +}) \ No newline at end of file diff --git a/src/main/webapp/unit-tests/getrule/base.js b/src/main/webapp/unit-tests/getrule/base.js new file mode 100644 index 000000000..f0121cdc4 --- /dev/null +++ b/src/main/webapp/unit-tests/getrule/base.js @@ -0,0 +1,39 @@ +module('get-mockjs-rule'); + +test('jQuery - getMockjsRule - /mockjs/projectId/action', function () { + stop(); + $.ajax({ + type: "get", + url: "/mockjs/114/mockjs/base", + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok('a|1-10' in data, 'mockjs rule: a|1-10 is in data'); + ok(KISSY.isNumber(data['a|1-10']), 'and dataType is number'); + }, + error: function () { + } + }); +}); + + +test('KISSY - getMockjsRule - /mockjs/projectId/action', function () { + stop(); + var base = '/mockjs/114/mockjs/base'; + KISSY.oldUse('io', function (S, IO) { + IO({ + type: "get", + url: base, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok('a|1-10' in data, 'mockjs rule: a|1-10 is in data'); + ok(KISSY.isNumber(data['a|1-10']), 'and dataType is number'); + }, + error: function () { + } + }) + }); +}); \ No newline at end of file diff --git a/src/main/webapp/unit-tests/getruledata/base.js b/src/main/webapp/unit-tests/getruledata/base.js new file mode 100644 index 000000000..74b5cbe18 --- /dev/null +++ b/src/main/webapp/unit-tests/getruledata/base.js @@ -0,0 +1,127 @@ +module('get-mockjs-data'); + +test('jQuery.ajax[ORIGIN] - getMockjsData - get /mockjsdata/projectId/action', function () { + stop(); + $.ajax({ + type: "get", + url: "/mockjsdata/114/mockjs/base", + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok('a' in data, 'property exists'); + ok(KISSY.isNumber(data.a), 'a is number'); + ok(data.a >= 1 && data.a <= 10, 'a between 1 and 10'); + }, + error: function () { + } + }); +}); + + +test('jQuery.ajax[RAPPED] - getMockjsData - Action : /mockjs/base', function () { + stop(); + equal(RAP.getPrefix(), '/mockjs/', 'PREFIX is /mockjs/'); + $.rapAjax({ + type: "get", + url: "/mockjs/base", + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok('a' in data, 'mockjs : a is in data'); + ok(KISSY.isNumber(data['a']), 'and dataType is number'); + }, + error: function () { + } + }); +}); + + +test('jQuery.ajax[RAPPED] - getMockjsData - Prefix: /mockjsdata/, Action:/mockjs/base', function () { + stop(); + equal(RAP.getPrefix(), '/mockjs/', 'PREFIX is /mockjs/'); + var old = RAP.getPrefix(); + RAP.setPrefix('/mockjsdata/') + $.rapAjax({ + type: "get", + url: "/mockjs/base", + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + RAP.setPrefix(old); + start(); + ok('a' in data, 'mockjs : a is in data'); + ok(KISSY.isNumber(data['a']), 'and dataType is number'); + }, + error: function () { + } + }); +}); + + +test('KISSY[ORIGIN] - getMockjsData - get /mockjsdata/projectId/action', function () { + stop(); + KISSY.oldUse('io', function (S, IO) { + IO({ + type: "get", + url: "/mockjsdata/114/mockjs/base", + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok('a' in data, 'property exists'); + ok(KISSY.isNumber(data.a), 'a is number'); + ok(data.a >= 1 && data.a <= 10, 'a between 1 and 10'); + }, + error: function () { + } + }) + }); +}); + + +test('KISSY[RAPPED] - getMockjsData - Action: /mockjs/base', function () { + stop(); + var base = '/mockjs/base'; + KISSY.use('io', function (S, IO) { + IO({ + type: "get", + url: base, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok('a' in data, 'property exists'); + ok(KISSY.isNumber(data.a), 'a is number'); + ok(data.a >= 1 && data.a <= 10, 'a between 1 and 10'); + }, + error: function () { + } + }) + }); +}); + +test('KISSY[RAPPED] - getMockjsData - Prefix: /mockjsdata/, Action: /mockjs/base', function () { + stop(); + var base = '/mockjs/base'; + KISSY.use('io', function (S, IO) { + var old = RAP.getPrefix(); + RAP.setPrefix('/mockjsdata/'); + IO({ + type: "get", + url: base, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok('a' in data, 'property exists'); + ok(KISSY.isNumber(data.a), 'a is number'); + ok(data.a >= 1 && data.a <= 10, 'a between 1 and 10'); + }, + error: function () { + } + }) + RAP.setPrefix(old); + }); +}); \ No newline at end of file diff --git a/src/main/webapp/unit-tests/getruledata/datatypes.js b/src/main/webapp/unit-tests/getruledata/datatypes.js new file mode 100644 index 000000000..adb8a0c24 --- /dev/null +++ b/src/main/webapp/unit-tests/getruledata/datatypes.js @@ -0,0 +1,147 @@ +module('mockjs-data-validation'); + +test('DATA_TYPES: exist and type', function () { + stop(); + var base = '/datatypes'; + KISSY.use('io', function (S, IO) { + IO({ + type: "get", + url: base, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + + ok('boolean' in data, 'boolean in data'); + ok('string' in data, 'string in data'); + ok('object' in data, 'object in data'); + ok('number' in data, 'number in data'); + + ok(KISSY.isNumber(data.number), 'number is number'); + ok(KISSY.isObject(data.object), 'object is object'); + ok(KISSY.isString(data.string), 'string is string'); + ok(KISSY.isBoolean(data.boolean), 'boolean is boolean'); + var obj = data.object; + ok('d' in obj, 'sub prop'); + + ok(KISSY.isNumber(obj.a), 'sub prop is number'); + ok(KISSY.isString(obj.b), 'sub prop is string'); + ok(KISSY.isBoolean(obj.c), 'sub prop is boolean'); + ok(KISSY.isObject(obj.d), 'sub prop is object'); + + ok(obj.d.d1, 'd1 in obj.d'); + ok(KISSY.isNumber(obj.d.d1), 'obj.d.d1 is number'); + + ok('array_boolean' in data, 'array boolean in data'); + ok('array_string' in data, 'array string in data'); + ok('array_number' in data, 'array number in data'); + ok('array_object' in data, 'array object in data'); + + ok(KISSY.isBoolean(data.array_boolean[0]), 'booleans[0] is boolean'); + ok(KISSY.isString(data.array_string[0]), 'strings[0] is string'); + ok(KISSY.isNumber(data.array_number[0]), 'numbers[0] is number'); + ok(KISSY.isObject(data.array_object[0]), 'objects[0] is object'); + + var obj = data.array_object[0]; + ok('d' in obj, 'sub prop exist'); + ok(KISSY.isObject(obj.d), 'is object!'); + ok('d1' in obj.d, 'sub sub prop exist'); + ok(KISSY.isNumber(obj.d.d1), 'is number'); + }, + error: function () { + } + }) + }); +}); + + +test('DATA_TYPES: values', function () { + stop(); + var base = '/datatypes'; + KISSY.use('io', function (S, IO) { + IO({ + type: "get", + url: base, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + + ok(data.number >= 1 && data.number <= 20, 'number|1-20'); + ok(data.boolean === true || data.boolean === false, 'boolean is true or false'); + ok(/^B{1,5}$/.test(data.string), 'string is B{1-5}'); + + var obj = data.object; + ok('d' in obj, 'sub prop'); + + ok(obj.a >= 1 && obj.a <= 10, 'a|1-10'); + ok(/^A{3,5}$/.test(obj.b), 'string is A{3-5}'); + ok(obj.c === true || obj.c === false, 'sub prop is boolean'); + + ok(obj.d.d1 >= 3 && obj.d.d1 <= 10, 'obj.d.d1|3-10'); + + var arr = data.array_boolean; + ok(arr[0] === true, 'a[0] = true'); + ok(arr[1] === false, 'a[1] = false'); + + var arr = data.array_string; + ok(arr[0] == 'a', 'b[0] = a'); + ok(arr[1] == 'b', 'b[1] = b'); + ok(arr[2] == 'c', 'b[2] = c'); + + var arr = data.array_number; + ok(arr[0] == 1, 'b[0] = 1'); + ok(arr[1] == 2, 'b[1] = 2'); + ok(arr[2] == 3, 'b[2] = 3'); + + var arr = data.array_object; + ok(arr.length == 3, 'object length is 3'); + + var obj = data.array_object[0]; + ok(obj.a >= 3 && obj.a <= 7, 'a|3-7'); + ok(/^A{4}$/.test(obj.b), 'b is AAAA'); + ok(obj.c === true || obj.c === false, 'c is true or false'); + ok(obj.d.d1 >= 3 && obj.d.d1 <= 7, 'd.d1|3-7'); + }, + error: function () { + } + }) + }); +}); + +function propsIn(props, obj, name) { + for (var i = 0; i < props.length; i++) { + ok(props[i] in obj, props[i] + ' in ' + name); + } +} +test('DATA_TYPES: demo data from mockjs.com(import by JSON, Cool~)', function () { + stop(); + var base = '/mockjs/demo/from/site'; + KISSY.use('io', function (S, IO) { + IO({ + type: "get", + url: base, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok(data.data, 'data exists'); + ok(KISSY.isArray(data.data), 'data is array'); + ok(data.data.length >= 1 && data.data.length <= 10, 'data|1-10'); + var pick = data.data[0]; + propsIn(['cn', 'date', 'datetime', 'dummyimage', 'email', 'float1', 'float2', 'float3', + 'float4', 'grade1', 'grade2', 'img1', 'img2', 'method', 'param', 'published', 'repeat', 'size', + 'star', 'time'], pick, 'data[0]'); + equal(pick.id, 1, 'id is 1'); + if (data.data.length > 1) { + equal(data.data[1].id, 2, 'id increment'); + } + } + }) + }); +}); + +// TODO +// @mock=@value@prop test +// 各种mockjs的规则编辑测试 +// @mock=和直接写的测试 diff --git a/src/main/webapp/unit-tests/index.js b/src/main/webapp/unit-tests/index.js new file mode 100644 index 000000000..20fd0652c --- /dev/null +++ b/src/main/webapp/unit-tests/index.js @@ -0,0 +1,25 @@ +module('env confirm'); +test('no KISSY.io when kissy seed inited', function () { + ok(KISSY.io === undefined, 'KISSY.io is undefined when kissy seed loaded'); +}); + +var scripts = [ + 'getrule/base.js', + + 'utility/structureValidator.js', + + 'getruledata/base.js', + 'getruledata/datatypes.js', + + 'rap-plugin/base.js', + 'rap-plugin/jsapis.js', + 'rap-plugin/modes.js', + 'rap-plugin/whiteblack.js', + 'rap-plugin/for-seajs.js', + + 'errors/rap-plugin-error.js', + 'errors/bugfix-list.js' +]; + +loadScripts(scripts, function () { +}); diff --git a/src/main/webapp/unit-tests/prepare.js b/src/main/webapp/unit-tests/prepare.js new file mode 100644 index 000000000..c958c5569 --- /dev/null +++ b/src/main/webapp/unit-tests/prepare.js @@ -0,0 +1,22 @@ +var root = /unit-tests/; +RAP.setHost(window.location.host); + +function loadScript(s, callback) { + $.getScript(root + s + '?' + (+new Date)).done(callback); +} + + +function loadScripts(scripts, callback) { + // keep in order + var i = 0; + loadScript(scripts[i], function () { + i++; + if (i == scripts.length) { + callback(); + return; + } + else { + loadScript(scripts[i], arguments.callee); + } + }); +} \ No newline at end of file diff --git a/src/main/webapp/unit-tests/rap-plugin/base.js b/src/main/webapp/unit-tests/rap-plugin/base.js new file mode 100644 index 000000000..9177accff --- /dev/null +++ b/src/main/webapp/unit-tests/rap-plugin/base.js @@ -0,0 +1,132 @@ +module('rap-plugin-base'); + +test('KISSY.use("rap_io"), to see KISSY.io|KISSY.IO|KISSY.ajax', function () { + stop(); + action = '/base'; + KISSY.use('rap_io', function (S, IO) { + ok(KISSY.io != undefined, 'got KISSY.io'); + ok(KISSY.ajax != undefined, 'got KISSY.ajax'); + ok(KISSY.IO != undefined, 'got KISSY.IO'); + + ok(KISSY.io == IO, 'KISSY.io is rap_io'); + ok(KISSY.ajax == IO, 'KISSY.io is rap_io'); + ok(KISSY.IO == IO, 'KISSY.io is rap_io'); + + IO({ + url: action, + dataType: 'json', + success: function (data) { + equal(typeof data.a, 'number', 'get data ok by KISSY.use("io")'); + start(); + } + }) + }) +}) + + +test('get data from KISSY.use("io")', function () { + stop(); + action = '/base'; + KISSY.use('io', function (S, IO) { + ok(KISSY.io != undefined, 'got KISSY.io'); + ok(KISSY.ajax != undefined, 'got KISSY.ajax'); + ok(KISSY.IO != undefined, 'got KISSY.IO'); + IO({ + url: action, + dataType: 'json', + success: function (data) { + equal(typeof data.a, 'number', 'get data ok by KISSY.use("io")'); + start(); + } + }) + }) +}); + +test('get data from KISSY.use("ajax")', function () { + stop(); + action = '/base'; + KISSY.use('ajax', function (S, IO) { + IO({ + url: action, + dataType: 'json', + success: function (data) { + equal(typeof data.a, 'number', 'get data ok by KISSY.use("ajax")'); + start(); + } + }) + }) +}); + +test('get Data from KISSY.io', function () { + action = '/base'; + stop(); + KISSY.io({ + url: action, + dataType: 'json', + success: function (data) { + equal(typeof data.a, 'number', 'KISSY.io get data ok: a'); + equal(typeof data.b, 'string', 'KISSY.io get data ok: b'); + ok(KISSY.isObject(data.c), 'c is object'); + start(); + } + }); +}); + + +test('get Data from KISSY.ajax', function () { + action = '/base'; + stop(); + KISSY.io({ + url: action, + dataType: 'json', + success: function (data) { + equal(typeof data.a, 'number', 'KISSY.ajax get data ok: a'); + equal(typeof data.b, 'string', 'KISSY.ajax get data ok: b'); + ok(KISSY.isObject(data.c), 'c is object'); + start(); + } + }); +}); + +test('KISSY.use("io", {success: function(S, IO) {}})', function () { + action = '/base'; + stop(); + KISSY.use("io", { + success: function (S, IO) { + ok(KISSY.io != undefined, 'got KISSY.io'); + ok(KISSY.ajax != undefined, 'got KISSY.ajax'); + ok(KISSY.IO != undefined, 'got KISSY.IO'); + + IO({ + url: action, + dataType: 'json', + success: function (data) { + equal(typeof data.a, 'number', 'get data ok'); + start(); + } + }) + } + }) +}); + + +test('KISSY.use("ajax", {success: function(S, IO) {}})', function () { + action = '/base'; + stop(); + KISSY.use("ajax", { + success: function (S, IO) { + ok(KISSY.io != undefined, 'got KISSY.io'); + ok(KISSY.ajax != undefined, 'got KISSY.ajax'); + ok(KISSY.IO != undefined, 'got KISSY.IO'); + + IO({ + url: action, + dataType: 'json', + success: function (data) { + equal(typeof data.a, 'number', 'get data ok'); + start(); + } + }) + } + }) +}); \ No newline at end of file diff --git a/src/main/webapp/unit-tests/rap-plugin/for-seajs.js b/src/main/webapp/unit-tests/rap-plugin/for-seajs.js new file mode 100644 index 000000000..836d3e90f --- /dev/null +++ b/src/main/webapp/unit-tests/rap-plugin/for-seajs.js @@ -0,0 +1,66 @@ +module('Seajs-jQuery-RAP'); + +test('Seajs+jQuery: basic check', function () { + stop(4); + ok(window.wrapJQueryForRAP, 'wrap method exists'); + define('a', function (require) { + start(1); + var jq = require('jquery'); + ok(jq.providedByRAP, 'provided by rap'); + ok(jq._rap_wrapped, 'ajax wrapped') + ok(jq('body')[0] == document.body, 'jquery is loaded by seajs'); + }) + + define('b', function (require) { + start(1); + var jq = require('jQuery'); + ok(jq.providedByRAP, 'provided by rap'); + ok(jq._rap_wrapped, 'ajax wrapped') + ok(jq('body')[0] == document.body, 'jQuery is loaded by seajs'); + }) + + define('c', function (require) { + start(1); + var jq = require('jq'); + ok(jq.providedByRAP, 'provided by rap'); + ok(jq._rap_wrapped, 'ajax wrapped') + ok(jq('body')[0] == document.body, 'jq is loaded by seajs'); + }) + + define('d', function (require) { + start(1); + var jq = require('jQ'); + ok(jq.providedByRAP, 'provided by rap'); + ok(jq._rap_wrapped, 'ajax wrapped') + ok(jq('body')[0] == document.body, 'jQ is loaded by seajs'); + }) + + seajs.use(['a', 'b', 'c', 'd'], function (a, b, c, d) { + }); +}); + + +test('Seajs+jQuery: get rap data', function () { + stop() + var action = '/base'; + define('e', function (require) { + var $ = require('jquery'); + equal(RAP.getPrefix(), '/mockjs/', 'PREFIX is /mockjs/'); + $.ajax({ + type: "get", + url: "/mockjs/base", + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok('a' in data, 'mockjs : a is in data'); + ok(KISSY.isNumber(data['a']), 'and dataType is number'); + }, + error: function () { + } + }); + }) + + seajs.use('e', function () { + }); +}) \ No newline at end of file diff --git a/src/main/webapp/unit-tests/rap-plugin/jsapis.js b/src/main/webapp/unit-tests/rap-plugin/jsapis.js new file mode 100644 index 000000000..f32bf9a22 --- /dev/null +++ b/src/main/webapp/unit-tests/rap-plugin/jsapis.js @@ -0,0 +1,70 @@ +module('rap-plugin-jsapis'); + +test('RAP.set/getWhiteList', function () { + var old = RAP.getWhiteList(); + var newList = ['a', 'b']; + RAP.setWhiteList(newList); + equal(RAP.getWhiteList(), newList, 'get/set ok'); + RAP.setWhiteList(old); + equal(RAP.getWhiteList(), old, 'recover ok'); +}); + +test('RAP.set/getHost', function () { + var old = RAP.getHost(); + equal(old, window.location.host, 'old is ok'); + var newHost = 'rap2.ali' + 'bab' + 'a-inc.com'; + RAP.setHost(newHost); + equal(RAP.getHost(), newHost, 'get/set ok'); + RAP.setHost(old); + equal(RAP.getHost(), old, 'recover ok'); +}); + +test('RAP.set/getBlackList', function () { + var old = RAP.getBlackList(); + var newList = ['a', 'b']; + RAP.setBlackList(newList); + equal(RAP.getBlackList(), newList, 'get/set ok'); + RAP.setBlackList(old); + equal(RAP.getBlackList(), old, 'recover ok'); +}); + +test('RAP.set/getMode', function () { + var old = RAP.getMode(); + var newMode = 3; + RAP.setMode(newMode); + equal(RAP.getMode(), newMode, 'get/set ok'); + RAP.setMode(old); + equal(RAP.getMode(), old, 'recover ok'); +}); + +test('RAP.set/getPrefix', function () { + var old = RAP.getPrefix(); + equal(old, '/mockjs/', 'old is /mockjs/'); + var newPrefix = '/mockjsdata/'; + RAP.setPrefix(newPrefix); + equal(RAP.getPrefix(), newPrefix, 'get/set ok'); + RAP.setPrefix(old); + equal(RAP.getPrefix(), old, 'recover ok'); +}); + +test('RAP.set/white list & black list functions', function () { + var arr = ['a', 'b', 'c']; + RAP.setWhiteList(arr); + var whiteList = RAP.getWhiteList(); + deepEqual(arr, whiteList, 'white list works fine'); + + var arr2 = ['a', 'b', 'c']; + RAP.setBlackList(arr2); + var blackList = RAP.getBlackList(); + deepEqual(arr2, blackList, 'black list works fined'); +}); + +test('RAP.set/getProjectId', function () { + var old = RAP.getProjectId(); + equal(old, 114, 'old is 114'); + var newProjectId = 121; + RAP.setProjectId(newProjectId); + equal(RAP.getProjectId(), newProjectId, 'get/set ok, new is ' + newProjectId); + RAP.setProjectId(old); + equal(RAP.getProjectId(), old, 'recover ok'); +}); diff --git a/src/main/webapp/unit-tests/rap-plugin/modes.js b/src/main/webapp/unit-tests/rap-plugin/modes.js new file mode 100644 index 000000000..0db2d4910 --- /dev/null +++ b/src/main/webapp/unit-tests/rap-plugin/modes.js @@ -0,0 +1,200 @@ +module('rap-plugin-modes'); + +//mode 0:不走rap,应该404 +test('setMode 0 - 404 [KISSY]', function () { + var old = RAP.getMode(); + RAP.setMode(0); + + stop(); + var action = '/base'; + KISSY.use('io', function (S, IO) { + IO({ + url: action, + dataType: 'json', + success: function (data) { + start(); + ok(0, 'in here, is not right in this case'); + RAP.setMode(old); + }, + error: function (data) { + start(); + ok(1, 'in here, 404 is right in this case'); + RAP.setMode(old); + } + }) + }) +}); + +//mode 0:不走rap,应该404 +test('setMode 0 - 404 [jQuery]', function () { + var old = RAP.getMode(); + RAP.setMode(0); + + stop(); + var action = '/base'; + $.rapAjax({ + type: "get", + url: action, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok(0, 'in here, is not right in this case'); + RAP.setMode(old); + }, + error: function () { + start(); + ok(1, 'in here, 404 is right in this case'); + RAP.setMode(old); + } + }); +}); + + +//mode 0:放行 +test('setMode 0 - 200 [KISSY]', function () { + var old = RAP.getMode(); + RAP.setMode(0); + + stop(); + var action = '/mockjsdata/114/mockjs/base'; + KISSY.use('io', function (S, IO) { + IO({ + url: action, + dataType: 'jsonp', + jsonp: 'callback', + success: function (data) { + start(); + ok(1, 'in here, is not right in this case'); + RAP.setMode(old); + }, + error: function (data) { + start(); + ok(0, 'in here, 404 is right in this case'); + RAP.setMode(old); + } + }) + }) +}); + +//mode 0:放行 +test('setMode 0 - 200 [jQuery]', function () { + var old = RAP.getMode(); + RAP.setMode(0); + + stop(); + var action = '/mockjsdata/114/mockjs/base'; + $.rapAjax({ + type: "get", + url: action, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok(1, 'in here, is not right in this case'); + RAP.setMode(old); + }, + error: function () { + start(); + ok(0, 'in here, 404 is right in this case'); + RAP.setMode(old); + } + }); +}); + +//mode 1:拦截所有请求 +test('setMode 1 - 200 [KISSY]', function () { + var old = RAP.getMode(); + RAP.setMode(1); + + stop(); + var action = '/base'; + KISSY.use('io', function (S, IO) { + IO({ + url: action, + dataType: 'json', + success: function (data) { + start(); + ok(1, 'in here, is right in this case'); + RAP.setMode(old); + }, + error: function (data) { + start(); + ok(0, 'in here, 404 is not right in this case'); + RAP.setMode(old); + } + }) + }) +}) + +// mode 1:拦截所有请求 +test('setMode 1 - 200 [jQuery]', function () { + var old = RAP.getMode(); + RAP.setMode(1); + + stop(); + var action = '/base'; + $.rapAjax({ + type: "get", + url: action, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok(1, 'in here, is right in this case'); + RAP.setMode(old); + }, + error: function () { + start(); + ok(0, 'in here, 404 is not right in this case'); + RAP.setMode(old); + } + }); +}) + + +//mode 1:拦截所有请求 +test('setMode 1 - 404 [KISSY]', function () { + var old = RAP.getMode(); + RAP.setMode(1); + + stop(); + var action = '/mockjsdata/114/mockjs/base'; + KISSY.use('io', function (S, IO) { + IO({ + url: action, + dataType: 'json', + success: function (data) { + start(); + ok(data.isOk === false, 'no matched action'); + equal(data.errMsg, 'no matched action', 'no matched action'); + RAP.setMode(old); + }, + error: function (data) { + } + }) + }) +}) + +// mode 1:拦截所有请求 +test('setMode 1 - 404 [jQuery]', function () { + var old = RAP.getMode(); + RAP.setMode(1); + + stop(); + var action = '/mockjsdata/114/mockjs/base'; + $.rapAjax({ + type: "get", + url: action, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + start(); + ok(data.isOk === false, 'no matched action'); + equal(data.errMsg, 'no matched action', 'no matched action'); + RAP.setMode(old); + }, + error: function () { + } + }); +}) \ No newline at end of file diff --git a/src/main/webapp/unit-tests/rap-plugin/whiteblack.js b/src/main/webapp/unit-tests/rap-plugin/whiteblack.js new file mode 100644 index 000000000..c368b1e0d --- /dev/null +++ b/src/main/webapp/unit-tests/rap-plugin/whiteblack.js @@ -0,0 +1,245 @@ +module('rap-plugin-whiteList'); + +test('setWhiteList[ok] in mode 3', function () { + var old = RAP.getMode(); + RAP.setMode(3); + var white = RAP.getWhiteList(); + RAP.setWhiteList(['/base']); + + stop(2); + var action = '/base'; + var counter = 0; + KISSY.use('io', function (S, IO) { + IO({ + url: action, + dataType: 'json', + success: function (data) { + counter++; + start(1); + ok(1, 'in here, is right in this case'); + if (counter == 2) { + RAP.setMode(old); + RAP.setWhiteList(white); + } + }, + error: function (data) { + counter++; + start(1); + ok(0, 'in here, 404 is not right in this case'); + if (counter == 2) { + RAP.setMode(old); + RAP.setWhiteList(white); + } + } + }) + }) + + $.rapAjax({ + type: "get", + url: action, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + counter++; + start(1); + ok(1, 'in here, is right in this case'); + if (counter == 2) { + RAP.setMode(old); + RAP.setWhiteList(white); + } + }, + error: function () { + counter++; + start(1); + ok(0, 'in here, 404 is not right in this case'); + if (counter == 2) { + RAP.setMode(old); + RAP.setWhiteList(white); + } + } + }); +}) + +test('setWhiteList[not ok] in mode 3', function () { + var old = RAP.getMode(); + RAP.setMode(3); + + var white = RAP.getWhiteList(); + RAP.setWhiteList(['/notExistsAction']); + + stop(2); + var action = '/base'; + var counter = 0; + KISSY.use('io', function (S, IO) { + IO({ + url: action, + dataType: 'json', + success: function (data) { + counter++; + start(1); + ok(0, 'whiteList mode, url node in list, should not 200'); + if (counter == 2) { + RAP.setMode(old); + RAP.setWhiteList(white); + } + }, + error: function (data) { + counter++; + start(1); + ok(1, 'whiteList mode, url node in list, should 404'); + if (counter == 2) { + RAP.setMode(old); + RAP.setWhiteList(white); + } + } + }) + }) + + $.rapAjax({ + type: "get", + url: action, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + counter++; + start(1); + ok(0, 'whiteList mode, url node in list, should not 200'); + if (counter == 2) { + RAP.setMode(old); + RAP.setWhiteList(white); + } + }, + error: function () { + counter++; + start(1); + ok(1, 'whiteList mode, url node in list, should 404'); + if (counter == 2) { + RAP.setMode(old); + RAP.setWhiteList(white); + } + } + }); +}) + + +module('rap-plugin-blackList'); + +test('setBlackList[not ok] in mode 2', function () { + var old = RAP.getMode(); + RAP.setMode(2); + + var black = RAP.getBlackList(); + RAP.setBlackList(['/notExistsAction']); + + stop(2); + var action = '/base'; + var counter = 0; + KISSY.use('io', function (S, IO) { + IO({ + url: action, + dataType: 'json', + success: function (data) { + counter++; + start(1); + ok(1, 'in here, is right in this case'); + if (counter == 2) { + RAP.setMode(old); + RAP.setBlackList(black); + } + }, + error: function (data) { + counter++; + start(1); + ok(0, 'in here, 404 is not right in this case'); + if (counter == 2) { + RAP.setMode(old); + RAP.setBlackList(black); + } + } + }) + }) + + $.rapAjax({ + type: "get", + url: action, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + counter++; + start(1); + ok(1, 'in here, is right in this case'); + if (counter == 2) { + RAP.setMode(old); + RAP.setBlackList(black); + } + }, + error: function () { + counter++; + start(1); + ok(0, 'in here, 404 is not right in this case'); + if (counter == 2) { + RAP.setMode(old); + RAP.setBlackList(black); + } + } + }); +}) + +test('setWhiteList[ok] in mode 2', function () { + var old = RAP.getMode(); + RAP.setMode(2); + + var black = RAP.getBlackList(); + RAP.setBlackList(['/base']); + + stop(2); + var action = '/base'; + var counter = 0; + KISSY.use('io', function (S, IO) { + IO({ + url: action, + dataType: 'json', + success: function (data) { + counter++; + start(1); + ok(0, 'whiteList mode, url node in list, should not 200'); + if (counter == 2) { + RAP.setMode(old); + RAP.setBlackList(black); + } + }, + error: function (data) { + counter++; + start(1); + ok(1, 'whiteList mode, url node in list, should 404'); + if (counter == 2) { + RAP.setMode(old); + RAP.setBlackList(black); + } + } + }) + }) + + $.rapAjax({ + type: "get", + url: action, + dataType: "jsonp", + jsonp: "callback", + success: function (data) { + counter++; + start(1); + ok(0, 'whiteList mode, url node in list, should not 200'); + if (counter == 2) { + RAP.setMode(old); + } + }, + error: function () { + counter++; + start(1); + ok(1, 'whiteList mode, url node in list, should 404'); + if (counter == 2) { + RAP.setMode(old); + } + } + }); +}) \ No newline at end of file diff --git a/src/main/webapp/unit-tests/utility/structureValidator.js b/src/main/webapp/unit-tests/utility/structureValidator.js new file mode 100644 index 000000000..00d58f0cb --- /dev/null +++ b/src/main/webapp/unit-tests/utility/structureValidator.js @@ -0,0 +1,35 @@ +module('utility-structureValidator'); + + +test('Utility: StructureValidator functions test', function () { + var o1 = { + p1: 1, + p2: 2, + p3: 3, + obj: [{ + op3: 3, + op6: 6, + op7: 7 + }] + }; + var o2 = { + p1: 1, + p3: 3, + p4: 4, + obj: [] + }; + + var validator = new StructureValidator(o1, o2); + + var correctData = { + "left": [{"type": "LOST", "property": "p4", "namespace": "obj"}], + "right": [{"type": "LOST", "property": "p2", "namespace": "obj"}, { + "type": "EMPTY_ARRAY", + "property": "obj", + "namespace": "obj" + }] + }; + var realData = validator.getResult(); + + deepEqual(correctData, realData, 'strcuture check complete'); +}); diff --git a/WebContent/stat/css/myWorkspace.css b/src/main/webapp/workspace/myWorkspace.css similarity index 71% rename from WebContent/stat/css/myWorkspace.css rename to src/main/webapp/workspace/myWorkspace.css index f10404a3e..1c67a2fc1 100644 --- a/WebContent/stat/css/myWorkspace.css +++ b/src/main/webapp/workspace/myWorkspace.css @@ -1,10 +1,31 @@ body { - margin:0; - padding:0; + margin: 0; + padding: 0; + color: #666; +} + +.add-link, .edit-link, .del-link, .test-link { + margin-top: 5px; + display: inline-block; + margin-left: 5px; + cursor: pointer; + text-decoration: none !important; + color: #999 !important; +} + +.ec-tree .add-link, +.ec-tree .edit-link, +.ec-tree .del-link, +.ec-tree .test-link { + margin-top: 2px; } -.workspace .container { - width: 90%; +.add-link:hover, .edit-link:hover, .del-link:hover, .test-link:hover { + color: #666 !important; +} + +.add-link { + background-position: 0 -31px; } .air { @@ -161,15 +182,16 @@ body { background: #FAFBFC } +.read-only #div-w { + +} #div-fixed-panel { - position: fixed; width: 1170px; - margin: 0 auto; + margin: 70px 0 0 0; background: #FFF; z-index: 1; - padding-top: 10px; - top:0; + top: 50px; } .m { @@ -178,7 +200,7 @@ body { background-color: #F2F2F2; border: 1px solid #DDD; border-radius: 0 0 12px 12px; - padding-top: 20px; + overflow-y: auto; } .tree-m { @@ -186,6 +208,8 @@ body { overflow-y: auto; overflow-x: auto; float: left; + margin-top: 8px; + } .tree-m .cur a { @@ -199,7 +223,7 @@ body { } .myfloater { - padding: 12px; + padding: 20px; width: 600px; } @@ -215,7 +239,8 @@ body { .div-a h2 { width: 648px; - margin: 12px 0 0 18px; + margin: 24px 0 0 18px; + font-size: 20px; } .div-a .head { @@ -255,7 +280,6 @@ body { } .div-a .op { - width: 45px; background-color: #E6E6E6; border-left: none; } @@ -311,7 +335,7 @@ body { border-bottom: 1px solid #DDD; width: 1157px; text-align: left; - margin-top:13px; + margin-top: 13px; } #div-mt-list .tab { @@ -325,6 +349,7 @@ body { float: right; text-align: center; cursor: pointer; + border-radius: 4px 4px 0 0; } #div-mt-list .cur { @@ -339,7 +364,7 @@ body { #div-add-m { float: right; - margin-top: 18px; + margin-top: 8px; } #div-remove-m { @@ -350,21 +375,17 @@ body { } #div-add-p { - position: absolute; - top: 54px; - left: 0px; - z-index: 10; + } #div-w { position: relative; - margin-top: 76px; + margin-top: -1px; } #div-w-message { font-size: 14px; float: left; - margin-left: 12px; margin-top: 5px; } @@ -377,7 +398,8 @@ body { } #div-control-panel { - float: right; margin-right: 13px; + float: right; + margin-right: 13px; } #div-control-panel .button { @@ -386,7 +408,7 @@ body { } #div-control-panel .btn { - outline: none; + outline: none; } #div-return { @@ -406,8 +428,7 @@ body { } -#div-save-floater-message,#div-checkin-floater-message,#div-checkout-floater-message,#div-version-floater-message,#div-saveVSS-floater-message - { +#div-save-floater-message, #div-checkin-floater-message, #div-checkout-floater-message, #div-version-floater-message, #div-saveVSS-floater-message { position: absolute; top: 40px; left: 28px; @@ -422,7 +443,7 @@ body { text-align: right; } -#div-checkin-floater-content,#div-checkout-floater-content { +#div-checkin-floater-content, #div-checkout-floater-content { margin: 8px; border: Gray 1px dashed; width: 550px; @@ -439,13 +460,13 @@ body { font-weight: bold; } -#floaterEditAFloater .radio-list label{ +#floaterEditAFloater .radio-list label { float: left; - margin:0 10px 0 4px; + margin: 0 10px 0 4px; cursor: pointer; } -#floaterEditAFloater .radio-list input{ +#floaterEditAFloater .radio-list input { float: left; } @@ -468,13 +489,13 @@ body { font-weight: bold; } -#div-saveVSS-floater-content .radio-list label{ +#div-saveVSS-floater-content .radio-list label { float: left; - margin:0 10px 0 4px; + margin: 0 10px 0 4px; cursor: pointer; } -#div-saveVSS-floater-content .radio-list input{ +#div-saveVSS-floater-content .radio-list input { float: left; } @@ -493,13 +514,14 @@ body { } #div-control-panel .btn { - margin-left:5px; + margin-left: 5px; } .td-param { border: white 1px solid; border-collapse: collapse; - height: 20px; + height: 28px; + padding-left: 5px; } .table-a { @@ -517,7 +539,6 @@ body { margin: 8px; } - .param-level-0 { background-color: #b8def5; } @@ -552,13 +573,13 @@ body { .td-param .edit-input, .tab input { background: none; - margin:0; - font-style:italic; + margin: 0; + font-style: italic; } .tab input { - height:22px; - font-size:12px; + height: 22px; + font-size: 12px; } .item { @@ -566,6 +587,11 @@ body { font-size: 12px; } +.item b { + display: inline-block; + width: 60px; +} + .select-dataType { background-color: #E6E6E6; border: none; @@ -576,7 +602,8 @@ body { } .action-info { - margin-left: 18px; + margin-left: 15px; + margin-top: 10px; } .head { @@ -648,9 +675,31 @@ body { } .div-op-container { - position: absolute; - margin-top: -8px; # - margin-top: 0; /* for IE */ + position: relative; +} + +.ec-tree > .edit-link, .ec-tree > .del-link { + visibility: hidden; +} + +.ec-tree:hover > .edit-link, .ec-tree:hover > .del-link { + visibility: visible; +} + +.div-op-container .del-link { + margin-left: 2px; +} + +.div-op-container .del-link i { + color: #d9534f; +} + +.div-op-container .add-link i { + color: #5cb85c; +} + +.div-op-container .del-link, .div-op-container .add-link { + margin-top: 0; } .div-add-param-link { @@ -663,28 +712,76 @@ body { .container .label { line-height: 20px; } -body .container { - margin:auto; - width:80%; -} #div-workspace-search { position: relative; display: inline-block; - width: 300px; + width: 200px; + float: left; } #div-workspace-search .glyphicon-search { - position: absolute; right: 8px; top: 10px; color: #999; -} -#inputSearch { - padding-right: 25px; + position: absolute; + right: 8px; + top: 10px; + color: #999; } #dropdown-workspace-search .dropdown-menu { - min-width: 300px; max-width: 687px; + min-width: 300px; + max-width: 687px; } #dropdown-workspace-search .dropdown-menu li a { - overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#pluginCodeInput { + 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; +} + +.table-version { + margin: 0 auto; +} + +.myfloater textarea, .myfloater input[type=text], .myfloater input[type=password] { + border: 1px solid #DDD; + border-radius: 2px; + padding: 5px; + outline: none; +} + +.myfloater textarea { + margin-top: 2px; + resize: none; +} + +#floaterEditAFloater input[type=text], #floaterEditAFloater input[type=password] { + margin-top: 3px; + margin-bottom: 3px; +} + +#floaterEditAFloater .radio-list { + padding-top: 5px; + padding-bottom: 5px; +} + +.glyphicon-remove { + color:#d9534f } diff --git a/src/main/webapp/workspace/myWorkspace.vm b/src/main/webapp/workspace/myWorkspace.vm new file mode 100644 index 000000000..742c5edda --- /dev/null +++ b/src/main/webapp/workspace/myWorkspace.vm @@ -0,0 +1,616 @@ + + #parse('/tcom/template.rap.vm') + + + + loading... + + #includeNewRapStatic + + + + + + +#bodyNewStart + +#breadcrumb("position:relative;top:60px;background-color:#FFF;") +
      +
      + + + +
      +
      + + +
      +
      +
      +
      + + Loading workspace... Please wait... +
      +
      +
      +
      +#bodyEnd + + +#startFloater("saveVSSFloater" "" 500 380) +
      + +
      + + + + + + + + + + + + + + + + + +
      推进版本 + + + + + + + + +
      变化预览: +
      +
      提交描述:
      + + +
      +
      +
      +#endFloater + +#startFloater("versionFloater" "" 600 400) +
      + +
      +
      + +     + +     + +
      +
      +#endFloater + + #startFloater("editAFloater" "编辑接口" 600 300) +
      +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      名称 + +
      请求类型 + + + + + + + + +
      请求链接 + +
      回跳模板 + +
      说明 + +
      返回格式 + + + + +
      +
      + + +
      +
      +
      +#endFloater + +#startFloater("editPFloater" "编辑页面" 600 400) +
      +
      + + + + + + + + + + + + +
      名称 + +
      说明 + +
      +
      + + +
      +
      +
      +#endFloater + +#startFloater("importJSONFloater" "JSON导入" 600 350) +
      + +
      + + + + +
      + +
      +
      + + +
      +
      +
      +#endFloater + +#startFloater("recoverWorkspaceFloater" "导入备份数据" 600 350) +
      + +
      + + + + +
      + +
      +
      + + +
      +
      +
      +#endFloater + +#startFloater("exportRAPDataFloater" "JSON导入" 600 350) +
      +
      + + + + +
      + +
      +
      + +
      +
      +
      +#endFloater + +#startFloater("pluginCodeFloater" "FE工具箱" 600 230) +
      +
      +
      插件代码
      +
      + +
      +
      项目路由
      +
      + +
      +
      + + +
      +
      +
      + +
      +
      +#endFloater + +#startFloater("actionUrlFloater" "请求链接" 600 180) +
      +
      +
      + +
      +
      + +
      +
      +
      +#endFloater + +#startFloater("mockDataPreviewFloater" "Mock数据预览" 600 600) +
      +
      +
      Mock API
      +
        +
      • Mock规则:
      • +
      • Mock数据:
      • +
      +
      Mock规则 + +
      + +
      +
      +
      Mock数据 + + + +
      + +
      +
      + +
      +
      +#endFloater + +#startFloater("actionOpFloater" "文档操作" 600 230) +
      +
      +
      + + +
      + + + +
      +
      +
      + +
        +
      • + +
      • +
      • + +
      • +
      +
      +
      + + +
      +
      +
      +#endFloater + + + + diff --git a/src/mysql.local.properties b/src/mysql.local.properties deleted file mode 100644 index 89e92faae..000000000 --- a/src/mysql.local.properties +++ /dev/null @@ -1,10 +0,0 @@ -jdbc.driverClassName=com.mysql.jdbc.Driver -jdbc.url=jdbc\:mysql\://localhost\:3306/BosnAutoPlatformDB?useUnicode\=true&characterEncoding\=utf8&zeroDateTimeBehavior\=convertToNull&noAccessToProcedureBodies\=true -jdbc.username=root -jdbc.password=880622 -jdbc.maxPoolSize=2 -jdbc.minPoolSize=1 -jdbc.initialPoolSize=1 -jdbc.idleConnectionTestPeriod=1800 -jdbc.maxIdleTime=3600 - diff --git a/src/mysql.remote.properties b/src/mysql.remote.properties deleted file mode 100644 index 6847c17a9..000000000 --- a/src/mysql.remote.properties +++ /dev/null @@ -1,9 +0,0 @@ -jdbc.driverClassName=com.mysql.jdbc.Driver -jdbc.url=jdbc\:mysql\://10.32.229.251\:3306/BosnAutoPlatformDB?useUnicode\=true&characterEncoding\=utf8&zeroDateTimeBehavior\=convertToNull&noAccessToProcedureBodies\=true -jdbc.username=root -jdbc.password=880622 -jdbc.maxPoolSize=2 -jdbc.minPoolSize=1 -jdbc.initialPoolSize=1 -jdbc.idleConnectionTestPeriod=1800 -jdbc.maxIdleTime=3600 \ No newline at end of file diff --git a/src/org/apache/struts2/views/velocity/RapVelocityResult.java b/src/org/apache/struts2/views/velocity/RapVelocityResult.java deleted file mode 100644 index fde48b00c..000000000 --- a/src/org/apache/struts2/views/velocity/RapVelocityResult.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.apache.struts2.views.velocity; - -import org.apache.struts2.dispatcher.VelocityResult; - -public class RapVelocityResult extends VelocityResult { - - private static final long serialVersionUID = 1468647758035361308L; - private String contentType = "text/html"; - - public void setContentType(String contentType) { - this.contentType = contentType; - } - - protected String getContentType(String templateLocation) { - return contentType; - } - } diff --git a/src/org/apache/struts2/views/velocity/VelocityManager.java b/src/org/apache/struts2/views/velocity/VelocityManager.java deleted file mode 100644 index 6a16a20d7..000000000 --- a/src/org/apache/struts2/views/velocity/VelocityManager.java +++ /dev/null @@ -1,653 +0,0 @@ -/* - * $Id: VelocityManager.java,v 1.1 2010/01/11 12:57:32 zhangchengsong Exp $ - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.struts2.views.velocity; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.struts2.ServletActionContext; -import org.apache.struts2.StrutsConstants; -import org.apache.struts2.StrutsException; -import org.apache.struts2.util.VelocityStrutsUtil; -import org.apache.struts2.views.TagLibrary; -import org.apache.struts2.views.jsp.ui.OgnlTool; -import org.apache.struts2.views.util.ContextUtil; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.Velocity; -import org.apache.velocity.app.VelocityEngine; -import org.apache.velocity.context.Context; -import org.apache.velocity.tools.view.ToolboxManager; -import org.apache.velocity.tools.view.context.ChainedContext; -import org.apache.velocity.tools.view.servlet.ServletToolboxManager; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; - -/** - * Manages the environment for Velocity result types - * - */ -public class VelocityManager { - private static final Log log = LogFactory.getLog(VelocityManager.class); - public static final String STRUTS = "struts"; - private ObjectFactory objectFactory; - - /** - * the parent JSP tag - */ - public static final String PARENT = "parent"; - - /** - * the current JSP tag - */ - public static final String TAG = "tag"; - - private VelocityEngine velocityEngine; - - /** - * A reference to the toolbox manager. - */ - protected ToolboxManager toolboxManager = null; - private String toolBoxLocation; - - /** - * Names of contexts that will be chained on every request - */ - private String[] chainedContextNames; - - private Properties velocityProperties; - - private String customConfigFile; - - private List tagLibraries; - - public VelocityManager() { - } - - @Inject - public void setObjectFactory(ObjectFactory fac) { - this.objectFactory = fac; - } - - @Inject - public void setContainer(Container container) { - List list = new ArrayList(); - Set prefixes = container.getInstanceNames(TagLibrary.class); - for (String prefix : prefixes) { - list.add(container.getInstance(TagLibrary.class, prefix)); - } - this.tagLibraries = Collections.unmodifiableList(list); - } - - /** - * retrieve an instance to the current VelocityManager - */ - /* - * public synchronized static VelocityManager getInstance() { if (instance - * == null) { String classname = VelocityManager.class.getName(); - * - * if (Settings.isSet(StrutsConstants.STRUTS_VELOCITY_MANAGER_CLASSNAME)) { - * classname = - * Settings.get(StrutsConstants.STRUTS_VELOCITY_MANAGER_CLASSNAME).trim(); } - * - * if (!classname.equals(VelocityManager.class.getName())) { try { - * log.info("Instantiating VelocityManager!, " + classname); // singleton - * instances shouldn't be built accessing request or session-specific - * context data instance = (VelocityManager) - * ObjectFactory.getObjectFactory().buildBean(classname, null); } catch - * (Exception e) { log.fatal( - * "Fatal exception occurred while trying to instantiate a VelocityManager instance, " - * + classname, e); instance = new VelocityManager(); } } else { instance = - * new VelocityManager(); } } - * - * return instance; } - */ - - /** - * @return a reference to the VelocityEngine used by all struts - * velocity thingies with the exception of directly accessed *.vm - * pages - */ - public VelocityEngine getVelocityEngine() { - return velocityEngine; - } - - /** - * This method is responsible for creating the standard VelocityContext used - * by all WW2 velocity views. The following context parameters are defined: - *

      - *

        - *
      • request - the current HttpServletRequest
      • - *
      • response - the current HttpServletResponse
      • - *
      • stack - the current {@link ValueStack}
      • - *
      • ognl - an {@link OgnlTool}
      • - *
      • struts - an instance of - * {@link org.apache.struts2.util.StrutsUtil}
      • - *
      • action - the current Struts action
      • - *
      - * - * @return a new StrutsVelocityContext - */ - @SuppressWarnings("rawtypes") - public Context createContext(ValueStack stack, HttpServletRequest req, - HttpServletResponse res) { - VelocityContext[] chainedContexts = prepareChainedContexts(req, res, - stack.getContext()); - StrutsVelocityContext context = new StrutsVelocityContext( - chainedContexts, stack); - Map standardMap = ContextUtil.getStandardContext(stack, req, res); - for (Iterator iterator = standardMap.entrySet().iterator(); iterator - .hasNext();) { - Map.Entry entry = (Map.Entry) iterator.next(); - context.put((String) entry.getKey(), entry.getValue()); - } - context.put(STRUTS, new VelocityStrutsUtil(velocityEngine, context, - stack, req, res)); - - ServletContext ctx = null; - try { - ctx = ServletActionContext.getServletContext(); - } catch (NullPointerException npe) { - // in case this was used outside the lifecycle of struts servlet - log.debug("internal toolbox context ignored"); - } - - if (toolboxManager != null && ctx != null) { - // here is the new constructor : - ChainedContext chained = new ChainedContext(getVelocityEngine(), - req, res, ctx); - - chained.setToolbox(toolboxManager.getToolbox(chained)); - return chained; - } else { - return context; - } - - } - - /** - * constructs contexts for chaining on this request. This method does not - * perform any initialization of the contexts. All that must be done in the - * context itself. - * - * @param servletRequest - * @param servletResponse - * @param extraContext - * @return an VelocityContext[] of contexts to chain - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - protected VelocityContext[] prepareChainedContexts( - HttpServletRequest servletRequest, - HttpServletResponse servletResponse, Map extraContext) { - if (this.chainedContextNames == null) { - return null; - } - List contextList = new ArrayList(); - for (int i = 0; i < chainedContextNames.length; i++) { - String className = chainedContextNames[i]; - try { - VelocityContext velocityContext = (VelocityContext) objectFactory - .buildBean(className, null); - contextList.add(velocityContext); - } catch (Exception e) { - log.warn("Warning. " - + e.getClass().getName() - + " caught while attempting to instantiate a chained VelocityContext, " - + className + " -- skipping"); - } - } - if (contextList.size() > 0) { - VelocityContext[] extraContexts = new VelocityContext[contextList - .size()]; - contextList.toArray(extraContexts); - return extraContexts; - } else { - return null; - } - } - - /** - * initializes the VelocityManager. this should be called during the - * initialization process, say by ServletDispatcher. this may be called - * multiple times safely although calls beyond the first won't do anything - * - * @param context - * the current servlet context - */ - public synchronized void init(ServletContext context) { - if (velocityEngine == null) { - velocityEngine = newVelocityEngine(context); - } - this.initToolbox(context); - } - - /** - * load optional velocity properties using the following loading strategy - *
        - *
      • relative to the servlet context path
      • - *
      • relative to the WEB-INF directory
      • - *
      • on the classpath
      • - *
      - * - * @param context - * the current ServletContext. may not be null - * @return the optional properties if struts.velocity.configfile was - * specified, an empty Properties file otherwise - */ - @SuppressWarnings("rawtypes") - public Properties loadConfiguration(ServletContext context) { - if (context == null) { - String gripe = "Error attempting to create a loadConfiguration from a null ServletContext!"; - log.error(gripe); - throw new IllegalArgumentException(gripe); - } - - Properties properties = new Properties(); - - // now apply our systemic defaults, then allow user to override - applyDefaultConfiguration(context, properties); - - String defaultUserDirective = properties.getProperty("userdirective"); - - /** - * if the user has specified an external velocity configuration file, - * we'll want to search for it in the following order - * - * 1. relative to the context path 2. relative to /WEB-INF 3. in the - * class path - */ - String configfile; - - if (customConfigFile != null) { - configfile = customConfigFile; - } else { - configfile = "velocity.properties"; - } - - configfile = configfile.trim(); - - InputStream in = null; - String resourceLocation = null; - - try { - if (context.getRealPath(configfile) != null) { - // 1. relative to context path, i.e. /velocity.properties - String filename = context.getRealPath(configfile); - - if (filename != null) { - File file = new File(filename); - - if (file.isFile()) { - resourceLocation = file.getCanonicalPath() - + " from file system"; - in = new FileInputStream(file); - } - - // 2. if nothing was found relative to the context path, - // search relative to the WEB-INF directory - if (in == null) { - file = new File(context.getRealPath("/WEB-INF/" - + configfile)); - - if (file.isFile()) { - resourceLocation = file.getCanonicalPath() - + " from file system"; - in = new FileInputStream(file); - } - } - } - } - - // 3. finally, if there's no physical file, how about something in - // our classpath - if (in == null) { - in = VelocityManager.class.getClassLoader() - .getResourceAsStream(configfile); - if (in != null) { - resourceLocation = configfile + " from classloader"; - } - } - - // if we've got something, load 'er up - if (in != null) { - log.info("Initializing velocity using " + resourceLocation); - properties.load(in); - } - } catch (IOException e) { - log.warn("Unable to load velocity configuration " - + resourceLocation, e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - } - } - } - - // override with programmatically set properties - if (this.velocityProperties != null) { - Iterator keys = this.velocityProperties.keySet().iterator(); - while (keys.hasNext()) { - String key = (String) keys.next(); - properties.setProperty(key, - this.velocityProperties.getProperty(key)); - } - } - - String userdirective = properties.getProperty("userdirective"); - - if ((userdirective == null) || userdirective.trim().equals("")) { - userdirective = defaultUserDirective; - } else { - userdirective = userdirective.trim() + "," + defaultUserDirective; - } - - properties.setProperty("userdirective", userdirective); - - // for debugging purposes, allows users to dump out the properties that - // have been configured - if (log.isDebugEnabled()) { - log.debug("Initializing Velocity with the following properties ..."); - - for (Iterator iter = properties.keySet().iterator(); iter.hasNext();) { - String key = (String) iter.next(); - String value = properties.getProperty(key); - - if (log.isDebugEnabled()) { - log.debug(" '" + key + "' = '" + value + "'"); - } - } - } - - return properties; - } - - @Inject(StrutsConstants.STRUTS_VELOCITY_CONFIGFILE) - public void setCustomConfigFile(String val) { - this.customConfigFile = val; - } - - @Inject(StrutsConstants.STRUTS_VELOCITY_TOOLBOXLOCATION) - public void setToolBoxLocation(String toolboxLocation) { - this.toolBoxLocation = toolboxLocation; - } - - /** - * allow users to specify via the struts.properties file a set of additional - * VelocityContexts to chain to the the StrutsVelocityContext. The intent is - * to allow these contexts to store helper objects that the ui developer may - * want access to. Examples of reasonable VelocityContexts would be an - * IoCVelocityContext, a SpringReferenceVelocityContext, and a - * ToolboxVelocityContext - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Inject(StrutsConstants.STRUTS_VELOCITY_CONTEXTS) - public void setChainedContexts(String contexts) { - // we expect contexts to be a comma separated list of classnames - StringTokenizer st = new StringTokenizer(contexts, ","); - List contextList = new ArrayList(); - - while (st.hasMoreTokens()) { - String classname = st.nextToken(); - contextList.add(classname); - } - if (contextList.size() > 0) { - String[] chainedContexts = new String[contextList.size()]; - contextList.toArray(chainedContexts); - this.chainedContextNames = chainedContexts; - } - } - - /** - * Initializes the ServletToolboxManager for this servlet's toolbox (if - * any). - */ - @SuppressWarnings("deprecation") - protected void initToolbox(ServletContext context) { - /* if we have a toolbox, get a manager for it */ - if (toolBoxLocation != null) { - toolboxManager = ServletToolboxManager.getInstance(context, - toolBoxLocation); - } else { - Velocity.info("VelocityViewServlet: No toolbox entry in configuration."); - } - } - - /** - *

      - * Instantiates a new VelocityEngine. - *

      - *

      - * The following is the default Velocity configuration - *

      - * - *
      -	 *  resource.loader = file, class
      -	 *  file.resource.loader.path = real path of webapp
      -	 *  class.resource.loader.description = Velocity Classpath Resource Loader
      -	 *  class.resource.loader.class = org.apache.struts2.views.velocity.StrutsResourceLoader
      -	 * 
      - *

      - * this default configuration can be overridden by specifying a - * struts.velocity.configfile property in the struts.properties file. the - * specified config file will be searched for in the following order: - *

      - *
        - *
      • relative to the servlet context path
      • - *
      • relative to the WEB-INF directory
      • - *
      • on the classpath
      • - *
      - * - * @param context - * the current ServletContext. may not be null - */ - protected VelocityEngine newVelocityEngine(ServletContext context) { - if (context == null) { - String gripe = "Error attempting to create a new VelocityEngine from a null ServletContext!"; - log.error(gripe); - throw new IllegalArgumentException(gripe); - } - - Properties p = loadConfiguration(context); - - VelocityEngine velocityEngine = new VelocityEngine(); - - // Set the velocity attribute for the servlet context - // if this is not set the webapp loader WILL NOT WORK - velocityEngine.setApplicationAttribute(ServletContext.class.getName(), - context); - - try { - velocityEngine.init(p); - } catch (Exception e) { - String gripe = "Unable to instantiate VelocityEngine!"; - throw new StrutsException(gripe, e); - } - - return velocityEngine; - } - - /** - * once we've loaded up the user defined configurations, we will want to - * apply Struts specification configurations. - *
        - *
      • if Velocity.RESOURCE_LOADER has not been defined, then we will use - * the defaults which is a joined file, class loader for unpackaed wars and - * a straight class loader otherwise
      • - *
      • we need to define the various Struts custom user directives such as - * #param, #tag, and #bodytag
      • - *
      - * - * @param context - * @param p - */ - @SuppressWarnings("rawtypes") - private void applyDefaultConfiguration(ServletContext context, Properties p) { - // ensure that caching isn't overly aggressive - - /** - * Load a default resource loader definition if there isn't one present. - * Ben Hall (22/08/2003) - */ - if (p.getProperty(Velocity.RESOURCE_LOADER) == null) { - p.setProperty(Velocity.RESOURCE_LOADER, "strutsfile, strutsclass"); - } - - /** - * If there's a "real" path add it for the strutsfile resource loader. - * If there's no real path and they haven't configured a loader then we - * change resource loader property to just use the strutsclass loader - * Ben Hall (22/08/2003) - */ - if (context.getRealPath("") != null) { - p.setProperty("strutsfile.resource.loader.description", - "Velocity File Resource Loader"); - p.setProperty("strutsfile.resource.loader.class", - "org.apache.velocity.runtime.resource.loader.FileResourceLoader"); - p.setProperty("strutsfile.resource.loader.path", - context.getRealPath("")); - p.setProperty( - "strutsfile.resource.loader.modificationCheckInterval", "2"); - p.setProperty("strutsfile.resource.loader.cache", "true"); - } else { - // remove strutsfile from resource loader property - String prop = p.getProperty(Velocity.RESOURCE_LOADER); - if (prop.indexOf("strutsfile,") != -1) { - prop = replace(prop, "strutsfile,", ""); - } else if (prop.indexOf(", strutsfile") != -1) { - prop = replace(prop, ", strutsfile", ""); - } else if (prop.indexOf("strutsfile") != -1) { - prop = replace(prop, "strutsfile", ""); - } - - p.setProperty(Velocity.RESOURCE_LOADER, prop); - } - - /** - * Refactored the Velocity templates for the Struts taglib into the - * classpath from the web path. This will enable Struts projects to have - * access to the templates by simply including the Struts jar file. - * Unfortunately, there does not appear to be a macro for the class - * loader keywords Matt Ho - Mon Mar 17 00:21:46 PST 2003 - */ - p.setProperty("strutsclass.resource.loader.description", - "Velocity Classpath Resource Loader"); - p.setProperty("strutsclass.resource.loader.class", - "org.apache.struts2.views.velocity.StrutsResourceLoader"); - p.setProperty("strutsclass.resource.loader.modificationCheckInterval", - "2"); - p.setProperty("strutsclass.resource.loader.cache", "true"); - - // components - StringBuffer sb = new StringBuffer(); - - for (TagLibrary tagLibrary : tagLibraries) { - List directives = tagLibrary.getVelocityDirectiveClasses(); - for (Class directive : directives) { - addDirective(sb, directive); - } - } - - String directives = sb.toString(); - - String userdirective = p.getProperty("userdirective"); - if ((userdirective == null) || userdirective.trim().equals("")) { - userdirective = directives; - } else { - userdirective = userdirective.trim() + "," + directives; - } - - p.setProperty("userdirective", userdirective); - } - - @SuppressWarnings("rawtypes") - private void addDirective(StringBuffer sb, Class clazz) { - sb.append(clazz.getName()).append(","); - } - - private static final String replace(String string, String oldString, - String newString) { - if (string == null) { - return null; - } - // If the newString is null, just return the string since there's - // nothing to replace. - if (newString == null) { - return string; - } - int i = 0; - // Make sure that oldString appears at least once before doing any - // processing. - if ((i = string.indexOf(oldString, i)) >= 0) { - // Use char []'s, as they are more efficient to deal with. - char[] string2 = string.toCharArray(); - char[] newString2 = newString.toCharArray(); - int oLength = oldString.length(); - StringBuffer buf = new StringBuffer(string2.length); - buf.append(string2, 0, i).append(newString2); - i += oLength; - int j = i; - // Replace all remaining instances of oldString with newString. - while ((i = string.indexOf(oldString, i)) > 0) { - buf.append(string2, j, i - j).append(newString2); - i += oLength; - j = i; - } - buf.append(string2, j, string2.length - j); - return buf.toString(); - } - return string; - } - - /** - * @return the velocityProperties - */ - public Properties getVelocityProperties() { - return velocityProperties; - } - - /** - * @param velocityProperties - * the velocityProperties to set - */ - public void setVelocityProperties(Properties velocityProperties) { - this.velocityProperties = velocityProperties; - } -} diff --git a/src/resource/export.vm b/src/resource/export.vm deleted file mode 100644 index 386565928..000000000 --- a/src/resource/export.vm +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - -
      - #foreach($module in $project.moduleListOrdered) - #set($moduleNo = $velocityCount) -
      -

      $moduleNo $module.name

      - #foreach($page in $module.pageListOrdered) - #set($pageNo = $velocityCount) -
      -

      $moduleNo.$pageNo $page.name

      - #foreach($action in $page.actionListOrdered) - #set($actionNo = $velocityCount) -
      -

      $moduleNo.$pageNo.$actionNo $action.name

      -

      Description

      -
      $action.description
      -

      Request Param List

      - $action.requestParameterListHTML -

      Response Param List

      - $action.responseParameterListHTML -
      - #end -
      - #end -
      - #end -
      - - diff --git a/src/struts.xml b/src/struts.xml deleted file mode 100644 index a29bdbced..000000000 --- a/src/struts.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - __cas__st__,__cas__id__,.*xwork\.MethodAccessor\.denyMethodExecution.*,.*java.lang.Runtime@getRuntime.* - - - - input,back,cancel,browse - - - input,back,cancel,browse - - - - - - - /account/login.vm - /error.vm - /bcom/jsonError.cb.vm - /error.vm - /common/redirect.vm - - - - - - - - - - - - - - - - - - - - - - - - -