diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml new file mode 100644 index 0000000..bc8fb1e --- /dev/null +++ b/.github/workflows/moodle-ci.yml @@ -0,0 +1,126 @@ +name: Moodle Plugin CI + +on: + push: + paths-ignore: + - 'node_modules/**' + pull_request: + paths-ignore: + - 'node_modules/**' + + +jobs: + test: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:12 + env: + POSTGRES_USER: 'postgres' + POSTGRES_HOST_AUTH_METHOD: 'trust' + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 + mariadb: + image: mariadb:10 + env: + MYSQL_USER: 'root' + MYSQL_ALLOW_EMPTY_PASSWORD: "true" + MYSQL_CHARACTER_SET_SERVER: "utf8mb4" + MYSQL_COLLATION_SERVER: "utf8mb4_unicode_ci" + + ports: + - 3306:3306 + options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3 + + strategy: + fail-fast: false + matrix: + include: + - php: '8.0' + moodle-branch: 'master' + database: 'pgsql' + - php: '8.1' + moodle-branch: 'MOODLE_401_STABLE' + database: 'pgsql' + - php: '8.1' + moodle-branch: 'MOODLE_402_STABLE' + database: 'pgsql' + + steps: + - name: Check out repository code + uses: actions/checkout@v2 + with: + path: plugin + + - name: Setup PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: ${{ matrix.extensions }} + ini-values: max_input_vars=5000 + # none to use phpdbg fallback. Specify pcov (Moodle 3.10 and up) or xdebug to use them instead. + coverage: none + + - name: Initialise moodle-plugin-ci + run: | + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + echo $(cd ci/bin; pwd) >> $GITHUB_PATH + echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH + sudo locale-gen en_AU.UTF-8 + echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV + - name: Install moodle-plugin-ci + run: | + moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 + env: + DB: ${{ matrix.database }} + MOODLE_BRANCH: ${{ matrix.moodle-branch }} + + - name: PHP Lint + if: ${{ always() }} + run: moodle-plugin-ci phplint + + - name: PHP Copy/Paste Detector + continue-on-error: true # This step will show errors but will not fail + if: ${{ always() }} + run: moodle-plugin-ci phpcpd + + - name: PHP Mess Detector + continue-on-error: true # This step will show errors but will not fail + if: ${{ always() }} + run: moodle-plugin-ci phpmd + + - name: Moodle Code Checker + if: ${{ always() }} + # Allow 3 warnings for privacy provider interfaces (Moodle <3.6) + run: moodle-plugin-ci codechecker --max-warnings 3 + + - name: Moodle PHPDoc Checker + if: ${{ always() }} + run: moodle-plugin-ci phpdoc + + - name: Validating + if: ${{ always() }} + run: moodle-plugin-ci validate + + - name: Check upgrade savepoints + if: ${{ always() }} + run: moodle-plugin-ci savepoints + +# Mustache and Grunt are failing so commenting out for now +# - name: Mustache Lint +# if: ${{ always() }} +# run: moodle-plugin-ci mustache + +# - name: Grunt +# if: ${{ always() }} +# run: moodle-plugin-ci grunt --max-lint-warnings 0 + + - name: PHPUnit tests + if: ${{ always() }} + run: moodle-plugin-ci phpunit --fail-on-warning + + - name: Behat features + if: ${{ always() }} + run: moodle-plugin-ci behat --profile chrome \ No newline at end of file diff --git a/README.md b/README.md index 66e1e62..e1ce47e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,59 @@ # moodle-tiny_panoptoltibutton -Moodle plugin that allow users to embed LTI content into the TinyMCE rich text editor. +This plugin adds a button to the TinyMCE Text Editor to allow for teachers and students to embed Panopto content using existing Panopto LTI tools + + +## Prerequisites for using the Panopto Button plugin for TinyMCE: + +* Access to the server where Moodle is installed and running. As this plugin is not registered for automatic update, it cannot be upgraded from Moodle +UI and requires direct access to the server. +* The Moodle 2.0 Plugin for Panopto. The plugin and instructions for installation may be found at + https://github.com/Panopto/Moodle-2.0-Plugin-for-Panopto +* The TinyMCE rich text editor for Moodle. This may be enabled by navigating to **Site Administration > Plugins > Text editors > Manage editors** on +the left-hand column of the Moodle page and using the up/down arrows to move 'TinyMCE editor' to the top of the list. Make sure that TinyMCE is +enabled by confirming that its corresponding icon under the 'Enable' column shows an unobstructed eye, or click the icon until it appears this way. + + +## Installation instructions: + +1. Get the latest release source package (either as zip or tar.gz) from https://github.com/Panopto/moodle-tiny_panoptoltibutton/releases +1. Log in to Moodle as an Admin. +1. Navigate to **System Administration > Plugins > Install Plugins** +1. Drag the .zip of the latest release over the drag and drop section to install a plugin. +1. Moodle should detect the new/upgraded plug-in and show "Plugins check" screen which prompts you to install/upgrade. Click "Upgrade Moodle database now" button to proceed. +1. After installation is completed, visit **Site Administration > Plugins > Text Editors > General Settings** and confirm that 'Add Panopto Video' has been added to the list of installed plugins for TinyMCE. +1. The Panopto LTI button for TinyMCE should now be installed and will appear on all rich text input windows throughout the Moodle site. + +## Usage: + +1. On a rich text input window on the Moodle site, navigate the cursor to the position at which you would like your content to be inserted and click the Panopto dropdown button (the button containing the green Panopto logo and a dropdown icon). +1. We only show existing LTI tool that have a Tool URL that matches the Panopto server a course is provisioned with. At this time Panopto only supports embedding rich text editor LTI content from pages associated with a course provisioned by the Panopto block. +1. After selecting an item in the dropdown a new window will appear containing the selected Panopto LTI tool. From here the user can select and embed content depending on what LTI tool was selected. + +## Making changes to the code: + +### Update AMD module + +You can build all modules in Moodle by using the grunt amd command. To update the amd module from this plugin: +1. Execute `npm install` on the root of the Moodle project. +2. Navigate to `/lib/editor/tiny/panoptoltibutton/amd/` and execute: + +``` +$ npx grunt amd +``` + +### Development mode + +In development mode Moodle will also send the browser the corresponding source map files for each of the JavaScript modules. The source map files will tell the browser how to map the minified source code back to the un-minified original source code so that the original source files will be displayed in the sources section of the browser's development tools. + +To enable development mode set the cachejs config value to false in the admin settings or directly in your config.php file: + +``` +// Prevent JS caching +$CFG->cachejs = false; +``` + +## Deploy new version + +1. Increment the version in version.php by 1 (e.g. change 2020061000 to 2020061001) +1. Add everything except the .git and node_modules folder to a zip archive +1. Treat the zip archive as a new release and follow the installation instructions above. As long as the version is higher than the currently installed version an update should trigger. \ No newline at end of file diff --git a/amd/build/commands.min.js b/amd/build/commands.min.js new file mode 100644 index 0000000..8010868 --- /dev/null +++ b/amd/build/commands.min.js @@ -0,0 +1,3 @@ +define("tiny_panoptoltibutton/commands",["exports","editor_tiny/utils","./ui","core/str","./common"],(function(_exports,_utils,_ui,_str,_common){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.getSetup=void 0;_exports.getSetup=async()=>{const[buttonText,buttonImage]=await Promise.all([(0,_str.get_string)("panopto_button_description",_common.component),(0,_utils.getButtonImage)("icon",_common.component)]);return editor=>{editor.ui.registry.addIcon(_common.icon,buttonImage.html),editor.ui.registry.addToggleButton(_common.buttonName,{icon:_common.icon,tooltip:buttonText,onAction:()=>(0,_ui.handleAction)(editor)}),editor.ui.registry.addMenuItem(_common.buttonName,{icon:_common.icon,text:buttonText,onAction:()=>(0,_ui.handleAction)(editor)})}}})); + +//# sourceMappingURL=commands.min.js.map \ No newline at end of file diff --git a/amd/build/commands.min.js.map b/amd/build/commands.min.js.map new file mode 100644 index 0000000..4cfdc4e --- /dev/null +++ b/amd/build/commands.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"commands.min.js","sources":["../src/commands.js"],"sourcesContent":["// This file is part of Moodle - https://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny Panopto LTI Video commands.\n *\n * @module tiny_panoptoltibutton/commands\n * @copyright 2023 Panopto\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getButtonImage} from 'editor_tiny/utils';\nimport {handleAction} from './ui';\nimport {get_string as getString} from 'core/str';\nimport {component, buttonName, icon} from './common';\n\nexport const getSetup = async() => {\n const [buttonText, buttonImage] = await Promise.all([\n getString(\"panopto_button_description\", component),\n getButtonImage(\"icon\", component),\n ]);\n\n return (editor) => {\n // Register the Moodle SVG as an icon suitable for use as a TinyMCE toolbar button.\n editor.ui.registry.addIcon(icon, buttonImage.html);\n\n // Register the Panopto LTI Video Toolbar Button.\n editor.ui.registry.addToggleButton(buttonName, {\n icon,\n tooltip: buttonText,\n onAction: () => handleAction(editor),\n });\n\n // Add the Panopto LTI Video Menu Item.\n // This allows it to be added to a standard menu, or a context menu.\n editor.ui.registry.addMenuItem(buttonName, {\n icon,\n text: buttonText,\n onAction: () => handleAction(editor),\n });\n };\n};\n"],"names":["async","buttonText","buttonImage","Promise","all","component","editor","ui","registry","addIcon","icon","html","addToggleButton","buttonName","tooltip","onAction","addMenuItem","text"],"mappings":"oPA4BwBA,gBACbC,WAAYC,mBAAqBC,QAAQC,IAAI,EAChD,mBAAU,6BAA8BC,oBACxC,yBAAe,OAAQA,4BAGnBC,SAEJA,OAAOC,GAAGC,SAASC,QAAQC,aAAMR,YAAYS,MAG7CL,OAAOC,GAAGC,SAASI,gBAAgBC,mBAAY,CAC3CH,KAAAA,aACAI,QAASb,WACTc,SAAU,KAAM,oBAAaT,UAKjCA,OAAOC,GAAGC,SAASQ,YAAYH,mBAAY,CACvCH,KAAAA,aACAO,KAAMhB,WACNc,SAAU,KAAM,oBAAaT"} \ No newline at end of file diff --git a/amd/build/common.min.js b/amd/build/common.min.js new file mode 100644 index 0000000..c7a2d64 --- /dev/null +++ b/amd/build/common.min.js @@ -0,0 +1,11 @@ +define("tiny_panoptoltibutton/common",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0; +/** + * Panopto LTI button common values. + * + * @module tiny_panoptoltibutton + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +const component="tiny_panoptoltibutton";var _default={component:component,pluginName:"".concat(component,"/plugin"),icon:component,buttonName:component};return _exports.default=_default,_exports.default})); + +//# sourceMappingURL=common.min.js.map \ No newline at end of file diff --git a/amd/build/common.min.js.map b/amd/build/common.min.js.map new file mode 100644 index 0000000..e38d089 --- /dev/null +++ b/amd/build/common.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"common.min.js","sources":["../src/common.js"],"sourcesContent":["// This file is part of Moodle - https://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Panopto LTI button common values.\n *\n * @module tiny_panoptoltibutton\n * @copyright 2023 Panopto\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nconst component = \"tiny_panoptoltibutton\";\n\nexport default {\n component,\n pluginName: `${component}/plugin`,\n icon: component,\n buttonName: component,\n};\n"],"names":["component","pluginName","icon","buttonName"],"mappings":";;;;;;;;MAuBMA,UAAY,qCAEH,CACXA,UAAAA,UACAC,qBAAeD,qBACfE,KAAMF,UACNG,WAAYH"} \ No newline at end of file diff --git a/amd/build/configuration.min.js b/amd/build/configuration.min.js new file mode 100644 index 0000000..65b061e --- /dev/null +++ b/amd/build/configuration.min.js @@ -0,0 +1,3 @@ +define("tiny_panoptoltibutton/configuration",["exports","./common","editor_tiny/utils"],(function(_exports,_common,_utils){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.configure=void 0;_exports.configure=instanceConfig=>({menu:(0,_utils.addMenubarItem)(instanceConfig.menu,"insert",_common.buttonName),toolbar:(0,_utils.addToolbarButton)(instanceConfig.toolbar,"content",_common.buttonName)})})); + +//# sourceMappingURL=configuration.min.js.map \ No newline at end of file diff --git a/amd/build/configuration.min.js.map b/amd/build/configuration.min.js.map new file mode 100644 index 0000000..5a0ddba --- /dev/null +++ b/amd/build/configuration.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"configuration.min.js","sources":["../src/configuration.js"],"sourcesContent":["// This file is part of Moodle - https://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny Panopto LTI configuration.\n *\n * @module tiny_panoptoltibutton/configuration\n * @copyright 2023 Panopto\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {buttonName} from './common';\nimport {addMenubarItem, addToolbarButton} from 'editor_tiny/utils';\n\nexport const configure = (instanceConfig) => {\n // Update the instance configuration to add the Panopto LTI Video menu option to the menus and toolbars.\n return {\n menu: addMenubarItem(instanceConfig.menu, \"insert\", buttonName),\n toolbar: addToolbarButton(\n instanceConfig.toolbar,\n \"content\",\n buttonName\n ),\n };\n};\n"],"names":["instanceConfig","menu","buttonName","toolbar"],"mappings":"gOA0B0BA,iBAEf,CACHC,MAAM,yBAAeD,eAAeC,KAAM,SAAUC,oBACpDC,SAAS,2BACLH,eAAeG,QACf,UACAD"} \ No newline at end of file diff --git a/amd/build/modal.min.js b/amd/build/modal.min.js new file mode 100644 index 0000000..0626d82 --- /dev/null +++ b/amd/build/modal.min.js @@ -0,0 +1,3 @@ +define("tiny_panoptoltibutton/modal",["exports","core/modal","core/modal_registry"],(function(_exports,_modal,_modal_registry){var _class;function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal=_interopRequireDefault(_modal),_modal_registry=_interopRequireDefault(_modal_registry);const PanoptoModal=(_defineProperty(_class=class extends _modal.default{registerEventListeners(){super.registerEventListeners(),this.registerCloseOnCancel()}},"TYPE","tiny_panoptoltibutton/modal"),_defineProperty(_class,"TEMPLATE","tiny_panoptoltibutton/modal"),_class);_modal_registry.default.register(PanoptoModal.TYPE,PanoptoModal,PanoptoModal.TEMPLATE);var _default=PanoptoModal;return _exports.default=_default,_exports.default})); + +//# sourceMappingURL=modal.min.js.map \ No newline at end of file diff --git a/amd/build/modal.min.js.map b/amd/build/modal.min.js.map new file mode 100644 index 0000000..0ce0d30 --- /dev/null +++ b/amd/build/modal.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"modal.min.js","sources":["../src/modal.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny Panopto LTI Video modal.\n *\n * @module tiny_panoptoltibutton/modal\n * @copyright 2023 Panopto\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\nimport ModalRegistry from 'core/modal_registry';\n\nconst PanoptoModal = class extends Modal {\n static TYPE = \"tiny_panoptoltibutton/modal\";\n static TEMPLATE = \"tiny_panoptoltibutton/modal\";\n\n registerEventListeners() {\n // Call the parent registration.\n super.registerEventListeners();\n\n // Register to close on cancel.\n this.registerCloseOnCancel();\n }\n};\n\nModalRegistry.register(PanoptoModal.TYPE, PanoptoModal, PanoptoModal.TEMPLATE);\n\nexport default PanoptoModal;\n"],"names":["PanoptoModal","Modal","registerEventListeners","registerCloseOnCancel","register","TYPE","TEMPLATE"],"mappings":"ojBA0BMA,qCAAe,cAAcC,eAI/BC,+BAEUA,8BAGDC,iCARK,iEACI,+DAWRC,SAASJ,aAAaK,KAAML,aAAcA,aAAaM,uBAEtDN"} \ No newline at end of file diff --git a/amd/build/options.min.js b/amd/build/options.min.js new file mode 100644 index 0000000..768687e --- /dev/null +++ b/amd/build/options.min.js @@ -0,0 +1,11 @@ +define("tiny_panoptoltibutton/options",["exports","editor_tiny/options","./common"],(function(_exports,_options,_common){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.register=_exports.getWwwroot=_exports.getUnprovisionedError=_exports.getTool=_exports.getResourceBase=_exports.getPanoptoLtiButtonLongDescription=_exports.getPanoptoLtiButtonDescription=_exports.getCourseId=_exports.getContentItemPath=void 0; +/** + * Tiny Panopto LTI Video Options helper. + * + * @module tiny_panoptoltibutton/options + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +const courseid=(0,_options.getPluginOptionName)(_common.pluginName,"courseid"),tool=(0,_options.getPluginOptionName)(_common.pluginName,"tool"),wwwroot=(0,_options.getPluginOptionName)(_common.pluginName,"wwwroot"),contentitempath=(0,_options.getPluginOptionName)(_common.pluginName,"contentitempath"),resourcebase=(0,_options.getPluginOptionName)(_common.pluginName,"resourcebase"),panoptoltibuttondescription=(0,_options.getPluginOptionName)(_common.pluginName,"panoptoltibuttondescription"),panoptoltibuttonlongdescription=(0,_options.getPluginOptionName)(_common.pluginName,"panoptoltibuttonlongdescription"),unprovisionederror=(0,_options.getPluginOptionName)(_common.pluginName,"unprovisionederror");_exports.register=editor=>{const registerOption=editor.options.register;registerOption(courseid,{processor:"string"}),registerOption(tool,{processor:"object"}),registerOption(wwwroot,{processor:"string"}),registerOption(contentitempath,{processor:"string"}),registerOption(resourcebase,{processor:"string"}),registerOption(panoptoltibuttondescription,{processor:"string"}),registerOption(panoptoltibuttonlongdescription,{processor:"string"}),registerOption(unprovisionederror,{processor:"string"})};_exports.getCourseId=editor=>editor.options.get(courseid);_exports.getTool=editor=>editor.options.get(tool);_exports.getWwwroot=editor=>editor.options.get(wwwroot);_exports.getContentItemPath=editor=>editor.options.get(contentitempath);_exports.getResourceBase=editor=>editor.options.get(resourcebase);_exports.getPanoptoLtiButtonDescription=editor=>editor.options.get(panoptoltibuttondescription);_exports.getPanoptoLtiButtonLongDescription=editor=>editor.options.get(panoptoltibuttonlongdescription);_exports.getUnprovisionedError=editor=>editor.options.get(unprovisionederror)})); + +//# sourceMappingURL=options.min.js.map \ No newline at end of file diff --git a/amd/build/options.min.js.map b/amd/build/options.min.js.map new file mode 100644 index 0000000..e94de0a --- /dev/null +++ b/amd/build/options.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"options.min.js","sources":["../src/options.js"],"sourcesContent":["// This file is part of Moodle - https://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny Panopto LTI Video Options helper.\n *\n * @module tiny_panoptoltibutton/options\n * @copyright 2023 Panopto\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {getPluginOptionName} from 'editor_tiny/options';\nimport {pluginName} from './common';\n\n// Helper variables for the option names.\nconst courseid = getPluginOptionName(pluginName, \"courseid\");\nconst tool = getPluginOptionName(pluginName, \"tool\");\nconst wwwroot = getPluginOptionName(pluginName, \"wwwroot\");\nconst contentitempath = getPluginOptionName(pluginName, \"contentitempath\");\nconst resourcebase = getPluginOptionName(pluginName, \"resourcebase\");\nconst panoptoltibuttondescription = getPluginOptionName(\n pluginName,\n \"panoptoltibuttondescription\"\n);\nconst panoptoltibuttonlongdescription = getPluginOptionName(\n pluginName,\n \"panoptoltibuttonlongdescription\"\n);\nconst unprovisionederror = getPluginOptionName(\n pluginName,\n \"unprovisionederror\"\n);\n\n/**\n * Options registration function.\n *\n * @param {tinyMCE} editor\n */\nexport const register = (editor) => {\n const registerOption = editor.options.register;\n\n // For each option, register it with the editor.\n registerOption(courseid, {\n processor: \"string\",\n });\n registerOption(tool, {\n processor: \"object\",\n });\n registerOption(wwwroot, {\n processor: \"string\",\n });\n registerOption(contentitempath, {\n processor: \"string\",\n });\n registerOption(resourcebase, {\n processor: \"string\",\n });\n registerOption(panoptoltibuttondescription, {\n processor: \"string\",\n });\n registerOption(panoptoltibuttonlongdescription, {\n processor: \"string\",\n });\n registerOption(unprovisionederror, {\n processor: \"string\",\n });\n};\n\n/**\n * Fetch the courseid value for this editor instance.\n *\n * @param {tinyMCE} editor The editor instance to fetch the value for\n * @returns {object} The value of the courseid option\n */\nexport const getCourseId = (editor) => editor.options.get(courseid);\n\n/**\n * Fetch the tool value for this editor instance.\n *\n * @param {tinyMCE} editor The editor instance to fetch the value for\n * @returns {object} The value of the tool option\n */\nexport const getTool = (editor) => editor.options.get(tool);\n\n/**\n * Fetch the wwwroot value for this editor instance.\n *\n * @param {tinyMCE} editor The editor instance to fetch the value for\n * @returns {object} The value of the wwwroot option\n */\nexport const getWwwroot = (editor) => editor.options.get(wwwroot);\n\n/**\n * Fetch the contentitempath value for this editor instance.\n *\n * @param {tinyMCE} editor The editor instance to fetch the value for\n * @returns {object} The value of the contentitempath option\n */\nexport const getContentItemPath = (editor) => editor.options.get(contentitempath);\n\n/**\n * Fetch the resourcebase value for this editor instance.\n *\n * @param {tinyMCE} editor The editor instance to fetch the value for\n * @returns {object} The value of the resourcebase option\n */\nexport const getResourceBase = (editor) => editor.options.get(resourcebase);\n\n/**\n * Fetch the panoptoltibuttondescription value for this editor instance.\n *\n * @param {tinyMCE} editor The editor instance to fetch the value for\n * @returns {object} The value of the panoptoltibuttondescription option\n */\nexport const getPanoptoLtiButtonDescription = (editor) =>\n editor.options.get(panoptoltibuttondescription);\n\n/**\n * Fetch the panoptoltibuttonlongdescription value for this editor instance.\n *\n * @param {tinyMCE} editor The editor instance to fetch the value for\n * @returns {object} The value of the panoptoltibuttonlongdescription option\n */\nexport const getPanoptoLtiButtonLongDescription = (editor) =>\n editor.options.get(panoptoltibuttonlongdescription);\n\n/**\n * Fetch the unprovisionederror value for this editor instance.\n *\n * @param {tinyMCE} editor The editor instance to fetch the value for\n * @returns {object} The value of the unprovisionederror option\n */\nexport const getUnprovisionedError = (editor) =>\n editor.options.get(unprovisionederror);\n"],"names":["courseid","pluginName","tool","wwwroot","contentitempath","resourcebase","panoptoltibuttondescription","panoptoltibuttonlongdescription","unprovisionederror","editor","registerOption","options","register","processor","get"],"mappings":";;;;;;;;MA2BMA,UAAW,gCAAoBC,mBAAY,YAC3CC,MAAO,gCAAoBD,mBAAY,QACvCE,SAAU,gCAAoBF,mBAAY,WAC1CG,iBAAkB,gCAAoBH,mBAAY,mBAClDI,cAAe,gCAAoBJ,mBAAY,gBAC/CK,6BAA8B,gCAChCL,mBACA,+BAEEM,iCAAkC,gCACpCN,mBACA,mCAEEO,oBAAqB,gCACvBP,mBACA,wCAQqBQ,eACfC,eAAiBD,OAAOE,QAAQC,SAGtCF,eAAeV,SAAU,CACrBa,UAAW,WAEfH,eAAeR,KAAM,CACjBW,UAAW,WAEfH,eAAeP,QAAS,CACpBU,UAAW,WAEfH,eAAeN,gBAAiB,CAC5BS,UAAW,WAEfH,eAAeL,aAAc,CACzBQ,UAAW,WAEfH,eAAeJ,4BAA6B,CACxCO,UAAW,WAEfH,eAAeH,gCAAiC,CAC5CM,UAAW,WAEfH,eAAeF,mBAAoB,CAC/BK,UAAW,iCAUSJ,QAAWA,OAAOE,QAAQG,IAAId,2BAQlCS,QAAWA,OAAOE,QAAQG,IAAIZ,0BAQ3BO,QAAWA,OAAOE,QAAQG,IAAIX,qCAQtBM,QAAWA,OAAOE,QAAQG,IAAIV,0CAQjCK,QAAWA,OAAOE,QAAQG,IAAIT,sDAQfI,QAC3CA,OAAOE,QAAQG,IAAIR,yEAQ4BG,QAC/CA,OAAOE,QAAQG,IAAIP,gEAQeE,QAClCA,OAAOE,QAAQG,IAAIN"} \ No newline at end of file diff --git a/amd/build/panopto.min.js b/amd/build/panopto.min.js new file mode 100644 index 0000000..b8ec97f --- /dev/null +++ b/amd/build/panopto.min.js @@ -0,0 +1,9 @@ +/** + * Tiny Panopto LTI CV Events API 3rd party library. + * + * @module tiny_panoptoltibutton + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +//# sourceMappingURL=panopto.min.js.map \ No newline at end of file diff --git a/amd/build/panopto.min.js.map b/amd/build/panopto.min.js.map new file mode 100644 index 0000000..a71f0c2 --- /dev/null +++ b/amd/build/panopto.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"panopto.min.js","sources":[],"sourcesContent":[],"names":[],"mappings":""} \ No newline at end of file diff --git a/amd/build/plugin.min.js b/amd/build/plugin.min.js new file mode 100644 index 0000000..17d0fab --- /dev/null +++ b/amd/build/plugin.min.js @@ -0,0 +1,10 @@ +define("tiny_panoptoltibutton/plugin",["exports","editor_tiny/loader","editor_tiny/utils","./common","./options","./commands","./configuration"],(function(_exports,_loader,_utils,_common,_options,_commands,Configuration){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Configuration=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj} +/** + * Tiny Panopto LTI Video plugin for Moodle. + * + * @module tiny_panoptoltibutton + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */(Configuration);var _default=new Promise((async resolve=>{const[tinyMCE,pluginMetadata,setupCommands]=await Promise.all([(0,_loader.getTinyMCE)(),(0,_utils.getPluginMetadata)(_common.component,_common.pluginName),(0,_commands.getSetup)()]);tinyMCE.PluginManager.add(_common.pluginName,(editor=>((0,_options.register)(editor),setupCommands(editor),pluginMetadata))),resolve([_common.pluginName,Configuration])}));return _exports.default=_default,_exports.default})); + +//# sourceMappingURL=plugin.min.js.map \ No newline at end of file diff --git a/amd/build/plugin.min.js.map b/amd/build/plugin.min.js.map new file mode 100644 index 0000000..35fb836 --- /dev/null +++ b/amd/build/plugin.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plugin.min.js","sources":["../src/plugin.js"],"sourcesContent":["// This file is part of Moodle - https://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny Panopto LTI Video plugin for Moodle.\n *\n * @module tiny_panoptoltibutton\n * @copyright 2023 Panopto\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport { getTinyMCE } from \"editor_tiny/loader\";\nimport { getPluginMetadata } from \"editor_tiny/utils\";\n\nimport { component, pluginName } from \"./common\";\nimport { register as registerOptions } from \"./options\";\nimport { getSetup as getCommandSetup } from \"./commands\";\nimport * as Configuration from \"./configuration\";\n\n// Setup the tiny_panoptoltibutton Plugin.\nexport default new Promise(async (resolve) => {\n // Note: The PluginManager.add function does not support asynchronous configuration.\n // Perform any asynchronous configuration here, and then call the PluginManager.add function.\n const [tinyMCE, pluginMetadata, setupCommands] = await Promise.all([\n getTinyMCE(),\n getPluginMetadata(component, pluginName),\n getCommandSetup(),\n ]);\n\n // Reminder: Any asynchronous code must be run before this point.\n tinyMCE.PluginManager.add(pluginName, (editor) => {\n // Register any options that your plugin has\n registerOptions(editor);\n\n // Setup any commands such as buttons, menu items, and so on.\n setupCommands(editor);\n\n // Return the pluginMetadata object. This is used by TinyMCE to display a help link for your plugin.\n return pluginMetadata;\n });\n\n resolve([pluginName, Configuration]);\n});\n"],"names":["Promise","async","tinyMCE","pluginMetadata","setupCommands","all","component","pluginName","PluginManager","add","editor","resolve","Configuration"],"mappings":";;;;;;;kCAgCe,IAAIA,SAAQC,MAAAA,gBAGhBC,QAASC,eAAgBC,qBAAuBJ,QAAQK,IAAI,EAC/D,yBACA,4BAAkBC,kBAAWC,qBAC7B,0BAIJL,QAAQM,cAAcC,IAAIF,oBAAaG,+BAEnBA,QAGhBN,cAAcM,QAGPP,kBAGXQ,QAAQ,CAACJ,mBAAYK"} \ No newline at end of file diff --git a/amd/build/ui.min.js b/amd/build/ui.min.js new file mode 100644 index 0000000..113ba26 --- /dev/null +++ b/amd/build/ui.min.js @@ -0,0 +1,10 @@ +define("tiny_panoptoltibutton/ui",["exports","tiny_panoptoltibutton/modal","core/modal_factory","./options","core/config"],(function(_exports,_modal,_modal_factory,_options,_config){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} +/** + * Tiny Panopto LTI Video ui helper. + * + * @module tiny_panoptoltibutton/ui + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.handleAction=void 0,_modal=_interopRequireDefault(_modal),_modal_factory=_interopRequireDefault(_modal_factory),_config=_interopRequireDefault(_config);_exports.handleAction=editor=>{displayDialogue(editor)};const getTemplateContext=(editor,data)=>{const baseUrl="".concat(_config.default.wwwroot,"/lib/editor/tiny/plugins/panoptoltibutton/panoptowrapper.html#"),unprovisionedError=encodeURIComponent((0,_options.getUnprovisionedError)(editor)),courseId=(0,_options.getCourseId)(editor),tool=encodeURIComponent(JSON.stringify((0,_options.getTool)(editor))),resourceBase=(0,_options.getResourceBase)(editor),wwwroot=encodeURIComponent((0,_options.getWwwroot)(editor)),contentItemPath=encodeURIComponent((0,_options.getContentItemPath)(editor)),fullUrl=baseUrl+"unprovisionerror=".concat(unprovisionedError)+"&courseid=".concat(courseId)+"&tool=".concat(tool)+"&resourcebase=".concat(resourceBase)+"&wwwroot=".concat(wwwroot)+"&contentitempath=".concat(contentItemPath);return Object.assign({},{iframe:fullUrl.toString()},data)},displayDialogue=async function(editor){let data=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};editor.focus(!0);const modal=await _modal_factory.default.create({type:_modal.default.TYPE,templateContext:getTemplateContext(editor,data),large:!0,scrollable:!1}),$root=await modal.getRoot();let iframe=$root.find("iframe");iframe.css({width:"100%",height:"100%",border:"none"});let contentContainer=$root.find(".modal-dialog");contentContainer.css({"max-width":"55vw"});let bodyContainer=$root.find(".modal-body");bodyContainer.css({height:"81vh"}),modal.show(),window.closeModal=()=>{const closeButton=document.querySelector("#panopto-close");closeButton&&closeButton.click()}}})); + +//# sourceMappingURL=ui.min.js.map \ No newline at end of file diff --git a/amd/build/ui.min.js.map b/amd/build/ui.min.js.map new file mode 100644 index 0000000..9c03091 --- /dev/null +++ b/amd/build/ui.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ui.min.js","sources":["../src/ui.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny Panopto LTI Video ui helper.\n *\n * @module tiny_panoptoltibutton/ui\n * @copyright 2023 Panopto\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'tiny_panoptoltibutton/modal';\nimport ModalFactory from 'core/modal_factory';\nimport\n {\n getCourseId,\n getWwwroot,\n getContentItemPath,\n getResourceBase,\n getTool,\n getUnprovisionedError\n } from './options';\nimport Config from 'core/config';\n\nexport const handleAction = (editor) => {\n displayDialogue(editor);\n};\n\n/**\n * Get the template context for the dialogue.\n *\n * @param {Editor} editor\n * @param {object} data\n * @returns {object} data\n */\nconst getTemplateContext = (editor, data) => {\n const baseUrl = `${Config.wwwroot}/lib/editor/tiny/plugins/panoptoltibutton/panoptowrapper.html#`;\n const unprovisionedError = encodeURIComponent(\n getUnprovisionedError(editor)\n );\n const courseId = getCourseId(editor);\n const tool = encodeURIComponent(JSON.stringify(getTool(editor)));\n const resourceBase = getResourceBase(editor);\n const wwwroot = encodeURIComponent(getWwwroot(editor));\n const contentItemPath = encodeURIComponent(getContentItemPath(editor));\n\n const fullUrl =\n baseUrl +\n `unprovisionerror=${unprovisionedError}` +\n `&courseid=${courseId}` +\n `&tool=${tool}` +\n `&resourcebase=${resourceBase}` +\n `&wwwroot=${wwwroot}` +\n `&contentitempath=${contentItemPath}`;\n\n return Object.assign({}, {\n iframe: fullUrl.toString(),\n }, data);\n};\n\nconst displayDialogue = async(editor, data = {}) => {\n editor.focus(true);\n const modal = await ModalFactory.create({\n type: Modal.TYPE,\n templateContext: getTemplateContext(editor, data),\n large: true,\n scrollable: false,\n });\n\n const $root = await modal.getRoot();\n\n // Get the iframe element inside the modal.\n let iframe = $root.find(\"iframe\");\n\n // Make the iframe responsive by setting its width and height to 100%.\n iframe.css({\n width: \"100%\",\n height: \"100%\",\n border: \"none\",\n });\n\n // Set the maximum width for the modal content container.\n let contentContainer = $root.find(\".modal-dialog\");\n contentContainer.css({\n \"max-width\": \"55vw\",\n });\n\n // Set height for the body container.\n let bodyContainer = $root.find(\".modal-body\");\n bodyContainer.css({\n height: \"81vh\",\n });\n\n modal.show();\n\n // Close modal from iframe.\n window.closeModal = () => {\n const closeButton = document.querySelector(\"#panopto-close\");\n if (closeButton) {\n closeButton.click();\n }\n };\n};\n"],"names":["editor","displayDialogue","getTemplateContext","data","baseUrl","Config","wwwroot","unprovisionedError","encodeURIComponent","courseId","tool","JSON","stringify","resourceBase","contentItemPath","fullUrl","Object","assign","iframe","toString","async","focus","modal","ModalFactory","create","type","Modal","TYPE","templateContext","large","scrollable","$root","getRoot","find","css","width","height","border","contentContainer","bodyContainer","show","window","closeModal","closeButton","document","querySelector","click"],"mappings":";;;;;;;oPAoC6BA,SACzBC,gBAAgBD,eAUdE,mBAAqB,CAACF,OAAQG,cAC1BC,kBAAaC,gBAAOC,0EACpBC,mBAAqBC,oBACvB,kCAAsBR,SAEpBS,UAAW,wBAAYT,QACvBU,KAAOF,mBAAmBG,KAAKC,WAAU,oBAAQZ,UACjDa,cAAe,4BAAgBb,QAC/BM,QAAUE,oBAAmB,uBAAWR,SACxCc,gBAAkBN,oBAAmB,+BAAmBR,SAExDe,QACFX,mCACoBG,wCACPE,0BACJC,8BACQG,iCACLP,oCACQQ,wBAEjBE,OAAOC,OAAO,GAAI,CACrBC,OAAQH,QAAQI,YACjBhB,OAGDF,gBAAkBmB,eAAMpB,YAAQG,4DAAO,GACzCH,OAAOqB,OAAM,SACPC,YAAcC,uBAAaC,OAAO,CACpCC,KAAMC,eAAMC,KACZC,gBAAiB1B,mBAAmBF,OAAQG,MAC5C0B,OAAO,EACPC,YAAY,IAGVC,YAAcT,MAAMU,cAGtBd,OAASa,MAAME,KAAK,UAGxBf,OAAOgB,IAAI,CACPC,MAAO,OACPC,OAAQ,OACRC,OAAQ,aAIRC,iBAAmBP,MAAME,KAAK,iBAClCK,iBAAiBJ,IAAI,aACJ,aAIbK,cAAgBR,MAAME,KAAK,eAC/BM,cAAcL,IAAI,CACdE,OAAQ,SAGZd,MAAMkB,OAGNC,OAAOC,WAAa,WACVC,YAAcC,SAASC,cAAc,kBACvCF,aACAA,YAAYG"} \ No newline at end of file diff --git a/amd/src/commands.js b/amd/src/commands.js new file mode 100644 index 0000000..abaddc4 --- /dev/null +++ b/amd/src/commands.js @@ -0,0 +1,54 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Panopto LTI Video commands. + * + * @module tiny_panoptoltibutton/commands + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {getButtonImage} from 'editor_tiny/utils'; +import {handleAction} from './ui'; +import {get_string as getString} from 'core/str'; +import {component, buttonName, icon} from './common'; + +export const getSetup = async() => { + const [buttonText, buttonImage] = await Promise.all([ + getString("panopto_button_description", component), + getButtonImage("icon", component), + ]); + + return (editor) => { + // Register the Moodle SVG as an icon suitable for use as a TinyMCE toolbar button. + editor.ui.registry.addIcon(icon, buttonImage.html); + + // Register the Panopto LTI Video Toolbar Button. + editor.ui.registry.addToggleButton(buttonName, { + icon, + tooltip: buttonText, + onAction: () => handleAction(editor), + }); + + // Add the Panopto LTI Video Menu Item. + // This allows it to be added to a standard menu, or a context menu. + editor.ui.registry.addMenuItem(buttonName, { + icon, + text: buttonText, + onAction: () => handleAction(editor), + }); + }; +}; diff --git a/amd/src/common.js b/amd/src/common.js new file mode 100644 index 0000000..4e35838 --- /dev/null +++ b/amd/src/common.js @@ -0,0 +1,31 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Panopto LTI button common values. + * + * @module tiny_panoptoltibutton + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +const component = "tiny_panoptoltibutton"; + +export default { + component, + pluginName: `${component}/plugin`, + icon: component, + buttonName: component, +}; diff --git a/amd/src/configuration.js b/amd/src/configuration.js new file mode 100644 index 0000000..9d3f9c1 --- /dev/null +++ b/amd/src/configuration.js @@ -0,0 +1,37 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Panopto LTI configuration. + * + * @module tiny_panoptoltibutton/configuration + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {buttonName} from './common'; +import {addMenubarItem, addToolbarButton} from 'editor_tiny/utils'; + +export const configure = (instanceConfig) => { + // Update the instance configuration to add the Panopto LTI Video menu option to the menus and toolbars. + return { + menu: addMenubarItem(instanceConfig.menu, "insert", buttonName), + toolbar: addToolbarButton( + instanceConfig.toolbar, + "content", + buttonName + ), + }; +}; diff --git a/amd/src/modal.js b/amd/src/modal.js new file mode 100644 index 0000000..9ec2bf7 --- /dev/null +++ b/amd/src/modal.js @@ -0,0 +1,42 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Panopto LTI Video modal. + * + * @module tiny_panoptoltibutton/modal + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Modal from 'core/modal'; +import ModalRegistry from 'core/modal_registry'; + +const PanoptoModal = class extends Modal { + static TYPE = "tiny_panoptoltibutton/modal"; + static TEMPLATE = "tiny_panoptoltibutton/modal"; + + registerEventListeners() { + // Call the parent registration. + super.registerEventListeners(); + + // Register to close on cancel. + this.registerCloseOnCancel(); + } +}; + +ModalRegistry.register(PanoptoModal.TYPE, PanoptoModal, PanoptoModal.TEMPLATE); + +export default PanoptoModal; diff --git a/amd/src/options.js b/amd/src/options.js new file mode 100644 index 0000000..c784389 --- /dev/null +++ b/amd/src/options.js @@ -0,0 +1,146 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Panopto LTI Video Options helper. + * + * @module tiny_panoptoltibutton/options + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {getPluginOptionName} from 'editor_tiny/options'; +import {pluginName} from './common'; + +// Helper variables for the option names. +const courseid = getPluginOptionName(pluginName, "courseid"); +const tool = getPluginOptionName(pluginName, "tool"); +const wwwroot = getPluginOptionName(pluginName, "wwwroot"); +const contentitempath = getPluginOptionName(pluginName, "contentitempath"); +const resourcebase = getPluginOptionName(pluginName, "resourcebase"); +const panoptoltibuttondescription = getPluginOptionName( + pluginName, + "panoptoltibuttondescription" +); +const panoptoltibuttonlongdescription = getPluginOptionName( + pluginName, + "panoptoltibuttonlongdescription" +); +const unprovisionederror = getPluginOptionName( + pluginName, + "unprovisionederror" +); + +/** + * Options registration function. + * + * @param {tinyMCE} editor + */ +export const register = (editor) => { + const registerOption = editor.options.register; + + // For each option, register it with the editor. + registerOption(courseid, { + processor: "string", + }); + registerOption(tool, { + processor: "object", + }); + registerOption(wwwroot, { + processor: "string", + }); + registerOption(contentitempath, { + processor: "string", + }); + registerOption(resourcebase, { + processor: "string", + }); + registerOption(panoptoltibuttondescription, { + processor: "string", + }); + registerOption(panoptoltibuttonlongdescription, { + processor: "string", + }); + registerOption(unprovisionederror, { + processor: "string", + }); +}; + +/** + * Fetch the courseid value for this editor instance. + * + * @param {tinyMCE} editor The editor instance to fetch the value for + * @returns {object} The value of the courseid option + */ +export const getCourseId = (editor) => editor.options.get(courseid); + +/** + * Fetch the tool value for this editor instance. + * + * @param {tinyMCE} editor The editor instance to fetch the value for + * @returns {object} The value of the tool option + */ +export const getTool = (editor) => editor.options.get(tool); + +/** + * Fetch the wwwroot value for this editor instance. + * + * @param {tinyMCE} editor The editor instance to fetch the value for + * @returns {object} The value of the wwwroot option + */ +export const getWwwroot = (editor) => editor.options.get(wwwroot); + +/** + * Fetch the contentitempath value for this editor instance. + * + * @param {tinyMCE} editor The editor instance to fetch the value for + * @returns {object} The value of the contentitempath option + */ +export const getContentItemPath = (editor) => editor.options.get(contentitempath); + +/** + * Fetch the resourcebase value for this editor instance. + * + * @param {tinyMCE} editor The editor instance to fetch the value for + * @returns {object} The value of the resourcebase option + */ +export const getResourceBase = (editor) => editor.options.get(resourcebase); + +/** + * Fetch the panoptoltibuttondescription value for this editor instance. + * + * @param {tinyMCE} editor The editor instance to fetch the value for + * @returns {object} The value of the panoptoltibuttondescription option + */ +export const getPanoptoLtiButtonDescription = (editor) => + editor.options.get(panoptoltibuttondescription); + +/** + * Fetch the panoptoltibuttonlongdescription value for this editor instance. + * + * @param {tinyMCE} editor The editor instance to fetch the value for + * @returns {object} The value of the panoptoltibuttonlongdescription option + */ +export const getPanoptoLtiButtonLongDescription = (editor) => + editor.options.get(panoptoltibuttonlongdescription); + +/** + * Fetch the unprovisionederror value for this editor instance. + * + * @param {tinyMCE} editor The editor instance to fetch the value for + * @returns {object} The value of the unprovisionederror option + */ +export const getUnprovisionedError = (editor) => + editor.options.get(unprovisionederror); diff --git a/amd/src/plugin.js b/amd/src/plugin.js new file mode 100644 index 0000000..550c6c5 --- /dev/null +++ b/amd/src/plugin.js @@ -0,0 +1,55 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Panopto LTI Video plugin for Moodle. + * + * @module tiny_panoptoltibutton + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import { getTinyMCE } from "editor_tiny/loader"; +import { getPluginMetadata } from "editor_tiny/utils"; + +import { component, pluginName } from "./common"; +import { register as registerOptions } from "./options"; +import { getSetup as getCommandSetup } from "./commands"; +import * as Configuration from "./configuration"; + +// Setup the tiny_panoptoltibutton Plugin. +export default new Promise(async (resolve) => { + // Note: The PluginManager.add function does not support asynchronous configuration. + // Perform any asynchronous configuration here, and then call the PluginManager.add function. + const [tinyMCE, pluginMetadata, setupCommands] = await Promise.all([ + getTinyMCE(), + getPluginMetadata(component, pluginName), + getCommandSetup(), + ]); + + // Reminder: Any asynchronous code must be run before this point. + tinyMCE.PluginManager.add(pluginName, (editor) => { + // Register any options that your plugin has + registerOptions(editor); + + // Setup any commands such as buttons, menu items, and so on. + setupCommands(editor); + + // Return the pluginMetadata object. This is used by TinyMCE to display a help link for your plugin. + return pluginMetadata; + }); + + resolve([pluginName, Configuration]); +}); diff --git a/amd/src/ui.js b/amd/src/ui.js new file mode 100644 index 0000000..343911d --- /dev/null +++ b/amd/src/ui.js @@ -0,0 +1,115 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Tiny Panopto LTI Video ui helper. + * + * @module tiny_panoptoltibutton/ui + * @copyright 2023 Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import Modal from 'tiny_panoptoltibutton/modal'; +import ModalFactory from 'core/modal_factory'; +import + { + getCourseId, + getWwwroot, + getContentItemPath, + getResourceBase, + getTool, + getUnprovisionedError + } from './options'; +import Config from 'core/config'; + +export const handleAction = (editor) => { + displayDialogue(editor); +}; + +/** + * Get the template context for the dialogue. + * + * @param {Editor} editor + * @param {object} data + * @returns {object} data + */ +const getTemplateContext = (editor, data) => { + const baseUrl = `${Config.wwwroot}/lib/editor/tiny/plugins/panoptoltibutton/panoptowrapper.html#`; + const unprovisionedError = encodeURIComponent( + getUnprovisionedError(editor) + ); + const courseId = getCourseId(editor); + const tool = encodeURIComponent(JSON.stringify(getTool(editor))); + const resourceBase = getResourceBase(editor); + const wwwroot = encodeURIComponent(getWwwroot(editor)); + const contentItemPath = encodeURIComponent(getContentItemPath(editor)); + + const fullUrl = + baseUrl + + `unprovisionerror=${unprovisionedError}` + + `&courseid=${courseId}` + + `&tool=${tool}` + + `&resourcebase=${resourceBase}` + + `&wwwroot=${wwwroot}` + + `&contentitempath=${contentItemPath}`; + + return Object.assign({}, { + iframe: fullUrl.toString(), + }, data); +}; + +const displayDialogue = async (editor, data = {}) => { + editor.focus(true); + const modal = await ModalFactory.create({ + type: Modal.TYPE, + templateContext: getTemplateContext(editor, data), + large: true, + scrollable: false, + }); + + const $root = await modal.getRoot(); + + // Get the iframe element inside the modal. + let iframe = $root.find("iframe"); + + // Make the iframe responsive by setting its width and height to 100%. + iframe.css({ + width: "100%", + height: "100%", + border: "none", + }); + + // Set the maximum width for the modal content container. + let contentContainer = $root.find(".modal-dialog"); + contentContainer.css({ + "max-width": "55vw", + }); + + // Set height for the body container. + let bodyContainer = $root.find(".modal-body"); + bodyContainer.css({ + height: "81vh", + }); + + modal.show(); + + // Close modal from iframe. + window.closeModal = () => { + const closeButton = document.querySelector("#panopto-close"); + if (closeButton) { + closeButton.click(); + } + }; +}; diff --git a/classes/plugininfo.php b/classes/plugininfo.php new file mode 100644 index 0000000..3caafe0 --- /dev/null +++ b/classes/plugininfo.php @@ -0,0 +1,107 @@ +. + +/** + * Tiny Panopto LTI Video plugin. + * + * @package tiny_panoptoltibutton + * @copyright 2023 Panopto + * @author Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tiny_panoptoltibutton; + +use context; +use editor_tiny\editor; +use editor_tiny\plugin; +use editor_tiny\plugin_with_buttons; +use editor_tiny\plugin_with_menuitems; +use editor_tiny\plugin_with_configuration; + +require_once(dirname(__FILE__) . '/../../../../../../config.php'); +require_once($CFG->dirroot . '/blocks/panopto/lib/lti/panoptoblock_lti_utility.php'); + +/** + * Tiny Panopto LTI Video plugin. + * + * @package tiny_panoptoltibutton + * @copyright 2023 Panopto + * @author Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class plugininfo extends plugin implements + plugin_with_buttons, + plugin_with_menuitems, + plugin_with_configuration { + + /** + * Get a list of the buttons provided by this plugin. + * + * @return string[] + */ + public static function get_available_buttons(): array { + return [ + 'tiny_panoptoltibutton/panoptoltibutton', + ]; + } + + /** + * Get a list of the menu items provided by this plugin. + * + * @return string[] + */ + public static function get_available_menuitems(): array { + return [ + 'tiny_panoptoltibutton/panoptoltibutton', + ]; + } + + /** + * Get an array of options provided by this plugin. + * + * @param context $context The context that the editor is used within + * @param array $options The options passed in when requesting the editor + * @param array $fpoptions The filepicker options passed in when requesting the editor + * @param editor|null $editor The editor instance in which the plugin is initialised + * @return array + */ + public static function get_plugin_configuration_for_context( + context $context, + array $options, + array $fpoptions, + ?\editor_tiny\editor $editor = null + ): array { + global $COURSE, $CFG, $PAGE; + + $ltitool = \panoptoblock_lti_utility::get_course_tool($COURSE->id); + $resourcebase = sha1( + $PAGE->url->__toString() . '&' . $PAGE->course->sortorder + . '&' . $PAGE->course->timecreated + ); + + return [ + // These will be mapped to a namespaced EditorOption in Tiny. + 'courseid' => $COURSE->id, + 'tool' => !empty($ltitool) ? $ltitool : "", + 'wwwroot' => $CFG->wwwroot, + 'contentitempath' => '/lib/editor/tiny/plugins/panoptoltibutton/contentitem.php', + 'resourcebase' => $resourcebase, + 'panoptoltibuttondescription' => get_string('panopto_button_description', 'tiny_panoptoltibutton'), + 'panoptoltibuttonlongdescription' => get_string('panopto_button_long_description', 'tiny_panoptoltibutton'), + 'unprovisionederror' => get_string('panopto_button_unprovisioned_error', 'tiny_panoptoltibutton') + ]; + } +} diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php new file mode 100644 index 0000000..77a6692 --- /dev/null +++ b/classes/privacy/provider.php @@ -0,0 +1,49 @@ +. + +/** + * Privacy Subsystem implementation for Panopto LTI Video. + * + * @package tiny_panoptoltibutton + * @copyright 2023 Panopto + * @author Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tiny_panoptoltibutton\privacy; + +/** + * Privacy Subsystem for Tiny Panopto LTI Video implementing null_provider. + * + * @package tiny_panoptoltibutton + * @copyright 2023 Panopto + * @author Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements + // This plugin does not store any personal user data. + \core_privacy\local\metadata\null_provider { + + /** + * Get the language string identifier with the component's language + * file to explain why this plugin stores no data. + * + * @return string + */ + public static function get_reason() : string { + return 'privacy:metadata'; + } +} diff --git a/contentitem.php b/contentitem.php new file mode 100644 index 0000000..f4ff44e --- /dev/null +++ b/contentitem.php @@ -0,0 +1,89 @@ +. + +/** + * Handle sending a user to a tool provider to initiate a content-item selection. + * + * @package tiny_panoptoltibutton + * @copyright 2023 Panopto + * @author Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(dirname(__FILE__) . '/../../../../../config.php'); +require_once($CFG->dirroot . '/blocks/panopto/lib/lti/panoptoblock_lti_utility.php'); +require_once($CFG->dirroot . '/mod/lti/lib.php'); +require_once($CFG->dirroot . '/mod/lti/locallib.php'); + +$id = required_param('id', PARAM_INT); +$courseid = required_param('course', PARAM_INT); +$callback = required_param('callback', PARAM_ALPHANUMEXT); + +/** + * LTI Tiny path. + */ +const LTI_TINY_PATH = '/lib/editor/tiny/plugins/panoptoltibutton/contentitem_return.php'; + +// Check access and capabilities. +$course = get_course($courseid); +require_login($course); + +// LTI 1.3 login request. +$config = lti_get_type_type_config($id); + +if ($config->lti_ltiversion === LTI_VERSION_1P3) { + $lti = null; + $isthismoodle41 = empty($CFG->version) ? false : $CFG->version >= 2022112800.00; + if ($isthismoodle41) { + // Moodle 4.1 needs LTI object. + $lti = new stdClass(); + + // Give it some random id, this is not used in the code but will create a PHP notice if not provided. + $ltiviewerurl = new moodle_url(LTI_TINY_PATH); + $resourcelinkid = sha1($ltiviewerurl->out(false) . + '&' . $courseid . + '&' . $course->timecreated + ); + $lti->id = $resourcelinkid; + } + if (!isset($SESSION->lti_initiatelogin_status)) { + echo lti_initiate_login($courseid, "tiny_panoptoltibutton, {$callback}", $lti, $config); + exit; + } +} + +$context = context_course::instance($courseid); + +// Set the return URL. We send the launch container along to help us avoid +// frames-within-frames when the user returns. +$returnurlparams = [ + 'course' => $course->id, + 'id' => $id, + 'sesskey' => sesskey(), + 'callback' => $callback, +]; + +$returnurl = new \moodle_url(LTI_TINY_PATH, $returnurlparams); + +// Prepare the request. +$request = lti_build_content_item_selection_request( + $id, $course, $returnurl, '', '', [], [], false, false, false, false, false +); + +// Get the launch HTML. +$content = lti_post_launch_html($request->params, $request->url, false); + +echo $content; diff --git a/contentitem_return.php b/contentitem_return.php new file mode 100644 index 0000000..4678fe6 --- /dev/null +++ b/contentitem_return.php @@ -0,0 +1,91 @@ +. + +/** + * Handles content item return. + * + * @package tiny_panoptoltibutton + * @copyright 2023 Panopto + * @author Panopto + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once(dirname(__FILE__) . '/../../../../../config.php'); +require_once($CFG->dirroot . '/blocks/panopto/lib/lti/panoptoblock_lti_utility.php'); +require_once($CFG->dirroot . '/mod/lti/lib.php'); +require_once($CFG->dirroot . '/mod/lti/locallib.php'); + +$courseid = required_param('course', PARAM_INT); +$id = required_param('id', PARAM_INT); +$callback = required_param('callback', PARAM_ALPHANUMEXT); +$jwt = optional_param('JWT', '', PARAM_RAW); + +require_login($courseid); + +$context = context_course::instance($courseid); + +$config = lti_get_type_type_config($id); +$islti1p3 = $config->lti_ltiversion === LTI_VERSION_1P3; + +if (!empty($jwt)) { + $params = lti_convert_from_jwt($id, $jwt); + $consumerkey = $params['oauth_consumer_key'] ?? ''; + $messagetype = $params['lti_message_type'] ?? ''; + $items = $params['content_items'] ?? ''; + $version = $params['lti_version'] ?? ''; + $errormsg = $params['lti_errormsg'] ?? ''; + $msg = $params['lti_msg'] ?? ''; +} else { + $consumerkey = required_param('oauth_consumer_key', PARAM_RAW); + $messagetype = required_param('lti_message_type', PARAM_TEXT); + $version = required_param('lti_version', PARAM_TEXT); + $items = optional_param('content_items', '', PARAM_RAW_TRIMMED); + $errormsg = optional_param('lti_errormsg', '', PARAM_TEXT); + $msg = optional_param('lti_msg', '', PARAM_TEXT); +} + +$contentitems = json_decode($items); + +$errors = []; + +// Affirm that the content item is a JSON object. +if (!is_object($contentitems) && !is_array($contentitems)) { + $errors[] = 'invalidjson'; +} + +if ($islti1p3) { + // Update content items data if this is lti 1.3 and not embed. + $doctarget = $contentitems->{'@graph'}[0]->placementAdvice->presentationDocumentTarget + ? $contentitems->{'@graph'}[0]->placementAdvice->presentationDocumentTarget + : ($contentitems->{'@graph'}[0]->iframe ? "iframe" : "frame"); + $thumbnail = $contentitems->{'@graph'}[0]->thumbnail; + if ($doctarget == 'iframe' && !empty($thumbnail)) { + $contentitems->{'@graph'}[0]->placementAdvice->presentationDocumentTarget = 'frame'; + $contentitems->{'@graph'}[0]->placementAdvice->windowTarget = '_blank'; + $contentitems->{'@graph'}[0]->{'@type'} = 'ContentItem'; + $contentitems->{'@graph'}[0]->mediaType = 'text/html'; + } +} + +?> + + diff --git a/js/handlebars.min-v4.7.7.js b/js/handlebars.min-v4.7.7.js new file mode 100644 index 0000000..1ebc260 --- /dev/null +++ b/js/handlebars.min-v4.7.7.js @@ -0,0 +1,29 @@ +/**! + + @license + handlebars v4.7.7 + +Copyright (C) 2011-2019 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +!function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?exports.Handlebars=b():a.Handlebars=b()}(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){"use strict";function d(){var a=r();return a.compile=function(b,c){return k.compile(b,c,a)},a.precompile=function(b,c){return k.precompile(b,c,a)},a.AST=i["default"],a.Compiler=k.Compiler,a.JavaScriptCompiler=m["default"],a.Parser=j.parser,a.parse=j.parse,a.parseWithoutProcessing=j.parseWithoutProcessing,a}var e=c(1)["default"];b.__esModule=!0;var f=c(2),g=e(f),h=c(45),i=e(h),j=c(46),k=c(51),l=c(52),m=e(l),n=c(49),o=e(n),p=c(44),q=e(p),r=g["default"].create,s=d();s.create=d,q["default"](s),s.Visitor=o["default"],s["default"]=s,b["default"]=s,a.exports=b["default"]},function(a,b){"use strict";b["default"]=function(a){return a&&a.__esModule?a:{"default":a}},b.__esModule=!0},function(a,b,c){"use strict";function d(){var a=new h.HandlebarsEnvironment;return n.extend(a,h),a.SafeString=j["default"],a.Exception=l["default"],a.Utils=n,a.escapeExpression=n.escapeExpression,a.VM=p,a.template=function(b){return p.template(b,a)},a}var e=c(3)["default"],f=c(1)["default"];b.__esModule=!0;var g=c(4),h=e(g),i=c(37),j=f(i),k=c(6),l=f(k),m=c(5),n=e(m),o=c(38),p=e(o),q=c(44),r=f(q),s=d();s.create=d,r["default"](s),s["default"]=s,b["default"]=s,a.exports=b["default"]},function(a,b){"use strict";b["default"]=function(a){if(a&&a.__esModule)return a;var b={};if(null!=a)for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&(b[c]=a[c]);return b["default"]=a,b},b.__esModule=!0},function(a,b,c){"use strict";function d(a,b,c){this.helpers=a||{},this.partials=b||{},this.decorators=c||{},i.registerDefaultHelpers(this),j.registerDefaultDecorators(this)}var e=c(1)["default"];b.__esModule=!0,b.HandlebarsEnvironment=d;var f=c(5),g=c(6),h=e(g),i=c(10),j=c(30),k=c(32),l=e(k),m=c(33),n="4.7.7";b.VERSION=n;var o=8;b.COMPILER_REVISION=o;var p=7;b.LAST_COMPATIBLE_COMPILER_REVISION=p;var q={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:"== 2.0.0-alpha.x",6:">= 2.0.0-beta.1",7:">= 4.0.0 <4.3.0",8:">= 4.3.0"};b.REVISION_CHANGES=q;var r="[object Object]";d.prototype={constructor:d,logger:l["default"],log:l["default"].log,registerHelper:function(a,b){if(f.toString.call(a)===r){if(b)throw new h["default"]("Arg not supported with multiple helpers");f.extend(this.helpers,a)}else this.helpers[a]=b},unregisterHelper:function(a){delete this.helpers[a]},registerPartial:function(a,b){if(f.toString.call(a)===r)f.extend(this.partials,a);else{if("undefined"==typeof b)throw new h["default"]('Attempting to register a partial called "'+a+'" as undefined');this.partials[a]=b}},unregisterPartial:function(a){delete this.partials[a]},registerDecorator:function(a,b){if(f.toString.call(a)===r){if(b)throw new h["default"]("Arg not supported with multiple decorators");f.extend(this.decorators,a)}else this.decorators[a]=b},unregisterDecorator:function(a){delete this.decorators[a]},resetLoggedPropertyAccesses:function(){m.resetLoggedProperties()}};var s=l["default"].log;b.log=s,b.createFrame=f.createFrame,b.logger=l["default"]},function(a,b){"use strict";function c(a){return k[a]}function d(a){for(var b=1;b":">",'"':""","'":"'","`":"`","=":"="},l=/[&<>"'`=]/g,m=/[&<>"'`=]/,n=Object.prototype.toString;b.toString=n;var o=function(a){return"function"==typeof a};o(/x/)&&(b.isFunction=o=function(a){return"function"==typeof a&&"[object Function]"===n.call(a)}),b.isFunction=o;var p=Array.isArray||function(a){return!(!a||"object"!=typeof a)&&"[object Array]"===n.call(a)};b.isArray=p},function(a,b,c){"use strict";function d(a,b){var c=b&&b.loc,g=void 0,h=void 0,i=void 0,j=void 0;c&&(g=c.start.line,h=c.end.line,i=c.start.column,j=c.end.column,a+=" - "+g+":"+i);for(var k=Error.prototype.constructor.call(this,a),l=0;l0?(c.ids&&(c.ids=[c.name]),a.helpers.each(b,c)):e(this);if(c.data&&c.ids){var g=d.createFrame(c.data);g.contextPath=d.appendContextPath(c.data.contextPath,c.name),c={data:g}}return f(b,c)})},a.exports=b["default"]},function(a,b,c){(function(d){"use strict";var e=c(13)["default"],f=c(1)["default"];b.__esModule=!0;var g=c(5),h=c(6),i=f(h);b["default"]=function(a){a.registerHelper("each",function(a,b){function c(b,c,d){l&&(l.key=b,l.index=c,l.first=0===c,l.last=!!d,m&&(l.contextPath=m+b)),k+=f(a[b],{data:l,blockParams:g.blockParams([a[b],b],[m+b,null])})}if(!b)throw new i["default"]("Must pass iterator to #each");var f=b.fn,h=b.inverse,j=0,k="",l=void 0,m=void 0;if(b.data&&b.ids&&(m=g.appendContextPath(b.data.contextPath,b.ids[0])+"."),g.isFunction(a)&&(a=a.call(this)),b.data&&(l=g.createFrame(b.data)),a&&"object"==typeof a)if(g.isArray(a))for(var n=a.length;j=0?b:parseInt(a,10)}return a},log:function(a){if(a=e.lookupLevel(a),"undefined"!=typeof console&&e.lookupLevel(e.level)<=a){var b=e.methodMap[a];console[b]||(b="log");for(var c=arguments.length,d=Array(c>1?c-1:0),f=1;f=v.LAST_COMPATIBLE_COMPILER_REVISION&&b<=v.COMPILER_REVISION)){if(b2&&v.push("'"+this.terminals_[s]+"'");x=this.lexer.showPosition?"Parse error on line "+(i+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+v.join(", ")+", got '"+(this.terminals_[n]||n)+"'":"Parse error on line "+(i+1)+": Unexpected "+(1==n?"end of input":"'"+(this.terminals_[n]||n)+"'"),this.parseError(x,{text:this.lexer.match,token:this.terminals_[n]||n,line:this.lexer.yylineno,loc:l,expected:v})}}if(q[0]instanceof Array&&q.length>1)throw new Error("Parse Error: multiple actions possible at state: "+p+", token: "+n);switch(q[0]){case 1:d.push(n),e.push(this.lexer.yytext),f.push(this.lexer.yylloc),d.push(q[1]),n=null,o?(n=o,o=null):(j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,l=this.lexer.yylloc,k>0&&k--);break;case 2:if(t=this.productions_[q[1]][1],w.$=e[e.length-t],w._$={first_line:f[f.length-(t||1)].first_line,last_line:f[f.length-1].last_line,first_column:f[f.length-(t||1)].first_column,last_column:f[f.length-1].last_column},m&&(w._$.range=[f[f.length-(t||1)].range[0],f[f.length-1].range[1]]),r=this.performAction.call(w,h,j,i,this.yy,q[1],e,f),"undefined"!=typeof r)return r;t&&(d=d.slice(0,-1*t*2),e=e.slice(0,-1*t),f=f.slice(0,-1*t)),d.push(this.productions_[q[1]][0]),e.push(w.$),f.push(w._$),u=g[d[d.length-2]][d[d.length-1]],d.push(u);break;case 3:return!0}}return!0}},c=function(){var a={EOF:1,parseError:function(a,b){if(!this.yy.parser)throw new Error(a);this.yy.parser.parseError(a,b)},setInput:function(a){return this._input=a,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var b=a.match(/(?:\r\n?|\n).*/g);return b?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var b=a.length,c=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-b-1),this.offset-=b;var d=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var e=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-b},this.options.ranges&&(this.yylloc.range=[e[0],e[0]+this.yyleng-b]),this},more:function(){return this._more=!0,this},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var a=this.pastInput(),b=new Array(a.length+1).join("-");return a+this.upcomingInput()+"\n"+b+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c,d,e;this._more||(this.yytext="",this.match="");for(var f=this._currentRules(),g=0;gb[0].length)||(b=c,d=g,this.options.flex));g++);return b?(e=b[0].match(/(?:\r\n?|\n).*/g),e&&(this.yylineno+=e.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:e?e[e.length-1].length-e[e.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+b[0].length},this.yytext+=b[0],this.match+=b[0],this.matches=b,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._input=this._input.slice(b[0].length),this.matched+=b[0],a=this.performAction.call(this,this.yy,this,f[d],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),a?a:void 0):""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var a=this.next();return"undefined"!=typeof a?a:this.lex()},begin:function(a){this.conditionStack.push(a)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(a){this.begin(a)}};return a.options={},a.performAction=function(a,b,c,d){function e(a,c){return b.yytext=b.yytext.substring(a,b.yyleng-c+a)}switch(c){case 0:if("\\\\"===b.yytext.slice(-2)?(e(0,1),this.begin("mu")):"\\"===b.yytext.slice(-1)?(e(0,1),this.begin("emu")):this.begin("mu"),b.yytext)return 15;break;case 1:return 15;case 2:return this.popState(),15;case 3:return this.begin("raw"),15;case 4:return this.popState(),"raw"===this.conditionStack[this.conditionStack.length-1]?15:(e(5,9),"END_RAW_BLOCK");case 5:return 15;case 6:return this.popState(),14;case 7:return 65;case 8:return 68;case 9:return 19;case 10:return this.popState(),this.begin("raw"),23;case 11:return 55;case 12:return 60;case 13:return 29;case 14:return 47;case 15:return this.popState(),44;case 16:return this.popState(),44;case 17:return 34;case 18:return 39;case 19:return 51;case 20:return 48;case 21:this.unput(b.yytext),this.popState(),this.begin("com");break;case 22:return this.popState(),14;case 23:return 48;case 24:return 73;case 25:return 72;case 26:return 72;case 27:return 87;case 28:break;case 29:return this.popState(),54;case 30:return this.popState(),33;case 31:return b.yytext=e(1,2).replace(/\\"/g,'"'),80;case 32:return b.yytext=e(1,2).replace(/\\'/g,"'"),80;case 33:return 85;case 34:return 82;case 35:return 82;case 36:return 83;case 37:return 84;case 38:return 81;case 39:return 75;case 40:return 77;case 41:return 72;case 42:return b.yytext=b.yytext.replace(/\\([\\\]])/g,"$1"),72;case 43:return"INVALID";case 44:return 5}},a.rules=[/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|\\\{\{|\\\\\{\{|$)))/,/^(?:\{\{\{\{(?=[^\/]))/,/^(?:\{\{\{\{\/[^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=[=}\s\/.])\}\}\}\})/,/^(?:[^\x00]+?(?=(\{\{\{\{)))/,/^(?:[\s\S]*?--(~)?\}\})/,/^(?:\()/,/^(?:\))/,/^(?:\{\{\{\{)/,/^(?:\}\}\}\})/,/^(?:\{\{(~)?>)/,/^(?:\{\{(~)?#>)/,/^(?:\{\{(~)?#\*?)/,/^(?:\{\{(~)?\/)/,/^(?:\{\{(~)?\^\s*(~)?\}\})/,/^(?:\{\{(~)?\s*else\s*(~)?\}\})/,/^(?:\{\{(~)?\^)/,/^(?:\{\{(~)?\s*else\b)/,/^(?:\{\{(~)?\{)/,/^(?:\{\{(~)?&)/,/^(?:\{\{(~)?!--)/,/^(?:\{\{(~)?![\s\S]*?\}\})/,/^(?:\{\{(~)?\*?)/,/^(?:=)/,/^(?:\.\.)/,/^(?:\.(?=([=~}\s\/.)|])))/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}(~)?\}\})/,/^(?:(~)?\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\s)])))/,/^(?:false(?=([~}\s)])))/,/^(?:undefined(?=([~}\s)])))/,/^(?:null(?=([~}\s)])))/,/^(?:-?[0-9]+(?:\.[0-9]+)?(?=([~}\s)])))/,/^(?:as\s+\|)/,/^(?:\|)/,/^(?:([^\s!"#%-,\.\/;->@\[-\^`\{-~]+(?=([=~}\s\/.)|]))))/,/^(?:\[(\\\]|[^\]])*\])/,/^(?:.)/,/^(?:$)/],a.conditions={mu:{rules:[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],inclusive:!1},emu:{rules:[2],inclusive:!1},com:{rules:[6],inclusive:!1},raw:{rules:[3,4,5],inclusive:!1},INITIAL:{rules:[0,1,44],inclusive:!0}},a}();return b.lexer=c,a.prototype=b,b.Parser=a,new a}();b["default"]=c,a.exports=b["default"]},function(a,b,c){"use strict";function d(){var a=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.options=a}function e(a,b,c){void 0===b&&(b=a.length);var d=a[b-1],e=a[b-2];return d?"ContentStatement"===d.type?(e||!c?/\r?\n\s*?$/:/(^|\r?\n)\s*?$/).test(d.original):void 0:c}function f(a,b,c){void 0===b&&(b=-1);var d=a[b+1],e=a[b+2];return d?"ContentStatement"===d.type?(e||!c?/^\s*?\r?\n/:/^\s*?(\r?\n|$)/).test(d.original):void 0:c}function g(a,b,c){var d=a[null==b?0:b+1];if(d&&"ContentStatement"===d.type&&(c||!d.rightStripped)){var e=d.value;d.value=d.value.replace(c?/^\s+/:/^[ \t]*\r?\n?/,""),d.rightStripped=d.value!==e}}function h(a,b,c){var d=a[null==b?a.length-1:b-1];if(d&&"ContentStatement"===d.type&&(c||!d.leftStripped)){var e=d.value;return d.value=d.value.replace(c?/\s+$/:/[ \t]+$/,""),d.leftStripped=d.value!==e,d.leftStripped}}var i=c(1)["default"];b.__esModule=!0;var j=c(49),k=i(j);d.prototype=new k["default"],d.prototype.Program=function(a){var b=!this.options.ignoreStandalone,c=!this.isRootSeen;this.isRootSeen=!0;for(var d=a.body,i=0,j=d.length;i0)throw new q["default"]("Invalid path: "+d,{loc:c});".."===i&&f++}}return{type:"PathExpression",data:a,depth:f,parts:e,original:d,loc:c}}function j(a,b,c,d,e,f){var g=d.charAt(3)||d.charAt(2),h="{"!==g&&"&"!==g,i=/\*/.test(d);return{type:i?"Decorator":"MustacheStatement",path:a,params:b,hash:c,escaped:h,strip:e,loc:this.locInfo(f)}}function k(a,b,c,e){d(a,c),e=this.locInfo(e);var f={type:"Program",body:b,strip:{},loc:e};return{type:"BlockStatement",path:a.path,params:a.params,hash:a.hash,program:f,openStrip:{},inverseStrip:{},closeStrip:{},loc:e}}function l(a,b,c,e,f,g){e&&e.path&&d(a,e);var h=/\*/.test(a.open);b.blockParams=a.blockParams;var i=void 0,j=void 0;if(c){if(h)throw new q["default"]("Unexpected inverse block on decorator",c);c.chain&&(c.program.body[0].closeStrip=e.strip),j=c.strip,i=c.program}return f&&(f=i,i=b,b=f),{type:h?"DecoratorBlock":"BlockStatement",path:a.path,params:a.params,hash:a.hash,program:b,inverse:i,openStrip:a.strip,inverseStrip:j,closeStrip:e&&e.strip,loc:this.locInfo(g)}}function m(a,b){if(!b&&a.length){var c=a[0].loc,d=a[a.length-1].loc;c&&d&&(b={source:c.source,start:{line:c.start.line,column:c.start.column},end:{line:d.end.line,column:d.end.column}})}return{type:"Program",body:a,strip:{},loc:b}}function n(a,b,c,e){return d(a,c),{type:"PartialBlockStatement",name:a.path,params:a.params,hash:a.hash,program:b,openStrip:a.strip,closeStrip:c&&c.strip,loc:this.locInfo(e)}}var o=c(1)["default"];b.__esModule=!0,b.SourceLocation=e,b.id=f,b.stripFlags=g,b.stripComment=h,b.preparePath=i,b.prepareMustache=j,b.prepareRawBlock=k,b.prepareBlock=l,b.prepareProgram=m,b.preparePartialBlock=n;var p=c(6),q=o(p)},function(a,b,c){"use strict";function d(){}function e(a,b,c){if(null==a||"string"!=typeof a&&"Program"!==a.type)throw new l["default"]("You must pass a string or Handlebars AST to Handlebars.precompile. You passed "+a);b=b||{},"data"in b||(b.data=!0),b.compat&&(b.useDepths=!0);var d=c.parse(a,b),e=(new c.Compiler).compile(d,b);return(new c.JavaScriptCompiler).compile(e,b)}function f(a,b,c){function d(){var d=c.parse(a,b),e=(new c.Compiler).compile(d,b),f=(new c.JavaScriptCompiler).compile(e,b,void 0,!0);return c.template(f)}function e(a,b){return f||(f=d()),f.call(this,a,b)}if(void 0===b&&(b={}),null==a||"string"!=typeof a&&"Program"!==a.type)throw new l["default"]("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+a);b=m.extend({},b),"data"in b||(b.data=!0),b.compat&&(b.useDepths=!0);var f=void 0;return e._setup=function(a){return f||(f=d()),f._setup(a)},e._child=function(a,b,c,e){return f||(f=d()),f._child(a,b,c,e)},e}function g(a,b){if(a===b)return!0;if(m.isArray(a)&&m.isArray(b)&&a.length===b.length){for(var c=0;c1)throw new l["default"]("Unsupported number of partial arguments: "+c.length,a);c.length||(this.options.explicitPartialContext?this.opcode("pushLiteral","undefined"):c.push({type:"PathExpression",parts:[],depth:0}));var d=a.name.original,e="SubExpression"===a.name.type;e&&this.accept(a.name),this.setupFullMustacheParams(a,b,void 0,!0);var f=a.indent||"";this.options.preventIndent&&f&&(this.opcode("appendContent",f),f=""),this.opcode("invokePartial",e,d,f),this.opcode("append")},PartialBlockStatement:function(a){this.PartialStatement(a)},MustacheStatement:function(a){this.SubExpression(a),a.escaped&&!this.options.noEscape?this.opcode("appendEscaped"):this.opcode("append")},Decorator:function(a){this.DecoratorBlock(a)},ContentStatement:function(a){a.value&&this.opcode("appendContent",a.value)},CommentStatement:function(){},SubExpression:function(a){h(a);var b=this.classifySexpr(a);"simple"===b?this.simpleSexpr(a):"helper"===b?this.helperSexpr(a):this.ambiguousSexpr(a)},ambiguousSexpr:function(a,b,c){var d=a.path,e=d.parts[0],f=null!=b||null!=c;this.opcode("getContext",d.depth),this.opcode("pushProgram",b),this.opcode("pushProgram",c),d.strict=!0,this.accept(d),this.opcode("invokeAmbiguous",e,f)},simpleSexpr:function(a){var b=a.path;b.strict=!0,this.accept(b),this.opcode("resolvePossibleLambda")},helperSexpr:function(a,b,c){var d=this.setupFullMustacheParams(a,b,c),e=a.path,f=e.parts[0];if(this.options.knownHelpers[f])this.opcode("invokeKnownHelper",d.length,f);else{if(this.options.knownHelpersOnly)throw new l["default"]("You specified knownHelpersOnly, but used the unknown helper "+f,a);e.strict=!0,e.falsy=!0,this.accept(e),this.opcode("invokeHelper",d.length,e.original,o["default"].helpers.simpleId(e))}},PathExpression:function(a){this.addDepth(a.depth),this.opcode("getContext",a.depth);var b=a.parts[0],c=o["default"].helpers.scopedId(a),d=!a.depth&&!c&&this.blockParamIndex(b);d?this.opcode("lookupBlockParam",d,a.parts):b?a.data?(this.options.data=!0,this.opcode("lookupData",a.depth,a.parts,a.strict)):this.opcode("lookupOnContext",a.parts,a.falsy,a.strict,c):this.opcode("pushContext")},StringLiteral:function(a){this.opcode("pushString",a.value)},NumberLiteral:function(a){this.opcode("pushLiteral",a.value)},BooleanLiteral:function(a){this.opcode("pushLiteral",a.value)},UndefinedLiteral:function(){this.opcode("pushLiteral","undefined")},NullLiteral:function(){this.opcode("pushLiteral","null")},Hash:function(a){var b=a.pairs,c=0,d=b.length;for(this.opcode("pushHash");c=0)return[b,e]}}}},function(a,b,c){"use strict";function d(a){this.value=a}function e(){}function f(a,b,c,d){var e=b.popStack(),f=0,g=c.length;for(a&&g--;f0&&(c+=", "+d.join(", "));var e=0;g(this.aliases).forEach(function(a){var d=b.aliases[a];d.children&&d.referenceCount>1&&(c+=", alias"+ ++e+"="+a,d.children[0]="alias"+e)}),this.lookupPropertyFunctionIsUsed&&(c+=", "+this.lookupPropertyFunctionVarDeclaration());var f=["container","depth0","helpers","partials","data"];(this.useBlockParams||this.useDepths)&&f.push("blockParams"),this.useDepths&&f.push("depths");var h=this.mergeSource(c);return a?(f.push(h),Function.apply(this,f)):this.source.wrap(["function(",f.join(","),") {\n ",h,"}"])},mergeSource:function(a){var b=this.environment.isSimple,c=!this.forceBuffer,d=void 0,e=void 0,f=void 0,g=void 0;return this.source.each(function(a){a.appendToBuffer?(f?a.prepend(" + "):f=a,g=a):(f&&(e?f.prepend("buffer += "):d=!0,g.add(";"),f=g=void 0),e=!0,b||(c=!1))}),c?f?(f.prepend("return "),g.add(";")):e||this.source.push('return "";'):(a+=", buffer = "+(d?"":this.initializeBuffer()),f?(f.prepend("return buffer + "),g.add(";")):this.source.push("return buffer;")),a&&this.source.prepend("var "+a.substring(2)+(d?"":";\n")),this.source.merge()},lookupPropertyFunctionVarDeclaration:function(){return"\n lookupProperty = container.lookupProperty || function(parent, propertyName) {\n if (Object.prototype.hasOwnProperty.call(parent, propertyName)) {\n return parent[propertyName];\n }\n return undefined\n }\n ".trim()},blockValue:function(a){var b=this.aliasable("container.hooks.blockHelperMissing"),c=[this.contextName(0)];this.setupHelperArgs(a,0,c);var d=this.popStack();c.splice(1,0,d),this.push(this.source.functionCall(b,"call",c))},ambiguousBlockValue:function(){var a=this.aliasable("container.hooks.blockHelperMissing"),b=[this.contextName(0)];this.setupHelperArgs("",0,b,!0),this.flushInline();var c=this.topStack();b.splice(1,0,c),this.pushSource(["if (!",this.lastHelper,") { ",c," = ",this.source.functionCall(a,"call",b),"}"])},appendContent:function(a){this.pendingContent?a=this.pendingContent+a:this.pendingLocation=this.source.currentLocation,this.pendingContent=a},append:function(){if(this.isInline())this.replaceStack(function(a){return[" != null ? ",a,' : ""']}),this.pushSource(this.appendToBuffer(this.popStack()));else{var a=this.popStack();this.pushSource(["if (",a," != null) { ",this.appendToBuffer(a,void 0,!0)," }"]),this.environment.isSimple&&this.pushSource(["else { ",this.appendToBuffer("''",void 0,!0)," }"])}},appendEscaped:function(){this.pushSource(this.appendToBuffer([this.aliasable("container.escapeExpression"),"(",this.popStack(),")"]))},getContext:function(a){this.lastContext=a},pushContext:function(){this.pushStackLiteral(this.contextName(this.lastContext))},lookupOnContext:function(a,b,c,d){var e=0;d||!this.options.compat||this.lastContext?this.pushContext():this.push(this.depthedLookup(a[e++])),this.resolvePath("context",a,e,b,c)},lookupBlockParam:function(a,b){this.useBlockParams=!0,this.push(["blockParams[",a[0],"][",a[1],"]"]),this.resolvePath("context",b,1)},lookupData:function(a,b,c){a?this.pushStackLiteral("container.data(data, "+a+")"):this.pushStackLiteral("data"),this.resolvePath("data",b,0,!0,c)},resolvePath:function(a,b,c,d,e){var g=this;if(this.options.strict||this.options.assumeObjects)return void this.push(f(this.options.strict&&e,this,b,a));for(var h=b.length;cthis.stackVars.length&&this.stackVars.push("stack"+this.stackSlot),this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var a=this.inlineStack;this.inlineStack=[];for(var b=0,c=a.length;b+~]|" + ge + ")" + ge + "*"), + x = new RegExp(ge + "|>"), + j = new RegExp(g), + A = new RegExp("^" + t + "$"), + D = { + ID: new RegExp("^#(" + t + ")"), + CLASS: new RegExp("^\\.(" + t + ")"), + TAG: new RegExp("^(" + t + "|[*])"), + ATTR: new RegExp("^" + p), + PSEUDO: new RegExp("^" + g), + CHILD: new RegExp( + "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + ge + + "*(even|odd|(([+-]|)(\\d*)n|)" + + ge + + "*(?:([+-]|)" + + ge + + "*(\\d+)|))" + + ge + + "*\\)|)", + "i" + ), + bool: new RegExp("^(?:" + f + ")$", "i"), + needsContext: new RegExp( + "^" + + ge + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + ge + + "*((?:-\\d)?\\d*)" + + ge + + "*\\)|)(?=[^-]|$)", + "i" + ), + }, + N = /^(?:input|select|textarea|button)$/i, + q = /^h\d$/i, + L = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + H = /[+~]/, + O = new RegExp( + "\\\\[\\da-fA-F]{1,6}" + ge + "?|\\\\([^\\r\\n\\f])", + "g" + ), + P = function (e, t) { + var n = "0x" + e.slice(1) - 65536; + return ( + t || + (n < 0 + ? String.fromCharCode(n + 65536) + : String.fromCharCode( + (n >> 10) | 55296, + (1023 & n) | 56320 + )) + ); + }, + R = function () { + V(); + }, + M = J( + function (e) { + return !0 === e.disabled && fe(e, "fieldset"); + }, + { dir: "parentNode", next: "legend" } + ); + try { + k.apply((oe = ae.call(ye.childNodes)), ye.childNodes), + oe[ye.childNodes.length].nodeType; + } catch (e) { + k = { + apply: function (e, t) { + me.apply(e, ae.call(t)); + }, + call: function (e) { + me.apply(e, ae.call(arguments, 1)); + }, + }; + } + function I(t, e, n, r) { + var i, + o, + a, + s, + u, + l, + c, + f = e && e.ownerDocument, + p = e ? e.nodeType : 9; + if ( + ((n = n || []), + "string" != typeof t || !t || (1 !== p && 9 !== p && 11 !== p)) + ) + return n; + if (!r && (V(e), (e = e || T), C)) { + if (11 !== p && (u = L.exec(t))) + if ((i = u[1])) { + if (9 === p) { + if (!(a = e.getElementById(i))) return n; + if (a.id === i) return k.call(n, a), n; + } else if ( + f && + (a = f.getElementById(i)) && + I.contains(e, a) && + a.id === i + ) + return k.call(n, a), n; + } else { + if (u[2]) + return k.apply(n, e.getElementsByTagName(t)), n; + if ((i = u[3]) && e.getElementsByClassName) + return k.apply(n, e.getElementsByClassName(i)), n; + } + if (!(h[t + " "] || (d && d.test(t)))) { + if ( + ((c = t), (f = e), 1 === p && (x.test(t) || m.test(t))) + ) { + ((f = (H.test(t) && z(e.parentNode)) || e) == e && + le.scope) || + ((s = e.getAttribute("id")) + ? (s = ce.escapeSelector(s)) + : e.setAttribute("id", (s = S))), + (o = (l = Y(t)).length); + while (o--) + l[o] = (s ? "#" + s : ":scope") + " " + Q(l[o]); + c = l.join(","); + } + try { + return k.apply(n, f.querySelectorAll(c)), n; + } catch (e) { + h(t, !0); + } finally { + s === S && e.removeAttribute("id"); + } + } + } + return re(t.replace(ve, "$1"), e, n, r); + } + function W() { + var r = []; + return function e(t, n) { + return ( + r.push(t + " ") > b.cacheLength && delete e[r.shift()], + (e[t + " "] = n) + ); + }; + } + function F(e) { + return (e[S] = !0), e; + } + function $(e) { + var t = T.createElement("fieldset"); + try { + return !!e(t); + } catch (e) { + return !1; + } finally { + t.parentNode && t.parentNode.removeChild(t), (t = null); + } + } + function B(t) { + return function (e) { + return fe(e, "input") && e.type === t; + }; + } + function _(t) { + return function (e) { + return (fe(e, "input") || fe(e, "button")) && e.type === t; + }; + } + function X(t) { + return function (e) { + return "form" in e + ? e.parentNode && !1 === e.disabled + ? "label" in e + ? "label" in e.parentNode + ? e.parentNode.disabled === t + : e.disabled === t + : e.isDisabled === t || + (e.isDisabled !== !t && M(e) === t) + : e.disabled === t + : "label" in e && e.disabled === t; + }; + } + function U(a) { + return F(function (o) { + return ( + (o = +o), + F(function (e, t) { + var n, + r = a([], e.length, o), + i = r.length; + while (i--) e[(n = r[i])] && (e[n] = !(t[n] = e[n])); + }) + ); + }); + } + function z(e) { + return e && "undefined" != typeof e.getElementsByTagName && e; + } + function V(e) { + var t, + n = e ? e.ownerDocument || e : ye; + return ( + n != T && + 9 === n.nodeType && + n.documentElement && + ((r = (T = n).documentElement), + (C = !ce.isXMLDoc(T)), + (i = + r.matches || + r.webkitMatchesSelector || + r.msMatchesSelector), + ye != T && + (t = T.defaultView) && + t.top !== t && + t.addEventListener("unload", R), + (le.getById = $(function (e) { + return ( + (r.appendChild(e).id = ce.expando), + !T.getElementsByName || + !T.getElementsByName(ce.expando).length + ); + })), + (le.disconnectedMatch = $(function (e) { + return i.call(e, "*"); + })), + (le.scope = $(function () { + return T.querySelectorAll(":scope"); + })), + (le.cssHas = $(function () { + try { + return T.querySelector(":has(*,:jqfake)"), !1; + } catch (e) { + return !0; + } + })), + le.getById + ? ((b.filter.ID = function (e) { + var t = e.replace(O, P); + return function (e) { + return e.getAttribute("id") === t; + }; + }), + (b.find.ID = function (e, t) { + if ("undefined" != typeof t.getElementById && C) { + var n = t.getElementById(e); + return n ? [n] : []; + } + })) + : ((b.filter.ID = function (e) { + var n = e.replace(O, P); + return function (e) { + var t = + "undefined" != + typeof e.getAttributeNode && + e.getAttributeNode("id"); + return t && t.value === n; + }; + }), + (b.find.ID = function (e, t) { + if ("undefined" != typeof t.getElementById && C) { + var n, + r, + i, + o = t.getElementById(e); + if (o) { + if ( + (n = o.getAttributeNode("id")) && + n.value === e + ) + return [o]; + (i = t.getElementsByName(e)), (r = 0); + while ((o = i[r++])) + if ( + (n = o.getAttributeNode("id")) && + n.value === e + ) + return [o]; + } + return []; + } + })), + (b.find.TAG = function (e, t) { + return "undefined" != typeof t.getElementsByTagName + ? t.getElementsByTagName(e) + : t.querySelectorAll(e); + }), + (b.find.CLASS = function (e, t) { + if ("undefined" != typeof t.getElementsByClassName && C) + return t.getElementsByClassName(e); + }), + (d = []), + $(function (e) { + var t; + (r.appendChild(e).innerHTML = + ""), + e.querySelectorAll("[selected]").length || + d.push("\\[" + ge + "*(?:value|" + f + ")"), + e.querySelectorAll("[id~=" + S + "-]").length || + d.push("~="), + e.querySelectorAll("a#" + S + "+*").length || + d.push(".#.+[+~]"), + e.querySelectorAll(":checked").length || + d.push(":checked"), + (t = T.createElement("input")).setAttribute( + "type", + "hidden" + ), + e.appendChild(t).setAttribute("name", "D"), + (r.appendChild(e).disabled = !0), + 2 !== e.querySelectorAll(":disabled").length && + d.push(":enabled", ":disabled"), + (t = T.createElement("input")).setAttribute( + "name", + "" + ), + e.appendChild(t), + e.querySelectorAll("[name='']").length || + d.push( + "\\[" + + ge + + "*name" + + ge + + "*=" + + ge + + "*(?:''|\"\")" + ); + }), + le.cssHas || d.push(":has"), + (d = d.length && new RegExp(d.join("|"))), + (l = function (e, t) { + if (e === t) return (a = !0), 0; + var n = + !e.compareDocumentPosition - + !t.compareDocumentPosition; + return ( + n || + (1 & + (n = + (e.ownerDocument || e) == + (t.ownerDocument || t) + ? e.compareDocumentPosition(t) + : 1) || + (!le.sortDetached && + t.compareDocumentPosition(e) === n) + ? e === T || + (e.ownerDocument == ye && I.contains(ye, e)) + ? -1 + : t === T || + (t.ownerDocument == ye && + I.contains(ye, t)) + ? 1 + : o + ? se.call(o, e) - se.call(o, t) + : 0 + : 4 & n + ? -1 + : 1) + ); + })), + T + ); + } + for (e in ((I.matches = function (e, t) { + return I(e, null, null, t); + }), + (I.matchesSelector = function (e, t) { + if ((V(e), C && !h[t + " "] && (!d || !d.test(t)))) + try { + var n = i.call(e, t); + if ( + n || + le.disconnectedMatch || + (e.document && 11 !== e.document.nodeType) + ) + return n; + } catch (e) { + h(t, !0); + } + return 0 < I(t, T, null, [e]).length; + }), + (I.contains = function (e, t) { + return (e.ownerDocument || e) != T && V(e), ce.contains(e, t); + }), + (I.attr = function (e, t) { + (e.ownerDocument || e) != T && V(e); + var n = b.attrHandle[t.toLowerCase()], + r = + n && ue.call(b.attrHandle, t.toLowerCase()) + ? n(e, t, !C) + : void 0; + return void 0 !== r ? r : e.getAttribute(t); + }), + (I.error = function (e) { + throw new Error("Syntax error, unrecognized expression: " + e); + }), + (ce.uniqueSort = function (e) { + var t, + n = [], + r = 0, + i = 0; + if ( + ((a = !le.sortStable), + (o = !le.sortStable && ae.call(e, 0)), + de.call(e, l), + a) + ) { + while ((t = e[i++])) t === e[i] && (r = n.push(i)); + while (r--) he.call(e, n[r], 1); + } + return (o = null), e; + }), + (ce.fn.uniqueSort = function () { + return this.pushStack(ce.uniqueSort(ae.apply(this))); + }), + ((b = ce.expr = + { + cacheLength: 50, + createPseudo: F, + match: D, + 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(O, P)), + (e[3] = (e[3] || e[4] || e[5] || "").replace(O, P)), + "~=" === 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] || I.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] && I.error(e[0]), + e + ); + }, + PSEUDO: function (e) { + var t, + n = !e[6] && e[2]; + return D.CHILD.test(e[0]) + ? null + : (e[3] + ? (e[2] = e[4] || e[5] || "") + : n && + j.test(n) && + (t = Y(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(O, P).toLowerCase(); + return "*" === e + ? function () { + return !0; + } + : function (e) { + return fe(e, t); + }; + }, + CLASS: function (e) { + var t = s[e + " "]; + return ( + t || + ((t = new RegExp( + "(^|" + ge + ")" + e + "(" + ge + "|$)" + )) && + s(e, function (e) { + return t.test( + ("string" == typeof e.className && + e.className) || + ("undefined" != + typeof e.getAttribute && + e.getAttribute("class")) || + "" + ); + })) + ); + }, + ATTR: function (n, r, i) { + return function (e) { + var t = I.attr(e, n); + return null == t + ? "!=" === r + : !r || + ((t += ""), + "=" === r + ? t === i + : "!=" === r + ? t !== i + : "^=" === r + ? i && 0 === t.indexOf(i) + : "*=" === r + ? i && -1 < t.indexOf(i) + : "$=" === r + ? i && t.slice(-i.length) === i + : "~=" === r + ? -1 < + ( + " " + + t.replace(v, " ") + + " " + ).indexOf(i) + : "|=" === r && + (t === i || + t.slice(0, i.length + 1) === + i + "-")); + }; + }, + CHILD: function (d, e, t, h, g) { + var v = "nth" !== d.slice(0, 3), + y = "last" !== d.slice(-4), + m = "of-type" === e; + return 1 === h && 0 === g + ? function (e) { + return !!e.parentNode; + } + : function (e, t, n) { + var r, + i, + o, + a, + s, + u = + v !== y + ? "nextSibling" + : "previousSibling", + l = e.parentNode, + c = m && e.nodeName.toLowerCase(), + f = !n && !m, + p = !1; + if (l) { + if (v) { + while (u) { + o = e; + while ((o = o[u])) + if ( + m + ? fe(o, c) + : 1 === o.nodeType + ) + return !1; + s = u = + "only" === d && + !s && + "nextSibling"; + } + return !0; + } + if ( + ((s = [ + y ? l.firstChild : l.lastChild, + ]), + y && f) + ) { + (p = + (a = + (r = + (i = l[S] || (l[S] = {}))[ + d + ] || [])[0] === E && + r[1]) && r[2]), + (o = a && l.childNodes[a]); + while ( + (o = + (++a && o && o[u]) || + (p = a = 0) || + s.pop()) + ) + if ( + 1 === o.nodeType && + ++p && + o === e + ) { + i[d] = [E, a, p]; + break; + } + } else if ( + (f && + (p = a = + (r = + (i = e[S] || (e[S] = {}))[ + d + ] || [])[0] === E && + r[1]), + !1 === p) + ) + while ( + (o = + (++a && o && o[u]) || + (p = a = 0) || + s.pop()) + ) + if ( + (m + ? fe(o, c) + : 1 === o.nodeType) && + ++p && + (f && + ((i = + o[S] || (o[S] = {}))[ + d + ] = [E, p]), + o === e) + ) + break; + return ( + (p -= g) === h || + (p % h == 0 && 0 <= p / h) + ); + } + }; + }, + PSEUDO: function (e, o) { + var t, + a = + b.pseudos[e] || + b.setFilters[e.toLowerCase()] || + I.error("unsupported pseudo: " + e); + return a[S] + ? a(o) + : 1 < a.length + ? ((t = [e, e, "", o]), + b.setFilters.hasOwnProperty(e.toLowerCase()) + ? F(function (e, t) { + var n, + r = a(e, o), + i = r.length; + while (i--) + e[(n = se.call(e, r[i]))] = !(t[n] = + r[i]); + }) + : function (e) { + return a(e, 0, t); + }) + : a; + }, + }, + pseudos: { + not: F(function (e) { + var r = [], + i = [], + s = ne(e.replace(ve, "$1")); + return s[S] + ? F(function (e, t, n, r) { + var i, + o = s(e, null, r, []), + a = e.length; + while (a--) + (i = o[a]) && (e[a] = !(t[a] = i)); + }) + : function (e, t, n) { + return ( + (r[0] = e), + s(r, null, n, i), + (r[0] = null), + !i.pop() + ); + }; + }), + has: F(function (t) { + return function (e) { + return 0 < I(t, e).length; + }; + }), + contains: F(function (t) { + return ( + (t = t.replace(O, P)), + function (e) { + return ( + -1 < + (e.textContent || ce.text(e)).indexOf(t) + ); + } + ); + }), + lang: F(function (n) { + return ( + A.test(n || "") || + I.error("unsupported lang: " + n), + (n = n.replace(O, P).toLowerCase()), + function (e) { + var t; + do { + if ( + (t = C + ? e.lang + : e.getAttribute("xml:lang") || + e.getAttribute("lang")) + ) + return ( + (t = t.toLowerCase()) === n || + 0 === t.indexOf(n + "-") + ); + } while ( + (e = e.parentNode) && + 1 === e.nodeType + ); + return !1; + } + ); + }), + target: function (e) { + var t = ie.location && ie.location.hash; + return t && t.slice(1) === e.id; + }, + root: function (e) { + return e === r; + }, + focus: function (e) { + return ( + e === + (function () { + try { + return T.activeElement; + } catch (e) {} + })() && + T.hasFocus() && + !!(e.type || e.href || ~e.tabIndex) + ); + }, + enabled: X(!1), + disabled: X(!0), + checked: function (e) { + return ( + (fe(e, "input") && !!e.checked) || + (fe(e, "option") && !!e.selected) + ); + }, + selected: function (e) { + return ( + e.parentNode && e.parentNode.selectedIndex, + !0 === e.selected + ); + }, + empty: function (e) { + for (e = e.firstChild; e; e = e.nextSibling) + if (e.nodeType < 6) return !1; + return !0; + }, + parent: function (e) { + return !b.pseudos.empty(e); + }, + header: function (e) { + return q.test(e.nodeName); + }, + input: function (e) { + return N.test(e.nodeName); + }, + button: function (e) { + return ( + (fe(e, "input") && "button" === e.type) || + fe(e, "button") + ); + }, + text: function (e) { + var t; + return ( + fe(e, "input") && + "text" === e.type && + (null == (t = e.getAttribute("type")) || + "text" === t.toLowerCase()) + ); + }, + first: U(function () { + return [0]; + }), + last: U(function (e, t) { + return [t - 1]; + }), + eq: U(function (e, t, n) { + return [n < 0 ? n + t : n]; + }), + even: U(function (e, t) { + for (var n = 0; n < t; n += 2) e.push(n); + return e; + }), + odd: U(function (e, t) { + for (var n = 1; n < t; n += 2) e.push(n); + return e; + }), + lt: U(function (e, t, n) { + var r; + for (r = n < 0 ? n + t : t < n ? t : n; 0 <= --r; ) + e.push(r); + return e; + }), + gt: U(function (e, t, n) { + for (var r = n < 0 ? n + t : n; ++r < t; ) e.push(r); + return e; + }), + }, + }).pseudos.nth = b.pseudos.eq), + { radio: !0, checkbox: !0, file: !0, password: !0, image: !0 })) + b.pseudos[e] = B(e); + for (e in { submit: !0, reset: !0 }) b.pseudos[e] = _(e); + function G() {} + function Y(e, t) { + var n, + r, + i, + o, + a, + s, + u, + l = c[e + " "]; + if (l) return t ? 0 : l.slice(0); + (a = e), (s = []), (u = b.preFilter); + while (a) { + for (o in ((n && !(r = y.exec(a))) || + (r && (a = a.slice(r[0].length) || a), s.push((i = []))), + (n = !1), + (r = m.exec(a)) && + ((n = r.shift()), + i.push({ value: n, type: r[0].replace(ve, " ") }), + (a = a.slice(n.length))), + b.filter)) + !(r = D[o].exec(a)) || + (u[o] && !(r = u[o](r))) || + ((n = r.shift()), + i.push({ value: n, type: o, matches: r }), + (a = a.slice(n.length))); + if (!n) break; + } + return t ? a.length : a ? I.error(e) : c(e, s).slice(0); + } + function Q(e) { + for (var t = 0, n = e.length, r = ""; t < n; t++) r += e[t].value; + return r; + } + function J(a, e, t) { + var s = e.dir, + u = e.next, + l = u || s, + c = t && "parentNode" === l, + f = n++; + return e.first + ? function (e, t, n) { + while ((e = e[s])) + if (1 === e.nodeType || c) return a(e, t, n); + return !1; + } + : function (e, t, n) { + var r, + i, + o = [E, f]; + if (n) { + while ((e = e[s])) + if ((1 === e.nodeType || c) && a(e, t, n)) + return !0; + } else + while ((e = e[s])) + if (1 === e.nodeType || c) + if ( + ((i = e[S] || (e[S] = {})), u && fe(e, u)) + ) + e = e[s] || e; + else { + if ( + (r = i[l]) && + r[0] === E && + r[1] === f + ) + return (o[2] = r[2]); + if (((i[l] = o)[2] = a(e, t, n))) + return !0; + } + return !1; + }; + } + function K(i) { + return 1 < i.length + ? function (e, t, n) { + var r = i.length; + while (r--) if (!i[r](e, t, n)) return !1; + return !0; + } + : i[0]; + } + function Z(e, t, n, r, i) { + for (var o, a = [], s = 0, u = e.length, l = null != t; s < u; s++) + (o = e[s]) && + ((n && !n(o, r, i)) || (a.push(o), l && t.push(s))); + return a; + } + function ee(d, h, g, v, y, e) { + return ( + v && !v[S] && (v = ee(v)), + y && !y[S] && (y = ee(y, e)), + F(function (e, t, n, r) { + var i, + o, + a, + s, + u = [], + l = [], + c = t.length, + f = + e || + (function (e, t, n) { + for (var r = 0, i = t.length; r < i; r++) + I(e, t[r], n); + return n; + })(h || "*", n.nodeType ? [n] : n, []), + p = !d || (!e && h) ? f : Z(f, u, d, n, r); + if ( + (g + ? g(p, (s = y || (e ? d : c || v) ? [] : t), n, r) + : (s = p), + v) + ) { + (i = Z(s, l)), v(i, [], n, r), (o = i.length); + while (o--) (a = i[o]) && (s[l[o]] = !(p[l[o]] = a)); + } + if (e) { + if (y || d) { + if (y) { + (i = []), (o = s.length); + while (o--) (a = s[o]) && i.push((p[o] = a)); + y(null, (s = []), i, r); + } + o = s.length; + while (o--) + (a = s[o]) && + -1 < (i = y ? se.call(e, a) : u[o]) && + (e[i] = !(t[i] = a)); + } + } else (s = Z(s === t ? s.splice(c, s.length) : s)), y ? y(null, t, s, r) : k.apply(t, s); + }) + ); + } + function te(e) { + for ( + var i, + t, + n, + r = e.length, + o = b.relative[e[0].type], + a = o || b.relative[" "], + s = o ? 1 : 0, + u = J( + function (e) { + return e === i; + }, + a, + !0 + ), + l = J( + function (e) { + return -1 < se.call(i, e); + }, + a, + !0 + ), + c = [ + function (e, t, n) { + var r = + (!o && (n || t != w)) || + ((i = t).nodeType ? u(e, t, n) : l(e, t, n)); + return (i = null), r; + }, + ]; + s < r; + s++ + ) + if ((t = b.relative[e[s].type])) c = [J(K(c), t)]; + else { + if ( + (t = b.filter[e[s].type].apply(null, e[s].matches))[S] + ) { + for (n = ++s; n < r; n++) + if (b.relative[e[n].type]) break; + return ee( + 1 < s && K(c), + 1 < s && + Q( + e + .slice(0, s - 1) + .concat({ + value: + " " === e[s - 2].type + ? "*" + : "", + }) + ).replace(ve, "$1"), + t, + s < n && te(e.slice(s, n)), + n < r && te((e = e.slice(n))), + n < r && Q(e) + ); + } + c.push(t); + } + return K(c); + } + function ne(e, t) { + var n, + v, + y, + m, + x, + r, + i = [], + o = [], + a = u[e + " "]; + if (!a) { + t || (t = Y(e)), (n = t.length); + while (n--) (a = te(t[n]))[S] ? i.push(a) : o.push(a); + (a = u( + e, + ((v = o), + (m = 0 < (y = i).length), + (x = 0 < v.length), + (r = function (e, t, n, r, i) { + var o, + a, + s, + u = 0, + l = "0", + c = e && [], + f = [], + p = w, + d = e || (x && b.find.TAG("*", i)), + h = (E += null == p ? 1 : Math.random() || 0.1), + g = d.length; + for ( + i && (w = t == T || t || i); + l !== g && null != (o = d[l]); + l++ + ) { + if (x && o) { + (a = 0), + t || + o.ownerDocument == T || + (V(o), (n = !C)); + while ((s = v[a++])) + if (s(o, t || T, n)) { + k.call(r, o); + break; + } + i && (E = h); + } + m && ((o = !s && o) && u--, e && c.push(o)); + } + if (((u += l), m && l !== u)) { + a = 0; + while ((s = y[a++])) s(c, f, t, n); + if (e) { + if (0 < u) + while (l--) + c[l] || f[l] || (f[l] = pe.call(r)); + f = Z(f); + } + k.apply(r, f), + i && + !e && + 0 < f.length && + 1 < u + y.length && + ce.uniqueSort(r); + } + return i && ((E = h), (w = p)), c; + }), + m ? F(r) : r) + )).selector = e; + } + return a; + } + function re(e, t, n, r) { + var i, + o, + a, + s, + u, + l = "function" == typeof e && e, + c = !r && Y((e = l.selector || e)); + if (((n = n || []), 1 === c.length)) { + if ( + 2 < (o = c[0] = c[0].slice(0)).length && + "ID" === (a = o[0]).type && + 9 === t.nodeType && + C && + b.relative[o[1].type] + ) { + if ( + !(t = (b.find.ID(a.matches[0].replace(O, P), t) || + [])[0]) + ) + return n; + l && (t = t.parentNode), + (e = e.slice(o.shift().value.length)); + } + i = D.needsContext.test(e) ? 0 : o.length; + while (i--) { + if (((a = o[i]), b.relative[(s = a.type)])) break; + if ( + (u = b.find[s]) && + (r = u( + a.matches[0].replace(O, P), + (H.test(o[0].type) && z(t.parentNode)) || t + )) + ) { + if ((o.splice(i, 1), !(e = r.length && Q(o)))) + return k.apply(n, r), n; + break; + } + } + } + return ( + (l || ne(e, c))( + r, + t, + !C, + n, + !t || (H.test(e) && z(t.parentNode)) || t + ), + n + ); + } + (G.prototype = b.filters = b.pseudos), + (b.setFilters = new G()), + (le.sortStable = S.split("").sort(l).join("") === S), + V(), + (le.sortDetached = $(function (e) { + return ( + 1 & e.compareDocumentPosition(T.createElement("fieldset")) + ); + })), + (ce.find = I), + (ce.expr[":"] = ce.expr.pseudos), + (ce.unique = ce.uniqueSort), + (I.compile = ne), + (I.select = re), + (I.setDocument = V), + (I.escape = ce.escapeSelector), + (I.getText = ce.text), + (I.isXML = ce.isXMLDoc), + (I.selectors = ce.expr), + (I.support = ce.support), + (I.uniqueSort = ce.uniqueSort); + })(); + var d = function (e, t, n) { + var r = [], + i = void 0 !== n; + while ((e = e[t]) && 9 !== e.nodeType) + if (1 === e.nodeType) { + if (i && ce(e).is(n)) break; + r.push(e); + } + return r; + }, + h = function (e, t) { + for (var n = []; e; e = e.nextSibling) + 1 === e.nodeType && e !== t && n.push(e); + return n; + }, + b = ce.expr.match.needsContext, + w = /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i; + function T(e, n, r) { + return v(n) + ? ce.grep(e, function (e, t) { + return !!n.call(e, t, e) !== r; + }) + : n.nodeType + ? ce.grep(e, function (e) { + return (e === n) !== r; + }) + : "string" != typeof n + ? ce.grep(e, function (e) { + return -1 < se.call(n, e) !== r; + }) + : ce.filter(n, e, r); + } + (ce.filter = function (e, t, n) { + var r = t[0]; + return ( + n && (e = ":not(" + e + ")"), + 1 === t.length && 1 === r.nodeType + ? ce.find.matchesSelector(r, e) + ? [r] + : [] + : ce.find.matches( + e, + ce.grep(t, function (e) { + return 1 === e.nodeType; + }) + ) + ); + }), + ce.fn.extend({ + find: function (e) { + var t, + n, + r = this.length, + i = this; + if ("string" != typeof e) + return this.pushStack( + ce(e).filter(function () { + for (t = 0; t < r; t++) + if (ce.contains(i[t], this)) return !0; + }) + ); + for (n = this.pushStack([]), t = 0; t < r; t++) + ce.find(e, i[t], n); + return 1 < r ? ce.uniqueSort(n) : n; + }, + filter: function (e) { + return this.pushStack(T(this, e || [], !1)); + }, + not: function (e) { + return this.pushStack(T(this, e || [], !0)); + }, + is: function (e) { + return !!T( + this, + "string" == typeof e && b.test(e) ? ce(e) : e || [], + !1 + ).length; + }, + }); + var k, + S = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/; + ((ce.fn.init = function (e, t, n) { + var r, i; + if (!e) return this; + if (((n = n || k), "string" == typeof e)) { + if ( + !(r = + "<" === e[0] && ">" === e[e.length - 1] && 3 <= e.length + ? [null, e, null] + : S.exec(e)) || + (!r[1] && t) + ) + return !t || t.jquery + ? (t || n).find(e) + : this.constructor(t).find(e); + if (r[1]) { + if ( + ((t = t instanceof ce ? t[0] : t), + ce.merge( + this, + ce.parseHTML( + r[1], + t && t.nodeType ? t.ownerDocument || t : C, + !0 + ) + ), + w.test(r[1]) && ce.isPlainObject(t)) + ) + for (r in t) + v(this[r]) ? this[r](t[r]) : this.attr(r, t[r]); + return this; + } + return ( + (i = C.getElementById(r[2])) && + ((this[0] = i), (this.length = 1)), + this + ); + } + return e.nodeType + ? ((this[0] = e), (this.length = 1), this) + : v(e) + ? void 0 !== n.ready + ? n.ready(e) + : e(ce) + : ce.makeArray(e, this); + }).prototype = ce.fn), + (k = ce(C)); + var E = /^(?:parents|prev(?:Until|All))/, + j = { children: !0, contents: !0, next: !0, prev: !0 }; + function A(e, t) { + while ((e = e[t]) && 1 !== e.nodeType); + return e; + } + ce.fn.extend({ + has: function (e) { + var t = ce(e, this), + n = t.length; + return this.filter(function () { + for (var e = 0; e < n; e++) + if (ce.contains(this, t[e])) return !0; + }); + }, + closest: function (e, t) { + var n, + r = 0, + i = this.length, + o = [], + a = "string" != typeof e && ce(e); + if (!b.test(e)) + for (; r < i; r++) + for (n = this[r]; n && n !== t; n = n.parentNode) + if ( + n.nodeType < 11 && + (a + ? -1 < a.index(n) + : 1 === n.nodeType && + ce.find.matchesSelector(n, e)) + ) { + o.push(n); + break; + } + return this.pushStack(1 < o.length ? ce.uniqueSort(o) : o); + }, + index: function (e) { + return e + ? "string" == typeof e + ? se.call(ce(e), this[0]) + : se.call(this, e.jquery ? e[0] : e) + : this[0] && this[0].parentNode + ? this.first().prevAll().length + : -1; + }, + add: function (e, t) { + return this.pushStack( + ce.uniqueSort(ce.merge(this.get(), ce(e, t))) + ); + }, + addBack: function (e) { + return this.add( + null == e ? this.prevObject : this.prevObject.filter(e) + ); + }, + }), + ce.each( + { + parent: function (e) { + var t = e.parentNode; + return t && 11 !== t.nodeType ? t : null; + }, + parents: function (e) { + return d(e, "parentNode"); + }, + parentsUntil: function (e, t, n) { + return d(e, "parentNode", n); + }, + next: function (e) { + return A(e, "nextSibling"); + }, + prev: function (e) { + return A(e, "previousSibling"); + }, + nextAll: function (e) { + return d(e, "nextSibling"); + }, + prevAll: function (e) { + return d(e, "previousSibling"); + }, + nextUntil: function (e, t, n) { + return d(e, "nextSibling", n); + }, + prevUntil: function (e, t, n) { + return d(e, "previousSibling", n); + }, + siblings: function (e) { + return h((e.parentNode || {}).firstChild, e); + }, + children: function (e) { + return h(e.firstChild); + }, + contents: function (e) { + return null != e.contentDocument && r(e.contentDocument) + ? e.contentDocument + : (fe(e, "template") && (e = e.content || e), + ce.merge([], e.childNodes)); + }, + }, + function (r, i) { + ce.fn[r] = function (e, t) { + var n = ce.map(this, i, e); + return ( + "Until" !== r.slice(-5) && (t = e), + t && "string" == typeof t && (n = ce.filter(t, n)), + 1 < this.length && + (j[r] || ce.uniqueSort(n), + E.test(r) && n.reverse()), + this.pushStack(n) + ); + }; + } + ); + var D = /[^\x20\t\r\n\f]+/g; + function N(e) { + return e; + } + function q(e) { + throw e; + } + function L(e, t, n, r) { + var i; + try { + e && v((i = e.promise)) + ? i.call(e).done(t).fail(n) + : e && v((i = e.then)) + ? i.call(e, t, n) + : t.apply(void 0, [e].slice(r)); + } catch (e) { + n.apply(void 0, [e]); + } + } + (ce.Callbacks = function (r) { + var e, n; + r = + "string" == typeof r + ? ((e = r), + (n = {}), + ce.each(e.match(D) || [], function (e, t) { + n[t] = !0; + }), + n) + : ce.extend({}, r); + var i, + t, + o, + a, + s = [], + u = [], + l = -1, + c = function () { + for (a = a || r.once, o = i = !0; u.length; l = -1) { + t = u.shift(); + while (++l < s.length) + !1 === s[l].apply(t[0], t[1]) && + r.stopOnFalse && + ((l = s.length), (t = !1)); + } + r.memory || (t = !1), (i = !1), a && (s = t ? [] : ""); + }, + f = { + add: function () { + return ( + s && + (t && !i && ((l = s.length - 1), u.push(t)), + (function n(e) { + ce.each(e, function (e, t) { + v(t) + ? (r.unique && f.has(t)) || s.push(t) + : t && + t.length && + "string" !== x(t) && + n(t); + }); + })(arguments), + t && !i && c()), + this + ); + }, + remove: function () { + return ( + ce.each(arguments, function (e, t) { + var n; + while (-1 < (n = ce.inArray(t, s, n))) + s.splice(n, 1), n <= l && l--; + }), + this + ); + }, + has: function (e) { + return e ? -1 < ce.inArray(e, s) : 0 < s.length; + }, + empty: function () { + return s && (s = []), this; + }, + disable: function () { + return (a = u = []), (s = t = ""), this; + }, + disabled: function () { + return !s; + }, + lock: function () { + return (a = u = []), t || i || (s = t = ""), this; + }, + locked: function () { + return !!a; + }, + fireWith: function (e, t) { + return ( + a || + ((t = [e, (t = t || []).slice ? t.slice() : t]), + u.push(t), + i || c()), + this + ); + }, + fire: function () { + return f.fireWith(this, arguments), this; + }, + fired: function () { + return !!o; + }, + }; + return f; + }), + ce.extend({ + Deferred: function (e) { + var o = [ + [ + "notify", + "progress", + ce.Callbacks("memory"), + ce.Callbacks("memory"), + 2, + ], + [ + "resolve", + "done", + ce.Callbacks("once memory"), + ce.Callbacks("once memory"), + 0, + "resolved", + ], + [ + "reject", + "fail", + ce.Callbacks("once memory"), + ce.Callbacks("once memory"), + 1, + "rejected", + ], + ], + i = "pending", + a = { + state: function () { + return i; + }, + always: function () { + return s.done(arguments).fail(arguments), this; + }, + catch: function (e) { + return a.then(null, e); + }, + pipe: function () { + var i = arguments; + return ce + .Deferred(function (r) { + ce.each(o, function (e, t) { + var n = v(i[t[4]]) && i[t[4]]; + s[t[1]](function () { + var e = + n && n.apply(this, arguments); + e && v(e.promise) + ? e + .promise() + .progress(r.notify) + .done(r.resolve) + .fail(r.reject) + : r[t[0] + "With"]( + this, + n ? [e] : arguments + ); + }); + }), + (i = null); + }) + .promise(); + }, + then: function (t, n, r) { + var u = 0; + function l(i, o, a, s) { + return function () { + var n = this, + r = arguments, + e = function () { + var e, t; + if (!(i < u)) { + if ( + (e = a.apply(n, r)) === + o.promise() + ) + throw new TypeError( + "Thenable self-resolution" + ); + (t = + e && + ("object" == typeof e || + "function" == + typeof e) && + e.then), + v(t) + ? s + ? t.call( + e, + l(u, o, N, s), + l(u, o, q, s) + ) + : (u++, + t.call( + e, + l(u, o, N, s), + l(u, o, q, s), + l( + u, + o, + N, + o.notifyWith + ) + )) + : (a !== N && + ((n = void 0), + (r = [e])), + (s || o.resolveWith)( + n, + r + )); + } + }, + t = s + ? e + : function () { + try { + e(); + } catch (e) { + ce.Deferred + .exceptionHook && + ce.Deferred.exceptionHook( + e, + t.error + ), + u <= i + 1 && + (a !== q && + ((n = void 0), + (r = [e])), + o.rejectWith( + n, + r + )); + } + }; + i + ? t() + : (ce.Deferred.getErrorHook + ? (t.error = + ce.Deferred.getErrorHook()) + : ce.Deferred.getStackHook && + (t.error = + ce.Deferred.getStackHook()), + ie.setTimeout(t)); + }; + } + return ce + .Deferred(function (e) { + o[0][3].add( + l(0, e, v(r) ? r : N, e.notifyWith) + ), + o[1][3].add(l(0, e, v(t) ? t : N)), + o[2][3].add(l(0, e, v(n) ? n : q)); + }) + .promise(); + }, + promise: function (e) { + return null != e ? ce.extend(e, a) : a; + }, + }, + s = {}; + return ( + ce.each(o, function (e, t) { + var n = t[2], + r = t[5]; + (a[t[1]] = n.add), + r && + n.add( + function () { + i = r; + }, + o[3 - e][2].disable, + o[3 - e][3].disable, + o[0][2].lock, + o[0][3].lock + ), + n.add(t[3].fire), + (s[t[0]] = function () { + return ( + s[t[0] + "With"]( + this === s ? void 0 : this, + arguments + ), + this + ); + }), + (s[t[0] + "With"] = n.fireWith); + }), + a.promise(s), + e && e.call(s, s), + s + ); + }, + when: function (e) { + var n = arguments.length, + t = n, + r = Array(t), + i = ae.call(arguments), + o = ce.Deferred(), + a = function (t) { + return function (e) { + (r[t] = this), + (i[t] = + 1 < arguments.length + ? ae.call(arguments) + : e), + --n || o.resolveWith(r, i); + }; + }; + if ( + n <= 1 && + (L(e, o.done(a(t)).resolve, o.reject, !n), + "pending" === o.state() || v(i[t] && i[t].then)) + ) + return o.then(); + while (t--) L(i[t], a(t), o.reject); + return o.promise(); + }, + }); + var H = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + (ce.Deferred.exceptionHook = function (e, t) { + ie.console && + ie.console.warn && + e && + H.test(e.name) && + ie.console.warn( + "jQuery.Deferred exception: " + e.message, + e.stack, + t + ); + }), + (ce.readyException = function (e) { + ie.setTimeout(function () { + throw e; + }); + }); + var O = ce.Deferred(); + function P() { + C.removeEventListener("DOMContentLoaded", P), + ie.removeEventListener("load", P), + ce.ready(); + } + (ce.fn.ready = function (e) { + return ( + O.then(e)["catch"](function (e) { + ce.readyException(e); + }), + this + ); + }), + ce.extend({ + isReady: !1, + readyWait: 1, + ready: function (e) { + (!0 === e ? --ce.readyWait : ce.isReady) || + ((ce.isReady = !0) !== e && 0 < --ce.readyWait) || + O.resolveWith(C, [ce]); + }, + }), + (ce.ready.then = O.then), + "complete" === C.readyState || + ("loading" !== C.readyState && !C.documentElement.doScroll) + ? ie.setTimeout(ce.ready) + : (C.addEventListener("DOMContentLoaded", P), + ie.addEventListener("load", P)); + var R = function (e, t, n, r, i, o, a) { + var s = 0, + u = e.length, + l = null == n; + if ("object" === x(n)) + for (s in ((i = !0), n)) R(e, t, s, n[s], !0, o, a); + else if ( + void 0 !== r && + ((i = !0), + v(r) || (a = !0), + l && + (a + ? (t.call(e, r), (t = null)) + : ((l = t), + (t = function (e, t, n) { + return l.call(ce(e), n); + }))), + t) + ) + for (; s < u; s++) + t(e[s], n, a ? r : r.call(e[s], s, t(e[s], n))); + return i ? e : l ? t.call(e) : u ? t(e[0], n) : o; + }, + M = /^-ms-/, + I = /-([a-z])/g; + function W(e, t) { + return t.toUpperCase(); + } + function F(e) { + return e.replace(M, "ms-").replace(I, W); + } + var $ = function (e) { + return 1 === e.nodeType || 9 === e.nodeType || !+e.nodeType; + }; + function B() { + this.expando = ce.expando + B.uid++; + } + (B.uid = 1), + (B.prototype = { + cache: function (e) { + var t = e[this.expando]; + return ( + t || + ((t = {}), + $(e) && + (e.nodeType + ? (e[this.expando] = t) + : Object.defineProperty(e, this.expando, { + value: t, + configurable: !0, + }))), + t + ); + }, + set: function (e, t, n) { + var r, + i = this.cache(e); + if ("string" == typeof t) i[F(t)] = n; + else for (r in t) i[F(r)] = t[r]; + return i; + }, + get: function (e, t) { + return void 0 === t + ? this.cache(e) + : e[this.expando] && e[this.expando][F(t)]; + }, + access: function (e, t, n) { + return void 0 === t || + (t && "string" == typeof t && void 0 === n) + ? this.get(e, t) + : (this.set(e, t, n), void 0 !== n ? n : t); + }, + remove: function (e, t) { + var n, + r = e[this.expando]; + if (void 0 !== r) { + if (void 0 !== t) { + n = (t = Array.isArray(t) + ? t.map(F) + : (t = F(t)) in r + ? [t] + : t.match(D) || []).length; + while (n--) delete r[t[n]]; + } + (void 0 === t || ce.isEmptyObject(r)) && + (e.nodeType + ? (e[this.expando] = void 0) + : delete e[this.expando]); + } + }, + hasData: function (e) { + var t = e[this.expando]; + return void 0 !== t && !ce.isEmptyObject(t); + }, + }); + var _ = new B(), + X = new B(), + U = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + z = /[A-Z]/g; + function V(e, t, n) { + var r, i; + if (void 0 === n && 1 === e.nodeType) + if ( + ((r = "data-" + t.replace(z, "-$&").toLowerCase()), + "string" == typeof (n = e.getAttribute(r))) + ) { + try { + n = + "true" === (i = n) || + ("false" !== i && + ("null" === i + ? null + : i === +i + "" + ? +i + : U.test(i) + ? JSON.parse(i) + : i)); + } catch (e) {} + X.set(e, t, n); + } else n = void 0; + return n; + } + ce.extend({ + hasData: function (e) { + return X.hasData(e) || _.hasData(e); + }, + data: function (e, t, n) { + return X.access(e, t, n); + }, + removeData: function (e, t) { + X.remove(e, t); + }, + _data: function (e, t, n) { + return _.access(e, t, n); + }, + _removeData: function (e, t) { + _.remove(e, t); + }, + }), + ce.fn.extend({ + data: function (n, e) { + var t, + r, + i, + o = this[0], + a = o && o.attributes; + if (void 0 === n) { + if ( + this.length && + ((i = X.get(o)), + 1 === o.nodeType && !_.get(o, "hasDataAttrs")) + ) { + t = a.length; + while (t--) + a[t] && + 0 === (r = a[t].name).indexOf("data-") && + ((r = F(r.slice(5))), V(o, r, i[r])); + _.set(o, "hasDataAttrs", !0); + } + return i; + } + return "object" == typeof n + ? this.each(function () { + X.set(this, n); + }) + : R( + this, + function (e) { + var t; + if (o && void 0 === e) + return void 0 !== (t = X.get(o, n)) + ? t + : void 0 !== (t = V(o, n)) + ? t + : void 0; + this.each(function () { + X.set(this, n, e); + }); + }, + null, + e, + 1 < arguments.length, + null, + !0 + ); + }, + removeData: function (e) { + return this.each(function () { + X.remove(this, e); + }); + }, + }), + ce.extend({ + queue: function (e, t, n) { + var r; + if (e) + return ( + (t = (t || "fx") + "queue"), + (r = _.get(e, t)), + n && + (!r || Array.isArray(n) + ? (r = _.access(e, t, ce.makeArray(n))) + : r.push(n)), + r || [] + ); + }, + dequeue: function (e, t) { + t = t || "fx"; + var n = ce.queue(e, t), + r = n.length, + i = n.shift(), + o = ce._queueHooks(e, t); + "inprogress" === i && ((i = n.shift()), r--), + i && + ("fx" === t && n.unshift("inprogress"), + delete o.stop, + i.call( + e, + function () { + ce.dequeue(e, t); + }, + o + )), + !r && o && o.empty.fire(); + }, + _queueHooks: function (e, t) { + var n = t + "queueHooks"; + return ( + _.get(e, n) || + _.access(e, n, { + empty: ce.Callbacks("once memory").add(function () { + _.remove(e, [t + "queue", n]); + }), + }) + ); + }, + }), + ce.fn.extend({ + queue: function (t, n) { + var e = 2; + return ( + "string" != typeof t && ((n = t), (t = "fx"), e--), + arguments.length < e + ? ce.queue(this[0], t) + : void 0 === n + ? this + : this.each(function () { + var e = ce.queue(this, t, n); + ce._queueHooks(this, t), + "fx" === t && + "inprogress" !== e[0] && + ce.dequeue(this, t); + }) + ); + }, + dequeue: function (e) { + return this.each(function () { + ce.dequeue(this, e); + }); + }, + clearQueue: function (e) { + return this.queue(e || "fx", []); + }, + promise: function (e, t) { + var n, + r = 1, + i = ce.Deferred(), + o = this, + a = this.length, + s = function () { + --r || i.resolveWith(o, [o]); + }; + "string" != typeof e && ((t = e), (e = void 0)), + (e = e || "fx"); + while (a--) + (n = _.get(o[a], e + "queueHooks")) && + n.empty && + (r++, n.empty.add(s)); + return s(), i.promise(t); + }, + }); + var G = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + Y = new RegExp("^(?:([+-])=|)(" + G + ")([a-z%]*)$", "i"), + Q = ["Top", "Right", "Bottom", "Left"], + J = C.documentElement, + K = function (e) { + return ce.contains(e.ownerDocument, e); + }, + Z = { composed: !0 }; + J.getRootNode && + (K = function (e) { + return ( + ce.contains(e.ownerDocument, e) || + e.getRootNode(Z) === e.ownerDocument + ); + }); + var ee = function (e, t) { + return ( + "none" === (e = t || e).style.display || + ("" === e.style.display && K(e) && "none" === ce.css(e, "display")) + ); + }; + function te(e, t, n, r) { + var i, + o, + a = 20, + s = r + ? function () { + return r.cur(); + } + : function () { + return ce.css(e, t, ""); + }, + u = s(), + l = (n && n[3]) || (ce.cssNumber[t] ? "" : "px"), + c = + e.nodeType && + (ce.cssNumber[t] || ("px" !== l && +u)) && + Y.exec(ce.css(e, t)); + if (c && c[3] !== l) { + (u /= 2), (l = l || c[3]), (c = +u || 1); + while (a--) + ce.style(e, t, c + l), + (1 - o) * (1 - (o = s() / u || 0.5)) <= 0 && (a = 0), + (c /= o); + (c *= 2), ce.style(e, t, c + l), (n = n || []); + } + return ( + n && + ((c = +c || +u || 0), + (i = n[1] ? c + (n[1] + 1) * n[2] : +n[2]), + r && ((r.unit = l), (r.start = c), (r.end = i))), + i + ); + } + var ne = {}; + function re(e, t) { + for (var n, r, i, o, a, s, u, l = [], c = 0, f = e.length; c < f; c++) + (r = e[c]).style && + ((n = r.style.display), + t + ? ("none" === n && + ((l[c] = _.get(r, "display") || null), + l[c] || (r.style.display = "")), + "" === r.style.display && + ee(r) && + (l[c] = + ((u = a = o = void 0), + (a = (i = r).ownerDocument), + (s = i.nodeName), + (u = ne[s]) || + ((o = a.body.appendChild(a.createElement(s))), + (u = ce.css(o, "display")), + o.parentNode.removeChild(o), + "none" === u && (u = "block"), + (ne[s] = u))))) + : "none" !== n && + ((l[c] = "none"), _.set(r, "display", n))); + for (c = 0; c < f; c++) null != l[c] && (e[c].style.display = l[c]); + return e; + } + ce.fn.extend({ + show: function () { + return re(this, !0); + }, + hide: function () { + return re(this); + }, + toggle: function (e) { + return "boolean" == typeof e + ? e + ? this.show() + : this.hide() + : this.each(function () { + ee(this) ? ce(this).show() : ce(this).hide(); + }); + }, + }); + var xe, + be, + we = /^(?:checkbox|radio)$/i, + Te = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i, + Ce = /^$|^module$|\/(?:java|ecma)script/i; + (xe = C.createDocumentFragment().appendChild(C.createElement("div"))), + (be = C.createElement("input")).setAttribute("type", "radio"), + be.setAttribute("checked", "checked"), + be.setAttribute("name", "t"), + xe.appendChild(be), + (le.checkClone = xe.cloneNode(!0).cloneNode(!0).lastChild.checked), + (xe.innerHTML = ""), + (le.noCloneChecked = !!xe.cloneNode(!0).lastChild.defaultValue), + (xe.innerHTML = ""), + (le.option = !!xe.lastChild); + var ke = { + thead: [1, "", "
"], + col: [2, "", "
"], + tr: [2, "", "
"], + td: [3, "", "
"], + _default: [0, "", ""], + }; + function Se(e, t) { + var n; + return ( + (n = + "undefined" != typeof e.getElementsByTagName + ? e.getElementsByTagName(t || "*") + : "undefined" != typeof e.querySelectorAll + ? e.querySelectorAll(t || "*") + : []), + void 0 === t || (t && fe(e, t)) ? ce.merge([e], n) : n + ); + } + function Ee(e, t) { + for (var n = 0, r = e.length; n < r; n++) + _.set(e[n], "globalEval", !t || _.get(t[n], "globalEval")); + } + (ke.tbody = ke.tfoot = ke.colgroup = ke.caption = ke.thead), + (ke.th = ke.td), + le.option || + (ke.optgroup = ke.option = + [1, ""]); + var je = /<|&#?\w+;/; + function Ae(e, t, n, r, i) { + for ( + var o, + a, + s, + u, + l, + c, + f = t.createDocumentFragment(), + p = [], + d = 0, + h = e.length; + d < h; + d++ + ) + if ((o = e[d]) || 0 === o) + if ("object" === x(o)) ce.merge(p, o.nodeType ? [o] : o); + else if (je.test(o)) { + (a = a || f.appendChild(t.createElement("div"))), + (s = (Te.exec(o) || ["", ""])[1].toLowerCase()), + (u = ke[s] || ke._default), + (a.innerHTML = u[1] + ce.htmlPrefilter(o) + u[2]), + (c = u[0]); + while (c--) a = a.lastChild; + ce.merge(p, a.childNodes), + ((a = f.firstChild).textContent = ""); + } else p.push(t.createTextNode(o)); + (f.textContent = ""), (d = 0); + while ((o = p[d++])) + if (r && -1 < ce.inArray(o, r)) i && i.push(o); + else if ( + ((l = K(o)), + (a = Se(f.appendChild(o), "script")), + l && Ee(a), + n) + ) { + c = 0; + while ((o = a[c++])) Ce.test(o.type || "") && n.push(o); + } + return f; + } + var De = /^([^.]*)(?:\.(.+)|)/; + function Ne() { + return !0; + } + function qe() { + return !1; + } + function Le(e, t, n, r, i, o) { + var a, s; + if ("object" == typeof t) { + for (s in ("string" != typeof n && ((r = r || n), (n = void 0)), t)) + Le(e, s, n, r, t[s], o); + return e; + } + if ( + (null == r && null == i + ? ((i = n), (r = n = void 0)) + : null == i && + ("string" == typeof n + ? ((i = r), (r = void 0)) + : ((i = r), (r = n), (n = void 0))), + !1 === i) + ) + i = qe; + else if (!i) return e; + return ( + 1 === o && + ((a = i), + ((i = function (e) { + return ce().off(e), a.apply(this, arguments); + }).guid = a.guid || (a.guid = ce.guid++))), + e.each(function () { + ce.event.add(this, t, i, r, n); + }) + ); + } + function He(e, r, t) { + t + ? (_.set(e, r, !1), + ce.event.add(e, r, { + namespace: !1, + handler: function (e) { + var t, + n = _.get(this, r); + if (1 & e.isTrigger && this[r]) { + if (n) + (ce.event.special[r] || {}).delegateType && + e.stopPropagation(); + else if ( + ((n = ae.call(arguments)), + _.set(this, r, n), + this[r](), + (t = _.get(this, r)), + _.set(this, r, !1), + n !== t) + ) + return ( + e.stopImmediatePropagation(), + e.preventDefault(), + t + ); + } else + n && + (_.set( + this, + r, + ce.event.trigger(n[0], n.slice(1), this) + ), + e.stopPropagation(), + (e.isImmediatePropagationStopped = Ne)); + }, + })) + : void 0 === _.get(e, r) && ce.event.add(e, r, Ne); + } + (ce.event = { + global: {}, + add: function (t, e, n, r, i) { + var o, + a, + s, + u, + l, + c, + f, + p, + d, + h, + g, + v = _.get(t); + if ($(t)) { + n.handler && ((n = (o = n).handler), (i = o.selector)), + i && ce.find.matchesSelector(J, i), + n.guid || (n.guid = ce.guid++), + (u = v.events) || (u = v.events = Object.create(null)), + (a = v.handle) || + (a = v.handle = + function (e) { + return "undefined" != typeof ce && + ce.event.triggered !== e.type + ? ce.event.dispatch.apply(t, arguments) + : void 0; + }), + (l = (e = (e || "").match(D) || [""]).length); + while (l--) + (d = g = (s = De.exec(e[l]) || [])[1]), + (h = (s[2] || "").split(".").sort()), + d && + ((f = ce.event.special[d] || {}), + (d = (i ? f.delegateType : f.bindType) || d), + (f = ce.event.special[d] || {}), + (c = ce.extend( + { + type: d, + origType: g, + data: r, + handler: n, + guid: n.guid, + selector: i, + needsContext: + i && ce.expr.match.needsContext.test(i), + namespace: h.join("."), + }, + o + )), + (p = u[d]) || + (((p = u[d] = []).delegateCount = 0), + (f.setup && !1 !== f.setup.call(t, r, h, a)) || + (t.addEventListener && + t.addEventListener(d, a))), + f.add && + (f.add.call(t, c), + c.handler.guid || (c.handler.guid = n.guid)), + i ? p.splice(p.delegateCount++, 0, c) : p.push(c), + (ce.event.global[d] = !0)); + } + }, + remove: function (e, t, n, r, i) { + var o, + a, + s, + u, + l, + c, + f, + p, + d, + h, + g, + v = _.hasData(e) && _.get(e); + if (v && (u = v.events)) { + l = (t = (t || "").match(D) || [""]).length; + while (l--) + if ( + ((d = g = (s = De.exec(t[l]) || [])[1]), + (h = (s[2] || "").split(".").sort()), + d) + ) { + (f = ce.event.special[d] || {}), + (p = + u[ + (d = (r ? f.delegateType : f.bindType) || d) + ] || []), + (s = + s[2] && + new RegExp( + "(^|\\.)" + + h.join("\\.(?:.*\\.|)") + + "(\\.|$)" + )), + (a = o = p.length); + while (o--) + (c = p[o]), + (!i && g !== c.origType) || + (n && n.guid !== c.guid) || + (s && !s.test(c.namespace)) || + (r && + r !== c.selector && + ("**" !== r || !c.selector)) || + (p.splice(o, 1), + c.selector && p.delegateCount--, + f.remove && f.remove.call(e, c)); + a && + !p.length && + ((f.teardown && + !1 !== f.teardown.call(e, h, v.handle)) || + ce.removeEvent(e, d, v.handle), + delete u[d]); + } else for (d in u) ce.event.remove(e, d + t[l], n, r, !0); + ce.isEmptyObject(u) && _.remove(e, "handle events"); + } + }, + dispatch: function (e) { + var t, + n, + r, + i, + o, + a, + s = new Array(arguments.length), + u = ce.event.fix(e), + l = + (_.get(this, "events") || Object.create(null))[u.type] || + [], + c = ce.event.special[u.type] || {}; + for (s[0] = u, t = 1; t < arguments.length; t++) + s[t] = arguments[t]; + if ( + ((u.delegateTarget = this), + !c.preDispatch || !1 !== c.preDispatch.call(this, u)) + ) { + (a = ce.event.handlers.call(this, u, l)), (t = 0); + while ((i = a[t++]) && !u.isPropagationStopped()) { + (u.currentTarget = i.elem), (n = 0); + while ( + (o = i.handlers[n++]) && + !u.isImmediatePropagationStopped() + ) + (u.rnamespace && + !1 !== o.namespace && + !u.rnamespace.test(o.namespace)) || + ((u.handleObj = o), + (u.data = o.data), + void 0 !== + (r = ( + (ce.event.special[o.origType] || {}) + .handle || o.handler + ).apply(i.elem, s)) && + !1 === (u.result = r) && + (u.preventDefault(), u.stopPropagation())); + } + return c.postDispatch && c.postDispatch.call(this, u), u.result; + } + }, + handlers: function (e, t) { + var n, + r, + i, + o, + a, + s = [], + u = t.delegateCount, + l = e.target; + if (u && l.nodeType && !("click" === e.type && 1 <= e.button)) + for (; l !== this; l = l.parentNode || this) + if ( + 1 === l.nodeType && + ("click" !== e.type || !0 !== l.disabled) + ) { + for (o = [], a = {}, n = 0; n < u; n++) + void 0 === a[(i = (r = t[n]).selector + " ")] && + (a[i] = r.needsContext + ? -1 < ce(i, this).index(l) + : ce.find(i, this, null, [l]).length), + a[i] && o.push(r); + o.length && s.push({ elem: l, handlers: o }); + } + return ( + (l = this), + u < t.length && s.push({ elem: l, handlers: t.slice(u) }), + s + ); + }, + addProp: function (t, e) { + Object.defineProperty(ce.Event.prototype, t, { + enumerable: !0, + configurable: !0, + get: v(e) + ? function () { + if (this.originalEvent) return e(this.originalEvent); + } + : function () { + if (this.originalEvent) return this.originalEvent[t]; + }, + set: function (e) { + Object.defineProperty(this, t, { + enumerable: !0, + configurable: !0, + writable: !0, + value: e, + }); + }, + }); + }, + fix: function (e) { + return e[ce.expando] ? e : new ce.Event(e); + }, + special: { + load: { noBubble: !0 }, + click: { + setup: function (e) { + var t = this || e; + return ( + we.test(t.type) && + t.click && + fe(t, "input") && + He(t, "click", !0), + !1 + ); + }, + trigger: function (e) { + var t = this || e; + return ( + we.test(t.type) && + t.click && + fe(t, "input") && + He(t, "click"), + !0 + ); + }, + _default: function (e) { + var t = e.target; + return ( + (we.test(t.type) && + t.click && + fe(t, "input") && + _.get(t, "click")) || + fe(t, "a") + ); + }, + }, + beforeunload: { + postDispatch: function (e) { + void 0 !== e.result && + e.originalEvent && + (e.originalEvent.returnValue = e.result); + }, + }, + }, + }), + (ce.removeEvent = function (e, t, n) { + e.removeEventListener && e.removeEventListener(t, n); + }), + (ce.Event = function (e, t) { + if (!(this instanceof ce.Event)) return new ce.Event(e, t); + e && e.type + ? ((this.originalEvent = e), + (this.type = e.type), + (this.isDefaultPrevented = + e.defaultPrevented || + (void 0 === e.defaultPrevented && !1 === e.returnValue) + ? Ne + : qe), + (this.target = + e.target && 3 === e.target.nodeType + ? e.target.parentNode + : e.target), + (this.currentTarget = e.currentTarget), + (this.relatedTarget = e.relatedTarget)) + : (this.type = e), + t && ce.extend(this, t), + (this.timeStamp = (e && e.timeStamp) || Date.now()), + (this[ce.expando] = !0); + }), + (ce.Event.prototype = { + constructor: ce.Event, + isDefaultPrevented: qe, + isPropagationStopped: qe, + isImmediatePropagationStopped: qe, + isSimulated: !1, + preventDefault: function () { + var e = this.originalEvent; + (this.isDefaultPrevented = Ne), + e && !this.isSimulated && e.preventDefault(); + }, + stopPropagation: function () { + var e = this.originalEvent; + (this.isPropagationStopped = Ne), + e && !this.isSimulated && e.stopPropagation(); + }, + stopImmediatePropagation: function () { + var e = this.originalEvent; + (this.isImmediatePropagationStopped = Ne), + e && !this.isSimulated && e.stopImmediatePropagation(), + this.stopPropagation(); + }, + }), + ce.each( + { + altKey: !0, + bubbles: !0, + cancelable: !0, + changedTouches: !0, + ctrlKey: !0, + detail: !0, + eventPhase: !0, + metaKey: !0, + pageX: !0, + pageY: !0, + shiftKey: !0, + view: !0, + char: !0, + code: !0, + charCode: !0, + key: !0, + keyCode: !0, + button: !0, + buttons: !0, + clientX: !0, + clientY: !0, + offsetX: !0, + offsetY: !0, + pointerId: !0, + pointerType: !0, + screenX: !0, + screenY: !0, + targetTouches: !0, + toElement: !0, + touches: !0, + which: !0, + }, + ce.event.addProp + ), + ce.each({ focus: "focusin", blur: "focusout" }, function (r, i) { + function o(e) { + if (C.documentMode) { + var t = _.get(this, "handle"), + n = ce.event.fix(e); + (n.type = "focusin" === e.type ? "focus" : "blur"), + (n.isSimulated = !0), + t(e), + n.target === n.currentTarget && t(n); + } else ce.event.simulate(i, e.target, ce.event.fix(e)); + } + (ce.event.special[r] = { + setup: function () { + var e; + if ((He(this, r, !0), !C.documentMode)) return !1; + (e = _.get(this, i)) || this.addEventListener(i, o), + _.set(this, i, (e || 0) + 1); + }, + trigger: function () { + return He(this, r), !0; + }, + teardown: function () { + var e; + if (!C.documentMode) return !1; + (e = _.get(this, i) - 1) + ? _.set(this, i, e) + : (this.removeEventListener(i, o), _.remove(this, i)); + }, + _default: function (e) { + return _.get(e.target, r); + }, + delegateType: i, + }), + (ce.event.special[i] = { + setup: function () { + var e = this.ownerDocument || this.document || this, + t = C.documentMode ? this : e, + n = _.get(t, i); + n || + (C.documentMode + ? this.addEventListener(i, o) + : e.addEventListener(r, o, !0)), + _.set(t, i, (n || 0) + 1); + }, + teardown: function () { + var e = this.ownerDocument || this.document || this, + t = C.documentMode ? this : e, + n = _.get(t, i) - 1; + n + ? _.set(t, i, n) + : (C.documentMode + ? this.removeEventListener(i, o) + : e.removeEventListener(r, o, !0), + _.remove(t, i)); + }, + }); + }), + ce.each( + { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout", + }, + function (e, i) { + ce.event.special[e] = { + delegateType: i, + bindType: i, + handle: function (e) { + var t, + n = e.relatedTarget, + r = e.handleObj; + return ( + (n && (n === this || ce.contains(this, n))) || + ((e.type = r.origType), + (t = r.handler.apply(this, arguments)), + (e.type = i)), + t + ); + }, + }; + } + ), + ce.fn.extend({ + on: function (e, t, n, r) { + return Le(this, e, t, n, r); + }, + one: function (e, t, n, r) { + return Le(this, e, t, n, r, 1); + }, + off: function (e, t, n) { + var r, i; + if (e && e.preventDefault && e.handleObj) + return ( + (r = e.handleObj), + ce(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 ( + (!1 !== t && "function" != typeof t) || + ((n = t), (t = void 0)), + !1 === n && (n = qe), + this.each(function () { + ce.event.remove(this, e, n, t); + }) + ); + }, + }); + var Oe = /\s*$/g; + function Me(e, t) { + return ( + (fe(e, "table") && + fe(11 !== t.nodeType ? t : t.firstChild, "tr") && + ce(e).children("tbody")[0]) || + e + ); + } + function Ie(e) { + return (e.type = (null !== e.getAttribute("type")) + "/" + e.type), e; + } + function We(e) { + return ( + "true/" === (e.type || "").slice(0, 5) + ? (e.type = e.type.slice(5)) + : e.removeAttribute("type"), + e + ); + } + function Fe(e, t) { + var n, r, i, o, a, s; + if (1 === t.nodeType) { + if (_.hasData(e) && (s = _.get(e).events)) + for (i in (_.remove(t, "handle events"), s)) + for (n = 0, r = s[i].length; n < r; n++) + ce.event.add(t, i, s[i][n]); + X.hasData(e) && + ((o = X.access(e)), (a = ce.extend({}, o)), X.set(t, a)); + } + } + function $e(n, r, i, o) { + r = g(r); + var e, + t, + a, + s, + u, + l, + c = 0, + f = n.length, + p = f - 1, + d = r[0], + h = v(d); + if ( + h || + (1 < f && "string" == typeof d && !le.checkClone && Pe.test(d)) + ) + return n.each(function (e) { + var t = n.eq(e); + h && (r[0] = d.call(this, e, t.html())), $e(t, r, i, o); + }); + if ( + f && + ((t = (e = Ae(r, n[0].ownerDocument, !1, n, o)).firstChild), + 1 === e.childNodes.length && (e = t), + t || o) + ) { + for (s = (a = ce.map(Se(e, "script"), Ie)).length; c < f; c++) + (u = e), + c !== p && + ((u = ce.clone(u, !0, !0)), + s && ce.merge(a, Se(u, "script"))), + i.call(n[c], u, c); + if (s) + for ( + l = a[a.length - 1].ownerDocument, ce.map(a, We), c = 0; + c < s; + c++ + ) + (u = a[c]), + Ce.test(u.type || "") && + !_.access(u, "globalEval") && + ce.contains(l, u) && + (u.src && "module" !== (u.type || "").toLowerCase() + ? ce._evalUrl && + !u.noModule && + ce._evalUrl( + u.src, + { + nonce: + u.nonce || + u.getAttribute("nonce"), + }, + l + ) + : m(u.textContent.replace(Re, ""), u, l)); + } + return n; + } + function Be(e, t, n) { + for (var r, i = t ? ce.filter(t, e) : e, o = 0; null != (r = i[o]); o++) + n || 1 !== r.nodeType || ce.cleanData(Se(r)), + r.parentNode && + (n && K(r) && Ee(Se(r, "script")), + r.parentNode.removeChild(r)); + return e; + } + ce.extend({ + htmlPrefilter: function (e) { + return e; + }, + clone: function (e, t, n) { + var r, + i, + o, + a, + s, + u, + l, + c = e.cloneNode(!0), + f = K(e); + if ( + !( + le.noCloneChecked || + (1 !== e.nodeType && 11 !== e.nodeType) || + ce.isXMLDoc(e) + ) + ) + for (a = Se(c), r = 0, i = (o = Se(e)).length; r < i; r++) + (s = o[r]), + (u = a[r]), + void 0, + "input" === (l = u.nodeName.toLowerCase()) && + we.test(s.type) + ? (u.checked = s.checked) + : ("input" !== l && "textarea" !== l) || + (u.defaultValue = s.defaultValue); + if (t) + if (n) + for ( + o = o || Se(e), a = a || Se(c), r = 0, i = o.length; + r < i; + r++ + ) + Fe(o[r], a[r]); + else Fe(e, c); + return ( + 0 < (a = Se(c, "script")).length && + Ee(a, !f && Se(e, "script")), + c + ); + }, + cleanData: function (e) { + for ( + var t, n, r, i = ce.event.special, o = 0; + void 0 !== (n = e[o]); + o++ + ) + if ($(n)) { + if ((t = n[_.expando])) { + if (t.events) + for (r in t.events) + i[r] + ? ce.event.remove(n, r) + : ce.removeEvent(n, r, t.handle); + n[_.expando] = void 0; + } + n[X.expando] && (n[X.expando] = void 0); + } + }, + }), + ce.fn.extend({ + detach: function (e) { + return Be(this, e, !0); + }, + remove: function (e) { + return Be(this, e); + }, + text: function (e) { + return R( + this, + function (e) { + return void 0 === e + ? ce.text(this) + : this.empty().each(function () { + (1 !== this.nodeType && + 11 !== this.nodeType && + 9 !== this.nodeType) || + (this.textContent = e); + }); + }, + null, + e, + arguments.length + ); + }, + append: function () { + return $e(this, arguments, function (e) { + (1 !== this.nodeType && + 11 !== this.nodeType && + 9 !== this.nodeType) || + Me(this, e).appendChild(e); + }); + }, + prepend: function () { + return $e(this, arguments, function (e) { + if ( + 1 === this.nodeType || + 11 === this.nodeType || + 9 === this.nodeType + ) { + var t = Me(this, e); + t.insertBefore(e, t.firstChild); + } + }); + }, + before: function () { + return $e(this, arguments, function (e) { + this.parentNode && this.parentNode.insertBefore(e, this); + }); + }, + after: function () { + return $e(this, arguments, function (e) { + this.parentNode && + this.parentNode.insertBefore(e, this.nextSibling); + }); + }, + empty: function () { + for (var e, t = 0; null != (e = this[t]); t++) + 1 === e.nodeType && + (ce.cleanData(Se(e, !1)), (e.textContent = "")); + return this; + }, + clone: function (e, t) { + return ( + (e = null != e && e), + (t = null == t ? e : t), + this.map(function () { + return ce.clone(this, e, t); + }) + ); + }, + html: function (e) { + return R( + this, + function (e) { + var t = this[0] || {}, + n = 0, + r = this.length; + if (void 0 === e && 1 === t.nodeType) + return t.innerHTML; + if ( + "string" == typeof e && + !Oe.test(e) && + !ke[(Te.exec(e) || ["", ""])[1].toLowerCase()] + ) { + e = ce.htmlPrefilter(e); + try { + for (; n < r; n++) + 1 === (t = this[n] || {}).nodeType && + (ce.cleanData(Se(t, !1)), + (t.innerHTML = e)); + t = 0; + } catch (e) {} + } + t && this.empty().append(e); + }, + null, + e, + arguments.length + ); + }, + replaceWith: function () { + var n = []; + return $e( + this, + arguments, + function (e) { + var t = this.parentNode; + ce.inArray(this, n) < 0 && + (ce.cleanData(Se(this)), + t && t.replaceChild(e, this)); + }, + n + ); + }, + }), + ce.each( + { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith", + }, + function (e, a) { + ce.fn[e] = function (e) { + for ( + var t, n = [], r = ce(e), i = r.length - 1, o = 0; + o <= i; + o++ + ) + (t = o === i ? this : this.clone(!0)), + ce(r[o])[a](t), + s.apply(n, t.get()); + return this.pushStack(n); + }; + } + ); + var _e = new RegExp("^(" + G + ")(?!px)[a-z%]+$", "i"), + Xe = /^--/, + Ue = function (e) { + var t = e.ownerDocument.defaultView; + return (t && t.opener) || (t = ie), t.getComputedStyle(e); + }, + ze = function (e, t, n) { + var r, + i, + o = {}; + for (i in t) (o[i] = e.style[i]), (e.style[i] = t[i]); + for (i in ((r = n.call(e)), t)) e.style[i] = o[i]; + return r; + }, + Ve = new RegExp(Q.join("|"), "i"); + function Ge(e, t, n) { + var r, + i, + o, + a, + s = Xe.test(t), + u = e.style; + return ( + (n = n || Ue(e)) && + ((a = n.getPropertyValue(t) || n[t]), + s && a && (a = a.replace(ve, "$1") || void 0), + "" !== a || K(e) || (a = ce.style(e, t)), + !le.pixelBoxStyles() && + _e.test(a) && + Ve.test(t) && + ((r = u.width), + (i = u.minWidth), + (o = u.maxWidth), + (u.minWidth = u.maxWidth = u.width = a), + (a = n.width), + (u.width = r), + (u.minWidth = i), + (u.maxWidth = o))), + void 0 !== a ? a + "" : a + ); + } + function Ye(e, t) { + return { + get: function () { + if (!e()) return (this.get = t).apply(this, arguments); + delete this.get; + }, + }; + } + !(function () { + function e() { + if (l) { + (u.style.cssText = + "position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0"), + (l.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%"), + J.appendChild(u).appendChild(l); + var e = ie.getComputedStyle(l); + (n = "1%" !== e.top), + (s = 12 === t(e.marginLeft)), + (l.style.right = "60%"), + (o = 36 === t(e.right)), + (r = 36 === t(e.width)), + (l.style.position = "absolute"), + (i = 12 === t(l.offsetWidth / 3)), + J.removeChild(u), + (l = null); + } + } + function t(e) { + return Math.round(parseFloat(e)); + } + var n, + r, + i, + o, + a, + s, + u = C.createElement("div"), + l = C.createElement("div"); + l.style && + ((l.style.backgroundClip = "content-box"), + (l.cloneNode(!0).style.backgroundClip = ""), + (le.clearCloneStyle = "content-box" === l.style.backgroundClip), + ce.extend(le, { + boxSizingReliable: function () { + return e(), r; + }, + pixelBoxStyles: function () { + return e(), o; + }, + pixelPosition: function () { + return e(), n; + }, + reliableMarginLeft: function () { + return e(), s; + }, + scrollboxSize: function () { + return e(), i; + }, + reliableTrDimensions: function () { + var e, t, n, r; + return ( + null == a && + ((e = C.createElement("table")), + (t = C.createElement("tr")), + (n = C.createElement("div")), + (e.style.cssText = + "position:absolute;left:-11111px;border-collapse:separate"), + (t.style.cssText = "border:1px solid"), + (t.style.height = "1px"), + (n.style.height = "9px"), + (n.style.display = "block"), + J.appendChild(e).appendChild(t).appendChild(n), + (r = ie.getComputedStyle(t)), + (a = + parseInt(r.height, 10) + + parseInt(r.borderTopWidth, 10) + + parseInt(r.borderBottomWidth, 10) === + t.offsetHeight), + J.removeChild(e)), + a + ); + }, + })); + })(); + var Qe = ["Webkit", "Moz", "ms"], + Je = C.createElement("div").style, + Ke = {}; + function Ze(e) { + var t = ce.cssProps[e] || Ke[e]; + return ( + t || + (e in Je + ? e + : (Ke[e] = + (function (e) { + var t = e[0].toUpperCase() + e.slice(1), + n = Qe.length; + while (n--) if ((e = Qe[n] + t) in Je) return e; + })(e) || e)) + ); + } + var et = /^(none|table(?!-c[ea]).+)/, + tt = { position: "absolute", visibility: "hidden", display: "block" }, + nt = { letterSpacing: "0", fontWeight: "400" }; + function rt(e, t, n) { + var r = Y.exec(t); + return r ? Math.max(0, r[2] - (n || 0)) + (r[3] || "px") : t; + } + function it(e, t, n, r, i, o) { + var a = "width" === t ? 1 : 0, + s = 0, + u = 0, + l = 0; + if (n === (r ? "border" : "content")) return 0; + for (; a < 4; a += 2) + "margin" === n && (l += ce.css(e, n + Q[a], !0, i)), + r + ? ("content" === n && + (u -= ce.css(e, "padding" + Q[a], !0, i)), + "margin" !== n && + (u -= ce.css(e, "border" + Q[a] + "Width", !0, i))) + : ((u += ce.css(e, "padding" + Q[a], !0, i)), + "padding" !== n + ? (u += ce.css(e, "border" + Q[a] + "Width", !0, i)) + : (s += ce.css(e, "border" + Q[a] + "Width", !0, i))); + return ( + !r && + 0 <= o && + (u += + Math.max( + 0, + Math.ceil( + e["offset" + t[0].toUpperCase() + t.slice(1)] - + o - + u - + s - + 0.5 + ) + ) || 0), + u + l + ); + } + function ot(e, t, n) { + var r = Ue(e), + i = + (!le.boxSizingReliable() || n) && + "border-box" === ce.css(e, "boxSizing", !1, r), + o = i, + a = Ge(e, t, r), + s = "offset" + t[0].toUpperCase() + t.slice(1); + if (_e.test(a)) { + if (!n) return a; + a = "auto"; + } + return ( + ((!le.boxSizingReliable() && i) || + (!le.reliableTrDimensions() && fe(e, "tr")) || + "auto" === a || + (!parseFloat(a) && "inline" === ce.css(e, "display", !1, r))) && + e.getClientRects().length && + ((i = "border-box" === ce.css(e, "boxSizing", !1, r)), + (o = s in e) && (a = e[s])), + (a = parseFloat(a) || 0) + + it(e, t, n || (i ? "border" : "content"), o, r, a) + + "px" + ); + } + function at(e, t, n, r, i) { + return new at.prototype.init(e, t, n, r, i); + } + ce.extend({ + cssHooks: { + opacity: { + get: function (e, t) { + if (t) { + var n = Ge(e, "opacity"); + return "" === n ? "1" : n; + } + }, + }, + }, + cssNumber: { + animationIterationCount: !0, + aspectRatio: !0, + borderImageSlice: !0, + columnCount: !0, + flexGrow: !0, + flexShrink: !0, + fontWeight: !0, + gridArea: !0, + gridColumn: !0, + gridColumnEnd: !0, + gridColumnStart: !0, + gridRow: !0, + gridRowEnd: !0, + gridRowStart: !0, + lineHeight: !0, + opacity: !0, + order: !0, + orphans: !0, + scale: !0, + widows: !0, + zIndex: !0, + zoom: !0, + fillOpacity: !0, + floodOpacity: !0, + stopOpacity: !0, + strokeMiterlimit: !0, + strokeOpacity: !0, + }, + cssProps: {}, + style: function (e, t, n, r) { + if (e && 3 !== e.nodeType && 8 !== e.nodeType && e.style) { + var i, + o, + a, + s = F(t), + u = Xe.test(t), + l = e.style; + if ( + (u || (t = Ze(s)), + (a = ce.cssHooks[t] || ce.cssHooks[s]), + void 0 === n) + ) + return a && "get" in a && void 0 !== (i = a.get(e, !1, r)) + ? i + : l[t]; + "string" === (o = typeof n) && + (i = Y.exec(n)) && + i[1] && + ((n = te(e, t, i)), (o = "number")), + null != n && + n == n && + ("number" !== o || + u || + (n += (i && i[3]) || (ce.cssNumber[s] ? "" : "px")), + le.clearCloneStyle || + "" !== n || + 0 !== t.indexOf("background") || + (l[t] = "inherit"), + (a && "set" in a && void 0 === (n = a.set(e, n, r))) || + (u ? l.setProperty(t, n) : (l[t] = n))); + } + }, + css: function (e, t, n, r) { + var i, + o, + a, + s = F(t); + return ( + Xe.test(t) || (t = Ze(s)), + (a = ce.cssHooks[t] || ce.cssHooks[s]) && + "get" in a && + (i = a.get(e, !0, n)), + void 0 === i && (i = Ge(e, t, r)), + "normal" === i && t in nt && (i = nt[t]), + "" === n || n + ? ((o = parseFloat(i)), + !0 === n || isFinite(o) ? o || 0 : i) + : i + ); + }, + }), + ce.each(["height", "width"], function (e, u) { + ce.cssHooks[u] = { + get: function (e, t, n) { + if (t) + return !et.test(ce.css(e, "display")) || + (e.getClientRects().length && + e.getBoundingClientRect().width) + ? ot(e, u, n) + : ze(e, tt, function () { + return ot(e, u, n); + }); + }, + set: function (e, t, n) { + var r, + i = Ue(e), + o = !le.scrollboxSize() && "absolute" === i.position, + a = + (o || n) && + "border-box" === ce.css(e, "boxSizing", !1, i), + s = n ? it(e, u, n, a, i) : 0; + return ( + a && + o && + (s -= Math.ceil( + e["offset" + u[0].toUpperCase() + u.slice(1)] - + parseFloat(i[u]) - + it(e, u, "border", !1, i) - + 0.5 + )), + s && + (r = Y.exec(t)) && + "px" !== (r[3] || "px") && + ((e.style[u] = t), (t = ce.css(e, u))), + rt(0, t, s) + ); + }, + }; + }), + (ce.cssHooks.marginLeft = Ye(le.reliableMarginLeft, function (e, t) { + if (t) + return ( + (parseFloat(Ge(e, "marginLeft")) || + e.getBoundingClientRect().left - + ze(e, { marginLeft: 0 }, function () { + return e.getBoundingClientRect().left; + })) + "px" + ); + })), + ce.each({ margin: "", padding: "", border: "Width" }, function (i, o) { + (ce.cssHooks[i + o] = { + expand: function (e) { + for ( + var t = 0, + n = {}, + r = "string" == typeof e ? e.split(" ") : [e]; + t < 4; + t++ + ) + n[i + Q[t] + o] = r[t] || r[t - 2] || r[0]; + return n; + }, + }), + "margin" !== i && (ce.cssHooks[i + o].set = rt); + }), + ce.fn.extend({ + css: function (e, t) { + return R( + this, + function (e, t, n) { + var r, + i, + o = {}, + a = 0; + if (Array.isArray(t)) { + for (r = Ue(e), i = t.length; a < i; a++) + o[t[a]] = ce.css(e, t[a], !1, r); + return o; + } + return void 0 !== n ? ce.style(e, t, n) : ce.css(e, t); + }, + e, + t, + 1 < arguments.length + ); + }, + }), + (((ce.Tween = at).prototype = { + constructor: at, + init: function (e, t, n, r, i, o) { + (this.elem = e), + (this.prop = n), + (this.easing = i || ce.easing._default), + (this.options = t), + (this.start = this.now = this.cur()), + (this.end = r), + (this.unit = o || (ce.cssNumber[n] ? "" : "px")); + }, + cur: function () { + var e = at.propHooks[this.prop]; + return e && e.get + ? e.get(this) + : at.propHooks._default.get(this); + }, + run: function (e) { + var t, + n = at.propHooks[this.prop]; + return ( + this.options.duration + ? (this.pos = t = + ce.easing[this.easing]( + e, + this.options.duration * e, + 0, + 1, + this.options.duration + )) + : (this.pos = t = e), + (this.now = (this.end - this.start) * t + this.start), + this.options.step && + this.options.step.call(this.elem, this.now, this), + n && n.set ? n.set(this) : at.propHooks._default.set(this), + this + ); + }, + }).init.prototype = at.prototype), + ((at.propHooks = { + _default: { + get: function (e) { + var t; + return 1 !== e.elem.nodeType || + (null != e.elem[e.prop] && null == e.elem.style[e.prop]) + ? e.elem[e.prop] + : (t = ce.css(e.elem, e.prop, "")) && "auto" !== t + ? t + : 0; + }, + set: function (e) { + ce.fx.step[e.prop] + ? ce.fx.step[e.prop](e) + : 1 !== e.elem.nodeType || + (!ce.cssHooks[e.prop] && + null == e.elem.style[Ze(e.prop)]) + ? (e.elem[e.prop] = e.now) + : ce.style(e.elem, e.prop, e.now + e.unit); + }, + }, + }).scrollTop = at.propHooks.scrollLeft = + { + set: function (e) { + e.elem.nodeType && + e.elem.parentNode && + (e.elem[e.prop] = e.now); + }, + }), + (ce.easing = { + linear: function (e) { + return e; + }, + swing: function (e) { + return 0.5 - Math.cos(e * Math.PI) / 2; + }, + _default: "swing", + }), + (ce.fx = at.prototype.init), + (ce.fx.step = {}); + var st, + ut, + lt, + ct, + ft = /^(?:toggle|show|hide)$/, + pt = /queueHooks$/; + function dt() { + ut && + (!1 === C.hidden && ie.requestAnimationFrame + ? ie.requestAnimationFrame(dt) + : ie.setTimeout(dt, ce.fx.interval), + ce.fx.tick()); + } + function ht() { + return ( + ie.setTimeout(function () { + st = void 0; + }), + (st = Date.now()) + ); + } + function gt(e, t) { + var n, + r = 0, + i = { height: e }; + for (t = t ? 1 : 0; r < 4; r += 2 - t) + i["margin" + (n = Q[r])] = i["padding" + n] = e; + return t && (i.opacity = i.width = e), i; + } + function vt(e, t, n) { + for ( + var r, + i = (yt.tweeners[t] || []).concat(yt.tweeners["*"]), + o = 0, + a = i.length; + o < a; + o++ + ) + if ((r = i[o].call(n, t, e))) return r; + } + function yt(o, e, t) { + var n, + a, + r = 0, + i = yt.prefilters.length, + s = ce.Deferred().always(function () { + delete u.elem; + }), + u = function () { + if (a) return !1; + for ( + var e = st || ht(), + t = Math.max(0, l.startTime + l.duration - e), + n = 1 - (t / l.duration || 0), + r = 0, + i = l.tweens.length; + r < i; + r++ + ) + l.tweens[r].run(n); + return ( + s.notifyWith(o, [l, n, t]), + n < 1 && i + ? t + : (i || s.notifyWith(o, [l, 1, 0]), + s.resolveWith(o, [l]), + !1) + ); + }, + l = s.promise({ + elem: o, + props: ce.extend({}, e), + opts: ce.extend( + !0, + { specialEasing: {}, easing: ce.easing._default }, + t + ), + originalProperties: e, + originalOptions: t, + startTime: st || ht(), + duration: t.duration, + tweens: [], + createTween: function (e, t) { + var n = ce.Tween( + o, + l.opts, + e, + t, + l.opts.specialEasing[e] || l.opts.easing + ); + return l.tweens.push(n), n; + }, + stop: function (e) { + var t = 0, + n = e ? l.tweens.length : 0; + if (a) return this; + for (a = !0; t < n; t++) l.tweens[t].run(1); + return ( + e + ? (s.notifyWith(o, [l, 1, 0]), + s.resolveWith(o, [l, e])) + : s.rejectWith(o, [l, e]), + this + ); + }, + }), + c = l.props; + for ( + !(function (e, t) { + var n, r, i, o, a; + for (n in e) + if ( + ((i = t[(r = F(n))]), + (o = e[n]), + Array.isArray(o) && ((i = o[1]), (o = e[n] = o[0])), + n !== r && ((e[r] = o), delete e[n]), + (a = ce.cssHooks[r]) && ("expand" in a)) + ) + for (n in ((o = a.expand(o)), delete e[r], o)) + (n in e) || ((e[n] = o[n]), (t[n] = i)); + else t[r] = i; + })(c, l.opts.specialEasing); + r < i; + r++ + ) + if ((n = yt.prefilters[r].call(l, o, c, l.opts))) + return ( + v(n.stop) && + (ce._queueHooks(l.elem, l.opts.queue).stop = + n.stop.bind(n)), + n + ); + return ( + ce.map(c, vt, l), + v(l.opts.start) && l.opts.start.call(o, l), + l + .progress(l.opts.progress) + .done(l.opts.done, l.opts.complete) + .fail(l.opts.fail) + .always(l.opts.always), + ce.fx.timer( + ce.extend(u, { elem: o, anim: l, queue: l.opts.queue }) + ), + l + ); + } + (ce.Animation = ce.extend(yt, { + tweeners: { + "*": [ + function (e, t) { + var n = this.createTween(e, t); + return te(n.elem, e, Y.exec(t), n), n; + }, + ], + }, + tweener: function (e, t) { + v(e) ? ((t = e), (e = ["*"])) : (e = e.match(D)); + for (var n, r = 0, i = e.length; r < i; r++) + (n = e[r]), + (yt.tweeners[n] = yt.tweeners[n] || []), + yt.tweeners[n].unshift(t); + }, + prefilters: [ + function (e, t, n) { + var r, + i, + o, + a, + s, + u, + l, + c, + f = "width" in t || "height" in t, + p = this, + d = {}, + h = e.style, + g = e.nodeType && ee(e), + v = _.get(e, "fxshow"); + for (r in (n.queue || + (null == (a = ce._queueHooks(e, "fx")).unqueued && + ((a.unqueued = 0), + (s = a.empty.fire), + (a.empty.fire = function () { + a.unqueued || s(); + })), + a.unqueued++, + p.always(function () { + p.always(function () { + a.unqueued--, + ce.queue(e, "fx").length || a.empty.fire(); + }); + })), + t)) + if (((i = t[r]), ft.test(i))) { + if ( + (delete t[r], + (o = o || "toggle" === i), + i === (g ? "hide" : "show")) + ) { + if ("show" !== i || !v || void 0 === v[r]) continue; + g = !0; + } + d[r] = (v && v[r]) || ce.style(e, r); + } + if ((u = !ce.isEmptyObject(t)) || !ce.isEmptyObject(d)) + for (r in (f && + 1 === e.nodeType && + ((n.overflow = [h.overflow, h.overflowX, h.overflowY]), + null == (l = v && v.display) && + (l = _.get(e, "display")), + "none" === (c = ce.css(e, "display")) && + (l + ? (c = l) + : (re([e], !0), + (l = e.style.display || l), + (c = ce.css(e, "display")), + re([e]))), + ("inline" === c || + ("inline-block" === c && null != l)) && + "none" === ce.css(e, "float") && + (u || + (p.done(function () { + h.display = l; + }), + null == l && + ((c = h.display), + (l = "none" === c ? "" : c))), + (h.display = "inline-block"))), + n.overflow && + ((h.overflow = "hidden"), + p.always(function () { + (h.overflow = n.overflow[0]), + (h.overflowX = n.overflow[1]), + (h.overflowY = n.overflow[2]); + })), + (u = !1), + d)) + u || + (v + ? "hidden" in v && (g = v.hidden) + : (v = _.access(e, "fxshow", { display: l })), + o && (v.hidden = !g), + g && re([e], !0), + p.done(function () { + for (r in (g || re([e]), + _.remove(e, "fxshow"), + d)) + ce.style(e, r, d[r]); + })), + (u = vt(g ? v[r] : 0, r, p)), + r in v || + ((v[r] = u.start), + g && ((u.end = u.start), (u.start = 0))); + }, + ], + prefilter: function (e, t) { + t ? yt.prefilters.unshift(e) : yt.prefilters.push(e); + }, + })), + (ce.speed = function (e, t, n) { + var r = + e && "object" == typeof e + ? ce.extend({}, e) + : { + complete: n || (!n && t) || (v(e) && e), + duration: e, + easing: (n && t) || (t && !v(t) && t), + }; + return ( + ce.fx.off + ? (r.duration = 0) + : "number" != typeof r.duration && + (r.duration in ce.fx.speeds + ? (r.duration = ce.fx.speeds[r.duration]) + : (r.duration = ce.fx.speeds._default)), + (null != r.queue && !0 !== r.queue) || (r.queue = "fx"), + (r.old = r.complete), + (r.complete = function () { + v(r.old) && r.old.call(this), + r.queue && ce.dequeue(this, r.queue); + }), + r + ); + }), + ce.fn.extend({ + fadeTo: function (e, t, n, r) { + return this.filter(ee) + .css("opacity", 0) + .show() + .end() + .animate({ opacity: t }, e, n, r); + }, + animate: function (t, e, n, r) { + var i = ce.isEmptyObject(t), + o = ce.speed(e, n, r), + a = function () { + var e = yt(this, ce.extend({}, t), o); + (i || _.get(this, "finish")) && e.stop(!0); + }; + return ( + (a.finish = a), + i || !1 === o.queue ? this.each(a) : this.queue(o.queue, a) + ); + }, + stop: function (i, e, o) { + var a = function (e) { + var t = e.stop; + delete e.stop, t(o); + }; + return ( + "string" != typeof i && ((o = e), (e = i), (i = void 0)), + e && this.queue(i || "fx", []), + this.each(function () { + var e = !0, + t = null != i && i + "queueHooks", + n = ce.timers, + r = _.get(this); + if (t) r[t] && r[t].stop && a(r[t]); + else + for (t in r) + r[t] && r[t].stop && pt.test(t) && a(r[t]); + for (t = n.length; t--; ) + n[t].elem !== this || + (null != i && n[t].queue !== i) || + (n[t].anim.stop(o), (e = !1), n.splice(t, 1)); + (!e && o) || ce.dequeue(this, i); + }) + ); + }, + finish: function (a) { + return ( + !1 !== a && (a = a || "fx"), + this.each(function () { + var e, + t = _.get(this), + n = t[a + "queue"], + r = t[a + "queueHooks"], + i = ce.timers, + o = n ? n.length : 0; + for ( + t.finish = !0, + ce.queue(this, a, []), + r && r.stop && r.stop.call(this, !0), + e = i.length; + e--; + + ) + i[e].elem === this && + i[e].queue === a && + (i[e].anim.stop(!0), i.splice(e, 1)); + for (e = 0; e < o; e++) + n[e] && n[e].finish && n[e].finish.call(this); + delete t.finish; + }) + ); + }, + }), + ce.each(["toggle", "show", "hide"], function (e, r) { + var i = ce.fn[r]; + ce.fn[r] = function (e, t, n) { + return null == e || "boolean" == typeof e + ? i.apply(this, arguments) + : this.animate(gt(r, !0), e, t, n); + }; + }), + ce.each( + { + slideDown: gt("show"), + slideUp: gt("hide"), + slideToggle: gt("toggle"), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" }, + }, + function (e, r) { + ce.fn[e] = function (e, t, n) { + return this.animate(r, e, t, n); + }; + } + ), + (ce.timers = []), + (ce.fx.tick = function () { + var e, + t = 0, + n = ce.timers; + for (st = Date.now(); t < n.length; t++) + (e = n[t])() || n[t] !== e || n.splice(t--, 1); + n.length || ce.fx.stop(), (st = void 0); + }), + (ce.fx.timer = function (e) { + ce.timers.push(e), ce.fx.start(); + }), + (ce.fx.interval = 13), + (ce.fx.start = function () { + ut || ((ut = !0), dt()); + }), + (ce.fx.stop = function () { + ut = null; + }), + (ce.fx.speeds = { slow: 600, fast: 200, _default: 400 }), + (ce.fn.delay = function (r, e) { + return ( + (r = (ce.fx && ce.fx.speeds[r]) || r), + (e = e || "fx"), + this.queue(e, function (e, t) { + var n = ie.setTimeout(e, r); + t.stop = function () { + ie.clearTimeout(n); + }; + }) + ); + }), + (lt = C.createElement("input")), + (ct = C.createElement("select").appendChild(C.createElement("option"))), + (lt.type = "checkbox"), + (le.checkOn = "" !== lt.value), + (le.optSelected = ct.selected), + ((lt = C.createElement("input")).value = "t"), + (lt.type = "radio"), + (le.radioValue = "t" === lt.value); + var mt, + xt = ce.expr.attrHandle; + ce.fn.extend({ + attr: function (e, t) { + return R(this, ce.attr, e, t, 1 < arguments.length); + }, + removeAttr: function (e) { + return this.each(function () { + ce.removeAttr(this, e); + }); + }, + }), + ce.extend({ + attr: function (e, t, n) { + var r, + i, + o = e.nodeType; + if (3 !== o && 8 !== o && 2 !== o) + return "undefined" == typeof e.getAttribute + ? ce.prop(e, t, n) + : ((1 === o && ce.isXMLDoc(e)) || + (i = + ce.attrHooks[t.toLowerCase()] || + (ce.expr.match.bool.test(t) ? mt : void 0)), + void 0 !== n + ? null === n + ? void ce.removeAttr(e, t) + : i && + "set" in i && + void 0 !== (r = i.set(e, n, t)) + ? r + : (e.setAttribute(t, n + ""), n) + : i && "get" in i && null !== (r = i.get(e, t)) + ? r + : null == (r = ce.find.attr(e, t)) + ? void 0 + : r); + }, + attrHooks: { + type: { + set: function (e, t) { + if (!le.radioValue && "radio" === t && fe(e, "input")) { + var n = e.value; + return ( + e.setAttribute("type", t), n && (e.value = n), t + ); + } + }, + }, + }, + removeAttr: function (e, t) { + var n, + r = 0, + i = t && t.match(D); + if (i && 1 === e.nodeType) + while ((n = i[r++])) e.removeAttribute(n); + }, + }), + (mt = { + set: function (e, t, n) { + return !1 === t ? ce.removeAttr(e, n) : e.setAttribute(n, n), n; + }, + }), + ce.each(ce.expr.match.bool.source.match(/\w+/g), function (e, t) { + var a = xt[t] || ce.find.attr; + xt[t] = function (e, t, n) { + var r, + i, + o = t.toLowerCase(); + return ( + n || + ((i = xt[o]), + (xt[o] = r), + (r = null != a(e, t, n) ? o : null), + (xt[o] = i)), + r + ); + }; + }); + var bt = /^(?:input|select|textarea|button)$/i, + wt = /^(?:a|area)$/i; + function Tt(e) { + return (e.match(D) || []).join(" "); + } + function Ct(e) { + return (e.getAttribute && e.getAttribute("class")) || ""; + } + function kt(e) { + return Array.isArray(e) + ? e + : ("string" == typeof e && e.match(D)) || []; + } + ce.fn.extend({ + prop: function (e, t) { + return R(this, ce.prop, e, t, 1 < arguments.length); + }, + removeProp: function (e) { + return this.each(function () { + delete this[ce.propFix[e] || e]; + }); + }, + }), + ce.extend({ + prop: function (e, t, n) { + var r, + i, + o = e.nodeType; + if (3 !== o && 8 !== o && 2 !== o) + return ( + (1 === o && ce.isXMLDoc(e)) || + ((t = ce.propFix[t] || t), (i = ce.propHooks[t])), + void 0 !== n + ? i && "set" in i && void 0 !== (r = i.set(e, n, t)) + ? r + : (e[t] = n) + : i && "get" in i && null !== (r = i.get(e, t)) + ? r + : e[t] + ); + }, + propHooks: { + tabIndex: { + get: function (e) { + var t = ce.find.attr(e, "tabindex"); + return t + ? parseInt(t, 10) + : bt.test(e.nodeName) || + (wt.test(e.nodeName) && e.href) + ? 0 + : -1; + }, + }, + }, + propFix: { for: "htmlFor", class: "className" }, + }), + le.optSelected || + (ce.propHooks.selected = { + get: function (e) { + var t = e.parentNode; + return ( + t && t.parentNode && t.parentNode.selectedIndex, null + ); + }, + set: function (e) { + var t = e.parentNode; + t && + (t.selectedIndex, + t.parentNode && t.parentNode.selectedIndex); + }, + }), + ce.each( + [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable", + ], + function () { + ce.propFix[this.toLowerCase()] = this; + } + ), + ce.fn.extend({ + addClass: function (t) { + var e, n, r, i, o, a; + return v(t) + ? this.each(function (e) { + ce(this).addClass(t.call(this, e, Ct(this))); + }) + : (e = kt(t)).length + ? this.each(function () { + if ( + ((r = Ct(this)), + (n = 1 === this.nodeType && " " + Tt(r) + " ")) + ) { + for (o = 0; o < e.length; o++) + (i = e[o]), + n.indexOf(" " + i + " ") < 0 && + (n += i + " "); + (a = Tt(n)), + r !== a && this.setAttribute("class", a); + } + }) + : this; + }, + removeClass: function (t) { + var e, n, r, i, o, a; + return v(t) + ? this.each(function (e) { + ce(this).removeClass(t.call(this, e, Ct(this))); + }) + : arguments.length + ? (e = kt(t)).length + ? this.each(function () { + if ( + ((r = Ct(this)), + (n = + 1 === this.nodeType && " " + Tt(r) + " ")) + ) { + for (o = 0; o < e.length; o++) { + i = e[o]; + while (-1 < n.indexOf(" " + i + " ")) + n = n.replace(" " + i + " ", " "); + } + (a = Tt(n)), + r !== a && this.setAttribute("class", a); + } + }) + : this + : this.attr("class", ""); + }, + toggleClass: function (t, n) { + var e, + r, + i, + o, + a = typeof t, + s = "string" === a || Array.isArray(t); + return v(t) + ? this.each(function (e) { + ce(this).toggleClass(t.call(this, e, Ct(this), n), n); + }) + : "boolean" == typeof n && s + ? n + ? this.addClass(t) + : this.removeClass(t) + : ((e = kt(t)), + this.each(function () { + if (s) + for (o = ce(this), i = 0; i < e.length; i++) + (r = e[i]), + o.hasClass(r) + ? o.removeClass(r) + : o.addClass(r); + else + (void 0 !== t && "boolean" !== a) || + ((r = Ct(this)) && + _.set(this, "__className__", r), + this.setAttribute && + this.setAttribute( + "class", + r || !1 === t + ? "" + : _.get(this, "__className__") || + "" + )); + })); + }, + hasClass: function (e) { + var t, + n, + r = 0; + t = " " + e + " "; + while ((n = this[r++])) + if ( + 1 === n.nodeType && + -1 < (" " + Tt(Ct(n)) + " ").indexOf(t) + ) + return !0; + return !1; + }, + }); + var St = /\r/g; + ce.fn.extend({ + val: function (n) { + var r, + e, + i, + t = this[0]; + return arguments.length + ? ((i = v(n)), + this.each(function (e) { + var t; + 1 === this.nodeType && + (null == (t = i ? n.call(this, e, ce(this).val()) : n) + ? (t = "") + : "number" == typeof t + ? (t += "") + : Array.isArray(t) && + (t = ce.map(t, function (e) { + return null == e ? "" : e + ""; + })), + ((r = + ce.valHooks[this.type] || + ce.valHooks[this.nodeName.toLowerCase()]) && + "set" in r && + void 0 !== r.set(this, t, "value")) || + (this.value = t)); + })) + : t + ? (r = + ce.valHooks[t.type] || + ce.valHooks[t.nodeName.toLowerCase()]) && + "get" in r && + void 0 !== (e = r.get(t, "value")) + ? e + : "string" == typeof (e = t.value) + ? e.replace(St, "") + : null == e + ? "" + : e + : void 0; + }, + }), + ce.extend({ + valHooks: { + option: { + get: function (e) { + var t = ce.find.attr(e, "value"); + return null != t ? t : Tt(ce.text(e)); + }, + }, + select: { + get: function (e) { + var t, + n, + r, + i = e.options, + o = e.selectedIndex, + a = "select-one" === e.type, + s = a ? null : [], + u = a ? o + 1 : i.length; + for (r = o < 0 ? u : a ? o : 0; r < u; r++) + if ( + ((n = i[r]).selected || r === o) && + !n.disabled && + (!n.parentNode.disabled || + !fe(n.parentNode, "optgroup")) + ) { + if (((t = ce(n).val()), a)) return t; + s.push(t); + } + return s; + }, + set: function (e, t) { + var n, + r, + i = e.options, + o = ce.makeArray(t), + a = i.length; + while (a--) + ((r = i[a]).selected = + -1 < + ce.inArray(ce.valHooks.option.get(r), o)) && + (n = !0); + return n || (e.selectedIndex = -1), o; + }, + }, + }, + }), + ce.each(["radio", "checkbox"], function () { + (ce.valHooks[this] = { + set: function (e, t) { + if (Array.isArray(t)) + return (e.checked = -1 < ce.inArray(ce(e).val(), t)); + }, + }), + le.checkOn || + (ce.valHooks[this].get = function (e) { + return null === e.getAttribute("value") + ? "on" + : e.value; + }); + }); + var Et = ie.location, + jt = { guid: Date.now() }, + At = /\?/; + ce.parseXML = function (e) { + var t, n; + if (!e || "string" != typeof e) return null; + try { + t = new ie.DOMParser().parseFromString(e, "text/xml"); + } catch (e) {} + return ( + (n = t && t.getElementsByTagName("parsererror")[0]), + (t && !n) || + ce.error( + "Invalid XML: " + + (n + ? ce + .map(n.childNodes, function (e) { + return e.textContent; + }) + .join("\n") + : e) + ), + t + ); + }; + var Dt = /^(?:focusinfocus|focusoutblur)$/, + Nt = function (e) { + e.stopPropagation(); + }; + ce.extend(ce.event, { + trigger: function (e, t, n, r) { + var i, + o, + a, + s, + u, + l, + c, + f, + p = [n || C], + d = ue.call(e, "type") ? e.type : e, + h = ue.call(e, "namespace") ? e.namespace.split(".") : []; + if ( + ((o = f = a = n = n || C), + 3 !== n.nodeType && + 8 !== n.nodeType && + !Dt.test(d + ce.event.triggered) && + (-1 < d.indexOf(".") && + ((d = (h = d.split(".")).shift()), h.sort()), + (u = d.indexOf(":") < 0 && "on" + d), + ((e = e[ce.expando] + ? e + : new ce.Event( + d, + "object" == typeof e && e + )).isTrigger = r ? 2 : 3), + (e.namespace = h.join(".")), + (e.rnamespace = e.namespace + ? new RegExp( + "(^|\\.)" + h.join("\\.(?:.*\\.|)") + "(\\.|$)" + ) + : null), + (e.result = void 0), + e.target || (e.target = n), + (t = null == t ? [e] : ce.makeArray(t, [e])), + (c = ce.event.special[d] || {}), + r || !c.trigger || !1 !== c.trigger.apply(n, t))) + ) { + if (!r && !c.noBubble && !y(n)) { + for ( + s = c.delegateType || d, + Dt.test(s + d) || (o = o.parentNode); + o; + o = o.parentNode + ) + p.push(o), (a = o); + a === (n.ownerDocument || C) && + p.push(a.defaultView || a.parentWindow || ie); + } + i = 0; + while ((o = p[i++]) && !e.isPropagationStopped()) + (f = o), + (e.type = 1 < i ? s : c.bindType || d), + (l = + (_.get(o, "events") || Object.create(null))[ + e.type + ] && _.get(o, "handle")) && l.apply(o, t), + (l = u && o[u]) && + l.apply && + $(o) && + ((e.result = l.apply(o, t)), + !1 === e.result && e.preventDefault()); + return ( + (e.type = d), + r || + e.isDefaultPrevented() || + (c._default && !1 !== c._default.apply(p.pop(), t)) || + !$(n) || + (u && + v(n[d]) && + !y(n) && + ((a = n[u]) && (n[u] = null), + (ce.event.triggered = d), + e.isPropagationStopped() && + f.addEventListener(d, Nt), + n[d](), + e.isPropagationStopped() && + f.removeEventListener(d, Nt), + (ce.event.triggered = void 0), + a && (n[u] = a))), + e.result + ); + } + }, + simulate: function (e, t, n) { + var r = ce.extend(new ce.Event(), n, { type: e, isSimulated: !0 }); + ce.event.trigger(r, null, t); + }, + }), + ce.fn.extend({ + trigger: function (e, t) { + return this.each(function () { + ce.event.trigger(e, t, this); + }); + }, + triggerHandler: function (e, t) { + var n = this[0]; + if (n) return ce.event.trigger(e, t, n, !0); + }, + }); + var qt = /\[\]$/, + Lt = /\r?\n/g, + Ht = /^(?:submit|button|image|reset|file)$/i, + Ot = /^(?:input|select|textarea|keygen)/i; + function Pt(n, e, r, i) { + var t; + if (Array.isArray(e)) + ce.each(e, function (e, t) { + r || qt.test(n) + ? i(n, t) + : Pt( + n + + "[" + + ("object" == typeof t && null != t ? e : "") + + "]", + t, + r, + i + ); + }); + else if (r || "object" !== x(e)) i(n, e); + else for (t in e) Pt(n + "[" + t + "]", e[t], r, i); + } + (ce.param = function (e, t) { + var n, + r = [], + i = function (e, t) { + var n = v(t) ? t() : t; + r[r.length] = + encodeURIComponent(e) + + "=" + + encodeURIComponent(null == n ? "" : n); + }; + if (null == e) return ""; + if (Array.isArray(e) || (e.jquery && !ce.isPlainObject(e))) + ce.each(e, function () { + i(this.name, this.value); + }); + else for (n in e) Pt(n, e[n], t, i); + return r.join("&"); + }), + ce.fn.extend({ + serialize: function () { + return ce.param(this.serializeArray()); + }, + serializeArray: function () { + return this.map(function () { + var e = ce.prop(this, "elements"); + return e ? ce.makeArray(e) : this; + }) + .filter(function () { + var e = this.type; + return ( + this.name && + !ce(this).is(":disabled") && + Ot.test(this.nodeName) && + !Ht.test(e) && + (this.checked || !we.test(e)) + ); + }) + .map(function (e, t) { + var n = ce(this).val(); + return null == n + ? null + : Array.isArray(n) + ? ce.map(n, function (e) { + return { + name: t.name, + value: e.replace(Lt, "\r\n"), + }; + }) + : { name: t.name, value: n.replace(Lt, "\r\n") }; + }) + .get(); + }, + }); + var Rt = /%20/g, + Mt = /#.*$/, + It = /([?&])_=[^&]*/, + Wt = /^(.*?):[ \t]*([^\r\n]*)$/gm, + Ft = /^(?:GET|HEAD)$/, + $t = /^\/\//, + Bt = {}, + _t = {}, + Xt = "*/".concat("*"), + Ut = C.createElement("a"); + function zt(o) { + return function (e, t) { + "string" != typeof e && ((t = e), (e = "*")); + var n, + r = 0, + i = e.toLowerCase().match(D) || []; + if (v(t)) + while ((n = i[r++])) + "+" === n[0] + ? ((n = n.slice(1) || "*"), + (o[n] = o[n] || []).unshift(t)) + : (o[n] = o[n] || []).push(t); + }; + } + function Vt(t, i, o, a) { + var s = {}, + u = t === _t; + function l(e) { + var r; + return ( + (s[e] = !0), + ce.each(t[e] || [], function (e, t) { + var n = t(i, o, a); + return "string" != typeof n || u || s[n] + ? u + ? !(r = n) + : void 0 + : (i.dataTypes.unshift(n), l(n), !1); + }), + r + ); + } + return l(i.dataTypes[0]) || (!s["*"] && l("*")); + } + function Gt(e, t) { + var n, + r, + i = ce.ajaxSettings.flatOptions || {}; + for (n in t) void 0 !== t[n] && ((i[n] ? e : r || (r = {}))[n] = t[n]); + return r && ce.extend(!0, e, r), e; + } + (Ut.href = Et.href), + ce.extend({ + active: 0, + lastModified: {}, + etag: {}, + ajaxSettings: { + url: Et.href, + type: "GET", + isLocal: + /^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test( + Et.protocol + ), + global: !0, + processData: !0, + async: !0, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + accepts: { + "*": Xt, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript", + }, + contents: { xml: /\bxml\b/, html: /\bhtml/, json: /\bjson\b/ }, + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON", + }, + converters: { + "* text": String, + "text html": !0, + "text json": JSON.parse, + "text xml": ce.parseXML, + }, + flatOptions: { url: !0, context: !0 }, + }, + ajaxSetup: function (e, t) { + return t + ? Gt(Gt(e, ce.ajaxSettings), t) + : Gt(ce.ajaxSettings, e); + }, + ajaxPrefilter: zt(Bt), + ajaxTransport: zt(_t), + ajax: function (e, t) { + "object" == typeof e && ((t = e), (e = void 0)), (t = t || {}); + var c, + f, + p, + n, + d, + r, + h, + g, + i, + o, + v = ce.ajaxSetup({}, t), + y = v.context || v, + m = + v.context && (y.nodeType || y.jquery) + ? ce(y) + : ce.event, + x = ce.Deferred(), + b = ce.Callbacks("once memory"), + w = v.statusCode || {}, + a = {}, + s = {}, + u = "canceled", + T = { + readyState: 0, + getResponseHeader: function (e) { + var t; + if (h) { + if (!n) { + n = {}; + while ((t = Wt.exec(p))) + n[t[1].toLowerCase() + " "] = ( + n[t[1].toLowerCase() + " "] || [] + ).concat(t[2]); + } + t = n[e.toLowerCase() + " "]; + } + return null == t ? null : t.join(", "); + }, + getAllResponseHeaders: function () { + return h ? p : null; + }, + setRequestHeader: function (e, t) { + return ( + null == h && + ((e = s[e.toLowerCase()] = + s[e.toLowerCase()] || e), + (a[e] = t)), + this + ); + }, + overrideMimeType: function (e) { + return null == h && (v.mimeType = e), this; + }, + statusCode: function (e) { + var t; + if (e) + if (h) T.always(e[T.status]); + else for (t in e) w[t] = [w[t], e[t]]; + return this; + }, + abort: function (e) { + var t = e || u; + return c && c.abort(t), l(0, t), this; + }, + }; + if ( + (x.promise(T), + (v.url = ((e || v.url || Et.href) + "").replace( + $t, + Et.protocol + "//" + )), + (v.type = t.method || t.type || v.method || v.type), + (v.dataTypes = (v.dataType || "*") + .toLowerCase() + .match(D) || [""]), + null == v.crossDomain) + ) { + r = C.createElement("a"); + try { + (r.href = v.url), + (r.href = r.href), + (v.crossDomain = + Ut.protocol + "//" + Ut.host != + r.protocol + "//" + r.host); + } catch (e) { + v.crossDomain = !0; + } + } + if ( + (v.data && + v.processData && + "string" != typeof v.data && + (v.data = ce.param(v.data, v.traditional)), + Vt(Bt, v, t, T), + h) + ) + return T; + for (i in ((g = ce.event && v.global) && + 0 == ce.active++ && + ce.event.trigger("ajaxStart"), + (v.type = v.type.toUpperCase()), + (v.hasContent = !Ft.test(v.type)), + (f = v.url.replace(Mt, "")), + v.hasContent + ? v.data && + v.processData && + 0 === + (v.contentType || "").indexOf( + "application/x-www-form-urlencoded" + ) && + (v.data = v.data.replace(Rt, "+")) + : ((o = v.url.slice(f.length)), + v.data && + (v.processData || "string" == typeof v.data) && + ((f += (At.test(f) ? "&" : "?") + v.data), + delete v.data), + !1 === v.cache && + ((f = f.replace(It, "$1")), + (o = + (At.test(f) ? "&" : "?") + "_=" + jt.guid++ + o)), + (v.url = f + o)), + v.ifModified && + (ce.lastModified[f] && + T.setRequestHeader( + "If-Modified-Since", + ce.lastModified[f] + ), + ce.etag[f] && + T.setRequestHeader("If-None-Match", ce.etag[f])), + ((v.data && v.hasContent && !1 !== v.contentType) || + t.contentType) && + T.setRequestHeader("Content-Type", v.contentType), + T.setRequestHeader( + "Accept", + v.dataTypes[0] && v.accepts[v.dataTypes[0]] + ? v.accepts[v.dataTypes[0]] + + ("*" !== v.dataTypes[0] + ? ", " + Xt + "; q=0.01" + : "") + : v.accepts["*"] + ), + v.headers)) + T.setRequestHeader(i, v.headers[i]); + if (v.beforeSend && (!1 === v.beforeSend.call(y, T, v) || h)) + return T.abort(); + if ( + ((u = "abort"), + b.add(v.complete), + T.done(v.success), + T.fail(v.error), + (c = Vt(_t, v, t, T))) + ) { + if ( + ((T.readyState = 1), + g && m.trigger("ajaxSend", [T, v]), + h) + ) + return T; + v.async && + 0 < v.timeout && + (d = ie.setTimeout(function () { + T.abort("timeout"); + }, v.timeout)); + try { + (h = !1), c.send(a, l); + } catch (e) { + if (h) throw e; + l(-1, e); + } + } else l(-1, "No Transport"); + function l(e, t, n, r) { + var i, + o, + a, + s, + u, + l = t; + h || + ((h = !0), + d && ie.clearTimeout(d), + (c = void 0), + (p = r || ""), + (T.readyState = 0 < e ? 4 : 0), + (i = (200 <= e && e < 300) || 304 === e), + n && + (s = (function (e, t, n) { + var r, + i, + o, + a, + s = e.contents, + u = e.dataTypes; + while ("*" === u[0]) + u.shift(), + void 0 === r && + (r = + e.mimeType || + t.getResponseHeader( + "Content-Type" + )); + if (r) + for (i in s) + if (s[i] && s[i].test(r)) { + u.unshift(i); + break; + } + if (u[0] in n) o = u[0]; + else { + for (i in n) { + if ( + !u[0] || + e.converters[i + " " + u[0]] + ) { + o = i; + break; + } + a || (a = i); + } + o = o || a; + } + if (o) return o !== u[0] && u.unshift(o), n[o]; + })(v, T, n)), + !i && + -1 < ce.inArray("script", v.dataTypes) && + ce.inArray("json", v.dataTypes) < 0 && + (v.converters["text script"] = function () {}), + (s = (function (e, t, n, r) { + var i, + o, + a, + s, + u, + l = {}, + c = e.dataTypes.slice(); + if (c[1]) + for (a in e.converters) + l[a.toLowerCase()] = e.converters[a]; + o = c.shift(); + while (o) + if ( + (e.responseFields[o] && + (n[e.responseFields[o]] = t), + !u && + r && + e.dataFilter && + (t = e.dataFilter(t, e.dataType)), + (u = o), + (o = c.shift())) + ) + if ("*" === o) o = u; + else if ("*" !== u && u !== o) { + if ( + !(a = l[u + " " + o] || l["* " + o]) + ) + for (i in l) + if ( + (s = i.split(" "))[1] === + o && + (a = + l[u + " " + s[0]] || + l["* " + s[0]]) + ) { + !0 === a + ? (a = l[i]) + : !0 !== l[i] && + ((o = s[0]), + c.unshift(s[1])); + break; + } + if (!0 !== a) + if (a && e["throws"]) t = a(t); + else + try { + t = a(t); + } catch (e) { + return { + state: "parsererror", + error: a + ? e + : "No conversion from " + + u + + " to " + + o, + }; + } + } + return { state: "success", data: t }; + })(v, s, T, i)), + i + ? (v.ifModified && + ((u = T.getResponseHeader("Last-Modified")) && + (ce.lastModified[f] = u), + (u = T.getResponseHeader("etag")) && + (ce.etag[f] = u)), + 204 === e || "HEAD" === v.type + ? (l = "nocontent") + : 304 === e + ? (l = "notmodified") + : ((l = s.state), + (o = s.data), + (i = !(a = s.error)))) + : ((a = l), + (!e && l) || ((l = "error"), e < 0 && (e = 0))), + (T.status = e), + (T.statusText = (t || l) + ""), + i + ? x.resolveWith(y, [o, l, T]) + : x.rejectWith(y, [T, l, a]), + T.statusCode(w), + (w = void 0), + g && + m.trigger(i ? "ajaxSuccess" : "ajaxError", [ + T, + v, + i ? o : a, + ]), + b.fireWith(y, [T, l]), + g && + (m.trigger("ajaxComplete", [T, v]), + --ce.active || ce.event.trigger("ajaxStop"))); + } + return T; + }, + getJSON: function (e, t, n) { + return ce.get(e, t, n, "json"); + }, + getScript: function (e, t) { + return ce.get(e, void 0, t, "script"); + }, + }), + ce.each(["get", "post"], function (e, i) { + ce[i] = function (e, t, n, r) { + return ( + v(t) && ((r = r || n), (n = t), (t = void 0)), + ce.ajax( + ce.extend( + { + url: e, + type: i, + dataType: r, + data: t, + success: n, + }, + ce.isPlainObject(e) && e + ) + ) + ); + }; + }), + ce.ajaxPrefilter(function (e) { + var t; + for (t in e.headers) + "content-type" === t.toLowerCase() && + (e.contentType = e.headers[t] || ""); + }), + (ce._evalUrl = function (e, t, n) { + return ce.ajax({ + url: e, + type: "GET", + dataType: "script", + cache: !0, + async: !1, + global: !1, + converters: { "text script": function () {} }, + dataFilter: function (e) { + ce.globalEval(e, t, n); + }, + }); + }), + ce.fn.extend({ + wrapAll: function (e) { + var t; + return ( + this[0] && + (v(e) && (e = e.call(this[0])), + (t = ce(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 (n) { + return v(n) + ? this.each(function (e) { + ce(this).wrapInner(n.call(this, e)); + }) + : this.each(function () { + var e = ce(this), + t = e.contents(); + t.length ? t.wrapAll(n) : e.append(n); + }); + }, + wrap: function (t) { + var n = v(t); + return this.each(function (e) { + ce(this).wrapAll(n ? t.call(this, e) : t); + }); + }, + unwrap: function (e) { + return ( + this.parent(e) + .not("body") + .each(function () { + ce(this).replaceWith(this.childNodes); + }), + this + ); + }, + }), + (ce.expr.pseudos.hidden = function (e) { + return !ce.expr.pseudos.visible(e); + }), + (ce.expr.pseudos.visible = function (e) { + return !!( + e.offsetWidth || + e.offsetHeight || + e.getClientRects().length + ); + }), + (ce.ajaxSettings.xhr = function () { + try { + return new ie.XMLHttpRequest(); + } catch (e) {} + }); + var Yt = { 0: 200, 1223: 204 }, + Qt = ce.ajaxSettings.xhr(); + (le.cors = !!Qt && "withCredentials" in Qt), + (le.ajax = Qt = !!Qt), + ce.ajaxTransport(function (i) { + var o, a; + if (le.cors || (Qt && !i.crossDomain)) + return { + send: function (e, t) { + var n, + r = i.xhr(); + if ( + (r.open( + i.type, + i.url, + i.async, + i.username, + i.password + ), + i.xhrFields) + ) + for (n in i.xhrFields) r[n] = i.xhrFields[n]; + for (n in (i.mimeType && + r.overrideMimeType && + r.overrideMimeType(i.mimeType), + i.crossDomain || + e["X-Requested-With"] || + (e["X-Requested-With"] = "XMLHttpRequest"), + e)) + r.setRequestHeader(n, e[n]); + (o = function (e) { + return function () { + o && + ((o = + a = + r.onload = + r.onerror = + r.onabort = + r.ontimeout = + r.onreadystatechange = + null), + "abort" === e + ? r.abort() + : "error" === e + ? "number" != typeof r.status + ? t(0, "error") + : t(r.status, r.statusText) + : t( + Yt[r.status] || r.status, + r.statusText, + "text" !== + (r.responseType || "text") || + "string" != + typeof r.responseText + ? { binary: r.response } + : { text: r.responseText }, + r.getAllResponseHeaders() + )); + }; + }), + (r.onload = o()), + (a = r.onerror = r.ontimeout = o("error")), + void 0 !== r.onabort + ? (r.onabort = a) + : (r.onreadystatechange = function () { + 4 === r.readyState && + ie.setTimeout(function () { + o && a(); + }); + }), + (o = o("abort")); + try { + r.send((i.hasContent && i.data) || null); + } catch (e) { + if (o) throw e; + } + }, + abort: function () { + o && o(); + }, + }; + }), + ce.ajaxPrefilter(function (e) { + e.crossDomain && (e.contents.script = !1); + }), + ce.ajaxSetup({ + accepts: { + script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript", + }, + contents: { script: /\b(?:java|ecma)script\b/ }, + converters: { + "text script": function (e) { + return ce.globalEval(e), e; + }, + }, + }), + ce.ajaxPrefilter("script", function (e) { + void 0 === e.cache && (e.cache = !1), + e.crossDomain && (e.type = "GET"); + }), + ce.ajaxTransport("script", function (n) { + var r, i; + if (n.crossDomain || n.scriptAttrs) + return { + send: function (e, t) { + (r = ce(" + + + + + + + Add Panopto Video + + +
+ +
+ + + diff --git a/pix/icon.png b/pix/icon.png new file mode 100644 index 0000000..ddd39b3 Binary files /dev/null and b/pix/icon.png differ diff --git a/pix/icon.svg b/pix/icon.svg new file mode 100644 index 0000000..ef4c238 --- /dev/null +++ b/pix/icon.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/modal.mustache b/templates/modal.mustache new file mode 100644 index 0000000..047ebbe --- /dev/null +++ b/templates/modal.mustache @@ -0,0 +1,38 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template tiny_panoptoltibutton/modal + + Modal to insert a Panopto Video within the Tiny Editor. + + Example context (json): + { + + } +}} + +{{< core/modal }} + {{$title}} + {{#str}} panopto_button_description, tiny_panoptoltibutton {{/str}} + {{/title}} + {{$body}} + + {{/body}} + {{$footer}} + + {{/footer}} +{{/ core/modal }} \ No newline at end of file diff --git a/version.php b/version.php new file mode 100644 index 0000000..35345f8 --- /dev/null +++ b/version.php @@ -0,0 +1,46 @@ +. + +/** + * Panopto LTI Button version. + * + * @copyright Panopto 2009 - 2023 + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + + +// The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2023083100; + +// Requires this Moodle version - 2.7. +$plugin->requires = 2014051200; + +// Full name of the plugin (used for diagnostics). +$plugin->component = 'tiny_panoptoltibutton'; + +// Supported versions. +$plugin->supported = [401, 402]; + +// This is considered as ready for production sites. +$plugin->maturity = MATURITY_BETA; + +// Dependencies. +$plugin->dependencies = array( + 'block_panopto' => 2022122000, + 'mod_lti' => ANY_VERSION +); diff --git a/view.php b/view.php new file mode 100644 index 0000000..910aab7 --- /dev/null +++ b/view.php @@ -0,0 +1,115 @@ +. + +/** + * This file launches LTI-tools enabled to be launched from a rich text editor + * + * @package tiny_panoptoltibutton + * @copyright 2023 Panopto + * @author Panopto with contributions from Adis Hrnjica + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +// @codingStandardsIgnoreLine +global $DB, $CFG, $COURSE; +if (empty($CFG)) { + // @codingStandardsIgnoreLine + require_once(dirname(__FILE__) . '/../../../../../config.php'); +} +require_once($CFG->dirroot . '/blocks/panopto/lib/block_panopto_lib.php'); +require_once($CFG->libdir .'/accesslib.php'); // Access control functions. +require_once($CFG->dirroot . '/mod/lti/lib.php'); +require_once($CFG->dirroot . '/mod/lti/locallib.php'); +require_once($CFG->dirroot . '/blocks/panopto/lib/lti/panoptoblock_lti_utility.php'); + +$configuredserverarray = panopto_get_configured_panopto_servers(); + +$contenturl = optional_param('contenturl', '', PARAM_URL); + +$contentverified = false; + +if ($contenturl) { + foreach ($configuredserverarray as $possibleserver) { + $contenthost = parse_url($contenturl, PHP_URL_HOST); + + if (stripos($contenthost, $possibleserver) !== false) { + $contentverified = true; + break; + } + } +} else { + $contentverified = true; +} + +if ($contentverified) { + $resourcelinkid = required_param('resourcelinkid', PARAM_ALPHANUMEXT); + $ltitypeid = required_param('ltitypeid', PARAM_INT); + $customdata = optional_param('custom', '', PARAM_RAW_TRIMMED); + + require_login(); + + // Make sure $ltitypeid is valid. + $ltitype = $DB->get_record('lti_types', ['id' => $ltitypeid], '*', MUST_EXIST); + + $lti = new stdClass(); + + // Try to detect if we are viewing content from an iframe nested in course, get the Id param if it exists. + $courseid = 0; + if (!empty($_SERVER['HTTP_REFERER']) && (strpos($_SERVER['HTTP_REFERER'], "/course/view.php") !== false)) { + $components = parse_url($_SERVER['HTTP_REFERER']); + parse_str($components['query'], $results); + + if (!empty($results['id'])) { + $lti->course = $results['id']; + $course = $DB->get_record('course', array('id' => $results['id']), '*', MUST_EXIST); + $courseid = $course->id; + $context = context_course::instance($results['id']); + $PAGE->set_context($context); + require_login($course, true); + } + } + + $lti->id = $resourcelinkid; + $lti->typeid = $ltitypeid; + $lti->launchcontainer = LTI_LAUNCH_CONTAINER_WINDOW; + $lti->toolurl = $contenturl; + $lti->custom = new stdClass(); + $lti->instructorcustomparameters = []; + $lti->debuglaunch = false; + if ($customdata) { + $decoded = json_decode($customdata, true); + + foreach ($decoded as $key => $value) { + $lti->custom->$key = $value; + } + } + + // LTI 1.3 login request. + $config = lti_get_type_type_config($ltitypeid); + if ($config->lti_ltiversion === LTI_VERSION_1P3) { + if (!isset($SESSION->lti_initiatelogin_status)) { + echo lti_initiate_login($courseid, + "tiny_panoptoltibutton,'',{$ltitypeid},{$resourcelinkid},{$contenturl},{$customdata}", + $lti, + $config + ); + exit; + } + } + + echo \panoptoblock_lti_utility::launch_tool($lti); +} else { + echo get_string('invalid_content_host', 'tiny_panoptoltibutton'); +}