From 4971307c4d67c16997555dd417480f93a0237716 Mon Sep 17 00:00:00 2001 From: varjolintu Date: Sat, 19 Jan 2019 10:46:16 +0200 Subject: [PATCH] No jQuery --- .gitignore | 1 + keepassxc-browser/_locales/en/messages.json | 58 +- keepassxc-browser/background/browserAction.js | 10 +- keepassxc-browser/background/event.js | 10 +- keepassxc-browser/background/httpauth.js | 8 +- keepassxc-browser/background/init.js | 11 +- keepassxc-browser/background/keepass.js | 89 +- keepassxc-browser/background/page.js | 40 +- keepassxc-browser/content/autocomplete.js | 188 ++ keepassxc-browser/content/define.js | 382 +++ .../content/keepassxc-browser.js | 1496 +++++++++++ keepassxc-browser/content/pwgen.js | 407 +++ keepassxc-browser/content/ui.js | 67 + keepassxc-browser/css/autocomplete.css | 19 + keepassxc-browser/css/button.css | 48 + keepassxc-browser/css/define.css | 110 + keepassxc-browser/css/pwgen.css | 114 + keepassxc-browser/global.js | 16 +- keepassxc-browser/jquery-ui.min.css | 7 - keepassxc-browser/jquery-ui.min.js | 13 - keepassxc-browser/keepassxc-browser.css | 255 -- keepassxc-browser/keepassxc-browser.js | 2258 ----------------- keepassxc-browser/manifest.json | 35 +- keepassxc-browser/options/options.html | 11 +- keepassxc-browser/options/options.js | 9 +- keepassxc-browser/options/shortcuts.js | 4 +- keepassxc-browser/popups/popup.css | 12 +- keepassxc-browser/popups/popup.html | 27 +- keepassxc-browser/popups/popup_httpauth.html | 17 +- keepassxc-browser/popups/popup_httpauth.js | 2 +- keepassxc-browser/popups/popup_login.html | 17 +- .../popups/popup_multiple-fields.html | 15 +- keepassxc-browser/popups/popup_remember.html | 15 +- keepassxc-browser/popups/popup_remember.js | 4 +- keepassxc-browser/popups/throbber.gif | Bin 583 -> 673 bytes 35 files changed, 3060 insertions(+), 2715 deletions(-) create mode 100644 keepassxc-browser/content/autocomplete.js create mode 100644 keepassxc-browser/content/define.js create mode 100755 keepassxc-browser/content/keepassxc-browser.js create mode 100644 keepassxc-browser/content/pwgen.js create mode 100644 keepassxc-browser/content/ui.js create mode 100644 keepassxc-browser/css/autocomplete.css create mode 100644 keepassxc-browser/css/button.css create mode 100644 keepassxc-browser/css/define.css create mode 100644 keepassxc-browser/css/pwgen.css delete mode 100644 keepassxc-browser/jquery-ui.min.css delete mode 100644 keepassxc-browser/jquery-ui.min.js delete mode 100644 keepassxc-browser/keepassxc-browser.css delete mode 100755 keepassxc-browser/keepassxc-browser.js diff --git a/.gitignore b/.gitignore index 5737441..a667390 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ .bz .bz2 .xz +node_modules/* diff --git a/keepassxc-browser/_locales/en/messages.json b/keepassxc-browser/_locales/en/messages.json index 8c0033d..633ba7f 100644 --- a/keepassxc-browser/_locales/en/messages.json +++ b/keepassxc-browser/_locales/en/messages.json @@ -112,7 +112,7 @@ "description": "Checkbox text below the password generator input field." }, "passwordGeneratorBits": { - "message": "??? Bits", + "message": "$1 Bits", "description": "Bits of the generated password." }, "passwordGeneratorTitle": { @@ -123,6 +123,10 @@ "message": "Generate", "description": "Generate button text in password generator." }, + "passwordGeneratorTryAgain": { + "message": "Try again", + "description": "Generate button text in password generator when not connected." + }, "passwordGeneratorCopy": { "message": "Copy", "description": "Copy button text in password generator." @@ -132,7 +136,15 @@ "description": "Fill and copy button text in password generator." }, "passwordGeneratorErrorTooLong": { - "message": "Error:\nThe generated password is longer than the allowed length!\nIt has been cut to fit the length.\n\nPlease remember the new password!", + "message": "Error: The generated password is longer than the allowed length!", + "description": "A warning text shown in the password generator." + }, + "passwordGeneratorErrorTooLongCut": { + "message": "It has been cut to fit the length.", + "description": "A warning text shown in the password generator." + }, + "passwordGeneratorErrorTooLongRemember": { + "message": "Please remember the new password!", "description": "A warning text shown in the password generator." }, "passwordGeneratorGenerateText": { @@ -140,7 +152,11 @@ "description": "Password icon title text." }, "passwordGeneratorError": { - "message": "Cannot receive generated password.
Is KeePassXC running?", + "message": "Cannot receive generated password.", + "description": "Password generator error text when KeePassXC is closed." + }, + "passwordGeneratorErrorIsRunning": { + "message": "Is KeePassXC running and connected?", "description": "Password generator error text when KeePassXC is closed." }, "defineDismiss": { @@ -208,27 +224,31 @@ "description": "Shown when no username is set in the credentials." }, "credentialsNoLoginsFound": { - "message": "Error:\nNo logins found.", + "message": "Error: No logins found.", "description": "Shown when no credentials are found for the current page." }, "credentialsMultipleFound": { - "message": "Error:\nMore than one login was found in KeePassXC!\nPress the KeePassXC-Browser icon for more options.", + "message": "Error: More than one login was found in KeePassXC!", + "description": "Alert message when trying to fill username and/or password when multiple credentials are found." + }, + "credentialsMultipleFoundSecondLine": { + "message": "Press the KeePassXC-Browser icon for more options.", "description": "Alert message when trying to fill username and/or password when multiple credentials are found." }, "credentialsNoUsernameFound": { - "message": "Error:\nNo credentials for the given username found.", + "message": "Error: No credentials for the given username found.", "description": "Alert message when no credentials are found for the given username." }, "fieldsFill": { - "message": "Error:\nCannot find fields to fill in.", + "message": "Error: Cannot find fields to fill in.", "description": "Alert message when no fields are found to fill in." }, "fieldsNoPasswordField": { - "message": "Error:\nUnable to find a password field.", + "message": "Error: Unable to find a password field.", "description": "Message shown when no password fields are found." }, "rememberNothingChanged": { - "message": "Error:\nCould not detect changed credentials.", + "message": "Error: Could not detect changed credentials.", "description": "Message shown when trying to save credentials that haven't changed." }, "popupTitle": { @@ -323,12 +343,12 @@ "message": "Please choose the group you want to add the new credentials.", "description": "A popup message shown choosing what group user wants to use for new credentials." }, - "popupRememberErrorDefaultGroupNotFound": { - "message": "Error: Specified default group not found. Creating all necessary groups.", - "description": "Error message shown when default group set cannot be found." + "popupRememberInfoDefaultGroupNotFound": { + "message": "Info: Default group created in connected database.", + "description": "Info message shown when default group set cannot be found." }, "popupRememberErrorCreatingNewGroup": { - "message": "New group(s) cannot be created.", + "message": "Error: New group(s) cannot be created.", "description": "Error message shown when new groups cannot be created." }, "popupRememberErrorPasswordNotChanged": { @@ -503,6 +523,10 @@ "message": "Automatically retrieve credentials.", "description": "Automatically retrieve credentials checkbox text." }, + "optionsCheckboxAutomaticReconnect": { + "message": "Automatically reconnect to KeePassXC.", + "description": "Auto-reconnect checkbox text." + }, "optionsCheckboxAutoFillSingleEntry": { "message": "Automatically fill in single-credential entries.", "description": "Automatically fill-in single credential entry checkbox text." @@ -579,6 +603,10 @@ "message": "KeePassXC-Browser will immediately retrieve credentials when a tab is activated.", "description": "Auto-Retrive Credentials option help text." }, + "optionsAutomaticReconnectHelpText": { + "message": "Reconnects automatically to KeePassXC when it is detected.", + "description": "Auto-reconnect option help text." + }, "optionsAutoFillSingleEntryHelpText": { "message": "Let KeePassXC-Browser automatically fill in credentials if it receives only a single entry.", "description": "Auto-Fill Single Entry option help text." @@ -731,6 +759,10 @@ "message": "Go to the page and click on the KeePassXC-Browser icon, then select ", "description": "Saved custom login fields info text, second part." }, + "optionsCustomFieldsTabHelpTextThird": { + "message": "On this page you can manage saved custom login fields.", + "description": "Saved custom login fields info text, third part." + }, "optionsCustomFieldsRemove": { "message": "Remove saved custom login fields?", "description": "Confirmation text when removing saved custom login fields." diff --git a/keepassxc-browser/background/browserAction.js b/keepassxc-browser/background/browserAction.js index c3e8b1b..4f8e7ac 100755 --- a/keepassxc-browser/background/browserAction.js +++ b/keepassxc-browser/background/browserAction.js @@ -193,7 +193,7 @@ browserAction.removeRememberPopup = function(callback, tab, removeImmediately) { const currentMS = Date.now(); if (removeImmediately || (data.visibleForPageUpdates <= 0 && data.redirectOffset > 0)) { browserAction.stackPop(tab.id); - browserAction.show(null, { 'id': tab.id }); + browserAction.show(null, { 'id': tab.id } ); page.clearCredentials(tab.id); } else if (!isNaN(data.visibleForPageUpdates) && data.redirectOffset > 0 && currentMS >= data.redirectOffset) { data.visibleForPageUpdates -= 1; @@ -205,7 +205,7 @@ browserAction.setRememberPopup = function(tabId, username, password, url, userna browser.storage.local.get({ 'settings': {} }).then(function(item) { const settings = item.settings; - // Don't show anything if the site is in the ignore + // Don't show anything if the site is in the ignore if (settings.sitePreferences !== undefined) { for (const site of settings.sitePreferences) { if (site.ignore === IGNORE_NORMAL && (site.url === url || siteMatch(site.url, url))) { @@ -233,7 +233,7 @@ browserAction.setRememberPopup = function(tabId, username, password, url, userna index: 0, counter: 0, max: 2, - icons: [ 'icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png' ] + icons: ['icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png'] }, icon: 'icon_remember_red_background_19x19.png', popup: 'popup_remember.html' @@ -271,8 +271,8 @@ browserAction.setRememberPopup = function(tabId, username, password, url, userna 'buttons': buttons }); - browser.notifications.onButtonClicked.addListener((id, index) => { - browser.notifications.clear(id); + browser.notifications.onButtonClicked.addListener((notificationId, index) => { + browser.notifications.clear(notificationId); if (index === 1) { browserAction.ignoreSite(url); } diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index 3414888..17b91de 100755 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -99,7 +99,7 @@ kpxcEvent.showStatus = function(configured, tab, callback) { keePassXCAvailable: keepass.isKeePassXCAvailable, encryptionKeyUnrecognized: keepass.isEncryptionKeyUnrecognized, associated: keepass.isAssociated(), - error: errorMessage ? errorMessage : null + error: errorMessage || null }); }; @@ -192,16 +192,16 @@ kpxcEvent.onGetConnectedDatabase = function(callback, tab) { kpxcEvent.onGetKeePassXCVersions = function(callback, tab) { if (keepass.currentKeePassXC === '') { keepass.getDatabaseHash((res) => { - callback({'current': keepass.currentKeePassXC, 'latest': keepass.latestKeePassXC.version}); + callback({ 'current': keepass.currentKeePassXC, 'latest': keepass.latestKeePassXC.version }); }, tab); } else { - callback({'current': keepass.currentKeePassXC, 'latest': keepass.latestKeePassXC.version}); + callback({ 'current': keepass.currentKeePassXC, 'latest': keepass.latestKeePassXC.version }); } }; kpxcEvent.onCheckUpdateKeePassXC = function(callback, tab) { keepass.checkForNewKeePassXCVersion(); - callback({current: keepass.currentKeePassXC.version, latest: keepass.latestKeePassXC.version}); + callback({ current: keepass.currentKeePassXC.version, latest: keepass.latestKeePassXC.version }); }; kpxcEvent.onUpdateAvailableKeePassXC = function(callback, tab) { @@ -285,6 +285,8 @@ kpxcEvent.messageHandlers = { 'associate': keepass.associate, 'check_update_keepassxc': kpxcEvent.onCheckUpdateKeePassXC, 'create_new_group': keepass.createNewGroup, + 'enable_automatic_reconnect': keepass.enableAutomaticReconnect, + 'disable_automatic_reconnect': keepass.disableAutomaticReconnect, 'generate_password': keepass.generatePassword, 'get_connected_database': kpxcEvent.onGetConnectedDatabase, 'get_database_groups': keepass.getDatabaseGroups, diff --git a/keepassxc-browser/background/httpauth.js b/keepassxc-browser/background/httpauth.js index cf9caef..367dc43 100755 --- a/keepassxc-browser/background/httpauth.js +++ b/keepassxc-browser/background/httpauth.js @@ -20,11 +20,11 @@ httpAuth.init = function() { browser.webRequest.onErrorOccurred.removeListener(httpAuth.requestCompleted); } - // only intercept http auth requests if the option is turned on. + // Only intercept http auth requests if the option is turned on. if (page.settings.autoFillAndSend) { - const opts = { urls: [''] }; + const opts = { urls: [ '' ] }; - browser.webRequest.onAuthRequired.addListener(handleReq, opts, [reqType]); + browser.webRequest.onAuthRequired.addListener(handleReq, opts, [ reqType ]); browser.webRequest.onCompleted.addListener(httpAuth.requestCompleted, opts); browser.webRequest.onErrorOccurred.addListener(httpAuth.requestCompleted, opts); } @@ -75,7 +75,7 @@ httpAuth.processPendingCallbacks = async function(details, resolve, reject) { httpAuth.loginOrShowCredentials = function(logins, details, resolve, reject) { // At least one login found --> use first to login - if (logins.length > 0 && page.settings.autoFillAndSend) { + if (logins.length > 0 && page.settings.autoFillAndSend) { if (logins.length === 1) { resolve({ authCredentials: { diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index c603f9f..bce352b 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -7,6 +7,7 @@ keepass.migrateKeyRing().then(() => { keepass.connectToNative(); keepass.generateNewKeyPair(); keepass.changePublicKeys(null).then((pkRes) => { + keepass.enableAutomaticReconnect(); keepass.getDatabaseHash((gdRes) => {}, null); }); }); @@ -85,11 +86,11 @@ const contextMenuItems = [ { title: tr('contextMenuFillPassword'), action: 'fill_password' }, { title: tr('contextMenuFillTOTP'), action: 'fill_totp' }, { title: tr('contextMenuShowPasswordGeneratorIcons'), action: 'activate_password_generator' }, - { title: tr('contextMenuSaveCredentials'), action: 'remember_credentials' }, - { title: tr('contextMenuShowPasswordGenerator'), action: 'show_password_generator' } + { title: tr('contextMenuShowPasswordGenerator'), action: 'show_password_generator' }, + { title: tr('contextMenuSaveCredentials'), action: 'remember_credentials' } ]; -const menuContexts = ['editable']; +const menuContexts = [ 'editable' ]; if (isFirefox()) { menuContexts.push('password'); @@ -103,8 +104,8 @@ for (const item of contextMenuItems) { onclick: (info, tab) => { browser.tabs.sendMessage(tab.id, { action: item.action - }).catch((e) => { - console.log(e); + }).catch((err) => { + console.log(err); }); } }); diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index 4b18c4d..c49e6c8 100755 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -1,8 +1,8 @@ 'use strict'; const keepass = {}; -keepass.associated = {'value': false, 'hash': null}; -keepass.keyPair = {publicKey: null, secretKey: null}; +keepass.associated = { 'value': false, 'hash': null }; +keepass.keyPair = { publicKey: null, secretKey: null }; keepass.serverPublicKey = ''; keepass.clientID = ''; keepass.isConnected = false; @@ -22,6 +22,7 @@ keepass.keyId = 'keepassxc-browser-cryptokey-name'; keepass.keyBody = 'keepassxc-browser-key'; keepass.messageTimeout = 500; // Milliseconds keepass.nonce = nacl.util.encodeBase64(nacl.randomBytes(keepass.keySize)); +keepass.reconnectLoop = null; const kpActions = { SET_LOGIN: 'set-login', @@ -80,11 +81,9 @@ const kpErrors = { } }; -browser.storage.local.get({ - 'latestKeePassXC': { 'version': '', 'lastChecked': null }, - 'keyRing': {}}).then((item) => { - keepass.latestKeePassXC = item.latestKeePassXC; - keepass.keyRing = item.keyRing; +browser.storage.local.get({ 'latestKeePassXC': { 'version': '', 'lastChecked': null }, 'keyRing': {} }).then((item) => { + keepass.latestKeePassXC = item.latestKeePassXC; + keepass.keyRing = item.keyRing; }); keepass.sendNativeMessage = function(request, enableTimeout = false) { @@ -134,7 +133,6 @@ keepass.addCredentials = function(callback, tab, username, password, url, group, }; keepass.updateCredentials = function(callback, tab, entryId, username, password, url, group, groupUuid) { - page.debug('keepass.updateCredentials(callback, {1}, {2}, {3}, [password], {4})', tab.id, entryId, username, url); if (tab && page.tabs[tab.id]) { page.tabs[tab.id].errorMessage = null; } @@ -199,8 +197,6 @@ keepass.updateCredentials = function(callback, tab, entryId, username, password, }; keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallback, triggerUnlock = false, httpAuth = false) { - page.debug('keepass.retrieveCredentials(callback, {1}, {2}, {3}, {4})', tab.id, url, submiturl, forceCallback); - keepass.testAssociation((response) => { if (!response) { browserAction.showDefault(null, tab); @@ -220,12 +216,12 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb } let entries = []; - let keys = []; + const keys = []; const kpAction = kpActions.GET_LOGINS; const nonce = keepass.getNonce(); const incrementedNonce = keepass.incrementedNonce(nonce); const { dbid } = keepass.getCryptoKey(); - + for (const keyHash in keepass.keyRing) { keys.push({ id: keepass.keyRing[keyHash].id, @@ -279,7 +275,6 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb } else { console.log('RetrieveCredentials for ' + url + ' rejected'); } - page.debug('keepass.retrieveCredentials() => entries.length = {1}', entries.length); } else if (response.error && response.errorCode) { keepass.handleError(tab, response.errorCode, response.error); callback([]); @@ -291,7 +286,7 @@ keepass.retrieveCredentials = function(callback, tab, url, submiturl, forceCallb }, tab, false, triggerUnlock); }; -keepass.generatePassword = function(callback, tab, forceCallback) { +keepass.generatePassword = function(callback, tab) { if (!keepass.isConnected) { callback([]); return; @@ -300,9 +295,7 @@ keepass.generatePassword = function(callback, tab, forceCallback) { keepass.testAssociation((taresponse) => { if (!taresponse) { browserAction.showDefault(null, tab); - if (forceCallback) { - callback([]); - } + callback([]); return; } @@ -359,7 +352,7 @@ keepass.associate = function(callback, tab) { return; } - keepass.getDatabaseHash((res) => { + keepass.getDatabaseHash((hash) => { if (keepass.isDatabaseClosed || !keepass.isKeePassXCAvailable) { callback([]); return; @@ -421,11 +414,22 @@ keepass.associate = function(callback, tab) { }, tab); }; -keepass.testAssociation = function(callback, tab, enableTimeout = false, triggerUnlock = false) { +keepass.testAssociation = async function(callback, tab, enableTimeout = false, triggerUnlock = false) { if (tab && page.tabs[tab.id]) { page.tabs[tab.id].errorMessage = null; } + if (!keepass.isKeePassXCAvailable && !page.settings.automaticReconnect) { + try { + keepass.connectToNative(); + await keepass.reconnect(); + } catch (err) { + keepass.handleError(tab, kpErrors.PUBLIC_KEY_NOT_FOUND); + callback(false); + return false; + } + } + keepass.getDatabaseHash((dbHash) => { if (!dbHash) { callback(false); @@ -622,8 +626,8 @@ keepass.changePublicKeys = function(tab, enableTimeout = false) { if (!keepass.verifyKeyResponse(response, key, incrementedNonce)) { if (tab && page.tabs[tab.id]) { keepass.handleError(tab, kpErrors.KEY_CHANGE_FAILED); - reject(false); } + reject(false); } else { keepass.isKeePassXCAvailable = true; console.log('Server public key: ' + nacl.util.encodeBase64(keepass.serverPublicKey)); @@ -846,10 +850,10 @@ keepass.migrateKeyRing = function() { // Change dates to numbers, for compatibilty with Chromium based browsers if (keyring) { let num = 0; - for (let keyHash in keyring) { - let key = keyring[keyHash]; - ['created', 'lastUsed'].forEach((fld) => { - let v = key[fld]; + for (const keyHash in keyring) { + const key = keyring[keyHash]; + [ 'created', 'lastUsed' ].forEach((fld) => { + const v = key[fld]; if (v instanceof Date && v.valueOf() >= 0) { key[fld] = v.valueOf(); num++; @@ -1127,25 +1131,32 @@ keepass.decrypt = function(input, nonce) { }; keepass.enableAutomaticReconnect = function() { - setInterval(() => { - if (!keepass.isKeePassXCAvailable) { - keepass.connectToNative(); - keepass.reconnect(); - } - }, 1000); + // Disable for Windows if KeePassXC is older than 2.3.4 + if (!page.settings.automaticReconnect || + (navigator.platform.toLowerCase().includes('win') && !keepass.compareVersion('2.3.4', keepass.currentKeePassXC))) { + return; + } + + if (keepass.reconnectLoop === null) { + keepass.reconnectLoop = setInterval(() => { + if (!keepass.isKeePassXCAvailable) { + keepass.connectToNative(); + keepass.reconnect().catch((e) => {}); + } + }, 1000); + } +}; + +keepass.disableAutomaticReconnect = function() { + clearInterval(keepass.reconnectLoop); + keepass.reconnectLoop = null; }; keepass.reconnect = function(callback, tab) { return new Promise((resolve, reject) => { keepass.generateNewKeyPair(); - keepass.changePublicKeys(tab).then((pkRes) => { - // Database hash should be received if the reconnection succeeded + keepass.changePublicKeys(tab, true).then((pkRes) => { keepass.getDatabaseHash((gdRes) => { - if (!gdRes) { - reject(false); - return; - } - keepass.testAssociation((response) => { keepass.isConfigured().then((configured) => { resolve(configured); @@ -1155,6 +1166,8 @@ keepass.reconnect = function(callback, tab) { }); }, tab); }, null); + }).catch((e) => { + reject(e); }); }); }; @@ -1178,7 +1191,7 @@ keepass.updateDatabase = function() { if (tabs.length) { browser.tabs.sendMessage(tabs[0].id, { action: 'check_database_hash', - hash: {old: keepass.previousDatabaseHash, new: keepass.databaseHash} + hash: { old: keepass.previousDatabaseHash, new: keepass.databaseHash } }); keepass.previousDatabaseHash = keepass.databaseHash; } diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 4db0bc4..313d8df 100755 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -10,6 +10,7 @@ const defaultSettings = { showNotifications: true, showLoginNotifications: true, saveDomainOnly: true, + automaticReconnect: true, defaultGroup: '', defaultGroupAlwaysAsk: false }; @@ -51,6 +52,9 @@ page.initSettings = function() { if (!('saveDomainOnly' in page.settings)) { page.settings.saveDomainOnly = defaultSettings.saveDomainOnly; } + if (!('automaticReconnect' in page.settings)) { + page.settings.automaticReconnect = defaultSettings.automaticReconnect; + } if (!('defaultGroup' in page.settings)) { page.settings.defaultGroup = defaultSettings.defaultGroup; } @@ -71,13 +75,13 @@ page.initOpenedTabs = function() { } // Set initial tab-ID - browser.tabs.query({ 'active': true, 'currentWindow': true }).then((t) => { - if (t.length === 0) { + browser.tabs.query({ 'active': true, 'currentWindow': true }).then((currentTabs) => { + if (currentTabs.length === 0) { resolve(); return; // For example: only the background devtools or a popup are opened } - page.currentTabId = t[0].id; - browserAction.show(null, t[0]); + page.currentTabId = currentTabs[0].id; + browserAction.show(null, currentTabs[0]); resolve(); }); }); @@ -147,31 +151,3 @@ page.removePageInformationFromNotExistingTabs = function() { }); } }; - -page.debugConsole = function() { - if (arguments.length > 1) { - console.log(page.sprintf(arguments[0], arguments)); - } else { - console.log(arguments[0]); - } -}; - -page.sprintf = function(input, args) { - return input.replace(/{(\d+)}/g, (match, number) => { - return typeof args[number] !== 'undefined' ? (typeof args[number] === 'object' ? JSON.stringify(args[number]) : args[number]) : match; - }); -}; - -page.debugDummy = function() {}; - -page.debug = page.debugDummy; - -page.setDebug = function(bool) { - if (bool) { - page.debug = page.debugConsole; - return 'Debug mode enabled'; - } else { - page.debug = page.debugDummy; - return 'Debug mode disabled'; - } -}; diff --git a/keepassxc-browser/content/autocomplete.js b/keepassxc-browser/content/autocomplete.js new file mode 100644 index 0000000..a91b63c --- /dev/null +++ b/keepassxc-browser/content/autocomplete.js @@ -0,0 +1,188 @@ +'use strict'; + +var kpxcAutocomplete = {}; +kpxcAutocomplete.elements = []; + +kpxcAutocomplete.create = function(input, showListInstantly = false) { + let _index = -1; + + input.addEventListener('click', function(e) { + if (!e.isTrusted) { + return; + } + + if (input.value !== '') { + input.select(); + } + showList(input); + }); + + input.addEventListener('keydown', keyPress); + input.setAttribute('autocomplete', 'off'); + + if (showListInstantly) { + showList(input); + } + + function showList(input) { + closeList(); + const div = kpxcUI.createElement('div', 'kpxcAutocomplete-items', { 'id': 'kpxcAutocomplete-list' }); + + // Element position + const rect = input.getBoundingClientRect(); + div.style.top = String((rect.top + document.body.scrollTop) + input.offsetHeight) + 'px'; + div.style.left = String((rect.left + document.body.scrollLeft)) + 'px'; + div.style.minWidth = String(input.offsetWidth) + 'px'; + div.style.zIndex = '2147483646'; + document.body.append(div); + + for (const c of kpxcAutocomplete.elements) { + const item = document.createElement('div'); + item.textContent += c.label; + const itemInput = kpxcUI.createElement('input', '', { 'type': 'hidden', 'value': c.value }); + item.append(itemInput); + item.addEventListener('click', function(e) { + if (!e.isTrusted) { + return; + } + + // Save index for combination.loginId + const index = Array.prototype.indexOf.call(e.currentTarget.parentElement.childNodes, e.currentTarget); + input.value = this.getElementsByTagName('input')[0].value; + fillPassword(input.value, index); + closeList(); + input.focus(); + }); + + // These events prevent the double hover effect if both keyboard and mouse are used + item.addEventListener('mouseover', function(e) { + removeItem(getAllItems()); + item.classList.add('kpxcAutocomplete-active'); + _index = Array.from(div.childNodes).indexOf(item); + }); + item.addEventListener('mouseout', function(e) { + item.classList.remove('kpxcAutocomplete-active'); + }); + + div.appendChild(item); + } + + // Activate the first item automatically + const items = getAllItems(); + _index = 0; + activateItem(items); + }; + + function activateItem(item) { + if (!item || item.length === 0) { + return; + } + + removeItem(item); + if (_index >= item.length) { + _index = 0; + } + + if (_index < 0) { + _index = item.length - 1; + } + + if (item[_index] !== undefined) { + item[_index].classList.add('kpxcAutocomplete-active'); + } + }; + + function removeItem(items) { + for (const item of items) { + item.classList.remove('kpxcAutocomplete-active'); + } + }; + + function closeList(elem) { + const items = document.getElementsByClassName('kpxcAutocomplete-items'); + for (const item of items) { + if (elem !== item && input) { + item.parentNode.removeChild(item); + } + } + }; + + function getAllItems() { + const list = document.getElementById('kpxcAutocomplete-list'); + if (!list) { + return []; + } + return list.getElementsByTagName('div'); + }; + + /** + * Keyboard shortcuts for autocomplete menu: + * - ArrowDown shows the list or selects item below, or the first item (last is active) + * - ArrowUp selects item above, or the last item (first is active) + * - Enter or Tab selects the item + * - Backspace and Delete shows the list if input field is empty. First item is activated + */ + function keyPress(e) { + if (!e.isTrusted) { + return; + } + + const item = getAllItems(); + if (e.key === 'ArrowDown') { + // If the list is now shown, show it + if (item.length === 0) { + _index = -1; + showList(input); + } else { + // Activate next item + ++_index; + activateItem(item); + } + } else if (e.key === 'ArrowUp') { + --_index; + activateItem(item); + } else if (e.key === 'Enter' || e.key === 'Tab') { + if (input.value === '' && e.key === 'Enter') { + e.preventDefault(); + } + + if (_index >= 0 && item && item[_index] !== undefined) { + input.value = e.currentTarget.value; + fillPassword(input.value, _index); + closeList(); + } + } else if (e.key === 'Escape') { + closeList(); + } else if ((e.key === 'Backspace' || e.key === 'Delete') && input.value === '') { + // Show menu when input field has no value and backspace is pressed + _index = -1; + showList(input); + } + }; + + function fillPassword(value, index) { + const fieldId = input.getAttribute('data-kpxc-id'); + kpxcFields.prepareId(fieldId); + const combination = kpxcFields.getCombination('username', fieldId); + combination.loginId = index; + + kpxc.fillInCredentials(combination, false, false); + input.setAttribute('fetched', true); + }; + + // Detect click outside autocomplete + document.addEventListener('click', function(e) { + if (!e.isTrusted) { + return; + } + + const list = document.getElementById('kpxcAutocomplete-list'); + if (!list) { + return; + } + + if (e.target !== input && (e.target.nodeName !== input.nodeName)) { + closeList(e.target); + } + }); +}; diff --git a/keepassxc-browser/content/define.js b/keepassxc-browser/content/define.js new file mode 100644 index 0000000..69b0e3a --- /dev/null +++ b/keepassxc-browser/content/define.js @@ -0,0 +1,382 @@ +'use strict'; + +var kpxcDefine = {}; + +kpxcDefine.selection = { + username: null, + password: null, + fields: [] +}; +kpxcDefine.eventFieldClick = null; +kpxcDefine.dialog = null; +kpxcDefine.startPosX = 0; +kpxcDefine.startPosY = 0; +kpxcDefine.diffX = 0; +kpxcDefine.diffY = 0; +kpxcDefine.keyDown = null; + +kpxcDefine.init = function() { + const backdrop = kpxcUI.createElement('div', 'kpxcDefine-modal-backdrop', { 'id': 'kpxcDefine-backdrop' }); + const chooser = kpxcUI.createElement('div', '', { 'id': 'kpxcDefine-fields' }); + const description = kpxcUI.createElement('div', '', { 'id': 'kpxcDefine-description' }); + + backdrop.append(description); + document.body.append(backdrop); + document.body.append(chooser); + + kpxcFields.getAllFields(); + kpxcFields.prepareVisibleFieldsWithID('select'); + + kpxcDefine.initDescription(); + kpxcDefine.resetSelection(); + kpxcDefine.prepareStep1(); + kpxcDefine.markAllUsernameFields('#kpxcDefine-fields'); + + kpxcDefine.dialog = $('#kpxcDefine-description');; + kpxcDefine.dialog.onmousedown = function(e) { + kpxcDefine.mouseDown(e); + }; + + document.addEventListener('keydown', kpxcDefine.keyDown); +}; + +kpxcDefine.close = function() { + $('#kpxcDefine-backdrop').remove(); + $('#kpxcDefine-fields').remove(); + document.removeEventListener('keydown', kpxcDefine.keyDown); +}; + +kpxcDefine.mouseDown = function(e) { + kpxcDefine.selected = kpxcDefine.dialog; + kpxcDefine.startPosX = e.clientX; + kpxcDefine.startPosY = e.clientY; + kpxcDefine.diffX = kpxcDefine.startPosX - kpxcDefine.dialog.offsetLeft; + kpxcDefine.diffY = kpxcDefine.startPosY - kpxcDefine.dialog.offsetTop; + return false; +}; + +kpxcDefine.initDescription = function() { + const description = $('#kpxcDefine-description'); + const h1 = kpxcUI.createElement('div', '', { 'id': 'kpxcDefine-chooser-headline' }); + const help = kpxcUI.createElement('div', 'kpxcDefine-chooser-help', { 'id': 'kpxcDefine-help' }); + + // Show keyboard shortcuts help text + const keyboardHelp = kpxcUI.createElement('div', 'kpxcDefine-keyboardHelp', {}, `${tr('optionsKeyboardShortcutsHeader')}:`); + keyboardHelp.style.marginBottom = '5px'; + keyboardHelp.appendMultiple(document.createElement('br'), kpxcUI.createElement('kbd', '', {}, 'Escape'), ' ' + tr('defineDismiss')); + keyboardHelp.appendMultiple(document.createElement('br'), kpxcUI.createElement('kbd', '', {}, 'S'), ' ' + tr('defineSkip')); + keyboardHelp.appendMultiple(document.createElement('br'), kpxcUI.createElement('kbd', '', {}, 'A'), ' ' + tr('defineAgain')); + keyboardHelp.appendMultiple(document.createElement('br'), kpxcUI.createElement('kbd', '', {}, 'C'), ' ' + tr('defineConfirm')); + keyboardHelp.appendMultiple(document.createElement('br'), kpxcUI.createElement('kbd', '', {}, 'M'), ' ' + tr('defineMore')); + keyboardHelp.appendMultiple(document.createElement('br'), kpxcUI.createElement('kbd', '', {}, 'D'), ' ' + tr('defineDiscard')); + + description.appendMultiple(h1, help, keyboardHelp); + + const buttonDismiss = kpxcUI.createElement('button', 'kpxc-button kpxc-red-button', { 'id': 'kpxcDefine-btn-dismiss' }, tr('defineDismiss')); + buttonDismiss.addEventListener('click', kpxcDefine.close); + + const buttonSkip = kpxcUI.createElement('button', 'kpxc-button kpxc-orange-button', { 'id': 'kpxcDefine-btn-skip' }, tr('defineSkip')); + buttonSkip.style.marginRight = '5px'; + buttonSkip.addEventListener('click', kpxcDefine.skip); + + const buttonMore = kpxcUI.createElement('button', 'kpxc-button kpxc-orange-button', { 'id': 'kpxcDefine-btn-more' }, tr('defineMore')); + buttonMore.style.marginRight = '5px'; + buttonMore.style.marginLeft = '5px'; + buttonMore.addEventListener('click', kpxcDefine.more); + + const buttonAgain = kpxcUI.createElement('button', 'kpxc-button kpxc-blue-button', { 'id': 'kpxcDefine-btn-again' }, tr('defineAgain')); + buttonAgain.style.marginRight = '5px'; + buttonAgain.addEventListener('click', kpxcDefine.again); + + const buttonConfirm = kpxcUI.createElement('button', 'kpxc-button kpxc-green-button', { 'id': 'kpxcDefine-btn-confirm' }, tr('defineConfirm')); + buttonConfirm.style.marginRight = '15px'; + buttonConfirm.style.display = 'none'; + buttonConfirm.addEventListener('click', kpxcDefine.confirm); + + description.appendMultiple(buttonConfirm, buttonSkip, buttonMore, buttonAgain, buttonDismiss); + + const location = kpxc.getDocumentLocation(); + if (kpxc.settings['defined-custom-fields'] && kpxc.settings['defined-custom-fields'][location]) { + const div = kpxcUI.createElement('div', 'alreadySelected', {}); + const defineDiscard = kpxcUI.createElement('p', '', {}, tr('defineAlreadySelected')); + const buttonDiscard = kpxcUI.createElement('button', 'kpxc-button kpxc-red-button', { 'id': 'kpxcDefine-btn-discard' }, tr('defineDiscard')); + buttonDiscard.style.marginTop = '5px'; + buttonDiscard.addEventListener('click', kpxcDefine.discard); + + div.appendMultiple(defineDiscard, buttonDiscard); + description.append(div); + } +}; + +kpxcDefine.resetSelection = function() { + kpxcDefine.selection = { + username: null, + password: null, + fields: [] + }; + + const fields = $('#kpxcDefine-fields'); + if (fields) { + fields.textContent = ''; + } +}; + +kpxcDefine.isFieldSelected = function(kpxcId) { + if (kpxcId) { + return ( + kpxcId === kpxcDefine.selection.username || + kpxcId === kpxcDefine.selection.password || + kpxcId in kpxcDefine.selection.fields + ); + } + return false; +}; + +kpxcDefine.markAllUsernameFields = function(chooser) { + kpxcDefine.eventFieldClick = function(e, elem) { + const field = elem || e.currentTarget; + kpxcDefine.selection.username = field.getAttribute('data-kpxc-id'); + field.classList.add('kpxcDefine-fixed-username-field'); + field.textContent = tr('username'); + field.onclick = null; + kpxcDefine.prepareStep2(); + kpxcDefine.markAllPasswordFields('#kpxcDefine-fields'); + }; + kpxcDefine.markFields(chooser, kpxcFields.inputQueryPattern); +}; + +kpxcDefine.markAllPasswordFields = function(chooser, more) { + kpxcDefine.eventFieldClick = function(e, elem) { + const field = elem || e.currentTarget; + kpxcDefine.selection.password = field.getAttribute('data-kpxc-id'); + field.classList.add('kpxcDefine-fixed-password-field'); + field.textContent = tr('password'); + field.onclick = null; + kpxcDefine.prepareStep3(); + kpxcDefine.markAllStringFields('#kpxcDefine-fields'); + }; + if (more) { + kpxcDefine.markFields(chooser, kpxcFields.inputQueryPattern); + } else { + kpxcDefine.markFields(chooser, 'input[type=\'password\']'); + } +}; + +kpxcDefine.markAllStringFields = function(chooser) { + kpxcDefine.eventFieldClick = function(e, elem) { + const field = elem || e.currentTarget; + const value = field.getAttribute('data-kpxc-id'); + kpxcDefine.selection.fields[value] = true; + + const count = Object.keys(kpxcDefine.selection.fields).length; + field.classList.add('kpxcDefine-fixed-string-field'); + field.textContent = tr('defineStringField') + String(count); + field.onclick = null; + }; + kpxcDefine.markFields(chooser, kpxcFields.inputQueryPattern + ', select'); +}; + +kpxcDefine.markFields = function(chooser, pattern) { + let index = 1; + let firstInput = null; + const inputs = document.querySelectorAll(pattern); + + for (const i of inputs) { + if (kpxcDefine.isFieldSelected(i.getAttribute('data-kpxc-id'))) { + return true; + } + + if (kpxcFields.isVisible(i)) { + const field = kpxcUI.createElement('div', 'kpxcDefine-fixed-field', { 'data-kpxc-id': i.getAttribute('data-kpxc-id') }); + const rect = i.getBoundingClientRect(); + field.style.top = rect.top + 'px'; + field.style.left = rect.left + 'px'; + field.style.width = rect.width + 'px'; + field.style.height = rect.height + 'px'; + field.textContent = String(index); + field.onclick = function(e) { + kpxcDefine.eventFieldClick(e); + }; + field.onmouseenter = function() { + field.classList.add('kpxcDefine-fixed-hover-field'); + }; + field.onmouseleave = function() { + field.classList.remove('kpxcDefine-fixed-hover-field'); + }; + i.onfocus = function() { + field.classList.add('kpxcDefine-fixed-hover-field'); + } + i.onblur = function() { + field.classList.remove('kpxcDefine-fixed-hover-field'); + }; + const elem = $(chooser); + if (elem) { + elem.append(field); + firstInput = field; + ++index; + } + } + } + + if (firstInput) { + firstInput.focus(); + } +}; + +kpxcDefine.prepareStep1 = function() { + const help = $('#kpxcDefine-help'); + help.style.marginBottom = '10px'; + help.textContent = tr('defineKeyboardText'); + + removeContent('div#kpxcDefine-fixed-field'); + $('#kpxcDefine-chooser-headline').textContent = tr('defineChooseUsername'); + kpxcDefine.dataStep = 1; + $('#kpxcDefine-btn-skip').style.display = 'inline-block'; + $('#kpxcDefine-btn-confirm').style.display = 'none'; + $('#kpxcDefine-btn-again').style.display = 'none'; + $('#kpxcDefine-btn-more').style.display = 'none'; +}; + +kpxcDefine.prepareStep2 = function() { + const help = $('#kpxcDefine-help'); + help.style.marginBottom = '10px'; + help.textContent = tr('defineKeyboardText'); + + removeContent('div.kpxcDefine-fixed-field:not(.kpxcDefine-fixed-username-field)'); + $('#kpxcDefine-chooser-headline').textContent = tr('defineChoosePassword'); + kpxcDefine.dataStep = 2; + $('#kpxcDefine-btn-again').style.display = 'inline-block'; + $('#kpxcDefine-btn-more').style.display = 'inline-block'; +}; + +kpxcDefine.prepareStep3 = function() { + $('#kpxcDefine-help').style.marginBottom = '10px'; + $('#kpxcDefine-help').textContent = tr('defineHelpText'); + + removeContent('div.kpxcDefine-fixed-field:not(.kpxcDefine-fixed-username-field):not(.kpxcDefine-fixed-password-field)'); + $('#kpxcDefine-chooser-headline').textContent = tr('defineConfirmSelection'); + kpxcDefine.dataStep = 3; + $('#kpxcDefine-btn-skip').style.display = 'none'; + $('#kpxcDefine-btn-more').style.display = 'none'; + $('#kpxcDefine-btn-again').style.display = 'inline-block'; + $('#kpxcDefine-btn-confirm').style.display = 'inline-block'; +}; + +kpxcDefine.skip = function() { + if (kpxcDefine.dataStep === 1) { + kpxcDefine.selection.username = null; + kpxcDefine.prepareStep2(); + kpxcDefine.markAllPasswordFields('#kpxcDefine-fields'); + } else if (kpxcDefine.dataStep === 2) { + kpxcDefine.selection.password = null; + kpxcDefine.prepareStep3(); + kpxcDefine.markAllStringFields('#kpxcDefine-fields'); + } +}; + +kpxcDefine.again = function() { + kpxcDefine.resetSelection(); + kpxcDefine.prepareStep1(); + kpxcDefine.markAllUsernameFields('#kpxcDefine-fields'); +}; + +kpxcDefine.more = function() { + if (kpxcDefine.dataStep === 2) { + kpxcDefine.prepareStep2(); + kpxcDefine.markAllPasswordFields('#kpxcDefine-fields', true); + } +}; + +kpxcDefine.confirm = function() { + if (kpxcDefine.dataStep !== 3) { + return; + } + + if (!kpxc.settings['defined-custom-fields']) { + kpxc.settings['defined-custom-fields'] = {}; + } + + if (kpxcDefine.selection.username) { + kpxcDefine.selection.username = kpxcFields.prepareId(kpxcDefine.selection.username); + } + + if (kpxcDefine.selection.password) { + kpxcDefine.selection.password = kpxcFields.prepareId(kpxcDefine.selection.password); + } + + const fieldIds = []; + const fieldKeys = Object.keys(kpxcDefine.selection.fields); + for (const i of fieldKeys) { + fieldIds.push(kpxcFields.prepareId(i)); + } + + const location = kpxc.getDocumentLocation(); + kpxc.settings['defined-custom-fields'][location] = { + username: kpxcDefine.selection.username, + password: kpxcDefine.selection.password, + fields: fieldIds + }; + + browser.runtime.sendMessage({ + action: 'save_settings', + args: [ kpxc.settings ] + }); + + kpxcDefine.close(); +}; + +kpxcDefine.discard = function() { + const location = kpxc.getDocumentLocation(); + delete kpxc.settings['defined-custom-fields'][location]; + + browser.runtime.sendMessage({ + action: 'save_settings', + args: [ kpxc.settings ] + }); + + browser.runtime.sendMessage({ + action: 'load_settings' + }); + + $('div.alreadySelected').remove(); +}; + +// Handle the keyboard events +kpxcDefine.keyDown = function(e) { + if (e.key === 'Escape') { + kpxcDefine.close(); + } else if (e.key === 'Enter') { + e.preventDefault(); + } else if (e.keyCode >= 49 && e.keyCode <= 57) { + // Select input field by number + e.preventDefault(); + const index = e.keyCode - 48; + const inputFields = document.querySelectorAll('div.kpxcDefine-fixed-field:not(.kpxcDefine-fixed-username-field):not(.kpxcDefine-fixed-password-field)'); + + if (inputFields.length >= index) { + kpxcDefine.eventFieldClick(e, inputFields[index - 1]); + } + } else if (e.key === 's') { + e.preventDefault(); + kpxcDefine.skip(); + } else if (e.key === 'a') { + e.preventDefault(); + kpxcDefine.again(); + } else if (e.key === 'c') { + e.preventDefault(); + kpxcDefine.confirm(); + } else if (e.key === 'm') { + e.preventDefault(); + kpxcDefine.more(); + } else if (e.key === 'd') { + e.preventDefault(); + kpxcDefine.discard(); + } +}; + +const removeContent = function(pattern) { + const elems = document.querySelectorAll(pattern); + for (const e of elems) { + e.remove(); + } +}; diff --git a/keepassxc-browser/content/keepassxc-browser.js b/keepassxc-browser/content/keepassxc-browser.js new file mode 100755 index 0000000..7eb916d --- /dev/null +++ b/keepassxc-browser/content/keepassxc-browser.js @@ -0,0 +1,1496 @@ +'use strict'; + +// contains already called method names +var _called = {}; +_called.retrieveCredentials = false; +_called.clearLogins = false; +_called.manualFillRequested = 'none'; +let _loginId = -1; +let _singleInputEnabledForPage = false; +const _maximumInputs = 100; + +// Count of detected form fields on the page +var _detectedFields = 0; + +// Element id's containing input fields detected by MutationObserver +var _observerIds = []; + +// Document URL +let _documentURL = document.location.href; + +// These are executed in each frame +browser.runtime.onMessage.addListener(function(req, sender) { + if ('action' in req) { + if (req.action === 'fill_user_pass_with_specific_login') { + if (kpxc.credentials[req.id]) { + let combination = null; + if (kpxc.u) { + kpxc.setValueWithChange(kpxc.u, kpxc.credentials[req.id].login); + combination = kpxcFields.getCombination('username', kpxc.u); + browser.runtime.sendMessage({ + action: 'page_set_login_id', args: [ req.id ] + }); + kpxc.u.focus(); + } + if (kpxc.p) { + kpxc.setValueWithChange(kpxc.p, kpxc.credentials[req.id].password); + browser.runtime.sendMessage({ + action: 'page_set_login_id', args: [ req.id ] + }); + combination = kpxcFields.getCombination('password', kpxc.p); + } + + let list = []; + if (kpxc.fillInStringFields(combination.fields, kpxc.credentials[req.id].stringFields, list)) { + kpxcForm.destroy(false, { 'password': list.list[0], 'username': list.list[1] }); + } + } + } else if (req.action === 'fill_username_password') { + _called.manualFillRequested = 'both'; + kpxc.receiveCredentialsIfNecessary().then((response) => { + kpxc.fillInFromActiveElement(false); + }); + } else if (req.action === 'fill_password') { + _called.manualFillRequested = 'pass'; + kpxc.receiveCredentialsIfNecessary().then((response) => { + kpxc.fillInFromActiveElement(false, true); // passOnly to true + }); + } else if (req.action === 'fill_totp') { + kpxc.receiveCredentialsIfNecessary().then((response) => { + kpxc.fillInFromActiveElementTOTPOnly(false); + }); + } else if (req.action === 'clear_credentials') { + kpxcEvents.clearCredentials(); + return Promise.resolve(); + } else if (req.action === 'activated_tab') { + kpxcEvents.triggerActivatedTab(); + return Promise.resolve(); + } else if (req.action === 'ignore_site') { + kpxc.ignoreSite(req.args); + } else if (req.action === 'check_database_hash' && 'hash' in req) { + kpxc.detectDatabaseChange(req.hash); + } else if (req.action === 'activate_password_generator') { + kpxc.initPasswordGenerator(kpxcFields.getAllFields()); + } else if (req.action === 'remember_credentials') { + kpxc.contextMenuRememberCredentials(); + } else if (req.action === 'choose_credential_fields') { + kpxcDefine.init(); + } else if (req.action === 'redetect_fields') { + browser.runtime.sendMessage({ + action: 'load_settings', + }).then((response) => { + kpxc.settings = response; + kpxc.initCredentialFields(true); + }); + } else if (req.action === 'show_password_generator') { + kpxcPassword.trigger(); +} + } +}); + +function _f(fieldId) { + const inputs = document.querySelectorAll('input[data-kpxc-id=\'' + fieldId + '\']'); + return inputs.length > 0 ? inputs[0] : null; +} + +function _fs(fieldId) { + const inputs = document.querySelectorAll('input[data-kpxc-id=\'' + fieldId + '\'], select[data-kpxc-id=\'' + fieldId + '\']'); + return inputs.length > 0 ? inputs[0] : null; +} + + +var kpxcForm = {}; + +kpxcForm.init = function(form, credentialFields) { + if (!form.getAttribute('kpxcForm-initialized') && (credentialFields.password || credentialFields.username)) { + form.setAttribute('kpxcForm-initialized', true); + kpxcForm.setInputFields(form, credentialFields); + form.addEventListener('submit', kpxcForm.onSubmit); + } +}; + +kpxcForm.destroy = function(form, credentialFields) { + if (form === false && credentialFields) { + const field = _f(credentialFields.password) || _f(credentialFields.username); + if (field) { + form = field.closest('form'); + } + } + + if (form && form.length > 0) { + form.onsubmit = null; + } +}; + +kpxcForm.setInputFields = function(form, credentialFields) { + form.setAttribute('kpxcUsername', credentialFields.username); + form.setAttribute('kpxcPassword', credentialFields.password); +}; + +kpxcForm.onSubmit = function() { + const usernameId = this.getAttribute('kpxcUsername'); + const passwordId = this.getAttribute('kpxcPassword'); + + let usernameValue = ''; + let passwordValue = ''; + + const usernameField = _f(usernameId); + const passwordField = _f(passwordId); + + if (usernameField) { + usernameValue = usernameField.value; + } + if (passwordField) { + passwordValue = passwordField.value; + } + + kpxc.rememberCredentials(usernameValue, passwordValue); +}; + + +var kpxcFields = {}; + +kpxcFields.inputQueryPattern = 'input[type=\'text\'], input[type=\'email\'], input[type=\'password\'], input[type=\'tel\'], input[type=\'number\'], input:not([type])'; +// Unique number as new IDs for input fields +kpxcFields.uniqueNumber = 342845638; +// Objects with combination of username + password fields +kpxcFields.combinations = []; + +kpxcFields.setUniqueId = function(field) { + if (field && !field.getAttribute('data-kpxc-id')) { + // Use ID of field if it is unique + const fieldId = field.getAttribute('id'); + if (fieldId) { + const foundIds = document.querySelectorAll('input#' + kpxcFields.prepareId(fieldId)); + if (foundIds.length === 1) { + field.setAttribute('data-kpxc-id', fieldId); + return; + } + } + + // Create own ID if no ID is set for this field + kpxcFields.uniqueNumber += 1; + field.setAttribute('data-kpxc-id', 'kpxcpw' + String(kpxcFields.uniqueNumber)); + } +}; + +kpxcFields.prepareId = function(id) { + return id.replace(/[:#.,\[\]\(\)' "]/g, function(m) { + return '\\' + m; + }); +}; + +/** + * Returns the first parent element satifying the {@code predicate} mapped by {@code resultFn} or else {@code defaultVal}. + * @param {HTMLElement} element The start element (excluded, starting with the parents) + * @param {function} predicate Matcher for the element to find, type (HTMLElement) => boolean + * @param {function} resultFn Callback function of type (HTMLElement) => {*} called for the first matching element + * @param {fun} defaultValFn Fallback return value supplier, if no element matching the predicate can be found + */ +kpxcFields.traverseParents = function(element, predicate, resultFn = () => true, defaultValFn = () => false) { + for (let f = element.parentElement; f !== null; f = f.parentElement) { + if (predicate(f)) { + return resultFn(f); + } + } + return defaultValFn(); +}; + +kpxcFields.getOverflowHidden = function(field) { + return kpxcFields.traverseParents(field, f => f.style.overflow === 'hidden'); +}; + +// Checks if input field is a search field. Attributes or form action containing 'search', or parent element holding +// role="search" will be identified as a search field. +kpxcFields.isSearchField = function(target) { + const attributes = target.attributes; + + // Check element attributes + for (const attr of attributes) { + if ((attr.value && (attr.value.toLowerCase().includes('search')) || attr.value === 'q')) { + return true; + } + } + + // Check closest form + const closestForm = target.closest('form'); + if (closestForm) { + // Check form action + const formAction = closestForm.getAttribute('action'); + if (formAction && (formAction.toLowerCase().includes('search') && + !formAction.toLowerCase().includes('research'))) { + return true; + } + + // Check form class and id + const closestFormId = closestForm.getAttribute('id'); + const closestFormClass = closestForm.className; + if (closestFormClass && (closestForm.className.toLowerCase().includes('search') || + (closestFormId && closestFormId.toLowerCase().includes('search') && !closestFormId.toLowerCase().includes('research')))) { + return true; + } + } + + // Check parent elements for role="search" + const roleFunc = f => f.getAttribute('role'); + const roleValue = kpxcFields.traverseParents(target, roleFunc, roleFunc, () => null); + if (roleValue && roleValue === 'search') { + return true; + } + + return false; +}; + +kpxcFields.isVisible = function(field) { + const rect = field.getBoundingClientRect(); + + // Check CSS visibility + const fieldStyle = getComputedStyle(field); + if (fieldStyle.visibility && (fieldStyle.visibility === 'hidden' || fieldStyle.visibility === 'collapse')) { + return false; + } + + // Check element position and size + if (rect.x < 0 || rect.y < 0 || rect.width < 8 || rect.height < 8) { + return false; + } + + return true; +}; + +kpxcFields.getAllFields = function() { + const fields = []; + const inputs = kpxcObserverHelper.getInputs(document); + for (const i of inputs) { + if (kpxcFields.isVisible(i) && !kpxcFields.isSearchField(i)) { + kpxcFields.setUniqueId(i); + fields.push(i); + } + } + + _detectedFields = fields.length; + return fields; +}; + +kpxcFields.prepareVisibleFieldsWithID = function(pattern) { + const patterns = document.querySelectorAll(pattern); + for (const i of patterns) { + if (kpxcFields.isVisible(i) && i.style.visibility !== 'hidden' && i.style.visibility !== 'collapsed') { + kpxcFields.setUniqueId(i); + } + } +}; + +kpxcFields.getAllCombinations = function(inputs) { + const fields = []; + let uField = null; + + for (const i of inputs) { + if (i) { + if (i.getAttribute('type') && i.getAttribute('type').toLowerCase() === 'password') { + const uId = (!uField || uField.length < 1) ? null : uField.getAttribute('data-kpxc-id'); + + const combination = { + username: uId, + password: i.getAttribute('data-kpxc-id') + }; + fields.push(combination); + + // Reset selected username field + uField = null; + } else { + // Username field + uField = i; + } + } + } + + if (_singleInputEnabledForPage && fields.length === 0 && uField) { + const combination = { + username: uField.getAttribute('data-kpxc-id'), + password: null + }; + fields.push(combination); + } + + return fields; +}; + +kpxcFields.getCombination = function(givenType, fieldId) { + if (kpxcFields.combinations.length === 0) { + if (kpxcFields.useDefinedCredentialFields()) { + return kpxcFields.combinations[0]; + } + } + // Use defined credential fields (already loaded into combinations) + const location = kpxc.getDocumentLocation(); + if (kpxc.settings['defined-custom-fields'] && kpxc.settings['defined-custom-fields'][location]) { + return kpxcFields.combinations[0]; + } + + for (let c of kpxcFields.combinations) { + if (c[givenType] === fieldId) { + return c; + } + } + + // Find new combination + let combination = { + username: null, + password: null + }; + + let newCombi = false; + if (givenType === 'username') { + const passwordField = kpxcFields.getPasswordField(fieldId, true); + let passwordId = null; + if (passwordField && passwordField.value.length > 0) { + passwordId = kpxcFields.prepareId(passwordField.getAttribute('data-kpxc-id')); + } + combination = { + username: fieldId, + password: passwordId + }; + newCombi = true; + } else if (givenType === 'password') { + const usernameField = kpxcFields.getUsernameField(fieldId, true); + let usernameId = null; + if (usernameField && usernameField.value.length > 0) { + usernameId = kpxcFields.prepareId(usernameField.getAttribute('data-kpxc-id')); + } + combination = { + username: usernameId, + password: fieldId + }; + newCombi = true; + } + + if (combination.username || combination.password) { + kpxcFields.combinations.push(combination); + } + + if (combination.username) { + if (kpxc.credentials.length > 0) { + kpxc.preparePageForMultipleCredentials(kpxc.credentials); + } + } + + if (newCombi) { + combination.isNew = true; + } + return combination; +}; + +/** +* Return the username field or null if it not exists +*/ +kpxcFields.getUsernameField = function(passwordId, checkDisabled) { + const passwordField = _f(passwordId); + if (!passwordField) { + return null; + } + + const form = passwordField.closest('form'); + let usernameField = null; + + // Search all inputs on this one form + if (form) { + const inputs = form.querySelectorAll(kpxcFields.inputQueryPattern); + for (const i of inputs) { + kpxcFields.setUniqueId(i); + if (i.getAttribute('data-kpxc-id') === passwordId) { + return false; // Break + } + + if (i.getAttribute('type') && i.getAttribute('type').toLowerCase() === 'password') { + return true; // Continue + } + + usernameField = i; + } + } else { + // Search all inputs on page + const inputs = kpxcFields.getAllFields(); + kpxc.initPasswordGenerator(inputs); + for (const i of inputs) { + if (i.getAttribute('data-kpxc-id') === passwordId) { + break; + } + + if (i.getAttribute('type') && i.getAttribute('type').toLowerCase() === 'password') { + continue; + } + + usernameField = i; + } + } + + if (usernameField && !checkDisabled) { + const usernameId = usernameField.getAttribute('data-kpxc-id'); + // Check if usernameField is already used by another combination + for (const c of kpxcFields.combinations) { + if (c.username === usernameId) { + usernameField = null; + break; + } + } + } + + kpxcFields.setUniqueId(usernameField); + return usernameField; +}; + +/** +* Return the password field or null if it not exists +*/ +kpxcFields.getPasswordField = function(usernameId, checkDisabled) { + const usernameField = _f(usernameId); + if (!usernameField) { + return null; + } + + const form = usernameField.closest('form'); + let passwordField = null; + + // Search all inputs on this one form + if (form) { + const inputs = form.querySelectorAll('input[type=\'password\']'); + if (inputs.length > 0) { + passwordField = inputs[0]; + } + if (passwordField && passwordField.length < 1) { + passwordField = null; + } + + if (kpxc.settings.usePasswordGenerator) { + kpxcPassword.init(); + kpxcPassword.initField(passwordField); + } + } else { + // Search all inputs on page + const inputs = kpxcFields.getAllFields(); + kpxc.initPasswordGenerator(inputs); + + let active = false; + for (const i of inputs) { + if (i.getAttribute('data-kpxc-id') === usernameId) { + active = true; + } + if (active && i.getAttribute('type') && i.getAttribute('type').toLowerCase() === 'password') { + passwordField = i; + break; + } + } + } + + if (passwordField && !checkDisabled) { + const passwordId = passwordField.getAttribute('data-kpxc-id'); + // Check if passwordField is already used by another combination + for (const c of kpxcFields.combinations) { + if (c.password === passwordId) { + passwordField = null; + break; + } + } + } + + kpxcFields.setUniqueId(passwordField); + return passwordField; +}; + +kpxcFields.prepareCombinations = function(combinations) { + for (const c of combinations) { + const pwField = _f(c.password); + // Needed for auto-complete: don't overwrite manually filled-in password field + if (pwField && !pwField.getAttribute('kpxcFields-onChange')) { + pwField.setAttribute('kpxcFields-onChange', true); + pwField.onchange = function() { + this.setAttribute('unchanged', false); + } + } + + // Initialize form-submit for remembering credentials + const fieldId = c.password || c.username; + const field = _f(fieldId); + if (field) { + const form = field.closest('form'); + if (form && form.length > 0) { + kpxcForm.init(form, c); + } + } + } +}; + +kpxcFields.useDefinedCredentialFields = function() { + const location = kpxc.getDocumentLocation(); + if (kpxc.settings['defined-credential-fields'] && kpxc.settings['defined-credential-fields'][location]) { + const creds = kpxc.settings['defined-credential-fields'][location]; + + let found = _f(creds.username) || _f(creds.password); + for (const i of creds.fields) { + if (_fs(i)) { + found = true; + break; + } + } + + if (found) { + const fields = { + username: creds.username, + password: creds.password, + fields: creds.fields + }; + kpxcFields.combinations = []; + kpxcFields.combinations.push(fields); + + return true; + } + } + + return false; +}; + +var kpxcObserverHelper = {}; +kpxcObserverHelper.inputTypes = [ + 'text', + 'email', + 'password', + 'tel', + 'number', + null // Input field can be without any type. Include these to the list. +]; + +// Ignores all nodes that doesn't contain elements +kpxcObserverHelper.ignoredNode = function(target) { + if (target.nodeType === Node.ATTRIBUTE_NODE || + target.nodeType === Node.TEXT_NODE || + target.nodeType === Node.CDATA_SECTION_NODE || + target.nodeType === Node.PROCESSING_INSTRUCTION_NODE || + target.nodeType === Node.COMMENT_NODE || + target.nodeType === Node.DOCUMENT_TYPE_NODE || + target.nodeType === Node.NOTATION_NODE) { + return true; + } + return false; +}; + +kpxcObserverHelper.getInputs = function(target) { + // Ignores target element if it's not an element node + if (kpxcObserverHelper.ignoredNode(target)) { + return []; + } + + // Filter out any input fields with type 'hidden' right away + const inputFields = []; + Array.from(target.getElementsByTagName('input')).forEach((e) => { + if (e.type !== 'hidden') { + inputFields.push(e); + } + }); + + // Do not allow more visible inputs than _maximumInputs (default value: 100) + if (inputFields.length === 0 || inputFields.length > _maximumInputs) { + return []; + } + + // Only include input fields that match with kpxcObserverHelper.inputTypes + const inputs = []; + for (const i of inputFields) { + let type = i.getAttribute('type'); + if (type) { + type = type.toLowerCase(); + } + + if (kpxcObserverHelper.inputTypes.includes(type)) { + inputs.push(i); + } + } + return inputs; +}; + +kpxcObserverHelper.getId = function(target) { + return target.classList.length === 0 ? target.id : target.classList; +}; + +kpxcObserverHelper.ignoredElement = function(target) { + // Ignore elements that do not have a className (including SVG) + if (typeof target.className !== 'string') { + return true; + } + + // Ignore KeePassXC-Browser classes + if (target.className && target.className !== undefined && + (target.className.includes('kpxc') || target.className.includes('ui-helper'))) { + return true; + } + + return false; +}; + +kpxcObserverHelper.handleObserverAdd = function(target) { + if (kpxcObserverHelper.ignoredElement(target)) { + return; + } + + const inputs = kpxcObserverHelper.getInputs(target); + if (inputs.length === 0) { + return; + } + + const neededLength = _detectedFields === 1 ? 0 : 1; + const id = kpxcObserverHelper.getId(target); + if (inputs.length > neededLength && !_observerIds.includes(id)) { + // Save target element id for preventing multiple calls to initCredentialsFields() + _observerIds.push(id); + + // Sometimes the settings haven't been loaded before new input fields are detected + if (Object.keys(kpxc.settings).length === 0) { + kpxc.init(); + } else { + kpxc.initCredentialFields(true); + } + } +}; + +kpxcObserverHelper.handleObserverRemove = function(target) { + if (kpxcObserverHelper.ignoredElement(target)) { + return; + } + + const inputs = kpxcObserverHelper.getInputs(target); + if (inputs.length === 0) { + return; + } + + // Remove target element id from the list + const id = kpxcObserverHelper.getId(target); + if (_observerIds.includes(id)) { + const index = _observerIds.indexOf(id); + if (index >= 0) { + _observerIds.splice(index, 1); + } + } +}; + +kpxcObserverHelper.detectURLChange = function() { + if (_documentURL !== document.location.href) { + _documentURL = document.location.href; + kpxcEvents.clearCredentials(); + kpxc.initCredentialFields(true); + } +}; + +MutationObserver = window.MutationObserver || window.WebKitMutationObserver; + +// Detects DOM changes in the document +let observer = new MutationObserver(function(mutations, observer) { + if (document.visibilityState === 'hidden') { + return; + } + + for (const mut of mutations) { + // Skip text nodes + if (mut.target.nodeType === Node.TEXT_NODE) { + continue; + } + + // Check document URL change and detect new fields + kpxcObserverHelper.detectURLChange(); + + // Handle attributes only if CSS display is modified + if (mut.type === 'attributes') { + const newValue = mut.target.getAttribute(mut.attributeName); + if (newValue && (newValue.includes('display') || newValue.includes('z-index'))) { + if (mut.target.style.display !== 'none') { + kpxcObserverHelper.handleObserverAdd(mut.target); + } else { + kpxcObserverHelper.handleObserverRemove(mut.target); + } + } + } else if (mut.type === 'childList') { + kpxcObserverHelper.handleObserverAdd((mut.addedNodes.length > 0) ? mut.addedNodes[0] : mut.target); + kpxcObserverHelper.handleObserverRemove((mut.removedNodes.length > 0) ? mut.removedNodes[0] : mut.target); + } + } +}); + +// define what element should be observed by the observer +// and what types of mutations trigger the callback +observer.observe(document, { + subtree: true, + attributes: true, + childList: true, + characterData: true, + attributeFilter: ['style'] +}); + +var kpxc = {}; +kpxc.settings = {}; +kpxc.u = null; +kpxc.p = null; +kpxc.url = null; +kpxc.submitUrl = null; +kpxc.credentials = []; + +const initcb = function() { + browser.runtime.sendMessage({ + action: 'load_settings', + }).then((response) => { + kpxc.settings = response; + kpxc.initCredentialFields(); + }); +}; + +if (document.readyState === 'complete' || (document.readyState !== 'loading' && !document.documentElement.doScroll)) { + initcb(); +} else { + document.addEventListener('DOMContentLoaded', initcb); +} + +kpxc.init = function() { + initcb(); +}; + +// Clears all from the content and background scripts, including autocomplete +kpxc.clearAllFromPage = function() { + kpxcEvents.clearCredentials(); + + browser.runtime.sendMessage({ + action: 'page_clear_logins' + }); + + // Switch back to default popup + browser.runtime.sendMessage({ + action: 'get_status', + args: [ true ] // Set polling to true, this is an internal function call + }); +}; + +// Switch credentials if database is changed or closed +kpxc.detectDatabaseChange = function(response) { + kpxc.clearAllFromPage(); + if (document.visibilityState !== 'hidden') { + if (response.new !== '' && response.new !== response.old) { + _called.retrieveCredentials = false; + browser.runtime.sendMessage({ + action: 'load_settings' + }).then((settings) => { + kpxc.settings = settings; + kpxc.initCredentialFields(true); + + // If user has requested a manual fill through context menu the actual credential filling + // is handled here when the opened database has been regognized. It's not a pretty hack. + if (_called.manualFillRequested && _called.manualFillRequested !== 'none') { + kpxc.fillInFromActiveElement(false, _called.manualFillRequested === 'pass'); + _called.manualFillRequested = 'none'; + } + }); + } + } +}; + +kpxc.initCredentialFields = function(forceCall) { + if (_called.initCredentialFields && !forceCall) { + return; + } + _called.initCredentialFields = true; + + browser.runtime.sendMessage({ 'action': 'page_clear_logins', args: [ _called.clearLogins ] }).then(() => { + _called.clearLogins = true; + + // Check site preferences + kpxc.initializeSitePreferences(); + if (kpxc.settings.sitePreferences) { + for (const site of kpxc.settings.sitePreferences) { + if (site.url === window.top.location.href || siteMatch(site.url, window.top.location.href)) { + if (site.ignore === IGNORE_FULL) { + return; + } + + _singleInputEnabledForPage = site.usernameOnly; + } + } + } + + const inputs = kpxcFields.getAllFields(); + if (inputs.length === 0) { + return; + } + + kpxcFields.prepareVisibleFieldsWithID('select'); + kpxc.initPasswordGenerator(inputs); + + if (!kpxcFields.useDefinedCredentialFields()) { + // Get all combinations of username + password fields + kpxcFields.combinations = kpxcFields.getAllCombinations(inputs); + } + kpxcFields.prepareCombinations(kpxcFields.combinations); + + if (kpxcFields.combinations.length === 0 && inputs.length === 0) { + browser.runtime.sendMessage({ + action: 'show_default_browseraction' + }); + return; + } + + kpxc.url = document.location.origin; + kpxc.submitUrl = kpxc.getFormActionUrl(kpxcFields.combinations[0]); + + // Get submitUrl for a single input + if (!kpxc.submitUrl && kpxcFields.combinations.length === 1 && inputs.length === 1) { + kpxc.submitUrl = kpxc.getFormActionUrlFromSingleInput(inputs[0]); + } + + if (kpxc.settings.autoRetrieveCredentials && _called.retrieveCredentials === false && (kpxc.url && kpxc.submitUrl)) { + browser.runtime.sendMessage({ + action: 'retrieve_credentials', + args: [ kpxc.url, kpxc.submitUrl ] + }).then(kpxc.retrieveCredentialsCallback).catch((e) => { + console.log(e); + }); + } else if (_singleInputEnabledForPage) { + kpxc.preparePageForMultipleCredentials(kpxc.credentials); + } + }); +}; + +kpxc.initPasswordGenerator = function(inputs) { + if (kpxc.settings.usePasswordGenerator) { + kpxcPassword.init(); + + for (let i = 0; i < inputs.length; i++) { + if (inputs[i] && inputs[i].getAttribute('type') && inputs[i].getAttribute('type').toLowerCase() === 'password') { + kpxcPassword.initField(inputs[i], inputs, i); + } + } + } +}; + +kpxc.receiveCredentialsIfNecessary = function() { + return new Promise((resolve, reject) => { + if (kpxc.credentials.length === 0 && _called.retrieveCredentials === false) { + browser.runtime.sendMessage({ + action: 'retrieve_credentials', + args: [ kpxc.url, kpxc.submitUrl, false, true ] // Sets triggerUnlock to true + }).then((credentials) => { + // If the database was locked, this is scope never met. In these cases the response is met at kpxc.detectDatabaseChange + _called.manualFillRequested = 'none'; + kpxc.retrieveCredentialsCallback(credentials, false); + resolve(credentials); + }); + } else { + resolve(kpxc.credentials); + } + }); +}; + +kpxc.retrieveCredentialsCallback = function(credentials, dontAutoFillIn) { + if (kpxcFields.combinations.length > 0) { + kpxc.u = _f(kpxcFields.combinations[0].username); + kpxc.p = _f(kpxcFields.combinations[0].password); + } + + if (credentials && credentials.length > 0) { + kpxc.credentials = credentials; + kpxc.prepareFieldsForCredentials(!Boolean(dontAutoFillIn)); + _called.retrieveCredentials = true; + } +}; + +kpxc.prepareFieldsForCredentials = function(autoFillInForSingle) { + // only one login for this site + if (autoFillInForSingle && kpxc.settings.autoFillSingleEntry && kpxc.credentials.length === 1) { + let combination = null; + if (!kpxc.p && !kpxc.u && kpxcFields.combinations.length > 0) { + kpxc.u = _f(kpxcFields.combinations[0].username); + kpxc.p = _f(kpxcFields.combinations[0].password); + combination = kpxcFields.combinations[0]; + } + if (kpxc.u) { + kpxc.setValueWithChange(kpxc.u, kpxc.credentials[0].login); + combination = kpxcFields.getCombination('username', kpxc.u); + } + if (kpxc.p) { + kpxc.setValueWithChange(kpxc.p, kpxc.credentials[0].password); + combination = kpxcFields.getCombination('password', kpxc.p); + } + + if (combination) { + let list = []; + if (kpxc.fillInStringFields(combination.fields, kpxc.credentials[0].stringFields, list)) { + kpxcForm.destroy(false, {'password': list.list[0], 'username': list.list[1]}); + } + } + + // Generate popup-list of usernames + descriptions + browser.runtime.sendMessage({ + action: 'popup_login', + args: [ [ kpxc.credentials[0].login + ' (' + kpxc.credentials[0].name + ')' ]] + }); + } else if (kpxc.credentials.length > 1 || (kpxc.credentials.length > 0 && (!kpxc.settings.autoFillSingleEntry || !autoFillInForSingle))) { + kpxc.preparePageForMultipleCredentials(kpxc.credentials); + } +}; + +kpxc.preparePageForMultipleCredentials = function(credentials) { + // add usernames + descriptions to autocomplete-list and popup-list + const usernames = []; + kpxcAutocomplete.elements = []; + let visibleLogin; + for (let i = 0; i < credentials.length; i++) { + visibleLogin = (credentials[i].login.length > 0) ? credentials[i].login : tr('credentialsNoUsername'); + usernames.push(visibleLogin + ' (' + credentials[i].name + ')'); + const item = { + label: visibleLogin + ' (' + credentials[i].name + ')', + value: credentials[i].login, + loginId: i + }; + kpxcAutocomplete.elements.push(item); + } + + // Generate popup-list of usernames + descriptions + browser.runtime.sendMessage({ + action: 'popup_login', + args: [ usernames ] + }); + + // Initialize autocomplete for username fields + if (kpxc.settings.autoCompleteUsernames) { + for (const i of kpxcFields.combinations) { + // Both username and password fields are visible + if (_detectedFields >= 2) { + if (_f(i.username)) { + kpxcAutocomplete.create(_f(i.username)); + } + } else if (_detectedFields === 1) { + if (_f(i.username)) { + kpxcAutocomplete.create(_f(i.username)); + } + if (_f(i.password)) { + kpxcAutocomplete.create(_f(i.password)); + } + } + } + } +}; + +kpxc.getFormActionUrl = function(combination) { + if (!combination) { + return null; + } + + const field = _f(combination.password) || _f(combination.username); + if (field === null) { + return null; + } + + const form = field.closest('form'); + let action = null; + + if (form && form.length > 0) { + action = form[0].action; + } + + if (typeof(action) !== 'string' || action === '') { + action = document.location.origin + document.location.pathname; + } + + return action; +}; + +kpxc.getFormActionUrlFromSingleInput = function(field) { + if (!field) { + return null; + } + + let action = field.formAction; + + if (typeof(action) !== 'string' || action === '') { + action = document.location.origin + document.location.pathname; + } + + return action; +}; + +kpxc.fillInCredentials = function(combination, onlyPassword, suppressWarnings) { + const action = kpxc.getFormActionUrl(combination); + const u = _f(combination.username); + const p = _f(combination.password); + + if (combination.isNew) { + // Initialize form-submit for remembering credentials + const fieldId = combination.password || combination.username; + const field = _f(fieldId); + if (field) { + const form2 = field.closest('form'); + if (form2 && form2.length > 0) { + kpxcForm.init(form2, combination); + } + } + } + + if (u) { + kpxc.u = u; + } + if (p) { + kpxc.p = p; + } + + if (kpxc.url === document.location.origin && kpxc.submitUrl === action && kpxc.credentials.length > 0) { + kpxc.fillIn(combination, onlyPassword, suppressWarnings); + } else { + kpxc.url = document.location.origin; + kpxc.submitUrl = action; + + browser.runtime.sendMessage({ + action: 'retrieve_credentials', + args: [ kpxc.url, kpxc.submitUrl, false, true ] + }).then((credentials) => { + kpxc.retrieveCredentialsCallback(credentials, true); + kpxc.fillIn(combination, onlyPassword, suppressWarnings); + }); + } +}; + +kpxc.fillInFromActiveElement = function(suppressWarnings, passOnly = false) { + const el = document.activeElement; + if (el.tagName.toLowerCase() !== 'input') { + if (kpxcFields.combinations.length > 0) { + kpxc.fillInCredentials(kpxcFields.combinations[0], false, suppressWarnings); + } + return; + } + + kpxcFields.setUniqueId(el); + const fieldId = kpxcFields.prepareId(el.getAttribute('data-kpxc-id')); + let combination = null; + if (el.getAttribute('type') === 'password') { + combination = kpxcFields.getCombination('password', fieldId); + } else { + combination = kpxcFields.getCombination('username', fieldId); + } + + if (passOnly) { + if (!_f(combination.password)) { + const message = tr('fieldsNoPasswordField'); + browser.runtime.sendMessage({ + action: 'show_notification', + args: [ message ] + }); + return; + } + } + + delete combination.loginId; + + kpxc.fillInCredentials(combination, passOnly, suppressWarnings); +}; + +kpxc.fillInFromActiveElementTOTPOnly = function(suppressWarnings) { + const el = document.activeElement; + kpxcFields.setUniqueId(el); + const fieldId = kpxcFields.prepareId(el.getAttribute('data-kpxc-id')); + + browser.runtime.sendMessage({ + action: 'page_get_login_id' + }).then((pos) => { + if (pos >= 0 && kpxc.credentials[pos]) { + // Check the value from stringFields (to be removed) + const currentField = _fs(fieldId); + if (kpxc.credentials[pos].stringFields && kpxc.credentials[pos].stringFields.length > 0) { + const stringFields = kpxc.credentials[pos].stringFields; + for (const s of stringFields) { + const val = s['KPH: {TOTP}']; + if (val) { + kpxc.setValue(currentField, val); + } + } + } else if (kpxc.credentials[pos].totp && kpxc.credentials[pos].totp.length > 0) { + kpxc.setValue(currentField, kpxc.credentials[pos].totp); + } + } + }); +}; + +kpxc.setValue = function(field, value) { + if (field.matches('select')) { + value = value.toLowerCase().trim(); + const options = field.querySelectorAll('option'); + for (const o of options) { + if (o.test().toLowerCase().trim() === value) { + kpxc.setValueWithChange(field, o.value); + return false; + } + } + } else { + kpxc.setValueWithChange(field, value); + } +}; + +kpxc.fillInStringFields = function(fields, stringFields, filledInFields) { + let filledIn = false; + + filledInFields.list = []; + if (fields && stringFields && fields.length > 0 && stringFields.length > 0) { + for (let i = 0; i < fields.length; i++) { + const currentField = _fs(fields[i]); + const stringFieldValue = Object.values(stringFields[i]); + if (currentField && stringFieldValue[0]) { + kpxc.setValue(currentField, stringFieldValue[0]); + filledInFields.list.push(fields[i]); + filledIn = true; + } + } + } + + return filledIn; +}; + +kpxc.setValueWithChange = function(field, value) { + if (kpxc.settings.respectMaxLength === true) { + const attributeMaxlength = field.getAttribute('maxlength'); + if (attributeMaxlength && !isNaN(attributeMaxlength) && attributeMaxlength > 0) { + value = value.substr(0, attributeMaxlength); + } + } + + field.value = value; + field.dispatchEvent(new Event('input', { 'bubbles': true })); + field.dispatchEvent(new Event('change', { 'bubbles': true })); +}; + +kpxc.fillIn = function(combination, onlyPassword, suppressWarnings) { + // No credentials available + if (kpxc.credentials.length === 0 && !suppressWarnings) { + const message = tr('credentialsNoLoginsFound'); + browser.runtime.sendMessage({ + action: 'show_notification', + args: [ message ] + }); + return; + } + + const uField = _f(combination.username); + const pField = _f(combination.password); + + // Exactly one pair of credentials available + if (kpxc.credentials.length === 1) { + let filledIn = false; + if (uField && (!onlyPassword || _singleInputEnabledForPage)) { + kpxc.setValueWithChange(uField, kpxc.credentials[0].login); + browser.runtime.sendMessage({ + action: 'page_set_login_id', args: [ 0 ] + }); + filledIn = true; + } + if (pField) { + pField.setAttribute('type', 'password'); + kpxc.setValueWithChange(pField, kpxc.credentials[0].password); + pField.setAttribute('unchanged', true); + browser.runtime.sendMessage({ + action: 'page_set_login_id', args: [ 0 ] + }); + filledIn = true; + } + + let list = []; + if (kpxc.fillInStringFields(combination.fields, kpxc.credentials[0].stringFields, list)) { + kpxcForm.destroy(false, { 'password': list.list[0], 'username': list.list[1] }); + filledIn = true; + } + + if (!filledIn) { + if (!suppressWarnings) { + const message = tr('fieldsFill'); + browser.runtime.sendMessage({ + action: 'show_notification', + args: [ message ] + }); + } + } + } else if (combination.loginId !== undefined && kpxc.credentials[combination.loginId]) { + // Specific login ID given + let filledIn = false; + if (uField) { + kpxc.setValueWithChange(uField, kpxc.credentials[combination.loginId].login); + browser.runtime.sendMessage({ + action: 'page_set_login_id', args: [ combination.loginId ] + }); + filledIn = true; + } + + if (pField) { + kpxc.setValueWithChange(pField, kpxc.credentials[combination.loginId].password); + pField.setAttribute('unchanged', true); + browser.runtime.sendMessage({ + action: 'page_set_login_id', args: [ combination.loginId ] + }); + filledIn = true; + } + + let list = []; + if (kpxc.fillInStringFields(combination.fields, kpxc.credentials[combination.loginId].stringFields, list)) { + kpxcForm.destroy(false, { 'password': list.list[0], 'username': list.list[1] }); + filledIn = true; + } + + if (!filledIn) { + if (!suppressWarnings) { + const message = tr('fieldsFill'); + browser.runtime.sendMessage({ + action: 'show_notification', + args: [ message ] + }); + } + } + } else { // Multiple credentials available + // Check if only one password for given username exists + let countPasswords = 0; + + if (uField) { + let valPassword = ''; + let valUsername = ''; + let valStringFields = []; + const valQueryUsername = uField.value.toLowerCase(); + + // Find passwords to given username (even those with empty username) + for (const c of kpxc.credentials) { + if (c.login.toLowerCase() === valQueryUsername) { + countPasswords += 1; + valPassword = c.password; + valUsername = c.login; + valStringFields = c.stringFields; + } + } + + // For the correct notification message: 0 = no logins, X > 1 = too many logins + if (countPasswords === 0) { + countPasswords = kpxc.credentials.length; + } + + // Only one mapping username found + if (countPasswords === 1) { + if (!onlyPassword) { + kpxc.setValueWithChange(uField, valUsername); + } + + if (pField) { + kpxc.setValueWithChange(pField, valPassword); + pField.setAttribute('unchanged', true); + } + + let list = []; + if (kpxc.fillInStringFields(combination.fields, valStringFields, list)) { + kpxcForm.destroy(false, { 'password': list.list[0], 'username': list.list[1] }); + } + } + + // User has to select correct credentials by himself + if (countPasswords > 1) { + if (!suppressWarnings) { + const target = onlyPassword ? pField : uField; + kpxcAutocomplete.create(target, true); + target.focus(); + } + } else if (countPasswords < 1) { + if (!suppressWarnings) { + const message = tr('credentialsNoUsernameFound'); + browser.runtime.sendMessage({ + action: 'show_notification', + args: [ message ] + }); + } + } + } else { + if (!suppressWarnings) { + const target = onlyPassword ? pField : uField; + kpxcAutocomplete.create(target, true); + target.focus(); + } + } + } +}; + +kpxc.contextMenuRememberCredentials = function() { + const el = document.activeElement; + if (el.tagName.toLowerCase() !== 'input') { + return; + } + + kpxcFields.setUniqueId(el); + const fieldId = kpxcFields.prepareId(el.getAttribute('data-kpxc-id')); + let combination = null; + if (el.getAttribute('type') === 'password') { + combination = kpxcFields.getCombination('password', fieldId); + } else { + combination = kpxcFields.getCombination('username', fieldId); + } + + let usernameValue = ''; + let passwordValue = ''; + + const usernameField = _f(combination.username); + const passwordField = _f(combination.password); + + if (usernameField) { + usernameValue = usernameField.value; + } + if (passwordField) { + passwordValue = passwordField.value; + } + + if (!kpxc.rememberCredentials(usernameValue, passwordValue)) { + const message = tr('rememberNothingChanged'); + browser.runtime.sendMessage({ + action: 'show_notification', + args: [ message ] + }); + } +}; + +kpxc.rememberCredentials = function(usernameValue, passwordValue) { + // No password given or field cleaned by a site-running script + // --> no password to save + if (passwordValue === '') { + return false; + } + + let usernameExists = false; + let nothingChanged = false; + + for (const c of kpxc.credentials) { + if (c.login === usernameValue && c.password === passwordValue) { + nothingChanged = true; + break; + } + + if (c.login === usernameValue) { + usernameExists = true; + } + } + + if (!nothingChanged) { + if (!usernameExists) { + for (const c of kpxc.credentials) { + if (c.login === usernameValue) { + usernameExists = true; + break; + } + } + } + const credentialsList = []; + for (const c of kpxc.credentials) { + credentialsList.push({ + login: c.login, + name: c.name, + uuid: c.uuid + }); + } + + let url = this.action; + if (!url) { + url = kpxc.getDocumentLocation(); + if (url.indexOf('?') > 0) { + url = url.substring(0, url.indexOf('?')); + if (url.length < document.location.origin.length) { + url = document.location.origin; + } + } + } + + browser.runtime.sendMessage({ + action: 'set_remember_credentials', + args: [ usernameValue, passwordValue, url, usernameExists, credentialsList ] + }); + + return true; + } + + return false; +}; + +kpxc.ignoreSite = function(sites) { + if (!sites || sites.length === 0) { + return; + } + + let site = sites[0]; + kpxc.initializeSitePreferences(); + + if (slashNeededForUrl(site)) { + site += '/'; + } + + // Check if the site already exists + let siteExists = false; + for (const existingSite of kpxc.settings['sitePreferences']) { + if (existingSite.url === site) { + existingSite.ignore = IGNORE_NORMAL; + siteExists = true; + } + } + + if (!siteExists) { + kpxc.settings['sitePreferences'].push({ + url: site, + ignore: IGNORE_NORMAL, + usernameOnly: false + }); + } + + browser.runtime.sendMessage({ + action: 'save_settings', + args: [ kpxc.settings ] + }); +}; + +// Delete previously created Object if it exists. It will be replaced by an Array +kpxc.initializeSitePreferences = function() { + if (kpxc.settings['sitePreferences'] !== undefined && kpxc.settings['sitePreferences'].constructor === Object) { + delete kpxc.settings['sitePreferences']; + } + + if (!kpxc.settings['sitePreferences']) { + kpxc.settings['sitePreferences'] = []; + } +}; + +kpxc.getDocumentLocation = function() { + return kpxc.settings.saveDomainOnly ? document.location.origin : document.location.href; +}; + + +var kpxcEvents = {}; + +kpxcEvents.clearCredentials = function() { + kpxc.credentials = []; + kpxcAutocomplete.elements = []; + _called.retrieveCredentials = false; + + if (kpxc.settings.autoCompleteUsernames) { + for (const c of kpxcFields.combinations) { + const uField = _f(c.username); + if (uField) { + if (uField.classList.contains('ui-autocomplete-input')) { + uField.autocomplete('destroy'); + } + } + } + } +}; + +kpxcEvents.triggerActivatedTab = function() { + // Doesn't run a second time because of _called.initCredentialFields set to true + kpxc.init(); + + // initCredentialFields calls also "retrieve_credentials", to prevent it + // check of init() was already called + if (_called.initCredentialFields && (kpxc.url && kpxc.submitUrl) && kpxc.settings.autoRetrieveCredentials) { + browser.runtime.sendMessage({ + action: 'retrieve_credentials', + args: [ kpxc.url, kpxc.submitUrl ] + }).then(kpxc.retrieveCredentialsCallback).catch((e) => { + console.log(e); + }); + } +}; diff --git a/keepassxc-browser/content/pwgen.js b/keepassxc-browser/content/pwgen.js new file mode 100644 index 0000000..dff2a0a --- /dev/null +++ b/keepassxc-browser/content/pwgen.js @@ -0,0 +1,407 @@ +'use strict'; + +var kpxcPassword = {}; +kpxcPassword.created = false; +kpxcPassword.icon = null; +kpxcPassword.inputField = null; +kpxcPassword.selected = null; +kpxcPassword.startPosX = 0; +kpxcPassword.startPosY = 0; +kpxcPassword.diffX = 0; +kpxcPassword.diffY = 0; +kpxcPassword.dialog = null; +kpxcPassword.titleBar = null; + +const DOMRectToArray = function(domRect) { + return [ domRect.bottom, domRect.height, domRect.left, domRect.right, domRect.top, domRect.width, domRect.x, domRect.y ]; +}; + +/** +* Detects if the input field appears or disappears -> show/hide the icon +* - boundingClientRect with slightly (< -10) negative values -> hidden +* - intersectionRatio === 0 -> hidden +* - isIntersecting === false -> hidden +* - intersectionRatio > 0 -> shown +* - isIntersecting === true -> shown +*/ +kpxcPassword.observer = new IntersectionObserver((entries) => { + for (const entry of entries) { + const rect = DOMRectToArray(entry.boundingClientRect); + + if ((entry.intersectionRatio === 0 && !entry.isIntersecting) || (rect.some(x => x < -10))) { + kpxcPassword.icon.style.display = 'none'; + } else if (entry.intersectionRatio > 0 && entry.isIntersecting) { + kpxcPassword.icon.style.display = 'block'; + + // Wait for possible DOM animations + setTimeout(() => { + kpxcPassword.setIconPosition(kpxcPassword.icon, entry.target) + }, 500); + } + } +}); + +kpxcPassword.init = function() { + if ('initPasswordGenerator' in _called) { + return; + } + + _called.initPasswordGenerator = true; +}; + +kpxcPassword.initField = function(field, inputs, pos) { + if (!field) { + return; + } + + // Observer the visibility + kpxcPassword.observer.observe(field); + + if (field.getAttribute('kpxc-password-generator')) { + return; + } + + field.setAttribute('kpxc-password-generator', true); + + kpxcPassword.createIcon(field); + kpxcPassword.inputField = field; + + let found = false; + if (inputs) { + for (let i = pos + 1; i < inputs.length; i++) { + if (inputs[i] && inputs[i].getAttribute('type') && inputs[i].getAttribute('type').toLowerCase() === 'password') { + field.setAttribute('kpxc-pwgen-next-field-id', inputs[i].getAttribute('data-kpxc-id')); + field.setAttribute('kpxc-pwgen-next-is-password-field', (i === 0)); + found = true; + break; + } + } + } + + field.setAttribute('kpxc-pwgen-next-field-exists', found); +}; + +kpxcPassword.createIcon = function(field) { + const className = (isFirefox() ? 'key-moz' : 'key'); + const size = (field.offsetHeight > 28) ? 24 : 16; + let offset = Math.floor((field.offsetHeight - size) / 3); + offset = (offset < 0) ? 0 : offset; + + const icon = kpxcUI.createElement('div', 'kpxc kpxc-pwgen-icon ' + className, + { + 'title': tr('passwordGeneratorGenerateText'), + 'alt': tr('passwordGeneratorIcon'), + 'size': size, + 'offset': offset, + 'kpxc-pwgen-field-id': field.getAttribute('data-kpxc-id') + }); + icon.style.zIndex = '9999'; + icon.style.width = String(size) + 'px'; + icon.style.height = String(size) + 'px'; + + icon.addEventListener('click', function(e) { + e.preventDefault(); + kpxcPassword.showDialog(field, icon); + }); + + kpxcPassword.setIconPosition(icon, field); + kpxcPassword.icon = icon; + document.body.appendChild(icon); +}; + +kpxcPassword.setIconPosition = function(icon, field) { + const rect = field.getBoundingClientRect(); + const offset = Number(icon.getAttribute('offset')); + const size = Number(icon.getAttribute('size')); + + icon.style.top = String((rect.top + document.scrollingElement.scrollTop) + offset + 1) + 'px'; + icon.style.left = String((rect.left + document.scrollingElement.scrollLeft) + field.offsetWidth - size - offset) + 'px'; +}; + +kpxcPassword.createDialog = function() { + if (kpxcPassword.created) { + // If database is open again, generate a new password right away + const input = $('.kpxc-pwgen-input'); + if (input.style.display === 'none') { + kpxcPassword.generate(); + } + return; + } + kpxcPassword.created = true; + + const wrapper = kpxcUI.createElement('div', 'kpxc'); + const dialog = kpxcUI.createElement('div', 'kpxc kpxc-pwgen-dialog'); + const titleBar = kpxcUI.createElement('div', 'kpxc-pwgen-titlebar', {}, tr('passwordGeneratorTitle')); + const closeButton = kpxcUI.createElement('div', 'kpxc-pwgen-close', {}, '×'); + closeButton.onclick = function(e) { + kpxcPassword.openDialog(); + }; + titleBar.append(closeButton); + + const passwordRow = kpxcUI.createElement('div', 'kpxc-pwgen-password-row'); + const input = kpxcUI.createElement('input', 'kpxc-pwgen-input', { 'placeholder': tr('passwordGeneratorPlaceholder'), 'type': 'text', 'tabindex': '-1' }); + const inputLabel = kpxcUI.createElement('label', 'kpxc-pwgen-bits', {}, tr('passwordGeneratorBits', '???')); + passwordRow.appendMultiple(input, inputLabel); + + const nextFillRow = kpxcUI.createElement('div', 'kpxc-pwgen-nextfill-row'); + const checkbox = kpxcUI.createElement('input', 'kpxc-pwgen-checkbox', { 'id': 'kpxc-pwgen-checkbox', 'type': 'checkbox' }); + const checkboxLabel = kpxcUI.createElement('label', 'kpxc-pwgen-checkbox-label', { 'for': 'kpxc-pwgen-checkbox' }, tr('passwordGeneratorLabel')); + nextFillRow.appendMultiple(checkbox, checkboxLabel); + + // Buttons + const buttonsRow = kpxcUI.createElement('div', 'kpxc-pwgen-buttons'); + const generateButton = kpxcUI.createElement('button', 'kpxc-button kpxc-white-button', { 'id': 'kpxc-pwgen-btn-generate' }, tr('passwordGeneratorGenerate')); + const copyButton = kpxcUI.createElement('button', 'kpxc-button', { 'id': 'kpxc-pwgen-btn-copy' }, tr('passwordGeneratorCopy')); + const fillButton = kpxcUI.createElement('button', 'kpxc-button', { 'id': 'kpxc-pwgen-btn-fill' }, tr('passwordGeneratorFillAndCopy')); + + generateButton.onclick = function(e) { + kpxcPassword.generate(e); + }; + + copyButton.onclick = function(e) { + kpxcPassword.copy(e); + }; + + fillButton.onclick = function(e) { + kpxcPassword.fill(e); + }; + + buttonsRow.appendMultiple(generateButton, copyButton, fillButton); + dialog.appendMultiple(titleBar, passwordRow, nextFillRow, buttonsRow); + wrapper.append(dialog); + + const icon = $('.kpxc-pwgen-icon'); + dialog.style.top = String(icon.offsetTop + icon.offsetHeight) + 'px'; + dialog.style.left = icon.style.left; + + document.body.append(wrapper); + + kpxcPassword.dialog = dialog; + kpxcPassword.titleBar = titleBar; + kpxcPassword.titleBar.onmousedown = function(e) { + kpxcPassword.mouseDown(e); + }; + + kpxcPassword.generate(); +}; + +kpxcPassword.mouseDown = function(e) { + kpxcPassword.selected = kpxcPassword.titleBar; + kpxcPassword.startPosX = e.clientX; + kpxcPassword.startPosY = e.clientY; + kpxcPassword.diffX = kpxcPassword.startPosX - kpxcPassword.dialog.offsetLeft; + kpxcPassword.diffY = kpxcPassword.startPosY - kpxcPassword.dialog.offsetTop; + return false; +}; + +kpxcPassword.openDialog = function() { + if (kpxcPassword.dialog.style.display === '' || kpxcPassword.dialog.style.display === 'none') { + kpxcPassword.dialog.style.display = 'block'; + } else { + kpxcPassword.dialog.style.display = 'none'; + } +}; + +kpxcPassword.trigger = function() { + kpxcPassword.showDialog(kpxcPassword.inputField, kpxcPassword.icon); +}; + +kpxcPassword.showDialog = function(field, icon) { + if (!kpxcFields.isVisible(field)) { + document.body.removeChild(icon); + field.removeAttribute('kpxc-password-generator'); + return; + } + + kpxcPassword.createDialog(); + kpxcPassword.openDialog(); + + // Adjust the dialog location + if (kpxcPassword.dialog) { + kpxcPassword.dialog.style.top = String(icon.offsetTop + icon.offsetHeight) + 'px'; + kpxcPassword.dialog.style.left = icon.style.left; + + kpxcPassword.dialog.setAttribute('kpxc-pwgen-field-id', field.getAttribute('data-kpxc-id')); + kpxcPassword.dialog.setAttribute('kpxc-pwgen-next-field-id', field.getAttribute('kpxc-pwgen-next-field-id')); + kpxcPassword.dialog.setAttribute('kpxc-pwgen-next-is-password-field', field.getAttribute('kpxc-pwgen-next-is-password-field')); + + const fieldExists = Boolean(field.getAttribute('kpxc-pwgen-next-field-exists')); + const checkbox = $('.kpxc-pwgen-checkbox'); + if (checkbox) { + checkbox.setAttribute('checked', fieldExists); + if (fieldExists) { + checkbox.removeAttribute('disabled'); + } else { + checkbox.setAttribute('disabled', ''); + } + } + } +}; + +kpxcPassword.generate = function(e) { + if (e) { + e.preventDefault(); + } + + browser.runtime.sendMessage({ + action: 'generate_password' + }).then(kpxcPassword.callbackGeneratedPassword).catch((err) => { + console.log(err); + }); +}; + +kpxcPassword.copy = function(e) { + e.preventDefault(); + if (kpxcPassword.copyPasswordToClipboard()) { + kpxcPassword.greenButton('#kpxc-pwgen-btn-copy'); + kpxcPassword.whiteButton('#kpxc-pwgen-btn-fill'); + } +}; + +kpxcPassword.fill = function(e) { + e.preventDefault(); + + let field = null; + const inputs = document.querySelectorAll('input[type=\'password\']'); + for (const i of inputs) { + if (i.getAttribute('data-kpxc-id')) { + field = i; + break; + } + } + + if (field) { + const password = $('.kpxc-pwgen-input'); + if (field.getAttribute('maxlength')) { + if (password.value.length > field.getAttribute('maxlength')) { + const message = tr('passwordGeneratorErrorTooLong') + '\r\n' + + tr('passwordGeneratorErrorTooLongCut') + '\r\n' + tr('passwordGeneratorErrorTooLongRemember'); + message.style.whiteSpace = 'pre'; + browser.runtime.sendMessage({ + action: 'show_notification', + args: [ message ] + }); + return; + } + } + + field.value = password.value; + if ($('.kpxc-pwgen-checkbox').checked) { + if (field.getAttribute('kpxc-pwgen-next-field-id')) { + const nextFieldId = field.getAttribute('kpxc-pwgen-next-field-id'); + const nextField = $('input[data-kpxc-id=\'' + nextFieldId + '\']'); + if (nextField) { + nextField.value = password.value; + } + } + } + + if (kpxcPassword.copyPasswordToClipboard()) { + kpxcPassword.greenButton('#kpxc-pwgen-btn-fill'); + kpxcPassword.whiteButton('#kpxc-pwgen-btn-copy'); + } + } +}; + +kpxcPassword.copyPasswordToClipboard = function() { + $('.kpxc-pwgen-input').select(); + try { + return document.execCommand('copy'); + } + catch (err) { + console.log('Could not copy password to clipboard: ' + err); + } + return false; +}; + +kpxcPassword.callbackGeneratedPassword = function(entries) { + if (entries && entries.length >= 1) { + const errorMessage = $('#kpxc-pwgen-error'); + if (errorMessage) { + kpxcPassword.enableButtons(); + + $('.kpxc-pwgen-checkbox').parentElement.style.display = 'block'; + $('.kpxc-pwgen-bits').style.display = 'block'; + + const input = $('.kpxc-pwgen-input'); + input.style.display = 'block'; + errorMessage.remove(); + } + + kpxcPassword.whiteButton('#kpxc-pwgen-btn-fill'); + kpxcPassword.whiteButton('#kpxc-pwgen-btn-copy'); + $('.kpxc-pwgen-input').value = entries[0].password; + $('.kpxc-pwgen-bits').textContent = tr('passwordGeneratorBits', (isNaN(entries[0].login) ? '???' : entries[0].login)); + } else { + if (document.querySelectorAll('div#kpxc-pwgen-error').length === 0) { + $('.kpxc-pwgen-checkbox').parentElement.style.display = 'none'; + $('.kpxc-pwgen-bits').style.display = 'none'; + + const input = $('.kpxc-pwgen-input'); + input.style.display = 'none'; + + const errorMessage = kpxcUI.createElement('div', '', { 'id': 'kpxc-pwgen-error' }, + tr('passwordGeneratorError') + '\r\n' + tr('passwordGeneratorErrorIsRunning')); + errorMessage.style.whiteSpace = 'pre'; + input.parentElement.append(errorMessage); + + kpxcPassword.disableButtons(); + } + } +}; + +kpxcPassword.onRequestPassword = function() { + browser.runtime.sendMessage({ + action: 'generate_password' + }).then(kpxcPassword.callbackGeneratedPassword); +}; + +kpxcPassword.greenButton = function(button) { + $(button).classList.remove('kpxc-white-button'); + $(button).classList.add('kpxc-green-button'); +}; + +kpxcPassword.whiteButton = function(button) { + $(button).classList.remove('kpxc-green-button'); + $(button).classList.add('kpxc-white-button'); +}; + +kpxcPassword.enableButtons = function() { + $('#kpxc-pwgen-btn-generate').textContent = tr('passwordGeneratorGenerate'); + $('#kpxc-pwgen-btn-copy').style.display = 'inline-block'; + $('#kpxc-pwgen-btn-fill').style.display = 'inline-block'; +}; + +kpxcPassword.disableButtons = function() { + $('#kpxc-pwgen-btn-generate').textContent = tr('passwordGeneratorTryAgain'); + $('#kpxc-pwgen-btn-copy').style.display = 'none'; + $('#kpxc-pwgen-btn-fill').style.display = 'none'; +}; + +// Handle icon position on window resize +window.addEventListener('resize', function(e) { + if (kpxcPassword.inputField && kpxcPassword.icon) { + kpxcPassword.setIconPosition(kpxcPassword.icon, kpxcPassword.inputField); + } +}); + +// Handle icon position on scroll +window.addEventListener('scroll', function(e) { + if (kpxcPassword.inputField && kpxcPassword.icon) { + kpxcPassword.setIconPosition(kpxcPassword.icon, kpxcPassword.inputField); + } +}); + +// Closes the dialog when clicked outside of it) +document.onclick = function(e) { + if (kpxcPassword.dialog && kpxcPassword.dialog.style.display === 'block') { + const dialogEndX = kpxcPassword.dialog.offsetLeft + kpxcPassword.dialog.offsetWidth; + const dialogEndY = kpxcPassword.dialog.offsetTop + kpxcPassword.dialog.offsetHeight; + + if ((e.clientX < kpxcPassword.dialog.offsetLeft || e.clientX > dialogEndX) || + (e.clientY < kpxcPassword.dialog.offsetTop || e.clientY > dialogEndY) && + !e.target.classList.contains('kpxc-pwgen-icon')) { + kpxcPassword.openDialog(); + } + } +}; diff --git a/keepassxc-browser/content/ui.js b/keepassxc-browser/content/ui.js new file mode 100644 index 0000000..7b87973 --- /dev/null +++ b/keepassxc-browser/content/ui.js @@ -0,0 +1,67 @@ +'use strict'; + +// jQuery style wrapper for querySelector() +var $ = function(elem) +{ + return document.querySelector(elem); +}; + +var kpxcUI = {}; + +// Wrapper for creating elements +kpxcUI.createElement = function(type, classes, attributes, textContent) { + const element = document.createElement(type); + + if (classes) { + const splitted = classes.split(' '); + for (const c of splitted) { + element.classList.add(c); + } + } + + if (attributes !== undefined) { + Object.keys(attributes).forEach((key) => { + element.setAttribute(key, attributes[key]); + }); + } + + if (textContent !== undefined) { + element.textContent = textContent; + } + + return element; +}; + +// Enables dragging +document.onmousemove = function(e) { + if (kpxcPassword.selected === kpxcPassword.titleBar) { + const x_pos = e.clientX - kpxcPassword.diffX; + const y_pos = e.clientY - kpxcPassword.diffY; + + if (kpxcPassword.selected !== null) { + kpxcPassword.dialog.style.left = x_pos + 'px'; + kpxcPassword.dialog.style.top = y_pos + 'px'; + } + } + + if (kpxcDefine.selected === kpxcDefine.dialog) { + const x_pos = e.clientX - kpxcDefine.diffX; + const y_pos = e.clientY - kpxcDefine.diffY; + + if (kpxcDefine.selected !== null) { + kpxcDefine.dialog.style.left = x_pos + 'px'; + kpxcDefine.dialog.style.top = y_pos + 'px'; + } + } +}; + +document.onmouseup = function() { + kpxcPassword.selected = null; + kpxcDefine.selected = null; +}; + +HTMLDivElement.prototype.appendMultiple = function(...args) { + for (const a of args) { + this.append(a); + } +}; diff --git a/keepassxc-browser/css/autocomplete.css b/keepassxc-browser/css/autocomplete.css new file mode 100644 index 0000000..fe5d99f --- /dev/null +++ b/keepassxc-browser/css/autocomplete.css @@ -0,0 +1,19 @@ +.kpxcAutocomplete-items { + position: absolute !important; + border: 1px solid #d4d4d4; +} + +.kpxcAutocomplete-items div { + padding: 5px; + cursor: pointer; + background-color: #fff; + border-bottom: 1px solid #d4d4d4; + width: auto; + color: #000; + font-size: .9em !important; +} + +.kpxcAutocomplete-active { + background-color: #6cac4d !important; + color: #ffffff !important; +} \ No newline at end of file diff --git a/keepassxc-browser/css/button.css b/keepassxc-browser/css/button.css new file mode 100644 index 0000000..16945ad --- /dev/null +++ b/keepassxc-browser/css/button.css @@ -0,0 +1,48 @@ +.kpxc-button { + font-size: 12px !important; + font-family: 'Lato', sans-serif !important; + height: 28px !important; + margin: .2em !important; + background-color: #fff; + border: 1px solid #888 !important; + border-radius: 4px !important; +} + +.kpxc-white-button { + color: #333 !important; + background-color: #fff !important; + border-color: #ccc !important; +} + +.kpxc-red-button { + color: #fff !important; + background-color: #d9534f !important; + border-color: #d43f3a !important; +} + +.kpxc-orange-button { + color: #fff !important; + background-color: #f0ad4e !important; + border-color: #eea236 !important; +} + +.kpxc-blue-button { + color: #fff !important; + background-color: #337ab7 !important; + border-color: #2e6da4 !important; +} + +.kpxc-green-button { + color: #fff !important; + background-color: #5cb85c !important; + border-color: #4cae4c !important; +} + +.kpxc-button:hover { + background-color: #eee; + cursor: pointer; +} + +.kpxc-button:active { + background-color: #ddd; +} \ No newline at end of file diff --git a/keepassxc-browser/css/define.css b/keepassxc-browser/css/define.css new file mode 100644 index 0000000..55525d5 --- /dev/null +++ b/keepassxc-browser/css/define.css @@ -0,0 +1,110 @@ +.kpxcDefine-modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 2147483645; +} + +.kpxcDefine-modal-backdrop:after { + content: ''; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: #000000; + opacity: 0.5; + filter: alpha(opacity=50); +} + +#kpxcDefine-fields { + z-index: 2147483646; +} + +#kpxcDefine-description { + z-index: 2147483646; + color: #efefef; + border: 2px solid #555555; + padding: 7px 5px; + position: absolute; + top: 100px; + left: 150px; + text-align: left; + cursor: pointer; + background-color: rgba(0,0,0,0.8); + font-size: 15px; + user-select: none; +} + +#kpxcDefine-description div:first-of-type { + margin-top: 0; + padding-top: 0; + text-align: left; + color: #efefef; + padding-bottom: 8px; + font-weight: bold; + font-size: 120%; +} + +#kpxcDefine-description p { + margin-top: 10px; + padding-top: 10px; + color: #efefef; + border-top: 2px solid #666666; + line-height: 110%; +} + +#kpxcDefine-help { + margin-bottom: 3px; +} + +.kpxcDefine-keyboardHelp { + font-size: 0.75em; +} + +.kpxcDefine-keyboardHelp kbd { + background-color: #eee; + border-radius: 3px; + border: 1px solid #b4b4b4; + color: #333; + display: inline-block; + line-height: 1; + padding: 2px 4px; + white-space: nowrap; +} + +.kpxcDefine-fixed-field { + position: absolute; + border: 2px solid #efefef; + color: #fff; + cursor: pointer; + z-index: 2147483646; + text-align: center; + font-weight: bold; + background-color: rgba(239,239,239,0.4); +} + +.kpxcDefine-fixed-hover-field { + border: 2px solid orange; + background-color: rgba(255,165,239,0.4); +} + +.kpxcDefine-fixed-password-field { + border: 2px solid red; + color: #efefef; + background-color: rgba(255,0,0,0.4); +} + +.kpxcDefine-fixed-username-field { + border: 2px solid limegreen; + color: #efefef; + background-color: rgba(50,205,50,0.4); +} + +.kpxcDefine-fixed-string-field { + border: 2px solid deepskyblue; + color: #efefef; + background-color: rgba(30,144,255,0.4); +} diff --git a/keepassxc-browser/css/pwgen.css b/keepassxc-browser/css/pwgen.css new file mode 100644 index 0000000..40b6ee0 --- /dev/null +++ b/keepassxc-browser/css/pwgen.css @@ -0,0 +1,114 @@ +.kpxc-pwgen-dialog { + font-family: 'Lato', sans-serif !important; + width: 350px; + min-height: 80px; + background-color: white; + border: 1px solid #ccc; + border-radius: 4px; + box-shadow: 0 4px 6px 0 hsla(0, 0%, 0%, 0.2); + z-index: 2147483645; + padding: .1em .2em .1em .2em; + position: absolute !important; +} + +.kpxc-pwgen-titlebar { + font-size: 14px !important; + background-color: #6cac4d; + color: #fff; + padding: .4em .2em .4em .8em; + margin: .2em 0 .2em 0; + position: relative; + cursor: move; +} + +.kpxc-pwgen-password-row { + color: #fff; + padding: .4em 1em; + margin: .2em 0 .2em 0; + display: flex; +} + +.kpxc-pwgen-nextfill-row { + font-size: 12px !important; + color: #000; + padding: .4em 1em; + margin: .2em 0 .2em 0; +} + +.kpxc-pwgen-buttons { + color: #fff; + padding: .4em 1em; + margin: .2em 0 .2em 0; + border-top: 1px solid #ccc; + display: flex; + align-items: center; + justify-content: center; +} + +.kpxc-pwgen-bits { + font-size: 12px !important; + font-style: normal !important; + font-weight: normal !important; + text-align: center; + color: #000; + background-color: #eee; + border: 1px solid #ccc; + padding: .4em; + border-radius: 4px; + min-width: 60px; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + border-collapse: separate; + vertical-align: middle; + white-space: nowrap; +} + +.kpxc-pwgen-close { + color: #fff; + float: right; + font-size: inherit; + font-weight: bold; + text-align: center; + min-width: 20px; +} + +.kpxc-pwgen-close:hover { + background-color: #6cac4d !important; + color: #fff; + cursor: pointer; +} + +.kpxc-pwgen-input { + width: 100%; + font-size: 12px !important; + font-weight: normal !important; +} + +.kpxc-pwgen-checkbox-label { + font-style: normal !important; + font-weight: normal !important; +} + +.kpxc #kpxc-pwgen-error { + color: #000; + font-size: 12px !important; + font-style: normal !important; + font-weight: normal !important; + text-align: center; + width: 100%; +} + +.kpxc-pwgen-icon { + position: absolute; + cursor: pointer; +} + +.kpxc-pwgen-icon.key { + background: url('chrome-extension://__MSG_@@extension_id__/icons/key.svg') right no-repeat; + background-size: contain; +} + +.kpxc-pwgen-icon.key-moz { + background: url('moz-extension://__MSG_@@extension_id__/icons/key.svg') right no-repeat; + background-size: contain; +} diff --git a/keepassxc-browser/global.js b/keepassxc-browser/global.js index 0e8b264..887a290 100755 --- a/keepassxc-browser/global.js +++ b/keepassxc-browser/global.js @@ -4,15 +4,12 @@ const IGNORE_NOTHING = 'ignoreNothing'; const IGNORE_NORMAL = 'ignoreNormal'; const IGNORE_FULL = 'ignoreFull'; -var schemeSegment = '(\\*|http|https|ws|wss|file|ftp)'; -var hostSegment = '(\\*|(?:\\*\\.)?(?:[^/*]+))?'; -var pathSegment = '(.*)'; +const schemeSegment = '(\\*|http|https|ws|wss|file|ftp)'; +const hostSegment = '(\\*|(?:\\*\\.)?(?:[^/*]+))?'; +const pathSegment = '(.*)'; var isFirefox = function() { - if (!(/Chrome/.test(navigator.userAgent) && /Google/.test(navigator.vendor))) { - return true; - } - return false; + return navigator.userAgent.indexOf('Firefox') !== -1 || navigator.userAgent.indexOf('Gecko/') !== -1; }; var showNotification = function(message) { @@ -45,12 +42,12 @@ var matchPatternToRegExp = function(pattern) { let match = matchPatternRegExp.exec(pattern); if (!match) { - throw new TypeError(pattern + ' is not a valid MatchPattern'); + throw new TypeError('"${pattern}" is not a valid MatchPattern'); } let [, scheme, host, path] = match; if (!host) { - throw new TypeError(pattern + ' does not have a valid host'); + throw new TypeError('"${pattern}" does not have a valid host'); } let regex = '^'; @@ -92,7 +89,6 @@ var siteMatch = function(site, url) { return url.match(rx); }; -// Checks if URL has only scheme and host without the last / char. var slashNeededForUrl = function(pattern) { const matchPattern = new RegExp(`^${schemeSegment}://${hostSegment}$`); return matchPattern.exec(pattern); diff --git a/keepassxc-browser/jquery-ui.min.css b/keepassxc-browser/jquery-ui.min.css deleted file mode 100644 index ced6235..0000000 --- a/keepassxc-browser/jquery-ui.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2017-11-16 -* http://jqueryui.com -* Includes: draggable.css, core.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=.kpxc&folderName=kpxc&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -.kpxc .ui-draggable-handle{-ms-touch-action:none;touch-action:none}.kpxc .ui-helper-hidden{display:none}.kpxc .ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.kpxc .ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.kpxc .ui-helper-clearfix:before,.kpxc .ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.kpxc .ui-helper-clearfix:after{clear:both}.kpxc .ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.kpxc .ui-front{z-index:100}.kpxc .ui-state-disabled{cursor:default!important;pointer-events:none}.kpxc .ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.kpxc .ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.kpxc .ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.kpxc .ui-resizable{position:relative}.kpxc .ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.kpxc .ui-resizable-disabled .ui-resizable-handle,.kpxc .ui-resizable-autohide .ui-resizable-handle{display:none}.kpxc .ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.kpxc .ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.kpxc .ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.kpxc .ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.kpxc .ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.kpxc .ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.kpxc .ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.kpxc .ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.kpxc .ui-selectable{-ms-touch-action:none;touch-action:none}.kpxc .ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.kpxc .ui-sortable-handle{-ms-touch-action:none;touch-action:none}.kpxc .ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.kpxc .ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.kpxc .ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.kpxc .ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.kpxc .ui-menu .ui-menu{position:absolute}.kpxc .ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.kpxc .ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.kpxc .ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.kpxc .ui-menu .ui-state-focus,.kpxc .ui-menu .ui-state-active{margin:-1px}.kpxc .ui-menu-icons{position:relative}.kpxc .ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.kpxc .ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.kpxc .ui-menu .ui-menu-icon{left:auto;right:0}.kpxc .ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.kpxc .ui-button,.kpxc .ui-button:link,.kpxc .ui-button:visited,.kpxc .ui-button:hover,.kpxc .ui-button:active{text-decoration:none}.kpxc .ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.kpxc .ui-button.ui-button-icon-only{text-indent:0}.kpxc .ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.kpxc .ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.kpxc .ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.kpxc .ui-button::-moz-focus-inner,button.kpxc .ui-button::-moz-focus-inner{border:0;padding:0}.kpxc .ui-controlgroup{vertical-align:middle;display:inline-block}.kpxc .ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.kpxc .ui-controlgroup > .ui-controlgroup-item:focus,.kpxc .ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.kpxc .ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.kpxc .ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.kpxc .ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.kpxc .ui-controlgroup .ui-controlgroup-label span{font-size:80%}.kpxc .ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.kpxc .ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.kpxc .ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.kpxc .ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.kpxc .ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.kpxc .ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.kpxc .ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.kpxc .ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.kpxc .ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.kpxc .ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.kpxc .ui-checkboxradio-disabled{pointer-events:none}.kpxc .ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.kpxc .ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.kpxc .ui-datepicker .ui-datepicker-prev,.kpxc .ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.kpxc .ui-datepicker .ui-datepicker-prev-hover,.kpxc .ui-datepicker .ui-datepicker-next-hover{top:1px}.kpxc .ui-datepicker .ui-datepicker-prev{left:2px}.kpxc .ui-datepicker .ui-datepicker-next{right:2px}.kpxc .ui-datepicker .ui-datepicker-prev-hover{left:1px}.kpxc .ui-datepicker .ui-datepicker-next-hover{right:1px}.kpxc .ui-datepicker .ui-datepicker-prev span,.kpxc .ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.kpxc .ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.kpxc .ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.kpxc .ui-datepicker select.ui-datepicker-month,.kpxc .ui-datepicker select.ui-datepicker-year{width:45%}.kpxc .ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.kpxc .ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.kpxc .ui-datepicker td{border:0;padding:1px}.kpxc .ui-datepicker td span,.kpxc .ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.kpxc .ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.kpxc .ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.kpxc .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.kpxc .ui-datepicker.ui-datepicker-multi{width:auto}.kpxc .ui-datepicker-multi .ui-datepicker-group{float:left}.kpxc .ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.kpxc .ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.kpxc .ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.kpxc .ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.kpxc .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.kpxc .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.kpxc .ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.kpxc .ui-datepicker-row-break{clear:both;width:100%;font-size:0}.kpxc .ui-datepicker-rtl{direction:rtl}.kpxc .ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.kpxc .ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.kpxc .ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.kpxc .ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.kpxc .ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.kpxc .ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.kpxc .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.kpxc .ui-datepicker-rtl .ui-datepicker-group{float:right}.kpxc .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.kpxc .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.kpxc .ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.kpxc .ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.kpxc .ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.kpxc .ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.kpxc .ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.kpxc .ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.kpxc .ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.kpxc .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.kpxc .ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.kpxc .ui-dialog .ui-resizable-n{height:2px;top:0}.kpxc .ui-dialog .ui-resizable-e{width:2px;right:0}.kpxc .ui-dialog .ui-resizable-s{height:2px;bottom:0}.kpxc .ui-dialog .ui-resizable-w{width:2px;left:0}.kpxc .ui-dialog .ui-resizable-se,.kpxc .ui-dialog .ui-resizable-sw,.kpxc .ui-dialog .ui-resizable-ne,.kpxc .ui-dialog .ui-resizable-nw{width:7px;height:7px}.kpxc .ui-dialog .ui-resizable-se{right:0;bottom:0}.kpxc .ui-dialog .ui-resizable-sw{left:0;bottom:0}.kpxc .ui-dialog .ui-resizable-ne{right:0;top:0}.kpxc .ui-dialog .ui-resizable-nw{left:0;top:0}.kpxc .ui-draggable .ui-dialog-titlebar{cursor:move}.kpxc .ui-progressbar{height:2em;text-align:left;overflow:hidden}.kpxc .ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.kpxc .ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.kpxc .ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.kpxc .ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.kpxc .ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.kpxc .ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.kpxc .ui-selectmenu-open{display:block}.kpxc .ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.kpxc .ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.kpxc .ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.kpxc .ui-slider{position:relative;text-align:left}.kpxc .ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.kpxc .ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.kpxc .ui-slider.ui-state-disabled .ui-slider-handle,.kpxc .ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.kpxc .ui-slider-horizontal{height:.8em}.kpxc .ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.kpxc .ui-slider-horizontal .ui-slider-range{top:0;height:100%}.kpxc .ui-slider-horizontal .ui-slider-range-min{left:0}.kpxc .ui-slider-horizontal .ui-slider-range-max{right:0}.kpxc .ui-slider-vertical{width:.8em;height:100px}.kpxc .ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.kpxc .ui-slider-vertical .ui-slider-range{left:0;width:100%}.kpxc .ui-slider-vertical .ui-slider-range-min{bottom:0}.kpxc .ui-slider-vertical .ui-slider-range-max{top:0}.kpxc .ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.kpxc .ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.kpxc .ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.kpxc .ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.kpxc .ui-spinner-up{top:0}.kpxc .ui-spinner-down{bottom:0}.kpxc .ui-tabs{position:relative;padding:.2em}.kpxc .ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.kpxc .ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.kpxc .ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.kpxc .ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.kpxc .ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.kpxc .ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.kpxc .ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.kpxc .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.kpxc .ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.kpxc .ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .kpxc .ui-tooltip{border-width:2px}.kpxc .ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.kpxc .ui-widget .ui-widget{font-size:1em}.kpxc .ui-widget input,.kpxc .ui-widget select,.kpxc .ui-widget textarea,.kpxc .ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.kpxc .ui-widget.ui-widget-content{border:1px solid #c5c5c5}.kpxc .ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.kpxc .ui-widget-content a{color:#333}.kpxc .ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.kpxc .ui-widget-header a{color:#333}.kpxc .ui-state-default,.kpxc .ui-widget-content .ui-state-default,.kpxc .ui-widget-header .ui-state-default,.kpxc .ui-button,html .kpxc .ui-button.ui-state-disabled:hover,html .kpxc .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.kpxc .ui-state-default a,.kpxc .ui-state-default a:link,.kpxc .ui-state-default a:visited,a.kpxc .ui-button,a:link.kpxc .ui-button,a:visited.kpxc .ui-button,.kpxc .ui-button{color:#454545;text-decoration:none}.kpxc .ui-state-hover,.kpxc .ui-widget-content .ui-state-hover,.kpxc .ui-widget-header .ui-state-hover,.kpxc .ui-state-focus,.kpxc .ui-widget-content .ui-state-focus,.kpxc .ui-widget-header .ui-state-focus,.kpxc .ui-button:hover,.kpxc .ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.kpxc .ui-state-hover a,.kpxc .ui-state-hover a:hover,.kpxc .ui-state-hover a:link,.kpxc .ui-state-hover a:visited,.kpxc .ui-state-focus a,.kpxc .ui-state-focus a:hover,.kpxc .ui-state-focus a:link,.kpxc .ui-state-focus a:visited,a.kpxc .ui-button:hover,a.kpxc .ui-button:focus{color:#2b2b2b;text-decoration:none}.kpxc .ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.kpxc .ui-state-active,.kpxc .ui-widget-content .ui-state-active,.kpxc .ui-widget-header .ui-state-active,a.kpxc .ui-button:active,.kpxc .ui-button:active,.kpxc .ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.kpxc .ui-icon-background,.kpxc .ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.kpxc .ui-state-active a,.kpxc .ui-state-active a:link,.kpxc .ui-state-active a:visited{color:#fff;text-decoration:none}.kpxc .ui-state-highlight,.kpxc .ui-widget-content .ui-state-highlight,.kpxc .ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.kpxc .ui-state-checked{border:1px solid #dad55e;background:#fffa90}.kpxc .ui-state-highlight a,.kpxc .ui-widget-content .ui-state-highlight a,.kpxc .ui-widget-header .ui-state-highlight a{color:#777620}.kpxc .ui-state-error,.kpxc .ui-widget-content .ui-state-error,.kpxc .ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.kpxc .ui-state-error a,.kpxc .ui-widget-content .ui-state-error a,.kpxc .ui-widget-header .ui-state-error a{color:#5f3f3f}.kpxc .ui-state-error-text,.kpxc .ui-widget-content .ui-state-error-text,.kpxc .ui-widget-header .ui-state-error-text{color:#5f3f3f}.kpxc .ui-priority-primary,.kpxc .ui-widget-content .ui-priority-primary,.kpxc .ui-widget-header .ui-priority-primary{font-weight:bold}.kpxc .ui-priority-secondary,.kpxc .ui-widget-content .ui-priority-secondary,.kpxc .ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.kpxc .ui-state-disabled,.kpxc .ui-widget-content .ui-state-disabled,.kpxc .ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.kpxc .ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.kpxc .ui-icon{width:16px;height:16px}.kpxc .ui-icon,.kpxc .ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.kpxc .ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.kpxc .ui-state-hover .ui-icon,.kpxc .ui-state-focus .ui-icon,.kpxc .ui-button:hover .ui-icon,.kpxc .ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.kpxc .ui-state-active .ui-icon,.kpxc .ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.kpxc .ui-state-highlight .ui-icon,.kpxc .ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.kpxc .ui-state-error .ui-icon,.kpxc .ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.kpxc .ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.kpxc .ui-icon-blank{background-position:16px 16px}.kpxc .ui-icon-caret-1-n{background-position:0 0}.kpxc .ui-icon-caret-1-ne{background-position:-16px 0}.kpxc .ui-icon-caret-1-e{background-position:-32px 0}.kpxc .ui-icon-caret-1-se{background-position:-48px 0}.kpxc .ui-icon-caret-1-s{background-position:-65px 0}.kpxc .ui-icon-caret-1-sw{background-position:-80px 0}.kpxc .ui-icon-caret-1-w{background-position:-96px 0}.kpxc .ui-icon-caret-1-nw{background-position:-112px 0}.kpxc .ui-icon-caret-2-n-s{background-position:-128px 0}.kpxc .ui-icon-caret-2-e-w{background-position:-144px 0}.kpxc .ui-icon-triangle-1-n{background-position:0 -16px}.kpxc .ui-icon-triangle-1-ne{background-position:-16px -16px}.kpxc .ui-icon-triangle-1-e{background-position:-32px -16px}.kpxc .ui-icon-triangle-1-se{background-position:-48px -16px}.kpxc .ui-icon-triangle-1-s{background-position:-65px -16px}.kpxc .ui-icon-triangle-1-sw{background-position:-80px -16px}.kpxc .ui-icon-triangle-1-w{background-position:-96px -16px}.kpxc .ui-icon-triangle-1-nw{background-position:-112px -16px}.kpxc .ui-icon-triangle-2-n-s{background-position:-128px -16px}.kpxc .ui-icon-triangle-2-e-w{background-position:-144px -16px}.kpxc .ui-icon-arrow-1-n{background-position:0 -32px}.kpxc .ui-icon-arrow-1-ne{background-position:-16px -32px}.kpxc .ui-icon-arrow-1-e{background-position:-32px -32px}.kpxc .ui-icon-arrow-1-se{background-position:-48px -32px}.kpxc .ui-icon-arrow-1-s{background-position:-65px -32px}.kpxc .ui-icon-arrow-1-sw{background-position:-80px -32px}.kpxc .ui-icon-arrow-1-w{background-position:-96px -32px}.kpxc .ui-icon-arrow-1-nw{background-position:-112px -32px}.kpxc .ui-icon-arrow-2-n-s{background-position:-128px -32px}.kpxc .ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.kpxc .ui-icon-arrow-2-e-w{background-position:-160px -32px}.kpxc .ui-icon-arrow-2-se-nw{background-position:-176px -32px}.kpxc .ui-icon-arrowstop-1-n{background-position:-192px -32px}.kpxc .ui-icon-arrowstop-1-e{background-position:-208px -32px}.kpxc .ui-icon-arrowstop-1-s{background-position:-224px -32px}.kpxc .ui-icon-arrowstop-1-w{background-position:-240px -32px}.kpxc .ui-icon-arrowthick-1-n{background-position:1px -48px}.kpxc .ui-icon-arrowthick-1-ne{background-position:-16px -48px}.kpxc .ui-icon-arrowthick-1-e{background-position:-32px -48px}.kpxc .ui-icon-arrowthick-1-se{background-position:-48px -48px}.kpxc .ui-icon-arrowthick-1-s{background-position:-64px -48px}.kpxc .ui-icon-arrowthick-1-sw{background-position:-80px -48px}.kpxc .ui-icon-arrowthick-1-w{background-position:-96px -48px}.kpxc .ui-icon-arrowthick-1-nw{background-position:-112px -48px}.kpxc .ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.kpxc .ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.kpxc .ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.kpxc .ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.kpxc .ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.kpxc .ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.kpxc .ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.kpxc .ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.kpxc .ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.kpxc .ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.kpxc .ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.kpxc .ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.kpxc .ui-icon-arrowreturn-1-w{background-position:-64px -64px}.kpxc .ui-icon-arrowreturn-1-n{background-position:-80px -64px}.kpxc .ui-icon-arrowreturn-1-e{background-position:-96px -64px}.kpxc .ui-icon-arrowreturn-1-s{background-position:-112px -64px}.kpxc .ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.kpxc .ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.kpxc .ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.kpxc .ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.kpxc .ui-icon-arrow-4{background-position:0 -80px}.kpxc .ui-icon-arrow-4-diag{background-position:-16px -80px}.kpxc .ui-icon-extlink{background-position:-32px -80px}.kpxc .ui-icon-newwin{background-position:-48px -80px}.kpxc .ui-icon-refresh{background-position:-64px -80px}.kpxc .ui-icon-shuffle{background-position:-80px -80px}.kpxc .ui-icon-transfer-e-w{background-position:-96px -80px}.kpxc .ui-icon-transferthick-e-w{background-position:-112px -80px}.kpxc .ui-icon-folder-collapsed{background-position:0 -96px}.kpxc .ui-icon-folder-open{background-position:-16px -96px}.kpxc .ui-icon-document{background-position:-32px -96px}.kpxc .ui-icon-document-b{background-position:-48px -96px}.kpxc .ui-icon-note{background-position:-64px -96px}.kpxc .ui-icon-mail-closed{background-position:-80px -96px}.kpxc .ui-icon-mail-open{background-position:-96px -96px}.kpxc .ui-icon-suitcase{background-position:-112px -96px}.kpxc .ui-icon-comment{background-position:-128px -96px}.kpxc .ui-icon-person{background-position:-144px -96px}.kpxc .ui-icon-print{background-position:-160px -96px}.kpxc .ui-icon-trash{background-position:-176px -96px}.kpxc .ui-icon-locked{background-position:-192px -96px}.kpxc .ui-icon-unlocked{background-position:-208px -96px}.kpxc .ui-icon-bookmark{background-position:-224px -96px}.kpxc .ui-icon-tag{background-position:-240px -96px}.kpxc .ui-icon-home{background-position:0 -112px}.kpxc .ui-icon-flag{background-position:-16px -112px}.kpxc .ui-icon-calendar{background-position:-32px -112px}.kpxc .ui-icon-cart{background-position:-48px -112px}.kpxc .ui-icon-pencil{background-position:-64px -112px}.kpxc .ui-icon-clock{background-position:-80px -112px}.kpxc .ui-icon-disk{background-position:-96px -112px}.kpxc .ui-icon-calculator{background-position:-112px -112px}.kpxc .ui-icon-zoomin{background-position:-128px -112px}.kpxc .ui-icon-zoomout{background-position:-144px -112px}.kpxc .ui-icon-search{background-position:-160px -112px}.kpxc .ui-icon-wrench{background-position:-176px -112px}.kpxc .ui-icon-gear{background-position:-192px -112px}.kpxc .ui-icon-heart{background-position:-208px -112px}.kpxc .ui-icon-star{background-position:-224px -112px}.kpxc .ui-icon-link{background-position:-240px -112px}.kpxc .ui-icon-cancel{background-position:0 -128px}.kpxc .ui-icon-plus{background-position:-16px -128px}.kpxc .ui-icon-plusthick{background-position:-32px -128px}.kpxc .ui-icon-minus{background-position:-48px -128px}.kpxc .ui-icon-minusthick{background-position:-64px -128px}.kpxc .ui-icon-close{background-position:-80px -128px}.kpxc .ui-icon-closethick{background-position:-96px -128px}.kpxc .ui-icon-key{background-position:-112px -128px}.kpxc .ui-icon-lightbulb{background-position:-128px -128px}.kpxc .ui-icon-scissors{background-position:-144px -128px}.kpxc .ui-icon-clipboard{background-position:-160px -128px}.kpxc .ui-icon-copy{background-position:-176px -128px}.kpxc .ui-icon-contact{background-position:-192px -128px}.kpxc .ui-icon-image{background-position:-208px -128px}.kpxc .ui-icon-video{background-position:-224px -128px}.kpxc .ui-icon-script{background-position:-240px -128px}.kpxc .ui-icon-alert{background-position:0 -144px}.kpxc .ui-icon-info{background-position:-16px -144px}.kpxc .ui-icon-notice{background-position:-32px -144px}.kpxc .ui-icon-help{background-position:-48px -144px}.kpxc .ui-icon-check{background-position:-64px -144px}.kpxc .ui-icon-bullet{background-position:-80px -144px}.kpxc .ui-icon-radio-on{background-position:-96px -144px}.kpxc .ui-icon-radio-off{background-position:-112px -144px}.kpxc .ui-icon-pin-w{background-position:-128px -144px}.kpxc .ui-icon-pin-s{background-position:-144px -144px}.kpxc .ui-icon-play{background-position:0 -160px}.kpxc .ui-icon-pause{background-position:-16px -160px}.kpxc .ui-icon-seek-next{background-position:-32px -160px}.kpxc .ui-icon-seek-prev{background-position:-48px -160px}.kpxc .ui-icon-seek-end{background-position:-64px -160px}.kpxc .ui-icon-seek-start{background-position:-80px -160px}.kpxc .ui-icon-seek-first{background-position:-80px -160px}.kpxc .ui-icon-stop{background-position:-96px -160px}.kpxc .ui-icon-eject{background-position:-112px -160px}.kpxc .ui-icon-volume-off{background-position:-128px -160px}.kpxc .ui-icon-volume-on{background-position:-144px -160px}.kpxc .ui-icon-power{background-position:0 -176px}.kpxc .ui-icon-signal-diag{background-position:-16px -176px}.kpxc .ui-icon-signal{background-position:-32px -176px}.kpxc .ui-icon-battery-0{background-position:-48px -176px}.kpxc .ui-icon-battery-1{background-position:-64px -176px}.kpxc .ui-icon-battery-2{background-position:-80px -176px}.kpxc .ui-icon-battery-3{background-position:-96px -176px}.kpxc .ui-icon-circle-plus{background-position:0 -192px}.kpxc .ui-icon-circle-minus{background-position:-16px -192px}.kpxc .ui-icon-circle-close{background-position:-32px -192px}.kpxc .ui-icon-circle-triangle-e{background-position:-48px -192px}.kpxc .ui-icon-circle-triangle-s{background-position:-64px -192px}.kpxc .ui-icon-circle-triangle-w{background-position:-80px -192px}.kpxc .ui-icon-circle-triangle-n{background-position:-96px -192px}.kpxc .ui-icon-circle-arrow-e{background-position:-112px -192px}.kpxc .ui-icon-circle-arrow-s{background-position:-128px -192px}.kpxc .ui-icon-circle-arrow-w{background-position:-144px -192px}.kpxc .ui-icon-circle-arrow-n{background-position:-160px -192px}.kpxc .ui-icon-circle-zoomin{background-position:-176px -192px}.kpxc .ui-icon-circle-zoomout{background-position:-192px -192px}.kpxc .ui-icon-circle-check{background-position:-208px -192px}.kpxc .ui-icon-circlesmall-plus{background-position:0 -208px}.kpxc .ui-icon-circlesmall-minus{background-position:-16px -208px}.kpxc .ui-icon-circlesmall-close{background-position:-32px -208px}.kpxc .ui-icon-squaresmall-plus{background-position:-48px -208px}.kpxc .ui-icon-squaresmall-minus{background-position:-64px -208px}.kpxc .ui-icon-squaresmall-close{background-position:-80px -208px}.kpxc .ui-icon-grip-dotted-vertical{background-position:0 -224px}.kpxc .ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.kpxc .ui-icon-grip-solid-vertical{background-position:-32px -224px}.kpxc .ui-icon-grip-solid-horizontal{background-position:-48px -224px}.kpxc .ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.kpxc .ui-icon-grip-diagonal-se{background-position:-80px -224px}.kpxc .ui-corner-all,.kpxc .ui-corner-top,.kpxc .ui-corner-left,.kpxc .ui-corner-tl{border-top-left-radius:3px}.kpxc .ui-corner-all,.kpxc .ui-corner-top,.kpxc .ui-corner-right,.kpxc .ui-corner-tr{border-top-right-radius:3px}.kpxc .ui-corner-all,.kpxc .ui-corner-bottom,.kpxc .ui-corner-left,.kpxc .ui-corner-bl{border-bottom-left-radius:3px}.kpxc .ui-corner-all,.kpxc .ui-corner-bottom,.kpxc .ui-corner-right,.kpxc .ui-corner-br{border-bottom-right-radius:3px}.kpxc .ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.kpxc .ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/keepassxc-browser/jquery-ui.min.js b/keepassxc-browser/jquery-ui.min.js deleted file mode 100644 index 0a0a38c..0000000 --- a/keepassxc-browser/jquery-ui.min.js +++ /dev/null @@ -1,13 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2017-11-16 -* http://jqueryui.com -* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/draggable.js, widgets/droppable.js, widgets/resizable.js, widgets/selectable.js, widgets/sortable.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/selectmenu.js, widgets/slider.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){function e(t){for(var e=t.css("visibility");"inherit"===e;)t=t.parent(),e=t.css("visibility");return"hidden"!==e}function i(t){for(var e,i;t.length&&t[0]!==document;){if(e=t.css("position"),("absolute"===e||"relative"===e||"fixed"===e)&&(i=parseInt(t.css("zIndex"),10),!isNaN(i)&&0!==i))return i;t=t.parent()}return 0}function s(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.regional.en=t.extend(!0,{},this.regional[""]),this.regional["en-US"]=t.extend(!0,{},this.regional.en),this.dpDiv=n(t("
"))}function n(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.on("mouseout",i,function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datepicker-next-hover")}).on("mouseover",i,o)}function o(){t.datepicker._isDisabledDatepicker(p.inline?p.dpDiv.parent()[0]:p.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))}function a(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}function r(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.ui=t.ui||{},t.ui.version="1.12.1";var l=0,h=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var i,s,n=h.call(arguments,1),o=0,a=n.length;a>o;o++)for(i in n[o])s=n[o][i],n[o].hasOwnProperty(i)&&void 0!==s&&(e[i]=t.isPlainObject(s)?t.isPlainObject(e[i])?t.widget.extend({},e[i],s):t.widget.extend({},s):s);return e},t.widget.bridge=function(e,i){var s=i.prototype.widgetFullName||e;t.fn[e]=function(n){var o="string"==typeof n,a=h.call(arguments,1),r=this;return o?this.length||"instance"!==n?this.each(function(){var i,o=t.data(this,s);return"instance"===n?(r=o,!1):o?t.isFunction(o[n])&&"_"!==n.charAt(0)?(i=o[n].apply(o,a),i!==o&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+n+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+n+"'")}):r=void 0:(a.length&&(n=t.widget.extend.apply(null,[n].concat(a))),this.each(function(){var e=t.data(this,s);e?(e.option(n||{}),e._init&&e._init()):t.data(this,s,new i(n,this))})),r}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,i){i=t(i||this.defaultElement||this)[0],this.element=t(i),this.uuid=l++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},i!==this&&(t.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===i&&this.destroy()}}),this.document=t(i.style?i.ownerDocument:i.document||i),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,l=/top|center|bottom/,h=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};h>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),l.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-r-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-r-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,(i>0||u>a(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.focusable=function(i,s){var n,o,a,r,l,h=i.nodeName.toLowerCase();return"area"===h?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(h)?(r=!i.disabled,r&&(l=t(i).closest("fieldset")[0],l&&(r=!l.disabled))):r="a"===h?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var c=!1;t(document).on("mouseup",function(){c=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!c){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,s=1===e.which,n="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),c=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,c=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.ui.safeActiveElement=function(t){var e;try{e=t.activeElement}catch(i){e=t.body}return e||(e=t.body),e.nodeName||(e=t.body),e},t.ui.safeBlur=function(e){e&&"body"!==e.nodeName.toLowerCase()&&t(e).trigger("blur")},t.widget("ui.draggable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this._addClass("ui-draggable"),this._setHandleClassName(),this._mouseInit()},_setOption:function(t,e){this._super(t,e),"handle"===t&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(this._blurActiveElement(e),this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(e){this.iframeBlocks=this.document.find(e).map(function(){var e=t(this);return t("
").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(e){var i=t.ui.safeActiveElement(this.document[0]),s=t(e.target);s.closest(i).length||t.ui.safeBlur(i)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===t(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(e),this.originalPosition=this.position=this._generatePosition(e,!1),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_refreshOffsets:function(t){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:t.pageX-this.offset.left,top:t.pageY-this.offset.top}},_mouseDrag:function(e,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp(new t.Event("mouseup",e)),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1},_mouseUp:function(e){return this._unblockFrames(),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),this.handleElement.is(e.target)&&this.element.trigger("focus"),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp(new t.Event("mouseup",{target:this.element[0]})):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this._addClass(this.handleElement,"ui-draggable-handle")},_removeHandleClassName:function(){this._removeClass(this.handleElement,"ui-draggable-handle")},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper),n=s?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_isRootNode:function(t){return/(html|body)/i.test(t.tagName)||t===this.document[0]},_getParentOffset:function(){var e=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var t=this.element.position(),e=this._isRootNode(this.scrollParent[0]);return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+(e?0:this.scrollParent.scrollTop()),left:t.left-(parseInt(this.helper.css("left"),10)||0)+(e?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options,o=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,t(o).width()-this.helperProportions.width-this.margins.left,(t(o).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0) -},_convertPositionTo:function(t,e){e||(e=this.position);var i="absolute"===t?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var i,s,n,o,a=this.options,r=this._isRootNode(this.scrollParent[0]),l=t.pageX,h=t.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.lefti[2]&&(l=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,l=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o),"y"===a.axis&&(l=this.originalPageX),"x"===a.axis&&(h=this.originalPageY)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i,s){var n=t.extend({},i,{item:s.element});s.sortables=[],t(s.options.connectToSortable).each(function(){var i=t(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",e,n))})},stop:function(e,i,s){var n=t.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,t.each(s.sortables,function(){var t=this;t.isOver?(t.isOver=0,s.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,n))})},drag:function(e,i,s){t.each(s.sortables,function(){var n=!1,o=this;o.positionAbs=s.positionAbs,o.helperProportions=s.helperProportions,o.offset.click=s.offset.click,o._intersectsWith(o.containerCache)&&(n=!0,t.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==o&&this._intersectsWith(this.containerCache)&&t.contains(o.element[0],this.element[0])&&(n=!1),n})),n?(o.isOver||(o.isOver=1,s._parent=i.helper.parent(),o.currentItem=i.helper.appendTo(o.element).data("ui-sortable-item",!0),o.options._helper=o.options.helper,o.options.helper=function(){return i.helper[0]},e.target=o.currentItem[0],o._mouseCapture(e,!0),o._mouseStart(e,!0,!0),o.offset.click.top=s.offset.click.top,o.offset.click.left=s.offset.click.left,o.offset.parent.left-=s.offset.parent.left-o.offset.parent.left,o.offset.parent.top-=s.offset.parent.top-o.offset.parent.top,s._trigger("toSortable",e),s.dropped=o.element,t.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,o.fromOutside=s),o.currentItem&&(o._mouseDrag(e),i.position=o.position)):o.isOver&&(o.isOver=0,o.cancelHelperRemoval=!0,o.options._revert=o.options.revert,o.options.revert=!1,o._trigger("out",e,o._uiHash(o)),o._mouseStop(e,!0),o.options.revert=o.options._revert,o.options.helper=o.options._helper,o.placeholder&&o.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(e),i.position=s._generatePosition(e,!0),s._trigger("fromSortable",e),s.dropped=!1,t.each(s.sortables,function(){this.refreshPositions()}))})}}),t.ui.plugin.add("draggable","cursor",{start:function(e,i,s){var n=t("body"),o=s.options;n.css("cursor")&&(o._cursor=n.css("cursor")),n.css("cursor",o.cursor)},stop:function(e,i,s){var n=s.options;n._cursor&&t("body").css("cursor",n._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("opacity")&&(o._opacity=n.css("opacity")),n.css("opacity",o.opacity)},stop:function(e,i,s){var n=s.options;n._opacity&&t(i.helper).css("opacity",n._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(e,i,s){var n=s.options,o=!1,a=s.scrollParentNotHidden[0],r=s.document[0];a!==r&&"HTML"!==a.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+a.offsetHeight-e.pageY=0;d--)l=s.snapElements[d].left-s.margins.left,h=l+s.snapElements[d].width,c=s.snapElements[d].top-s.margins.top,u=c+s.snapElements[d].height,l-g>_||m>h+g||c-g>b||v>u+g||!t.contains(s.snapElements[d].item.ownerDocument,s.snapElements[d].item)?(s.snapElements[d].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=!1):("inner"!==f.snapMode&&(n=g>=Math.abs(c-b),o=g>=Math.abs(u-v),a=g>=Math.abs(l-_),r=g>=Math.abs(h-m),n&&(i.position.top=s._convertPositionTo("relative",{top:c-s.helperProportions.height,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left)),p=n||o||a||r,"outer"!==f.snapMode&&(n=g>=Math.abs(c-v),o=g>=Math.abs(u-b),a=g>=Math.abs(l-m),r=g>=Math.abs(h-_),n&&(i.position.top=s._convertPositionTo("relative",{top:c,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left)),!s.snapElements[d].snapping&&(n||o||a||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=n||o||a||r||p)}}),t.ui.plugin.add("draggable","stack",{start:function(e,i,s){var n,o=s.options,a=t.makeArray(t(o.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});a.length&&(n=parseInt(t(a[0]).css("zIndex"),10)||0,t(a).each(function(e){t(this).css("zIndex",n+e)}),this.css("zIndex",n+a.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("zIndex")&&(o._zIndex=n.css("zIndex")),n.css("zIndex",o.zIndex)},stop:function(e,i,s){var n=s.options;n._zIndex&&t(i.helper).css("zIndex",n._zIndex)}}),t.ui.draggable,t.widget("ui.droppable",{version:"1.12.1",widgetEventPrefix:"drop",options:{accept:"*",addClasses:!0,greedy:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var e,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=t.isFunction(s)?s:function(t){return t.is(s)},this.proportions=function(){return arguments.length?(e=arguments[0],void 0):e?e:e={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this._addClass("ui-droppable")},_addToManager:function(e){t.ui.ddmanager.droppables[e]=t.ui.ddmanager.droppables[e]||[],t.ui.ddmanager.droppables[e].push(this)},_splice:function(t){for(var e=0;t.length>e;e++)t[e]===this&&t.splice(e,1)},_destroy:function(){var e=t.ui.ddmanager.droppables[this.options.scope];this._splice(e)},_setOption:function(e,i){if("accept"===e)this.accept=t.isFunction(i)?i:function(t){return t.is(i)};else if("scope"===e){var s=t.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(e,i)},_activate:function(e){var i=t.ui.ddmanager.current;this._addActiveClass(),i&&this._trigger("activate",e,this.ui(i))},_deactivate:function(e){var i=t.ui.ddmanager.current;this._removeActiveClass(),i&&this._trigger("deactivate",e,this.ui(i))},_over:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this._addHoverClass(),this._trigger("over",e,this.ui(i)))},_out:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this._removeHoverClass(),this._trigger("out",e,this.ui(i)))},_drop:function(e,i){var s=i||t.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=t(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&u(s,t.extend(i,{offset:i.element.offset()}),i.options.tolerance,e)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this._removeActiveClass(),this._removeHoverClass(),this._trigger("drop",e,this.ui(s)),this.element):!1):!1},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}},_addHoverClass:function(){this._addClass("ui-droppable-hover")},_removeHoverClass:function(){this._removeClass("ui-droppable-hover")},_addActiveClass:function(){this._addClass("ui-droppable-active")},_removeActiveClass:function(){this._removeClass("ui-droppable-active")}});var u=t.ui.intersect=function(){function t(t,e,i){return t>=e&&e+i>t}return function(e,i,s,n){if(!i.offset)return!1;var o=(e.positionAbs||e.position.absolute).left+e.margins.left,a=(e.positionAbs||e.position.absolute).top+e.margins.top,r=o+e.helperProportions.width,l=a+e.helperProportions.height,h=i.offset.left,c=i.offset.top,u=h+i.proportions().width,d=c+i.proportions().height;switch(s){case"fit":return o>=h&&u>=r&&a>=c&&d>=l;case"intersect":return o+e.helperProportions.width/2>h&&u>r-e.helperProportions.width/2&&a+e.helperProportions.height/2>c&&d>l-e.helperProportions.height/2;case"pointer":return t(n.pageY,c,i.proportions().height)&&t(n.pageX,h,i.proportions().width);case"touch":return(a>=c&&d>=a||l>=c&&d>=l||c>a&&l>d)&&(o>=h&&u>=o||r>=h&&u>=r||h>o&&r>u);default:return!1}}}();t.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,i){var s,n,o=t.ui.ddmanager.droppables[e.options.scope]||[],a=i?i.type:null,r=(e.currentItem||e.element).find(":data(ui-droppable)").addBack();t:for(s=0;o.length>s;s++)if(!(o[s].options.disabled||e&&!o[s].accept.call(o[s].element[0],e.currentItem||e.element))){for(n=0;r.length>n;n++)if(r[n]===o[s].element[0]){o[s].proportions().height=0;continue t}o[s].visible="none"!==o[s].element.css("display"),o[s].visible&&("mousedown"===a&&o[s]._activate.call(o[s],i),o[s].offset=o[s].element.offset(),o[s].proportions({width:o[s].element[0].offsetWidth,height:o[s].element[0].offsetHeight}))}},drop:function(e,i){var s=!1;return t.each((t.ui.ddmanager.droppables[e.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&u(e,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(e,i){e.element.parentsUntil("body").on("scroll.droppable",function(){e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)})},drag:function(e,i){e.options.refreshPositions&&t.ui.ddmanager.prepareOffsets(e,i),t.each(t.ui.ddmanager.droppables[e.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,o,a=u(e,this,this.options.tolerance,i),r=!a&&this.isover?"isout":a&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,o=this.element.parents(":data(ui-droppable)").filter(function(){return t(this).droppable("instance").options.scope===n}),o.length&&(s=t(o[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(e,i){e.element.parentsUntil("body").off("scroll.droppable"),e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)}},t.uiBackCompat!==!1&&t.widget("ui.droppable",t.ui.droppable,{options:{hoverClass:!1,activeClass:!1},_addActiveClass:function(){this._super(),this.options.activeClass&&this.element.addClass(this.options.activeClass)},_removeActiveClass:function(){this._super(),this.options.activeClass&&this.element.removeClass(this.options.activeClass)},_addHoverClass:function(){this._super(),this.options.hoverClass&&this.element.addClass(this.options.hoverClass)},_removeHoverClass:function(){this._super(),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass)}}),t.ui.droppable,t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("
").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("
"),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,l=this._change[o];return this._updatePrevProperties(),l?(i=l.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,l,h=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,l=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,h.animate||this.element.css(t.extend(a,{top:l,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!h.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidtht.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,l=this.originalPosition.top+this.originalSize.height,h=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&h&&(t.left=r-e.minWidth),s&&h&&(t.left=r-e.maxWidth),a&&c&&(t.top=l-e.minHeight),n&&c&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("
"),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,l={width:i.size.width-r,height:i.size.height-a},h=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(l,c&&h?{top:c,left:h}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,l=t(this).resizable("instance"),h=l.options,c=l.element,u=h.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(l.containerElement=t(d),/document/.test(u)||u===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=l._num(e.css("padding"+s))}),l.containerOffset=e.offset(),l.containerPosition=e.position(),l.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=l.containerOffset,n=l.containerSize.height,o=l.containerSize.width,a=l._hasScroll(d,"left")?d.scrollWidth:o,r=l._hasScroll(d)?d.scrollHeight:n,l.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,l=a.containerOffset,h=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=l),h.left<(a._helper?l.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-l.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?l.left:0),h.top<(a._helper?l.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-l.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?l.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-l.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-l.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),l=a.outerWidth()-e.sizeDiff.width,h=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0}; -t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,l="number"==typeof s.grid?[s.grid,s.grid]:s.grid,h=l[0]||1,c=l[1]||1,u=Math.round((n.width-o.width)/h)*h,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,g=s.maxWidth&&p>s.maxWidth,m=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=l,_&&(p+=h),v&&(f+=c),g&&(p-=h),m&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-h)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-h>0?(i.size.width=p,i.position.left=a.left-u):(p=h-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable,t.widget("ui.selectable",t.ui.mouse,{version:"1.12.1",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var e=this;this._addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){e.elementPos=t(e.element[0]).offset(),e.selectees=t(e.options.filter,e.element[0]),e._addClass(e.selectees,"ui-selectee"),e.selectees.each(function(){var i=t(this),s=i.offset(),n={left:s.left-e.elementPos.left,top:s.top-e.elementPos.top};t.data(this,"selectable-item",{element:this,$element:i,left:n.left,top:n.top,right:n.left+i.outerWidth(),bottom:n.top+i.outerHeight(),startselected:!1,selected:i.hasClass("ui-selected"),selecting:i.hasClass("ui-selecting"),unselecting:i.hasClass("ui-unselecting")})})},this.refresh(),this._mouseInit(),this.helper=t("
"),this._addClass(this.helper,"ui-selectable-helper")},_destroy:function(){this.selectees.removeData("selectable-item"),this._mouseDestroy()},_mouseStart:function(e){var i=this,s=this.options;this.opos=[e.pageX,e.pageY],this.elementPos=t(this.element[0]).offset(),this.options.disabled||(this.selectees=t(s.filter,this.element[0]),this._trigger("start",e),t(s.appendTo).append(this.helper),this.helper.css({left:e.pageX,top:e.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=t.data(this,"selectable-item");s.startselected=!0,e.metaKey||e.ctrlKey||(i._removeClass(s.$element,"ui-selected"),s.selected=!1,i._addClass(s.$element,"ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",e,{unselecting:s.element}))}),t(e.target).parents().addBack().each(function(){var s,n=t.data(this,"selectable-item");return n?(s=!e.metaKey&&!e.ctrlKey||!n.$element.hasClass("ui-selected"),i._removeClass(n.$element,s?"ui-unselecting":"ui-selected")._addClass(n.$element,s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",e,{selecting:n.element}):i._trigger("unselecting",e,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(e){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,o=this.opos[0],a=this.opos[1],r=e.pageX,l=e.pageY;return o>r&&(i=r,r=o,o=i),a>l&&(i=l,l=a,a=i),this.helper.css({left:o,top:a,width:r-o,height:l-a}),this.selectees.each(function(){var i=t.data(this,"selectable-item"),h=!1,c={};i&&i.element!==s.element[0]&&(c.left=i.left+s.elementPos.left,c.right=i.right+s.elementPos.left,c.top=i.top+s.elementPos.top,c.bottom=i.bottom+s.elementPos.top,"touch"===n.tolerance?h=!(c.left>r||o>c.right||c.top>l||a>c.bottom):"fit"===n.tolerance&&(h=c.left>o&&r>c.right&&c.top>a&&l>c.bottom),h?(i.selected&&(s._removeClass(i.$element,"ui-selected"),i.selected=!1),i.unselecting&&(s._removeClass(i.$element,"ui-unselecting"),i.unselecting=!1),i.selecting||(s._addClass(i.$element,"ui-selecting"),i.selecting=!0,s._trigger("selecting",e,{selecting:i.element}))):(i.selecting&&((e.metaKey||e.ctrlKey)&&i.startselected?(s._removeClass(i.$element,"ui-selecting"),i.selecting=!1,s._addClass(i.$element,"ui-selected"),i.selected=!0):(s._removeClass(i.$element,"ui-selecting"),i.selecting=!1,i.startselected&&(s._addClass(i.$element,"ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",e,{unselecting:i.element}))),i.selected&&(e.metaKey||e.ctrlKey||i.startselected||(s._removeClass(i.$element,"ui-selected"),i.selected=!1,s._addClass(i.$element,"ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",e,{unselecting:i.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,t(".ui-unselecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");i._removeClass(s.$element,"ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",e,{unselected:s.element})}),t(".ui-selecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");i._removeClass(s.$element,"ui-selecting")._addClass(s.$element,"ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",e,{selected:s.element})}),this._trigger("stop",e),this.helper.remove(),!1}}),t.widget("ui.sortable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(t,e,i){return t>=e&&e+i>t},_isFloating:function(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))},_create:function(){this.containerCache={},this._addClass("ui-sortable"),this.refresh(),this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(t,e){this._super(t,e),"handle"===t&&this._setHandleClassName()},_setHandleClassName:function(){var e=this;this._removeClass(this.element.find(".ui-sortable-handle"),"ui-sortable-handle"),t.each(this.items,function(){e._addClass(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item,"ui-sortable-handle")})},_destroy:function(){this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):void 0}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp(new t.Event("mouseup",{target:null})),"original"===this.options.helper?(this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,l=r+t.height,h=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+h>r&&l>s+h,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&l>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var e,i,s="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),n="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),o=s&&n;return o?(e=this._getDragVerticalDirection(),i=this._getDragHorizontalDirection(),this.floating?"right"===i||"down"===e?2:1:e&&("down"===e?2:1)):!1},_intersectsWithSides:function(t){var e=this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&e||"up"===s&&!e)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){function i(){r.push(this)}var s,n,o,a,r=[],l=[],h=this._connectWith();if(h&&e)for(s=h.length-1;s>=0;s--)for(o=t(h[s],this.document[0]),n=o.length-1;n>=0;n--)a=t.data(o[n],this.widgetFullName),a&&a!==this&&!a.options.disabled&&l.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(l.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=l.length-1;s>=0;s--)l[s][0].each(i);return t(r)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,l,h,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i],this.document[0]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,h=r.length;h>s;s++)l=t(r[s]),l.data(this.widgetName+"-item",a),c.push({item:l,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.floating=this.items.length?"x"===this.options.axis||this._isFloating(this.items[0].item):!1,this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]);return e._addClass(n,"ui-sortable-placeholder",i||e.currentItem[0].className)._removeClass(n,"ui-sortable-helper"),"tbody"===s?e._createTrPlaceholder(e.currentItem.find("tr").eq(0),t("",e.document[0]).appendTo(n)):"tr"===s?e._createTrPlaceholder(e.currentItem,n):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_createTrPlaceholder:function(e,i){var s=this;e.children().each(function(){t(" ",s.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(i)})},_contactContainers:function(e){var i,s,n,o,a,r,l,h,c,u,d=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!t.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(d&&t.contains(this.containers[i].element[0],d.element[0]))continue;d=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",e,this._uiHash(this)),this.containers[i].containerCache.over=0);if(d)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,o=null,c=d.floating||this._isFloating(this.currentItem),a=c?"left":"top",r=c?"width":"height",u=c?"pageX":"pageY",s=this.items.length-1;s>=0;s--)t.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(l=this.items[s].item.offset()[a],h=!1,e[u]-l>this.items[s][r]/2&&(h=!0),n>Math.abs(e[u]-l)&&(n=Math.abs(e[u]-l),o=this.items[s],this.direction=h?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",e,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;o?this._rearrange(e,o,null,!0):this._rearrange(e,null,this.containers[p].element,!0),this._trigger("change",e,this._uiHash()),this.containers[p]._trigger("change",e,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",e,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===n.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===n.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.leftthis.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():l?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():l?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){function i(t,e,i){return function(s){i._trigger(t,s,e._uiHash(e))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&n.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||n.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(n.push(function(t){this._trigger("remove",t,this._uiHash())}),n.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)e||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(s=0;n.length>s;s++)n[s].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}}),t.widget("ui.accordion",{version:"1.12.1",options:{active:0,animate:{},classes:{"ui-accordion-header":"ui-corner-top","ui-accordion-header-collapsed":"ui-corner-all","ui-accordion-content":"ui-corner-bottom"},collapsible:!1,event:"click",header:"> li > :first-child, > :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var e=this.options;this.prevShow=this.prevHide=t(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),e.collapsible||e.active!==!1&&null!=e.active||(e.active=0),this._processPanels(),0>e.active&&(e.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():t()}},_createIcons:function(){var e,i,s=this.options.icons;s&&(e=t(""),this._addClass(e,"ui-accordion-header-icon","ui-icon "+s.header),e.prependTo(this.headers),i=this.active.children(".ui-accordion-header-icon"),this._removeClass(i,s.header)._addClass(i,null,s.activeHeader)._addClass(this.headers,"ui-accordion-icons")) -},_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){return"active"===t?(this._activate(e),void 0):("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||this.options.active!==!1||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons()),void 0)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t),this._toggleClass(this.headers.add(this.headers.next()),null,"ui-state-disabled",!!t)},_keydown:function(e){if(!e.altKey&&!e.ctrlKey){var i=t.ui.keyCode,s=this.headers.length,n=this.headers.index(e.target),o=!1;switch(e.keyCode){case i.RIGHT:case i.DOWN:o=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:o=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(e);break;case i.HOME:o=this.headers[0];break;case i.END:o=this.headers[s-1]}o&&(t(e.target).attr("tabIndex",-1),t(o).attr("tabIndex",0),t(o).trigger("focus"),e.preventDefault())}},_panelKeyDown:function(e){e.keyCode===t.ui.keyCode.UP&&e.ctrlKey&&t(e.currentTarget).prev().trigger("focus")},refresh:function(){var e=this.options;this._processPanels(),e.active===!1&&e.collapsible===!0||!this.headers.length?(e.active=!1,this.active=t()):e.active===!1?this._activate(0):this.active.length&&!t.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(e.active=!1,this.active=t()):this._activate(Math.max(0,e.active-1)):e.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var e,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var e=t(this),i=e.uniqueId().attr("id"),s=e.next(),n=s.uniqueId().attr("id");e.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(e=n.height(),this.element.siblings(":visible").each(function(){var i=t(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(e-=i.outerHeight(!0))}),this.headers.each(function(){e-=t(this).outerHeight(!0)}),this.headers.next().each(function(){t(this).height(Math.max(0,e-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===s&&(e=0,this.headers.next().each(function(){var i=t(this).is(":visible");i||t(this).show(),e=Math.max(e,t(this).css("height","").height()),i||t(this).hide()}).height(e))},_activate:function(e){var i=this._findActive(e)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return"number"==typeof e?this.headers.eq(e):t()},_setupEvents:function(e){var i={keydown:"_keydown"};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(e){var i,s,n=this.options,o=this.active,a=t(e.currentTarget),r=a[0]===o[0],l=r&&n.collapsible,h=l?t():a.next(),c=o.next(),u={oldHeader:o,oldPanel:c,newHeader:l?t():a,newPanel:h};e.preventDefault(),r&&!n.collapsible||this._trigger("beforeActivate",e,u)===!1||(n.active=l?!1:this.headers.index(a),this.active=r?t():a,this._toggle(u),this._removeClass(o,"ui-accordion-header-active","ui-state-active"),n.icons&&(i=o.children(".ui-accordion-header-icon"),this._removeClass(i,null,n.icons.activeHeader)._addClass(i,null,n.icons.header)),r||(this._removeClass(a,"ui-accordion-header-collapsed")._addClass(a,"ui-accordion-header-active","ui-state-active"),n.icons&&(s=a.children(".ui-accordion-header-icon"),this._removeClass(s,null,n.icons.header)._addClass(s,null,n.icons.activeHeader)),this._addClass(a.next(),"ui-accordion-content-active")))},_toggle:function(e){var i=e.newPanel,s=this.prevShow.length?this.prevShow:e.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,e):(s.hide(),i.show(),this._toggleComplete(e)),s.attr({"aria-hidden":"true"}),s.prev().attr({"aria-selected":"false","aria-expanded":"false"}),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===parseInt(t(this).attr("tabIndex"),10)}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,e,i){var s,n,o,a=this,r=0,l=t.css("box-sizing"),h=t.length&&(!e.length||t.index()",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault()},"click .ui-menu-item":function(e){var i=t(e.target),s=t(t.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&s.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){if(!this.previousFilter){var i=t(e.target).closest(".ui-menu-item"),s=t(e.currentTarget);i[0]===s[0]&&(this._removeClass(s.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(e,s))}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.find(this.options.items).eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){var i=!t.contains(this.element[0],t.ui.safeActiveElement(this.document[0]));i&&this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){var e=this.element.find(".ui-menu-item").removeAttr("role aria-disabled"),i=e.children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),i.children().each(function(){var e=t(this);e.data("ui-menu-submenu-caret")&&e.remove()})},_keydown:function(e){var i,s,n,o,a=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:a=!1,s=this.previousFilter||"",o=!1,n=e.keyCode>=96&&105>=e.keyCode?""+(e.keyCode-96):String.fromCharCode(e.keyCode),clearTimeout(this.filterTimer),n===s?o=!0:n=s+n,i=this._filterMenuItems(n),i=o&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(e.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(e,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}a&&e.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i,s,n,o,a=this,r=this.options.icons.submenu,l=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),s=l.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),i=e.prev(),s=t("").data("ui-menu-submenu-caret",!0);a._addClass(s,"ui-menu-icon","ui-icon "+r),i.attr("aria-haspopup","true").prepend(s),e.attr("aria-labelledby",i.attr("id"))}),this._addClass(s,"ui-menu","ui-widget ui-widget-content ui-front"),e=l.add(this.element),i=e.find(this.options.items),i.not(".ui-menu-item").each(function(){var e=t(this);a._isDivider(e)&&a._addClass(e,"ui-menu-divider","ui-widget-content")}),n=i.not(".ui-menu-item, .ui-menu-divider"),o=n.children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(n,"ui-menu-item")._addClass(o,"ui-menu-item-wrapper"),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){if("icons"===t){var i=this.element.find(".ui-menu-icon");this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)}this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t+""),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i,s,n;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children(".ui-menu-item-wrapper"),this._addClass(s,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),n=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(n,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,o,a,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,o=this.activeMenu.scrollTop(),a=this.activeMenu.height(),r=e.outerHeight(),0>n?this.activeMenu.scrollTop(o+n):n+r>a&&this.activeMenu.scrollTop(o+n-a+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this._removeClass(this.active.children(".ui-menu-item-wrapper"),null,"ui-state-active"),this._trigger("blur",t,{item:this.active}),this.active=null)},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this._removeClass(s.find(".ui-state-active"),null,"ui-state-active"),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false")},_closeOnDocumentClick:function(e){return!t(e.target).closest(".ui-menu").length},_isDivider:function(t){return!/[^\-\u2014\u2013\s]/.test(t.text())},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(e),void 0)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items).first())),void 0):(this.next(e),void 0)},_hasScroll:function(){return this.element.outerHeight()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),o="textarea"===n,a="input"===n;this.isMultiLine=o||!a&&this._isContentEditable(this.element),this.valueMethod=this.element[o||a?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,void 0;e=!1,s=!1,i=!1;var o=t.ui.keyCode;switch(n.keyCode){case o.PAGE_UP:e=!0,this._move("previousPage",n);break;case o.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case o.UP:e=!0,this._keyEvent("previous",n);break;case o.DOWN:e=!0,this._keyEvent("next",n);break;case o.ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case o.TAB:this.menu.active&&this.menu.select(n);break;case o.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),void 0):(this._searchTimeout(t),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(t),this._change(t),void 0)}}),this._initSource(),this.menu=t("