diff --git a/CHANGELOG.md b/CHANGELOG.md index 860e26c59ca..d1b390da5ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,134 +1,130 @@ # Changelog -## [3.7.0-nightly.7](https://github.com/pypeclub/OpenPype/tree/HEAD) +## [3.8.0-nightly.5](https://github.com/pypeclub/OpenPype/tree/HEAD) -[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.6.4...HEAD) +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/3.7.0...HEAD) ### πŸ“– Documentation -- docs\[website\]: Add Ellipse Studio \(logo\) as an OpenPype contributor [\#2324](https://github.com/pypeclub/OpenPype/pull/2324) +- Renamed to proper name [\#2546](https://github.com/pypeclub/OpenPype/pull/2546) +- Slack: Add review to notification message [\#2498](https://github.com/pypeclub/OpenPype/pull/2498) **πŸ†• New features** -- Settings UI use OpenPype styles [\#2296](https://github.com/pypeclub/OpenPype/pull/2296) +- Flame: OpenTimelineIO Export Modul [\#2398](https://github.com/pypeclub/OpenPype/pull/2398) **πŸš€ Enhancements** -- Settings: Webpublisher in hosts enum [\#2367](https://github.com/pypeclub/OpenPype/pull/2367) -- Hiero: python3 compatibility [\#2365](https://github.com/pypeclub/OpenPype/pull/2365) -- Burnins: Be able recognize mxf OPAtom format [\#2361](https://github.com/pypeclub/OpenPype/pull/2361) -- Local settings: Copyable studio paths [\#2349](https://github.com/pypeclub/OpenPype/pull/2349) -- Assets Widget: Clear model on project change [\#2345](https://github.com/pypeclub/OpenPype/pull/2345) -- General: OpenPype default modules hierarchy [\#2338](https://github.com/pypeclub/OpenPype/pull/2338) -- General: FFprobe error exception contain original error message [\#2328](https://github.com/pypeclub/OpenPype/pull/2328) -- Resolve: Add experimental button to menu [\#2325](https://github.com/pypeclub/OpenPype/pull/2325) -- Hiero: Add experimental tools action [\#2323](https://github.com/pypeclub/OpenPype/pull/2323) -- Input links: Cleanup and unification of differences [\#2322](https://github.com/pypeclub/OpenPype/pull/2322) -- General: Don't validate vendor bin with executing them [\#2317](https://github.com/pypeclub/OpenPype/pull/2317) -- General: Multilayer EXRs support [\#2315](https://github.com/pypeclub/OpenPype/pull/2315) -- General: Run process log stderr as info log level [\#2309](https://github.com/pypeclub/OpenPype/pull/2309) -- General: Reduce vendor imports [\#2305](https://github.com/pypeclub/OpenPype/pull/2305) -- Tools: Cleanup of unused classes [\#2304](https://github.com/pypeclub/OpenPype/pull/2304) -- Project Manager: Added ability to delete project [\#2298](https://github.com/pypeclub/OpenPype/pull/2298) -- Ftrack: Synchronize input links [\#2287](https://github.com/pypeclub/OpenPype/pull/2287) -- Nuke: extract baked review videos presets [\#2248](https://github.com/pypeclub/OpenPype/pull/2248) +- Settings: PathInput strip passed string [\#2550](https://github.com/pypeclub/OpenPype/pull/2550) +- General: Validate if current process OpenPype version is requested version [\#2529](https://github.com/pypeclub/OpenPype/pull/2529) +- General: Be able to use anatomy data in ffmpeg output arguments [\#2525](https://github.com/pypeclub/OpenPype/pull/2525) +- Expose toggle publish plug-in settings for Maya Look Shading Engine Naming [\#2521](https://github.com/pypeclub/OpenPype/pull/2521) +- Photoshop: Move implementation to OpenPype [\#2510](https://github.com/pypeclub/OpenPype/pull/2510) +- TimersManager: Move module one hierarchy higher [\#2501](https://github.com/pypeclub/OpenPype/pull/2501) +- Slack: notifications are sent with Openpype logo and bot name [\#2499](https://github.com/pypeclub/OpenPype/pull/2499) +- Ftrack: Event handlers settings [\#2496](https://github.com/pypeclub/OpenPype/pull/2496) +- Flame - create publishable clips [\#2495](https://github.com/pypeclub/OpenPype/pull/2495) +- Tools: Fix style and modality of errors in loader and creator [\#2489](https://github.com/pypeclub/OpenPype/pull/2489) +- Project Manager: Remove project button cleanup [\#2482](https://github.com/pypeclub/OpenPype/pull/2482) +- Tools: Be able to change models of tasks and assets widgets [\#2475](https://github.com/pypeclub/OpenPype/pull/2475) +- Publish pype: Reduce publish process defering [\#2464](https://github.com/pypeclub/OpenPype/pull/2464) +- Maya: Improve speed of Collect History logic [\#2460](https://github.com/pypeclub/OpenPype/pull/2460) +- Maya: Validate Rig Controllers - fix Error: in script editor [\#2459](https://github.com/pypeclub/OpenPype/pull/2459) +- Maya: Optimize Validate Locked Normals speed for dense polymeshes [\#2457](https://github.com/pypeclub/OpenPype/pull/2457) +- Fix \#2453 Refactor missing \_get\_reference\_node method [\#2455](https://github.com/pypeclub/OpenPype/pull/2455) +- Houdini: Remove broken unique name counter [\#2450](https://github.com/pypeclub/OpenPype/pull/2450) +- Maya: Improve lib.polyConstraint performance when Select tool is not the active tool context [\#2447](https://github.com/pypeclub/OpenPype/pull/2447) +- General: Validate third party before build [\#2425](https://github.com/pypeclub/OpenPype/pull/2425) +- Maya : add option to not group reference in ReferenceLoader [\#2383](https://github.com/pypeclub/OpenPype/pull/2383) **πŸ› Bug fixes** +- Fix published frame content for sequence starting with 0 [\#2513](https://github.com/pypeclub/OpenPype/pull/2513) +- Fix \#2497: reset empty string attributes correctly to "" instead of "None" [\#2506](https://github.com/pypeclub/OpenPype/pull/2506) +- General: Settings work if OpenPypeVersion is available [\#2494](https://github.com/pypeclub/OpenPype/pull/2494) +- General: PYTHONPATH may break OpenPype dependencies [\#2493](https://github.com/pypeclub/OpenPype/pull/2493) +- Workfiles tool: Files widget show files on first show [\#2488](https://github.com/pypeclub/OpenPype/pull/2488) +- General: Custom template paths filter fix [\#2483](https://github.com/pypeclub/OpenPype/pull/2483) +- Loader: Remove always on top flag in tray [\#2480](https://github.com/pypeclub/OpenPype/pull/2480) +- General: Anatomy does not return root envs as unicode [\#2465](https://github.com/pypeclub/OpenPype/pull/2465) +- Maya: Validate Shape Zero do not keep fixed geometry vertices selected/active after repair [\#2456](https://github.com/pypeclub/OpenPype/pull/2456) + +**Merged pull requests:** + +- General: Fix install thread in igniter [\#2549](https://github.com/pypeclub/OpenPype/pull/2549) +- AfterEffects: Move implementation to OpenPype [\#2543](https://github.com/pypeclub/OpenPype/pull/2543) +- Fix create zip tool - path argument [\#2522](https://github.com/pypeclub/OpenPype/pull/2522) +- General: Modules import function output fix [\#2492](https://github.com/pypeclub/OpenPype/pull/2492) +- AE: fix hiding of alert window below Publish [\#2491](https://github.com/pypeclub/OpenPype/pull/2491) +- Maya: Validate NGONs re-use polyConstraint code from openpype.host.maya.api.lib [\#2458](https://github.com/pypeclub/OpenPype/pull/2458) + +## [3.7.0](https://github.com/pypeclub/OpenPype/tree/3.7.0) (2022-01-04) + +[Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.7.0-nightly.14...3.7.0) + +**πŸš€ Enhancements** + +- General: Workdir extra folders [\#2462](https://github.com/pypeclub/OpenPype/pull/2462) +- Photoshop: New style validations for New publisher [\#2429](https://github.com/pypeclub/OpenPype/pull/2429) +- General: Environment variables groups [\#2424](https://github.com/pypeclub/OpenPype/pull/2424) +- Unreal: Dynamic menu created in Python [\#2422](https://github.com/pypeclub/OpenPype/pull/2422) +- Settings UI: Hyperlinks to settings [\#2420](https://github.com/pypeclub/OpenPype/pull/2420) +- Modules: JobQueue module moved one hierarchy level higher [\#2419](https://github.com/pypeclub/OpenPype/pull/2419) +- TimersManager: Start timer post launch hook [\#2418](https://github.com/pypeclub/OpenPype/pull/2418) +- General: Run applications as separate processes under linux [\#2408](https://github.com/pypeclub/OpenPype/pull/2408) +- Ftrack: Check existence of object type on recreation [\#2404](https://github.com/pypeclub/OpenPype/pull/2404) +- Enhancement: Global cleanup plugin that explicitly remove paths from context [\#2402](https://github.com/pypeclub/OpenPype/pull/2402) +- General: MongoDB ability to specify replica set groups [\#2401](https://github.com/pypeclub/OpenPype/pull/2401) +- Flame: moving `utility\_scripts` to api folder also with `scripts` [\#2385](https://github.com/pypeclub/OpenPype/pull/2385) +- Centos 7 dependency compatibility [\#2384](https://github.com/pypeclub/OpenPype/pull/2384) +- Enhancement: Settings: Use project settings values from another project [\#2382](https://github.com/pypeclub/OpenPype/pull/2382) +- Blender 3: Support auto install for new blender version [\#2377](https://github.com/pypeclub/OpenPype/pull/2377) +- Maya add render image path to settings [\#2375](https://github.com/pypeclub/OpenPype/pull/2375) + +**πŸ› Bug fixes** + +- TVPaint: Create render layer dialog is in front [\#2471](https://github.com/pypeclub/OpenPype/pull/2471) +- Short Pyblish plugin path [\#2428](https://github.com/pypeclub/OpenPype/pull/2428) +- PS: Introduced settings for invalid characters to use in ValidateNaming plugin [\#2417](https://github.com/pypeclub/OpenPype/pull/2417) +- Settings UI: Breadcrumbs path does not create new entities [\#2416](https://github.com/pypeclub/OpenPype/pull/2416) +- AfterEffects: Variant 2022 is in defaults but missing in schemas [\#2412](https://github.com/pypeclub/OpenPype/pull/2412) +- Nuke: baking representations was not additive [\#2406](https://github.com/pypeclub/OpenPype/pull/2406) +- General: Fix access to environments from default settings [\#2403](https://github.com/pypeclub/OpenPype/pull/2403) +- Fix: Placeholder Input color set fix [\#2399](https://github.com/pypeclub/OpenPype/pull/2399) +- Settings: Fix state change of wrapper label [\#2396](https://github.com/pypeclub/OpenPype/pull/2396) - Flame: fix ftrack publisher [\#2381](https://github.com/pypeclub/OpenPype/pull/2381) - hiero: solve custom ocio path [\#2379](https://github.com/pypeclub/OpenPype/pull/2379) - hiero: fix workio and flatten [\#2378](https://github.com/pypeclub/OpenPype/pull/2378) - Nuke: fixing menu re-drawing during context change [\#2374](https://github.com/pypeclub/OpenPype/pull/2374) - Webpublisher: Fix assignment of families of TVpaint instances [\#2373](https://github.com/pypeclub/OpenPype/pull/2373) -- Nuke: fixing node name based on switched asset name [\#2369](https://github.com/pypeclub/OpenPype/pull/2369) -- JobQueue: Fix loading of settings [\#2362](https://github.com/pypeclub/OpenPype/pull/2362) -- Tools: Placeholder color [\#2359](https://github.com/pypeclub/OpenPype/pull/2359) -- Launcher: Minimize button on MacOs [\#2355](https://github.com/pypeclub/OpenPype/pull/2355) -- StandalonePublisher: Fix import of constant [\#2354](https://github.com/pypeclub/OpenPype/pull/2354) -- Adobe products show issue [\#2347](https://github.com/pypeclub/OpenPype/pull/2347) -- Maya Look Assigner: Fix Python 3 compatibility [\#2343](https://github.com/pypeclub/OpenPype/pull/2343) -- Remove wrongly used host for hook [\#2342](https://github.com/pypeclub/OpenPype/pull/2342) -- Tools: Use Qt context on tools show [\#2340](https://github.com/pypeclub/OpenPype/pull/2340) -- Flame: Fix default argument value in custom dictionary [\#2339](https://github.com/pypeclub/OpenPype/pull/2339) -- Timers Manager: Disable auto stop timer on linux platform [\#2334](https://github.com/pypeclub/OpenPype/pull/2334) -- nuke: bake preset single input exception [\#2331](https://github.com/pypeclub/OpenPype/pull/2331) -- Hiero: fixing multiple templates at a hierarchy parent [\#2330](https://github.com/pypeclub/OpenPype/pull/2330) -- Fix - provider icons are pulled from a folder [\#2326](https://github.com/pypeclub/OpenPype/pull/2326) -- InputLinks: Typo in "inputLinks" key [\#2314](https://github.com/pypeclub/OpenPype/pull/2314) -- Deadline timeout and logging [\#2312](https://github.com/pypeclub/OpenPype/pull/2312) -- nuke: do not multiply representation on class method [\#2311](https://github.com/pypeclub/OpenPype/pull/2311) -- Workfiles tool: Fix task formatting [\#2306](https://github.com/pypeclub/OpenPype/pull/2306) -- Delivery: Fix delivery paths created on windows [\#2302](https://github.com/pypeclub/OpenPype/pull/2302) -- Maya: Deadline - fix limit groups [\#2295](https://github.com/pypeclub/OpenPype/pull/2295) -- Royal Render: Fix plugin order and OpenPype auto-detection [\#2291](https://github.com/pypeclub/OpenPype/pull/2291) -- Alternate site for site sync doesnt work for sequences [\#2284](https://github.com/pypeclub/OpenPype/pull/2284) **Merged pull requests:** -- Linux : flip updating submodules logic [\#2357](https://github.com/pypeclub/OpenPype/pull/2357) -- Update of avalon-core [\#2346](https://github.com/pypeclub/OpenPype/pull/2346) -- Maya: configurable model top level validation [\#2321](https://github.com/pypeclub/OpenPype/pull/2321) +- Forced cx\_freeze to include sqlite3 into build [\#2432](https://github.com/pypeclub/OpenPype/pull/2432) +- Maya: Replaced PATH usage with vendored oiio path for maketx utility [\#2405](https://github.com/pypeclub/OpenPype/pull/2405) +- \[Fix\]\[MAYA\] Handle message type attribute within CollectLook [\#2394](https://github.com/pypeclub/OpenPype/pull/2394) +- Add validator to check correct version of extension for PS and AE [\#2387](https://github.com/pypeclub/OpenPype/pull/2387) ## [3.6.4](https://github.com/pypeclub/OpenPype/tree/3.6.4) (2021-11-23) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.7.0-nightly.1...3.6.4) -**πŸ› Bug fixes** - -- Nuke: inventory update removes all loaded read nodes [\#2294](https://github.com/pypeclub/OpenPype/pull/2294) - ## [3.6.3](https://github.com/pypeclub/OpenPype/tree/3.6.3) (2021-11-19) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.6.3-nightly.1...3.6.3) -**πŸ› Bug fixes** - -- Deadline: Fix publish targets [\#2280](https://github.com/pypeclub/OpenPype/pull/2280) - ## [3.6.2](https://github.com/pypeclub/OpenPype/tree/3.6.2) (2021-11-18) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.6.2-nightly.2...3.6.2) -**πŸš€ Enhancements** - -- Tools: Assets widget [\#2265](https://github.com/pypeclub/OpenPype/pull/2265) -- SceneInventory: Choose loader in asset switcher [\#2262](https://github.com/pypeclub/OpenPype/pull/2262) -- Style: New fonts in OpenPype style [\#2256](https://github.com/pypeclub/OpenPype/pull/2256) -- Tools: Tasks widget [\#2251](https://github.com/pypeclub/OpenPype/pull/2251) -- Tools: Creator in OpenPype [\#2244](https://github.com/pypeclub/OpenPype/pull/2244) - -**πŸ› Bug fixes** - -- Tools: Parenting of tools in Nuke and Hiero [\#2266](https://github.com/pypeclub/OpenPype/pull/2266) -- limiting validator to specific editorial hosts [\#2264](https://github.com/pypeclub/OpenPype/pull/2264) -- Tools: Select Context dialog attribute fix [\#2261](https://github.com/pypeclub/OpenPype/pull/2261) -- Maya: Render publishing fails on linux [\#2260](https://github.com/pypeclub/OpenPype/pull/2260) -- LookAssigner: Fix tool reopen [\#2259](https://github.com/pypeclub/OpenPype/pull/2259) -- Standalone: editorial not publishing thumbnails on all subsets [\#2258](https://github.com/pypeclub/OpenPype/pull/2258) -- Burnins: Support mxf metadata [\#2247](https://github.com/pypeclub/OpenPype/pull/2247) - ## [3.6.1](https://github.com/pypeclub/OpenPype/tree/3.6.1) (2021-11-16) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.6.1-nightly.1...3.6.1) -**πŸ› Bug fixes** - -- Loader doesn't allow changing of version before loading [\#2254](https://github.com/pypeclub/OpenPype/pull/2254) - ## [3.6.0](https://github.com/pypeclub/OpenPype/tree/3.6.0) (2021-11-15) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.6.0-nightly.6...3.6.0) -**πŸš€ Enhancements** - -- Tools: SceneInventory in OpenPype [\#2255](https://github.com/pypeclub/OpenPype/pull/2255) -- Tools: Subset manager in OpenPype [\#2243](https://github.com/pypeclub/OpenPype/pull/2243) - -**πŸ› Bug fixes** - -- Ftrack: Sync project ftrack id cache issue [\#2250](https://github.com/pypeclub/OpenPype/pull/2250) -- Ftrack: Session creation and Prepare project [\#2245](https://github.com/pypeclub/OpenPype/pull/2245) - ## [3.5.0](https://github.com/pypeclub/OpenPype/tree/3.5.0) (2021-10-17) [Full Changelog](https://github.com/pypeclub/OpenPype/compare/CI/3.5.0-nightly.8...3.5.0) diff --git a/Dockerfile.centos7 b/Dockerfile.centos7 index f3b257e66b4..736a42663c4 100644 --- a/Dockerfile.centos7 +++ b/Dockerfile.centos7 @@ -41,6 +41,8 @@ RUN yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.n ncurses \ ncurses-devel \ qt5-qtbase-devel \ + xcb-util-wm \ + xcb-util-renderutil \ && yum clean all # we need to build our own patchelf @@ -92,7 +94,8 @@ RUN source $HOME/.bashrc \ RUN cp /usr/lib64/libffi* ./build/exe.linux-x86_64-3.7/lib \ && cp /usr/lib64/libssl* ./build/exe.linux-x86_64-3.7/lib \ && cp /usr/lib64/libcrypto* ./build/exe.linux-x86_64-3.7/lib \ - && cp /root/.pyenv/versions/${OPENPYPE_PYTHON_VERSION}/lib/libpython* ./build/exe.linux-x86_64-3.7/lib + && cp /root/.pyenv/versions/${OPENPYPE_PYTHON_VERSION}/lib/libpython* ./build/exe.linux-x86_64-3.7/lib \ + && cp /usr/lib64/libxcb* ./build/exe.linux-x86_64-3.7/vendor/python/PySide2/Qt/lib RUN cd /opt/openpype \ rm -rf ./vendor/bin diff --git a/app_launcher.py b/app_launcher.py new file mode 100644 index 00000000000..6dc15183706 --- /dev/null +++ b/app_launcher.py @@ -0,0 +1,49 @@ +"""Launch process that is not child process of python or OpenPype. + +This is written for linux distributions where process tree may affect what +is when closed or blocked to be closed. +""" + +import os +import sys +import subprocess +import json + + +def main(input_json_path): + """Read launch arguments from json file and launch the process. + + Expected that json contains "args" key with string or list of strings. + + Arguments are converted to string using `list2cmdline`. At the end is added + `&` which will cause that launched process is detached and running as + "background" process. + + ## Notes + @iLLiCiT: This should be possible to do with 'disown' or double forking but + I didn't find a way how to do it properly. Disown didn't work as + expected for me and double forking killed parent process which is + unexpected too. + """ + with open(input_json_path, "r") as stream: + data = json.load(stream) + + # Change environment variables + env = data.get("env") or {} + for key, value in env.items(): + os.environ[key] = value + + # Prepare launch arguments + args = data["args"] + if isinstance(args, list): + args = subprocess.list2cmdline(args) + + # Run the command as background process + shell_cmd = args + " &" + os.system(shell_cmd) + sys.exit(0) + + +if __name__ == "__main__": + # Expect that last argument is path to a json with launch args information + main(sys.argv[-1]) diff --git a/igniter/__init__.py b/igniter/__init__.py index defd45e233a..02cba6a483a 100644 --- a/igniter/__init__.py +++ b/igniter/__init__.py @@ -6,9 +6,18 @@ os.chdir(os.path.dirname(__file__)) # for override sys.path in Deadline -from .bootstrap_repos import BootstrapRepos +from .bootstrap_repos import ( + BootstrapRepos, + OpenPypeVersion +) from .version import __version__ as version +# Store OpenPypeVersion to 'sys.modules' +# - this makes it available in OpenPype processes without modifying +# 'sys.path' or 'PYTHONPATH' +if "OpenPypeVersion" not in sys.modules: + sys.modules["OpenPypeVersion"] = OpenPypeVersion + def open_dialog(): """Show Igniter dialog.""" @@ -22,7 +31,9 @@ def open_dialog(): if scale_attr is not None: QtWidgets.QApplication.setAttribute(scale_attr) - app = QtWidgets.QApplication(sys.argv) + app = QtWidgets.QApplication.instance() + if not app: + app = QtWidgets.QApplication(sys.argv) d = InstallDialog() d.open() @@ -43,7 +54,9 @@ def open_update_window(openpype_version): if scale_attr is not None: QtWidgets.QApplication.setAttribute(scale_attr) - app = QtWidgets.QApplication(sys.argv) + app = QtWidgets.QApplication.instance() + if not app: + app = QtWidgets.QApplication(sys.argv) d = UpdateWindow(version=openpype_version) d.open() @@ -53,9 +66,32 @@ def open_update_window(openpype_version): return version_path +def show_message_dialog(title, message): + """Show dialog with a message and title to user.""" + if os.getenv("OPENPYPE_HEADLESS_MODE"): + print("!!! Can't open dialog in headless mode. Exiting.") + sys.exit(1) + from Qt import QtWidgets, QtCore + from .message_dialog import MessageDialog + + scale_attr = getattr(QtCore.Qt, "AA_EnableHighDpiScaling", None) + if scale_attr is not None: + QtWidgets.QApplication.setAttribute(scale_attr) + + app = QtWidgets.QApplication.instance() + if not app: + app = QtWidgets.QApplication(sys.argv) + + dialog = MessageDialog(title, message) + dialog.open() + + app.exec_() + + __all__ = [ "BootstrapRepos", "open_dialog", "open_update_window", + "show_message_dialog", "version" ] diff --git a/igniter/bootstrap_repos.py b/igniter/bootstrap_repos.py index 151597e505c..207253cd2d0 100644 --- a/igniter/bootstrap_repos.py +++ b/igniter/bootstrap_repos.py @@ -22,7 +22,10 @@ OpenPypeSecureRegistry, OpenPypeSettingsRegistry ) -from .tools import get_openpype_path_from_db +from .tools import ( + get_openpype_path_from_db, + get_expected_studio_version_str +) LOG_INFO = 0 @@ -60,6 +63,7 @@ class OpenPypeVersion(semver.VersionInfo): staging = False path = None _VERSION_REGEX = re.compile(r"(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$") # noqa: E501 + _installed_version = None def __init__(self, *args, **kwargs): """Create OpenPype version. @@ -232,6 +236,390 @@ def __hash__(self): else: return hash(str(self)) + @staticmethod + def is_version_in_dir( + dir_item: Path, version: OpenPypeVersion) -> Tuple[bool, str]: + """Test if path item is OpenPype version matching detected version. + + If item is directory that might (based on it's name) + contain OpenPype version, check if it really does contain + OpenPype and that their versions matches. + + Args: + dir_item (Path): Directory to test. + version (OpenPypeVersion): OpenPype version detected + from name. + + Returns: + Tuple: State and reason, True if it is valid OpenPype version, + False otherwise. + + """ + try: + # add one 'openpype' level as inside dir there should + # be many other repositories. + version_str = OpenPypeVersion.get_version_string_from_directory( + dir_item) # noqa: E501 + version_check = OpenPypeVersion(version=version_str) + except ValueError: + return False, f"cannot determine version from {dir_item}" + + version_main = version_check.get_main_version() + detected_main = version.get_main_version() + if version_main != detected_main: + return False, (f"dir version ({version}) and " + f"its content version ({version_check}) " + "doesn't match. Skipping.") + return True, "Versions match" + + @staticmethod + def is_version_in_zip( + zip_item: Path, version: OpenPypeVersion) -> Tuple[bool, str]: + """Test if zip path is OpenPype version matching detected version. + + Open zip file, look inside and parse version from OpenPype + inside it. If there is none, or it is different from + version specified in file name, skip it. + + Args: + zip_item (Path): Zip file to test. + version (OpenPypeVersion): Pype version detected + from name. + + Returns: + Tuple: State and reason, True if it is valid OpenPype version, + False otherwise. + + """ + # skip non-zip files + if zip_item.suffix.lower() != ".zip": + return False, "Not a zip" + + try: + with ZipFile(zip_item, "r") as zip_file: + with zip_file.open( + "openpype/version.py") as version_file: + zip_version = {} + exec(version_file.read(), zip_version) + try: + version_check = OpenPypeVersion( + version=zip_version["__version__"]) + except ValueError as e: + return False, str(e) + + version_main = version_check.get_main_version() # + # noqa: E501 + detected_main = version.get_main_version() + # noqa: E501 + + if version_main != detected_main: + return False, (f"zip version ({version}) " + f"and its content version " + f"({version_check}) " + "doesn't match. Skipping.") + except BadZipFile: + return False, f"{zip_item} is not a zip file" + except KeyError: + return False, "Zip does not contain OpenPype" + return True, "Versions match" + + @staticmethod + def get_version_string_from_directory(repo_dir: Path) -> Union[str, None]: + """Get version of OpenPype in given directory. + + Note: in frozen OpenPype installed in user data dir, this must point + one level deeper as it is: + `openpype-version-v3.0.0/openpype/version.py` + + Args: + repo_dir (Path): Path to OpenPype repo. + + Returns: + str: version string. + None: if OpenPype is not found. + + """ + # try to find version + version_file = Path(repo_dir) / "openpype" / "version.py" + if not version_file.exists(): + return None + + version = {} + with version_file.open("r") as fp: + exec(fp.read(), version) + + return version['__version__'] + + @classmethod + def get_openpype_path(cls): + """Path to openpype zip directory. + + Path can be set through environment variable 'OPENPYPE_PATH' which + is set during start of OpenPype if is not available. + """ + return os.getenv("OPENPYPE_PATH") + + @classmethod + def openpype_path_is_set(cls): + """Path to OpenPype zip directory is set.""" + if cls.get_openpype_path(): + return True + return False + + @classmethod + def openpype_path_is_accessible(cls): + """Path to OpenPype zip directory is accessible. + + Exists for this machine. + """ + # First check if is set + if not cls.openpype_path_is_set(): + return False + + # Validate existence + if Path(cls.get_openpype_path()).exists(): + return True + return False + + @classmethod + def get_local_versions( + cls, production: bool = None, staging: bool = None + ) -> List: + """Get all versions available on this machine. + + Arguments give ability to specify if filtering is needed. If both + arguments are set to None all found versions are returned. + + Args: + production (bool): Return production versions. + staging (bool): Return staging versions. + """ + # Return all local versions if arguments are set to None + if production is None and staging is None: + production = True + staging = True + + elif production is None and not staging: + production = True + + elif staging is None and not production: + staging = True + + # Just return empty output if both are disabled + if not production and not staging: + return [] + + dir_to_search = Path(user_data_dir("openpype", "pypeclub")) + versions = OpenPypeVersion.get_versions_from_directory( + dir_to_search + ) + filtered_versions = [] + for version in versions: + if version.is_staging(): + if staging: + filtered_versions.append(version) + elif production: + filtered_versions.append(version) + return list(sorted(set(filtered_versions))) + + @classmethod + def get_remote_versions( + cls, production: bool = None, staging: bool = None + ) -> List: + """Get all versions available in OpenPype Path. + + Arguments give ability to specify if filtering is needed. If both + arguments are set to None all found versions are returned. + + Args: + production (bool): Return production versions. + staging (bool): Return staging versions. + """ + # Return all local versions if arguments are set to None + if production is None and staging is None: + production = True + staging = True + + elif production is None and not staging: + production = True + + elif staging is None and not production: + staging = True + + # Just return empty output if both are disabled + if not production and not staging: + return [] + + dir_to_search = None + if cls.openpype_path_is_accessible(): + dir_to_search = Path(cls.get_openpype_path()) + else: + registry = OpenPypeSettingsRegistry() + try: + registry_dir = Path(str(registry.get_item("openPypePath"))) + if registry_dir.exists(): + dir_to_search = registry_dir + + except ValueError: + # nothing found in registry, we'll use data dir + pass + + if not dir_to_search: + return [] + + versions = cls.get_versions_from_directory(dir_to_search) + filtered_versions = [] + for version in versions: + if version.is_staging(): + if staging: + filtered_versions.append(version) + elif production: + filtered_versions.append(version) + return list(sorted(set(filtered_versions))) + + @staticmethod + def get_versions_from_directory(openpype_dir: Path) -> List: + """Get all detected OpenPype versions in directory. + + Args: + openpype_dir (Path): Directory to scan. + + Returns: + list of OpenPypeVersion + + Throws: + ValueError: if invalid path is specified. + + """ + if not openpype_dir.exists() and not openpype_dir.is_dir(): + raise ValueError("specified directory is invalid") + + _openpype_versions = [] + # iterate over directory in first level and find all that might + # contain OpenPype. + for item in openpype_dir.iterdir(): + + # if file, strip extension, in case of dir not. + name = item.name if item.is_dir() else item.stem + result = OpenPypeVersion.version_in_str(name) + + if result: + detected_version: OpenPypeVersion + detected_version = result + + if item.is_dir() and not OpenPypeVersion.is_version_in_dir( + item, detected_version + )[0]: + continue + + if item.is_file() and not OpenPypeVersion.is_version_in_zip( + item, detected_version + )[0]: + continue + + detected_version.path = item + _openpype_versions.append(detected_version) + + return sorted(_openpype_versions) + + @staticmethod + def get_installed_version_str() -> str: + """Get version of local OpenPype.""" + + version = {} + path = Path(os.environ["OPENPYPE_ROOT"]) / "openpype" / "version.py" + with open(path, "r") as fp: + exec(fp.read(), version) + return version["__version__"] + + @classmethod + def get_installed_version(cls): + """Get version of OpenPype inside build.""" + if cls._installed_version is None: + installed_version_str = cls.get_installed_version_str() + if installed_version_str: + cls._installed_version = OpenPypeVersion( + version=installed_version_str, + path=Path(os.environ["OPENPYPE_ROOT"]) + ) + return cls._installed_version + + @staticmethod + def get_latest_version( + staging: bool = False, + local: bool = None, + remote: bool = None + ) -> OpenPypeVersion: + """Get latest available version. + + The version does not contain information about path and source. + + This is utility version to get latest version from all found. Build + version is not listed if staging is enabled. + + Arguments 'local' and 'remote' define if local and remote repository + versions are used. All versions are used if both are not set (or set + to 'None'). If only one of them is set to 'True' the other is disabled. + It is possible to set both to 'True' (same as both set to None) and to + 'False' in that case only build version can be used. + + Args: + staging (bool, optional): List staging versions if True. + local (bool, optional): List local versions if True. + remote (bool, optional): List remote versions if True. + """ + if local is None and remote is None: + local = True + remote = True + + elif local is None and not remote: + local = True + + elif remote is None and not local: + remote = True + + installed_version = OpenPypeVersion.get_installed_version() + local_versions = [] + remote_versions = [] + if local: + local_versions = OpenPypeVersion.get_local_versions( + staging=staging + ) + if remote: + remote_versions = OpenPypeVersion.get_remote_versions( + staging=staging + ) + all_versions = local_versions + remote_versions + if not staging: + all_versions.append(installed_version) + + if not all_versions: + return None + + all_versions.sort() + return all_versions[-1] + + @classmethod + def get_expected_studio_version(cls, staging=False, global_settings=None): + """Expected OpenPype version that should be used at the moment. + + If version is not defined in settings the latest found version is + used. + + Using precached global settings is needed for usage inside OpenPype. + + Args: + staging (bool): Staging version or production version. + global_settings (dict): Optional precached global settings. + + Returns: + OpenPypeVersion: Version that should be used. + """ + result = get_expected_studio_version_str(staging, global_settings) + if not result: + return None + return OpenPypeVersion(version=result) + class BootstrapRepos: """Class for bootstrapping local OpenPype installation. @@ -301,16 +689,6 @@ def get_version_path_from_list( return v.path return None - @staticmethod - def get_local_live_version() -> str: - """Get version of local OpenPype.""" - - version = {} - path = Path(os.environ["OPENPYPE_ROOT"]) / "openpype" / "version.py" - with open(path, "r") as fp: - exec(fp.read(), version) - return version["__version__"] - @staticmethod def get_version(repo_dir: Path) -> Union[str, None]: """Get version of OpenPype in given directory. @@ -358,7 +736,7 @@ def create_version_from_live_code( # version and use it as a source. Otherwise repo_dir is user # entered location. if not repo_dir: - version = self.get_local_live_version() + version = OpenPypeVersion.get_installed_version_str() repo_dir = self.live_repo_dir else: version = self.get_version(repo_dir) @@ -384,7 +762,7 @@ def create_version_from_live_code( destination = self._move_zip_to_data_dir(temp_zip) - return OpenPypeVersion(version=version, path=destination) + return OpenPypeVersion(version=version, path=Path(destination)) def _move_zip_to_data_dir(self, zip_file) -> Union[None, Path]: """Move zip with OpenPype version to user data directory. @@ -534,7 +912,6 @@ def _create_openpype_zip(self, zip_path: Path, openpype_path: Path) -> None: processed_path = file self._print(f"- processing {processed_path}") - checksums.append( ( sha256sum(file.as_posix()), @@ -734,6 +1111,65 @@ def add_paths_from_directory(directory: Path) -> None: os.environ["PYTHONPATH"] = os.pathsep.join(paths) + @staticmethod + def find_openpype_version(version, staging): + if isinstance(version, str): + version = OpenPypeVersion(version=version) + + installed_version = OpenPypeVersion.get_installed_version() + if installed_version == version: + return installed_version + + local_versions = OpenPypeVersion.get_local_versions( + staging=staging, production=not staging + ) + zip_version = None + for local_version in local_versions: + if local_version == version: + if local_version.path.suffix.lower() == ".zip": + zip_version = local_version + else: + return local_version + + if zip_version is not None: + return zip_version + + remote_versions = OpenPypeVersion.get_remote_versions( + staging=staging, production=not staging + ) + for remote_version in remote_versions: + if remote_version == version: + return remote_version + return None + + @staticmethod + def find_latest_openpype_version(staging): + installed_version = OpenPypeVersion.get_installed_version() + local_versions = OpenPypeVersion.get_local_versions( + staging=staging + ) + remote_versions = OpenPypeVersion.get_remote_versions( + staging=staging + ) + all_versions = local_versions + remote_versions + if not staging: + all_versions.append(installed_version) + + if not all_versions: + return None + + all_versions.sort() + latest_version = all_versions[-1] + if latest_version == installed_version: + return latest_version + + if not latest_version.path.is_dir(): + for version in local_versions: + if version == latest_version and version.path.is_dir(): + latest_version = version + break + return latest_version + def find_openpype( self, openpype_path: Union[Path, str] = None, @@ -1107,7 +1543,8 @@ def _is_openpype_in_zip(self, Args: zip_item (Path): Zip file to test. - detected_version (OpenPypeVersion): Pype version detected from name. + detected_version (OpenPypeVersion): Pype version detected from + name. Returns: True if it is valid OpenPype version, False otherwise. diff --git a/igniter/install_dialog.py b/igniter/install_dialog.py index 1fe67e33975..251adebc9ff 100644 --- a/igniter/install_dialog.py +++ b/igniter/install_dialog.py @@ -12,7 +12,8 @@ from .install_thread import InstallThread from .tools import ( validate_mongo_connection, - get_openpype_path_from_db + get_openpype_path_from_db, + get_openpype_icon_path ) from .nice_progress_bar import NiceProgressBar @@ -187,7 +188,6 @@ def __init__(self, parent=None): current_dir = os.path.dirname(os.path.abspath(__file__)) roboto_font_path = os.path.join(current_dir, "RobotoMono-Regular.ttf") poppins_font_path = os.path.join(current_dir, "Poppins") - icon_path = os.path.join(current_dir, "openpype_icon.png") # Install roboto font QtGui.QFontDatabase.addApplicationFont(roboto_font_path) @@ -196,6 +196,7 @@ def __init__(self, parent=None): QtGui.QFontDatabase.addApplicationFont(filename) # Load logo + icon_path = get_openpype_icon_path() pixmap_openpype_logo = QtGui.QPixmap(icon_path) # Set logo as icon of window self.setWindowIcon(QtGui.QIcon(pixmap_openpype_logo)) diff --git a/igniter/install_thread.py b/igniter/install_thread.py index 383012b88b5..8e31f8cb8fe 100644 --- a/igniter/install_thread.py +++ b/igniter/install_thread.py @@ -60,7 +60,7 @@ def run(self): # find local version of OpenPype bs = BootstrapRepos( progress_callback=self.set_progress, message=self.message) - local_version = bs.get_local_live_version() + local_version = OpenPypeVersion.get_installed_version_str() # if user did entered nothing, we install OpenPype from local version. # zip content of `repos`, copy it to user data dir and append diff --git a/igniter/message_dialog.py b/igniter/message_dialog.py new file mode 100644 index 00000000000..c8e875cc37e --- /dev/null +++ b/igniter/message_dialog.py @@ -0,0 +1,44 @@ +from Qt import QtWidgets, QtGui + +from .tools import ( + load_stylesheet, + get_openpype_icon_path +) + + +class MessageDialog(QtWidgets.QDialog): + """Simple message dialog with title, message and OK button.""" + def __init__(self, title, message): + super(MessageDialog, self).__init__() + + # Set logo as icon of window + icon_path = get_openpype_icon_path() + pixmap_openpype_logo = QtGui.QPixmap(icon_path) + self.setWindowIcon(QtGui.QIcon(pixmap_openpype_logo)) + + # Set title + self.setWindowTitle(title) + + # Set message + label_widget = QtWidgets.QLabel(message, self) + + ok_btn = QtWidgets.QPushButton("OK", self) + btns_layout = QtWidgets.QHBoxLayout() + btns_layout.addStretch(1) + btns_layout.addWidget(ok_btn, 0) + + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(label_widget, 1) + layout.addLayout(btns_layout, 0) + + ok_btn.clicked.connect(self._on_ok_clicked) + + self._label_widget = label_widget + self._ok_btn = ok_btn + + def _on_ok_clicked(self): + self.close() + + def showEvent(self, event): + super(MessageDialog, self).showEvent(event) + self.setStyleSheet(load_stylesheet()) diff --git a/igniter/tools.py b/igniter/tools.py index 3e862f58030..735402e9a2d 100644 --- a/igniter/tools.py +++ b/igniter/tools.py @@ -16,6 +16,11 @@ ) +class OpenPypeVersionNotFound(Exception): + """OpenPype version was not found in remote and local repository.""" + pass + + def should_add_certificate_path_to_mongo_url(mongo_url): """Check if should add ca certificate to mongo url. @@ -182,6 +187,28 @@ def get_openpype_path_from_db(url: str) -> Union[str, None]: return None +def get_expected_studio_version_str( + staging=False, global_settings=None +) -> str: + """Version that should be currently used in studio. + + Args: + staging (bool): Get current version for staging. + global_settings (dict): Optional precached global settings. + + Returns: + str: OpenPype version which should be used. Empty string means latest. + """ + mongo_url = os.environ.get("OPENPYPE_MONGO") + if global_settings is None: + global_settings = get_openpype_global_settings(mongo_url) + if staging: + key = "staging_version" + else: + key = "production_version" + return global_settings.get(key) or "" + + def load_stylesheet() -> str: """Load css style sheet. @@ -192,3 +219,11 @@ def load_stylesheet() -> str: stylesheet_path = Path(__file__).parent.resolve() / "stylesheet.css" return stylesheet_path.read_text() + + +def get_openpype_icon_path() -> str: + """Path to OpenPype icon png file.""" + return os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "openpype_icon.png" + ) diff --git a/openpype/action.py b/openpype/action.py index 3fc6dd1a8f6..50741875e48 100644 --- a/openpype/action.py +++ b/openpype/action.py @@ -72,7 +72,7 @@ class RepairContextAction(pyblish.api.Action): is available on the plugin. """ - label = "Repair Context" + label = "Repair" on = "failed" # This action is only available on a failed plug-in def process(self, context, plugin): diff --git a/openpype/api.py b/openpype/api.py index a6529202ff2..51854492abb 100644 --- a/openpype/api.py +++ b/openpype/api.py @@ -31,8 +31,6 @@ ) from .lib.mongo import ( - decompose_url, - compose_url, get_default_components ) @@ -84,8 +82,6 @@ "Anatomy", "config", "execute", - "decompose_url", - "compose_url", "get_default_components", "ApplicationManager", "BuildWorkfile", diff --git a/openpype/cli.py b/openpype/cli.py index 4c4dc1a3c66..6e9c237b0e1 100644 --- a/openpype/cli.py +++ b/openpype/cli.py @@ -138,7 +138,10 @@ def webpublisherwebserver(debug, executable, upload_dir, host=None, port=None): @click.option("--asset", help="Asset name", default=None) @click.option("--task", help="Task name", default=None) @click.option("--app", help="Application name", default=None) -def extractenvironments(output_json_path, project, asset, task, app): +@click.option( + "--envgroup", help="Environment group (e.g. \"farm\")", default=None +) +def extractenvironments(output_json_path, project, asset, task, app, envgroup): """Extract environment variables for entered context to a json file. Entered output filepath will be created if does not exists. @@ -149,7 +152,7 @@ def extractenvironments(output_json_path, project, asset, task, app): Context options are "project", "asset", "task", "app" """ PypeCommands.extractenvironments( - output_json_path, project, asset, task, app + output_json_path, project, asset, task, app, envgroup ) @@ -356,9 +359,22 @@ def run(script): "--pyargs", help="Run tests from package", default=None) -def runtests(folder, mark, pyargs): +@click.option("-t", + "--test_data_folder", + help="Unzipped directory path of test file", + default=None) +@click.option("-s", + "--persist", + help="Persist test DB and published files after test end", + default=None) +@click.option("-a", + "--app_variant", + help="Provide specific app variant for test, empty for latest", + default=None) +def runtests(folder, mark, pyargs, test_data_folder, persist, app_variant): """Run all automatic tests after proper initialization via start.py""" - PypeCommands().run_tests(folder, mark, pyargs) + PypeCommands().run_tests(folder, mark, pyargs, test_data_folder, + persist, app_variant) @main.command() diff --git a/openpype/hooks/pre_create_extra_workdir_folders.py b/openpype/hooks/pre_create_extra_workdir_folders.py new file mode 100644 index 00000000000..d79c5831ee1 --- /dev/null +++ b/openpype/hooks/pre_create_extra_workdir_folders.py @@ -0,0 +1,33 @@ +import os +from openpype.lib import ( + PreLaunchHook, + create_workdir_extra_folders +) + + +class AddLastWorkfileToLaunchArgs(PreLaunchHook): + """Add last workfile path to launch arguments. + + This is not possible to do for all applications the same way. + """ + + # Execute after workfile template copy + order = 15 + + def execute(self): + if not self.application.is_host: + return + + env = self.data.get("env") or {} + workdir = env.get("AVALON_WORKDIR") + if not workdir or not os.path.exists(workdir): + return + + host_name = self.application.host_name + task_type = self.data["task_type"] + task_name = self.data["task_name"] + project_name = self.data["project_name"] + + create_workdir_extra_folders( + workdir, host_name, task_type, task_name, project_name, + ) diff --git a/openpype/hooks/pre_global_host_data.py b/openpype/hooks/pre_global_host_data.py index b32fb5e44a2..6b08cdb444c 100644 --- a/openpype/hooks/pre_global_host_data.py +++ b/openpype/hooks/pre_global_host_data.py @@ -48,7 +48,7 @@ def execute(self): "log": self.log }) - prepare_host_environments(temp_data) + prepare_host_environments(temp_data, self.launch_context.env_group) prepare_context_environments(temp_data) temp_data.pop("log") diff --git a/openpype/hooks/pre_non_python_host_launch.py b/openpype/hooks/pre_non_python_host_launch.py index 848ed675a82..29e40d28c8a 100644 --- a/openpype/hooks/pre_non_python_host_launch.py +++ b/openpype/hooks/pre_non_python_host_launch.py @@ -3,7 +3,7 @@ from openpype.lib import ( PreLaunchHook, - get_pype_execute_args + get_openpype_execute_args ) from openpype import PACKAGE_DIR as OPENPYPE_DIR @@ -35,7 +35,7 @@ def execute(self): "non_python_host_launch.py" ) - new_launch_args = get_pype_execute_args( + new_launch_args = get_openpype_execute_args( "run", script_path, executable_path ) # Add workfile path if exists @@ -48,4 +48,3 @@ def execute(self): if remainders: self.launch_context.launch_args.extend(remainders) - diff --git a/openpype/hosts/aftereffects/api/README.md b/openpype/hosts/aftereffects/api/README.md new file mode 100644 index 00000000000..790c9f859a4 --- /dev/null +++ b/openpype/hosts/aftereffects/api/README.md @@ -0,0 +1,66 @@ +# AfterEffects Integration + +Requirements: This extension requires use of Javascript engine, which is +available since CC 16.0. +Please check your File>Project Settings>Expressions>Expressions Engine + +## Setup + +The After Effects integration requires two components to work; `extension` and `server`. + +### Extension + +To install the extension download [Extension Manager Command Line tool (ExManCmd)](https://github.com/Adobe-CEP/Getting-Started-guides/tree/master/Package%20Distribute%20Install#option-2---exmancmd). + +``` +ExManCmd /install {path to avalon-core}\avalon\photoshop\extension.zxp +``` +OR +download [Anastasiy’s Extension Manager](https://install.anastasiy.com/) + +### Server + +The easiest way to get the server and After Effects launch is with: + +``` +python -c ^"import avalon.photoshop;avalon.aftereffects.launch(""c:\Program Files\Adobe\Adobe After Effects 2020\Support Files\AfterFX.exe"")^" +``` + +`avalon.aftereffects.launch` launches the application and server, and also closes the server when After Effects exists. + +## Usage + +The After Effects extension can be found under `Window > Extensions > OpenPype`. Once launched you should be presented with a panel like this: + +![Avalon Panel](panel.PNG "Avalon Panel") + + +## Developing + +### Extension +When developing the extension you can load it [unsigned](https://github.com/Adobe-CEP/CEP-Resources/blob/master/CEP_9.x/Documentation/CEP%209.0%20HTML%20Extension%20Cookbook.md#debugging-unsigned-extensions). + +When signing the extension you can use this [guide](https://github.com/Adobe-CEP/Getting-Started-guides/tree/master/Package%20Distribute%20Install#package-distribute-install-guide). + +``` +ZXPSignCmd -selfSignedCert NA NA Avalon Avalon-After-Effects avalon extension.p12 +ZXPSignCmd -sign {path to avalon-core}\avalon\aftereffects\extension {path to avalon-core}\avalon\aftereffects\extension.zxp extension.p12 avalon +``` + +### Plugin Examples + +These plugins were made with the [polly config](https://github.com/mindbender-studio/config). To fully integrate and load, you will have to use this config and add `image` to the [integration plugin](https://github.com/mindbender-studio/config/blob/master/polly/plugins/publish/integrate_asset.py). + +Expected deployed extension location on default Windows: +`c:\Program Files (x86)\Common Files\Adobe\CEP\extensions\com.openpype.AE.panel` + +For easier debugging of Javascript: +https://community.adobe.com/t5/download-install/adobe-extension-debuger-problem/td-p/10911704?page=1 +Add (optional) --enable-blink-features=ShadowDOMV0,CustomElementsV0 when starting Chrome +then localhost:8092 + +Or use Visual Studio Code https://medium.com/adobetech/extendscript-debugger-for-visual-studio-code-public-release-a2ff6161fa01 +## Resources + - https://javascript-tools-guide.readthedocs.io/introduction/index.html + - https://github.com/Adobe-CEP/Getting-Started-guides + - https://github.com/Adobe-CEP/CEP-Resources diff --git a/openpype/hosts/aftereffects/api/__init__.py b/openpype/hosts/aftereffects/api/__init__.py index b1edb91a5ca..cea1bdc0236 100644 --- a/openpype/hosts/aftereffects/api/__init__.py +++ b/openpype/hosts/aftereffects/api/__init__.py @@ -1,115 +1,68 @@ -import os -import sys -import logging - -from avalon import io -from avalon import api as avalon -from Qt import QtWidgets -from openpype import lib, api -import pyblish.api as pyblish -import openpype.hosts.aftereffects - - -log = logging.getLogger("openpype.hosts.aftereffects") - - -HOST_DIR = os.path.dirname(os.path.abspath(openpype.hosts.aftereffects.__file__)) -PLUGINS_DIR = os.path.join(HOST_DIR, "plugins") -PUBLISH_PATH = os.path.join(PLUGINS_DIR, "publish") -LOAD_PATH = os.path.join(PLUGINS_DIR, "load") -CREATE_PATH = os.path.join(PLUGINS_DIR, "create") -INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") - - -def check_inventory(): - if not lib.any_outdated(): - return - - host = pyblish.registered_host() - outdated_containers = [] - for container in host.ls(): - representation = container['representation'] - representation_doc = io.find_one( - { - "_id": io.ObjectId(representation), - "type": "representation" - }, - projection={"parent": True} - ) - if representation_doc and not lib.is_latest(representation_doc): - outdated_containers.append(container) - - # Warn about outdated containers. - print("Starting new QApplication..") - app = QtWidgets.QApplication(sys.argv) - - message_box = QtWidgets.QMessageBox() - message_box.setIcon(QtWidgets.QMessageBox.Warning) - msg = "There are outdated containers in the scene." - message_box.setText(msg) - message_box.exec_() - - # Garbage collect QApplication. - del app - - -def application_launch(): - check_inventory() - - -def install(): - print("Installing Pype config...") - - pyblish.register_plugin_path(PUBLISH_PATH) - avalon.register_plugin_path(avalon.Loader, LOAD_PATH) - avalon.register_plugin_path(avalon.Creator, CREATE_PATH) - log.info(PUBLISH_PATH) - - pyblish.register_callback( - "instanceToggled", on_pyblish_instance_toggled - ) - - avalon.on("application.launched", application_launch) - - -def uninstall(): - pyblish.deregister_plugin_path(PUBLISH_PATH) - avalon.deregister_plugin_path(avalon.Loader, LOAD_PATH) - avalon.deregister_plugin_path(avalon.Creator, CREATE_PATH) - - -def on_pyblish_instance_toggled(instance, old_value, new_value): - """Toggle layer visibility on instance toggles.""" - instance[0].Visible = new_value - - -def get_asset_settings(): - """Get settings on current asset from database. - - Returns: - dict: Scene data. - - """ - asset_data = lib.get_asset()["data"] - fps = asset_data.get("fps") - frame_start = asset_data.get("frameStart") - frame_end = asset_data.get("frameEnd") - handle_start = asset_data.get("handleStart") - handle_end = asset_data.get("handleEnd") - resolution_width = asset_data.get("resolutionWidth") - resolution_height = asset_data.get("resolutionHeight") - duration = (frame_end - frame_start + 1) + handle_start + handle_end - entity_type = asset_data.get("entityType") - - scene_data = { - "fps": fps, - "frameStart": frame_start, - "frameEnd": frame_end, - "handleStart": handle_start, - "handleEnd": handle_end, - "resolutionWidth": resolution_width, - "resolutionHeight": resolution_height, - "duration": duration - } - - return scene_data +"""Public API + +Anything that isn't defined here is INTERNAL and unreliable for external use. + +""" + +from .launch_logic import ( + get_stub, + stub, +) + +from .pipeline import ( + ls, + get_asset_settings, + install, + uninstall, + list_instances, + remove_instance, + containerise +) + +from .workio import ( + file_extensions, + has_unsaved_changes, + save_file, + open_file, + current_file, + work_root, +) + +from .lib import ( + maintained_selection, + get_extension_manifest_path +) + +from .plugin import ( + AfterEffectsLoader +) + + +__all__ = [ + # launch_logic + "get_stub", + "stub", + + # pipeline + "ls", + "get_asset_settings", + "install", + "uninstall", + "list_instances", + "remove_instance", + "containerise", + + "file_extensions", + "has_unsaved_changes", + "save_file", + "open_file", + "current_file", + "work_root", + + # lib + "maintained_selection", + "get_extension_manifest_path", + + # plugin + "AfterEffectsLoader" +] diff --git a/openpype/hosts/aftereffects/api/extension.zxp b/openpype/hosts/aftereffects/api/extension.zxp new file mode 100644 index 00000000000..35b0c0fc42a Binary files /dev/null and b/openpype/hosts/aftereffects/api/extension.zxp differ diff --git a/openpype/hosts/aftereffects/api/extension/.debug b/openpype/hosts/aftereffects/api/extension/.debug new file mode 100644 index 00000000000..b06ec515dde --- /dev/null +++ b/openpype/hosts/aftereffects/api/extension/.debug @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/openpype/hosts/aftereffects/api/extension/CSXS/manifest.xml b/openpype/hosts/aftereffects/api/extension/CSXS/manifest.xml new file mode 100644 index 00000000000..24800898252 --- /dev/null +++ b/openpype/hosts/aftereffects/api/extension/CSXS/manifest.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ./index.html + ./jsx/hostscript.jsx + + + true + + + Panel + OpenPype + + + 200 + 100 + + + + + + ./icons/iconNormal.png + ./icons/iconRollover.png + ./icons/iconDisabled.png + ./icons/iconDarkNormal.png + ./icons/iconDarkRollover.png + + + + + + \ No newline at end of file diff --git a/openpype/hosts/aftereffects/api/extension/css/boilerplate.css b/openpype/hosts/aftereffects/api/extension/css/boilerplate.css new file mode 100644 index 00000000000..d208999b8ac --- /dev/null +++ b/openpype/hosts/aftereffects/api/extension/css/boilerplate.css @@ -0,0 +1,327 @@ +/* + * HTML5 ✰ Boilerplate + * + * What follows is the result of much research on cross-browser styling. + * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, + * Kroc Camen, and the H5BP dev community and team. + * + * Detailed information about this CSS: h5bp.com/css + * + * ==|== normalize ========================================================== + */ + + +/* ============================================================================= + HTML5 display definitions + ========================================================================== */ + +article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } +audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } +audio:not([controls]) { display: none; } +[hidden] { display: none; } + + +/* ============================================================================= + Base + ========================================================================== */ + +/* + * 1. Correct text resizing oddly in IE6/7 when body font-size is set using em units + * 2. Force vertical scrollbar in non-IE + * 3. Prevent iOS text size adjust on device orientation change, without disabling user zoom: h5bp.com/g + */ + +html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } + +body { margin: 0; font-size: 100%; line-height: 1.231; } + +body, button, input, select, textarea { font-family: helvetica, arial,"lucida grande", verdana, "パむγƒͺγ‚ͺ", "οΌ­οΌ³ Pゴシック", sans-serif; color: #222; } +/* + * Remove text-shadow in selection highlight: h5bp.com/i + * These selection declarations have to be separate + * Also: hot pink! (or customize the background color to match your design) + */ + +::selection { text-shadow: none; background-color: highlight; color: highlighttext; } + + +/* ============================================================================= + Links + ========================================================================== */ + +a { color: #00e; } +a:visited { color: #551a8b; } +a:hover { color: #06e; } +a:focus { outline: thin dotted; } + +/* Improve readability when focused and hovered in all browsers: h5bp.com/h */ +a:hover, a:active { outline: 0; } + + +/* ============================================================================= + Typography + ========================================================================== */ + +abbr[title] { border-bottom: 1px dotted; } + +b, strong { font-weight: bold; } + +blockquote { margin: 1em 40px; } + +dfn { font-style: italic; } + +hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } + +ins { background: #ff9; color: #000; text-decoration: none; } + +mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } + +/* Redeclare monospace font family: h5bp.com/j */ +pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; } + +/* Improve readability of pre-formatted text in all browsers */ +pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } + +q { quotes: none; } +q:before, q:after { content: ""; content: none; } + +small { font-size: 85%; } + +/* Position subscript and superscript content without affecting line-height: h5bp.com/k */ +sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } +sup { top: -0.5em; } +sub { bottom: -0.25em; } + + +/* ============================================================================= + Lists + ========================================================================== */ + +ul, ol { margin: 1em 0; padding: 0 0 0 40px; } +dd { margin: 0 0 0 40px; } +nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; } + + +/* ============================================================================= + Embedded content + ========================================================================== */ + +/* + * 1. Improve image quality when scaled in IE7: h5bp.com/d + * 2. Remove the gap between images and borders on image containers: h5bp.com/e + */ + +img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; } + +/* + * Correct overflow not hidden in IE9 + */ + +svg:not(:root) { overflow: hidden; } + + +/* ============================================================================= + Figures + ========================================================================== */ + +figure { margin: 0; } + + +/* ============================================================================= + Forms + ========================================================================== */ + +form { margin: 0; } +fieldset { border: 0; margin: 0; padding: 0; } + +/* Indicate that 'label' will shift focus to the associated form element */ +label { cursor: pointer; } + +/* + * 1. Correct color not inheriting in IE6/7/8/9 + * 2. Correct alignment displayed oddly in IE6/7 + */ + +legend { border: 0; *margin-left: -7px; padding: 0; } + +/* + * 1. Correct font-size not inheriting in all browsers + * 2. Remove margins in FF3/4 S5 Chrome + * 3. Define consistent vertical alignment display in all browsers + */ + +button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } + +/* + * 1. Define line-height as normal to match FF3/4 (set using !important in the UA stylesheet) + */ + +button, input { line-height: normal; } + +/* + * 1. Display hand cursor for clickable form elements + * 2. Allow styling of clickable form elements in iOS + * 3. Correct inner spacing displayed oddly in IE7 (doesn't effect IE6) + */ + +button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; } + +/* + * Consistent box sizing and appearance + */ + +input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; } +input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; } +input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } + +/* + * Remove inner padding and border in FF3/4: h5bp.com/l + */ + +button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } + +/* + * 1. Remove default vertical scrollbar in IE6/7/8/9 + * 2. Allow only vertical resizing + */ + +textarea { overflow: auto; vertical-align: top; resize: vertical; } + +/* Colors for form validity */ +input:valid, textarea:valid { } +input:invalid, textarea:invalid { background-color: #f0dddd; } + + +/* ============================================================================= + Tables + ========================================================================== */ + +table { border-collapse: collapse; border-spacing: 0; } +td { vertical-align: top; } + + +/* ==|== primary styles ===================================================== + Author: + ========================================================================== */ + +/* ==|== media queries ====================================================== + PLACEHOLDER Media Queries for Responsive Design. + These override the primary ('mobile first') styles + Modify as content requires. + ========================================================================== */ + +@media only screen and (min-width: 480px) { + /* Style adjustments for viewports 480px and over go here */ + +} + +@media only screen and (min-width: 768px) { + /* Style adjustments for viewports 768px and over go here */ + +} + + + +/* ==|== non-semantic helper classes ======================================== + Please define your styles before this section. + ========================================================================== */ + +/* For image replacement */ +.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; } +.ir br { display: none; } + +/* Hide from both screenreaders and browsers: h5bp.com/u */ +.hidden { display: none !important; visibility: hidden; } + +/* Hide only visually, but have it available for screenreaders: h5bp.com/v */ +.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } + +/* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: h5bp.com/p */ +.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } + +/* Hide visually and from screenreaders, but maintain layout */ +.invisible { visibility: hidden; } + +/* Contain floats: h5bp.com/q */ +.clearfix:before, .clearfix:after { content: ""; display: table; } +.clearfix:after { clear: both; } +.clearfix { *zoom: 1; } + + + +/* ==|== print styles ======================================================= + Print styles. + Inlined to avoid required HTTP connection: h5bp.com/r + ========================================================================== */ + +@media print { + * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */ + a, a:visited { text-decoration: underline; } + a[href]:after { content: " (" attr(href) ")"; } + abbr[title]:after { content: " (" attr(title) ")"; } + .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } /* Don't show links for images, or javascript/internal links */ + pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } + table { display: table-header-group; } /* h5bp.com/t */ + tr, img { page-break-inside: avoid; } + img { max-width: 100% !important; } + @page { margin: 0.5cm; } + p, h2, h3 { orphans: 3; widows: 3; } + h2, h3 { page-break-after: avoid; } +} + +/* reflow reset for -webkit-margin-before: 1em */ +p { margin: 0; } + +html { + overflow-y: auto; + background-color: transparent; + height: 100%; +} + +body { + background: #fff; + font: normal 100%; + position: relative; + height: 100%; +} + +body, div, img, p, button, input, select, textarea { + box-sizing: border-box; +} + +.image { + display: block; +} + +input { + cursor: default; + display: block; +} + +input[type=button] { + background-color: #e5e9e8; + border: 1px solid #9daca9; + border-radius: 4px; + box-shadow: inset 0 1px #fff; + font: inherit; + letter-spacing: inherit; + text-indent: inherit; + color: inherit; +} + +input[type=button]:hover { + background-color: #eff1f1; +} + +input[type=button]:active { + background-color: #d2d6d6; + border: 1px solid #9daca9; + box-shadow: inset 0 1px rgba(0,0,0,0.1); +} + +/* Reset anchor styles to an unstyled default to be in parity with design surface. It + is presumed that most link styles in real-world designs are custom (non-default). */ +a, a:visited, a:hover, a:active { + color: inherit; + text-decoration: inherit; +} \ No newline at end of file diff --git a/openpype/hosts/aftereffects/api/extension/css/styles.css b/openpype/hosts/aftereffects/api/extension/css/styles.css new file mode 100644 index 00000000000..c9cf2b93acf --- /dev/null +++ b/openpype/hosts/aftereffects/api/extension/css/styles.css @@ -0,0 +1,51 @@ +/*Your styles*/ + + body { + margin: 10px; +} + + +#content { + margin-right:auto; + margin-left:auto; + vertical-align:middle; + width:100%; +} + + +#btn_test{ + width: 100%; +} + + + + +/* +Those classes will be edited at runtime with values specified +by the settings of the CC application +*/ +.hostFontColor{} +.hostFontFamily{} +.hostFontSize{} + +/*font family, color and size*/ +.hostFont{} +/*background color*/ +.hostBgd{} +/*lighter background color*/ +.hostBgdLight{} +/*darker background color*/ +.hostBgdDark{} +/*background color and font*/ +.hostElt{} + + +.hostButton{ + border:1px solid; + border-radius:2px; + height:20px; + vertical-align:bottom; + font-family:inherit; + color:inherit; + font-size:inherit; +} \ No newline at end of file diff --git a/openpype/hosts/aftereffects/api/extension/css/topcoat-desktop-dark.min.css b/openpype/hosts/aftereffects/api/extension/css/topcoat-desktop-dark.min.css new file mode 100644 index 00000000000..6b479def439 --- /dev/null +++ b/openpype/hosts/aftereffects/api/extension/css/topcoat-desktop-dark.min.css @@ -0,0 +1 @@ +.button-bar{display:table;table-layout:fixed;white-space:nowrap;margin:0;padding:0}.button-bar__item{display:table-cell;width:auto;border-radius:0}.button-bar__item>input{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.button-bar__button{border-radius:inherit}.button-bar__item:disabled{opacity:.3;cursor:default;pointer-events:none}.button,.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta,.topcoat-button-bar__button,.topcoat-button-bar__button--large{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.button--disabled,.topcoat-button:disabled,.topcoat-button--quiet:disabled,.topcoat-button--large:disabled,.topcoat-button--large--quiet:disabled,.topcoat-button--cta:disabled,.topcoat-button--large--cta:disabled,.topcoat-button-bar__button:disabled,.topcoat-button-bar__button--large:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta,.topcoat-button-bar__button,.topcoat-button-bar__button--large{padding:0 .563rem;font-size:12px;line-height:1.313rem;letter-spacing:0;color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);vertical-align:top;background-color:#595b5b;box-shadow:inset 0 1px #737373;border:1px solid #333434;border-radius:4px}.topcoat-button:hover,.topcoat-button--quiet:hover,.topcoat-button--large:hover,.topcoat-button--large--quiet:hover,.topcoat-button-bar__button:hover,.topcoat-button-bar__button--large:hover{background-color:#626465}.topcoat-button:focus,.topcoat-button--quiet:focus,.topcoat-button--quiet:hover:focus,.topcoat-button--large:focus,.topcoat-button--large--quiet:focus,.topcoat-button--large--quiet:hover:focus,.topcoat-button--cta:focus,.topcoat-button--large--cta:focus,.topcoat-button-bar__button:focus,.topcoat-button-bar__button--large:focus{border:1px solid #0036ff;box-shadow:inset 0 1px rgba(255,255,255,.36),0 0 0 2px #6fb5f1;outline:0}.topcoat-button:active,.topcoat-button--large:active,.topcoat-button-bar__button:active,.topcoat-button-bar__button--large:active,:checked+.topcoat-button-bar__button{border:1px solid #333434;background-color:#3f4041;box-shadow:inset 0 1px rgba(0,0,0,.05)}.topcoat-button--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.topcoat-button--quiet:hover,.topcoat-button--large--quiet:hover{text-shadow:0 -1px rgba(0,0,0,.69);border:1px solid #333434;box-shadow:inset 0 1px #737373}.topcoat-button--quiet:active,.topcoat-button--quiet:focus:active,.topcoat-button--large--quiet:active,.topcoat-button--large--quiet:focus:active{color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);background-color:#3f4041;border:1px solid #333434;box-shadow:inset 0 1px rgba(0,0,0,.05)}.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button-bar__button--large{font-size:.875rem;font-weight:600;line-height:1.688rem;padding:0 .875rem}.topcoat-button--large--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.topcoat-button--cta,.topcoat-button--large--cta{border:1px solid #134f7f;background-color:#288edf;box-shadow:inset 0 1px rgba(255,255,255,.36);color:#fff;font-weight:500;text-shadow:0 -1px rgba(0,0,0,.36)}.topcoat-button--cta:hover,.topcoat-button--large--cta:hover{background-color:#4ca1e4}.topcoat-button--cta:active,.topcoat-button--large--cta:active{background-color:#1e7dc8;box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button--large--cta{font-size:.875rem;font-weight:600;line-height:1.688rem;padding:0 .875rem}.button-bar,.topcoat-button-bar{display:table;table-layout:fixed;white-space:nowrap;margin:0;padding:0}.button-bar__item,.topcoat-button-bar__item{display:table-cell;width:auto;border-radius:0}.button-bar__item>input,.topcoat-button-bar__item>input{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.button-bar__button{border-radius:inherit}.button-bar__item:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button-bar>.topcoat-button-bar__item:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px}.topcoat-button-bar>.topcoat-button-bar__item:last-child{border-top-right-radius:4px;border-bottom-right-radius:4px}.topcoat-button-bar__item:first-child>.topcoat-button-bar__button,.topcoat-button-bar__item:first-child>.topcoat-button-bar__button--large{border-right:0}.topcoat-button-bar__item:last-child>.topcoat-button-bar__button,.topcoat-button-bar__item:last-child>.topcoat-button-bar__button--large{border-left:0}.topcoat-button-bar__button{border-radius:inherit}.topcoat-button-bar__button:focus,.topcoat-button-bar__button--large:focus{z-index:1}.topcoat-button-bar__button--large{border-radius:inherit}.button{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.button--disabled{opacity:.3;cursor:default;pointer-events:none}.button,.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.button--disabled,.topcoat-button:disabled,.topcoat-button--quiet:disabled,.topcoat-button--large:disabled,.topcoat-button--large--quiet:disabled,.topcoat-button--cta:disabled,.topcoat-button--large--cta:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta{padding:0 .563rem;font-size:12px;line-height:1.313rem;letter-spacing:0;color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);vertical-align:top;background-color:#595b5b;box-shadow:inset 0 1px #737373;border:1px solid #333434;border-radius:4px}.topcoat-button:hover,.topcoat-button--quiet:hover,.topcoat-button--large:hover,.topcoat-button--large--quiet:hover{background-color:#626465}.topcoat-button:focus,.topcoat-button--quiet:focus,.topcoat-button--quiet:hover:focus,.topcoat-button--large:focus,.topcoat-button--large--quiet:focus,.topcoat-button--large--quiet:hover:focus,.topcoat-button--cta:focus,.topcoat-button--large--cta:focus{border:1px solid #0036ff;box-shadow:inset 0 1px rgba(255,255,255,.36),0 0 0 2px #6fb5f1;outline:0}.topcoat-button:active,.topcoat-button--large:active{border:1px solid #333434;background-color:#3f4041;box-shadow:inset 0 1px rgba(0,0,0,.05)}.topcoat-button--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.topcoat-button--quiet:hover,.topcoat-button--large--quiet:hover{text-shadow:0 -1px rgba(0,0,0,.69);border:1px solid #333434;box-shadow:inset 0 1px #737373}.topcoat-button--quiet:active,.topcoat-button--quiet:focus:active,.topcoat-button--large--quiet:active,.topcoat-button--large--quiet:focus:active{color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);background-color:#3f4041;border:1px solid #333434;box-shadow:inset 0 1px rgba(0,0,0,.05)}.topcoat-button--large,.topcoat-button--large--quiet{font-size:.875rem;font-weight:600;line-height:1.688rem;padding:0 .875rem}.topcoat-button--large--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.topcoat-button--cta,.topcoat-button--large--cta{border:1px solid #134f7f;background-color:#288edf;box-shadow:inset 0 1px rgba(255,255,255,.36);color:#fff;font-weight:500;text-shadow:0 -1px rgba(0,0,0,.36)}.topcoat-button--cta:hover,.topcoat-button--large--cta:hover{background-color:#4ca1e4}.topcoat-button--cta:active,.topcoat-button--large--cta:active{background-color:#1e7dc8;box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button--large--cta{font-size:.875rem;font-weight:600;line-height:1.688rem;padding:0 .875rem}input[type=checkbox]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.checkbox{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox--disabled{opacity:.3;cursor:default;pointer-events:none}.checkbox:before,.checkbox:after{content:'';position:absolute}.checkbox:before{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box}input[type=checkbox]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.checkbox,.topcoat-checkbox__checkmark{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox__label,.topcoat-checkbox{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.checkbox--disabled,input[type=checkbox]:disabled+.topcoat-checkbox__checkmark{opacity:.3;cursor:default;pointer-events:none}.checkbox:before,.checkbox:after,.topcoat-checkbox__checkmark:before,.topcoat-checkbox__checkmark:after{content:'';position:absolute}.checkbox:before,.topcoat-checkbox__checkmark:before{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box}.topcoat-checkbox__checkmark{height:1rem}input[type=checkbox]{height:1rem;width:1rem;margin-top:0;margin-right:-1rem;margin-bottom:-1rem;margin-left:0}input[type=checkbox]:checked+.topcoat-checkbox__checkmark:after{opacity:1}.topcoat-checkbox{line-height:1rem}.topcoat-checkbox__checkmark:before{width:1rem;height:1rem;background:#595b5b;border:1px solid #333434;border-radius:3px;box-shadow:inset 0 1px #737373}.topcoat-checkbox__checkmark{width:1rem;height:1rem}.topcoat-checkbox__checkmark:after{top:2px;left:1px;opacity:0;width:14px;height:4px;background:transparent;border:7px solid #c6c8c8;border-width:3px;border-top:0;border-right:0;border-radius:1px;-webkit-transform:rotate(-50deg);-ms-transform:rotate(-50deg);transform:rotate(-50deg)}input[type=checkbox]:focus+.topcoat-checkbox__checkmark:before{border:1px solid #0036ff;box-shadow:inset 0 1px rgba(255,255,255,.36),0 0 0 2px #6fb5f1}input[type=checkbox]:active+.topcoat-checkbox__checkmark:before{border:1px solid #333434;background-color:#3f4041;box-shadow:inset 0 1px rgba(0,0,0,.05)}input[type=checkbox]:disabled:active+.topcoat-checkbox__checkmark:before{border:1px solid #333434;background:#595b5b;box-shadow:inset 0 1px #737373}.button,.topcoat-icon-button,.topcoat-icon-button--quiet,.topcoat-icon-button--large,.topcoat-icon-button--large--quiet{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.button--disabled,.topcoat-icon-button:disabled,.topcoat-icon-button--quiet:disabled,.topcoat-icon-button--large:disabled,.topcoat-icon-button--large--quiet:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon-button,.topcoat-icon-button--quiet,.topcoat-icon-button--large,.topcoat-icon-button--large--quiet{padding:0 .25rem;line-height:1.313rem;letter-spacing:0;color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);vertical-align:baseline;background-color:#595b5b;box-shadow:inset 0 1px #737373;border:1px solid #333434;border-radius:4px}.topcoat-icon-button:hover,.topcoat-icon-button--quiet:hover,.topcoat-icon-button--large:hover,.topcoat-icon-button--large--quiet:hover{background-color:#626465}.topcoat-icon-button:focus,.topcoat-icon-button--quiet:focus,.topcoat-icon-button--quiet:hover:focus,.topcoat-icon-button--large:focus,.topcoat-icon-button--large--quiet:focus,.topcoat-icon-button--large--quiet:hover:focus{border:1px solid #0036ff;box-shadow:inset 0 1px rgba(255,255,255,.36),0 0 0 2px #6fb5f1;outline:0}.topcoat-icon-button:active,.topcoat-icon-button--large:active{border:1px solid #333434;background-color:#3f4041;box-shadow:inset 0 1px rgba(0,0,0,.05)}.topcoat-icon-button--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.topcoat-icon-button--quiet:hover,.topcoat-icon-button--large--quiet:hover{text-shadow:0 -1px rgba(0,0,0,.69);border:1px solid #333434;box-shadow:inset 0 1px #737373}.topcoat-icon-button--quiet:active,.topcoat-icon-button--quiet:focus:active,.topcoat-icon-button--large--quiet:active,.topcoat-icon-button--large--quiet:focus:active{color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);background-color:#3f4041;border:1px solid #333434;box-shadow:inset 0 1px rgba(0,0,0,.05)}.topcoat-icon-button--large,.topcoat-icon-button--large--quiet{width:1.688rem;height:1.688rem;line-height:1.688rem}.topcoat-icon-button--large--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.topcoat-icon,.topcoat-icon--large{position:relative;display:inline-block;vertical-align:top;overflow:hidden;width:.81406rem;height:.81406rem;vertical-align:middle;top:-1px}.topcoat-icon--large{width:1.06344rem;height:1.06344rem;top:-2px}.input{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;vertical-align:top;outline:0}.input:disabled{opacity:.3;cursor:default;pointer-events:none}.list{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:auto;-webkit-overflow-scrolling:touch}.list__header{margin:0}.list__container{padding:0;margin:0;list-style-type:none}.list__item{margin:0;padding:0}.navigation-bar{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;white-space:nowrap;overflow:hidden;word-spacing:0;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.navigation-bar__item{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0}.navigation-bar__title{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.notification{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.notification,.topcoat-notification{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.topcoat-notification{padding:.15em .5em .2em;border-radius:2px;background-color:#ec514e;color:#fff}input[type=radio]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.radio-button{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button__label{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button:before,.radio-button:after{content:'';position:absolute;border-radius:100%}.radio-button:after{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.radio-button:before{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box}.radio-button--disabled{opacity:.3;cursor:default;pointer-events:none}input[type=radio]{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.radio-button,.topcoat-radio-button__checkmark{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button__label,.topcoat-radio-button{position:relative;display:inline-block;vertical-align:top;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.radio-button:before,.radio-button:after,.topcoat-radio-button__checkmark:before,.topcoat-radio-button__checkmark:after{content:'';position:absolute;border-radius:100%}.radio-button:after,.topcoat-radio-button__checkmark:after{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.radio-button:before,.topcoat-radio-button__checkmark:before{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box}.radio-button--disabled,input[type=radio]:disabled+.topcoat-radio-button__checkmark{opacity:.3;cursor:default;pointer-events:none}input[type=radio]{height:1.063rem;width:1.063rem;margin-top:0;margin-right:-1.063rem;margin-bottom:-1.063rem;margin-left:0}input[type=radio]:checked+.topcoat-radio-button__checkmark:after{opacity:1}.topcoat-radio-button{color:#c6c8c8;line-height:1.063rem}.topcoat-radio-button__checkmark:before{width:1.063rem;height:1.063rem;background:#595b5b;border:1px solid #333434;box-shadow:inset 0 1px #737373}.topcoat-radio-button__checkmark{position:relative;width:1.063rem;height:1.063rem}.topcoat-radio-button__checkmark:after{opacity:0;width:.313rem;height:.313rem;background:#c6c8c8;border:1px solid rgba(0,0,0,.05);box-shadow:0 1px rgba(255,255,255,.1);-webkit-transform:none;-ms-transform:none;transform:none;top:.313rem;left:.313rem}input[type=radio]:focus+.topcoat-radio-button__checkmark:before{border:1px solid #0036ff;box-shadow:inset 0 1px rgba(255,255,255,.36),0 0 0 2px #6fb5f1}input[type=radio]:active+.topcoat-radio-button__checkmark:before{border:1px solid #333434;background-color:#3f4041;box-shadow:inset 0 1px rgba(0,0,0,.05)}input[type=radio]:disabled:active+.topcoat-radio-button__checkmark:before{border:1px solid #333434;background:#595b5b;box-shadow:inset 0 1px #737373}.range{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;vertical-align:top;outline:0;-webkit-appearance:none}.range__thumb{cursor:pointer}.range__thumb--webkit{cursor:pointer;-webkit-appearance:none}.range:disabled{opacity:.3;cursor:default;pointer-events:none}.range,.topcoat-range{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;vertical-align:top;outline:0;-webkit-appearance:none}.range__thumb,.topcoat-range::-moz-range-thumb{cursor:pointer}.range__thumb--webkit,.topcoat-range::-webkit-slider-thumb{cursor:pointer;-webkit-appearance:none}.range:disabled,.topcoat-range:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-range{border-radius:4px;border:1px solid #333434;background-color:#454646;height:.5rem;border-radius:15px}.topcoat-range::-moz-range-track{border-radius:4px;border:1px solid #333434;background-color:#454646;height:.5rem;border-radius:15px}.topcoat-range::-webkit-slider-thumb{height:1.313rem;width:.75rem;background-color:#595b5b;border:1px solid #333434;border-radius:4px;box-shadow:inset 0 1px #737373}.topcoat-range::-moz-range-thumb{height:1.313rem;width:.75rem;background-color:#595b5b;border:1px solid #333434;border-radius:4px;box-shadow:inset 0 1px #737373}.topcoat-range:focus::-webkit-slider-thumb{border:1px solid #0036ff;box-shadow:inset 0 1px rgba(255,255,255,.36),0 0 0 2px #6fb5f1}.topcoat-range:focus::-moz-range-thumb{border:1px solid #0036ff;box-shadow:inset 0 1px rgba(255,255,255,.36),0 0 0 2px #6fb5f1}.topcoat-range:active::-webkit-slider-thumb{border:1px solid #333434;box-shadow:inset 0 1px #737373}.topcoat-range:active::-moz-range-thumb{border:1px solid #333434;box-shadow:inset 0 1px #737373}.search-input{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;vertical-align:top;outline:0;-webkit-appearance:none}input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}.search-input:disabled{opacity:.3;cursor:default;pointer-events:none}.search-input,.topcoat-search-input,.topcoat-search-input--large{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;vertical-align:top;outline:0;-webkit-appearance:none}input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}.search-input:disabled,.topcoat-search-input:disabled,.topcoat-search-input--large:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-search-input,.topcoat-search-input--large{line-height:1.313rem;height:1.313rem;font-size:12px;border:1px solid #333434;background-color:#454646;box-shadow:inset 0 1px 0 rgba(0,0,0,.23);color:#c6c8c8;padding:0 0 0 1.3rem;border-radius:15px;background-image:url(../img/search.svg);background-position:1rem center;background-repeat:no-repeat;background-size:12px}.topcoat-search-input:focus,.topcoat-search-input--large:focus{background-color:#595b5b;color:#fff;border:1px solid #0036ff;box-shadow:inset 0 1px 0 rgba(0,0,0,.23),0 0 0 2px #6fb5f1}.topcoat-search-input::-webkit-search-cancel-button,.topcoat-search-input::-webkit-search-decoration,.topcoat-search-input--large::-webkit-search-cancel-button,.topcoat-search-input--large::-webkit-search-decoration{margin-right:5px}.topcoat-search-input:focus::-webkit-input-placeholder,.topcoat-search-input:focus::-webkit-input-placeholder{color:#c6c8c8}.topcoat-search-input:disabled::-webkit-input-placeholder{color:#fff}.topcoat-search-input:disabled::-moz-placeholder{color:#fff}.topcoat-search-input:disabled:-ms-input-placeholder{color:#fff}.topcoat-search-input--large{line-height:1.688rem;height:1.688rem;font-size:.875rem;font-weight:400;padding:0 0 0 1.8rem;border-radius:25px;background-position:1.2rem center;background-size:.875rem}.topcoat-search-input--large:disabled{color:#fff}.topcoat-search-input--large:disabled::-webkit-input-placeholder{color:#fff}.topcoat-search-input--large:disabled::-moz-placeholder{color:#fff}.topcoat-search-input--large:disabled:-ms-input-placeholder{color:#fff}.switch{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box}.switch__input{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.switch__toggle{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch__toggle:before,.switch__toggle:after{content:'';position:absolute;z-index:-1;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box}.switch--disabled{opacity:.3;cursor:default;pointer-events:none}.switch,.topcoat-switch{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box}.switch__input,.topcoat-switch__input{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.switch__toggle,.topcoat-switch__toggle{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.switch__toggle:before,.switch__toggle:after,.topcoat-switch__toggle:before,.topcoat-switch__toggle:after{content:'';position:absolute;z-index:-1;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box}.switch--disabled,.topcoat-switch__input:disabled+.topcoat-switch__toggle{opacity:.3;cursor:default;pointer-events:none}.topcoat-switch{font-size:12px;padding:0 .563rem;border-radius:4px;border:1px solid #333434;overflow:hidden;width:3.5rem}.topcoat-switch__toggle:before,.topcoat-switch__toggle:after{top:-1px;width:2.6rem}.topcoat-switch__toggle:before{content:'ON';color:#288edf;background-color:#3f4041;right:.8rem;padding-left:.75rem}.topcoat-switch__toggle{line-height:1.313rem;height:1.313rem;width:1rem;border-radius:4px;color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);background-color:#595b5b;border:1px solid #333434;margin-left:-.6rem;margin-bottom:-1px;margin-top:-1px;box-shadow:inset 0 1px #737373;-webkit-transition:margin-left .05s ease-in-out;transition:margin-left .05s ease-in-out}.topcoat-switch__toggle:after{content:'OFF';background-color:#3f4041;left:.8rem;padding-left:.6rem}.topcoat-switch__input:checked+.topcoat-switch__toggle{margin-left:1.85rem}.topcoat-switch__input:active+.topcoat-switch__toggle{border:1px solid #333434;box-shadow:inset 0 1px #737373}.topcoat-switch__input:focus+.topcoat-switch__toggle{border:1px solid #0036ff;box-shadow:0 0 0 2px #6fb5f1}.topcoat-switch__input:disabled+.topcoat-switch__toggle:after,.topcoat-switch__input:disabled+.topcoat-switch__toggle:before{background:transparent}.button,.topcoat-tab-bar__button{position:relative;display:inline-block;vertical-align:top;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;text-decoration:none}.button--quiet{background:transparent;border:1px solid transparent;box-shadow:none}.button--disabled,.topcoat-tab-bar__button:disabled{opacity:.3;cursor:default;pointer-events:none}.button-bar,.topcoat-tab-bar{display:table;table-layout:fixed;white-space:nowrap;margin:0;padding:0}.button-bar__item,.topcoat-tab-bar__item{display:table-cell;width:auto;border-radius:0}.button-bar__item>input,.topcoat-tab-bar__item>input{position:absolute;overflow:hidden;padding:0;border:0;opacity:.001;z-index:1;vertical-align:top;outline:0}.button-bar__button{border-radius:inherit}.button-bar__item:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-tab-bar__button{padding:0 .563rem;height:1.313rem;line-height:1.313rem;letter-spacing:0;color:#c6c8c8;text-shadow:0 -1px rgba(0,0,0,.69);vertical-align:top;background-color:#595b5b;box-shadow:inset 0 1px #737373;border-top:1px solid #333434}.topcoat-tab-bar__button:active,.topcoat-tab-bar__button--large:active,:checked+.topcoat-tab-bar__button{color:#288edf;background-color:#3f4041;box-shadow:inset 0 0 1px rgba(0,0,0,.05)}.topcoat-tab-bar__button:focus,.topcoat-tab-bar__button--large:focus{z-index:1;box-shadow:inset 0 1px rgba(255,255,255,.36),0 0 0 2px #6fb5f1;outline:0}.input,.topcoat-text-input,.topcoat-text-input--large{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;vertical-align:top;outline:0}.input:disabled,.topcoat-text-input:disabled,.topcoat-text-input--large:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input,.topcoat-text-input--large{line-height:1.313rem;font-size:12px;letter-spacing:0;padding:0 .563rem;border:1px solid #333434;border-radius:4px;background-color:#454646;box-shadow:inset 0 1px rgba(0,0,0,.05);color:#c6c8c8;vertical-align:top}.topcoat-text-input:focus,.topcoat-text-input--large:focus{background-color:#595b5b;color:#fff;border:1px solid #0036ff;box-shadow:0 0 0 2px #6fb5f1}.topcoat-text-input:disabled::-webkit-input-placeholder{color:#fff}.topcoat-text-input:disabled::-moz-placeholder{color:#fff}.topcoat-text-input:disabled:-ms-input-placeholder{color:#fff}.topcoat-text-input:invalid{border:1px solid #ec514e}.topcoat-text-input--large{line-height:1.688rem;font-size:.875rem}.topcoat-text-input--large:disabled{color:#fff}.topcoat-text-input--large:disabled::-webkit-input-placeholder{color:#fff}.topcoat-text-input--large:disabled::-moz-placeholder{color:#fff}.topcoat-text-input--large:disabled:-ms-input-placeholder{color:#fff}.topcoat-text-input--large:invalid{border:1px solid #ec514e}.textarea{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;vertical-align:top;resize:none;outline:0}.textarea:disabled{opacity:.3;cursor:default;pointer-events:none}.textarea,.topcoat-textarea,.topcoat-textarea--large{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;vertical-align:top;resize:none;outline:0}.textarea:disabled,.topcoat-textarea:disabled,.topcoat-textarea--large:disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-textarea,.topcoat-textarea--large{padding:1rem;font-size:1rem;font-weight:400;border-radius:4px;line-height:1.313rem;border:1px solid #333434;background-color:#454646;box-shadow:inset 0 1px rgba(0,0,0,.05);color:#c6c8c8;letter-spacing:0}.topcoat-textarea:focus,.topcoat-textarea--large:focus{background-color:#595b5b;color:#fff;border:1px solid #0036ff;box-shadow:0 0 0 2px #6fb5f1}.topcoat-textarea:disabled::-webkit-input-placeholder{color:#fff}.topcoat-textarea:disabled::-moz-placeholder{color:#fff}.topcoat-textarea:disabled:-ms-input-placeholder{color:#fff}.topcoat-textarea--large{font-size:1.3rem;line-height:1.688rem}.topcoat-textarea--large:disabled{color:#fff}.topcoat-textarea--large:disabled::-webkit-input-placeholder{color:#fff}.topcoat-textarea--large:disabled::-moz-placeholder{color:#fff}.topcoat-textarea--large:disabled:-ms-input-placeholder{color:#fff}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Regular.otf)}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Light.otf);font-weight:200}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Semibold.otf);font-weight:600}body{margin:0;padding:0;background:#4b4d4e;color:#000;font:16px "Source Sans",helvetica,arial,sans-serif;font-weight:400}:focus{outline-color:transparent;outline-style:none}.topcoat-icon--menu-stack{background:url(../img/hamburger_light.svg) no-repeat;background-size:cover}.quarter{width:25%}.half{width:50%}.three-quarters{width:75%}.third{width:33.333%}.two-thirds{width:66.666%}.full{width:100%}.left{text-align:left}.center{text-align:center}.right{text-align:right}.reset-ui{-moz-box-sizing:border-box;box-sizing:border-box;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-overflow:ellipsis;white-space:nowrap;overflow:hidden} \ No newline at end of file diff --git a/openpype/hosts/aftereffects/api/extension/icons/iconDarkNormal.png b/openpype/hosts/aftereffects/api/extension/icons/iconDarkNormal.png new file mode 100644 index 00000000000..b8652a85b84 Binary files /dev/null and b/openpype/hosts/aftereffects/api/extension/icons/iconDarkNormal.png differ diff --git a/openpype/hosts/aftereffects/api/extension/icons/iconDarkRollover.png b/openpype/hosts/aftereffects/api/extension/icons/iconDarkRollover.png new file mode 100644 index 00000000000..49edd7ca278 Binary files /dev/null and b/openpype/hosts/aftereffects/api/extension/icons/iconDarkRollover.png differ diff --git a/openpype/hosts/aftereffects/api/extension/icons/iconDisabled.png b/openpype/hosts/aftereffects/api/extension/icons/iconDisabled.png new file mode 100644 index 00000000000..49edd7ca278 Binary files /dev/null and b/openpype/hosts/aftereffects/api/extension/icons/iconDisabled.png differ diff --git a/openpype/hosts/aftereffects/api/extension/icons/iconNormal.png b/openpype/hosts/aftereffects/api/extension/icons/iconNormal.png new file mode 100644 index 00000000000..199326f2eac Binary files /dev/null and b/openpype/hosts/aftereffects/api/extension/icons/iconNormal.png differ diff --git a/openpype/hosts/aftereffects/api/extension/icons/iconRollover.png b/openpype/hosts/aftereffects/api/extension/icons/iconRollover.png new file mode 100644 index 00000000000..ff626457985 Binary files /dev/null and b/openpype/hosts/aftereffects/api/extension/icons/iconRollover.png differ diff --git a/openpype/hosts/aftereffects/api/extension/index.html b/openpype/hosts/aftereffects/api/extension/index.html new file mode 100644 index 00000000000..9e39bf1accc --- /dev/null +++ b/openpype/hosts/aftereffects/api/extension/index.html @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/openpype/hosts/aftereffects/api/extension/js/libs/CSInterface.js b/openpype/hosts/aftereffects/api/extension/js/libs/CSInterface.js new file mode 100644 index 00000000000..4239391efd0 --- /dev/null +++ b/openpype/hosts/aftereffects/api/extension/js/libs/CSInterface.js @@ -0,0 +1,1193 @@ +/************************************************************************************************** +* +* ADOBE SYSTEMS INCORPORATED +* Copyright 2013 Adobe Systems Incorporated +* All Rights Reserved. +* +* NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the +* terms of the Adobe license agreement accompanying it. If you have received this file from a +* source other than Adobe, then your use, modification, or distribution of it requires the prior +* written permission of Adobe. +* +**************************************************************************************************/ + +/** CSInterface - v8.0.0 */ + +/** + * Stores constants for the window types supported by the CSXS infrastructure. + */ +function CSXSWindowType() +{ +} + +/** Constant for the CSXS window type Panel. */ +CSXSWindowType._PANEL = "Panel"; + +/** Constant for the CSXS window type Modeless. */ +CSXSWindowType._MODELESS = "Modeless"; + +/** Constant for the CSXS window type ModalDialog. */ +CSXSWindowType._MODAL_DIALOG = "ModalDialog"; + +/** EvalScript error message */ +EvalScript_ErrMessage = "EvalScript error."; + +/** + * @class Version + * Defines a version number with major, minor, micro, and special + * components. The major, minor and micro values are numeric; the special + * value can be any string. + * + * @param major The major version component, a positive integer up to nine digits long. + * @param minor The minor version component, a positive integer up to nine digits long. + * @param micro The micro version component, a positive integer up to nine digits long. + * @param special The special version component, an arbitrary string. + * + * @return A new \c Version object. + */ +function Version(major, minor, micro, special) +{ + this.major = major; + this.minor = minor; + this.micro = micro; + this.special = special; +} + +/** + * The maximum value allowed for a numeric version component. + * This reflects the maximum value allowed in PlugPlug and the manifest schema. + */ +Version.MAX_NUM = 999999999; + +/** + * @class VersionBound + * Defines a boundary for a version range, which associates a \c Version object + * with a flag for whether it is an inclusive or exclusive boundary. + * + * @param version The \c #Version object. + * @param inclusive True if this boundary is inclusive, false if it is exclusive. + * + * @return A new \c VersionBound object. + */ +function VersionBound(version, inclusive) +{ + this.version = version; + this.inclusive = inclusive; +} + +/** + * @class VersionRange + * Defines a range of versions using a lower boundary and optional upper boundary. + * + * @param lowerBound The \c #VersionBound object. + * @param upperBound The \c #VersionBound object, or null for a range with no upper boundary. + * + * @return A new \c VersionRange object. + */ +function VersionRange(lowerBound, upperBound) +{ + this.lowerBound = lowerBound; + this.upperBound = upperBound; +} + +/** + * @class Runtime + * Represents a runtime related to the CEP infrastructure. + * Extensions can declare dependencies on particular + * CEP runtime versions in the extension manifest. + * + * @param name The runtime name. + * @param version A \c #VersionRange object that defines a range of valid versions. + * + * @return A new \c Runtime object. + */ +function Runtime(name, versionRange) +{ + this.name = name; + this.versionRange = versionRange; +} + +/** +* @class Extension +* Encapsulates a CEP-based extension to an Adobe application. +* +* @param id The unique identifier of this extension. +* @param name The localizable display name of this extension. +* @param mainPath The path of the "index.html" file. +* @param basePath The base path of this extension. +* @param windowType The window type of the main window of this extension. + Valid values are defined by \c #CSXSWindowType. +* @param width The default width in pixels of the main window of this extension. +* @param height The default height in pixels of the main window of this extension. +* @param minWidth The minimum width in pixels of the main window of this extension. +* @param minHeight The minimum height in pixels of the main window of this extension. +* @param maxWidth The maximum width in pixels of the main window of this extension. +* @param maxHeight The maximum height in pixels of the main window of this extension. +* @param defaultExtensionDataXml The extension data contained in the default \c ExtensionDispatchInfo section of the extension manifest. +* @param specialExtensionDataXml The extension data contained in the application-specific \c ExtensionDispatchInfo section of the extension manifest. +* @param requiredRuntimeList An array of \c Runtime objects for runtimes required by this extension. +* @param isAutoVisible True if this extension is visible on loading. +* @param isPluginExtension True if this extension has been deployed in the Plugins folder of the host application. +* +* @return A new \c Extension object. +*/ +function Extension(id, name, mainPath, basePath, windowType, width, height, minWidth, minHeight, maxWidth, maxHeight, + defaultExtensionDataXml, specialExtensionDataXml, requiredRuntimeList, isAutoVisible, isPluginExtension) +{ + this.id = id; + this.name = name; + this.mainPath = mainPath; + this.basePath = basePath; + this.windowType = windowType; + this.width = width; + this.height = height; + this.minWidth = minWidth; + this.minHeight = minHeight; + this.maxWidth = maxWidth; + this.maxHeight = maxHeight; + this.defaultExtensionDataXml = defaultExtensionDataXml; + this.specialExtensionDataXml = specialExtensionDataXml; + this.requiredRuntimeList = requiredRuntimeList; + this.isAutoVisible = isAutoVisible; + this.isPluginExtension = isPluginExtension; +} + +/** + * @class CSEvent + * A standard JavaScript event, the base class for CEP events. + * + * @param type The name of the event type. + * @param scope The scope of event, can be "GLOBAL" or "APPLICATION". + * @param appId The unique identifier of the application that generated the event. + * @param extensionId The unique identifier of the extension that generated the event. + * + * @return A new \c CSEvent object + */ +function CSEvent(type, scope, appId, extensionId) +{ + this.type = type; + this.scope = scope; + this.appId = appId; + this.extensionId = extensionId; +} + +/** Event-specific data. */ +CSEvent.prototype.data = ""; + +/** + * @class SystemPath + * Stores operating-system-specific location constants for use in the + * \c #CSInterface.getSystemPath() method. + * @return A new \c SystemPath object. + */ +function SystemPath() +{ +} + +/** The path to user data. */ +SystemPath.USER_DATA = "userData"; + +/** The path to common files for Adobe applications. */ +SystemPath.COMMON_FILES = "commonFiles"; + +/** The path to the user's default document folder. */ +SystemPath.MY_DOCUMENTS = "myDocuments"; + +/** @deprecated. Use \c #SystemPath.Extension. */ +SystemPath.APPLICATION = "application"; + +/** The path to current extension. */ +SystemPath.EXTENSION = "extension"; + +/** The path to hosting application's executable. */ +SystemPath.HOST_APPLICATION = "hostApplication"; + +/** + * @class ColorType + * Stores color-type constants. + */ +function ColorType() +{ +} + +/** RGB color type. */ +ColorType.RGB = "rgb"; + +/** Gradient color type. */ +ColorType.GRADIENT = "gradient"; + +/** Null color type. */ +ColorType.NONE = "none"; + +/** + * @class RGBColor + * Stores an RGB color with red, green, blue, and alpha values. + * All values are in the range [0.0 to 255.0]. Invalid numeric values are + * converted to numbers within this range. + * + * @param red The red value, in the range [0.0 to 255.0]. + * @param green The green value, in the range [0.0 to 255.0]. + * @param blue The blue value, in the range [0.0 to 255.0]. + * @param alpha The alpha (transparency) value, in the range [0.0 to 255.0]. + * The default, 255.0, means that the color is fully opaque. + * + * @return A new RGBColor object. + */ +function RGBColor(red, green, blue, alpha) +{ + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; +} + +/** + * @class Direction + * A point value in which the y component is 0 and the x component + * is positive or negative for a right or left direction, + * or the x component is 0 and the y component is positive or negative for + * an up or down direction. + * + * @param x The horizontal component of the point. + * @param y The vertical component of the point. + * + * @return A new \c Direction object. + */ +function Direction(x, y) +{ + this.x = x; + this.y = y; +} + +/** + * @class GradientStop + * Stores gradient stop information. + * + * @param offset The offset of the gradient stop, in the range [0.0 to 1.0]. + * @param rgbColor The color of the gradient at this point, an \c #RGBColor object. + * + * @return GradientStop object. + */ +function GradientStop(offset, rgbColor) +{ + this.offset = offset; + this.rgbColor = rgbColor; +} + +/** + * @class GradientColor + * Stores gradient color information. + * + * @param type The gradient type, must be "linear". + * @param direction A \c #Direction object for the direction of the gradient + (up, down, right, or left). + * @param numStops The number of stops in the gradient. + * @param gradientStopList An array of \c #GradientStop objects. + * + * @return A new \c GradientColor object. + */ +function GradientColor(type, direction, numStops, arrGradientStop) +{ + this.type = type; + this.direction = direction; + this.numStops = numStops; + this.arrGradientStop = arrGradientStop; +} + +/** + * @class UIColor + * Stores color information, including the type, anti-alias level, and specific color + * values in a color object of an appropriate type. + * + * @param type The color type, 1 for "rgb" and 2 for "gradient". + The supplied color object must correspond to this type. + * @param antialiasLevel The anti-alias level constant. + * @param color A \c #RGBColor or \c #GradientColor object containing specific color information. + * + * @return A new \c UIColor object. + */ +function UIColor(type, antialiasLevel, color) +{ + this.type = type; + this.antialiasLevel = antialiasLevel; + this.color = color; +} + +/** + * @class AppSkinInfo + * Stores window-skin properties, such as color and font. All color parameter values are \c #UIColor objects except that systemHighlightColor is \c #RGBColor object. + * + * @param baseFontFamily The base font family of the application. + * @param baseFontSize The base font size of the application. + * @param appBarBackgroundColor The application bar background color. + * @param panelBackgroundColor The background color of the extension panel. + * @param appBarBackgroundColorSRGB The application bar background color, as sRGB. + * @param panelBackgroundColorSRGB The background color of the extension panel, as sRGB. + * @param systemHighlightColor The highlight color of the extension panel, if provided by the host application. Otherwise, the operating-system highlight color. + * + * @return AppSkinInfo object. + */ +function AppSkinInfo(baseFontFamily, baseFontSize, appBarBackgroundColor, panelBackgroundColor, appBarBackgroundColorSRGB, panelBackgroundColorSRGB, systemHighlightColor) +{ + this.baseFontFamily = baseFontFamily; + this.baseFontSize = baseFontSize; + this.appBarBackgroundColor = appBarBackgroundColor; + this.panelBackgroundColor = panelBackgroundColor; + this.appBarBackgroundColorSRGB = appBarBackgroundColorSRGB; + this.panelBackgroundColorSRGB = panelBackgroundColorSRGB; + this.systemHighlightColor = systemHighlightColor; +} + +/** + * @class HostEnvironment + * Stores information about the environment in which the extension is loaded. + * + * @param appName The application's name. + * @param appVersion The application's version. + * @param appLocale The application's current license locale. + * @param appUILocale The application's current UI locale. + * @param appId The application's unique identifier. + * @param isAppOnline True if the application is currently online. + * @param appSkinInfo An \c #AppSkinInfo object containing the application's default color and font styles. + * + * @return A new \c HostEnvironment object. + */ +function HostEnvironment(appName, appVersion, appLocale, appUILocale, appId, isAppOnline, appSkinInfo) +{ + this.appName = appName; + this.appVersion = appVersion; + this.appLocale = appLocale; + this.appUILocale = appUILocale; + this.appId = appId; + this.isAppOnline = isAppOnline; + this.appSkinInfo = appSkinInfo; +} + +/** + * @class HostCapabilities + * Stores information about the host capabilities. + * + * @param EXTENDED_PANEL_MENU True if the application supports panel menu. + * @param EXTENDED_PANEL_ICONS True if the application supports panel icon. + * @param DELEGATE_APE_ENGINE True if the application supports delegated APE engine. + * @param SUPPORT_HTML_EXTENSIONS True if the application supports HTML extensions. + * @param DISABLE_FLASH_EXTENSIONS True if the application disables FLASH extensions. + * + * @return A new \c HostCapabilities object. + */ +function HostCapabilities(EXTENDED_PANEL_MENU, EXTENDED_PANEL_ICONS, DELEGATE_APE_ENGINE, SUPPORT_HTML_EXTENSIONS, DISABLE_FLASH_EXTENSIONS) +{ + this.EXTENDED_PANEL_MENU = EXTENDED_PANEL_MENU; + this.EXTENDED_PANEL_ICONS = EXTENDED_PANEL_ICONS; + this.DELEGATE_APE_ENGINE = DELEGATE_APE_ENGINE; + this.SUPPORT_HTML_EXTENSIONS = SUPPORT_HTML_EXTENSIONS; + this.DISABLE_FLASH_EXTENSIONS = DISABLE_FLASH_EXTENSIONS; // Since 5.0.0 +} + +/** + * @class ApiVersion + * Stores current api version. + * + * Since 4.2.0 + * + * @param major The major version + * @param minor The minor version. + * @param micro The micro version. + * + * @return ApiVersion object. + */ +function ApiVersion(major, minor, micro) +{ + this.major = major; + this.minor = minor; + this.micro = micro; +} + +/** + * @class MenuItemStatus + * Stores flyout menu item status + * + * Since 5.2.0 + * + * @param menuItemLabel The menu item label. + * @param enabled True if user wants to enable the menu item. + * @param checked True if user wants to check the menu item. + * + * @return MenuItemStatus object. + */ +function MenuItemStatus(menuItemLabel, enabled, checked) +{ + this.menuItemLabel = menuItemLabel; + this.enabled = enabled; + this.checked = checked; +} + +/** + * @class ContextMenuItemStatus + * Stores the status of the context menu item. + * + * Since 5.2.0 + * + * @param menuItemID The menu item id. + * @param enabled True if user wants to enable the menu item. + * @param checked True if user wants to check the menu item. + * + * @return MenuItemStatus object. + */ +function ContextMenuItemStatus(menuItemID, enabled, checked) +{ + this.menuItemID = menuItemID; + this.enabled = enabled; + this.checked = checked; +} +//------------------------------ CSInterface ---------------------------------- + +/** + * @class CSInterface + * This is the entry point to the CEP extensibility infrastructure. + * Instantiate this object and use it to: + *
    + *
  • Access information about the host application in which an extension is running
  • + *
  • Launch an extension
  • + *
  • Register interest in event notifications, and dispatch events
  • + *
+ * + * @return A new \c CSInterface object + */ +function CSInterface() +{ +} + +/** + * User can add this event listener to handle native application theme color changes. + * Callback function gives extensions ability to fine-tune their theme color after the + * global theme color has been changed. + * The callback function should be like below: + * + * @example + * // event is a CSEvent object, but user can ignore it. + * function OnAppThemeColorChanged(event) + * { + * // Should get a latest HostEnvironment object from application. + * var skinInfo = JSON.parse(window.__adobe_cep__.getHostEnvironment()).appSkinInfo; + * // Gets the style information such as color info from the skinInfo, + * // and redraw all UI controls of your extension according to the style info. + * } + */ +CSInterface.THEME_COLOR_CHANGED_EVENT = "com.adobe.csxs.events.ThemeColorChanged"; + +/** The host environment data object. */ +CSInterface.prototype.hostEnvironment = window.__adobe_cep__ ? JSON.parse(window.__adobe_cep__.getHostEnvironment()) : null; + +/** Retrieves information about the host environment in which the + * extension is currently running. + * + * @return A \c #HostEnvironment object. + */ +CSInterface.prototype.getHostEnvironment = function() +{ + this.hostEnvironment = JSON.parse(window.__adobe_cep__.getHostEnvironment()); + return this.hostEnvironment; +}; + +/** Closes this extension. */ +CSInterface.prototype.closeExtension = function() +{ + window.__adobe_cep__.closeExtension(); +}; + +/** + * Retrieves a path for which a constant is defined in the system. + * + * @param pathType The path-type constant defined in \c #SystemPath , + * + * @return The platform-specific system path string. + */ +CSInterface.prototype.getSystemPath = function(pathType) +{ + var path = decodeURI(window.__adobe_cep__.getSystemPath(pathType)); + var OSVersion = this.getOSInformation(); + if (OSVersion.indexOf("Windows") >= 0) + { + path = path.replace("file:///", ""); + } + else if (OSVersion.indexOf("Mac") >= 0) + { + path = path.replace("file://", ""); + } + return path; +}; + +/** + * Evaluates a JavaScript script, which can use the JavaScript DOM + * of the host application. + * + * @param script The JavaScript script. + * @param callback Optional. A callback function that receives the result of execution. + * If execution fails, the callback function receives the error message \c EvalScript_ErrMessage. + */ +CSInterface.prototype.evalScript = function(script, callback) +{ + if(callback === null || callback === undefined) + { + callback = function(result){}; + } + window.__adobe_cep__.evalScript(script, callback); +}; + +/** + * Retrieves the unique identifier of the application. + * in which the extension is currently running. + * + * @return The unique ID string. + */ +CSInterface.prototype.getApplicationID = function() +{ + var appId = this.hostEnvironment.appId; + return appId; +}; + +/** + * Retrieves host capability information for the application + * in which the extension is currently running. + * + * @return A \c #HostCapabilities object. + */ +CSInterface.prototype.getHostCapabilities = function() +{ + var hostCapabilities = JSON.parse(window.__adobe_cep__.getHostCapabilities() ); + return hostCapabilities; +}; + +/** + * Triggers a CEP event programmatically. Yoy can use it to dispatch + * an event of a predefined type, or of a type you have defined. + * + * @param event A \c CSEvent object. + */ +CSInterface.prototype.dispatchEvent = function(event) +{ + if (typeof event.data == "object") + { + event.data = JSON.stringify(event.data); + } + + window.__adobe_cep__.dispatchEvent(event); +}; + +/** + * Registers an interest in a CEP event of a particular type, and + * assigns an event handler. + * The event infrastructure notifies your extension when events of this type occur, + * passing the event object to the registered handler function. + * + * @param type The name of the event type of interest. + * @param listener The JavaScript handler function or method. + * @param obj Optional, the object containing the handler method, if any. + * Default is null. + */ +CSInterface.prototype.addEventListener = function(type, listener, obj) +{ + window.__adobe_cep__.addEventListener(type, listener, obj); +}; + +/** + * Removes a registered event listener. + * + * @param type The name of the event type of interest. + * @param listener The JavaScript handler function or method that was registered. + * @param obj Optional, the object containing the handler method, if any. + * Default is null. + */ +CSInterface.prototype.removeEventListener = function(type, listener, obj) +{ + window.__adobe_cep__.removeEventListener(type, listener, obj); +}; + +/** + * Loads and launches another extension, or activates the extension if it is already loaded. + * + * @param extensionId The extension's unique identifier. + * @param startupParams Not currently used, pass "". + * + * @example + * To launch the extension "help" with ID "HLP" from this extension, call: + * requestOpenExtension("HLP", ""); + * + */ +CSInterface.prototype.requestOpenExtension = function(extensionId, params) +{ + window.__adobe_cep__.requestOpenExtension(extensionId, params); +}; + +/** + * Retrieves the list of extensions currently loaded in the current host application. + * The extension list is initialized once, and remains the same during the lifetime + * of the CEP session. + * + * @param extensionIds Optional, an array of unique identifiers for extensions of interest. + * If omitted, retrieves data for all extensions. + * + * @return Zero or more \c #Extension objects. + */ +CSInterface.prototype.getExtensions = function(extensionIds) +{ + var extensionIdsStr = JSON.stringify(extensionIds); + var extensionsStr = window.__adobe_cep__.getExtensions(extensionIdsStr); + + var extensions = JSON.parse(extensionsStr); + return extensions; +}; + +/** + * Retrieves network-related preferences. + * + * @return A JavaScript object containing network preferences. + */ +CSInterface.prototype.getNetworkPreferences = function() +{ + var result = window.__adobe_cep__.getNetworkPreferences(); + var networkPre = JSON.parse(result); + + return networkPre; +}; + +/** + * Initializes the resource bundle for this extension with property values + * for the current application and locale. + * To support multiple locales, you must define a property file for each locale, + * containing keyed display-string values for that locale. + * See localization documentation for Extension Builder and related products. + * + * Keys can be in the + * form key.value="localized string", for use in HTML text elements. + * For example, in this input element, the localized \c key.value string is displayed + * instead of the empty \c value string: + * + * + * + * @return An object containing the resource bundle information. + */ +CSInterface.prototype.initResourceBundle = function() +{ + var resourceBundle = JSON.parse(window.__adobe_cep__.initResourceBundle()); + var resElms = document.querySelectorAll('[data-locale]'); + for (var n = 0; n < resElms.length; n++) + { + var resEl = resElms[n]; + // Get the resource key from the element. + var resKey = resEl.getAttribute('data-locale'); + if (resKey) + { + // Get all the resources that start with the key. + for (var key in resourceBundle) + { + if (key.indexOf(resKey) === 0) + { + var resValue = resourceBundle[key]; + if (key.length == resKey.length) + { + resEl.innerHTML = resValue; + } + else if ('.' == key.charAt(resKey.length)) + { + var attrKey = key.substring(resKey.length + 1); + resEl[attrKey] = resValue; + } + } + } + } + } + return resourceBundle; +}; + +/** + * Writes installation information to a file. + * + * @return The file path. + */ +CSInterface.prototype.dumpInstallationInfo = function() +{ + return window.__adobe_cep__.dumpInstallationInfo(); +}; + +/** + * Retrieves version information for the current Operating System, + * See http://www.useragentstring.com/pages/Chrome/ for Chrome \c navigator.userAgent values. + * + * @return A string containing the OS version, or "unknown Operation System". + * If user customizes the User Agent by setting CEF command parameter "--user-agent", only + * "Mac OS X" or "Windows" will be returned. + */ +CSInterface.prototype.getOSInformation = function() +{ + var userAgent = navigator.userAgent; + + if ((navigator.platform == "Win32") || (navigator.platform == "Windows")) + { + var winVersion = "Windows"; + var winBit = ""; + if (userAgent.indexOf("Windows") > -1) + { + if (userAgent.indexOf("Windows NT 5.0") > -1) + { + winVersion = "Windows 2000"; + } + else if (userAgent.indexOf("Windows NT 5.1") > -1) + { + winVersion = "Windows XP"; + } + else if (userAgent.indexOf("Windows NT 5.2") > -1) + { + winVersion = "Windows Server 2003"; + } + else if (userAgent.indexOf("Windows NT 6.0") > -1) + { + winVersion = "Windows Vista"; + } + else if (userAgent.indexOf("Windows NT 6.1") > -1) + { + winVersion = "Windows 7"; + } + else if (userAgent.indexOf("Windows NT 6.2") > -1) + { + winVersion = "Windows 8"; + } + else if (userAgent.indexOf("Windows NT 6.3") > -1) + { + winVersion = "Windows 8.1"; + } + else if (userAgent.indexOf("Windows NT 10") > -1) + { + winVersion = "Windows 10"; + } + + if (userAgent.indexOf("WOW64") > -1 || userAgent.indexOf("Win64") > -1) + { + winBit = " 64-bit"; + } + else + { + winBit = " 32-bit"; + } + } + + return winVersion + winBit; + } + else if ((navigator.platform == "MacIntel") || (navigator.platform == "Macintosh")) + { + var result = "Mac OS X"; + + if (userAgent.indexOf("Mac OS X") > -1) + { + result = userAgent.substring(userAgent.indexOf("Mac OS X"), userAgent.indexOf(")")); + result = result.replace(/_/g, "."); + } + + return result; + } + + return "Unknown Operation System"; +}; + +/** + * Opens a page in the default system browser. + * + * Since 4.2.0 + * + * @param url The URL of the page/file to open, or the email address. + * Must use HTTP/HTTPS/file/mailto protocol. For example: + * "http://www.adobe.com" + * "https://github.com" + * "file:///C:/log.txt" + * "mailto:test@adobe.com" + * + * @return One of these error codes:\n + *
    \n + *
  • NO_ERROR - 0
  • \n + *
  • ERR_UNKNOWN - 1
  • \n + *
  • ERR_INVALID_PARAMS - 2
  • \n + *
  • ERR_INVALID_URL - 201
  • \n + *
\n + */ +CSInterface.prototype.openURLInDefaultBrowser = function(url) +{ + return cep.util.openURLInDefaultBrowser(url); +}; + +/** + * Retrieves extension ID. + * + * Since 4.2.0 + * + * @return extension ID. + */ +CSInterface.prototype.getExtensionID = function() +{ + return window.__adobe_cep__.getExtensionId(); +}; + +/** + * Retrieves the scale factor of screen. + * On Windows platform, the value of scale factor might be different from operating system's scale factor, + * since host application may use its self-defined scale factor. + * + * Since 4.2.0 + * + * @return One of the following float number. + *
    \n + *
  • -1.0 when error occurs
  • \n + *
  • 1.0 means normal screen
  • \n + *
  • >1.0 means HiDPI screen
  • \n + *
\n + */ +CSInterface.prototype.getScaleFactor = function() +{ + return window.__adobe_cep__.getScaleFactor(); +}; + +/** + * Set a handler to detect any changes of scale factor. This only works on Mac. + * + * Since 4.2.0 + * + * @param handler The function to be called when scale factor is changed. + * + */ +CSInterface.prototype.setScaleFactorChangedHandler = function(handler) +{ + window.__adobe_cep__.setScaleFactorChangedHandler(handler); +}; + +/** + * Retrieves current API version. + * + * Since 4.2.0 + * + * @return ApiVersion object. + * + */ +CSInterface.prototype.getCurrentApiVersion = function() +{ + var apiVersion = JSON.parse(window.__adobe_cep__.getCurrentApiVersion()); + return apiVersion; +}; + +/** + * Set panel flyout menu by an XML. + * + * Since 5.2.0 + * + * Register a callback function for "com.adobe.csxs.events.flyoutMenuClicked" to get notified when a + * menu item is clicked. + * The "data" attribute of event is an object which contains "menuId" and "menuName" attributes. + * + * Register callback functions for "com.adobe.csxs.events.flyoutMenuOpened" and "com.adobe.csxs.events.flyoutMenuClosed" + * respectively to get notified when flyout menu is opened or closed. + * + * @param menu A XML string which describes menu structure. + * An example menu XML: + * + * + * + * + * + * + * + * + * + * + * + * + */ +CSInterface.prototype.setPanelFlyoutMenu = function(menu) +{ + if ("string" != typeof menu) + { + return; + } + + window.__adobe_cep__.invokeSync("setPanelFlyoutMenu", menu); +}; + +/** + * Updates a menu item in the extension window's flyout menu, by setting the enabled + * and selection status. + * + * Since 5.2.0 + * + * @param menuItemLabel The menu item label. + * @param enabled True to enable the item, false to disable it (gray it out). + * @param checked True to select the item, false to deselect it. + * + * @return false when the host application does not support this functionality (HostCapabilities.EXTENDED_PANEL_MENU is false). + * Fails silently if menu label is invalid. + * + * @see HostCapabilities.EXTENDED_PANEL_MENU + */ +CSInterface.prototype.updatePanelMenuItem = function(menuItemLabel, enabled, checked) +{ + var ret = false; + if (this.getHostCapabilities().EXTENDED_PANEL_MENU) + { + var itemStatus = new MenuItemStatus(menuItemLabel, enabled, checked); + ret = window.__adobe_cep__.invokeSync("updatePanelMenuItem", JSON.stringify(itemStatus)); + } + return ret; +}; + + +/** + * Set context menu by XML string. + * + * Since 5.2.0 + * + * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. + * - an item without menu ID or menu name is disabled and is not shown. + * - if the item name is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. + * - Checkable attribute takes precedence over Checked attribute. + * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item. + The Chrome extension contextMenus API was taken as a reference. + https://developer.chrome.com/extensions/contextMenus + * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. + * + * @param menu A XML string which describes menu structure. + * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. + * + * @description An example menu XML: + * + * + * + * + * + * + * + * + * + * + * + */ +CSInterface.prototype.setContextMenu = function(menu, callback) +{ + if ("string" != typeof menu) + { + return; + } + + window.__adobe_cep__.invokeAsync("setContextMenu", menu, callback); +}; + +/** + * Set context menu by JSON string. + * + * Since 6.0.0 + * + * There are a number of conventions used to communicate what type of menu item to create and how it should be handled. + * - an item without menu ID or menu name is disabled and is not shown. + * - if the item label is "---" (three hyphens) then it is treated as a separator. The menu ID in this case will always be NULL. + * - Checkable attribute takes precedence over Checked attribute. + * - a PNG icon. For optimal display results please supply a 16 x 16px icon as larger dimensions will increase the size of the menu item. + The Chrome extension contextMenus API was taken as a reference. + * - the items with icons and checkable items cannot coexist on the same menu level. The former take precedences over the latter. + https://developer.chrome.com/extensions/contextMenus + * + * @param menu A JSON string which describes menu structure. + * @param callback The callback function which is called when a menu item is clicked. The only parameter is the returned ID of clicked menu item. + * + * @description An example menu JSON: + * + * { + * "menu": [ + * { + * "id": "menuItemId1", + * "label": "testExample1", + * "enabled": true, + * "checkable": true, + * "checked": false, + * "icon": "./image/small_16X16.png" + * }, + * { + * "id": "menuItemId2", + * "label": "testExample2", + * "menu": [ + * { + * "id": "menuItemId2-1", + * "label": "testExample2-1", + * "menu": [ + * { + * "id": "menuItemId2-1-1", + * "label": "testExample2-1-1", + * "enabled": false, + * "checkable": true, + * "checked": true + * } + * ] + * }, + * { + * "id": "menuItemId2-2", + * "label": "testExample2-2", + * "enabled": true, + * "checkable": true, + * "checked": true + * } + * ] + * }, + * { + * "label": "---" + * }, + * { + * "id": "menuItemId3", + * "label": "testExample3", + * "enabled": false, + * "checkable": true, + * "checked": false + * } + * ] + * } + * + */ +CSInterface.prototype.setContextMenuByJSON = function(menu, callback) +{ + if ("string" != typeof menu) + { + return; + } + + window.__adobe_cep__.invokeAsync("setContextMenuByJSON", menu, callback); +}; + +/** + * Updates a context menu item by setting the enabled and selection status. + * + * Since 5.2.0 + * + * @param menuItemID The menu item ID. + * @param enabled True to enable the item, false to disable it (gray it out). + * @param checked True to select the item, false to deselect it. + */ +CSInterface.prototype.updateContextMenuItem = function(menuItemID, enabled, checked) +{ + var itemStatus = new ContextMenuItemStatus(menuItemID, enabled, checked); + ret = window.__adobe_cep__.invokeSync("updateContextMenuItem", JSON.stringify(itemStatus)); +}; + +/** + * Get the visibility status of an extension window. + * + * Since 6.0.0 + * + * @return true if the extension window is visible; false if the extension window is hidden. + */ +CSInterface.prototype.isWindowVisible = function() +{ + return window.__adobe_cep__.invokeSync("isWindowVisible", ""); +}; + +/** + * Resize extension's content to the specified dimensions. + * 1. Works with modal and modeless extensions in all Adobe products. + * 2. Extension's manifest min/max size constraints apply and take precedence. + * 3. For panel extensions + * 3.1 This works in all Adobe products except: + * * Premiere Pro + * * Prelude + * * After Effects + * 3.2 When the panel is in certain states (especially when being docked), + * it will not change to the desired dimensions even when the + * specified size satisfies min/max constraints. + * + * Since 6.0.0 + * + * @param width The new width + * @param height The new height + */ +CSInterface.prototype.resizeContent = function(width, height) +{ + window.__adobe_cep__.resizeContent(width, height); +}; + +/** + * Register the invalid certificate callback for an extension. + * This callback will be triggered when the extension tries to access the web site that contains the invalid certificate on the main frame. + * But if the extension does not call this function and tries to access the web site containing the invalid certificate, a default error page will be shown. + * + * Since 6.1.0 + * + * @param callback the callback function + */ +CSInterface.prototype.registerInvalidCertificateCallback = function(callback) +{ + return window.__adobe_cep__.registerInvalidCertificateCallback(callback); +}; + +/** + * Register an interest in some key events to prevent them from being sent to the host application. + * + * This function works with modeless extensions and panel extensions. + * Generally all the key events will be sent to the host application for these two extensions if the current focused element + * is not text input or dropdown, + * If you want to intercept some key events and want them to be handled in the extension, please call this function + * in advance to prevent them being sent to the host application. + * + * Since 6.1.0 + * + * @param keyEventsInterest A JSON string describing those key events you are interested in. A null object or + an empty string will lead to removing the interest + * + * This JSON string should be an array, each object has following keys: + * + * keyCode: [Required] represents an OS system dependent virtual key code identifying + * the unmodified value of the pressed key. + * ctrlKey: [optional] a Boolean that indicates if the control key was pressed (true) or not (false) when the event occurred. + * altKey: [optional] a Boolean that indicates if the alt key was pressed (true) or not (false) when the event occurred. + * shiftKey: [optional] a Boolean that indicates if the shift key was pressed (true) or not (false) when the event occurred. + * metaKey: [optional] (Mac Only) a Boolean that indicates if the Meta key was pressed (true) or not (false) when the event occurred. + * On Macintosh keyboards, this is the command key. To detect Windows key on Windows, please use keyCode instead. + * An example JSON string: + * + * [ + * { + * "keyCode": 48 + * }, + * { + * "keyCode": 123, + * "ctrlKey": true + * }, + * { + * "keyCode": 123, + * "ctrlKey": true, + * "metaKey": true + * } + * ] + * + */ +CSInterface.prototype.registerKeyEventsInterest = function(keyEventsInterest) +{ + return window.__adobe_cep__.registerKeyEventsInterest(keyEventsInterest); +}; + +/** + * Set the title of the extension window. + * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. + * + * Since 6.1.0 + * + * @param title The window title. + */ +CSInterface.prototype.setWindowTitle = function(title) +{ + window.__adobe_cep__.invokeSync("setWindowTitle", title); +}; + +/** + * Get the title of the extension window. + * This function works with modal and modeless extensions in all Adobe products, and panel extensions in Photoshop, InDesign, InCopy, Illustrator, Flash Pro and Dreamweaver. + * + * Since 6.1.0 + * + * @return The window title. + */ +CSInterface.prototype.getWindowTitle = function() +{ + return window.__adobe_cep__.invokeSync("getWindowTitle", ""); +}; diff --git a/openpype/hosts/aftereffects/api/extension/js/libs/jquery-2.0.2.min.js b/openpype/hosts/aftereffects/api/extension/js/libs/jquery-2.0.2.min.js new file mode 100644 index 00000000000..73e5218d210 --- /dev/null +++ b/openpype/hosts/aftereffects/api/extension/js/libs/jquery-2.0.2.min.js @@ -0,0 +1,6 @@ +/*! jQuery v2.0.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-2.0.2.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.2",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=at(),k=at(),N=at(),E=!1,S=function(){return 0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],H=L.pop,q=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){q.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=vt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+xt(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 St(e.replace(z,"$1"),t,r,i)}function st(e){return Q.test(e+"")}function at(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function ut(e){return e[v]=!0,e}function lt(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t,n){e=e.split("|");var r,o=e.length,s=n?null:t;while(o--)(r=i.attrHandle[e[o]])&&r!==t||(i.attrHandle[e[o]]=s)}function pt(e,t){var n=e.getAttributeNode(t);return n&&n.specified?n.value:e[t]===!0?t.toLowerCase():null}function ft(e,t){return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}function ht(e){return"input"===e.nodeName.toLowerCase()?e.defaultValue:undefined}function dt(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 gt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function mt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function yt(e){return ut(function(t){return t=+t,ut(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.parentWindow;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.frameElement&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=lt(function(e){return e.innerHTML="",ct("type|href|height|width",ft,"#"===e.firstChild.getAttribute("href")),ct(R,pt,null==e.getAttribute("disabled")),e.className="i",!e.getAttribute("className")}),n.input=lt(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")}),ct("value",ht,n.attributes&&n.input),n.getElementsByTagName=lt(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=lt(function(e){return e.innerHTML="
",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=lt(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=st(t.querySelectorAll))&&(lt(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),lt(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=st(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&<(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=st(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},n.sortDetached=lt(function(e){return 1&e.compareDocumentPosition(t.createElement("div"))}),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 dt(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?dt(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:ut,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=vt(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())?ut(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:ut(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?ut(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:ut(function(e){return function(t){return ot(e,t).length>0}}),contains:ut(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ut(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:yt(function(){return[0]}),last:yt(function(e,t){return[t-1]}),eq:yt(function(e,t,n){return[0>n?n+t:n]}),even:yt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:yt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:yt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:yt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=gt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=mt(t);function vt(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 xt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function bt(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 wt(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 Tt(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 Ct(e,t,n,r,i,o){return r&&!r[v]&&(r=Ct(r)),i&&!i[v]&&(i=Ct(i,o)),ut(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Et(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:Tt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=Tt(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=Tt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function kt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=bt(function(e){return e===t},a,!0),p=bt(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=[bt(wt(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 Ct(l>1&&wt(f),l>1&&xt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&kt(e.slice(l,r)),o>r&&kt(e=e.slice(r)),o>r&&xt(e))}f.push(n)}return wt(f)}function Nt(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]=H.call(f));y=Tt(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?ut(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=vt(e)),n=t.length;while(n--)o=kt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Nt(i,r))}return o};function Et(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function St(e,t,r,o){var s,u,l,c,p,f=vt(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&&xt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}i.pseudos.nth=i.pseudos.eq;function jt(){}jt.prototype=i.filters=i.pseudos,i.setFilters=new jt,n.sortStable=v.split("").sort(S).join("")===v,c(),[0,0].sort(S),n.detectDuplicates=E,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 t=t||[],t=[e,t.slice?t.slice():t],!a||n&&!u||(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,H,q=/(?:\{[\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){return t===undefined||t&&"string"==typeof t&&n===undefined?this.get(e,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,H=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||H.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 H.access(e,t,n)},_removeData:function(e,t){H.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&&!H.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]));H.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:q.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=H.get(e,t),n&&(!r||x.isArray(n)?r=H.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 H.get(e,n)||H.access(e,n,{empty:x.Callbacks("once memory").add(function(){H.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=H.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,i="boolean"==typeof t;return 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 o,s=0,a=x(this),u=t,l=e.match(w)||[];while(o=l[s++])u=i?u:!a.hasClass(o),a[u?"addClass":"removeClass"](o)}else(n===r||"boolean"===n)&&(this.className&&H.set(this,"__className__",this.className),this.className=this.className||e===!1?"":H.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=H.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=H.hasData(e)&&H.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,H.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=(H.get(a,"events")||{})[t.type]&&H.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=(H.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||"")&&!H.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.firstChild;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[H.expando],o&&(t=H.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);H.cache[o]&&delete H.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++)H.set(e[r],"globalEval",!t||H.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(H.hasData(e)&&(o=H.access(e),s=H.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 Ht(t){return e.getComputedStyle(t,null)}function qt(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=H.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=H.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&H.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=Ht(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 qt(this,!0)},hide:function(){return qt(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e: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,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||Ht(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=Ht(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("